stitchkit 0.100.2 → 0.101.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 +153 -0
- package/README.md +2 -1
- package/dist/entrypoints/agent-runtime/browser.js +119 -119
- package/dist/entrypoints/agent-runtime/coding-tools.js +15 -20
- package/dist/entrypoints/agent-runtime/harness.js +55 -63
- package/dist/entrypoints/agent-runtime/openrouter.js +6 -6
- package/dist/entrypoints/agent-runtime/sandbox.js +20 -25
- package/dist/entrypoints/agent-runtime/sqlite/bun.js +11 -13
- package/dist/entrypoints/agent-runtime/sqlite/node.js +11 -13
- package/dist/entrypoints/agent-runtime/testing.js +32 -34
- package/dist/entrypoints/agent-runtime.js +395 -402
- package/dist/entrypoints/application/diagnostic-journal.js +26 -27
- package/dist/entrypoints/application/directory-inbox.js +16 -17
- package/dist/entrypoints/application/grammy.js +13 -13
- package/dist/entrypoints/application/opentelemetry.js +13 -13
- package/dist/entrypoints/application/schemas.js +24 -24
- package/dist/entrypoints/application.js +209 -210
- package/dist/entrypoints/bin/upgrade-cli.js +2 -2
- package/dist/entrypoints/cli.js +81 -84
- package/dist/entrypoints/contract.js +54 -57
- package/dist/entrypoints/declaration.js +22 -22
- package/dist/entrypoints/files.js +18 -21
- package/dist/entrypoints/geo.js +7 -8
- package/dist/entrypoints/google.js +2 -2
- package/dist/entrypoints/index.js +150 -154
- package/dist/entrypoints/live.js +45 -47
- package/dist/entrypoints/node.js +68 -74
- package/dist/entrypoints/oauth.js +6 -6
- package/dist/entrypoints/observability.d.ts +1 -0
- package/dist/entrypoints/observability.d.ts.map +1 -1
- package/dist/entrypoints/observability.js +116 -87
- package/dist/entrypoints/primitives.js +35 -35
- package/dist/entrypoints/react/keyboard.d.ts +4 -0
- package/dist/entrypoints/react/keyboard.d.ts.map +1 -0
- package/dist/entrypoints/react/keyboard.js +397 -0
- package/dist/entrypoints/react.js +10 -10
- package/dist/entrypoints/release.js +7 -7
- package/dist/entrypoints/remote.js +15 -17
- package/dist/entrypoints/server.js +198 -200
- package/dist/entrypoints/telegram/html.d.ts +5 -0
- package/dist/entrypoints/telegram/html.d.ts.map +1 -0
- package/dist/entrypoints/telegram/html.js +26 -0
- package/dist/entrypoints/telegram/screens.d.ts +14 -0
- package/dist/entrypoints/telegram/screens.d.ts.map +1 -0
- package/dist/entrypoints/telegram/screens.js +2028 -0
- package/dist/entrypoints/telegram.d.ts +11 -3
- package/dist/entrypoints/telegram.d.ts.map +1 -1
- package/dist/entrypoints/telegram.js +779 -159
- package/dist/entrypoints/testing.js +75 -79
- package/dist/entrypoints/tools/connections.js +30 -32
- package/dist/entrypoints/tools/contract.js +18 -20
- package/dist/entrypoints/tools/invoker.js +12 -17
- package/dist/entrypoints/tools.js +224 -229
- package/dist/entrypoints/tracking/server.js +6 -6
- package/dist/entrypoints/tracking.js +40 -42
- package/dist/entrypoints/voice.js +3 -3
- package/dist/{index-eaysmdtq.js → index-0ndk4555.js} +56 -56
- package/dist/{index-2bxbyab0.js → index-1bx1xv1k.js} +1 -1
- package/dist/{index-p5r7qpdd.js → index-1eeqpadm.js} +4 -4
- package/dist/{index-hadmp193.js → index-3ct7hhq6.js} +210 -210
- package/dist/{index-e01r054k.js → index-45tdvqa3.js} +26 -26
- package/dist/{index-dce5wxcq.js → index-4s0fep5q.js} +8 -8
- package/dist/index-50ejfz75.js +9 -0
- package/dist/{index-m9zn6cpq.js → index-5107q189.js} +12 -12
- package/dist/{index-sbdmyz75.js → index-5cc6r990.js} +3 -3
- package/dist/{index-c6bxbsnc.js → index-7kxw1awn.js} +2 -2
- package/dist/{index-0r0fbk7z.js → index-7z9ym7t8.js} +28 -28
- package/dist/{index-p7hgdyhb.js → index-814xpr6d.js} +2 -2
- package/dist/{index-gtj3zc53.js → index-8kzct1d6.js} +99 -99
- package/dist/{index-1zbbzgfh.js → index-9pw0a51a.js} +4 -4
- package/dist/{index-79z7m7dt.js → index-a9pd417t.js} +35 -35
- package/dist/{index-ham5sz8m.js → index-aaj97r4y.js} +45 -45
- package/dist/{index-s812ycat.js → index-aan6hqb9.js} +3 -3
- package/dist/{index-10x2hbx0.js → index-adhgd4pe.js} +44 -44
- package/dist/{index-2gxzjvyr.js → index-afjvjyck.js} +23 -23
- package/dist/{index-qmy6zq75.js → index-ahvsksw5.js} +16 -16
- package/dist/{index-hr4tzbwq.js → index-ap3gqe56.js} +3 -3
- package/dist/{index-znfs20ss.js → index-b2bz0kdm.js} +16 -16
- package/dist/{index-r066jx76.js → index-c6aagrbd.js} +148 -120
- package/dist/{index-k30h66yd.js → index-ck71tbcf.js} +9 -9
- package/dist/{index-eqqvgdb3.js → index-ct75c3at.js} +2 -2
- package/dist/{index-gw8bmyaj.js → index-djjhhgjk.js} +41 -41
- package/dist/{index-8qt2m66q.js → index-dvwj1f43.js} +43 -43
- package/dist/index-e05cjgtf.js +144 -0
- package/dist/{index-yw4fzmdz.js → index-e6c2spsd.js} +79 -30
- package/dist/{index-fhwqwxe0.js → index-ej331hah.js} +1 -1
- package/dist/{index-9t3dffv2.js → index-ewbaywk5.js} +5 -5
- package/dist/{index-7p1f0vp2.js → index-fyphpknh.js} +25 -25
- package/dist/{index-83bdg97s.js → index-g149e9pk.js} +1 -1
- package/dist/{index-ngfhvfpd.js → index-g6a3na27.js} +4 -4
- package/dist/{index-qwhynv6x.js → index-h124epcf.js} +20 -20
- package/dist/{index-h6eeys1v.js → index-h97tqqp1.js} +9 -9
- package/dist/{index-zcgf3gqf.js → index-hby4qhax.js} +10 -10
- package/dist/{index-5jrd0yng.js → index-j8aw2c0e.js} +4 -4
- package/dist/{index-d8m8zpd8.js → index-jzczzcsb.js} +14 -14
- package/dist/index-kqnd6a85.js +26 -0
- package/dist/{index-35mh5bhj.js → index-kw1ws0cs.js} +12 -12
- package/dist/{index-4gcnakhx.js → index-m38ej7e5.js} +2 -2
- package/dist/{index-ndddxtyx.js → index-m79yr938.js} +19 -19
- package/dist/{index-5p2m7we1.js → index-m9fndta6.js} +11 -11
- package/dist/index-mnkk1ffz.js +150 -0
- package/dist/index-n15jny5b.js +4 -0
- package/dist/{index-2vtcmrj9.js → index-n53mswt3.js} +20 -20
- package/dist/{index-bt14acb5.js → index-n5yqxd3d.js} +21 -21
- package/dist/{index-bm5rx7n6.js → index-n9tyz8z3.js} +12 -12
- package/dist/index-nmaqxdx7.js +463 -0
- package/dist/{index-mqv3b5rh.js → index-nx6eazt0.js} +30 -30
- package/dist/{index-3z73fh2c.js → index-q0th8q0z.js} +9 -9
- package/dist/{index-v260df89.js → index-qjeggp8w.js} +20 -20
- package/dist/{index-zfrhfn82.js → index-r1z0rd9c.js} +20 -20
- package/dist/{index-wqgjfstn.js → index-r5c4fedv.js} +3 -3
- package/dist/{index-cyktc4bp.js → index-r5hsgkz5.js} +118 -118
- package/dist/{index-0b1ess5e.js → index-r7a7r7ha.js} +1 -1
- package/dist/{index-1j8pm5t0.js → index-rfkh44ss.js} +15 -15
- package/dist/index-rz3z13e9.js +47 -0
- package/dist/{index-k6gpggb9.js → index-s80awwsw.js} +35 -35
- package/dist/{index-vqr7f7v8.js → index-ssmd41kh.js} +124 -124
- package/dist/index-sznqf8fx.js +20 -0
- package/dist/{index-ensd0r74.js → index-v14qqmys.js} +41 -41
- package/dist/{index-paz6sgdp.js → index-v4a2fjtk.js} +36 -36
- package/dist/{index-d9pk3td4.js → index-w0eqdhyd.js} +14 -14
- package/dist/{index-5qn1kx34.js → index-w575evhq.js} +29 -29
- package/dist/{index-3gye9wzb.js → index-w5s3xftz.js} +26 -26
- package/dist/{index-tm88avnj.js → index-wykebpn9.js} +3 -3
- package/dist/{index-sh3s86na.js → index-xkhk5d6g.js} +17 -17
- package/dist/{index-6k1937bx.js → index-xqhede6x.js} +4 -4
- package/dist/{index-f4fx2tza.js → index-zs4ms3th.js} +181 -181
- package/dist/{index-k5hsfc3j.js → index-zsvzhjtk.js} +1 -1
- package/dist/internal/secret-shapes.d.ts +21 -0
- package/dist/internal/secret-shapes.d.ts.map +1 -0
- package/dist/observability/bounded-logger.d.ts +2 -0
- package/dist/observability/bounded-logger.d.ts.map +1 -1
- package/dist/observability/sanitize.d.ts +6 -0
- package/dist/observability/sanitize.d.ts.map +1 -1
- package/dist/observability/secret-values.d.ts +25 -0
- package/dist/observability/secret-values.d.ts.map +1 -0
- package/dist/react/keyboard/hooks.d.ts +71 -0
- package/dist/react/keyboard/hooks.d.ts.map +1 -0
- package/dist/react/keyboard/layers.d.ts +98 -0
- package/dist/react/keyboard/layers.d.ts.map +1 -0
- package/dist/react/keyboard/zone.d.ts +139 -0
- package/dist/react/keyboard/zone.d.ts.map +1 -0
- package/dist/telegram/bot-api.d.ts +7 -4
- package/dist/telegram/bot-api.d.ts.map +1 -1
- package/dist/telegram/crypto.d.ts +16 -0
- package/dist/telegram/crypto.d.ts.map +1 -0
- package/dist/telegram/html/check.d.ts +26 -0
- package/dist/telegram/html/check.d.ts.map +1 -0
- package/dist/telegram/html/nodes.d.ts +70 -0
- package/dist/telegram/html/nodes.d.ts.map +1 -0
- package/dist/telegram/html/parse.d.ts +35 -0
- package/dist/telegram/html/parse.d.ts.map +1 -0
- package/dist/telegram/html/render.d.ts +39 -0
- package/dist/telegram/html/render.d.ts.map +1 -0
- package/dist/telegram/init-data.d.ts +3 -44
- package/dist/telegram/init-data.d.ts.map +1 -1
- package/dist/telegram/operator-channel.d.ts +19 -3
- package/dist/telegram/operator-channel.d.ts.map +1 -1
- package/dist/telegram/operator-dedupe.d.ts +44 -0
- package/dist/telegram/operator-dedupe.d.ts.map +1 -0
- package/dist/telegram/screens/callback-codec.d.ts +34 -0
- package/dist/telegram/screens/callback-codec.d.ts.map +1 -0
- package/dist/telegram/screens/dispatch.d.ts +22 -0
- package/dist/telegram/screens/dispatch.d.ts.map +1 -0
- package/dist/telegram/screens/display.d.ts +70 -0
- package/dist/telegram/screens/display.d.ts.map +1 -0
- package/dist/telegram/screens/execute.d.ts +57 -0
- package/dist/telegram/screens/execute.d.ts.map +1 -0
- package/dist/telegram/screens/html.d.ts +36 -0
- package/dist/telegram/screens/html.d.ts.map +1 -0
- package/dist/telegram/screens/outcome.d.ts +74 -0
- package/dist/telegram/screens/outcome.d.ts.map +1 -0
- package/dist/telegram/screens/path.d.ts +29 -0
- package/dist/telegram/screens/path.d.ts.map +1 -0
- package/dist/telegram/screens/reconcile.d.ts +67 -0
- package/dist/telegram/screens/reconcile.d.ts.map +1 -0
- package/dist/telegram/screens/registry.d.ts +23 -0
- package/dist/telegram/screens/registry.d.ts.map +1 -0
- package/dist/telegram/screens/render.d.ts +70 -0
- package/dist/telegram/screens/render.d.ts.map +1 -0
- package/dist/telegram/screens/runtime.d.ts +133 -0
- package/dist/telegram/screens/runtime.d.ts.map +1 -0
- package/dist/telegram/screens/screen-types.d.ts +130 -0
- package/dist/telegram/screens/screen-types.d.ts.map +1 -0
- package/dist/telegram/screens/screen.d.ts +138 -0
- package/dist/telegram/screens/screen.d.ts.map +1 -0
- package/dist/telegram/screens/state.d.ts +115 -0
- package/dist/telegram/screens/state.d.ts.map +1 -0
- package/dist/telegram/screens/telegram-screens.d.ts +18 -0
- package/dist/telegram/screens/telegram-screens.d.ts.map +1 -0
- package/dist/telegram/screens/test-chat-telegram.d.ts +47 -0
- package/dist/telegram/screens/test-chat-telegram.d.ts.map +1 -0
- package/dist/telegram/screens/test-chat.d.ts +66 -0
- package/dist/telegram/screens/test-chat.d.ts.map +1 -0
- package/dist/telegram/screens/view.d.ts +89 -0
- package/dist/telegram/screens/view.d.ts.map +1 -0
- package/dist/telegram/send-failure.d.ts +25 -0
- package/dist/telegram/send-failure.d.ts.map +1 -1
- package/dist/telegram/update-intake.d.ts +82 -0
- package/dist/telegram/update-intake.d.ts.map +1 -0
- package/dist/telegram/update-store-check.d.ts +22 -0
- package/dist/telegram/update-store-check.d.ts.map +1 -0
- package/dist/telegram/update-store-postgres.d.ts +33 -0
- package/dist/telegram/update-store-postgres.d.ts.map +1 -0
- package/dist/telegram/update-store-sqlite.d.ts +26 -0
- package/dist/telegram/update-store-sqlite.d.ts.map +1 -0
- package/dist/telegram/update-store.d.ts +67 -0
- package/dist/telegram/update-store.d.ts.map +1 -0
- package/dist/telegram/user.d.ts +51 -0
- package/dist/telegram/user.d.ts.map +1 -0
- package/dist/telegram/webhook.d.ts +105 -0
- package/dist/telegram/webhook.d.ts.map +1 -0
- package/dist/tools/cli/args-fields.d.ts +8 -0
- package/dist/tools/cli/args-fields.d.ts.map +1 -1
- package/dist/tools/cli/args-route.d.ts.map +1 -1
- package/dist/tools/cli/args.d.ts.map +1 -1
- package/dist/tools/cli/help.d.ts.map +1 -1
- package/llms/cli.txt +8 -2
- package/llms/observability.txt +15 -2
- package/llms/react-keyboard.txt +193 -0
- package/llms/server.4.txt +16 -0
- package/llms/stitchkit.txt +10 -4
- package/llms/telegram-html.txt +35 -0
- package/llms/telegram-screens.txt +365 -0
- package/llms/telegram.txt +245 -11
- package/llms/{upgrading-0.74.0-0.100.0.txt → upgrading-0.74.0-0.101.0.txt} +39 -3
- package/llms/upgrading.txt +1 -1
- package/llms-full.txt +889 -19
- package/llms.txt +12 -7
- package/package.json +17 -2
- package/dist/index-2k4yrqkc.js +0 -9
- package/dist/index-crykmqkr.js +0 -26
- package/dist/index-y64k3s0h.js +0 -150
- package/dist/index-y91ry9h2.js +0 -4
- /package/dist/{index-hffjpmq9.js → index-9jfdm5tg.js} +0 -0
- /package/dist/{index-zjjyynm3.js → index-d4pa2bgs.js} +0 -0
- /package/dist/{index-rxfy4cq7.js → index-dwfv9a85.js} +0 -0
- /package/dist/{index-5jm36zv1.js → index-gfk7nrht.js} +0 -0
- /package/dist/{index-b9aefrqd.js → index-n1dqr7gf.js} +0 -0
- /package/dist/{index-q3pyb9n0.js → index-sykb5ag7.js} +0 -0
- /package/dist/{index-48ffdxgk.js → index-xhzq2qvj.js} +0 -0
- /package/dist/{index-kzfs85xp.js → index-zsarb5xp.js} +0 -0
|
@@ -1,44 +1,44 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
} from "./index-
|
|
2
|
+
validateDeclaredOutput
|
|
3
|
+
} from "./index-b2bz0kdm.js";
|
|
4
4
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
toolResultFromError,
|
|
6
|
+
toolErrorFromResult
|
|
7
|
+
} from "./index-dvwj1f43.js";
|
|
7
8
|
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
} from "./index-bm5rx7n6.js";
|
|
9
|
+
coerceJsonArgs2
|
|
10
|
+
} from "./index-9pw0a51a.js";
|
|
11
11
|
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
} from "./index-8qt2m66q.js";
|
|
15
|
-
import {
|
|
16
|
-
coerceJsonArgs
|
|
17
|
-
} from "./index-1zbbzgfh.js";
|
|
12
|
+
jsonSchemaFields
|
|
13
|
+
} from "./index-ct75c3at.js";
|
|
18
14
|
import {
|
|
15
|
+
objectShapeKeys,
|
|
19
16
|
assertUniqueToolName,
|
|
20
|
-
buildToolPresentationSchema
|
|
21
|
-
|
|
22
|
-
} from "./index-0r0fbk7z.js";
|
|
17
|
+
buildToolPresentationSchema
|
|
18
|
+
} from "./index-7z9ym7t8.js";
|
|
23
19
|
import {
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
createToolRunner,
|
|
21
|
+
formatToolError
|
|
22
|
+
} from "./index-n9tyz8z3.js";
|
|
26
23
|
import {
|
|
27
|
-
|
|
28
|
-
} from "./index-
|
|
24
|
+
isWithinDir2
|
|
25
|
+
} from "./index-5cc6r990.js";
|
|
29
26
|
import {
|
|
30
|
-
|
|
31
|
-
} from "./index-
|
|
27
|
+
collectToolSurface
|
|
28
|
+
} from "./index-ewbaywk5.js";
|
|
29
|
+
import {
|
|
30
|
+
formatZodError2
|
|
31
|
+
} from "./index-1eeqpadm.js";
|
|
32
32
|
import {
|
|
33
33
|
isUnsafeKey,
|
|
34
34
|
safeJsonParse
|
|
35
|
-
} from "./index-
|
|
35
|
+
} from "./index-zsarb5xp.js";
|
|
36
36
|
import {
|
|
37
37
|
isRecord
|
|
38
|
-
} from "./index-
|
|
38
|
+
} from "./index-9jfdm5tg.js";
|
|
39
39
|
|
|
40
40
|
// src/tools/cli/command.ts
|
|
41
|
-
function
|
|
41
|
+
function defineCliCommand2(definition) {
|
|
42
42
|
return definition;
|
|
43
43
|
}
|
|
44
44
|
function cliCommandReturnsResult(definition) {
|
|
@@ -78,7 +78,7 @@ function cliCommandPresentationSchema(definition) {
|
|
|
78
78
|
async function executeCliCommand(definition, rawArgs, options, writers, coerceJson, globals = {}) {
|
|
79
79
|
let parsed;
|
|
80
80
|
try {
|
|
81
|
-
parsed = definition.input.safeParse(coerceJson ?
|
|
81
|
+
parsed = definition.input.safeParse(coerceJson ? coerceJsonArgs2(rawArgs, definition.input) : rawArgs);
|
|
82
82
|
} catch (error) {
|
|
83
83
|
return toolResultFromError(error);
|
|
84
84
|
}
|
|
@@ -86,7 +86,7 @@ async function executeCliCommand(definition, rawArgs, options, writers, coerceJs
|
|
|
86
86
|
return {
|
|
87
87
|
ok: false,
|
|
88
88
|
code: "VALIDATION_ERROR",
|
|
89
|
-
details: { message: `Invalid input: ${
|
|
89
|
+
details: { message: `Invalid input: ${formatZodError2(parsed.error)}` }
|
|
90
90
|
};
|
|
91
91
|
}
|
|
92
92
|
try {
|
|
@@ -111,7 +111,7 @@ async function executeCliCommand(definition, rawArgs, options, writers, coerceJs
|
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
// src/tools/cli/format.ts
|
|
114
|
-
var
|
|
114
|
+
var DEFAULT_EXIT_CODES2 = {
|
|
115
115
|
VALIDATION_ERROR: 1,
|
|
116
116
|
BAD_REQUEST: 1,
|
|
117
117
|
UNAUTHORIZED: 2,
|
|
@@ -123,18 +123,18 @@ var DEFAULT_EXIT_CODES = {
|
|
|
123
123
|
WAIT_FAILED: 1,
|
|
124
124
|
INTERNAL_SERVER_ERROR: 1
|
|
125
125
|
};
|
|
126
|
-
function
|
|
126
|
+
function cliExitCode2(result, exitCodes) {
|
|
127
127
|
if (result.ok)
|
|
128
128
|
return 0;
|
|
129
|
-
const codes = { ...
|
|
129
|
+
const codes = { ...DEFAULT_EXIT_CODES2, ...exitCodes };
|
|
130
130
|
return Object.hasOwn(codes, result.code) ? codes[result.code] ?? 1 : 1;
|
|
131
131
|
}
|
|
132
|
-
function
|
|
132
|
+
function emitResult2(result, writers, opts) {
|
|
133
133
|
if (result.ok) {
|
|
134
134
|
if (result.data === undefined)
|
|
135
135
|
return 0;
|
|
136
|
-
const
|
|
137
|
-
writers.stdout(`${
|
|
136
|
+
const text = opts.json ? JSON.stringify(result.data) : JSON.stringify(result.data, null, 2);
|
|
137
|
+
writers.stdout(`${text}
|
|
138
138
|
`);
|
|
139
139
|
return 0;
|
|
140
140
|
}
|
|
@@ -142,11 +142,11 @@ function emitResult(result, writers, opts) {
|
|
|
142
142
|
const text = opts.json ? JSON.stringify(error) : JSON.stringify(error, null, 2);
|
|
143
143
|
writers.stderr(`${text}
|
|
144
144
|
`);
|
|
145
|
-
return
|
|
145
|
+
return cliExitCode2(result, opts.exitCodes);
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
// src/tools/cli/argument-error.ts
|
|
149
|
-
class
|
|
149
|
+
class CliArgumentError2 extends Error {
|
|
150
150
|
name = "CliArgumentError";
|
|
151
151
|
}
|
|
152
152
|
|
|
@@ -230,6 +230,13 @@ function describeSchemaFields(schema) {
|
|
|
230
230
|
}
|
|
231
231
|
var TRUE_WORDS = new Set(["true", "1", "yes", "on"]);
|
|
232
232
|
var FALSE_WORDS = new Set(["false", "0", "no", "off"]);
|
|
233
|
+
function separateBoolValue(next) {
|
|
234
|
+
if (next === "true")
|
|
235
|
+
return true;
|
|
236
|
+
if (next === "false")
|
|
237
|
+
return false;
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
233
240
|
function isReservedBoolWord(value) {
|
|
234
241
|
const word = value.toLowerCase();
|
|
235
242
|
return TRUE_WORDS.has(word) || FALSE_WORDS.has(word);
|
|
@@ -240,7 +247,7 @@ function parseReservedBool(name, value) {
|
|
|
240
247
|
return true;
|
|
241
248
|
if (FALSE_WORDS.has(v))
|
|
242
249
|
return false;
|
|
243
|
-
throw new
|
|
250
|
+
throw new CliArgumentError2(`--${name} expects a boolean (true/false), got "${value}"`);
|
|
244
251
|
}
|
|
245
252
|
function coerceScalar(kind, value) {
|
|
246
253
|
switch (kind) {
|
|
@@ -295,10 +302,10 @@ function coerceNamed(label, kind, integer, value) {
|
|
|
295
302
|
const coerced = coerceScalar(kind, value);
|
|
296
303
|
const expected = expectedValue(kind, integer);
|
|
297
304
|
if (expected !== undefined && typeof coerced === "string") {
|
|
298
|
-
throw new
|
|
305
|
+
throw new CliArgumentError2(`${label} expects ${expected}, got "${value}"`);
|
|
299
306
|
}
|
|
300
307
|
if (integer && typeof coerced === "number" && !Number.isInteger(coerced)) {
|
|
301
|
-
throw new
|
|
308
|
+
throw new CliArgumentError2(`${label} expects ${expected}, got "${value}"`);
|
|
302
309
|
}
|
|
303
310
|
return coerced;
|
|
304
311
|
}
|
|
@@ -318,7 +325,7 @@ function coerceField(info, values, label) {
|
|
|
318
325
|
function setNested(target, path, value) {
|
|
319
326
|
const unsafe = path.find(isUnsafeKey);
|
|
320
327
|
if (unsafe !== undefined) {
|
|
321
|
-
throw new
|
|
328
|
+
throw new CliArgumentError2(`Unsafe option path segment "${unsafe}"`);
|
|
322
329
|
}
|
|
323
330
|
let node = target;
|
|
324
331
|
for (let i = 0;i < path.length - 1; i++) {
|
|
@@ -425,7 +432,7 @@ function parseCliGlobals(schema, globals) {
|
|
|
425
432
|
return globals ?? {};
|
|
426
433
|
return schema.parse(globals ?? {});
|
|
427
434
|
}
|
|
428
|
-
function
|
|
435
|
+
function cliInvocationResult2(result, toolName, config) {
|
|
429
436
|
if (result.ok)
|
|
430
437
|
return { ok: true, exitCode: 0, data: result.data };
|
|
431
438
|
const normalized = toolErrorFromResult(result);
|
|
@@ -437,7 +444,7 @@ function cliInvocationResult(result, toolName, config) {
|
|
|
437
444
|
hints.push(global);
|
|
438
445
|
return {
|
|
439
446
|
ok: false,
|
|
440
|
-
exitCode:
|
|
447
|
+
exitCode: cliExitCode2(result, config.exitCodes),
|
|
441
448
|
error: {
|
|
442
449
|
code: result.code,
|
|
443
450
|
message: normalized.message,
|
|
@@ -447,7 +454,7 @@ function cliInvocationResult(result, toolName, config) {
|
|
|
447
454
|
}
|
|
448
455
|
};
|
|
449
456
|
}
|
|
450
|
-
async function
|
|
457
|
+
async function createCliInvoker2(config, globals) {
|
|
451
458
|
const typedGlobals = parseCliGlobals(config.globalOptions, globals);
|
|
452
459
|
const auth = await (config.resolveAuth ? config.resolveAuth(typedGlobals) : config.auth);
|
|
453
460
|
const natives = new Map((config.commands ?? []).filter(cliCommandReturnsResult).map((definition) => [definition.name, definition]));
|
|
@@ -475,7 +482,7 @@ async function createCliInvoker(config, globals) {
|
|
|
475
482
|
return runNativeCommand(native, args, config, typedGlobals);
|
|
476
483
|
const tool = tools.get(command);
|
|
477
484
|
if (!tool) {
|
|
478
|
-
return
|
|
485
|
+
return cliInvocationResult2({
|
|
479
486
|
ok: false,
|
|
480
487
|
code: "NOT_FOUND",
|
|
481
488
|
details: { message: `Unknown command "${command}"` }
|
|
@@ -487,7 +494,7 @@ async function createCliInvoker(config, globals) {
|
|
|
487
494
|
} catch (error) {
|
|
488
495
|
result = toolResultFromError(error);
|
|
489
496
|
}
|
|
490
|
-
return
|
|
497
|
+
return cliInvocationResult2(result, command, config);
|
|
491
498
|
}
|
|
492
499
|
};
|
|
493
500
|
}
|
|
@@ -509,7 +516,7 @@ async function runNativeCommand(definition, args, config, globals) {
|
|
|
509
516
|
err += text;
|
|
510
517
|
}
|
|
511
518
|
}, config.coerceJsonArgs ?? true, globals);
|
|
512
|
-
let invocation =
|
|
519
|
+
let invocation = cliInvocationResult2(result, definition.name, config);
|
|
513
520
|
if (invocation.ok) {
|
|
514
521
|
try {
|
|
515
522
|
invocation = {
|
|
@@ -517,7 +524,7 @@ async function runNativeCommand(definition, args, config, globals) {
|
|
|
517
524
|
exitCode: cliCommandSuccessExitCode(definition, result.ok ? result.data : undefined)
|
|
518
525
|
};
|
|
519
526
|
} catch (error) {
|
|
520
|
-
invocation =
|
|
527
|
+
invocation = cliInvocationResult2(toolResultFromError(error), definition.name, config);
|
|
521
528
|
}
|
|
522
529
|
}
|
|
523
530
|
if (out === "" && err === "")
|
|
@@ -588,7 +595,7 @@ function helpFilterFrom(token, rest) {
|
|
|
588
595
|
const next = rest[0];
|
|
589
596
|
return next !== undefined && !next.startsWith("-") ? next : undefined;
|
|
590
597
|
}
|
|
591
|
-
function
|
|
598
|
+
function routeCliArgv2(argv, defaultCommand) {
|
|
592
599
|
if (defaultCommand === undefined) {
|
|
593
600
|
const [command, ...commandArgv] = argv;
|
|
594
601
|
const helpFilter = helpFilterFrom(command, commandArgv);
|
|
@@ -655,6 +662,11 @@ function routeCliArgv(argv, defaultCommand) {
|
|
|
655
662
|
if (option.globalKind === "boolean") {
|
|
656
663
|
globals.push(token);
|
|
657
664
|
index += 1;
|
|
665
|
+
const next = argv[index];
|
|
666
|
+
if (option.value === undefined && next !== undefined && separateBoolValue(next) !== undefined) {
|
|
667
|
+
globals.push(next);
|
|
668
|
+
index += 1;
|
|
669
|
+
}
|
|
658
670
|
continue;
|
|
659
671
|
}
|
|
660
672
|
if (option.globalKind === "value") {
|
|
@@ -700,7 +712,7 @@ function routeCliArgv(argv, defaultCommand) {
|
|
|
700
712
|
function resolveCliView(flags, ascending) {
|
|
701
713
|
if (flags.size === 0) {
|
|
702
714
|
if (ascending) {
|
|
703
|
-
throw new
|
|
715
|
+
throw new CliArgumentError2("--ascending orders a record view; pass --sort with it");
|
|
704
716
|
}
|
|
705
717
|
return;
|
|
706
718
|
}
|
|
@@ -714,31 +726,31 @@ function resolveCliView(flags, ascending) {
|
|
|
714
726
|
["--sum", sum]
|
|
715
727
|
].filter(([, value]) => value !== undefined);
|
|
716
728
|
if (named.length > 1) {
|
|
717
|
-
throw new
|
|
729
|
+
throw new CliArgumentError2(`${named.map(([flag]) => flag).join(" and ")} ask for different shapes — pass one`);
|
|
718
730
|
}
|
|
719
731
|
let top;
|
|
720
732
|
if (rawTop !== undefined) {
|
|
721
733
|
top = Number(rawTop);
|
|
722
734
|
if (!Number.isInteger(top) || top <= 0) {
|
|
723
|
-
throw new
|
|
735
|
+
throw new CliArgumentError2("--top must be a positive whole number");
|
|
724
736
|
}
|
|
725
737
|
}
|
|
726
738
|
const sort = flags.get("sort");
|
|
727
739
|
if (table !== undefined || sort !== undefined) {
|
|
728
740
|
if (countBy !== undefined || sum !== undefined) {
|
|
729
|
-
throw new
|
|
741
|
+
throw new CliArgumentError2(`${table !== undefined ? "--table" : "--sort"} lists records; --count-by and --sum aggregate them — pass one`);
|
|
730
742
|
}
|
|
731
743
|
if (by !== undefined) {
|
|
732
|
-
throw new
|
|
744
|
+
throw new CliArgumentError2("--by groups a view; a record view orders with --sort");
|
|
733
745
|
}
|
|
734
746
|
if (top !== undefined && sort === undefined) {
|
|
735
|
-
throw new
|
|
747
|
+
throw new CliArgumentError2("--top needs --sort here: unordered records have no n largest");
|
|
736
748
|
}
|
|
737
749
|
let fields;
|
|
738
750
|
if (table !== undefined) {
|
|
739
751
|
fields = table.split(",").map((field) => field.trim()).filter(Boolean);
|
|
740
752
|
if (fields.length === 0)
|
|
741
|
-
throw new
|
|
753
|
+
throw new CliArgumentError2("--table needs at least one field");
|
|
742
754
|
}
|
|
743
755
|
return {
|
|
744
756
|
kind: "records",
|
|
@@ -749,11 +761,11 @@ function resolveCliView(flags, ascending) {
|
|
|
749
761
|
};
|
|
750
762
|
}
|
|
751
763
|
if (ascending) {
|
|
752
|
-
throw new
|
|
764
|
+
throw new CliArgumentError2("--ascending orders a record view; pass --sort with it");
|
|
753
765
|
}
|
|
754
766
|
if (sum !== undefined) {
|
|
755
767
|
if (top !== undefined && by === undefined) {
|
|
756
|
-
throw new
|
|
768
|
+
throw new CliArgumentError2("--top needs --by: a single sum has nothing to rank");
|
|
757
769
|
}
|
|
758
770
|
return {
|
|
759
771
|
kind: "sum",
|
|
@@ -764,17 +776,17 @@ function resolveCliView(flags, ascending) {
|
|
|
764
776
|
}
|
|
765
777
|
if (countBy !== undefined) {
|
|
766
778
|
if (by !== undefined) {
|
|
767
|
-
throw new
|
|
779
|
+
throw new CliArgumentError2("--count-by already names the grouping field; drop --by");
|
|
768
780
|
}
|
|
769
781
|
return { kind: "count", field: countBy, ...top !== undefined && { top } };
|
|
770
782
|
}
|
|
771
783
|
if (by !== undefined) {
|
|
772
784
|
if (top === undefined) {
|
|
773
|
-
throw new
|
|
785
|
+
throw new CliArgumentError2("--by groups a view; pass --count-by, --sum or --top with it");
|
|
774
786
|
}
|
|
775
787
|
return { kind: "count", field: by, top };
|
|
776
788
|
}
|
|
777
|
-
throw new
|
|
789
|
+
throw new CliArgumentError2("--top needs --sort, --by, --count-by or --sum to rank");
|
|
778
790
|
}
|
|
779
791
|
|
|
780
792
|
// src/tools/cli/args.ts
|
|
@@ -820,35 +832,41 @@ function readCliTokens(argv, fields, config) {
|
|
|
820
832
|
const alias = match?.[1];
|
|
821
833
|
const field = alias === undefined ? undefined : config.optionAliases?.get(alias);
|
|
822
834
|
if (!alias || !field)
|
|
823
|
-
throw new
|
|
835
|
+
throw new CliArgumentError2(`Unknown option "${tok}"`);
|
|
824
836
|
const inline = match?.[2];
|
|
825
|
-
const
|
|
826
|
-
if (
|
|
827
|
-
|
|
837
|
+
const info = fields.get(field);
|
|
838
|
+
if (info?.kind === "boolean") {
|
|
839
|
+
const separate = inline === undefined ? separateBoolValue(argv[i + 1]) : undefined;
|
|
840
|
+
if (separate !== undefined)
|
|
841
|
+
i++;
|
|
842
|
+
boolFlags.set(field, inline === undefined ? separate ?? true : parseReservedBool(field, inline));
|
|
828
843
|
continue;
|
|
829
844
|
}
|
|
830
|
-
let
|
|
831
|
-
if (
|
|
845
|
+
let value = inline;
|
|
846
|
+
if (value === undefined) {
|
|
832
847
|
const next = argv[i + 1];
|
|
833
848
|
if (next !== undefined && !isOptionToken(next)) {
|
|
834
|
-
|
|
849
|
+
value = next;
|
|
835
850
|
i++;
|
|
836
851
|
} else {
|
|
837
|
-
throw new
|
|
852
|
+
throw new CliArgumentError2(`--${field} requires a value`);
|
|
838
853
|
}
|
|
839
854
|
}
|
|
840
|
-
pushFlag(field,
|
|
855
|
+
pushFlag(field, value);
|
|
841
856
|
continue;
|
|
842
857
|
}
|
|
843
858
|
const option = classifyLongOptionToken(tok);
|
|
844
859
|
if (!option)
|
|
845
|
-
throw new
|
|
860
|
+
throw new CliArgumentError2(`Unknown option "${tok}"`);
|
|
846
861
|
const { name } = option;
|
|
847
862
|
let { value } = option;
|
|
848
863
|
if (name.length === 0)
|
|
849
|
-
throw new
|
|
864
|
+
throw new CliArgumentError2("Invalid empty option name");
|
|
850
865
|
if (option.globalKind === "boolean") {
|
|
851
|
-
const
|
|
866
|
+
const separate = value === undefined ? separateBoolValue(argv[i + 1]) : undefined;
|
|
867
|
+
if (separate !== undefined)
|
|
868
|
+
i++;
|
|
869
|
+
const enabled = value === undefined ? separate ?? true : parseReservedBool(name, value);
|
|
852
870
|
if (name === "dry-run")
|
|
853
871
|
options.dryRun = enabled;
|
|
854
872
|
else if (name === "json")
|
|
@@ -867,19 +885,19 @@ function readCliTokens(argv, fields, config) {
|
|
|
867
885
|
const next = argv[i + 1];
|
|
868
886
|
value = value ?? next;
|
|
869
887
|
if (value === undefined || !option.inline && isOptionToken(value)) {
|
|
870
|
-
throw new
|
|
888
|
+
throw new CliArgumentError2(`--${name} requires a value`);
|
|
871
889
|
}
|
|
872
890
|
if (!option.inline)
|
|
873
891
|
i++;
|
|
874
892
|
if (name === "wait-timeout") {
|
|
875
893
|
const timeout = Number(value);
|
|
876
894
|
if (!Number.isFinite(timeout) || timeout <= 0) {
|
|
877
|
-
throw new
|
|
895
|
+
throw new CliArgumentError2("--wait-timeout must be a positive number");
|
|
878
896
|
}
|
|
879
897
|
options.waitTimeout = timeout;
|
|
880
898
|
} else if (VIEW_OPTIONS.has(name)) {
|
|
881
899
|
if (viewFlags.has(name))
|
|
882
|
-
throw new
|
|
900
|
+
throw new CliArgumentError2(`--${name} was given twice`);
|
|
883
901
|
viewFlags.set(name, value);
|
|
884
902
|
} else {
|
|
885
903
|
options.outputDir = value;
|
|
@@ -892,16 +910,19 @@ function readCliTokens(argv, fields, config) {
|
|
|
892
910
|
}
|
|
893
911
|
const unsafeSegment = name.split(".").find(isUnsafeKey);
|
|
894
912
|
if (unsafeSegment !== undefined) {
|
|
895
|
-
throw new
|
|
913
|
+
throw new CliArgumentError2(`Unsafe option name "--${name}"`);
|
|
896
914
|
}
|
|
897
915
|
const info = fields.get(name);
|
|
898
916
|
const rootName = name.split(".")[0] ?? name;
|
|
899
917
|
if (!fields.has(rootName) && !config.allowUnknown) {
|
|
900
|
-
throw new
|
|
918
|
+
throw new CliArgumentError2(`Unknown option "--${name}"`);
|
|
901
919
|
}
|
|
902
920
|
if (value === undefined) {
|
|
903
921
|
if (info?.kind === "boolean") {
|
|
904
|
-
|
|
922
|
+
const separate = separateBoolValue(argv[i + 1]);
|
|
923
|
+
if (separate !== undefined)
|
|
924
|
+
i++;
|
|
925
|
+
boolFlags.set(name, separate ?? true);
|
|
905
926
|
continue;
|
|
906
927
|
}
|
|
907
928
|
const next = argv[i + 1];
|
|
@@ -909,7 +930,7 @@ function readCliTokens(argv, fields, config) {
|
|
|
909
930
|
value = next;
|
|
910
931
|
i++;
|
|
911
932
|
} else {
|
|
912
|
-
throw new
|
|
933
|
+
throw new CliArgumentError2(`--${name} requires a value`);
|
|
913
934
|
}
|
|
914
935
|
}
|
|
915
936
|
pushFlag(name, value);
|
|
@@ -927,7 +948,7 @@ function buildToolArgs(tokens, fields, declaredPositionals) {
|
|
|
927
948
|
break;
|
|
928
949
|
if (key === variadicTail) {
|
|
929
950
|
if (flags.has(key)) {
|
|
930
|
-
throw new
|
|
951
|
+
throw new CliArgumentError2(`--${key} conflicts with the positional values for "${key}" — pass one form, not both`);
|
|
931
952
|
}
|
|
932
953
|
toolArgs[key] = coerceField(fields.get(key), positionals.slice(pi), `<${key}>`);
|
|
933
954
|
pi = positionals.length;
|
|
@@ -941,7 +962,7 @@ function buildToolArgs(tokens, fields, declaredPositionals) {
|
|
|
941
962
|
}
|
|
942
963
|
}
|
|
943
964
|
if (pi < positionals.length) {
|
|
944
|
-
throw new
|
|
965
|
+
throw new CliArgumentError2(`Unexpected positional argument "${positionals[pi]}"`);
|
|
945
966
|
}
|
|
946
967
|
for (const [key, value] of boolFlags) {
|
|
947
968
|
toolArgs[key] = value;
|
|
@@ -954,26 +975,26 @@ function buildToolArgs(tokens, fields, declaredPositionals) {
|
|
|
954
975
|
}
|
|
955
976
|
for (const [root, dotted] of dottedRoots) {
|
|
956
977
|
if (flags.has(root)) {
|
|
957
|
-
throw new
|
|
978
|
+
throw new CliArgumentError2(`--${root} conflicts with --${dotted} — pass one form, not both`);
|
|
958
979
|
}
|
|
959
980
|
}
|
|
960
981
|
for (const [key, values] of flags) {
|
|
961
982
|
if (key.includes(".")) {
|
|
962
983
|
if (values.length > 1) {
|
|
963
|
-
throw new
|
|
984
|
+
throw new CliArgumentError2(`--${key} was passed ${values.length} times`);
|
|
964
985
|
}
|
|
965
986
|
setNested(toolArgs, key.split("."), looseCoerce(values[0] ?? ""));
|
|
966
987
|
continue;
|
|
967
988
|
}
|
|
968
989
|
const info = fields.get(key);
|
|
969
990
|
if (values.length > 1 && info !== undefined && info.kind !== "array" && info.kind !== "other") {
|
|
970
|
-
throw new
|
|
991
|
+
throw new CliArgumentError2(`--${key} was passed ${values.length} times`);
|
|
971
992
|
}
|
|
972
993
|
toolArgs[key] = coerceField(info, values, `--${key}`);
|
|
973
994
|
}
|
|
974
995
|
return toolArgs;
|
|
975
996
|
}
|
|
976
|
-
function
|
|
997
|
+
function parseCliArgs2(argv, schema, config = {}) {
|
|
977
998
|
const fields = describeSchemaFields(schema);
|
|
978
999
|
for (const name of config.knownFields ?? []) {
|
|
979
1000
|
if (!fields.has(name))
|
|
@@ -986,7 +1007,7 @@ function parseCliArgs(argv, schema, config = {}) {
|
|
|
986
1007
|
options.view = view;
|
|
987
1008
|
return { toolArgs: buildToolArgs(tokens, fields, config.positionals), options };
|
|
988
1009
|
}
|
|
989
|
-
function
|
|
1010
|
+
function extractCliGlobalOptions2(argv, schema) {
|
|
990
1011
|
if (schema === undefined)
|
|
991
1012
|
return { argv: [...argv], globals: {} };
|
|
992
1013
|
const fields = describeSchemaFields(schema);
|
|
@@ -1007,14 +1028,17 @@ function extractCliGlobalOptions(argv, schema) {
|
|
|
1007
1028
|
}
|
|
1008
1029
|
let { value } = option;
|
|
1009
1030
|
if (value === undefined && info.kind === "boolean") {
|
|
1010
|
-
|
|
1031
|
+
const separate = separateBoolValue(argv[i + 1]);
|
|
1032
|
+
if (separate !== undefined)
|
|
1033
|
+
i++;
|
|
1034
|
+
value = String(separate ?? true);
|
|
1011
1035
|
} else if (value === undefined) {
|
|
1012
1036
|
const next = argv[i + 1];
|
|
1013
1037
|
if (next !== undefined && !isOptionToken(next)) {
|
|
1014
1038
|
value = next;
|
|
1015
1039
|
i++;
|
|
1016
1040
|
} else {
|
|
1017
|
-
throw new
|
|
1041
|
+
throw new CliArgumentError2(`--${option.name} requires a value`);
|
|
1018
1042
|
}
|
|
1019
1043
|
}
|
|
1020
1044
|
const existing = raw.get(option.name);
|
|
@@ -1027,12 +1051,12 @@ function extractCliGlobalOptions(argv, schema) {
|
|
|
1027
1051
|
for (const [name, values] of raw) {
|
|
1028
1052
|
args[name] = coerceField(fields.get(name), values, `--${name}`);
|
|
1029
1053
|
}
|
|
1030
|
-
const parsed = schema.safeParse(
|
|
1054
|
+
const parsed = schema.safeParse(coerceJsonArgs2(args, schema));
|
|
1031
1055
|
if (!parsed.success) {
|
|
1032
1056
|
const issue = parsed.error.issues[0];
|
|
1033
1057
|
const field = issue?.path[0];
|
|
1034
1058
|
const where = typeof field === "string" ? `--${field}` : "application option";
|
|
1035
|
-
throw new
|
|
1059
|
+
throw new CliArgumentError2(`${where}: ${issue?.message ?? "invalid value"}`);
|
|
1036
1060
|
}
|
|
1037
1061
|
return { argv: rest, globals: parsed.data };
|
|
1038
1062
|
}
|
|
@@ -1048,10 +1072,10 @@ function selectRecords(data) {
|
|
|
1048
1072
|
if (arrays.length === 1 && only && Array.isArray(only[1]))
|
|
1049
1073
|
return only[1];
|
|
1050
1074
|
if (arrays.length > 1) {
|
|
1051
|
-
throw new
|
|
1075
|
+
throw new CliArgumentError2(`an aggregate needs one collection, but the result carries several: ${arrays.map(([key]) => key).join(", ")} — name the shape you want with jq instead`);
|
|
1052
1076
|
}
|
|
1053
1077
|
}
|
|
1054
|
-
throw new
|
|
1078
|
+
throw new CliArgumentError2("an aggregate needs a collection; this result is not one");
|
|
1055
1079
|
}
|
|
1056
1080
|
function readField(record, path) {
|
|
1057
1081
|
let current = record;
|
|
@@ -1065,7 +1089,7 @@ function readField(record, path) {
|
|
|
1065
1089
|
function fieldPath(field) {
|
|
1066
1090
|
const path = field.split(".");
|
|
1067
1091
|
if (path.some((segment) => segment.length === 0 || isUnsafeKey(segment))) {
|
|
1068
|
-
throw new
|
|
1092
|
+
throw new CliArgumentError2(`"${field}" is not a readable field path`);
|
|
1069
1093
|
}
|
|
1070
1094
|
return path;
|
|
1071
1095
|
}
|
|
@@ -1083,7 +1107,7 @@ function assertFieldPresent(records, field) {
|
|
|
1083
1107
|
const present = records.some((record) => readField(record, path) !== undefined);
|
|
1084
1108
|
if (!present) {
|
|
1085
1109
|
const available = availableFields(records);
|
|
1086
|
-
throw new
|
|
1110
|
+
throw new CliArgumentError2(`no record carries the field "${field}"${available.length > 0 ? ` — available: ${available.join(", ")}` : ""}`);
|
|
1087
1111
|
}
|
|
1088
1112
|
return path;
|
|
1089
1113
|
}
|
|
@@ -1108,7 +1132,7 @@ function numericValue(value, field) {
|
|
|
1108
1132
|
return value;
|
|
1109
1133
|
if (typeof value === "bigint")
|
|
1110
1134
|
return Number(value);
|
|
1111
|
-
throw new
|
|
1135
|
+
throw new CliArgumentError2(`--sum ${field}: "${groupKey(value)}" is not a number`);
|
|
1112
1136
|
}
|
|
1113
1137
|
function renderTable(records, fields) {
|
|
1114
1138
|
const paths = fields.map((field) => assertFieldPresent(records, field));
|
|
@@ -1155,18 +1179,18 @@ function renderRecords(records, view) {
|
|
|
1155
1179
|
selected = selected.slice(0, view.top);
|
|
1156
1180
|
return view.table ? { kind: "text", text: renderTable(selected, view.table) } : { kind: "json", data: selected };
|
|
1157
1181
|
}
|
|
1158
|
-
function
|
|
1182
|
+
function renderCliView2(data, view) {
|
|
1159
1183
|
const records = selectRecords(data);
|
|
1160
1184
|
if (view.kind === "records")
|
|
1161
1185
|
return renderRecords(records, view);
|
|
1162
1186
|
if (view.kind === "count") {
|
|
1163
|
-
const
|
|
1164
|
-
const
|
|
1187
|
+
const path = assertFieldPresent(records, view.field);
|
|
1188
|
+
const totals = new Map;
|
|
1165
1189
|
for (const record of records) {
|
|
1166
|
-
const key = groupKey(readField(record,
|
|
1167
|
-
|
|
1190
|
+
const key = groupKey(readField(record, path));
|
|
1191
|
+
totals.set(key, (totals.get(key) ?? 0) + 1);
|
|
1168
1192
|
}
|
|
1169
|
-
return { kind: "json", data: ordered(
|
|
1193
|
+
return { kind: "json", data: ordered(totals, view.top) };
|
|
1170
1194
|
}
|
|
1171
1195
|
const path = assertFieldPresent(records, view.field);
|
|
1172
1196
|
if (view.by === undefined) {
|
|
@@ -1292,7 +1316,7 @@ function waitFailure(tool, result) {
|
|
|
1292
1316
|
}
|
|
1293
1317
|
};
|
|
1294
1318
|
}
|
|
1295
|
-
async function
|
|
1319
|
+
async function pollUntilDone2(params) {
|
|
1296
1320
|
const { initial, wait, call } = params;
|
|
1297
1321
|
if (!initial.ok)
|
|
1298
1322
|
return initial;
|
|
@@ -1609,8 +1633,8 @@ async function resolvePublicAddress(url, signal) {
|
|
|
1609
1633
|
}
|
|
1610
1634
|
const pending = lookup(host, { all: true });
|
|
1611
1635
|
const records = signal ? await raceWithAbort(pending, signal) : await pending;
|
|
1612
|
-
for (const
|
|
1613
|
-
if (isPrivateIp(
|
|
1636
|
+
for (const record of records) {
|
|
1637
|
+
if (isPrivateIp(record.address)) {
|
|
1614
1638
|
throw new PrivateAddressRefusal("refusing to fetch a host that resolves to a private address");
|
|
1615
1639
|
}
|
|
1616
1640
|
}
|
|
@@ -1727,7 +1751,7 @@ async function readCapped(res, max) {
|
|
|
1727
1751
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
1728
1752
|
import { dirname } from "node:path";
|
|
1729
1753
|
async function writeDownload(root, target, data) {
|
|
1730
|
-
if (!
|
|
1754
|
+
if (!isWithinDir2(root, target)) {
|
|
1731
1755
|
throw new Error("download name escapes the output dir");
|
|
1732
1756
|
}
|
|
1733
1757
|
await mkdir(dirname(target), { recursive: true });
|
|
@@ -1882,6 +1906,10 @@ function renderCommandHelp(name, command, descriptor, applicationOptions = []) {
|
|
|
1882
1906
|
const label = labels.get(f.name) ?? `--${f.name}`;
|
|
1883
1907
|
lines.push(` ${padRight(label, width)} <${typeLabel(f.schema)}>${req}${desc}`);
|
|
1884
1908
|
}
|
|
1909
|
+
const flag = [...kinds].find(([, info]) => info.kind === "boolean")?.[0];
|
|
1910
|
+
if (flag !== undefined) {
|
|
1911
|
+
lines.push("", `A boolean flag is on alone or takes true/false: --${flag}, --${flag} false, --no-${flag}`);
|
|
1912
|
+
}
|
|
1885
1913
|
lines.push("");
|
|
1886
1914
|
}
|
|
1887
1915
|
const applicationLines = applicationOptionLines(applicationOptions);
|
|
@@ -1955,11 +1983,11 @@ function resolveCliRoute(session, argv) {
|
|
|
1955
1983
|
let globals;
|
|
1956
1984
|
let routableArgv;
|
|
1957
1985
|
try {
|
|
1958
|
-
const lifted =
|
|
1986
|
+
const lifted = extractCliGlobalOptions2(argv, config.globalOptions);
|
|
1959
1987
|
globals = lifted.globals;
|
|
1960
1988
|
routableArgv = lifted.argv;
|
|
1961
1989
|
} catch (error) {
|
|
1962
|
-
if (!(error instanceof
|
|
1990
|
+
if (!(error instanceof CliArgumentError2))
|
|
1963
1991
|
throw error;
|
|
1964
1992
|
stderr(`${error.message}
|
|
1965
1993
|
`);
|
|
@@ -1967,7 +1995,7 @@ function resolveCliRoute(session, argv) {
|
|
|
1967
1995
|
return;
|
|
1968
1996
|
}
|
|
1969
1997
|
const typedGlobals = globals;
|
|
1970
|
-
const route =
|
|
1998
|
+
const route = routeCliArgv2(routableArgv, config.defaultCommand);
|
|
1971
1999
|
if (route.error) {
|
|
1972
2000
|
stderr(`${route.error}
|
|
1973
2001
|
`);
|
|
@@ -1998,7 +2026,7 @@ function emitOptionsFor(config, json, toolName) {
|
|
|
1998
2026
|
json,
|
|
1999
2027
|
toolName,
|
|
2000
2028
|
errorHint: config.errorHint,
|
|
2001
|
-
exitCodes: { ...
|
|
2029
|
+
exitCodes: { ...DEFAULT_EXIT_CODES2, ...config.exitCodes }
|
|
2002
2030
|
};
|
|
2003
2031
|
}
|
|
2004
2032
|
|
|
@@ -2072,14 +2100,14 @@ function collectPassthrough(toolArgs, field, knownKeys) {
|
|
|
2072
2100
|
async function prepareInvocation(command, commandArgv, descriptor, config, readStdin) {
|
|
2073
2101
|
let parsed;
|
|
2074
2102
|
try {
|
|
2075
|
-
parsed =
|
|
2103
|
+
parsed = parseCliArgs2(commandArgv, descriptor.argumentSchema, {
|
|
2076
2104
|
allowUnknown: config.passthrough?.[command] !== undefined,
|
|
2077
2105
|
knownFields: jsonSchemaFields(descriptor.presentationSchema).map((field) => field.name),
|
|
2078
2106
|
optionAliases: new Map([...descriptor.aliases].map(([field, alias]) => [alias, field])),
|
|
2079
2107
|
positionals: descriptor.positionals
|
|
2080
2108
|
});
|
|
2081
2109
|
} catch (error) {
|
|
2082
|
-
if (!(error instanceof
|
|
2110
|
+
if (!(error instanceof CliArgumentError2))
|
|
2083
2111
|
throw error;
|
|
2084
2112
|
return { ok: false, message: error.message };
|
|
2085
2113
|
}
|
|
@@ -2091,7 +2119,7 @@ async function prepareInvocation(command, commandArgv, descriptor, config, readS
|
|
|
2091
2119
|
if (descriptor.positionals === undefined) {
|
|
2092
2120
|
toolArgs[firstUnset.name] = piped;
|
|
2093
2121
|
} else {
|
|
2094
|
-
const stdinArgs =
|
|
2122
|
+
const stdinArgs = parseCliArgs2([`--${firstUnset.name}`, piped], descriptor.argumentSchema);
|
|
2095
2123
|
toolArgs[firstUnset.name] = stdinArgs.toolArgs[firstUnset.name];
|
|
2096
2124
|
}
|
|
2097
2125
|
}
|
|
@@ -2113,7 +2141,7 @@ async function runManagedInvocation(session, route) {
|
|
|
2113
2141
|
if (topLevelHelp)
|
|
2114
2142
|
return respondTopLevelHelp(session, route, managed);
|
|
2115
2143
|
if (!managed.resolved) {
|
|
2116
|
-
return exit(
|
|
2144
|
+
return exit(emitResult2(managed.failure, { stdout, stderr }, emitOptionsFor(config, beforeSeparator.includes("--json"), command ?? config.name)));
|
|
2117
2145
|
}
|
|
2118
2146
|
return runManagedCommand(session, route, command, managed);
|
|
2119
2147
|
}
|
|
@@ -2127,7 +2155,7 @@ function respondTopLevelHelp(session, route, managed) {
|
|
|
2127
2155
|
stderr(`no command matches "${filter}" (${managed.help.size} available)
|
|
2128
2156
|
` + (managed.resolved ? "" : `Managed commands are unavailable: ${managed.reason}
|
|
2129
2157
|
`));
|
|
2130
|
-
const codes = { ...
|
|
2158
|
+
const codes = { ...DEFAULT_EXIT_CODES2, ...config.exitCodes };
|
|
2131
2159
|
exit(codes.NOT_FOUND ?? 4);
|
|
2132
2160
|
return;
|
|
2133
2161
|
}
|
|
@@ -2214,7 +2242,7 @@ async function executeManagedTool(session, route, command, managed, tool, { tool
|
|
|
2214
2242
|
}
|
|
2215
2243
|
const waitConfig = config.wait?.[command];
|
|
2216
2244
|
if (options.wait && waitConfig) {
|
|
2217
|
-
result = await
|
|
2245
|
+
result = await pollUntilDone2({
|
|
2218
2246
|
initial: result,
|
|
2219
2247
|
wait: waitConfig,
|
|
2220
2248
|
call: async (toolName, args) => {
|
|
@@ -2247,9 +2275,9 @@ async function emitManagedResult(session, command, initial, options) {
|
|
|
2247
2275
|
if (options.view && result.ok) {
|
|
2248
2276
|
let viewed;
|
|
2249
2277
|
try {
|
|
2250
|
-
viewed =
|
|
2278
|
+
viewed = renderCliView2(result.data, options.view);
|
|
2251
2279
|
} catch (error) {
|
|
2252
|
-
if (!(error instanceof
|
|
2280
|
+
if (!(error instanceof CliArgumentError2))
|
|
2253
2281
|
throw error;
|
|
2254
2282
|
stderr(`${error.message}
|
|
2255
2283
|
`);
|
|
@@ -2261,7 +2289,7 @@ async function emitManagedResult(session, command, initial, options) {
|
|
|
2261
2289
|
}
|
|
2262
2290
|
result = { ...result, data: viewed.data };
|
|
2263
2291
|
}
|
|
2264
|
-
const exitCode =
|
|
2292
|
+
const exitCode = emitResult2(result, { stdout, stderr }, emitOptionsFor(config, options.json, command));
|
|
2265
2293
|
return exit(downloadsOk ? exitCode : 1);
|
|
2266
2294
|
}
|
|
2267
2295
|
|
|
@@ -2315,13 +2343,13 @@ async function runNativeCommand2(session, route, command, native) {
|
|
|
2315
2343
|
stdout(emission.presentation);
|
|
2316
2344
|
emittedExitCode = 0;
|
|
2317
2345
|
} else {
|
|
2318
|
-
emittedExitCode =
|
|
2346
|
+
emittedExitCode = emitResult2(emission.result, { stdout, stderr }, emitOptionsFor(config, options.json, command));
|
|
2319
2347
|
}
|
|
2320
2348
|
return exit(emission.result.ok ? emission.successExitCode : emittedExitCode);
|
|
2321
2349
|
}
|
|
2322
2350
|
|
|
2323
2351
|
// src/tools/cli/create-cli.ts
|
|
2324
|
-
async function
|
|
2352
|
+
async function createCli2(config) {
|
|
2325
2353
|
const io = createCliIo(config);
|
|
2326
2354
|
const argv = config.argv ?? process.argv.slice(2);
|
|
2327
2355
|
if (config.auth !== undefined && config.resolveAuth !== undefined) {
|
|
@@ -2339,4 +2367,4 @@ async function createCli(config) {
|
|
|
2339
2367
|
return runManagedInvocation(session, route);
|
|
2340
2368
|
}
|
|
2341
2369
|
|
|
2342
|
-
export { fetchGuarded, PrivateAddressRefusal, fetchPinnedDocument, readCapped, WaitTimeoutError, runWaitOperation,
|
|
2370
|
+
export { fetchGuarded, PrivateAddressRefusal, fetchPinnedDocument, readCapped, WaitTimeoutError, runWaitOperation, defineCliCommand2, DEFAULT_EXIT_CODES2, cliExitCode2, emitResult2, CliArgumentError2, cliInvocationResult2, createCliInvoker2, routeCliArgv2, parseCliArgs2, extractCliGlobalOptions2, renderCliView2, pollUntilDone2, createCli2 };
|