stitchkit 0.122.2 → 0.123.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/CHANGELOG.md +80 -0
- package/dist/browser/client.d.ts.map +1 -1
- package/dist/browser/contract-identity.d.ts +21 -0
- package/dist/browser/contract-identity.d.ts.map +1 -0
- package/dist/browser/unknown-operation.d.ts +3 -0
- package/dist/browser/unknown-operation.d.ts.map +1 -0
- package/dist/contract/define.d.ts +6 -2
- package/dist/contract/define.d.ts.map +1 -1
- package/dist/contract/endpoint-capabilities.d.ts.map +1 -1
- package/dist/contract/errors.d.ts +4 -0
- package/dist/contract/errors.d.ts.map +1 -1
- package/dist/contract/fingerprint.d.ts +51 -0
- package/dist/contract/fingerprint.d.ts.map +1 -0
- package/dist/contract/identity.d.ts +21 -0
- package/dist/contract/identity.d.ts.map +1 -0
- package/dist/contract/stream.d.ts +32 -0
- package/dist/contract/stream.d.ts.map +1 -1
- package/dist/entrypoints/agent-runtime/browser.js +2 -2
- package/dist/entrypoints/agent-runtime/coding-tools.js +11 -11
- package/dist/entrypoints/agent-runtime/harness.js +12 -12
- package/dist/entrypoints/agent-runtime/openrouter.js +1 -1
- package/dist/entrypoints/agent-runtime/realtime.js +2 -2
- package/dist/entrypoints/agent-runtime/sandbox.js +11 -11
- package/dist/entrypoints/agent-runtime/sqlite/bun.js +15 -15
- package/dist/entrypoints/agent-runtime/sqlite/node.js +15 -15
- package/dist/entrypoints/agent-runtime/testing.js +15 -15
- package/dist/entrypoints/agent-runtime.js +22 -22
- package/dist/entrypoints/application/diagnostic-journal.js +5 -5
- package/dist/entrypoints/application/directory-inbox.js +5 -5
- package/dist/entrypoints/application/grammy.js +1 -1
- package/dist/entrypoints/application.js +7 -7
- package/dist/entrypoints/cli/publish.js +5 -5
- package/dist/entrypoints/cli.d.ts +1 -1
- package/dist/entrypoints/cli.d.ts.map +1 -1
- package/dist/entrypoints/cli.js +20 -17
- package/dist/entrypoints/contract.d.ts +2 -0
- package/dist/entrypoints/contract.d.ts.map +1 -1
- package/dist/entrypoints/contract.js +11 -5
- package/dist/entrypoints/files/packaging.d.ts +1 -0
- package/dist/entrypoints/files/packaging.d.ts.map +1 -1
- package/dist/entrypoints/files/packaging.js +230 -61
- package/dist/entrypoints/files.js +5 -5
- package/dist/entrypoints/geo.js +3 -3
- package/dist/entrypoints/http.js +3 -3
- package/dist/entrypoints/index.d.ts +1 -0
- package/dist/entrypoints/index.d.ts.map +1 -1
- package/dist/entrypoints/index.js +45 -24
- package/dist/entrypoints/live.js +2 -2
- package/dist/entrypoints/node.js +11 -11
- package/dist/entrypoints/observability.js +4 -4
- package/dist/entrypoints/primitives.js +1 -1
- package/dist/entrypoints/process/owner-loss.js +2 -2
- package/dist/entrypoints/process.d.ts +6 -1
- package/dist/entrypoints/process.d.ts.map +1 -1
- package/dist/entrypoints/process.js +370 -9
- package/dist/entrypoints/react.js +2 -2
- package/dist/entrypoints/realtime.js +3 -3
- package/dist/entrypoints/remote.js +20 -10
- package/dist/entrypoints/server.d.ts +1 -0
- package/dist/entrypoints/server.d.ts.map +1 -1
- package/dist/entrypoints/server.js +56 -20
- package/dist/entrypoints/telegram/screens.js +4 -4
- package/dist/entrypoints/telegram.js +6 -6
- package/dist/entrypoints/testing.js +10 -10
- package/dist/entrypoints/tools/agent.js +9 -9
- package/dist/entrypoints/tools/connections.js +7 -7
- package/dist/entrypoints/tools/contract.js +1 -1
- package/dist/entrypoints/tools/invoker.js +7 -7
- package/dist/entrypoints/tools/mcp.js +9 -9
- package/dist/entrypoints/tools/toolkit.js +15 -14
- package/dist/entrypoints/tools.js +17 -17
- package/dist/entrypoints/tracking/contract.js +2 -2
- package/dist/entrypoints/tracking.js +1 -1
- package/dist/files/client-artifact.d.ts +75 -0
- package/dist/files/client-artifact.d.ts.map +1 -0
- package/dist/{index-am1h8c9v.js → index-0d3sm0m9.js} +5 -5
- package/dist/{index-72xtvcvr.js → index-0ndz5r8z.js} +1 -1
- package/dist/index-0v9xb8pz.js +66 -0
- package/dist/{index-qcn84byh.js → index-0w0hxp7n.js} +4 -0
- package/dist/{index-3za04re9.js → index-1c945ten.js} +1 -1
- package/dist/{index-r6v4mc67.js → index-1d7s7da0.js} +1 -1
- package/dist/{index-zsvzhjtk.js → index-20hn8pbh.js} +1 -1
- package/dist/{index-f6pw75e1.js → index-2x2ch0bt.js} +2 -2
- package/dist/{index-61hve0ez.js → index-303qne11.js} +1 -1
- package/dist/{index-g149e9pk.js → index-3bzk2645.js} +1 -1
- package/dist/index-45dyex0j.js +119 -0
- package/dist/{index-nwm3ww60.js → index-64b2dxqz.js} +1 -1
- package/dist/{index-aqwg2dm5.js → index-6k47xdtt.js} +2 -2
- package/dist/index-7q05ag0z.js +10 -0
- package/dist/{index-kz9734jc.js → index-96yjwwgf.js} +6 -5
- package/dist/{index-ff39f9dr.js → index-993vtv1w.js} +3 -3
- package/dist/{index-4jpykzvw.js → index-99nnsz39.js} +2 -2
- package/dist/{index-pfvde2fz.js → index-9ypczvpj.js} +1 -1
- package/dist/{index-qch1vcaa.js → index-a7ebd769.js} +2 -2
- package/dist/{index-98hv3sba.js → index-aw6kx2e6.js} +1 -1
- package/dist/{index-yj6saztf.js → index-bz9cmnqq.js} +96 -14
- package/dist/{index-mtwh9hyp.js → index-cjzaj7ev.js} +1 -1
- package/dist/{index-gtx3eknx.js → index-dv7pa9w6.js} +2 -2
- package/dist/{index-sa99p98w.js → index-eabx6qjh.js} +3 -3
- package/dist/{index-8yxgcyt6.js → index-egg0yp2j.js} +1 -1
- package/dist/{index-h1j71dr1.js → index-enkc9pem.js} +1 -1
- package/dist/{index-aqmadanx.js → index-fa53vygr.js} +2 -2
- package/dist/{index-e6c2spsd.js → index-fpwbskp2.js} +1 -1
- package/dist/{index-m8a44e64.js → index-ftk3838x.js} +1 -1
- package/dist/{index-j95jp7ee.js → index-gdqawggb.js} +1 -1
- package/dist/{index-9dyd8xzf.js → index-hkw233vx.js} +2 -2
- package/dist/{index-9jfdm5tg.js → index-hkxgennw.js} +7 -1
- package/dist/{index-qaqxdbxf.js → index-j8rda9n6.js} +7 -7
- package/dist/{index-4tyt1qya.js → index-jc5xgkpk.js} +2 -2
- package/dist/{index-s9a0fjh3.js → index-kffm4r8w.js} +1 -1
- package/dist/{index-5w6t91ze.js → index-m8ddk770.js} +1 -1
- package/dist/{index-2fc1k9k2.js → index-mdyhr36s.js} +32 -122
- package/dist/{index-r7a7r7ha.js → index-mfntvj58.js} +6 -3
- package/dist/{index-gq3fnq3f.js → index-n90tkkcv.js} +2 -2
- package/dist/{index-k42ckyzx.js → index-ndjzbt2v.js} +2 -2
- package/dist/{index-ycqhyars.js → index-qc7tq0za.js} +3 -3
- package/dist/{index-9frf01t9.js → index-r0xr7y4m.js} +1 -1
- package/dist/{index-s3yxw6kt.js → index-s512scra.js} +9 -7
- package/dist/{index-1h2zv8rx.js → index-sqc6ezrb.js} +41 -1
- package/dist/{index-2bqf0a74.js → index-sqkttz7z.js} +1 -1
- package/dist/{index-rbzq0q16.js → index-t8jz0e20.js} +1 -1
- package/dist/{index-8ryydawp.js → index-tt3ej8r3.js} +1 -1
- package/dist/{index-x4p3kw1p.js → index-tynna0n4.js} +6 -6
- package/dist/{index-72r9k0av.js → index-v62cpkx3.js} +1 -1
- package/dist/{index-10rg78vf.js → index-v8xm2s9v.js} +2 -2
- package/dist/{index-y6ye582c.js → index-w0wy05gr.js} +10 -10
- package/dist/{index-kw1ws0cs.js → index-w3nv6kr8.js} +1 -1
- package/dist/{index-eeahxwvg.js → index-ww3gss55.js} +1 -1
- package/dist/{index-6j15ktag.js → index-wzqd6pen.js} +1 -1
- package/dist/{index-aswegq1r.js → index-xjb131sc.js} +367 -131
- package/dist/{index-1fyea34p.js → index-yebkpytc.js} +5 -5
- package/dist/{index-bgcwxhxh.js → index-yfpt7sxr.js} +24 -46
- package/dist/{index-69t14s4a.js → index-yt1gg11x.js} +3 -2
- package/dist/{index-jk29rwkr.js → index-zfncctjp.js} +1 -1
- package/dist/internal/stable-digest.d.ts +5 -0
- package/dist/internal/stable-digest.d.ts.map +1 -1
- package/dist/internal/typed.d.ts +2 -0
- package/dist/internal/typed.d.ts.map +1 -1
- package/dist/process/operation-child.d.ts +38 -0
- package/dist/process/operation-child.d.ts.map +1 -0
- package/dist/process/operation-wire.d.ts +68 -0
- package/dist/process/operation-wire.d.ts.map +1 -0
- package/dist/process/operation.d.ts +74 -0
- package/dist/process/operation.d.ts.map +1 -0
- package/dist/server/contract-identity.d.ts +10 -0
- package/dist/server/contract-identity.d.ts.map +1 -0
- package/dist/server/contract-stream.d.ts.map +1 -1
- package/dist/server/endpoint-response.d.ts.map +1 -1
- package/dist/server/error-hook.d.ts +1 -0
- package/dist/server/error-hook.d.ts.map +1 -1
- package/dist/tools/cli/args-route.d.ts.map +1 -1
- package/dist/tools/cli/args-tokens.d.ts.map +1 -1
- package/dist/tools/cli/command.d.ts +39 -18
- package/dist/tools/cli/command.d.ts.map +1 -1
- package/dist/tools/cli/format.d.ts.map +1 -1
- package/dist/tools/cli/help.d.ts.map +1 -1
- package/dist/tools/cli/invoke.d.ts +3 -1
- package/dist/tools/cli/invoke.d.ts.map +1 -1
- package/dist/tools/cli/io.d.ts +6 -0
- package/dist/tools/cli/io.d.ts.map +1 -1
- package/dist/tools/cli/managed-surface.d.ts +2 -0
- package/dist/tools/cli/managed-surface.d.ts.map +1 -1
- package/dist/tools/cli/policy.d.ts +14 -0
- package/dist/tools/cli/policy.d.ts.map +1 -1
- package/dist/tools/cli/run-managed.d.ts.map +1 -1
- package/dist/tools/cli/run-native.d.ts.map +1 -1
- package/dist/tools/cli/run-stream.d.ts +23 -0
- package/dist/tools/cli/run-stream.d.ts.map +1 -0
- package/dist/tools/cli/session.d.ts +8 -0
- package/dist/tools/cli/session.d.ts.map +1 -1
- package/dist/tools/cli/stream-surface.d.ts +17 -0
- package/dist/tools/cli/stream-surface.d.ts.map +1 -0
- package/dist/tools/execute.d.ts +7 -1
- package/dist/tools/execute.d.ts.map +1 -1
- package/dist/tools/invoker.d.ts.map +1 -1
- package/dist/tools/remote.d.ts.map +1 -1
- package/llms/cli.2.txt +56 -1
- package/llms/cli.txt +68 -1
- package/llms/contract.txt +4 -1
- package/llms/files-packaging.txt +10 -0
- package/llms/process.2.txt +75 -1
- package/llms/process.txt +59 -25
- package/llms/server.4.txt +8 -4
- package/llms/server.5.txt +1 -0
- package/llms/stitchkit.2.txt +74 -0
- package/llms/stitchkit.txt +5 -5
- package/llms/tools.txt +1 -1
- package/llms/{upgrading-0.106.0-0.122.0.txt → upgrading-0.106.0-0.123.0.txt} +50 -3
- package/llms/upgrading.txt +1 -1
- package/llms-full.txt +379 -13
- package/llms.txt +7 -7
- package/package.json +1 -1
- package/dist/index-h2fhjqy7.js +0 -19
- package/dist/index-m5m9rmvt.js +0 -44
|
@@ -1,45 +1,53 @@
|
|
|
1
1
|
import {
|
|
2
2
|
validateDeclaredOutput
|
|
3
|
-
} from "./index-
|
|
3
|
+
} from "./index-ndjzbt2v.js";
|
|
4
4
|
import {
|
|
5
5
|
jsonSchemaObjectCoercionMembers
|
|
6
6
|
} from "./index-dsa676h8.js";
|
|
7
7
|
import {
|
|
8
8
|
coerceJsonArgs2
|
|
9
|
-
} from "./index-
|
|
9
|
+
} from "./index-t8jz0e20.js";
|
|
10
10
|
import {
|
|
11
|
+
toJsonSchema,
|
|
11
12
|
jsonSchemaFields
|
|
12
13
|
} from "./index-ct75c3at.js";
|
|
13
14
|
import {
|
|
15
|
+
toolSurfaceOutputSchema,
|
|
14
16
|
objectShapeKeys,
|
|
17
|
+
mergeSchemas,
|
|
18
|
+
toToolName,
|
|
15
19
|
assertUniqueToolName,
|
|
16
20
|
buildToolPresentationSchema
|
|
17
|
-
} from "./index-
|
|
21
|
+
} from "./index-tynna0n4.js";
|
|
18
22
|
import {
|
|
19
23
|
toolResultFromError,
|
|
20
24
|
toolErrorFromResult
|
|
21
|
-
} from "./index-
|
|
25
|
+
} from "./index-s512scra.js";
|
|
22
26
|
import {
|
|
23
27
|
createToolRunner,
|
|
24
28
|
formatToolError
|
|
25
|
-
} from "./index-
|
|
29
|
+
} from "./index-qc7tq0za.js";
|
|
26
30
|
import {
|
|
27
31
|
isRepeatableRead
|
|
28
32
|
} from "./index-332d0m9g.js";
|
|
33
|
+
import {
|
|
34
|
+
readContractStreamItems,
|
|
35
|
+
contractStreamLifetimeExceeded
|
|
36
|
+
} from "./index-0v9xb8pz.js";
|
|
29
37
|
import {
|
|
30
38
|
writeContainedFile
|
|
31
|
-
} from "./index-
|
|
39
|
+
} from "./index-fa53vygr.js";
|
|
32
40
|
import {
|
|
33
41
|
openPinnedDirectory,
|
|
34
42
|
isSafeEntryName,
|
|
35
43
|
containedEntryMetadata
|
|
36
|
-
} from "./index-
|
|
44
|
+
} from "./index-ww3gss55.js";
|
|
37
45
|
import {
|
|
38
46
|
pollUntil
|
|
39
47
|
} from "./index-bph35vpy.js";
|
|
40
48
|
import {
|
|
41
49
|
collectToolSurface
|
|
42
|
-
} from "./index-
|
|
50
|
+
} from "./index-993vtv1w.js";
|
|
43
51
|
import {
|
|
44
52
|
fetchGuarded,
|
|
45
53
|
readCapped
|
|
@@ -57,32 +65,108 @@ import {
|
|
|
57
65
|
import {
|
|
58
66
|
AppError2,
|
|
59
67
|
STITCH_ERROR_STATUS2
|
|
60
|
-
} from "./index-
|
|
68
|
+
} from "./index-0w0hxp7n.js";
|
|
61
69
|
import {
|
|
62
|
-
isRecord
|
|
63
|
-
|
|
70
|
+
isRecord,
|
|
71
|
+
isAsyncIterable
|
|
72
|
+
} from "./index-hkxgennw.js";
|
|
73
|
+
|
|
74
|
+
// src/tools/cli/format.ts
|
|
75
|
+
var DEFAULT_EXIT_CODES2 = {
|
|
76
|
+
VALIDATION_ERROR: 1,
|
|
77
|
+
BAD_REQUEST: 1,
|
|
78
|
+
UNAUTHORIZED: 2,
|
|
79
|
+
FORBIDDEN: 3,
|
|
80
|
+
NOT_FOUND: 4,
|
|
81
|
+
UNKNOWN_OPERATION: 4,
|
|
82
|
+
CONFLICT: 5,
|
|
83
|
+
RATE_LIMITED: 6,
|
|
84
|
+
TIMEOUT: 7,
|
|
85
|
+
REQUEST_ABORTED: 130,
|
|
86
|
+
REQUEST_TIMEOUT: 7,
|
|
87
|
+
CONNECTION_TIMEOUT: 7,
|
|
88
|
+
STREAM_LIFETIME_EXCEEDED: 7,
|
|
89
|
+
CONNECTION_RESPONSE_TOO_LARGE: 1,
|
|
90
|
+
CONNECTION_REQUEST_FAILED: 1,
|
|
91
|
+
UPSTREAM_TOOL_ERROR: 1,
|
|
92
|
+
WAIT_FAILED: 1,
|
|
93
|
+
CLI_COMMAND_UNAVAILABLE: 1,
|
|
94
|
+
CLI_PRESENTATION_FAILED: 8,
|
|
95
|
+
INTERNAL_SERVER_ERROR: 1
|
|
96
|
+
};
|
|
97
|
+
function cliExitCode2(result, exitCodes) {
|
|
98
|
+
if (result.ok)
|
|
99
|
+
return 0;
|
|
100
|
+
const codes = { ...DEFAULT_EXIT_CODES2, ...exitCodes };
|
|
101
|
+
return Object.hasOwn(codes, result.code) ? codes[result.code] ?? 1 : 1;
|
|
102
|
+
}
|
|
103
|
+
function emitResult2(result, writers, opts) {
|
|
104
|
+
if (result.ok) {
|
|
105
|
+
if (result.data === undefined)
|
|
106
|
+
return 0;
|
|
107
|
+
const text = opts.json ? JSON.stringify(result.data) : JSON.stringify(result.data, null, 2);
|
|
108
|
+
writers.stdout(`${text}
|
|
109
|
+
`);
|
|
110
|
+
return 0;
|
|
111
|
+
}
|
|
112
|
+
const error = formatToolError(result, opts.toolName, opts.errorHint);
|
|
113
|
+
const text = opts.json ? JSON.stringify(error) : JSON.stringify(error, null, 2);
|
|
114
|
+
writers.stderr(`${text}
|
|
115
|
+
`);
|
|
116
|
+
return cliExitCode2(result, opts.exitCodes);
|
|
117
|
+
}
|
|
118
|
+
function presentationFailureHint(repeatable, printed) {
|
|
119
|
+
if (repeatable) {
|
|
120
|
+
return "The result was not printed: this command only reads. Repeat it with a corrected view.";
|
|
121
|
+
}
|
|
122
|
+
return printed ? "The complete, unformatted result is on stdout. Do not repeat the command to recover its result." : "The command returned no result. Do not repeat it.";
|
|
123
|
+
}
|
|
124
|
+
function emitPresentationFailure(result, failure, writers, opts) {
|
|
125
|
+
const printed = !opts.repeatable && result.data !== undefined;
|
|
126
|
+
if (printed)
|
|
127
|
+
emitResult2(result, writers, opts);
|
|
128
|
+
return emitResult2({
|
|
129
|
+
ok: false,
|
|
130
|
+
code: "CLI_PRESENTATION_FAILED",
|
|
131
|
+
retryable: false,
|
|
132
|
+
details: {
|
|
133
|
+
message: "The command completed successfully, but its result presentation failed.",
|
|
134
|
+
command: opts.toolName,
|
|
135
|
+
operationSucceeded: true,
|
|
136
|
+
resultOnStdout: printed,
|
|
137
|
+
cause: formatToolError(failure)
|
|
138
|
+
},
|
|
139
|
+
hint: presentationFailureHint(opts.repeatable, printed)
|
|
140
|
+
}, writers, { json: opts.json, toolName: opts.toolName, exitCodes: opts.exitCodes });
|
|
141
|
+
}
|
|
64
142
|
|
|
65
143
|
// src/tools/cli/command.ts
|
|
144
|
+
function defineCliResult2(output, policy) {
|
|
145
|
+
return { ...policy, output };
|
|
146
|
+
}
|
|
66
147
|
function defineCliCommand2(definition) {
|
|
67
148
|
return definition;
|
|
68
149
|
}
|
|
69
150
|
function cliCommandReturnsResult(definition) {
|
|
70
151
|
return definition.output !== undefined;
|
|
71
152
|
}
|
|
72
|
-
function cliCommandSuccessExitCode(
|
|
73
|
-
const successExitCode =
|
|
153
|
+
function cliCommandSuccessExitCode(policy, data) {
|
|
154
|
+
const successExitCode = policy?.exitCode?.(data) ?? 0;
|
|
74
155
|
if (!Number.isSafeInteger(successExitCode) || successExitCode < 0 || successExitCode > 255) {
|
|
75
156
|
throw new Error("CLI success exit code must be an integer from 0 to 255");
|
|
76
157
|
}
|
|
77
158
|
return successExitCode;
|
|
78
159
|
}
|
|
79
|
-
function
|
|
80
|
-
|
|
160
|
+
function cliCommandResultPolicy(definition) {
|
|
161
|
+
return cliCommandReturnsResult(definition) ? definition : undefined;
|
|
162
|
+
}
|
|
163
|
+
function prepareCliCommandEmission(policy, result, options) {
|
|
164
|
+
if (!result.ok || policy === undefined) {
|
|
81
165
|
return { result, successExitCode: 0 };
|
|
82
166
|
}
|
|
83
167
|
let successExitCode;
|
|
84
168
|
try {
|
|
85
|
-
successExitCode = cliCommandSuccessExitCode(
|
|
169
|
+
successExitCode = cliCommandSuccessExitCode(policy, result.data);
|
|
86
170
|
} catch (error) {
|
|
87
171
|
return {
|
|
88
172
|
result: toolResultFromError(new Error("CLI result policy failed", { cause: error })),
|
|
@@ -90,9 +174,9 @@ function prepareCliCommandEmission(definition, result, options) {
|
|
|
90
174
|
};
|
|
91
175
|
}
|
|
92
176
|
try {
|
|
93
|
-
if (
|
|
177
|
+
if (policy.present === undefined)
|
|
94
178
|
return { result, successExitCode };
|
|
95
|
-
const presentation =
|
|
179
|
+
const presentation = policy.present({ result: result.data, options });
|
|
96
180
|
if (typeof presentation !== "string") {
|
|
97
181
|
throw new Error("CLI result presenter must return a string");
|
|
98
182
|
}
|
|
@@ -105,6 +189,18 @@ function prepareCliCommandEmission(definition, result, options) {
|
|
|
105
189
|
};
|
|
106
190
|
}
|
|
107
191
|
}
|
|
192
|
+
function emitCliCommandResult(policy, result, options, writers, emit) {
|
|
193
|
+
const emission = prepareCliCommandEmission(policy, result, options);
|
|
194
|
+
if (emission.result.ok && emission.presentationFailure !== undefined) {
|
|
195
|
+
return emitPresentationFailure(emission.result, emission.presentationFailure, writers, emit);
|
|
196
|
+
}
|
|
197
|
+
if (emission.result.ok && emission.presentation !== undefined) {
|
|
198
|
+
writers.stdout(emission.presentation);
|
|
199
|
+
return emission.successExitCode;
|
|
200
|
+
}
|
|
201
|
+
const emitted = emitResult2(emission.result, writers, emit);
|
|
202
|
+
return emission.result.ok ? emission.successExitCode : emitted;
|
|
203
|
+
}
|
|
108
204
|
function cliCommandPresentationSchema(definition) {
|
|
109
205
|
return buildToolPresentationSchema({
|
|
110
206
|
inputSchema: definition.input,
|
|
@@ -146,73 +242,6 @@ async function executeCliCommand(definition, rawArgs, options, writers, coerceJs
|
|
|
146
242
|
}
|
|
147
243
|
}
|
|
148
244
|
|
|
149
|
-
// src/tools/cli/format.ts
|
|
150
|
-
var DEFAULT_EXIT_CODES2 = {
|
|
151
|
-
VALIDATION_ERROR: 1,
|
|
152
|
-
BAD_REQUEST: 1,
|
|
153
|
-
UNAUTHORIZED: 2,
|
|
154
|
-
FORBIDDEN: 3,
|
|
155
|
-
NOT_FOUND: 4,
|
|
156
|
-
CONFLICT: 5,
|
|
157
|
-
RATE_LIMITED: 6,
|
|
158
|
-
TIMEOUT: 7,
|
|
159
|
-
REQUEST_ABORTED: 130,
|
|
160
|
-
REQUEST_TIMEOUT: 7,
|
|
161
|
-
CONNECTION_TIMEOUT: 7,
|
|
162
|
-
CONNECTION_RESPONSE_TOO_LARGE: 1,
|
|
163
|
-
CONNECTION_REQUEST_FAILED: 1,
|
|
164
|
-
UPSTREAM_TOOL_ERROR: 1,
|
|
165
|
-
WAIT_FAILED: 1,
|
|
166
|
-
CLI_COMMAND_UNAVAILABLE: 1,
|
|
167
|
-
CLI_PRESENTATION_FAILED: 8,
|
|
168
|
-
INTERNAL_SERVER_ERROR: 1
|
|
169
|
-
};
|
|
170
|
-
function cliExitCode2(result, exitCodes) {
|
|
171
|
-
if (result.ok)
|
|
172
|
-
return 0;
|
|
173
|
-
const codes = { ...DEFAULT_EXIT_CODES2, ...exitCodes };
|
|
174
|
-
return Object.hasOwn(codes, result.code) ? codes[result.code] ?? 1 : 1;
|
|
175
|
-
}
|
|
176
|
-
function emitResult2(result, writers, opts) {
|
|
177
|
-
if (result.ok) {
|
|
178
|
-
if (result.data === undefined)
|
|
179
|
-
return 0;
|
|
180
|
-
const text = opts.json ? JSON.stringify(result.data) : JSON.stringify(result.data, null, 2);
|
|
181
|
-
writers.stdout(`${text}
|
|
182
|
-
`);
|
|
183
|
-
return 0;
|
|
184
|
-
}
|
|
185
|
-
const error = formatToolError(result, opts.toolName, opts.errorHint);
|
|
186
|
-
const text = opts.json ? JSON.stringify(error) : JSON.stringify(error, null, 2);
|
|
187
|
-
writers.stderr(`${text}
|
|
188
|
-
`);
|
|
189
|
-
return cliExitCode2(result, opts.exitCodes);
|
|
190
|
-
}
|
|
191
|
-
function presentationFailureHint(repeatable, printed) {
|
|
192
|
-
if (repeatable) {
|
|
193
|
-
return "The result was not printed: this command only reads. Repeat it with a corrected view.";
|
|
194
|
-
}
|
|
195
|
-
return printed ? "The complete, unformatted result is on stdout. Do not repeat the command to recover its result." : "The command returned no result. Do not repeat it.";
|
|
196
|
-
}
|
|
197
|
-
function emitPresentationFailure(result, failure, writers, opts) {
|
|
198
|
-
const printed = !opts.repeatable && result.data !== undefined;
|
|
199
|
-
if (printed)
|
|
200
|
-
emitResult2(result, writers, opts);
|
|
201
|
-
return emitResult2({
|
|
202
|
-
ok: false,
|
|
203
|
-
code: "CLI_PRESENTATION_FAILED",
|
|
204
|
-
retryable: false,
|
|
205
|
-
details: {
|
|
206
|
-
message: "The command completed successfully, but its result presentation failed.",
|
|
207
|
-
command: opts.toolName,
|
|
208
|
-
operationSucceeded: true,
|
|
209
|
-
resultOnStdout: printed,
|
|
210
|
-
cause: formatToolError(failure)
|
|
211
|
-
},
|
|
212
|
-
hint: presentationFailureHint(opts.repeatable, printed)
|
|
213
|
-
}, writers, { json: opts.json, toolName: opts.toolName, exitCodes: opts.exitCodes });
|
|
214
|
-
}
|
|
215
|
-
|
|
216
245
|
// src/tools/cli/args-fields.ts
|
|
217
246
|
import { z } from "zod";
|
|
218
247
|
|
|
@@ -575,6 +604,9 @@ function resolvePositionals(command, descriptor, configured) {
|
|
|
575
604
|
}
|
|
576
605
|
return [...configured];
|
|
577
606
|
}
|
|
607
|
+
function cliResultPolicy(config, command) {
|
|
608
|
+
return config.results && Object.hasOwn(config.results, command) ? config.results[command] : undefined;
|
|
609
|
+
}
|
|
578
610
|
function applyCliPresentationPolicy(command, descriptor, config) {
|
|
579
611
|
const base = { ...descriptor, aliases: new Map };
|
|
580
612
|
const configuredAliases = config.optionAliases && Object.hasOwn(config.optionAliases, command) ? config.optionAliases[command] : undefined;
|
|
@@ -588,7 +620,8 @@ function applyCliPresentationPolicy(command, descriptor, config) {
|
|
|
588
620
|
function assertCliPoliciesResolved(commands, config) {
|
|
589
621
|
const configuredNames = new Set([
|
|
590
622
|
...Object.keys(config.optionAliases ?? {}),
|
|
591
|
-
...Object.keys(config.positionals ?? {})
|
|
623
|
+
...Object.keys(config.positionals ?? {}),
|
|
624
|
+
...Object.keys(config.results ?? {})
|
|
592
625
|
]);
|
|
593
626
|
if (config.defaultCommand !== undefined)
|
|
594
627
|
configuredNames.add(config.defaultCommand);
|
|
@@ -599,6 +632,33 @@ function assertCliPoliciesResolved(commands, config) {
|
|
|
599
632
|
}
|
|
600
633
|
}
|
|
601
634
|
|
|
635
|
+
// src/tools/cli/stream-surface.ts
|
|
636
|
+
function collectCliStreams(services) {
|
|
637
|
+
const streams = new Map;
|
|
638
|
+
for (const service of services) {
|
|
639
|
+
for (const [methodName, method] of Object.entries(service.methods)) {
|
|
640
|
+
if (method.stream === undefined || !method.expose?.includes("CLI"))
|
|
641
|
+
continue;
|
|
642
|
+
const name = toToolName(service.name, methodName);
|
|
643
|
+
streams.set(name, {
|
|
644
|
+
descriptor: method.stream,
|
|
645
|
+
tool: {
|
|
646
|
+
method,
|
|
647
|
+
name,
|
|
648
|
+
argumentSchema: mergeSchemas(method.paramsSchema, method.inputSchema),
|
|
649
|
+
presentationSchema: buildToolPresentationSchema({
|
|
650
|
+
paramsSchema: method.paramsSchema,
|
|
651
|
+
inputSchema: method.inputSchema,
|
|
652
|
+
unrepresentable: "any"
|
|
653
|
+
}),
|
|
654
|
+
shouldExtend: false
|
|
655
|
+
}
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
return streams;
|
|
660
|
+
}
|
|
661
|
+
|
|
602
662
|
// src/tools/cli/invoke.ts
|
|
603
663
|
function parseCliGlobals(schema, globals) {
|
|
604
664
|
if (!schema)
|
|
@@ -657,8 +717,8 @@ async function createCliInvoker2(config, globals) {
|
|
|
657
717
|
if (!tool) {
|
|
658
718
|
return cliInvocationResult2({
|
|
659
719
|
ok: false,
|
|
660
|
-
code: "
|
|
661
|
-
details: { message: `Unknown command "${command}"
|
|
720
|
+
code: "UNKNOWN_OPERATION",
|
|
721
|
+
details: { message: `Unknown command "${command}"`, operation: command }
|
|
662
722
|
}, command, config);
|
|
663
723
|
}
|
|
664
724
|
let result;
|
|
@@ -667,10 +727,19 @@ async function createCliInvoker2(config, globals) {
|
|
|
667
727
|
} catch (error) {
|
|
668
728
|
result = toolResultFromError(error);
|
|
669
729
|
}
|
|
670
|
-
return cliInvocationResult2(result, command, config);
|
|
730
|
+
return withSuccessExitCode(cliInvocationResult2(result, command, config), cliResultPolicy(config, command), result, command, config);
|
|
671
731
|
}
|
|
672
732
|
};
|
|
673
733
|
}
|
|
734
|
+
function withSuccessExitCode(invocation, policy, result, command, config) {
|
|
735
|
+
if (!result.ok || policy === undefined)
|
|
736
|
+
return invocation;
|
|
737
|
+
try {
|
|
738
|
+
return { ...invocation, exitCode: cliCommandSuccessExitCode(policy, result.data) };
|
|
739
|
+
} catch (error) {
|
|
740
|
+
return cliInvocationResult2(toolResultFromError(new Error("CLI result policy failed", { cause: error })), command, config);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
674
743
|
var IN_PROCESS_RUN_OPTIONS = Object.freeze({
|
|
675
744
|
json: false,
|
|
676
745
|
wait: false,
|
|
@@ -689,17 +758,7 @@ async function runNativeCommand(definition, args, config, globals) {
|
|
|
689
758
|
err += text;
|
|
690
759
|
}
|
|
691
760
|
}, config.coerceJsonArgs ?? true, globals);
|
|
692
|
-
|
|
693
|
-
if (invocation.ok) {
|
|
694
|
-
try {
|
|
695
|
-
invocation = {
|
|
696
|
-
...invocation,
|
|
697
|
-
exitCode: cliCommandSuccessExitCode(definition, result.ok ? result.data : undefined)
|
|
698
|
-
};
|
|
699
|
-
} catch (error) {
|
|
700
|
-
invocation = cliInvocationResult2(toolResultFromError(error), definition.name, config);
|
|
701
|
-
}
|
|
702
|
-
}
|
|
761
|
+
const invocation = withSuccessExitCode(cliInvocationResult2(result, definition.name, config), cliCommandResultPolicy(definition), result, definition.name, config);
|
|
703
762
|
if (out === "" && err === "")
|
|
704
763
|
return invocation;
|
|
705
764
|
return {
|
|
@@ -727,14 +786,38 @@ function buildCliSurface(config, auth, nativeHelp, applicationGlobalNames, shape
|
|
|
727
786
|
help.set(mountable.name, descriptor);
|
|
728
787
|
}
|
|
729
788
|
}
|
|
789
|
+
const streams = collectCliStreams(services);
|
|
790
|
+
for (const [name, stream] of streams) {
|
|
791
|
+
const descriptor = applyCliPresentationPolicy(name, {
|
|
792
|
+
...managedCliDescriptor(stream.tool),
|
|
793
|
+
outputSchema: stream.descriptor.item,
|
|
794
|
+
stream: true
|
|
795
|
+
}, config);
|
|
796
|
+
const issue = shapeIssue?.(name, descriptor, help.has(name), config.passthrough?.[name], applicationGlobalNames);
|
|
797
|
+
if (issue !== undefined)
|
|
798
|
+
throw new Error(issue);
|
|
799
|
+
help.set(name, descriptor);
|
|
800
|
+
}
|
|
730
801
|
assertCliPoliciesResolved(help, config);
|
|
731
|
-
|
|
802
|
+
for (const [name, policy] of Object.entries(config.results ?? {})) {
|
|
803
|
+
if (!tools.has(name) && !streams.has(name)) {
|
|
804
|
+
throw new Error(`[stitchkit] CLI result policy "${name}" targets a command that is not managed; a native command declares present and exitCode on defineCliCommand`);
|
|
805
|
+
}
|
|
806
|
+
if (policy.output !== undefined && policy.output !== help.get(name)?.outputSchema) {
|
|
807
|
+
throw new Error(`[stitchkit] CLI result policy "${name}" is typed against a schema that is not the one the command answers with; pass the command's own output schema to defineCliResult`);
|
|
808
|
+
}
|
|
809
|
+
if (streams.has(name) && policy.exitCode !== undefined) {
|
|
810
|
+
throw new Error(`[stitchkit] CLI result policy "${name}" declares exitCode for a stream command; a stream has no single result to classify`);
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
return { tools, streams, help };
|
|
732
814
|
}
|
|
733
815
|
function managedCliDescriptor(tool) {
|
|
734
816
|
return {
|
|
735
817
|
description: tool.method.desc,
|
|
736
818
|
argumentSchema: tool.argumentSchema,
|
|
737
|
-
presentationSchema: tool.presentationSchema
|
|
819
|
+
presentationSchema: tool.presentationSchema,
|
|
820
|
+
outputSchema: toolSurfaceOutputSchema(tool.method)
|
|
738
821
|
};
|
|
739
822
|
}
|
|
740
823
|
|
|
@@ -786,6 +869,9 @@ function readPipedStdin(input = process.stdin) {
|
|
|
786
869
|
}
|
|
787
870
|
|
|
788
871
|
// src/tools/cli/io.ts
|
|
872
|
+
function isReaderGone(error) {
|
|
873
|
+
return isRecord(error) && (error.code === "EPIPE" || error.code === "ERR_STREAM_DESTROYED");
|
|
874
|
+
}
|
|
789
875
|
function createCliIo(config) {
|
|
790
876
|
let pendingWrite;
|
|
791
877
|
let writeFailed = false;
|
|
@@ -796,6 +882,8 @@ function createCliIo(config) {
|
|
|
796
882
|
try {
|
|
797
883
|
offset += writeSync(fd, bytes, offset, bytes.length - offset);
|
|
798
884
|
} catch (error) {
|
|
885
|
+
if (fd === 1 && isReaderGone(error))
|
|
886
|
+
throw error;
|
|
799
887
|
if (isRecord(error) && error.code === "EAGAIN") {
|
|
800
888
|
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 1);
|
|
801
889
|
continue;
|
|
@@ -813,7 +901,24 @@ function createCliIo(config) {
|
|
|
813
901
|
}
|
|
814
902
|
}
|
|
815
903
|
};
|
|
816
|
-
const
|
|
904
|
+
const writeStdout = config.stdout ?? ((text) => writeFd(1, text));
|
|
905
|
+
let readerGone = false;
|
|
906
|
+
const stdoutWhileOpen = (text) => {
|
|
907
|
+
if (readerGone)
|
|
908
|
+
return false;
|
|
909
|
+
try {
|
|
910
|
+
writeStdout(text);
|
|
911
|
+
return true;
|
|
912
|
+
} catch (error) {
|
|
913
|
+
if (!isReaderGone(error))
|
|
914
|
+
throw error;
|
|
915
|
+
readerGone = true;
|
|
916
|
+
return false;
|
|
917
|
+
}
|
|
918
|
+
};
|
|
919
|
+
const stdout = (text) => {
|
|
920
|
+
stdoutWhileOpen(text);
|
|
921
|
+
};
|
|
817
922
|
const stderr = config.stderr ?? ((text) => writeFd(2, text));
|
|
818
923
|
const exit = config.exit ?? ((code) => {
|
|
819
924
|
if (pendingWrite === undefined)
|
|
@@ -822,7 +927,7 @@ function createCliIo(config) {
|
|
|
822
927
|
pendingWrite.then(() => process.exit(writeFailed ? 1 : code));
|
|
823
928
|
});
|
|
824
929
|
const readStdin = config.stdin ?? readPipedStdin;
|
|
825
|
-
return { stdout, stderr, exit, readStdin };
|
|
930
|
+
return { stdout, stdoutWhileOpen, stderr, exit, readStdin };
|
|
826
931
|
}
|
|
827
932
|
|
|
828
933
|
// src/tools/cli/download.ts
|
|
@@ -900,6 +1005,7 @@ var GLOBAL_OPTIONS = [
|
|
|
900
1005
|
["--output-dir <dir>", "Download result media into a directory"],
|
|
901
1006
|
["--quiet", "Suppress non-essential stderr output"],
|
|
902
1007
|
["--dry-run", "Print the resolved call without executing it"],
|
|
1008
|
+
["--schema", "Print the JSON Schema of a command input and output"],
|
|
903
1009
|
["--help, -h", "Show help for a command"],
|
|
904
1010
|
["--help <text>", "List only the commands matching a substring"],
|
|
905
1011
|
["--count-by <field>", "Count records per distinct value of a field"],
|
|
@@ -1105,7 +1211,15 @@ function isOptionToken(token) {
|
|
|
1105
1211
|
function looksLikeOption(token) {
|
|
1106
1212
|
return token.startsWith("--") || /^-[A-Za-z]/.test(token);
|
|
1107
1213
|
}
|
|
1108
|
-
var BOOL_OPTIONS = new Set([
|
|
1214
|
+
var BOOL_OPTIONS = new Set([
|
|
1215
|
+
"json",
|
|
1216
|
+
"wait",
|
|
1217
|
+
"quiet",
|
|
1218
|
+
"dry-run",
|
|
1219
|
+
"help",
|
|
1220
|
+
"schema",
|
|
1221
|
+
"ascending"
|
|
1222
|
+
]);
|
|
1109
1223
|
var VIEW_OPTIONS = new Set(["count-by", "sum", "by", "top", "table", "sort"]);
|
|
1110
1224
|
var VALUE_OPTIONS = new Set(["wait-timeout", "output-dir", ...VIEW_OPTIONS]);
|
|
1111
1225
|
var RESERVED_CLI_OPTIONS = new Set([...BOOL_OPTIONS, ...VALUE_OPTIONS]);
|
|
@@ -1291,8 +1405,8 @@ async function buildManagedSurface(session, typedGlobals, forExecution) {
|
|
|
1291
1405
|
};
|
|
1292
1406
|
}
|
|
1293
1407
|
}
|
|
1294
|
-
const { tools, help } = buildCliSurface(config, auth, nativeHelp, applicationGlobalNames, commandShapeIssue);
|
|
1295
|
-
return { resolved: true, auth, help, tools };
|
|
1408
|
+
const { tools, streams, help } = buildCliSurface(config, auth, nativeHelp, applicationGlobalNames, commandShapeIssue);
|
|
1409
|
+
return { resolved: true, auth, help, tools, streams };
|
|
1296
1410
|
}
|
|
1297
1411
|
|
|
1298
1412
|
// src/tools/cli/args.ts
|
|
@@ -1416,6 +1530,8 @@ function readCliTokens(argv, fields, fieldFor, config) {
|
|
|
1416
1530
|
options.quiet = enabled;
|
|
1417
1531
|
else if (name === "ascending")
|
|
1418
1532
|
ascending = enabled;
|
|
1533
|
+
else if (name === "schema")
|
|
1534
|
+
continue;
|
|
1419
1535
|
else
|
|
1420
1536
|
options.help = options.help || enabled;
|
|
1421
1537
|
continue;
|
|
@@ -1790,7 +1906,8 @@ function nativeDescriptor(definition) {
|
|
|
1790
1906
|
return {
|
|
1791
1907
|
description: definition.description,
|
|
1792
1908
|
argumentSchema: definition.input,
|
|
1793
|
-
presentationSchema: cliCommandPresentationSchema(definition)
|
|
1909
|
+
presentationSchema: cliCommandPresentationSchema(definition),
|
|
1910
|
+
outputSchema: definition.output
|
|
1794
1911
|
};
|
|
1795
1912
|
}
|
|
1796
1913
|
function createCliSession(config, io) {
|
|
@@ -1859,12 +1976,14 @@ function resolveCliRoute(session, argv) {
|
|
|
1859
1976
|
return;
|
|
1860
1977
|
}
|
|
1861
1978
|
const beforeSeparator = commandArgv.indexOf("--") === -1 ? commandArgv : commandArgv.slice(0, commandArgv.indexOf("--"));
|
|
1862
|
-
const
|
|
1863
|
-
if (token === "
|
|
1979
|
+
const asked = (name) => beforeSeparator.some((token) => {
|
|
1980
|
+
if (token === `--${name}` || name === "help" && token === "-h")
|
|
1864
1981
|
return true;
|
|
1865
1982
|
const option = classifyLongOptionToken(token);
|
|
1866
|
-
return option?.name ===
|
|
1983
|
+
return option?.name === name && option.value !== undefined && isReservedBoolWord(option.value) && parseReservedBool(name, option.value);
|
|
1867
1984
|
});
|
|
1985
|
+
const helpRequested = asked("help");
|
|
1986
|
+
const schemaRequested = !helpRequested && asked("schema");
|
|
1868
1987
|
return {
|
|
1869
1988
|
globals,
|
|
1870
1989
|
typedGlobals,
|
|
@@ -1872,9 +1991,20 @@ function resolveCliRoute(session, argv) {
|
|
|
1872
1991
|
command,
|
|
1873
1992
|
commandArgv,
|
|
1874
1993
|
beforeSeparator,
|
|
1875
|
-
helpRequested
|
|
1994
|
+
helpRequested,
|
|
1995
|
+
schemaRequested
|
|
1876
1996
|
};
|
|
1877
1997
|
}
|
|
1998
|
+
function renderCommandSchema(command, descriptor) {
|
|
1999
|
+
return `${JSON.stringify({
|
|
2000
|
+
command,
|
|
2001
|
+
input: descriptor.presentationSchema,
|
|
2002
|
+
...descriptor.outputSchema !== undefined && {
|
|
2003
|
+
[descriptor.stream ? "item" : "output"]: toJsonSchema(descriptor.outputSchema, "output", "any", "draft-07")
|
|
2004
|
+
}
|
|
2005
|
+
})}
|
|
2006
|
+
`;
|
|
2007
|
+
}
|
|
1878
2008
|
function emitOptionsFor(config, json, toolName) {
|
|
1879
2009
|
return {
|
|
1880
2010
|
json,
|
|
@@ -1884,6 +2014,106 @@ function emitOptionsFor(config, json, toolName) {
|
|
|
1884
2014
|
};
|
|
1885
2015
|
}
|
|
1886
2016
|
|
|
2017
|
+
// src/tools/cli/run-stream.ts
|
|
2018
|
+
async function runStreamCommand(session, route, managed, stream, { toolArgs, options }) {
|
|
2019
|
+
const { config } = session;
|
|
2020
|
+
const { stdout, stderr, exit } = session.io;
|
|
2021
|
+
const command = stream.tool.name;
|
|
2022
|
+
if (options.wait || options.outputDir !== undefined || options.view !== undefined) {
|
|
2023
|
+
stderr(`--wait, --output-dir and aggregate views do not apply to stream command "${command}"
|
|
2024
|
+
`);
|
|
2025
|
+
return exit(2);
|
|
2026
|
+
}
|
|
2027
|
+
const abort = new AbortController;
|
|
2028
|
+
let cancelled = false;
|
|
2029
|
+
const cancel = () => {
|
|
2030
|
+
cancelled = true;
|
|
2031
|
+
abort.abort(config.signal?.reason);
|
|
2032
|
+
};
|
|
2033
|
+
if (config.signal?.aborted)
|
|
2034
|
+
cancel();
|
|
2035
|
+
else
|
|
2036
|
+
config.signal?.addEventListener("abort", cancel, { once: true });
|
|
2037
|
+
const runTool = createToolRunner({
|
|
2038
|
+
source: "cli",
|
|
2039
|
+
toolSurface: true,
|
|
2040
|
+
context: { ...config.context?.(managed.auth, route.typedGlobals), signal: abort.signal },
|
|
2041
|
+
hooks: config.hooks,
|
|
2042
|
+
lifecycle: config.lifecycle,
|
|
2043
|
+
coerceJsonArgs: config.coerceJsonArgs
|
|
2044
|
+
});
|
|
2045
|
+
let opened;
|
|
2046
|
+
try {
|
|
2047
|
+
opened = await runTool(stream.tool, toolArgs);
|
|
2048
|
+
} catch (error) {
|
|
2049
|
+
opened = toolResultFromError(error);
|
|
2050
|
+
}
|
|
2051
|
+
const policy = cliResultPolicy(config, command);
|
|
2052
|
+
let outcome;
|
|
2053
|
+
if (!opened.ok)
|
|
2054
|
+
outcome = opened;
|
|
2055
|
+
else if (!isAsyncIterable(opened.data)) {
|
|
2056
|
+
outcome = toolResultFromError(new Error(`Stream command "${command}" handler did not return an async iterable`));
|
|
2057
|
+
} else {
|
|
2058
|
+
outcome = await printStreamItems(opened.data, stream, abort, () => cancelled, (item) => session.io.stdoutWhileOpen(streamLine(command, item, policy, options)));
|
|
2059
|
+
}
|
|
2060
|
+
config.signal?.removeEventListener("abort", cancel);
|
|
2061
|
+
if (outcome === "completed" || outcome === "reader-gone")
|
|
2062
|
+
return exit(0);
|
|
2063
|
+
if (outcome === "cancelled" || cancelled) {
|
|
2064
|
+
return exit(cliExitCode2({ ok: false, code: "REQUEST_ABORTED" }, config.exitCodes));
|
|
2065
|
+
}
|
|
2066
|
+
return exit(emitResult2(outcome, { stdout, stderr }, emitOptionsFor(config, options.json, command)));
|
|
2067
|
+
}
|
|
2068
|
+
function streamLine(command, item, policy, options) {
|
|
2069
|
+
if (policy?.present === undefined)
|
|
2070
|
+
return `${JSON.stringify(item)}
|
|
2071
|
+
`;
|
|
2072
|
+
let line;
|
|
2073
|
+
try {
|
|
2074
|
+
line = policy.present({ result: item, options });
|
|
2075
|
+
if (typeof line !== "string")
|
|
2076
|
+
throw new Error("CLI result presenter must return a string");
|
|
2077
|
+
} catch (error) {
|
|
2078
|
+
throw new AppError2("CLI_PRESENTATION_FAILED", {
|
|
2079
|
+
message: "A stream item was produced, but its presentation failed.",
|
|
2080
|
+
status: 500,
|
|
2081
|
+
details: { command, cause: formatToolError(toolResultFromError(error)) }
|
|
2082
|
+
});
|
|
2083
|
+
}
|
|
2084
|
+
return line;
|
|
2085
|
+
}
|
|
2086
|
+
async function printStreamItems(source, { descriptor }, abort, wasCancelled, write) {
|
|
2087
|
+
const iterator = source[Symbol.asyncIterator]();
|
|
2088
|
+
let lifetimeExpired = false;
|
|
2089
|
+
const lifetime = descriptor.lifetimeMs === undefined ? undefined : setTimeout(() => {
|
|
2090
|
+
lifetimeExpired = true;
|
|
2091
|
+
abort.abort(new Error("Stream lifetime expired"));
|
|
2092
|
+
}, descriptor.lifetimeMs);
|
|
2093
|
+
lifetime?.unref?.();
|
|
2094
|
+
try {
|
|
2095
|
+
for await (const { item } of readContractStreamItems(iterator, descriptor, abort.signal)) {
|
|
2096
|
+
if (!write(item))
|
|
2097
|
+
return "reader-gone";
|
|
2098
|
+
}
|
|
2099
|
+
return "completed";
|
|
2100
|
+
} catch (error) {
|
|
2101
|
+
if (wasCancelled())
|
|
2102
|
+
return "cancelled";
|
|
2103
|
+
if (lifetimeExpired) {
|
|
2104
|
+
return toolResultFromError(contractStreamLifetimeExceeded());
|
|
2105
|
+
}
|
|
2106
|
+
return toolResultFromError(error);
|
|
2107
|
+
} finally {
|
|
2108
|
+
if (lifetime !== undefined)
|
|
2109
|
+
clearTimeout(lifetime);
|
|
2110
|
+
abort.abort();
|
|
2111
|
+
Promise.resolve().then(() => iterator.return?.(undefined)).catch(() => {
|
|
2112
|
+
return;
|
|
2113
|
+
});
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2116
|
+
|
|
1887
2117
|
// src/tools/cli/unavailable.ts
|
|
1888
2118
|
function unavailableCommand(reason) {
|
|
1889
2119
|
return toolResultFromError(new AppError2("CLI_COMMAND_UNAVAILABLE", {
|
|
@@ -2148,9 +2378,9 @@ async function pollUntilDone2(params) {
|
|
|
2148
2378
|
async function runManagedInvocation(session, route) {
|
|
2149
2379
|
const { config } = session;
|
|
2150
2380
|
const { stdout, stderr, exit } = session.io;
|
|
2151
|
-
const { command, helpRequested, beforeSeparator } = route;
|
|
2381
|
+
const { command, helpRequested, schemaRequested, beforeSeparator } = route;
|
|
2152
2382
|
const topLevelHelp = route.route.topLevelHelp || command === undefined || command === "help" || command === "--help" || command === "-h" || command.startsWith("--help=") && !isReservedBoolWord(command.slice("--help=".length));
|
|
2153
|
-
const managed = await buildManagedSurface(session, route.typedGlobals, !topLevelHelp && !helpRequested);
|
|
2383
|
+
const managed = await buildManagedSurface(session, route.typedGlobals, !topLevelHelp && !helpRequested && !schemaRequested);
|
|
2154
2384
|
if (topLevelHelp)
|
|
2155
2385
|
return respondTopLevelHelp(session, route, managed);
|
|
2156
2386
|
if (!managed.resolved) {
|
|
@@ -2196,11 +2426,16 @@ async function runManagedCommand(session, route, command, managed) {
|
|
|
2196
2426
|
stdout(renderCommandHelp(config.name, command, descriptor, applicationOptions));
|
|
2197
2427
|
return exit(0);
|
|
2198
2428
|
}
|
|
2429
|
+
if (route.schemaRequested) {
|
|
2430
|
+
stdout(renderCommandSchema(command, descriptor));
|
|
2431
|
+
return exit(0);
|
|
2432
|
+
}
|
|
2199
2433
|
if (descriptor.unavailableReason !== undefined) {
|
|
2200
2434
|
return exit(emitResult2(unavailableCommand(descriptor.unavailableReason), { stdout, stderr }, emitOptionsFor(config, unavailableCommandJson(route.commandArgv), command)));
|
|
2201
2435
|
}
|
|
2436
|
+
const stream = managed.streams.get(command);
|
|
2202
2437
|
const tool = managed.tools.get(command);
|
|
2203
|
-
if (!tool)
|
|
2438
|
+
if (!tool && !stream)
|
|
2204
2439
|
throw new Error("[stitchkit] managed CLI executable invariant failed");
|
|
2205
2440
|
const prepared = await prepareInvocation(command, route.commandArgv, descriptor, config, readStdin);
|
|
2206
2441
|
if (!prepared.ok) {
|
|
@@ -2233,6 +2468,10 @@ async function runManagedCommand(session, route, command, managed) {
|
|
|
2233
2468
|
`);
|
|
2234
2469
|
return exit(0);
|
|
2235
2470
|
}
|
|
2471
|
+
if (stream)
|
|
2472
|
+
return runStreamCommand(session, route, managed, stream, { toolArgs, options });
|
|
2473
|
+
if (!tool)
|
|
2474
|
+
throw new Error("[stitchkit] managed CLI executable invariant failed");
|
|
2236
2475
|
const result = await executeManagedTool(session, route, command, managed, tool, {
|
|
2237
2476
|
toolArgs,
|
|
2238
2477
|
options
|
|
@@ -2269,8 +2508,11 @@ async function executeManagedTool(session, route, command, managed, tool, { tool
|
|
|
2269
2508
|
if (!pollTool) {
|
|
2270
2509
|
return {
|
|
2271
2510
|
ok: false,
|
|
2272
|
-
code: "
|
|
2273
|
-
details: {
|
|
2511
|
+
code: "UNKNOWN_OPERATION",
|
|
2512
|
+
details: {
|
|
2513
|
+
message: `--wait: no command "${toolName}" to poll`,
|
|
2514
|
+
operation: toolName
|
|
2515
|
+
}
|
|
2274
2516
|
};
|
|
2275
2517
|
}
|
|
2276
2518
|
return runTool(pollTool, args);
|
|
@@ -2314,7 +2556,8 @@ async function emitManagedResult(session, command, initial, options, repeatable)
|
|
|
2314
2556
|
}
|
|
2315
2557
|
result = { ...result, data: viewed.data };
|
|
2316
2558
|
}
|
|
2317
|
-
const
|
|
2559
|
+
const policy = options.view === undefined && !options.wait ? cliResultPolicy(config, command) : undefined;
|
|
2560
|
+
const exitCode = emitCliCommandResult(policy, result, options, { stdout, stderr }, { ...emitOptionsFor(config, options.json, command), repeatable });
|
|
2318
2561
|
return exit(downloadsOk ? exitCode : 1);
|
|
2319
2562
|
}
|
|
2320
2563
|
|
|
@@ -2330,6 +2573,10 @@ async function runNativeCommand2(session, route, command, native) {
|
|
|
2330
2573
|
stdout(renderCommandHelp(config.name, command, descriptor, applicationOptions));
|
|
2331
2574
|
return exit(0);
|
|
2332
2575
|
}
|
|
2576
|
+
if (route.schemaRequested) {
|
|
2577
|
+
stdout(renderCommandSchema(command, descriptor));
|
|
2578
|
+
return exit(0);
|
|
2579
|
+
}
|
|
2333
2580
|
const prepared = await prepareInvocation(command, commandArgv, descriptor, config, readStdin);
|
|
2334
2581
|
if (!prepared.ok) {
|
|
2335
2582
|
stderr(`${prepared.message}
|
|
@@ -2362,18 +2609,7 @@ async function runNativeCommand2(session, route, command, native) {
|
|
|
2362
2609
|
return exit(0);
|
|
2363
2610
|
}
|
|
2364
2611
|
const result = await executeCliCommand(native, toolArgs, options, { stdout, stderr }, config.coerceJsonArgs ?? true, globals);
|
|
2365
|
-
|
|
2366
|
-
if (emission.result.ok && emission.presentationFailure !== undefined) {
|
|
2367
|
-
return exit(emitPresentationFailure(emission.result, emission.presentationFailure, { stdout, stderr }, { ...emitOptionsFor(config, options.json, command), repeatable: false }));
|
|
2368
|
-
}
|
|
2369
|
-
let emittedExitCode;
|
|
2370
|
-
if (emission.result.ok && emission.presentation !== undefined) {
|
|
2371
|
-
stdout(emission.presentation);
|
|
2372
|
-
emittedExitCode = 0;
|
|
2373
|
-
} else {
|
|
2374
|
-
emittedExitCode = emitResult2(emission.result, { stdout, stderr }, emitOptionsFor(config, options.json, command));
|
|
2375
|
-
}
|
|
2376
|
-
return exit(emission.result.ok ? emission.successExitCode : emittedExitCode);
|
|
2612
|
+
return exit(emitCliCommandResult(cliCommandResultPolicy(native), result, options, { stdout, stderr }, { ...emitOptionsFor(config, options.json, command), repeatable: false }));
|
|
2377
2613
|
}
|
|
2378
2614
|
|
|
2379
2615
|
// src/tools/cli/create-cli.ts
|
|
@@ -2395,4 +2631,4 @@ async function createCli2(config) {
|
|
|
2395
2631
|
return runManagedInvocation(session, route);
|
|
2396
2632
|
}
|
|
2397
2633
|
|
|
2398
|
-
export {
|
|
2634
|
+
export { DEFAULT_EXIT_CODES2, cliExitCode2, emitResult2, defineCliResult2, defineCliCommand2, CliArgumentError2, cliInvocationResult2, createCliInvoker2, routeCliArgv2, parseCliArgs2, extractCliGlobalOptions2, renderCliView2, pollUntilDone2, createCli2 };
|