stitchkit 0.94.0 → 0.94.1
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 +64 -0
- package/dist/agent-runtime/coding-shell-process.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-listing.d.ts.map +1 -1
- package/dist/agent-runtime/coding-tool-search-patch.d.ts.map +1 -1
- package/dist/agent-runtime/contained-darwin.d.ts +38 -0
- package/dist/agent-runtime/contained-darwin.d.ts.map +1 -0
- package/dist/agent-runtime/contained-files.d.ts +11 -26
- package/dist/agent-runtime/contained-files.d.ts.map +1 -1
- package/dist/agent-runtime/contained-scan.d.ts +21 -0
- package/dist/agent-runtime/contained-scan.d.ts.map +1 -0
- package/dist/agent-runtime/contained-write.d.ts +9 -0
- package/dist/agent-runtime/contained-write.d.ts.map +1 -0
- package/dist/agent-runtime/deferred-tool-types.d.ts +3 -2
- package/dist/agent-runtime/deferred-tool-types.d.ts.map +1 -1
- package/dist/agent-runtime/harness-control.d.ts +0 -1
- package/dist/agent-runtime/harness-control.d.ts.map +1 -1
- package/dist/agent-runtime/harness.d.ts +0 -5
- package/dist/agent-runtime/harness.d.ts.map +1 -1
- package/dist/agent-runtime/managed-tools.d.ts +3 -2
- package/dist/agent-runtime/managed-tools.d.ts.map +1 -1
- package/dist/agent-runtime/runtime.d.ts +1 -1
- package/dist/agent-runtime/runtime.d.ts.map +1 -1
- package/dist/agent-runtime/schedule-records.d.ts +34 -0
- package/dist/agent-runtime/schedule-records.d.ts.map +1 -0
- package/dist/agent-runtime/schedules.d.ts +34 -0
- package/dist/agent-runtime/schedules.d.ts.map +1 -1
- package/dist/agent-runtime/store-conformance-lifecycle.d.ts +434 -0
- package/dist/agent-runtime/store-conformance-lifecycle.d.ts.map +1 -0
- package/dist/agent-runtime/store-conformance-ordering.d.ts +18 -0
- package/dist/agent-runtime/store-conformance-ordering.d.ts.map +1 -0
- package/dist/agent-runtime/store-conformance-support.d.ts +130 -0
- package/dist/agent-runtime/store-conformance-support.d.ts.map +1 -0
- package/dist/agent-runtime/store-conformance-terminal.d.ts +12 -0
- package/dist/agent-runtime/store-conformance-terminal.d.ts.map +1 -0
- package/dist/agent-runtime/store-conformance.d.ts.map +1 -1
- package/dist/application/admission-rate.d.ts +21 -0
- package/dist/application/admission-rate.d.ts.map +1 -0
- package/dist/application/admission-run.d.ts +8 -0
- package/dist/application/admission-run.d.ts.map +1 -0
- package/dist/application/admission.d.ts.map +1 -1
- package/dist/application/diagnostic-journal-lock.d.ts +9 -34
- package/dist/application/diagnostic-journal-lock.d.ts.map +1 -1
- package/dist/application/diagnostic-journal-manager.d.ts.map +1 -1
- package/dist/application/diagnostic-journal-storage.d.ts.map +1 -1
- package/dist/application/kernel-resource-context.d.ts.map +1 -1
- package/dist/application/notification-outbox.d.ts.map +1 -1
- package/dist/application/schedule.d.ts +0 -1
- package/dist/application/schedule.d.ts.map +1 -1
- package/dist/application/watch-hub-core.d.ts +122 -0
- package/dist/application/watch-hub-core.d.ts.map +1 -0
- package/dist/application/watch-hub.d.ts +2 -2
- package/dist/application/watch-hub.d.ts.map +1 -1
- package/dist/browser/client-executors.d.ts +14 -0
- package/dist/browser/client-executors.d.ts.map +1 -0
- package/dist/browser/client-multipart.d.ts +1 -1
- package/dist/browser/client-multipart.d.ts.map +1 -1
- package/dist/browser/client.d.ts +3 -2
- package/dist/browser/client.d.ts.map +1 -1
- package/dist/browser/http-fetch.d.ts +22 -0
- package/dist/browser/http-fetch.d.ts.map +1 -0
- package/dist/browser/http.d.ts +1 -3
- package/dist/browser/http.d.ts.map +1 -1
- package/dist/browser/live-state-core.d.ts +63 -0
- package/dist/browser/live-state-core.d.ts.map +1 -0
- package/dist/browser/live-state.d.ts.map +1 -1
- package/dist/browser/realtime-client.d.ts +26 -0
- package/dist/browser/realtime-client.d.ts.map +1 -0
- package/dist/browser/socket-io-connection.d.ts +82 -0
- package/dist/browser/socket-io-connection.d.ts.map +1 -0
- package/dist/browser/socket-io-peer.d.ts +20 -0
- package/dist/browser/socket-io-peer.d.ts.map +1 -0
- package/dist/browser/socket-io-trace.d.ts +31 -0
- package/dist/browser/socket-io-trace.d.ts.map +1 -0
- package/dist/browser/socket-io.d.ts +2 -18
- package/dist/browser/socket-io.d.ts.map +1 -1
- package/dist/contract/client-types.d.ts +134 -0
- package/dist/contract/client-types.d.ts.map +1 -0
- package/dist/contract/define-validation.d.ts +30 -0
- package/dist/contract/define-validation.d.ts.map +1 -0
- package/dist/contract/define.d.ts +3 -357
- package/dist/contract/define.d.ts.map +1 -1
- package/dist/contract/runtime-context.d.ts +131 -0
- package/dist/contract/runtime-context.d.ts.map +1 -0
- package/dist/contract/tool-options.d.ts +105 -0
- package/dist/contract/tool-options.d.ts.map +1 -0
- package/dist/contract/tool-view.d.ts +15 -2
- package/dist/contract/tool-view.d.ts.map +1 -1
- package/dist/durability/contract.d.ts +83 -0
- package/dist/durability/contract.d.ts.map +1 -1
- package/dist/durability/effect.d.ts +24 -0
- package/dist/durability/effect.d.ts.map +1 -0
- package/dist/durability/engine.d.ts +2 -2
- package/dist/durability/engine.d.ts.map +1 -1
- package/dist/durability/events.d.ts +2 -0
- package/dist/durability/events.d.ts.map +1 -1
- package/dist/durability/ledger.d.ts +11 -0
- package/dist/durability/ledger.d.ts.map +1 -1
- package/dist/durability/parks.d.ts +22 -0
- package/dist/durability/parks.d.ts.map +1 -0
- package/dist/durability/scheduler.d.ts +1 -0
- package/dist/durability/scheduler.d.ts.map +1 -1
- package/dist/entrypoints/agent-runtime/coding-tools.js +4 -4
- package/dist/entrypoints/agent-runtime/harness.js +127 -116
- package/dist/entrypoints/agent-runtime/sandbox.js +4 -4
- package/dist/entrypoints/agent-runtime/sqlite/bun.js +3 -3
- package/dist/entrypoints/agent-runtime/sqlite/node.js +3 -3
- package/dist/entrypoints/agent-runtime/testing.js +246 -214
- package/dist/entrypoints/agent-runtime.js +224 -203
- package/dist/entrypoints/application/diagnostic-journal.js +63 -203
- package/dist/entrypoints/application/opentelemetry.js +1 -1
- package/dist/entrypoints/application.js +361 -324
- package/dist/entrypoints/cli.d.ts +4 -1
- package/dist/entrypoints/cli.d.ts.map +1 -1
- package/dist/entrypoints/cli.js +57 -35
- package/dist/entrypoints/contract.d.ts +5 -2
- package/dist/entrypoints/contract.d.ts.map +1 -1
- package/dist/entrypoints/contract.js +3 -2
- package/dist/entrypoints/files.d.ts +2 -0
- package/dist/entrypoints/files.d.ts.map +1 -1
- package/dist/entrypoints/files.js +98 -2
- package/dist/entrypoints/index.d.ts +4 -2
- package/dist/entrypoints/index.d.ts.map +1 -1
- package/dist/entrypoints/index.js +348 -282
- package/dist/entrypoints/live.js +89 -71
- package/dist/entrypoints/node.d.ts +2 -1
- package/dist/entrypoints/node.d.ts.map +1 -1
- package/dist/entrypoints/node.js +13 -12
- package/dist/entrypoints/react.js +1 -1
- package/dist/entrypoints/remote.js +4 -4
- package/dist/entrypoints/server.d.ts +4 -2
- package/dist/entrypoints/server.d.ts.map +1 -1
- package/dist/entrypoints/server.js +293 -79
- package/dist/entrypoints/testing.d.ts +2 -1
- package/dist/entrypoints/testing.d.ts.map +1 -1
- package/dist/entrypoints/testing.js +288 -281
- package/dist/entrypoints/tools/connections.js +2 -2
- package/dist/entrypoints/tools/invoker.js +4 -4
- package/dist/entrypoints/tools.d.ts +6 -3
- package/dist/entrypoints/tools.d.ts.map +1 -1
- package/dist/entrypoints/tools.js +245 -202
- package/dist/entrypoints/tracking.js +325 -274
- package/dist/files/boundary.d.ts.map +1 -1
- package/dist/files/file-io.d.ts +14 -0
- package/dist/files/file-io.d.ts.map +1 -0
- package/dist/index-1j8pm5t0.js +412 -0
- package/dist/{index-kvj7f4hq.js → index-2bxbyab0.js} +10 -2
- package/dist/{index-xnj9bgxe.js → index-2gxzjvyr.js} +2 -162
- package/dist/index-4gcnakhx.js +82 -0
- package/dist/{index-j05z5gn4.js → index-55hkhm67.js} +136 -119
- package/dist/{index-cq4qfycf.js → index-79z7m7dt.js} +227 -59
- package/dist/{index-97ac4gph.js → index-7f68ghdn.js} +3 -3
- package/dist/{index-r7nmqpsg.js → index-7p1f0vp2.js} +1 -1
- package/dist/{index-dcpdvjsc.js → index-863ea9jb.js} +4 -4
- package/dist/index-8p52kd5p.js +242 -0
- package/dist/{index-2qzskm8h.js → index-dce5wxcq.js} +1 -1
- package/dist/index-e01r054k.js +105 -0
- package/dist/{index-sees8yf8.js → index-ensd0r74.js} +118 -111
- package/dist/{index-1nd48tm9.js → index-gxrt5h6v.js} +2 -1
- package/dist/{index-e87kakm4.js → index-ham5sz8m.js} +112 -110
- package/dist/{index-kj2wbeta.js → index-het2he5g.js} +280 -196
- package/dist/{index-vcvkq30w.js → index-hmp4800j.js} +3 -3
- package/dist/{index-gyr48nzg.js → index-k30h66yd.js} +71 -151
- package/dist/{index-2cr1cqhn.js → index-khtgb21r.js} +2 -2
- package/dist/{index-x4799c19.js → index-ndddxtyx.js} +11 -11
- package/dist/{index-dydjcp8z.js → index-np4m8hd3.js} +38 -36
- package/dist/{index-p81267c2.js → index-p3vsv1fb.js} +621 -357
- package/dist/{index-mp5sn43f.js → index-p9e0w8hs.js} +2 -2
- package/dist/{index-rewkc2hj.js → index-p9sh0xx4.js} +3 -3
- package/dist/{index-70yj2ebz.js → index-paz6sgdp.js} +107 -103
- package/dist/{index-bn2cjajt.js → index-px2gm2jp.js} +26 -102
- package/dist/index-s812ycat.js +65 -0
- package/dist/{index-xsqjkha9.js → index-sp1tzwnb.js} +2 -2
- package/dist/{index-n6hxg8as.js → index-t9rhjr9f.js} +615 -566
- package/dist/{index-zeemqhqx.js → index-v260df89.js} +88 -80
- package/dist/{index-fdp6hdxn.js → index-w906953s.js} +5 -1
- package/dist/{index-mdzh02yc.js → index-wdkt63w3.js} +1 -1
- package/dist/{index-58k4fp34.js → index-wsm5w4ee.js} +1 -1
- package/dist/{index-v38qyerb.js → index-xw3s75nj.js} +1 -1
- package/dist/internal/atomic-file.d.ts +23 -2
- package/dist/internal/atomic-file.d.ts.map +1 -1
- package/dist/internal/exclusive-lock.d.ts +51 -0
- package/dist/internal/exclusive-lock.d.ts.map +1 -0
- package/dist/internal/process-identity.d.ts +47 -0
- package/dist/internal/process-identity.d.ts.map +1 -0
- package/dist/internal/with-exclusive-lock.d.ts +67 -0
- package/dist/internal/with-exclusive-lock.d.ts.map +1 -0
- package/dist/live/watch-client.d.ts.map +1 -1
- package/dist/observability/audit.d.ts +2 -2
- package/dist/observability/audit.d.ts.map +1 -1
- package/dist/observability/event.d.ts +2 -1
- package/dist/observability/event.d.ts.map +1 -1
- package/dist/primitives/export-operation.d.ts +1 -1
- package/dist/primitives/export-operation.d.ts.map +1 -1
- package/dist/realtime/registry.d.ts +0 -5
- package/dist/realtime/registry.d.ts.map +1 -1
- package/dist/server/bun.d.ts +0 -1
- package/dist/server/bun.d.ts.map +1 -1
- package/dist/server/context-contribution.d.ts +1 -1
- package/dist/server/context-contribution.d.ts.map +1 -1
- package/dist/server/context.d.ts +1 -1
- package/dist/server/context.d.ts.map +1 -1
- package/dist/server/endpoint-response.d.ts +2 -1
- package/dist/server/endpoint-response.d.ts.map +1 -1
- package/dist/server/error-dispatch.d.ts +1 -1
- package/dist/server/error-dispatch.d.ts.map +1 -1
- package/dist/server/error-hook.d.ts +1 -1
- package/dist/server/error-hook.d.ts.map +1 -1
- package/dist/server/handler-state.d.ts +1 -1
- package/dist/server/handler-state.d.ts.map +1 -1
- package/dist/server/implement-registry.d.ts +54 -0
- package/dist/server/implement-registry.d.ts.map +1 -0
- package/dist/server/implement.d.ts +9 -55
- package/dist/server/implement.d.ts.map +1 -1
- package/dist/server/middleware/auth.d.ts +1 -31
- package/dist/server/middleware/auth.d.ts.map +1 -1
- package/dist/server/middleware/jwt.d.ts +31 -0
- package/dist/server/middleware/jwt.d.ts.map +1 -0
- package/dist/server/multipart-reader.d.ts +22 -0
- package/dist/server/multipart-reader.d.ts.map +1 -0
- package/dist/server/multipart.d.ts +1 -1
- package/dist/server/multipart.d.ts.map +1 -1
- package/dist/server/oauth/cimd.d.ts +88 -0
- package/dist/server/oauth/cimd.d.ts.map +1 -0
- package/dist/server/oauth/endpoints.d.ts +39 -0
- package/dist/server/oauth/endpoints.d.ts.map +1 -0
- package/dist/server/oauth/provider.d.ts +1 -68
- package/dist/server/oauth/provider.d.ts.map +1 -1
- package/dist/server/streaming-pump.d.ts +66 -0
- package/dist/server/streaming-pump.d.ts.map +1 -0
- package/dist/server/streaming-route.d.ts +12 -5
- package/dist/server/streaming-route.d.ts.map +1 -1
- package/dist/server/types.d.ts +4 -1
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/unix-client-bun.d.ts.map +1 -1
- package/dist/server/unix-client-http1.d.ts +76 -0
- package/dist/server/unix-client-http1.d.ts.map +1 -0
- package/dist/server/unix-client.d.ts.map +1 -1
- package/dist/testing/handler-clients.d.ts +2 -1
- package/dist/testing/handler-clients.d.ts.map +1 -1
- package/dist/testing/realtime-probe.d.ts +33 -0
- package/dist/testing/realtime-probe.d.ts.map +1 -0
- package/dist/testing/surface-conformance.d.ts +0 -31
- package/dist/testing/surface-conformance.d.ts.map +1 -1
- package/dist/testing/surface-manifest-digest.d.ts +44 -0
- package/dist/testing/surface-manifest-digest.d.ts.map +1 -0
- package/dist/testing/surface-manifest.d.ts.map +1 -1
- package/dist/tools/agent.d.ts +1 -1
- package/dist/tools/agent.d.ts.map +1 -1
- package/dist/tools/cli/args-fields.d.ts +31 -0
- package/dist/tools/cli/args-fields.d.ts.map +1 -0
- package/dist/tools/cli/args-route.d.ts +42 -0
- package/dist/tools/cli/args-route.d.ts.map +1 -0
- package/dist/tools/cli/args-view.d.ts +32 -0
- package/dist/tools/cli/args-view.d.ts.map +1 -0
- package/dist/tools/cli/args.d.ts +2 -65
- package/dist/tools/cli/args.d.ts.map +1 -1
- package/dist/tools/cli/argument-error.d.ts +5 -0
- package/dist/tools/cli/argument-error.d.ts.map +1 -0
- package/dist/tools/cli/checkpoint.d.ts.map +1 -1
- package/dist/tools/cli/command.d.ts +1 -1
- package/dist/tools/cli/command.d.ts.map +1 -1
- package/dist/tools/cli/config.d.ts +1 -1
- package/dist/tools/cli/config.d.ts.map +1 -1
- package/dist/tools/cli/format.d.ts +2 -1
- package/dist/tools/cli/format.d.ts.map +1 -1
- package/dist/tools/cli/invoke.d.ts +2 -1
- package/dist/tools/cli/invoke.d.ts.map +1 -1
- package/dist/tools/cli/managed-surface.d.ts +1 -1
- package/dist/tools/cli/managed-surface.d.ts.map +1 -1
- package/dist/tools/cli/policy.d.ts +1 -1
- package/dist/tools/cli/policy.d.ts.map +1 -1
- package/dist/tools/cli/prepare.d.ts.map +1 -1
- package/dist/tools/cli/run-managed.d.ts.map +1 -1
- package/dist/tools/cli/session.d.ts +1 -1
- package/dist/tools/cli/session.d.ts.map +1 -1
- package/dist/tools/cli/update.d.ts +19 -0
- package/dist/tools/cli/update.d.ts.map +1 -1
- package/dist/tools/cli/view.d.ts +1 -1
- package/dist/tools/cli/view.d.ts.map +1 -1
- package/dist/tools/cli/wait.d.ts +1 -1
- package/dist/tools/cli/wait.d.ts.map +1 -1
- package/dist/tools/connections/runtime.d.ts +1 -1
- package/dist/tools/connections/runtime.d.ts.map +1 -1
- package/dist/tools/execute-args.d.ts +23 -0
- package/dist/tools/execute-args.d.ts.map +1 -0
- package/dist/tools/execute-hooks.d.ts +146 -0
- package/dist/tools/execute-hooks.d.ts.map +1 -0
- package/dist/tools/execute-result.d.ts +40 -0
- package/dist/tools/execute-result.d.ts.map +1 -0
- package/dist/tools/execute.d.ts +4 -193
- package/dist/tools/execute.d.ts.map +1 -1
- package/dist/tools/internal/surface-projector.d.ts +2 -1
- package/dist/tools/internal/surface-projector.d.ts.map +1 -1
- package/dist/tools/invoker.d.ts +2 -1
- package/dist/tools/invoker.d.ts.map +1 -1
- package/dist/tools/lifecycle.d.ts +1 -1
- package/dist/tools/lifecycle.d.ts.map +1 -1
- package/dist/tools/mcp/mount.d.ts +1 -1
- package/dist/tools/mcp/mount.d.ts.map +1 -1
- package/dist/tools/mcp/prepare.d.ts +2 -1
- package/dist/tools/mcp/prepare.d.ts.map +1 -1
- package/dist/tools/mcp/progress.d.ts +1 -1
- package/dist/tools/mcp/progress.d.ts.map +1 -1
- package/dist/tools/mcp/register.d.ts +3 -2
- package/dist/tools/mcp/register.d.ts.map +1 -1
- package/dist/tools/mcp/round-context.d.ts +38 -0
- package/dist/tools/mcp/round-context.d.ts.map +1 -0
- package/dist/tools/mcp/round-policy.d.ts +1 -1
- package/dist/tools/mcp/round-policy.d.ts.map +1 -1
- package/dist/tools/mcp/round.d.ts +3 -11
- package/dist/tools/mcp/round.d.ts.map +1 -1
- package/dist/tools/mcp/runtime-tools.d.ts +2 -1
- package/dist/tools/mcp/runtime-tools.d.ts.map +1 -1
- package/dist/tools/mount.d.ts +3 -1
- package/dist/tools/mount.d.ts.map +1 -1
- package/dist/tools/native-definition.d.ts +2 -1
- package/dist/tools/native-definition.d.ts.map +1 -1
- package/dist/tools/operations/async-operation-runtime-tools.d.ts +2 -1
- package/dist/tools/operations/async-operation-runtime-tools.d.ts.map +1 -1
- package/dist/tools/operations/async-operation-runtime-types.d.ts +2 -1
- package/dist/tools/operations/async-operation-runtime-types.d.ts.map +1 -1
- package/dist/tools/remote.d.ts.map +1 -1
- package/dist/tools/runtime-tool.d.ts +3 -1
- package/dist/tools/runtime-tool.d.ts.map +1 -1
- package/dist/tools/tool-logger.d.ts +1 -1
- package/dist/tools/tool-logger.d.ts.map +1 -1
- package/dist/tracking/client-listeners.d.ts +30 -0
- package/dist/tracking/client-listeners.d.ts.map +1 -0
- package/dist/tracking/client-visit.d.ts +61 -0
- package/dist/tracking/client-visit.d.ts.map +1 -0
- package/dist/tracking/client.d.ts +3 -2
- package/dist/tracking/client.d.ts.map +1 -1
- package/llms/application.2.txt +266 -2
- package/llms/application.txt +8 -266
- package/llms/cli.2.txt +80 -0
- package/llms/cli.txt +45 -74
- package/llms/contract.txt +3 -3
- package/llms/files.txt +3 -0
- package/llms/tools.2.txt +88 -279
- package/llms/tools.3.txt +288 -0
- package/llms/tools.txt +27 -65
- package/llms-full.txt +108 -12
- package/llms.txt +5 -5
- package/package.json +1 -1
- package/dist/index-e2z3ahw9.js +0 -325
- package/dist/index-mkm15s49.js +0 -394
|
@@ -3,15 +3,15 @@ import {
|
|
|
3
3
|
} from "./index-sbdmyz75.js";
|
|
4
4
|
import {
|
|
5
5
|
collectToolSurface
|
|
6
|
-
} from "./index-
|
|
6
|
+
} from "./index-hmp4800j.js";
|
|
7
7
|
import {
|
|
8
8
|
createToolRunner,
|
|
9
9
|
formatToolError
|
|
10
|
-
} from "./index-
|
|
10
|
+
} from "./index-khtgb21r.js";
|
|
11
11
|
import {
|
|
12
12
|
toolErrorFromResult,
|
|
13
13
|
toolResultFromError
|
|
14
|
-
} from "./index-
|
|
14
|
+
} from "./index-55hkhm67.js";
|
|
15
15
|
import {
|
|
16
16
|
coerceJsonArgs
|
|
17
17
|
} from "./index-1zbbzgfh.js";
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
assertUniqueToolName,
|
|
20
20
|
buildToolPresentationSchema,
|
|
21
21
|
objectShapeKeys
|
|
22
|
-
} from "./index-
|
|
22
|
+
} from "./index-np4m8hd3.js";
|
|
23
23
|
import {
|
|
24
24
|
jsonSchemaFields
|
|
25
25
|
} from "./index-eqqvgdb3.js";
|
|
@@ -145,149 +145,13 @@ function emitResult(result, writers, opts) {
|
|
|
145
145
|
return cliExitCode(result, opts.exitCodes);
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
// src/tools/cli/
|
|
149
|
-
import { z } from "zod";
|
|
150
|
-
var NUMERIC_VALUE = /^-(\d+\.?\d*|\.\d+)$/;
|
|
151
|
-
var BOOL_OPTIONS = new Set(["json", "wait", "quiet", "dry-run", "help", "ascending"]);
|
|
152
|
-
var VIEW_OPTIONS = new Set(["count-by", "sum", "by", "top", "table", "sort"]);
|
|
153
|
-
var VALUE_OPTIONS = new Set(["wait-timeout", "output-dir", ...VIEW_OPTIONS]);
|
|
154
|
-
var RESERVED_CLI_OPTIONS = new Set([...BOOL_OPTIONS, ...VALUE_OPTIONS]);
|
|
155
|
-
function classifyLongOptionToken(token) {
|
|
156
|
-
if (!token.startsWith("--") || token === "--")
|
|
157
|
-
return;
|
|
158
|
-
const equals = token.indexOf("=");
|
|
159
|
-
const name = equals >= 0 ? token.slice(2, equals) : token.slice(2);
|
|
160
|
-
return {
|
|
161
|
-
name,
|
|
162
|
-
value: equals >= 0 ? token.slice(equals + 1) : undefined,
|
|
163
|
-
inline: equals >= 0,
|
|
164
|
-
globalKind: BOOL_OPTIONS.has(name) ? "boolean" : VALUE_OPTIONS.has(name) ? "value" : undefined
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
var HELP_TOKENS = new Set(["--help", "-h", "help"]);
|
|
168
|
-
function helpFilterFrom(token, rest) {
|
|
169
|
-
if (token?.startsWith("--help=")) {
|
|
170
|
-
const value = token.slice("--help=".length).trim();
|
|
171
|
-
if (value.length === 0 || isReservedBoolWord(value))
|
|
172
|
-
return;
|
|
173
|
-
return value;
|
|
174
|
-
}
|
|
175
|
-
if (token === undefined || !HELP_TOKENS.has(token))
|
|
176
|
-
return;
|
|
177
|
-
const next = rest[0];
|
|
178
|
-
return next !== undefined && !next.startsWith("-") ? next : undefined;
|
|
179
|
-
}
|
|
180
|
-
function routeCliArgv(argv, defaultCommand) {
|
|
181
|
-
if (defaultCommand === undefined) {
|
|
182
|
-
const [command, ...commandArgv] = argv;
|
|
183
|
-
const helpFilter = helpFilterFrom(command, commandArgv);
|
|
184
|
-
return {
|
|
185
|
-
command,
|
|
186
|
-
commandArgv,
|
|
187
|
-
topLevelHelp: false,
|
|
188
|
-
version: false,
|
|
189
|
-
...helpFilter !== undefined && { helpFilter }
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
const globals = [];
|
|
193
|
-
let index = 0;
|
|
194
|
-
while (index < argv.length) {
|
|
195
|
-
const token = argv[index];
|
|
196
|
-
if (token === undefined)
|
|
197
|
-
break;
|
|
198
|
-
if (token === "--") {
|
|
199
|
-
return {
|
|
200
|
-
commandArgv: [],
|
|
201
|
-
topLevelHelp: false,
|
|
202
|
-
version: false,
|
|
203
|
-
error: 'A command is required before "--"'
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
const inlineHelpFilter = token.startsWith("--help=") && !isReservedBoolWord(token.slice("--help=".length));
|
|
207
|
-
if (token === "--help" || token === "-h" || inlineHelpFilter) {
|
|
208
|
-
const helpFilter = helpFilterFrom(token, argv.slice(index + 1));
|
|
209
|
-
return {
|
|
210
|
-
commandArgv: [],
|
|
211
|
-
topLevelHelp: true,
|
|
212
|
-
version: false,
|
|
213
|
-
...helpFilter !== undefined && { helpFilter }
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
if (token === "--version" || token === "version") {
|
|
217
|
-
return { commandArgv: [], topLevelHelp: false, version: true };
|
|
218
|
-
}
|
|
219
|
-
if (!token.startsWith("-") || token === "-") {
|
|
220
|
-
return {
|
|
221
|
-
command: token,
|
|
222
|
-
commandArgv: [...globals, ...argv.slice(index + 1)],
|
|
223
|
-
topLevelHelp: false,
|
|
224
|
-
version: false
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
if (!token.startsWith("--")) {
|
|
228
|
-
return {
|
|
229
|
-
command: defaultCommand,
|
|
230
|
-
commandArgv: [...globals, ...argv.slice(index)],
|
|
231
|
-
topLevelHelp: false,
|
|
232
|
-
version: false
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
|
-
const option = classifyLongOptionToken(token);
|
|
236
|
-
if (!option) {
|
|
237
|
-
return {
|
|
238
|
-
command: defaultCommand,
|
|
239
|
-
commandArgv: [...globals, ...argv.slice(index)],
|
|
240
|
-
topLevelHelp: false,
|
|
241
|
-
version: false
|
|
242
|
-
};
|
|
243
|
-
}
|
|
244
|
-
if (option.globalKind === "boolean") {
|
|
245
|
-
globals.push(token);
|
|
246
|
-
index += 1;
|
|
247
|
-
continue;
|
|
248
|
-
}
|
|
249
|
-
if (option.globalKind === "value") {
|
|
250
|
-
globals.push(token);
|
|
251
|
-
if (!option.inline) {
|
|
252
|
-
const value = argv[index + 1];
|
|
253
|
-
if (value === "--help" || value === "-h") {
|
|
254
|
-
const helpFilter = helpFilterFrom(value, argv.slice(index + 2));
|
|
255
|
-
return {
|
|
256
|
-
commandArgv: [],
|
|
257
|
-
topLevelHelp: true,
|
|
258
|
-
version: false,
|
|
259
|
-
...helpFilter !== undefined && { helpFilter }
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
if (value === "--version" || value === "version") {
|
|
263
|
-
return { commandArgv: [], topLevelHelp: false, version: true };
|
|
264
|
-
}
|
|
265
|
-
if (value !== undefined)
|
|
266
|
-
globals.push(value);
|
|
267
|
-
index += value === undefined ? 1 : 2;
|
|
268
|
-
} else {
|
|
269
|
-
index += 1;
|
|
270
|
-
}
|
|
271
|
-
continue;
|
|
272
|
-
}
|
|
273
|
-
return {
|
|
274
|
-
command: defaultCommand,
|
|
275
|
-
commandArgv: [...globals, ...argv.slice(index)],
|
|
276
|
-
topLevelHelp: false,
|
|
277
|
-
version: false
|
|
278
|
-
};
|
|
279
|
-
}
|
|
280
|
-
return {
|
|
281
|
-
command: defaultCommand,
|
|
282
|
-
commandArgv: globals,
|
|
283
|
-
topLevelHelp: false,
|
|
284
|
-
version: false
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
|
|
148
|
+
// src/tools/cli/argument-error.ts
|
|
288
149
|
class CliArgumentError extends Error {
|
|
289
150
|
name = "CliArgumentError";
|
|
290
151
|
}
|
|
152
|
+
|
|
153
|
+
// src/tools/cli/args-fields.ts
|
|
154
|
+
import { z } from "zod";
|
|
291
155
|
function unwrap(field) {
|
|
292
156
|
if (field instanceof z.ZodOptional || field instanceof z.ZodNullable || field instanceof z.ZodDefault) {
|
|
293
157
|
return unwrap(field.unwrap());
|
|
@@ -334,9 +198,15 @@ function collectSchemaFields(schema, fields) {
|
|
|
334
198
|
const fieldBase = unwrap(raw);
|
|
335
199
|
const kind = classify(fieldBase);
|
|
336
200
|
if (kind === "array" && fieldBase instanceof z.ZodArray) {
|
|
337
|
-
mergeField(fields, name, {
|
|
201
|
+
mergeField(fields, name, {
|
|
202
|
+
kind,
|
|
203
|
+
elementKind: classify(unwrap(fieldBase.element))
|
|
204
|
+
});
|
|
338
205
|
} else {
|
|
339
|
-
mergeField(fields, name, {
|
|
206
|
+
mergeField(fields, name, {
|
|
207
|
+
kind,
|
|
208
|
+
...fieldBase instanceof z.ZodNumber && fieldBase.isInt && { integer: true }
|
|
209
|
+
});
|
|
340
210
|
}
|
|
341
211
|
}
|
|
342
212
|
return;
|
|
@@ -412,18 +282,38 @@ function looksLikeJson(value) {
|
|
|
412
282
|
const t = value.trim();
|
|
413
283
|
return t.startsWith("[") || t.startsWith("{");
|
|
414
284
|
}
|
|
415
|
-
function
|
|
285
|
+
function expectedValue(kind, integer) {
|
|
286
|
+
if (kind === "number")
|
|
287
|
+
return integer ? "a whole number" : "a number";
|
|
288
|
+
if (kind === "bigint")
|
|
289
|
+
return "a whole number";
|
|
290
|
+
if (kind === "date")
|
|
291
|
+
return "a date";
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
function coerceNamed(label, kind, integer, value) {
|
|
295
|
+
const coerced = coerceScalar(kind, value);
|
|
296
|
+
const expected = expectedValue(kind, integer);
|
|
297
|
+
if (expected !== undefined && typeof coerced === "string") {
|
|
298
|
+
throw new CliArgumentError(`${label} expects ${expected}, got "${value}"`);
|
|
299
|
+
}
|
|
300
|
+
if (integer && typeof coerced === "number" && !Number.isInteger(coerced)) {
|
|
301
|
+
throw new CliArgumentError(`${label} expects ${expected}, got "${value}"`);
|
|
302
|
+
}
|
|
303
|
+
return coerced;
|
|
304
|
+
}
|
|
305
|
+
function coerceField(info, values, label) {
|
|
416
306
|
const last = values[values.length - 1] ?? "";
|
|
417
307
|
if (!info)
|
|
418
308
|
return values.length > 1 ? values : last;
|
|
419
309
|
if (info.kind === "array") {
|
|
420
310
|
if (values.length === 1 && looksLikeJson(last))
|
|
421
311
|
return last;
|
|
422
|
-
return values.map((v) =>
|
|
312
|
+
return values.map((v) => coerceNamed(label, info.elementKind ?? "string", false, v));
|
|
423
313
|
}
|
|
424
314
|
if (info.kind === "object")
|
|
425
315
|
return last;
|
|
426
|
-
return
|
|
316
|
+
return coerceNamed(label, info.kind, info.integer, last);
|
|
427
317
|
}
|
|
428
318
|
function setNested(target, path, value) {
|
|
429
319
|
const unsafe = path.find(isUnsafeKey);
|
|
@@ -448,253 +338,365 @@ function setNested(target, path, value) {
|
|
|
448
338
|
if (leaf !== undefined)
|
|
449
339
|
node[leaf] = value;
|
|
450
340
|
}
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
341
|
+
|
|
342
|
+
// src/tools/cli/policy.ts
|
|
343
|
+
var SHORT_ALIAS = /^[A-Za-z]$/;
|
|
344
|
+
var RESERVED_SHORT_OPTIONS = new Set(["h"]);
|
|
345
|
+
function fieldMap(descriptor) {
|
|
346
|
+
return new Map(jsonSchemaFields(descriptor.presentationSchema).map((field) => [field.name, field]));
|
|
347
|
+
}
|
|
348
|
+
function resolveAliases(command, descriptor, configured) {
|
|
349
|
+
if (!configured)
|
|
350
|
+
return new Map;
|
|
351
|
+
const fields = fieldMap(descriptor);
|
|
352
|
+
const aliases = new Map;
|
|
353
|
+
for (const [alias, target] of Object.entries(configured)) {
|
|
354
|
+
if (!SHORT_ALIAS.test(alias)) {
|
|
355
|
+
throw new Error(`[stitchkit] CLI command "${command}" alias "${alias}" must be one ASCII letter`);
|
|
356
|
+
}
|
|
357
|
+
if (RESERVED_SHORT_OPTIONS.has(alias)) {
|
|
358
|
+
throw new Error(`[stitchkit] CLI command "${command}" alias "-${alias}" is reserved`);
|
|
359
|
+
}
|
|
360
|
+
if (isUnsafeKey(target) || !fields.has(target)) {
|
|
361
|
+
throw new Error(`[stitchkit] CLI command "${command}" alias "-${alias}" targets unknown field "${target}"`);
|
|
362
|
+
}
|
|
363
|
+
const existing = aliases.get(target);
|
|
364
|
+
if (existing !== undefined) {
|
|
365
|
+
throw new Error(`[stitchkit] CLI command "${command}" field "${target}" has multiple aliases: -${existing}, -${alias}`);
|
|
366
|
+
}
|
|
367
|
+
aliases.set(target, alias);
|
|
463
368
|
}
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
const
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
for (let i = 0;i < argv.length; i++) {
|
|
478
|
-
const tok = argv[i];
|
|
479
|
-
if (tok === undefined)
|
|
480
|
-
continue;
|
|
481
|
-
if (!optionsEnded && tok === "--") {
|
|
482
|
-
optionsEnded = true;
|
|
483
|
-
continue;
|
|
369
|
+
return aliases;
|
|
370
|
+
}
|
|
371
|
+
function resolvePositionals(command, descriptor, configured) {
|
|
372
|
+
if (configured === undefined)
|
|
373
|
+
return;
|
|
374
|
+
const fields = fieldMap(descriptor);
|
|
375
|
+
const kinds = describeSchemaFields(descriptor.argumentSchema);
|
|
376
|
+
const seen = new Set;
|
|
377
|
+
let optionalSeen = false;
|
|
378
|
+
for (const name of configured) {
|
|
379
|
+
const field = fields.get(name);
|
|
380
|
+
if (isUnsafeKey(name) || !field || !kinds.has(name)) {
|
|
381
|
+
throw new Error(`[stitchkit] CLI command "${command}" positional targets unknown field "${name}"`);
|
|
484
382
|
}
|
|
485
|
-
if (
|
|
486
|
-
|
|
487
|
-
continue;
|
|
383
|
+
if (seen.has(name)) {
|
|
384
|
+
throw new Error(`[stitchkit] CLI command "${command}" repeats positional field "${name}"`);
|
|
488
385
|
}
|
|
489
|
-
if (
|
|
490
|
-
|
|
491
|
-
continue;
|
|
386
|
+
if (kinds.get(name)?.kind === "boolean") {
|
|
387
|
+
throw new Error(`[stitchkit] CLI command "${command}" boolean field "${name}" cannot be positional`);
|
|
492
388
|
}
|
|
493
|
-
if (
|
|
494
|
-
|
|
495
|
-
const alias = match?.[1];
|
|
496
|
-
const field = alias === undefined ? undefined : config.optionAliases?.get(alias);
|
|
497
|
-
if (!alias || !field)
|
|
498
|
-
throw new CliArgumentError(`Unknown option "${tok}"`);
|
|
499
|
-
const inline = match?.[2];
|
|
500
|
-
const info2 = fields.get(field);
|
|
501
|
-
if (info2?.kind === "boolean") {
|
|
502
|
-
boolFlags.set(field, inline === undefined ? true : parseReservedBool(field, inline));
|
|
503
|
-
continue;
|
|
504
|
-
}
|
|
505
|
-
let value2 = inline;
|
|
506
|
-
if (value2 === undefined) {
|
|
507
|
-
const next = argv[i + 1];
|
|
508
|
-
if (next !== undefined && (!next.startsWith("-") || NUMERIC_VALUE.test(next))) {
|
|
509
|
-
value2 = next;
|
|
510
|
-
i++;
|
|
511
|
-
} else {
|
|
512
|
-
throw new CliArgumentError(`--${field} requires a value`);
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
pushFlag(field, value2);
|
|
516
|
-
continue;
|
|
389
|
+
if (optionalSeen && field.required) {
|
|
390
|
+
throw new Error(`[stitchkit] CLI command "${command}" required positional "${name}" cannot follow an optional positional`);
|
|
517
391
|
}
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
if (value === undefined || value.startsWith("-") && !NUMERIC_VALUE.test(value)) {
|
|
545
|
-
throw new CliArgumentError(`--${name} requires a value`);
|
|
546
|
-
}
|
|
547
|
-
if (!option.inline)
|
|
548
|
-
i++;
|
|
549
|
-
if (name === "wait-timeout") {
|
|
550
|
-
const timeout = Number(value);
|
|
551
|
-
if (!Number.isFinite(timeout) || timeout <= 0) {
|
|
552
|
-
throw new CliArgumentError("--wait-timeout must be a positive number");
|
|
553
|
-
}
|
|
554
|
-
options.waitTimeout = timeout;
|
|
555
|
-
} else if (VIEW_OPTIONS.has(name)) {
|
|
556
|
-
if (viewFlags.has(name))
|
|
557
|
-
throw new CliArgumentError(`--${name} was given twice`);
|
|
558
|
-
viewFlags.set(name, value);
|
|
559
|
-
} else {
|
|
560
|
-
options.outputDir = value;
|
|
561
|
-
}
|
|
562
|
-
continue;
|
|
563
|
-
}
|
|
564
|
-
if (value === undefined && name.startsWith("no-") && fields.get(name.slice(3))?.kind === "boolean") {
|
|
565
|
-
boolFlags.set(name.slice(3), false);
|
|
566
|
-
continue;
|
|
567
|
-
}
|
|
568
|
-
const unsafeSegment = name.split(".").find(isUnsafeKey);
|
|
569
|
-
if (unsafeSegment !== undefined) {
|
|
570
|
-
throw new CliArgumentError(`Unsafe option name "--${name}"`);
|
|
392
|
+
if (!field.required)
|
|
393
|
+
optionalSeen = true;
|
|
394
|
+
seen.add(name);
|
|
395
|
+
}
|
|
396
|
+
return [...configured];
|
|
397
|
+
}
|
|
398
|
+
function applyCliPresentationPolicy(command, descriptor, config) {
|
|
399
|
+
const base = { ...descriptor, aliases: new Map };
|
|
400
|
+
const configuredAliases = config.optionAliases && Object.hasOwn(config.optionAliases, command) ? config.optionAliases[command] : undefined;
|
|
401
|
+
const configuredPositionals = config.positionals && Object.hasOwn(config.positionals, command) ? config.positionals[command] : undefined;
|
|
402
|
+
return {
|
|
403
|
+
...base,
|
|
404
|
+
aliases: resolveAliases(command, base, configuredAliases),
|
|
405
|
+
positionals: resolvePositionals(command, base, configuredPositionals)
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
function assertCliPoliciesResolved(commands, config) {
|
|
409
|
+
const configuredNames = new Set([
|
|
410
|
+
...Object.keys(config.optionAliases ?? {}),
|
|
411
|
+
...Object.keys(config.positionals ?? {})
|
|
412
|
+
]);
|
|
413
|
+
if (config.defaultCommand !== undefined)
|
|
414
|
+
configuredNames.add(config.defaultCommand);
|
|
415
|
+
for (const name of configuredNames) {
|
|
416
|
+
if (!commands.has(name)) {
|
|
417
|
+
throw new Error(`[stitchkit] CLI policy targets unavailable command "${name}"`);
|
|
571
418
|
}
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// src/tools/cli/invoke.ts
|
|
423
|
+
function parseCliGlobals(schema, globals) {
|
|
424
|
+
if (!schema)
|
|
425
|
+
return globals ?? {};
|
|
426
|
+
return schema.parse(globals ?? {});
|
|
427
|
+
}
|
|
428
|
+
function cliInvocationResult(result, toolName, config) {
|
|
429
|
+
if (result.ok)
|
|
430
|
+
return { ok: true, exitCode: 0, data: result.data };
|
|
431
|
+
const normalized = toolErrorFromResult(result);
|
|
432
|
+
const hints = [];
|
|
433
|
+
if (result.hint)
|
|
434
|
+
hints.push(result.hint);
|
|
435
|
+
const global = config.errorHint?.(toolName, result.code);
|
|
436
|
+
if (global)
|
|
437
|
+
hints.push(global);
|
|
438
|
+
return {
|
|
439
|
+
ok: false,
|
|
440
|
+
exitCode: cliExitCode(result, config.exitCodes),
|
|
441
|
+
error: {
|
|
442
|
+
code: result.code,
|
|
443
|
+
message: normalized.message,
|
|
444
|
+
...result.details !== undefined && { details: result.details },
|
|
445
|
+
...hints.length > 0 && { hint: hints.join(" ") },
|
|
446
|
+
...result.retryable !== undefined && { retryable: result.retryable }
|
|
576
447
|
}
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
async function createCliInvoker(config, globals) {
|
|
451
|
+
const typedGlobals = parseCliGlobals(config.globalOptions, globals);
|
|
452
|
+
const auth = await (config.resolveAuth ? config.resolveAuth(typedGlobals) : config.auth);
|
|
453
|
+
const natives = new Map((config.commands ?? []).filter(cliCommandReturnsResult).map((definition) => [definition.name, definition]));
|
|
454
|
+
const nativeHelp = new Map([...natives].map(([name, definition]) => [
|
|
455
|
+
name,
|
|
456
|
+
{ description: definition.description, argumentSchema: {}, presentationSchema: {} }
|
|
457
|
+
]));
|
|
458
|
+
const { tools, help } = buildCliSurface(config, auth, new Map, new Set);
|
|
459
|
+
const runTool = createToolRunner({
|
|
460
|
+
source: "cli",
|
|
461
|
+
toolSurface: true,
|
|
462
|
+
context: { ...config.context?.(auth, typedGlobals), signal: config.signal },
|
|
463
|
+
hooks: config.hooks,
|
|
464
|
+
lifecycle: config.lifecycle,
|
|
465
|
+
coerceJsonArgs: config.coerceJsonArgs
|
|
466
|
+
});
|
|
467
|
+
return {
|
|
468
|
+
commands: [...nativeHelp, ...help].map(([name, presentation]) => ({
|
|
469
|
+
name,
|
|
470
|
+
description: presentation.description
|
|
471
|
+
})),
|
|
472
|
+
invoke: async (command, args) => {
|
|
473
|
+
const native = natives.get(command);
|
|
474
|
+
if (native)
|
|
475
|
+
return runNativeCommand(native, args, config, typedGlobals);
|
|
476
|
+
const tool = tools.get(command);
|
|
477
|
+
if (!tool) {
|
|
478
|
+
return cliInvocationResult({
|
|
479
|
+
ok: false,
|
|
480
|
+
code: "NOT_FOUND",
|
|
481
|
+
details: { message: `Unknown command "${command}"` }
|
|
482
|
+
}, command, config);
|
|
581
483
|
}
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
throw new CliArgumentError(`--${name} requires a value`);
|
|
484
|
+
let result;
|
|
485
|
+
try {
|
|
486
|
+
result = await runTool(tool, args);
|
|
487
|
+
} catch (error) {
|
|
488
|
+
result = toolResultFromError(error);
|
|
588
489
|
}
|
|
490
|
+
return cliInvocationResult(result, command, config);
|
|
589
491
|
}
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
var IN_PROCESS_RUN_OPTIONS = Object.freeze({
|
|
495
|
+
json: false,
|
|
496
|
+
wait: false,
|
|
497
|
+
quiet: true,
|
|
498
|
+
dryRun: false,
|
|
499
|
+
help: false
|
|
500
|
+
});
|
|
501
|
+
async function runNativeCommand(definition, args, config, globals) {
|
|
502
|
+
let out = "";
|
|
503
|
+
let err = "";
|
|
504
|
+
const result = await executeCliCommand(definition, args, IN_PROCESS_RUN_OPTIONS, {
|
|
505
|
+
stdout: (text) => {
|
|
506
|
+
out += text;
|
|
507
|
+
},
|
|
508
|
+
stderr: (text) => {
|
|
509
|
+
err += text;
|
|
510
|
+
}
|
|
511
|
+
}, config.coerceJsonArgs ?? true, globals);
|
|
512
|
+
let invocation = cliInvocationResult(result, definition.name, config);
|
|
513
|
+
if (invocation.ok) {
|
|
514
|
+
try {
|
|
515
|
+
invocation = {
|
|
516
|
+
...invocation,
|
|
517
|
+
exitCode: cliCommandSuccessExitCode(definition, result.ok ? result.data : undefined)
|
|
518
|
+
};
|
|
519
|
+
} catch (error) {
|
|
520
|
+
invocation = cliInvocationResult(toolResultFromError(error), definition.name, config);
|
|
609
521
|
}
|
|
610
|
-
if (flags.has(key))
|
|
611
|
-
continue;
|
|
612
|
-
const value = positionals[pi++];
|
|
613
|
-
if (value !== undefined)
|
|
614
|
-
toolArgs[key] = coerceField(fields.get(key), [value]);
|
|
615
522
|
}
|
|
616
|
-
if (
|
|
617
|
-
|
|
523
|
+
if (out === "" && err === "")
|
|
524
|
+
return invocation;
|
|
525
|
+
return {
|
|
526
|
+
...invocation,
|
|
527
|
+
written: { ...out !== "" && { stdout: out }, ...err !== "" && { stderr: err } }
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
function buildCliSurface(config, auth, nativeHelp, applicationGlobalNames, assertShape) {
|
|
531
|
+
const services = typeof config.services === "function" ? config.services(auth) : config.services ?? [];
|
|
532
|
+
const runtimeTools = typeof config.runtimeTools === "function" ? config.runtimeTools(auth) : config.runtimeTools ?? [];
|
|
533
|
+
const tools = new Map;
|
|
534
|
+
const help = new Map(nativeHelp);
|
|
535
|
+
for (const { mountable } of collectToolSurface({
|
|
536
|
+
surface: { services, runtimeTools },
|
|
537
|
+
transport: "CLI"
|
|
538
|
+
})) {
|
|
539
|
+
const descriptor = applyCliPresentationPolicy(mountable.name, managedCliDescriptor(mountable), config);
|
|
540
|
+
assertShape?.(mountable.name, descriptor, help.has(mountable.name), config.passthrough?.[mountable.name], applicationGlobalNames);
|
|
541
|
+
tools.set(mountable.name, mountable);
|
|
542
|
+
help.set(mountable.name, descriptor);
|
|
618
543
|
}
|
|
619
|
-
|
|
620
|
-
|
|
544
|
+
assertCliPoliciesResolved(help, config);
|
|
545
|
+
return { tools, help };
|
|
546
|
+
}
|
|
547
|
+
function managedCliDescriptor(tool) {
|
|
548
|
+
return {
|
|
549
|
+
description: tool.method.desc,
|
|
550
|
+
argumentSchema: tool.argumentSchema,
|
|
551
|
+
presentationSchema: tool.presentationSchema
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// src/tools/cli/args-route.ts
|
|
556
|
+
function isOptionToken(token) {
|
|
557
|
+
return token.startsWith("--") || /^-[A-Za-z](?:=|$)/.test(token);
|
|
558
|
+
}
|
|
559
|
+
function looksLikeOption(token) {
|
|
560
|
+
return token.startsWith("--") || /^-[A-Za-z]/.test(token);
|
|
561
|
+
}
|
|
562
|
+
var BOOL_OPTIONS = new Set(["json", "wait", "quiet", "dry-run", "help", "ascending"]);
|
|
563
|
+
var VIEW_OPTIONS = new Set(["count-by", "sum", "by", "top", "table", "sort"]);
|
|
564
|
+
var VALUE_OPTIONS = new Set(["wait-timeout", "output-dir", ...VIEW_OPTIONS]);
|
|
565
|
+
var RESERVED_CLI_OPTIONS = new Set([...BOOL_OPTIONS, ...VALUE_OPTIONS]);
|
|
566
|
+
function classifyLongOptionToken(token) {
|
|
567
|
+
if (!token.startsWith("--") || token === "--")
|
|
568
|
+
return;
|
|
569
|
+
const equals = token.indexOf("=");
|
|
570
|
+
const name = equals >= 0 ? token.slice(2, equals) : token.slice(2);
|
|
571
|
+
return {
|
|
572
|
+
name,
|
|
573
|
+
value: equals >= 0 ? token.slice(equals + 1) : undefined,
|
|
574
|
+
inline: equals >= 0,
|
|
575
|
+
globalKind: BOOL_OPTIONS.has(name) ? "boolean" : VALUE_OPTIONS.has(name) ? "value" : undefined
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
var HELP_TOKENS = new Set(["--help", "-h", "help"]);
|
|
579
|
+
function helpFilterFrom(token, rest) {
|
|
580
|
+
if (token?.startsWith("--help=")) {
|
|
581
|
+
const value = token.slice("--help=".length).trim();
|
|
582
|
+
if (value.length === 0 || isReservedBoolWord(value))
|
|
583
|
+
return;
|
|
584
|
+
return value;
|
|
621
585
|
}
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
586
|
+
if (token === undefined || !HELP_TOKENS.has(token))
|
|
587
|
+
return;
|
|
588
|
+
const next = rest[0];
|
|
589
|
+
return next !== undefined && !next.startsWith("-") ? next : undefined;
|
|
590
|
+
}
|
|
591
|
+
function routeCliArgv(argv, defaultCommand) {
|
|
592
|
+
if (defaultCommand === undefined) {
|
|
593
|
+
const [command, ...commandArgv] = argv;
|
|
594
|
+
const helpFilter = helpFilterFrom(command, commandArgv);
|
|
595
|
+
return {
|
|
596
|
+
command,
|
|
597
|
+
commandArgv,
|
|
598
|
+
topLevelHelp: false,
|
|
599
|
+
version: false,
|
|
600
|
+
...helpFilter !== undefined && { helpFilter }
|
|
601
|
+
};
|
|
627
602
|
}
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
603
|
+
const globals = [];
|
|
604
|
+
let index = 0;
|
|
605
|
+
while (index < argv.length) {
|
|
606
|
+
const token = argv[index];
|
|
607
|
+
if (token === undefined)
|
|
608
|
+
break;
|
|
609
|
+
if (token === "--") {
|
|
610
|
+
return {
|
|
611
|
+
commandArgv: [],
|
|
612
|
+
topLevelHelp: false,
|
|
613
|
+
version: false,
|
|
614
|
+
error: 'A command is required before "--"'
|
|
615
|
+
};
|
|
631
616
|
}
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
617
|
+
const inlineHelpFilter = token.startsWith("--help=") && !isReservedBoolWord(token.slice("--help=".length));
|
|
618
|
+
if (token === "--help" || token === "-h" || inlineHelpFilter) {
|
|
619
|
+
const helpFilter = helpFilterFrom(token, argv.slice(index + 1));
|
|
620
|
+
return {
|
|
621
|
+
commandArgv: [],
|
|
622
|
+
topLevelHelp: true,
|
|
623
|
+
version: false,
|
|
624
|
+
...helpFilter !== undefined && { helpFilter }
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
if (token === "--version" || token === "version") {
|
|
628
|
+
return { commandArgv: [], topLevelHelp: false, version: true };
|
|
629
|
+
}
|
|
630
|
+
if (!token.startsWith("-") || token === "-") {
|
|
631
|
+
return {
|
|
632
|
+
command: token,
|
|
633
|
+
commandArgv: [...globals, ...argv.slice(index + 1)],
|
|
634
|
+
topLevelHelp: false,
|
|
635
|
+
version: false
|
|
636
|
+
};
|
|
640
637
|
}
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
638
|
+
if (!token.startsWith("--")) {
|
|
639
|
+
return {
|
|
640
|
+
command: defaultCommand,
|
|
641
|
+
commandArgv: [...globals, ...argv.slice(index)],
|
|
642
|
+
topLevelHelp: false,
|
|
643
|
+
version: false
|
|
644
|
+
};
|
|
644
645
|
}
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
const token = argv[i];
|
|
658
|
-
if (token === undefined)
|
|
659
|
-
continue;
|
|
660
|
-
if (!ended && token === "--")
|
|
661
|
-
ended = true;
|
|
662
|
-
const option = ended ? undefined : classifyLongOptionToken(token);
|
|
663
|
-
const info = option && option.globalKind === undefined ? fields.get(option.name) : undefined;
|
|
664
|
-
if (!option || !info) {
|
|
665
|
-
rest.push(token);
|
|
646
|
+
const option = classifyLongOptionToken(token);
|
|
647
|
+
if (!option) {
|
|
648
|
+
return {
|
|
649
|
+
command: defaultCommand,
|
|
650
|
+
commandArgv: [...globals, ...argv.slice(index)],
|
|
651
|
+
topLevelHelp: false,
|
|
652
|
+
version: false
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
if (option.globalKind === "boolean") {
|
|
656
|
+
globals.push(token);
|
|
657
|
+
index += 1;
|
|
666
658
|
continue;
|
|
667
659
|
}
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
660
|
+
if (option.globalKind === "value") {
|
|
661
|
+
globals.push(token);
|
|
662
|
+
if (!option.inline) {
|
|
663
|
+
const value = argv[index + 1];
|
|
664
|
+
if (value === "--help" || value === "-h") {
|
|
665
|
+
const helpFilter = helpFilterFrom(value, argv.slice(index + 2));
|
|
666
|
+
return {
|
|
667
|
+
commandArgv: [],
|
|
668
|
+
topLevelHelp: true,
|
|
669
|
+
version: false,
|
|
670
|
+
...helpFilter !== undefined && { helpFilter }
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
if (value === "--version" || value === "version") {
|
|
674
|
+
return { commandArgv: [], topLevelHelp: false, version: true };
|
|
675
|
+
}
|
|
676
|
+
if (value !== undefined)
|
|
677
|
+
globals.push(value);
|
|
678
|
+
index += value === undefined ? 1 : 2;
|
|
676
679
|
} else {
|
|
677
|
-
|
|
680
|
+
index += 1;
|
|
678
681
|
}
|
|
682
|
+
continue;
|
|
679
683
|
}
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
const args = {};
|
|
687
|
-
for (const [name, values] of raw)
|
|
688
|
-
args[name] = coerceField(fields.get(name), values);
|
|
689
|
-
const parsed = schema.safeParse(coerceJsonArgs(args, schema));
|
|
690
|
-
if (!parsed.success) {
|
|
691
|
-
const issue = parsed.error.issues[0];
|
|
692
|
-
const field = issue?.path[0];
|
|
693
|
-
const where = typeof field === "string" ? `--${field}` : "application option";
|
|
694
|
-
throw new CliArgumentError(`${where}: ${issue?.message ?? "invalid value"}`);
|
|
684
|
+
return {
|
|
685
|
+
command: defaultCommand,
|
|
686
|
+
commandArgv: [...globals, ...argv.slice(index)],
|
|
687
|
+
topLevelHelp: false,
|
|
688
|
+
version: false
|
|
689
|
+
};
|
|
695
690
|
}
|
|
696
|
-
return {
|
|
691
|
+
return {
|
|
692
|
+
command: defaultCommand,
|
|
693
|
+
commandArgv: globals,
|
|
694
|
+
topLevelHelp: false,
|
|
695
|
+
version: false
|
|
696
|
+
};
|
|
697
697
|
}
|
|
698
|
+
|
|
699
|
+
// src/tools/cli/args-view.ts
|
|
698
700
|
function resolveCliView(flags, ascending) {
|
|
699
701
|
if (flags.size === 0) {
|
|
700
702
|
if (ascending) {
|
|
@@ -775,217 +777,264 @@ function resolveCliView(flags, ascending) {
|
|
|
775
777
|
throw new CliArgumentError("--top needs --sort, --by, --count-by or --sum to rank");
|
|
776
778
|
}
|
|
777
779
|
|
|
778
|
-
// src/tools/cli/
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
const
|
|
788
|
-
const
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
780
|
+
// src/tools/cli/args.ts
|
|
781
|
+
function readCliTokens(argv, fields, config) {
|
|
782
|
+
const options = {
|
|
783
|
+
json: false,
|
|
784
|
+
wait: false,
|
|
785
|
+
quiet: false,
|
|
786
|
+
dryRun: false,
|
|
787
|
+
help: false
|
|
788
|
+
};
|
|
789
|
+
const flags = new Map;
|
|
790
|
+
const boolFlags = new Map;
|
|
791
|
+
const viewFlags = new Map;
|
|
792
|
+
let ascending = false;
|
|
793
|
+
const positionals = [];
|
|
794
|
+
const pushFlag = (name, value) => {
|
|
795
|
+
const existing = flags.get(name);
|
|
796
|
+
if (existing)
|
|
797
|
+
existing.push(value);
|
|
798
|
+
else
|
|
799
|
+
flags.set(name, [value]);
|
|
800
|
+
};
|
|
801
|
+
let optionsEnded = false;
|
|
802
|
+
for (let i = 0;i < argv.length; i++) {
|
|
803
|
+
const tok = argv[i];
|
|
804
|
+
if (tok === undefined)
|
|
805
|
+
continue;
|
|
806
|
+
if (!optionsEnded && tok === "--") {
|
|
807
|
+
optionsEnded = true;
|
|
808
|
+
continue;
|
|
792
809
|
}
|
|
793
|
-
if (
|
|
794
|
-
|
|
810
|
+
if (optionsEnded || !looksLikeOption(tok)) {
|
|
811
|
+
positionals.push(tok);
|
|
812
|
+
continue;
|
|
795
813
|
}
|
|
796
|
-
if (
|
|
797
|
-
|
|
814
|
+
if (tok === "-h") {
|
|
815
|
+
options.help = true;
|
|
816
|
+
continue;
|
|
817
|
+
}
|
|
818
|
+
if (!tok.startsWith("--")) {
|
|
819
|
+
const match = /^-([A-Za-z])(?:=(.*))?$/.exec(tok);
|
|
820
|
+
const alias = match?.[1];
|
|
821
|
+
const field = alias === undefined ? undefined : config.optionAliases?.get(alias);
|
|
822
|
+
if (!alias || !field)
|
|
823
|
+
throw new CliArgumentError(`Unknown option "${tok}"`);
|
|
824
|
+
const inline = match?.[2];
|
|
825
|
+
const info2 = fields.get(field);
|
|
826
|
+
if (info2?.kind === "boolean") {
|
|
827
|
+
boolFlags.set(field, inline === undefined ? true : parseReservedBool(field, inline));
|
|
828
|
+
continue;
|
|
829
|
+
}
|
|
830
|
+
let value2 = inline;
|
|
831
|
+
if (value2 === undefined) {
|
|
832
|
+
const next = argv[i + 1];
|
|
833
|
+
if (next !== undefined && !isOptionToken(next)) {
|
|
834
|
+
value2 = next;
|
|
835
|
+
i++;
|
|
836
|
+
} else {
|
|
837
|
+
throw new CliArgumentError(`--${field} requires a value`);
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
pushFlag(field, value2);
|
|
841
|
+
continue;
|
|
842
|
+
}
|
|
843
|
+
const option = classifyLongOptionToken(tok);
|
|
844
|
+
if (!option)
|
|
845
|
+
throw new CliArgumentError(`Unknown option "${tok}"`);
|
|
846
|
+
const { name } = option;
|
|
847
|
+
let { value } = option;
|
|
848
|
+
if (name.length === 0)
|
|
849
|
+
throw new CliArgumentError("Invalid empty option name");
|
|
850
|
+
if (option.globalKind === "boolean") {
|
|
851
|
+
const enabled = value === undefined ? true : parseReservedBool(name, value);
|
|
852
|
+
if (name === "dry-run")
|
|
853
|
+
options.dryRun = enabled;
|
|
854
|
+
else if (name === "json")
|
|
855
|
+
options.json = enabled;
|
|
856
|
+
else if (name === "wait")
|
|
857
|
+
options.wait = enabled;
|
|
858
|
+
else if (name === "quiet")
|
|
859
|
+
options.quiet = enabled;
|
|
860
|
+
else if (name === "ascending")
|
|
861
|
+
ascending = enabled;
|
|
862
|
+
else
|
|
863
|
+
options.help = enabled;
|
|
864
|
+
continue;
|
|
865
|
+
}
|
|
866
|
+
if (option.globalKind === "value") {
|
|
867
|
+
const next = argv[i + 1];
|
|
868
|
+
value = value ?? next;
|
|
869
|
+
if (value === undefined || !option.inline && isOptionToken(value)) {
|
|
870
|
+
throw new CliArgumentError(`--${name} requires a value`);
|
|
871
|
+
}
|
|
872
|
+
if (!option.inline)
|
|
873
|
+
i++;
|
|
874
|
+
if (name === "wait-timeout") {
|
|
875
|
+
const timeout = Number(value);
|
|
876
|
+
if (!Number.isFinite(timeout) || timeout <= 0) {
|
|
877
|
+
throw new CliArgumentError("--wait-timeout must be a positive number");
|
|
878
|
+
}
|
|
879
|
+
options.waitTimeout = timeout;
|
|
880
|
+
} else if (VIEW_OPTIONS.has(name)) {
|
|
881
|
+
if (viewFlags.has(name))
|
|
882
|
+
throw new CliArgumentError(`--${name} was given twice`);
|
|
883
|
+
viewFlags.set(name, value);
|
|
884
|
+
} else {
|
|
885
|
+
options.outputDir = value;
|
|
886
|
+
}
|
|
887
|
+
continue;
|
|
888
|
+
}
|
|
889
|
+
if (value === undefined && name.startsWith("no-") && fields.get(name.slice(3))?.kind === "boolean") {
|
|
890
|
+
boolFlags.set(name.slice(3), false);
|
|
891
|
+
continue;
|
|
892
|
+
}
|
|
893
|
+
const unsafeSegment = name.split(".").find(isUnsafeKey);
|
|
894
|
+
if (unsafeSegment !== undefined) {
|
|
895
|
+
throw new CliArgumentError(`Unsafe option name "--${name}"`);
|
|
896
|
+
}
|
|
897
|
+
const info = fields.get(name);
|
|
898
|
+
const rootName = name.split(".")[0] ?? name;
|
|
899
|
+
if (!fields.has(rootName) && !config.allowUnknown) {
|
|
900
|
+
throw new CliArgumentError(`Unknown option "--${name}"`);
|
|
901
|
+
}
|
|
902
|
+
if (value === undefined) {
|
|
903
|
+
if (info?.kind === "boolean") {
|
|
904
|
+
boolFlags.set(name, true);
|
|
905
|
+
continue;
|
|
906
|
+
}
|
|
907
|
+
const next = argv[i + 1];
|
|
908
|
+
if (next !== undefined && !isOptionToken(next)) {
|
|
909
|
+
value = next;
|
|
910
|
+
i++;
|
|
911
|
+
} else {
|
|
912
|
+
throw new CliArgumentError(`--${name} requires a value`);
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
pushFlag(name, value);
|
|
916
|
+
}
|
|
917
|
+
return { options, flags, boolFlags, viewFlags, ascending, positionals };
|
|
918
|
+
}
|
|
919
|
+
function buildToolArgs(tokens, fields, declaredPositionals) {
|
|
920
|
+
const { flags, boolFlags, positionals } = tokens;
|
|
921
|
+
const toolArgs = {};
|
|
922
|
+
const fillable = declaredPositionals === undefined ? [...fields.entries()].filter(([, info]) => info.kind !== "boolean").map(([name]) => name) : [...declaredPositionals];
|
|
923
|
+
const variadicTail = declaredPositionals !== undefined && fields.get(fillable[fillable.length - 1] ?? "")?.kind === "array" ? fillable[fillable.length - 1] : undefined;
|
|
924
|
+
let pi = 0;
|
|
925
|
+
for (const key of fillable) {
|
|
926
|
+
if (pi >= positionals.length)
|
|
927
|
+
break;
|
|
928
|
+
if (key === variadicTail) {
|
|
929
|
+
if (flags.has(key)) {
|
|
930
|
+
throw new CliArgumentError(`--${key} conflicts with the positional values for "${key}" — pass one form, not both`);
|
|
931
|
+
}
|
|
932
|
+
toolArgs[key] = coerceField(fields.get(key), positionals.slice(pi), `<${key}>`);
|
|
933
|
+
pi = positionals.length;
|
|
934
|
+
break;
|
|
798
935
|
}
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
936
|
+
if (flags.has(key))
|
|
937
|
+
continue;
|
|
938
|
+
const value = positionals[pi++];
|
|
939
|
+
if (value !== undefined) {
|
|
940
|
+
toolArgs[key] = coerceField(fields.get(key), [value], `<${key}>`);
|
|
802
941
|
}
|
|
803
|
-
aliases.set(target, alias);
|
|
804
942
|
}
|
|
805
|
-
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
const
|
|
812
|
-
const
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
throw new Error(`[stitchkit] CLI command "${command}" repeats positional field "${name}"`);
|
|
943
|
+
if (pi < positionals.length) {
|
|
944
|
+
throw new CliArgumentError(`Unexpected positional argument "${positionals[pi]}"`);
|
|
945
|
+
}
|
|
946
|
+
for (const [key, value] of boolFlags) {
|
|
947
|
+
toolArgs[key] = value;
|
|
948
|
+
}
|
|
949
|
+
const dottedRoots = new Map;
|
|
950
|
+
for (const key of flags.keys()) {
|
|
951
|
+
const dot = key.indexOf(".");
|
|
952
|
+
if (dot > 0)
|
|
953
|
+
dottedRoots.set(key.slice(0, dot), key);
|
|
954
|
+
}
|
|
955
|
+
for (const [root, dotted] of dottedRoots) {
|
|
956
|
+
if (flags.has(root)) {
|
|
957
|
+
throw new CliArgumentError(`--${root} conflicts with --${dotted} — pass one form, not both`);
|
|
821
958
|
}
|
|
822
|
-
|
|
823
|
-
|
|
959
|
+
}
|
|
960
|
+
for (const [key, values] of flags) {
|
|
961
|
+
if (key.includes(".")) {
|
|
962
|
+
if (values.length > 1) {
|
|
963
|
+
throw new CliArgumentError(`--${key} was passed ${values.length} times`);
|
|
964
|
+
}
|
|
965
|
+
setNested(toolArgs, key.split("."), looseCoerce(values[0] ?? ""));
|
|
966
|
+
continue;
|
|
824
967
|
}
|
|
825
|
-
|
|
826
|
-
|
|
968
|
+
const info = fields.get(key);
|
|
969
|
+
if (values.length > 1 && info !== undefined && info.kind !== "array" && info.kind !== "other") {
|
|
970
|
+
throw new CliArgumentError(`--${key} was passed ${values.length} times`);
|
|
827
971
|
}
|
|
828
|
-
|
|
829
|
-
optionalSeen = true;
|
|
830
|
-
seen.add(name);
|
|
972
|
+
toolArgs[key] = coerceField(info, values, `--${key}`);
|
|
831
973
|
}
|
|
832
|
-
return
|
|
833
|
-
}
|
|
834
|
-
function applyCliPresentationPolicy(command, descriptor, config) {
|
|
835
|
-
const base = { ...descriptor, aliases: new Map };
|
|
836
|
-
const configuredAliases = config.optionAliases && Object.hasOwn(config.optionAliases, command) ? config.optionAliases[command] : undefined;
|
|
837
|
-
const configuredPositionals = config.positionals && Object.hasOwn(config.positionals, command) ? config.positionals[command] : undefined;
|
|
838
|
-
return {
|
|
839
|
-
...base,
|
|
840
|
-
aliases: resolveAliases(command, base, configuredAliases),
|
|
841
|
-
positionals: resolvePositionals(command, base, configuredPositionals)
|
|
842
|
-
};
|
|
974
|
+
return toolArgs;
|
|
843
975
|
}
|
|
844
|
-
function
|
|
845
|
-
const
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
if (config.defaultCommand !== undefined)
|
|
850
|
-
configuredNames.add(config.defaultCommand);
|
|
851
|
-
for (const name of configuredNames) {
|
|
852
|
-
if (!commands.has(name)) {
|
|
853
|
-
throw new Error(`[stitchkit] CLI policy targets unavailable command "${name}"`);
|
|
854
|
-
}
|
|
976
|
+
function parseCliArgs(argv, schema, config = {}) {
|
|
977
|
+
const fields = describeSchemaFields(schema);
|
|
978
|
+
for (const name of config.knownFields ?? []) {
|
|
979
|
+
if (!fields.has(name))
|
|
980
|
+
fields.set(name, { kind: "other" });
|
|
855
981
|
}
|
|
982
|
+
const tokens = readCliTokens(argv, fields, config);
|
|
983
|
+
const { options } = tokens;
|
|
984
|
+
const view = resolveCliView(tokens.viewFlags, tokens.ascending);
|
|
985
|
+
if (view)
|
|
986
|
+
options.view = view;
|
|
987
|
+
return { toolArgs: buildToolArgs(tokens, fields, config.positionals), options };
|
|
856
988
|
}
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
ok: false,
|
|
876
|
-
exitCode: cliExitCode(result, config.exitCodes),
|
|
877
|
-
error: {
|
|
878
|
-
code: result.code,
|
|
879
|
-
message: normalized.message,
|
|
880
|
-
...result.details !== undefined && { details: result.details },
|
|
881
|
-
...hints.length > 0 && { hint: hints.join(" ") },
|
|
882
|
-
...result.retryable !== undefined && { retryable: result.retryable }
|
|
989
|
+
function extractCliGlobalOptions(argv, schema) {
|
|
990
|
+
if (schema === undefined)
|
|
991
|
+
return { argv: [...argv], globals: {} };
|
|
992
|
+
const fields = describeSchemaFields(schema);
|
|
993
|
+
const rest = [];
|
|
994
|
+
const raw = new Map;
|
|
995
|
+
let ended = false;
|
|
996
|
+
for (let i = 0;i < argv.length; i++) {
|
|
997
|
+
const token = argv[i];
|
|
998
|
+
if (token === undefined)
|
|
999
|
+
continue;
|
|
1000
|
+
if (!ended && token === "--")
|
|
1001
|
+
ended = true;
|
|
1002
|
+
const option = ended ? undefined : classifyLongOptionToken(token);
|
|
1003
|
+
const info = option && option.globalKind === undefined ? fields.get(option.name) : undefined;
|
|
1004
|
+
if (!option || !info) {
|
|
1005
|
+
rest.push(token);
|
|
1006
|
+
continue;
|
|
883
1007
|
}
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
const { tools, help } = buildCliSurface(config, auth, new Map, new Set);
|
|
895
|
-
const runTool = createToolRunner({
|
|
896
|
-
source: "cli",
|
|
897
|
-
toolSurface: true,
|
|
898
|
-
context: { ...config.context?.(auth, typedGlobals), signal: config.signal },
|
|
899
|
-
hooks: config.hooks,
|
|
900
|
-
lifecycle: config.lifecycle,
|
|
901
|
-
coerceJsonArgs: config.coerceJsonArgs
|
|
902
|
-
});
|
|
903
|
-
return {
|
|
904
|
-
commands: [...nativeHelp, ...help].map(([name, presentation]) => ({
|
|
905
|
-
name,
|
|
906
|
-
description: presentation.description
|
|
907
|
-
})),
|
|
908
|
-
invoke: async (command, args) => {
|
|
909
|
-
const native = natives.get(command);
|
|
910
|
-
if (native)
|
|
911
|
-
return runNativeCommand(native, args, config, typedGlobals);
|
|
912
|
-
const tool = tools.get(command);
|
|
913
|
-
if (!tool) {
|
|
914
|
-
return cliInvocationResult({
|
|
915
|
-
ok: false,
|
|
916
|
-
code: "NOT_FOUND",
|
|
917
|
-
details: { message: `Unknown command "${command}"` }
|
|
918
|
-
}, command, config);
|
|
919
|
-
}
|
|
920
|
-
let result;
|
|
921
|
-
try {
|
|
922
|
-
result = await runTool(tool, args);
|
|
923
|
-
} catch (error) {
|
|
924
|
-
result = toolResultFromError(error);
|
|
1008
|
+
let { value } = option;
|
|
1009
|
+
if (value === undefined && info.kind === "boolean") {
|
|
1010
|
+
value = "true";
|
|
1011
|
+
} else if (value === undefined) {
|
|
1012
|
+
const next = argv[i + 1];
|
|
1013
|
+
if (next !== undefined && !isOptionToken(next)) {
|
|
1014
|
+
value = next;
|
|
1015
|
+
i++;
|
|
1016
|
+
} else {
|
|
1017
|
+
throw new CliArgumentError(`--${option.name} requires a value`);
|
|
925
1018
|
}
|
|
926
|
-
return cliInvocationResult(result, command, config);
|
|
927
|
-
}
|
|
928
|
-
};
|
|
929
|
-
}
|
|
930
|
-
var IN_PROCESS_RUN_OPTIONS = Object.freeze({
|
|
931
|
-
json: false,
|
|
932
|
-
wait: false,
|
|
933
|
-
quiet: true,
|
|
934
|
-
dryRun: false,
|
|
935
|
-
help: false
|
|
936
|
-
});
|
|
937
|
-
async function runNativeCommand(definition, args, config, globals) {
|
|
938
|
-
let out = "";
|
|
939
|
-
let err = "";
|
|
940
|
-
const result = await executeCliCommand(definition, args, IN_PROCESS_RUN_OPTIONS, {
|
|
941
|
-
stdout: (text) => {
|
|
942
|
-
out += text;
|
|
943
|
-
},
|
|
944
|
-
stderr: (text) => {
|
|
945
|
-
err += text;
|
|
946
|
-
}
|
|
947
|
-
}, config.coerceJsonArgs ?? true, globals);
|
|
948
|
-
let invocation = cliInvocationResult(result, definition.name, config);
|
|
949
|
-
if (invocation.ok) {
|
|
950
|
-
try {
|
|
951
|
-
invocation = {
|
|
952
|
-
...invocation,
|
|
953
|
-
exitCode: cliCommandSuccessExitCode(definition, result.ok ? result.data : undefined)
|
|
954
|
-
};
|
|
955
|
-
} catch (error) {
|
|
956
|
-
invocation = cliInvocationResult(toolResultFromError(error), definition.name, config);
|
|
957
1019
|
}
|
|
1020
|
+
const existing = raw.get(option.name);
|
|
1021
|
+
if (existing)
|
|
1022
|
+
existing.push(value);
|
|
1023
|
+
else
|
|
1024
|
+
raw.set(option.name, [value]);
|
|
958
1025
|
}
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
...invocation,
|
|
963
|
-
written: { ...out !== "" && { stdout: out }, ...err !== "" && { stderr: err } }
|
|
964
|
-
};
|
|
965
|
-
}
|
|
966
|
-
function buildCliSurface(config, auth, nativeHelp, applicationGlobalNames, assertShape) {
|
|
967
|
-
const services = typeof config.services === "function" ? config.services(auth) : config.services ?? [];
|
|
968
|
-
const runtimeTools = typeof config.runtimeTools === "function" ? config.runtimeTools(auth) : config.runtimeTools ?? [];
|
|
969
|
-
const tools = new Map;
|
|
970
|
-
const help = new Map(nativeHelp);
|
|
971
|
-
for (const { mountable } of collectToolSurface({
|
|
972
|
-
surface: { services, runtimeTools },
|
|
973
|
-
transport: "CLI"
|
|
974
|
-
})) {
|
|
975
|
-
const descriptor = applyCliPresentationPolicy(mountable.name, managedCliDescriptor(mountable), config);
|
|
976
|
-
assertShape?.(mountable.name, descriptor, help.has(mountable.name), config.passthrough?.[mountable.name], applicationGlobalNames);
|
|
977
|
-
tools.set(mountable.name, mountable);
|
|
978
|
-
help.set(mountable.name, descriptor);
|
|
1026
|
+
const args = {};
|
|
1027
|
+
for (const [name, values] of raw) {
|
|
1028
|
+
args[name] = coerceField(fields.get(name), values, `--${name}`);
|
|
979
1029
|
}
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
};
|
|
1030
|
+
const parsed = schema.safeParse(coerceJsonArgs(args, schema));
|
|
1031
|
+
if (!parsed.success) {
|
|
1032
|
+
const issue = parsed.error.issues[0];
|
|
1033
|
+
const field = issue?.path[0];
|
|
1034
|
+
const where = typeof field === "string" ? `--${field}` : "application option";
|
|
1035
|
+
throw new CliArgumentError(`${where}: ${issue?.message ?? "invalid value"}`);
|
|
1036
|
+
}
|
|
1037
|
+
return { argv: rest, globals: parsed.data };
|
|
989
1038
|
}
|
|
990
1039
|
|
|
991
1040
|
// src/tools/cli/view.ts
|
|
@@ -2254,4 +2303,4 @@ async function createCli(config) {
|
|
|
2254
2303
|
return runManagedInvocation(session, route);
|
|
2255
2304
|
}
|
|
2256
2305
|
|
|
2257
|
-
export { fetchGuarded, PrivateAddressRefusal, fetchPinnedDocument, readCapped, WaitTimeoutError, runWaitOperation, defineCliCommand, DEFAULT_EXIT_CODES, cliExitCode, emitResult,
|
|
2306
|
+
export { fetchGuarded, PrivateAddressRefusal, fetchPinnedDocument, readCapped, WaitTimeoutError, runWaitOperation, defineCliCommand, DEFAULT_EXIT_CODES, cliExitCode, emitResult, CliArgumentError, cliInvocationResult, createCliInvoker, routeCliArgv, parseCliArgs, extractCliGlobalOptions, renderCliView, pollUntilDone, createCli };
|