@martini-film/cli 0.1.0

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/help.js ADDED
@@ -0,0 +1,127 @@
1
+ /**
2
+ * `--help` is written for the model that reads it: every command on one screen
3
+ * grouped by noun, every flag with its type and whether it is required, the
4
+ * tool's own description (already written for agents), and one example. Limits
5
+ * live in the descriptions the registry ships, so they are never restated here.
6
+ */
7
+ import { CLI_VERSION } from './api.js';
8
+ import { groupTools } from './manifest.js';
9
+ import { flagSpecs } from './schema.js';
10
+ export const GLOBAL_FLAGS = [
11
+ ['--fields a,b.c', 'keep only these dotted paths of the result (applied on the server)'],
12
+ ['--out <path>', 'write the result (or media bytes) to a file; print one summary line'],
13
+ ['--json <object|@file>', 'pass the whole arguments object as JSON instead of flags'],
14
+ [
15
+ '--wait / --no-wait',
16
+ 'block until produced assets, renders, or runs settle (default on for single-item generation)',
17
+ ],
18
+ ['--timeout <seconds>', 'how long --wait waits before exiting 4 with the pending ids (default 50)'],
19
+ ['--project / --canvas / --run <id>', 'context defaults for projectId / canvasId / runId'],
20
+ [
21
+ '--api-key / --api-url / --profile',
22
+ 'credential and endpoint overrides (else env, .martini/config.json, ~/.config/martini/config.json)',
23
+ ],
24
+ ['--quiet', 'print nothing on success'],
25
+ ];
26
+ export function renderHelp(manifest, compounds) {
27
+ const lines = [];
28
+ lines.push(`martini ${CLI_VERSION} — the Martini CLI for agents and scripts`);
29
+ lines.push('');
30
+ lines.push('Usage: martini <command> [flags] martini <command> --help');
31
+ lines.push('');
32
+ lines.push('Commands (what no single tool does):');
33
+ for (const command of compounds)
34
+ lines.push(` ${command.name.padEnd(28)} ${command.summary}`);
35
+ lines.push('');
36
+ lines.push(`Tools (${manifest.tools.length}; each MCP tool is a command with flags derived from its arguments):`);
37
+ for (const { group, tools } of groupTools(manifest.tools)) {
38
+ lines.push(` ${group}:`);
39
+ lines.push(` ${tools.map(tool => tool.name).join(' ')}`);
40
+ }
41
+ lines.push('');
42
+ lines.push('Global flags:');
43
+ for (const [flag, description] of GLOBAL_FLAGS)
44
+ lines.push(` ${flag.padEnd(36)} ${description}`);
45
+ lines.push('');
46
+ lines.push('Output: JSON on stdout (compact when piped). Errors: one JSON object on stderr.');
47
+ lines.push('Exit codes: 0 ok · 1 tool error · 2 usage · 3 auth · 4 not ready or timed out · 5 insufficient olives');
48
+ lines.push('Docs: https://www.martini.film/docs/cli');
49
+ return lines.join('\n') + '\n';
50
+ }
51
+ function describeFlag(spec) {
52
+ const type = spec.kind === 'array'
53
+ ? `${spec.items ?? 'string'}[] (repeat the flag, or a JSON list)`
54
+ : spec.kind === 'object' || spec.kind === 'json'
55
+ ? 'JSON'
56
+ : spec.kind;
57
+ const parts = [`--${spec.flag}`.padEnd(30), `${type}${spec.required ? ', required' : ''}`];
58
+ if (spec.enum)
59
+ parts.push(`one of: ${spec.enum.map(value => JSON.stringify(value)).join(', ')}`);
60
+ return parts.join(' ');
61
+ }
62
+ export function renderToolHelp(tool) {
63
+ const specs = flagSpecs(tool);
64
+ const lines = [];
65
+ lines.push(`martini ${tool.name}${tool.title ? ` — ${tool.title}` : ''}`);
66
+ lines.push('');
67
+ lines.push(wrap(tool.description, 100));
68
+ lines.push('');
69
+ const facts = [
70
+ tool.annotations.readOnlyHint ? 'read-only' : tool.annotations.destructiveHint ? 'destructive write' : 'write',
71
+ tool.requiresActions ? 'needs workflows (Actions) access' : null,
72
+ tool.deprecated ? `deprecated${tool.deprecated.supersededBy ? `, use ${tool.deprecated.supersededBy}` : ''}` : null,
73
+ ].filter(Boolean);
74
+ lines.push(`Kind: ${facts.join('; ')}`);
75
+ lines.push('');
76
+ lines.push('Flags:');
77
+ if (specs.length === 0)
78
+ lines.push(' (no arguments)');
79
+ for (const spec of specs) {
80
+ lines.push(` ${describeFlag(spec)}`);
81
+ if (spec.description)
82
+ lines.push(` ${wrap(spec.description, 96).split('\n').join('\n ')}`);
83
+ }
84
+ lines.push('');
85
+ lines.push('Example:');
86
+ lines.push(` ${exampleFor(tool, specs)}`);
87
+ lines.push('');
88
+ lines.push('Any argument can also be given as JSON: --json \'{"...": ...}\' or --json @args.json.');
89
+ return lines.join('\n') + '\n';
90
+ }
91
+ export function exampleFor(tool, specs = flagSpecs(tool)) {
92
+ const required = specs.filter(spec => spec.required && spec.property !== 'projectId' && spec.property !== 'canvasId');
93
+ const parts = [`martini ${tool.name}`];
94
+ for (const spec of required) {
95
+ const sample = spec.enum?.[0] !== undefined
96
+ ? JSON.stringify(spec.enum[0])
97
+ : spec.kind === 'boolean'
98
+ ? ''
99
+ : spec.kind === 'number' || spec.kind === 'integer'
100
+ ? '1'
101
+ : spec.kind === 'array'
102
+ ? '<id>'
103
+ : spec.kind === 'object' || spec.kind === 'json'
104
+ ? "'{...}'"
105
+ : `<${spec.flag}>`;
106
+ parts.push(sample ? `--${spec.flag} ${sample}` : `--${spec.flag}`);
107
+ }
108
+ return parts.join(' ');
109
+ }
110
+ export function wrap(text, width) {
111
+ const words = text.split(/\s+/);
112
+ const lines = [];
113
+ let current = '';
114
+ for (const word of words) {
115
+ if ((current + ' ' + word).trim().length > width && current) {
116
+ lines.push(current);
117
+ current = word;
118
+ }
119
+ else {
120
+ current = current ? `${current} ${word}` : word;
121
+ }
122
+ }
123
+ if (current)
124
+ lines.push(current);
125
+ return lines.join('\n');
126
+ }
127
+ //# sourceMappingURL=help.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help.js","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"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"}
package/dist/host.js ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Which agent the CLI is running inside, read from the environment the host
3
+ * sets. Carried in the User-Agent (`martini-cli/0.1.0 (claude-code)`) so a
4
+ * tool call from the CLI under Claude Code is distinguishable from one Claude
5
+ * Code made over MCP. Unknown hosts yield null; nothing is guessed.
6
+ */
7
+ const HOST_ENV_MARKERS = [
8
+ ['CLAUDECODE', 'claude-code'],
9
+ ['CLAUDE_CODE', 'claude-code'],
10
+ ['CURSOR_AGENT', 'cursor'],
11
+ ['CURSOR_TRACE_ID', 'cursor'],
12
+ ['CODEX_SANDBOX', 'codex'],
13
+ ['CODEX_CI', 'codex'],
14
+ ['GEMINI_CLI', 'gemini-cli'],
15
+ ['OPENCODE', 'opencode'],
16
+ ['WINDSURF_AGENT', 'windsurf'],
17
+ ['MARTINI_RUN_ID', 'martini-workflow'],
18
+ ];
19
+ export function detectHostAgent(env = process.env) {
20
+ if (env.MARTINI_HOST_AGENT)
21
+ return env.MARTINI_HOST_AGENT;
22
+ for (const [variable, host] of HOST_ENV_MARKERS) {
23
+ if (env[variable])
24
+ return host;
25
+ }
26
+ if (env.TERM_PROGRAM && /cursor/i.test(env.TERM_PROGRAM))
27
+ return 'cursor';
28
+ return null;
29
+ }
30
+ //# sourceMappingURL=host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host.js","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,gBAAgB,GAA4B;IAChD,CAAC,YAAY,EAAE,aAAa,CAAC;IAC7B,CAAC,aAAa,EAAE,aAAa,CAAC;IAC9B,CAAC,cAAc,EAAE,QAAQ,CAAC;IAC1B,CAAC,iBAAiB,EAAE,QAAQ,CAAC;IAC7B,CAAC,eAAe,EAAE,OAAO,CAAC;IAC1B,CAAC,UAAU,EAAE,OAAO,CAAC;IACrB,CAAC,YAAY,EAAE,YAAY,CAAC;IAC5B,CAAC,UAAU,EAAE,UAAU,CAAC;IACxB,CAAC,gBAAgB,EAAE,UAAU,CAAC;IAC9B,CAAC,gBAAgB,EAAE,kBAAkB,CAAC;CACvC,CAAA;AAED,MAAM,UAAU,eAAe,CAAC,MAAyB,OAAO,CAAC,GAAG;IAClE,IAAI,GAAG,CAAC,kBAAkB;QAAE,OAAO,GAAG,CAAC,kBAAkB,CAAA;IACzD,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,gBAAgB,EAAE,CAAC;QAChD,IAAI,GAAG,CAAC,QAAQ,CAAC;YAAE,OAAO,IAAI,CAAA;IAChC,CAAC;IACD,IAAI,GAAG,CAAC,YAAY,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC;QAAE,OAAO,QAAQ,CAAA;IACzE,OAAO,IAAI,CAAA;AACb,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * The tool manifest the CLI is generated from: `src/generated/manifest.json`,
3
+ * exported from the backend registry with `pnpm --dir backend run export:tool-manifest`
4
+ * and drift-tested there against the live registry. Every entry becomes a
5
+ * command with the tool's name; the JSON Schema becomes its flags.
6
+ */
7
+ import manifestJson from './generated/manifest.json' with { type: 'json' };
8
+ /** Imported, not read at runtime, so the compiled single-file binary embeds it. */
9
+ export function loadManifest() {
10
+ return manifestJson;
11
+ }
12
+ export function findTool(name, manifest = loadManifest()) {
13
+ return manifest.tools.find(tool => tool.name === name);
14
+ }
15
+ /** Tools grouped for `--help`, by the noun their name is about. */
16
+ export function groupTools(tools) {
17
+ const groups = new Map();
18
+ for (const tool of tools) {
19
+ const group = groupOf(tool.name);
20
+ const list = groups.get(group) ?? [];
21
+ list.push(tool);
22
+ groups.set(group, list);
23
+ }
24
+ return [...groups.entries()]
25
+ .sort(([a], [b]) => a.localeCompare(b))
26
+ .map(([group, list]) => ({ group, tools: list.sort((a, b) => a.name.localeCompare(b.name)) }));
27
+ }
28
+ const GROUP_KEYWORDS = [
29
+ [/timeline|checkpoint|render|export_timeline|artifact|audio_report/, 'timeline'],
30
+ [/project_file|json_file|file_input/, 'files'],
31
+ [/workflow|run\b|_run$|actions?\b|^(pause|resume|approve|cancel|list)_run/, 'workflows'],
32
+ [/upload|storage|download/, 'uploads'],
33
+ [/library|subject|collection/, 'library'],
34
+ [/model|voice|upscale_presets/, 'models'],
35
+ [/generate|draft|upscale|enhance|blender|camera/, 'generation'],
36
+ [/bin|node|canvas|text_note|variable|layout|move_|duplicate|delete|metadata|labels|color/, 'canvas'],
37
+ [/comment/, 'comments'],
38
+ [/asset|inspect|frame|crop|view_/, 'assets'],
39
+ [/support/, 'support'],
40
+ [/project/, 'projects'],
41
+ ];
42
+ export function groupOf(name) {
43
+ for (const [pattern, group] of GROUP_KEYWORDS)
44
+ if (pattern.test(name))
45
+ return group;
46
+ return 'other';
47
+ }
48
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,YAAY,MAAM,2BAA2B,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAA;AAgD1E,mFAAmF;AACnF,MAAM,UAAU,YAAY;IAC1B,OAAO,YAAmC,CAAA;AAC5C,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,WAAqB,YAAY,EAAE;IACxE,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAA;AACxD,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAA;IACxC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAChC,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAA;QACpC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACf,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;IACzB,CAAC;IACD,OAAO,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;SACzB,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;SACtC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;AAClG,CAAC;AAED,MAAM,cAAc,GAA4B;IAC9C,CAAC,kEAAkE,EAAE,UAAU,CAAC;IAChF,CAAC,mCAAmC,EAAE,OAAO,CAAC;IAC9C,CAAC,yEAAyE,EAAE,WAAW,CAAC;IACxF,CAAC,yBAAyB,EAAE,SAAS,CAAC;IACtC,CAAC,4BAA4B,EAAE,SAAS,CAAC;IACzC,CAAC,6BAA6B,EAAE,QAAQ,CAAC;IACzC,CAAC,+CAA+C,EAAE,YAAY,CAAC;IAC/D,CAAC,wFAAwF,EAAE,QAAQ,CAAC;IACpG,CAAC,SAAS,EAAE,UAAU,CAAC;IACvB,CAAC,gCAAgC,EAAE,QAAQ,CAAC;IAC5C,CAAC,SAAS,EAAE,SAAS,CAAC;IACtB,CAAC,SAAS,EAAE,UAAU,CAAC;CACxB,CAAA;AAED,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,KAAK,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,cAAc;QAAE,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,KAAK,CAAA;IACnF,OAAO,OAAO,CAAA;AAChB,CAAC"}
package/dist/output.js ADDED
@@ -0,0 +1,128 @@
1
+ /**
2
+ * The output and exit contract (docs/plans/agent-cli.md, decision 4).
3
+ *
4
+ * stdout carries results only: compact JSON when it is a pipe (an agent is
5
+ * reading), indented JSON on a terminal. `--out <path>` writes the result to a
6
+ * file and prints one summary line instead. Errors are one JSON object on
7
+ * stderr: `{ "error": { "code", "message", "hint" } }`, never mixed into stdout.
8
+ *
9
+ * Exit codes: 0 ok · 1 tool error · 2 usage · 3 auth · 4 not ready / timeout ·
10
+ * 5 insufficient credits.
11
+ */
12
+ import { writeFileSync } from 'node:fs';
13
+ import { CliApiError } from './api.js';
14
+ import { ArgumentError } from './schema.js';
15
+ export const EXIT = {
16
+ ok: 0,
17
+ toolError: 1,
18
+ usage: 2,
19
+ auth: 3,
20
+ notReady: 4,
21
+ insufficientCredits: 5,
22
+ };
23
+ function write(options, text) {
24
+ ;
25
+ (options.stdout ?? (line => process.stdout.write(line)))(text);
26
+ }
27
+ export function printResult(value, options = {}) {
28
+ if (options.out) {
29
+ const text = typeof value === 'string' ? value : JSON.stringify(value, null, 2) + '\n';
30
+ writeFileSync(options.out, text);
31
+ if (!options.quiet)
32
+ write(options, `${summarize(value)} → ${options.out}\n`);
33
+ return;
34
+ }
35
+ if (options.quiet)
36
+ return;
37
+ if (typeof value === 'string') {
38
+ write(options, value.endsWith('\n') ? value : `${value}\n`);
39
+ return;
40
+ }
41
+ const tty = options.isTTY ?? Boolean(process.stdout.isTTY);
42
+ write(options, (tty ? JSON.stringify(value, null, 2) : JSON.stringify(value)) + '\n');
43
+ }
44
+ export function printBytes(bytes, options) {
45
+ if (options.out) {
46
+ writeFileSync(options.out, bytes);
47
+ if (!options.quiet)
48
+ write(options, `${bytes.byteLength} bytes${options.contentType ? ` (${options.contentType})` : ''} → ${options.out}\n`);
49
+ return;
50
+ }
51
+ process.stdout.write(bytes);
52
+ }
53
+ /** One line describing a result for the `--out` summary. */
54
+ export function summarize(value) {
55
+ if (value === null || value === undefined)
56
+ return 'empty result';
57
+ if (typeof value !== 'object')
58
+ return String(value);
59
+ if (Array.isArray(value))
60
+ return `${value.length} items`;
61
+ const record = value;
62
+ const keys = Object.keys(record);
63
+ const counted = keys.find(key => Array.isArray(record[key]));
64
+ if (counted)
65
+ return `${record[counted].length} ${counted}`;
66
+ return keys.length ? `object with ${keys.join(', ')}` : 'empty object';
67
+ }
68
+ export function exitCodeFor(error) {
69
+ if (error instanceof ArgumentError)
70
+ return EXIT.usage;
71
+ if (error instanceof CliApiError) {
72
+ if (error.code === 'NO_API_KEY' ||
73
+ error.status === 401 ||
74
+ /^(INVALID_API_KEY|API_KEY_REVOKED|API_KEY_EXPIRED|API_KEY_DEFAULTS_MISSING)$/.test(error.code)) {
75
+ return EXIT.auth;
76
+ }
77
+ if (error.code === 'INSUFFICIENT_CREDITS' || error.code === 'INSUFFICIENT_OLIVES' || error.status === 402) {
78
+ return EXIT.insufficientCredits;
79
+ }
80
+ if (/_NOT_READY$/.test(error.code) || error.code === 'TIMEOUT' || error.code === 'RUN_NOT_ACTIVE')
81
+ return EXIT.notReady;
82
+ if (error.code === 'INVALID_ARGUMENTS' || error.code === 'INVALID_REQUEST' || error.code === 'TOOL_NOT_FOUND') {
83
+ return EXIT.usage;
84
+ }
85
+ return EXIT.toolError;
86
+ }
87
+ return EXIT.toolError;
88
+ }
89
+ export function hintFor(error) {
90
+ if (error instanceof CliApiError) {
91
+ switch (error.code) {
92
+ case 'NO_API_KEY':
93
+ return 'Run martini login (laptops) or set MARTINI_API_KEY (scripts). Inside a workflow run the key is in .martini/config.json.';
94
+ case 'API_KEY_EXPIRED':
95
+ return 'Run martini login again to mint a fresh key.';
96
+ case 'INVALID_ARGUMENTS':
97
+ return error.tool ? `Run martini ${error.tool} --help for the flags and their types.` : undefined;
98
+ case 'TOOL_NOT_FOUND':
99
+ return 'Run martini tools to list what this key can call.';
100
+ case 'RUN_NOT_ACTIVE':
101
+ return 'Run keys work only while their workflow run is executing.';
102
+ case 'INSUFFICIENT_CREDITS':
103
+ return 'Top up olives in Martini, or lower the batch.';
104
+ default:
105
+ if (/_NOT_READY$/.test(error.code))
106
+ return 'Wait for status completed: martini wait <asset-id>, or pass --wait.';
107
+ return undefined;
108
+ }
109
+ }
110
+ if (error instanceof ArgumentError)
111
+ return 'Run martini <command> --help.';
112
+ return undefined;
113
+ }
114
+ export function printError(error, options = {}) {
115
+ const code = exitCodeFor(error);
116
+ const payload = {
117
+ error: {
118
+ code: error instanceof CliApiError ? error.code : error instanceof ArgumentError ? 'USAGE' : 'CLI_ERROR',
119
+ message: error instanceof Error ? error.message : String(error),
120
+ ...(error instanceof CliApiError && error.tool ? { tool: error.tool } : {}),
121
+ ...(hintFor(error) ? { hint: hintFor(error) } : {}),
122
+ exitCode: code,
123
+ },
124
+ };
125
+ (options.stderr ?? (line => process.stderr.write(line)))(JSON.stringify(payload) + '\n');
126
+ return code;
127
+ }
128
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"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"}
package/dist/schema.js ADDED
@@ -0,0 +1,169 @@
1
+ /**
2
+ * From a tool's JSON Schema to command flags, and from parsed flags back to the
3
+ * arguments object the tool expects. Scalars become `--kebab-case` flags,
4
+ * arrays repeat the flag (or take a JSON list), objects take JSON. `--json
5
+ * '{...}'` and `--json @file.json` merge a whole arguments object, so a plan a
6
+ * script computed is submitted without retyping it flag by flag.
7
+ */
8
+ import { readFileSync } from 'node:fs';
9
+ export class ArgumentError extends Error {
10
+ constructor(message) {
11
+ super(message);
12
+ this.name = 'ArgumentError';
13
+ }
14
+ }
15
+ export function kebab(property) {
16
+ return property
17
+ .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
18
+ .replace(/_/g, '-')
19
+ .toLowerCase();
20
+ }
21
+ function schemaKind(schema) {
22
+ if (!schema)
23
+ return 'json';
24
+ const type = Array.isArray(schema.type) ? schema.type.find(t => t !== 'null') : schema.type;
25
+ switch (type) {
26
+ case 'string':
27
+ return 'string';
28
+ case 'number':
29
+ return 'number';
30
+ case 'integer':
31
+ return 'integer';
32
+ case 'boolean':
33
+ return 'boolean';
34
+ case 'array':
35
+ return 'array';
36
+ case 'object':
37
+ return 'object';
38
+ default: {
39
+ const variants = schema.anyOf ?? schema.oneOf;
40
+ if (variants && variants.length > 0) {
41
+ const kinds = new Set(variants.map(variant => schemaKind(variant)));
42
+ if (kinds.size === 1)
43
+ return [...kinds][0];
44
+ }
45
+ if (schema.enum)
46
+ return 'string';
47
+ return 'json';
48
+ }
49
+ }
50
+ }
51
+ export function flagSpecs(tool) {
52
+ const properties = tool.inputSchema.properties ?? {};
53
+ const required = new Set(tool.inputSchema.required ?? []);
54
+ return Object.entries(properties).map(([property, schema]) => {
55
+ const kind = schemaKind(schema);
56
+ const spec = {
57
+ property,
58
+ flag: kebab(property),
59
+ kind,
60
+ required: required.has(property),
61
+ description: schema.description ?? '',
62
+ };
63
+ if (schema.enum)
64
+ spec.enum = schema.enum;
65
+ if (kind === 'array')
66
+ spec.items = schemaKind(schema.items);
67
+ return spec;
68
+ });
69
+ }
70
+ function readJsonArgument(raw, what) {
71
+ const text = raw.startsWith('@') ? readFileSync(raw === '@-' ? 0 : raw.slice(1), 'utf8') : raw;
72
+ try {
73
+ return JSON.parse(text);
74
+ }
75
+ catch {
76
+ throw new ArgumentError(`${what} must be JSON${raw.startsWith('@') ? ` (read from ${raw.slice(1)})` : ''}.`);
77
+ }
78
+ }
79
+ function coerceScalar(raw, kind, what) {
80
+ switch (kind) {
81
+ case 'string':
82
+ return raw;
83
+ case 'number': {
84
+ const value = Number(raw);
85
+ if (!Number.isFinite(value))
86
+ throw new ArgumentError(`${what} must be a number.`);
87
+ return value;
88
+ }
89
+ case 'integer': {
90
+ const value = Number(raw);
91
+ if (!Number.isInteger(value))
92
+ throw new ArgumentError(`${what} must be an integer.`);
93
+ return value;
94
+ }
95
+ case 'boolean':
96
+ if (raw === 'true' || raw === '1' || raw === 'yes')
97
+ return true;
98
+ if (raw === 'false' || raw === '0' || raw === 'no')
99
+ return false;
100
+ throw new ArgumentError(`${what} must be true or false.`);
101
+ case 'object':
102
+ case 'json':
103
+ case 'array':
104
+ return readJsonArgument(raw, what);
105
+ }
106
+ }
107
+ /** Build the tool arguments from flags (plus `--json`); unknown flags are an error so typos never silently drop an argument. */
108
+ export function buildArguments(tool, flags, options = {}) {
109
+ const specs = flagSpecs(tool);
110
+ const byFlag = new Map(specs.map(spec => [spec.flag, spec]));
111
+ const args = {};
112
+ const json = flags.get('json');
113
+ if (json !== undefined && json !== true) {
114
+ const raw = Array.isArray(json) ? json[json.length - 1] : json;
115
+ const merged = readJsonArgument(raw, '--json');
116
+ if (!merged || typeof merged !== 'object' || Array.isArray(merged)) {
117
+ throw new ArgumentError('--json must be an object of tool arguments.');
118
+ }
119
+ Object.assign(args, merged);
120
+ }
121
+ for (const [flag, value] of flags) {
122
+ if (flag === 'json' || options.ignore?.has(flag))
123
+ continue;
124
+ const spec = byFlag.get(flag);
125
+ if (!spec) {
126
+ const known = specs.map(s => `--${s.flag}`).join(', ');
127
+ throw new ArgumentError(`Unknown flag --${flag} for ${tool.name}. Flags: ${known || '(none)'}.`);
128
+ }
129
+ const what = `--${spec.flag}`;
130
+ if (value === true) {
131
+ if (spec.kind !== 'boolean')
132
+ throw new ArgumentError(`${what} needs a value.`);
133
+ args[spec.property] = true;
134
+ continue;
135
+ }
136
+ const values = Array.isArray(value) ? value : [value];
137
+ if (spec.kind === 'array') {
138
+ const single = values.length === 1 && values[0].trim().startsWith('[') ? values[0] : null;
139
+ const jsonList = single ? readJsonArgument(single, what) : null;
140
+ args[spec.property] = Array.isArray(jsonList)
141
+ ? jsonList
142
+ : values.map(raw => coerceScalar(raw, spec.items === 'json' ? 'string' : (spec.items ?? 'string'), what));
143
+ continue;
144
+ }
145
+ args[spec.property] = coerceScalar(values[values.length - 1], spec.kind, what);
146
+ }
147
+ // Context (the run's project, the configured canvas) fills what the caller
148
+ // left out, before required-ness is judged — a sandbox never types --project-id.
149
+ const filled = options.context ? applyContextDefaults(tool, args, options.context) : args;
150
+ for (const spec of specs) {
151
+ if (spec.required && filled[spec.property] === undefined) {
152
+ throw new ArgumentError(`--${spec.flag} is required for ${tool.name}.`);
153
+ }
154
+ }
155
+ return filled;
156
+ }
157
+ /** Fill `projectId` / `canvasId` / `runId` from the configured context when the tool takes them and the caller did not say. */
158
+ export function applyContextDefaults(tool, args, context) {
159
+ const properties = tool.inputSchema.properties ?? {};
160
+ const filled = { ...args };
161
+ if ('projectId' in properties && filled.projectId === undefined && context.projectId)
162
+ filled.projectId = context.projectId;
163
+ if ('canvasId' in properties && filled.canvasId === undefined && context.canvasId)
164
+ filled.canvasId = context.canvasId;
165
+ if ('runId' in properties && filled.runId === undefined && context.runId)
166
+ filled.runId = context.runId;
167
+ return filled;
168
+ }
169
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}