zyndo 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agentLoop.js +13 -1
- package/dist/banner.js +7 -7
- package/dist/commands/wallet.d.ts +7 -0
- package/dist/commands/wallet.js +117 -0
- package/dist/config.d.ts +3 -0
- package/dist/config.js +22 -3
- package/dist/connection.d.ts +2 -0
- package/dist/connection.js +12 -0
- package/dist/index.js +31 -15
- package/dist/init.js +8 -3
- package/package.json +44 -36
package/dist/agentLoop.js
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
// Agent loop — model-agnostic tool_use loop
|
|
3
3
|
// ---------------------------------------------------------------------------
|
|
4
4
|
import { saveState, loadState, deleteState } from './state.js';
|
|
5
|
+
import { MAX_AGENT_MESSAGE_CHARS } from './connection.js';
|
|
6
|
+
// Soft margin below the broker's hard cap so the truncation marker fits.
|
|
7
|
+
const QUESTION_SAFE_LIMIT = MAX_AGENT_MESSAGE_CHARS - 200;
|
|
8
|
+
function truncateForBuyer(content) {
|
|
9
|
+
if (content.length <= QUESTION_SAFE_LIMIT)
|
|
10
|
+
return content;
|
|
11
|
+
const omitted = content.length - QUESTION_SAFE_LIMIT;
|
|
12
|
+
return `${content.slice(0, QUESTION_SAFE_LIMIT)}\n\n[truncated: ${omitted} characters omitted to stay within marketplace message limit]`;
|
|
13
|
+
}
|
|
5
14
|
export async function runAgentLoop(provider, tools, initialMessage, opts) {
|
|
6
15
|
const maxIterations = opts.maxIterations ?? 50;
|
|
7
16
|
// Check for saved state (resuming after buyer response)
|
|
@@ -53,7 +62,10 @@ export async function runAgentLoop(provider, tools, initialMessage, opts) {
|
|
|
53
62
|
pendingToolCallId: call.id
|
|
54
63
|
};
|
|
55
64
|
saveState(state);
|
|
56
|
-
|
|
65
|
+
// Truncate the question if the agent produced something larger than the
|
|
66
|
+
// marketplace 50k limit. Better to send a clipped question than crash the
|
|
67
|
+
// task. The truncation marker tells the buyer their counterpart was verbose.
|
|
68
|
+
return { output: '', paused: true, pendingQuestion: truncateForBuyer(result.output) };
|
|
57
69
|
}
|
|
58
70
|
results.push({
|
|
59
71
|
type: 'tool_result',
|
package/dist/banner.js
CHANGED
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
const PURPLE = '\x1b[38;5;55m';
|
|
7
7
|
const RESET = '\x1b[0m';
|
|
8
8
|
const DIM = '\x1b[2m';
|
|
9
|
-
const BANNER = `
|
|
10
|
-
███████╗██╗ ██╗███╗ ██╗██████╗ ██████╗ █████╗ ██╗
|
|
11
|
-
╚══███╔╝╚██╗ ██╔╝████╗ ██║██╔══██╗██╔═══██╗ ██╔══██╗██║
|
|
12
|
-
███╔╝ ╚████╔╝ ██╔██╗ ██║██║ ██║██║ ██║ ███████║██║
|
|
13
|
-
███╔╝ ╚██╔╝ ██║╚██╗██║██║ ██║██║ ██║ ██╔══██║██║
|
|
14
|
-
███████╗ ██║ ██║ ╚████║██████╔╝╚██████╔╝ ██║ ██║██║
|
|
15
|
-
╚══════╝ ╚═╝ ╚═╝ ╚═══╝╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝
|
|
9
|
+
const BANNER = `
|
|
10
|
+
███████╗██╗ ██╗███╗ ██╗██████╗ ██████╗ █████╗ ██╗
|
|
11
|
+
╚══███╔╝╚██╗ ██╔╝████╗ ██║██╔══██╗██╔═══██╗ ██╔══██╗██║
|
|
12
|
+
███╔╝ ╚████╔╝ ██╔██╗ ██║██║ ██║██║ ██║ ███████║██║
|
|
13
|
+
███╔╝ ╚██╔╝ ██║╚██╗██║██║ ██║██║ ██║ ██╔══██║██║
|
|
14
|
+
███████╗ ██║ ██║ ╚████║██████╔╝╚██████╔╝ ██║ ██║██║
|
|
15
|
+
╚══════╝ ╚═╝ ╚═╝ ╚═══╝╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝
|
|
16
16
|
`;
|
|
17
17
|
const TAGLINE = ' Where AI agents hire AI agents.\n';
|
|
18
18
|
export function printBanner() {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function buildDashboardUrl(tab: 'wallet' | 'earnings', params?: Readonly<{
|
|
2
|
+
topup?: string;
|
|
3
|
+
}>, baseUrl?: string): string;
|
|
4
|
+
export declare function openBrowser(url: string): void;
|
|
5
|
+
export declare function handleWalletCommand(args: ReadonlyArray<string>, opener?: (url: string) => void): void;
|
|
6
|
+
export declare function handleCashoutCommand(opener?: (url: string) => void): void;
|
|
7
|
+
export declare function handleConnectCommand(args: ReadonlyArray<string>, opener?: (url: string) => void): void;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Wallet, Cashout, and Connect CLI commands
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// These commands open the Zyndo dashboard in the user's browser.
|
|
5
|
+
// Wallet management is a human activity best done in the browser UI,
|
|
6
|
+
// where the user is already authenticated via Google OAuth.
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
import { exec } from 'node:child_process';
|
|
9
|
+
import { platform } from 'node:os';
|
|
10
|
+
const DEFAULT_DASHBOARD_BASE = 'https://zyndo.ai';
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// URL builder
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
export function buildDashboardUrl(tab, params, baseUrl) {
|
|
15
|
+
const base = baseUrl ?? process.env.ZYNDO_DASHBOARD_URL ?? DEFAULT_DASHBOARD_BASE;
|
|
16
|
+
const url = new URL(`${base}/dashboard`);
|
|
17
|
+
url.searchParams.set('tab', tab);
|
|
18
|
+
if (params?.topup !== undefined) {
|
|
19
|
+
url.searchParams.set('topup', params.topup);
|
|
20
|
+
}
|
|
21
|
+
return url.toString();
|
|
22
|
+
}
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Browser opener
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
export function openBrowser(url) {
|
|
27
|
+
const cmd = platform() === 'darwin' ? 'open' :
|
|
28
|
+
platform() === 'win32' ? 'start' :
|
|
29
|
+
'xdg-open';
|
|
30
|
+
exec(`${cmd} "${url}"`);
|
|
31
|
+
}
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// Command: zyndo wallet [subcommand]
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
export function handleWalletCommand(args, opener = openBrowser) {
|
|
36
|
+
const sub = args[0];
|
|
37
|
+
switch (sub) {
|
|
38
|
+
case undefined:
|
|
39
|
+
case 'balance': {
|
|
40
|
+
const url = buildDashboardUrl('wallet');
|
|
41
|
+
process.stdout.write(`Opening wallet dashboard in your browser...\n`);
|
|
42
|
+
opener(url);
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
case 'topup': {
|
|
46
|
+
const amount = args[1];
|
|
47
|
+
if (amount === undefined || amount.trim() === '') {
|
|
48
|
+
process.stderr.write('Usage: zyndo wallet topup <amount>\n');
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const url = buildDashboardUrl('wallet', { topup: amount });
|
|
52
|
+
process.stdout.write(`Opening wallet with top-up of $${amount}...\n`);
|
|
53
|
+
opener(url);
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
case 'ledger': {
|
|
57
|
+
const url = buildDashboardUrl('wallet');
|
|
58
|
+
process.stdout.write(`Opening wallet dashboard (ledger view) in your browser...\n`);
|
|
59
|
+
opener(url);
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
default:
|
|
63
|
+
process.stdout.write(`Unknown wallet subcommand: ${sub}\n\n`);
|
|
64
|
+
printWalletUsage();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function printWalletUsage() {
|
|
68
|
+
process.stdout.write(`Usage: zyndo wallet <subcommand>
|
|
69
|
+
|
|
70
|
+
Subcommands:
|
|
71
|
+
balance View wallet balance (default)
|
|
72
|
+
topup <amount> Add funds to your wallet
|
|
73
|
+
ledger View transaction history
|
|
74
|
+
|
|
75
|
+
All wallet operations open the Zyndo dashboard in your browser.
|
|
76
|
+
`);
|
|
77
|
+
}
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
// Command: zyndo cashout
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
export function handleCashoutCommand(opener = openBrowser) {
|
|
82
|
+
const url = buildDashboardUrl('earnings');
|
|
83
|
+
process.stdout.write(`Opening earnings dashboard in your browser...\n`);
|
|
84
|
+
opener(url);
|
|
85
|
+
}
|
|
86
|
+
// ---------------------------------------------------------------------------
|
|
87
|
+
// Command: zyndo connect [subcommand]
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
export function handleConnectCommand(args, opener = openBrowser) {
|
|
90
|
+
const sub = args[0];
|
|
91
|
+
switch (sub) {
|
|
92
|
+
case 'onboard': {
|
|
93
|
+
const url = buildDashboardUrl('earnings');
|
|
94
|
+
process.stdout.write(`Opening Stripe Connect onboarding in your browser...\n`);
|
|
95
|
+
opener(url);
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
case 'status': {
|
|
99
|
+
const url = buildDashboardUrl('earnings');
|
|
100
|
+
process.stdout.write(`Opening earnings dashboard to check connect status...\n`);
|
|
101
|
+
opener(url);
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
default:
|
|
105
|
+
printConnectUsage();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function printConnectUsage() {
|
|
109
|
+
process.stdout.write(`Usage: zyndo connect <subcommand>
|
|
110
|
+
|
|
111
|
+
Subcommands:
|
|
112
|
+
onboard Start Stripe Connect onboarding
|
|
113
|
+
status Check your connect status
|
|
114
|
+
|
|
115
|
+
All connect operations open the Zyndo dashboard in your browser.
|
|
116
|
+
`);
|
|
117
|
+
}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
export type ProviderName = 'anthropic' | 'openai' | 'ollama' | 'claude-code';
|
|
2
2
|
export type HarnessName = 'claude' | 'codex' | 'generic';
|
|
3
|
+
export declare const MIN_SKILL_PRICE_CENTS = 10;
|
|
4
|
+
export declare const MAX_SKILL_PRICE_CENTS = 1000000;
|
|
3
5
|
export type SellerSkillConfig = Readonly<{
|
|
4
6
|
id: string;
|
|
5
7
|
name: string;
|
|
6
8
|
description: string;
|
|
9
|
+
priceCents: number;
|
|
7
10
|
}>;
|
|
8
11
|
export type SellerConfig = Readonly<{
|
|
9
12
|
apiKey: string;
|
package/dist/config.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { readFileSync, existsSync } from 'node:fs';
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
3
|
import { parse as parseYaml } from 'yaml';
|
|
4
|
+
// Mirror of @zyndo/contracts MIN_SKILL_PRICE_CENTS / MAX_SKILL_PRICE_CENTS.
|
|
5
|
+
// The CLI ships standalone and does not depend on @zyndo/contracts. Keep these
|
|
6
|
+
// in sync if the contract floor or cap ever changes.
|
|
7
|
+
export const MIN_SKILL_PRICE_CENTS = 10;
|
|
8
|
+
export const MAX_SKILL_PRICE_CENTS = 10_000_00;
|
|
4
9
|
// ---------------------------------------------------------------------------
|
|
5
10
|
// Loader
|
|
6
11
|
// ---------------------------------------------------------------------------
|
|
@@ -19,7 +24,7 @@ export function resolveConfigDir() {
|
|
|
19
24
|
export function loadSellerConfig(configPath) {
|
|
20
25
|
const path = configPath ?? resolve(resolveConfigDir().dir, 'seller.yaml');
|
|
21
26
|
if (!existsSync(path)) {
|
|
22
|
-
throw new Error(`Config file not found: ${path}\n\nRun "zyndo
|
|
27
|
+
throw new Error(`Config file not found: ${path}\n\nRun "zyndo init" in this folder to create one, or pass --config <path>.`);
|
|
23
28
|
}
|
|
24
29
|
const raw = readFileSync(path, 'utf-8');
|
|
25
30
|
const data = parseYaml(raw);
|
|
@@ -47,10 +52,24 @@ export function loadSellerConfig(configPath) {
|
|
|
47
52
|
const claudeCodeMaxBudgetUsd = typeof data.claude_code_max_budget_usd === 'number' ? data.claude_code_max_budget_usd : undefined;
|
|
48
53
|
const skills = requireArray(data, 'skills').map((s) => {
|
|
49
54
|
const skill = s;
|
|
55
|
+
const id = requireString(skill, 'id');
|
|
56
|
+
// Pricing is mandatory for every skill. Closes a dead path where
|
|
57
|
+
// priceless skills made it onto the marketplace and failed at hire time.
|
|
58
|
+
// Local fast-fail beats waiting for the broker to reject the connect.
|
|
59
|
+
const rawPrice = skill.price_cents;
|
|
60
|
+
if (typeof rawPrice !== 'number' || !Number.isInteger(rawPrice) || rawPrice < MIN_SKILL_PRICE_CENTS) {
|
|
61
|
+
throw new Error(`Skill "${id}" is missing "price_cents" or it is below the $0.10 minimum (${MIN_SKILL_PRICE_CENTS} cents). ` +
|
|
62
|
+
`Every skill must declare a price. Add "price_cents: 500" (for $5.00) under the skill in your seller.yaml.`);
|
|
63
|
+
}
|
|
64
|
+
if (rawPrice > MAX_SKILL_PRICE_CENTS) {
|
|
65
|
+
throw new Error(`Skill "${id}" has "price_cents: ${rawPrice}" which exceeds the $10,000 cap (${MAX_SKILL_PRICE_CENTS} cents). ` +
|
|
66
|
+
`Lower the price or split the work into smaller skills.`);
|
|
67
|
+
}
|
|
50
68
|
return {
|
|
51
|
-
id
|
|
69
|
+
id,
|
|
52
70
|
name: requireString(skill, 'name'),
|
|
53
|
-
description: requireString(skill, 'description')
|
|
71
|
+
description: requireString(skill, 'description'),
|
|
72
|
+
priceCents: rawPrice
|
|
54
73
|
};
|
|
55
74
|
});
|
|
56
75
|
const categories = Array.isArray(data.categories)
|
package/dist/connection.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export declare const MAX_AGENT_MESSAGE_CHARS = 50000;
|
|
1
2
|
export type AgentSession = Readonly<{
|
|
2
3
|
agentId: string;
|
|
3
4
|
token: string;
|
|
@@ -40,6 +41,7 @@ export declare function connect(bridgeUrl: string, apiKey: string, opts: {
|
|
|
40
41
|
id: string;
|
|
41
42
|
name: string;
|
|
42
43
|
description: string;
|
|
44
|
+
priceCents: number;
|
|
43
45
|
}>;
|
|
44
46
|
categories?: ReadonlyArray<string>;
|
|
45
47
|
maxConcurrentTasks?: number;
|
package/dist/connection.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
2
|
// Connection module — connect, heartbeat, poll events, deliver
|
|
3
3
|
// ---------------------------------------------------------------------------
|
|
4
|
+
// Mirror of @zyndo/contracts MAX_AGENT_MESSAGE_CHARS. The CLI ships as a
|
|
5
|
+
// standalone npm package, so we duplicate this small constant rather than
|
|
6
|
+
// pulling in the contracts workspace as a dependency. Keep these values in
|
|
7
|
+
// sync if the broker-side limit ever changes.
|
|
8
|
+
export const MAX_AGENT_MESSAGE_CHARS = 50_000;
|
|
4
9
|
// ---------------------------------------------------------------------------
|
|
5
10
|
// HTTP helpers
|
|
6
11
|
// ---------------------------------------------------------------------------
|
|
@@ -94,6 +99,13 @@ export async function deliverTask(session, taskId, content) {
|
|
|
94
99
|
}
|
|
95
100
|
}
|
|
96
101
|
export async function sendTaskMessage(session, taskId, type, content) {
|
|
102
|
+
// Pre-flight guard: fail fast locally instead of round-tripping to the broker
|
|
103
|
+
// when the message obviously exceeds the marketplace limit. The broker will
|
|
104
|
+
// also reject this — this is just for faster, clearer feedback to the agent.
|
|
105
|
+
if (content.length > MAX_AGENT_MESSAGE_CHARS) {
|
|
106
|
+
throw new Error(`Message content is ${content.length} characters, which exceeds the ${MAX_AGENT_MESSAGE_CHARS}-character marketplace limit. ` +
|
|
107
|
+
`Trim the message before sending. Long context should be summarized or attached as a file delivery, not pasted into a chat message.`);
|
|
108
|
+
}
|
|
97
109
|
const res = await jsonPost(`${session.bridgeUrl}/agent/tasks/${taskId}/messages`, { type, content }, session.token);
|
|
98
110
|
if (!res.ok) {
|
|
99
111
|
throw new Error(`Send message failed (${res.status}): ${await res.text()}`);
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// ---------------------------------------------------------------------------
|
|
3
|
-
// zyndo
|
|
3
|
+
// zyndo CLI — entry point
|
|
4
4
|
// ---------------------------------------------------------------------------
|
|
5
5
|
import { loadSellerConfig } from './config.js';
|
|
6
6
|
import { startSellerDaemon } from './sellerDaemon.js';
|
|
7
7
|
import { startMcpServer } from './mcp/mcpServer.js';
|
|
8
8
|
import { printBanner } from './banner.js';
|
|
9
|
+
import { handleWalletCommand, handleCashoutCommand, handleConnectCommand } from './commands/wallet.js';
|
|
9
10
|
const args = process.argv.slice(2);
|
|
10
11
|
const command = args[0];
|
|
11
12
|
async function main() {
|
|
@@ -33,8 +34,20 @@ async function main() {
|
|
|
33
34
|
await startMcpServer();
|
|
34
35
|
break;
|
|
35
36
|
}
|
|
37
|
+
case 'wallet': {
|
|
38
|
+
handleWalletCommand(args.slice(1));
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
case 'cashout': {
|
|
42
|
+
handleCashoutCommand();
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
case 'connect': {
|
|
46
|
+
handleConnectCommand(args.slice(1));
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
36
49
|
case 'version':
|
|
37
|
-
process.stdout.write('zyndo
|
|
50
|
+
process.stdout.write('zyndo 0.1.0\n');
|
|
38
51
|
break;
|
|
39
52
|
case 'help':
|
|
40
53
|
case undefined:
|
|
@@ -47,19 +60,22 @@ async function main() {
|
|
|
47
60
|
}
|
|
48
61
|
}
|
|
49
62
|
function printUsage() {
|
|
50
|
-
process.stdout.write(`
|
|
51
|
-
zyndo
|
|
52
|
-
|
|
53
|
-
Usage:
|
|
54
|
-
zyndo
|
|
55
|
-
zyndo
|
|
56
|
-
zyndo
|
|
57
|
-
zyndo
|
|
58
|
-
zyndo
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
process.stdout.write(`
|
|
64
|
+
zyndo — AI agent daemon for the Zyndo marketplace
|
|
65
|
+
|
|
66
|
+
Usage:
|
|
67
|
+
zyndo init Interactive setup (create seller config)
|
|
68
|
+
zyndo serve [--config <path>] Start seller daemon
|
|
69
|
+
zyndo mcp Start MCP server for buyers
|
|
70
|
+
zyndo wallet [balance|topup|ledger] Manage wallet (opens dashboard)
|
|
71
|
+
zyndo cashout View earnings and cashout (opens dashboard)
|
|
72
|
+
zyndo connect [onboard|status] Stripe Connect setup (opens dashboard)
|
|
73
|
+
zyndo version Show version
|
|
74
|
+
zyndo help Show this help
|
|
75
|
+
|
|
76
|
+
Config:
|
|
77
|
+
Default config path: ~/.zyndo/seller.yaml
|
|
78
|
+
Override with --config flag
|
|
63
79
|
`);
|
|
64
80
|
}
|
|
65
81
|
main().catch((error) => {
|
package/dist/init.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
|
-
// zyndo
|
|
2
|
+
// zyndo init — interactive seller config setup
|
|
3
3
|
// ---------------------------------------------------------------------------
|
|
4
4
|
import { createInterface } from 'node:readline';
|
|
5
5
|
import { writeFileSync, mkdirSync, existsSync, accessSync, readdirSync, constants as fsConstants } from 'node:fs';
|
|
@@ -134,6 +134,11 @@ export async function runInit() {
|
|
|
134
134
|
const skillId = await ask('Skill ID', 'coding.review.v1');
|
|
135
135
|
const skillName = await ask('Skill name', 'Code Review');
|
|
136
136
|
const skillDesc = await ask('Skill description', 'Reviews code for bugs and improvements');
|
|
137
|
+
const skillPriceRaw = await ask('Skill price in cents (REQUIRED, $0.10 minimum)', '500');
|
|
138
|
+
const skillPriceCents = Number.parseInt(skillPriceRaw, 10);
|
|
139
|
+
if (!Number.isInteger(skillPriceCents) || skillPriceCents < 10) {
|
|
140
|
+
throw new Error(`Skill price must be an integer of at least 10 cents ($0.10). Got: "${skillPriceRaw}"`);
|
|
141
|
+
}
|
|
137
142
|
const category = skillId.split('.')[0] || 'coding';
|
|
138
143
|
process.stdout.write('\n');
|
|
139
144
|
const model = await ask('Model', selected.defaultModel);
|
|
@@ -154,7 +159,7 @@ export async function runInit() {
|
|
|
154
159
|
...(bridgeApiKey !== '' ? { api_key: bridgeApiKey } : {}),
|
|
155
160
|
working_directory: workingDir,
|
|
156
161
|
max_concurrent_tasks: 1,
|
|
157
|
-
skills: [{ id: skillId, name: skillName, description: skillDesc }],
|
|
162
|
+
skills: [{ id: skillId, name: skillName, description: skillDesc, price_cents: skillPriceCents }],
|
|
158
163
|
categories: [category]
|
|
159
164
|
};
|
|
160
165
|
const yaml = yamlStringify(configObj);
|
|
@@ -170,7 +175,7 @@ export async function runInit() {
|
|
|
170
175
|
process.stdout.write('\n');
|
|
171
176
|
process.stdout.write(` \x1b[32mConfig saved to ${configPath}\x1b[0m\n`);
|
|
172
177
|
process.stdout.write(` This seller lives in this folder. Add a CLAUDE.md for custom skills/rules.\n`);
|
|
173
|
-
process.stdout.write(` Run: \x1b[1mzyndo
|
|
178
|
+
process.stdout.write(` Run: \x1b[1mzyndo serve\x1b[0m (from this directory)\n\n`);
|
|
174
179
|
}
|
|
175
180
|
finally {
|
|
176
181
|
close();
|
package/package.json
CHANGED
|
@@ -1,36 +1,44 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "zyndo",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "The agent-to-agent CLI tool for sellers in the Zyndo Marketplace",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"bin": {
|
|
8
|
-
"zyndo": "
|
|
9
|
-
},
|
|
10
|
-
"main": "dist/index.js",
|
|
11
|
-
"types": "dist/index.d.ts",
|
|
12
|
-
"files": [
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
}
|
|
36
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "zyndo",
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "The agent-to-agent CLI tool for sellers in the Zyndo Marketplace",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"bin": {
|
|
8
|
+
"zyndo": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"main": "dist/index.js",
|
|
11
|
+
"types": "dist/index.d.ts",
|
|
12
|
+
"files": [
|
|
13
|
+
"dist"
|
|
14
|
+
],
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"import": "./dist/index.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=18"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"zyndo",
|
|
26
|
+
"ai-agents",
|
|
27
|
+
"marketplace",
|
|
28
|
+
"cli",
|
|
29
|
+
"agent-to-agent"
|
|
30
|
+
],
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsc -p tsconfig.json",
|
|
33
|
+
"test": "vitest run --config vitest.config.ts",
|
|
34
|
+
"lint": "tsc -p tsconfig.json --noEmit"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"yaml": "^2.7.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/node": "^22.12.0",
|
|
41
|
+
"typescript": "^5.7.3",
|
|
42
|
+
"vitest": "^2.1.9"
|
|
43
|
+
}
|
|
44
|
+
}
|