Compare commits
11 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
5e5733f2e5 | |
|
|
c9d4e13814 | |
|
|
cbde7a9647 | |
|
|
a811058901 | |
|
|
1b1f3eb46c | |
|
|
06fe7445ea | |
|
|
9892adf566 | |
|
|
5d42a64615 | |
|
|
81b932a97d | |
|
|
2e23d74701 | |
|
|
850bc75046 |
|
|
@ -1,6 +0,0 @@
|
|||
on: [push]
|
||||
jobs:
|
||||
smoke:
|
||||
runs-on: docker
|
||||
steps:
|
||||
- run: echo forgejo-actions-ok
|
||||
7
SKILL.md
7
SKILL.md
|
|
@ -42,6 +42,13 @@ Returns structured JSON with product data:
|
|||
- Variants/SKUs
|
||||
- Supplier info
|
||||
|
||||
## Rules — MUST follow
|
||||
|
||||
1. **Execute only, do not reason about internals.** Run the CLI command and return the output. Do NOT attempt to understand, debug, or bypass the scrape/query/polling logic inside the tool.
|
||||
2. **No fallback strategies.** If the command fails, report the error as-is. Do NOT try alternative approaches such as browser scraping, direct HTTP calls, or different API endpoints.
|
||||
3. **No retry loops.** If authentication or the scrape call fails, report the failure. Do NOT re-check configs, re-acquire tokens, or retry on your own.
|
||||
4. **Trust the tool's output.** The CLI handles session management, retries, and error formatting internally. Your job is to invoke it and relay the result — nothing more.
|
||||
|
||||
## Reference
|
||||
|
||||
See [references/1688-product-master.md](references/1688-product-master.md).
|
||||
|
|
|
|||
10
bun.lock
10
bun.lock
|
|
@ -5,11 +5,17 @@
|
|||
"": {
|
||||
"name": "1688-product-master",
|
||||
"dependencies": {
|
||||
"@clawd/auth-runtime": "git+http://192.168.0.108:3030/agent-skills/auth-runtime.git",
|
||||
"@clawd/auth-runtime": "file:../auth-runtime",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@clawd/auth-runtime": ["@clawd/auth-runtime@git+http://192.168.0.108:3030/agent-skills/auth-runtime.git#70cf86889eecbe9c4649bb072cd971c3a560e889", {}, "70cf86889eecbe9c4649bb072cd971c3a560e889"],
|
||||
"@clawd/auth-runtime": ["@clawd/auth-runtime@file:../auth-runtime", { "devDependencies": { "@types/node": "^25.3.3", "typescript": "^5.9.3" } }],
|
||||
|
||||
"@types/node": ["@types/node@25.5.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw=="],
|
||||
|
||||
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||
|
||||
"undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="],
|
||||
}
|
||||
}
|
||||
|
|
|
|||
38
install.sh
38
install.sh
|
|
@ -1,24 +1,34 @@
|
|||
#!/usr/bin/env bash
|
||||
# Install 1688-product-master to a target directory.
|
||||
# Bundles the skill + auth-runtime into a single self-contained file.
|
||||
#
|
||||
# Usage:
|
||||
# ./install.sh # installs to ~/.openclaw/skills/
|
||||
# ./install.sh /custom/path/
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SKILL_NAME="1688-product-master"
|
||||
DEST="${1:-$HOME/.openclaw/skills}"
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
echo "Building $SKILL_NAME..."
|
||||
bun install --frozen-lockfile
|
||||
# Auto-install auth-rt if not found
|
||||
if ! command -v auth-rt &>/dev/null && [ ! -x "$HOME/.local/bin/auth-rt" ]; then
|
||||
echo "auth-rt not found, installing..."
|
||||
_FORGEJO="http://192.168.0.108:3030"
|
||||
_OS="$(uname -s | tr '[:upper:]' '[:lower:]')"
|
||||
_ARCH="$(uname -m)"; case "$_ARCH" in x86_64) _ARCH="amd64";; aarch64) _ARCH="arm64";; esac
|
||||
_URL="$_FORGEJO/agent-skills/auth-runtime/releases/download/latest/auth-rt-${_OS}-${_ARCH}"
|
||||
mkdir -p "$HOME/.local/bin"
|
||||
if curl -fsSL "$_URL" -o "$HOME/.local/bin/auth-rt" 2>/dev/null; then
|
||||
chmod +x "$HOME/.local/bin/auth-rt"
|
||||
echo "auth-rt installed (downloaded)"
|
||||
else
|
||||
echo "Download failed, building from source..."
|
||||
_SRC="$HOME/.local/share/auth-runtime"
|
||||
if [ -d "$_SRC/.git" ]; then git -C "$_SRC" pull --ff-only
|
||||
else git clone --depth 1 "$_FORGEJO/agent-skills/auth-runtime.git" "$_SRC"
|
||||
fi
|
||||
bash "$_SRC/install.sh"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Building 1688-product-master..."
|
||||
bun build scripts/run.ts --outfile dist/run.js --target bun
|
||||
|
||||
DEST="${1:-$HOME/.openclaw/skills}"
|
||||
SKILL_NAME="1688-product-master"
|
||||
mkdir -p "$DEST/$SKILL_NAME"
|
||||
cp dist/run.js "$DEST/$SKILL_NAME/run.js"
|
||||
|
||||
echo "Installed: $DEST/$SKILL_NAME/run.js"
|
||||
echo "Run with: bun $DEST/$SKILL_NAME/run.js <command> [args...]"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"name": "1688-product-master",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "1688-product-master",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@clawd/auth-runtime": "git+http://192.168.0.108:3030/agent-skills/auth-runtime.git"
|
||||
}
|
||||
},
|
||||
"node_modules/@clawd/auth-runtime": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "git+http://192.168.0.108:3030/agent-skills/auth-runtime.git#466a4303b247f99eb444a74b014c40b148974e02",
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,5 @@
|
|||
"build": "bun build scripts/run.ts --outfile dist/run.js --target bun",
|
||||
"package": "bun run build && cd .. && zip -r 1688-product-master.skill 1688-product-master/SKILL.md 1688-product-master/dist/run.js && echo 'Created: 1688-product-master.skill'"
|
||||
},
|
||||
"dependencies": {
|
||||
"@clawd/auth-runtime": "git+http://192.168.0.108:3030/agent-skills/auth-runtime.git"
|
||||
}
|
||||
"dependencies": {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,119 @@
|
|||
/**
|
||||
* Thin CLI wrapper for auth-runtime.
|
||||
*
|
||||
* Copy this file into your skill's src/ directory. It calls the
|
||||
* `auth-rt` binary (a standalone Go executable), so the skill has
|
||||
* zero npm/runtime dependency on auth-runtime.
|
||||
*
|
||||
* Prerequisites:
|
||||
* `auth-rt` must be in PATH or at ~/.local/bin/auth-rt
|
||||
* (install.sh handles this automatically)
|
||||
*
|
||||
* Usage:
|
||||
* import { createSkillClient } from './auth-cli.ts';
|
||||
* const client = createSkillClient();
|
||||
* const res = await client.post('/ecom/tasks/scrape', { url: '...' });
|
||||
*/
|
||||
|
||||
import { spawnSync } from 'child_process';
|
||||
import * as path from 'path';
|
||||
import * as os from 'os';
|
||||
|
||||
const home = process.env.HOME || os.homedir();
|
||||
const AUTH_RT_BIN = process.env.AUTH_RT_BIN
|
||||
|| (() => {
|
||||
// Check if auth-rt is in PATH
|
||||
const which = spawnSync('which', ['auth-rt'], { encoding: 'utf-8' });
|
||||
if (which.status === 0 && which.stdout.trim()) {
|
||||
return which.stdout.trim();
|
||||
}
|
||||
return path.join(home, '.local', 'bin', 'auth-rt');
|
||||
})();
|
||||
|
||||
export interface ApiResponse {
|
||||
status: number;
|
||||
body: string;
|
||||
}
|
||||
|
||||
export interface SessionResponse {
|
||||
accessToken: string;
|
||||
expiresIn: number;
|
||||
ownerSessionToken?: string;
|
||||
hookUrl?: string;
|
||||
hookToken?: string;
|
||||
}
|
||||
|
||||
export interface SkillClientOptions {
|
||||
apiBase?: string;
|
||||
dryRun?: boolean;
|
||||
}
|
||||
|
||||
function runCli(...args: string[]): string {
|
||||
const result = spawnSync(AUTH_RT_BIN, args, {
|
||||
encoding: 'utf-8',
|
||||
timeout: 60_000,
|
||||
});
|
||||
|
||||
if (result.error) {
|
||||
throw new Error(`auth-rt spawn failed: ${result.error.message}`);
|
||||
}
|
||||
if (result.status !== 0) {
|
||||
throw new Error(`auth-rt failed (exit ${result.status}): ${(result.stderr || '').trim()}`);
|
||||
}
|
||||
return (result.stdout || '').trim();
|
||||
}
|
||||
|
||||
export class SkillClient {
|
||||
private readonly apiBase?: string;
|
||||
private readonly dryRun: boolean;
|
||||
|
||||
constructor(options: SkillClientOptions = {}) {
|
||||
this.apiBase = options.apiBase;
|
||||
this.dryRun = options.dryRun ?? false;
|
||||
}
|
||||
|
||||
async session(): Promise<SessionResponse> {
|
||||
if (this.dryRun) {
|
||||
return { accessToken: '<dry-run-token>', expiresIn: 900 };
|
||||
}
|
||||
return JSON.parse(runCli('session'));
|
||||
}
|
||||
|
||||
async get(urlPath: string): Promise<ApiResponse> {
|
||||
return this.request('GET', urlPath);
|
||||
}
|
||||
|
||||
async post(urlPath: string, body?: unknown): Promise<ApiResponse> {
|
||||
return this.request('POST', urlPath, body);
|
||||
}
|
||||
|
||||
async put(urlPath: string, body?: unknown): Promise<ApiResponse> {
|
||||
return this.request('PUT', urlPath, body);
|
||||
}
|
||||
|
||||
async patch(urlPath: string, body?: unknown): Promise<ApiResponse> {
|
||||
return this.request('PATCH', urlPath, body);
|
||||
}
|
||||
|
||||
async delete(urlPath: string, body?: unknown): Promise<ApiResponse> {
|
||||
return this.request('DELETE', urlPath, body);
|
||||
}
|
||||
|
||||
private async request(method: string, urlPath: string, body?: unknown): Promise<ApiResponse> {
|
||||
if (this.dryRun) {
|
||||
return { status: 200, body: JSON.stringify({ dryRun: true, method, path: urlPath }) };
|
||||
}
|
||||
const args = ['request', method, urlPath];
|
||||
if (body != null) {
|
||||
args.push('--body', JSON.stringify(body));
|
||||
}
|
||||
if (this.apiBase) {
|
||||
args.push('--api-base', this.apiBase);
|
||||
}
|
||||
return JSON.parse(runCli(...args));
|
||||
}
|
||||
}
|
||||
|
||||
export function createSkillClient(options?: SkillClientOptions): SkillClient {
|
||||
return new SkillClient(options);
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import type { Command, OutputResult, ScrapePayload } from './types.js';
|
||||
import { createSkillClient } from '@clawd/auth-runtime';
|
||||
import { createSkillClient } from './auth-cli.ts';
|
||||
import { buildPayloadFromUrl, validatePayloadJson } from './scrape.js';
|
||||
|
||||
export async function run1688(
|
||||
|
|
|
|||
Loading…
Reference in New Issue