stitchkit 0.110.4 → 0.110.6

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.
Files changed (44) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/agent-runtime/branch-observations.d.ts +16 -16
  3. package/dist/entrypoints/agent-runtime/coding-tools.js +2 -2
  4. package/dist/entrypoints/agent-runtime/sandbox.js +2 -2
  5. package/dist/entrypoints/agent-runtime/sqlite/bun.js +4 -4
  6. package/dist/entrypoints/agent-runtime/sqlite/node.js +4 -4
  7. package/dist/entrypoints/agent-runtime/testing.js +4 -4
  8. package/dist/entrypoints/agent-runtime.js +4 -4
  9. package/dist/entrypoints/cli.js +1 -1
  10. package/dist/entrypoints/process.js +1 -1
  11. package/dist/entrypoints/server.d.ts +1 -0
  12. package/dist/entrypoints/server.d.ts.map +1 -1
  13. package/dist/entrypoints/server.js +55 -3
  14. package/dist/entrypoints/tools.js +1 -1
  15. package/dist/{index-mpg1t7nv.js → index-0z3kfphz.js} +1 -1
  16. package/dist/{index-5pbtbce0.js → index-7c957abz.js} +1 -1
  17. package/dist/{index-e1sjcjfy.js → index-7r4knwf8.js} +94 -23
  18. package/dist/{index-bm180f2d.js → index-ey15wx6j.js} +1 -1
  19. package/dist/{index-9ket8wzx.js → index-mnk5vgdr.js} +1 -1
  20. package/dist/{index-2tazbwhv.js → index-n7hrpngg.js} +151 -92
  21. package/dist/process/group-diagnostics.d.ts +20 -0
  22. package/dist/process/group-diagnostics.d.ts.map +1 -0
  23. package/dist/process/group-settlement.d.ts +1 -1
  24. package/dist/process/group-settlement.d.ts.map +1 -1
  25. package/dist/process/group.d.ts.map +1 -1
  26. package/dist/server/bun.d.ts +9 -0
  27. package/dist/server/bun.d.ts.map +1 -1
  28. package/dist/server/proxy-origin.d.ts +12 -0
  29. package/dist/server/proxy-origin.d.ts.map +1 -0
  30. package/dist/tools/cli/args-json.d.ts +12 -0
  31. package/dist/tools/cli/args-json.d.ts.map +1 -0
  32. package/dist/tools/cli/args-tokens.d.ts +27 -0
  33. package/dist/tools/cli/args-tokens.d.ts.map +1 -0
  34. package/dist/tools/cli/args.d.ts +4 -0
  35. package/dist/tools/cli/args.d.ts.map +1 -1
  36. package/dist/tools/cli/help.d.ts.map +1 -1
  37. package/llms/cli.2.txt +7 -2
  38. package/llms/cli.txt +17 -0
  39. package/llms/server.2.txt +131 -0
  40. package/llms/server.5.txt +1 -0
  41. package/llms/server.txt +55 -131
  42. package/llms-full.txt +80 -2
  43. package/llms.txt +2 -2
  44. package/package.json +1 -1
@@ -830,88 +830,28 @@ function routeCliArgv2(argv, defaultCommand) {
830
830
  // src/tools/cli/args.ts
831
831
  import { z as z2 } from "zod";
832
832
 
833
- // src/tools/cli/args-view.ts
834
- function resolveCliView(flags, ascending) {
835
- if (flags.size === 0) {
836
- if (ascending) {
837
- throw new CliArgumentError2("--ascending orders a record view; pass --sort with it");
838
- }
839
- return;
840
- }
841
- const countBy = flags.get("count-by");
842
- const sum = flags.get("sum");
843
- const table = flags.get("table");
844
- const by = flags.get("by");
845
- const rawTop = flags.get("top");
846
- const named = [
847
- ["--count-by", countBy],
848
- ["--sum", sum]
849
- ].filter(([, value]) => value !== undefined);
850
- if (named.length > 1) {
851
- throw new CliArgumentError2(`${named.map(([flag]) => flag).join(" and ")} ask for different shapes — pass one`);
852
- }
853
- let top;
854
- if (rawTop !== undefined) {
855
- top = Number(rawTop);
856
- if (!Number.isInteger(top) || top <= 0) {
857
- throw new CliArgumentError2("--top must be a positive whole number");
858
- }
859
- }
860
- const sort = flags.get("sort");
861
- if (table !== undefined || sort !== undefined) {
862
- if (countBy !== undefined || sum !== undefined) {
863
- throw new CliArgumentError2(`${table !== undefined ? "--table" : "--sort"} lists records; --count-by and --sum aggregate them — pass one`);
864
- }
865
- if (by !== undefined) {
866
- throw new CliArgumentError2("--by groups a view; a record view orders with --sort");
867
- }
868
- if (top !== undefined && sort === undefined) {
869
- throw new CliArgumentError2("--top needs --sort here: unordered records have no n largest");
870
- }
871
- let fields;
872
- if (table !== undefined) {
873
- fields = table.split(",").map((field) => field.trim()).filter(Boolean);
874
- if (fields.length === 0)
875
- throw new CliArgumentError2("--table needs at least one field");
876
- }
877
- return {
878
- kind: "records",
879
- ...sort !== undefined && { sort },
880
- ...ascending && { ascending },
881
- ...top !== undefined && { top },
882
- ...fields && { table: fields }
883
- };
884
- }
885
- if (ascending) {
886
- throw new CliArgumentError2("--ascending orders a record view; pass --sort with it");
887
- }
888
- if (sum !== undefined) {
889
- if (top !== undefined && by === undefined) {
890
- throw new CliArgumentError2("--top needs --by: a single sum has nothing to rank");
891
- }
892
- return {
893
- kind: "sum",
894
- field: sum,
895
- ...by !== undefined && { by },
896
- ...top !== undefined && { top }
897
- };
898
- }
899
- if (countBy !== undefined) {
900
- if (by !== undefined) {
901
- throw new CliArgumentError2("--count-by already names the grouping field; drop --by");
902
- }
903
- return { kind: "count", field: countBy, ...top !== undefined && { top } };
904
- }
905
- if (by !== undefined) {
906
- if (top === undefined) {
907
- throw new CliArgumentError2("--by groups a view; pass --count-by, --sum or --top with it");
908
- }
909
- return { kind: "count", field: by, top };
833
+ // src/tools/cli/args-json.ts
834
+ function cliFieldOption(option, fields) {
835
+ const json = option.inline && option.name.endsWith(":") && !fields.has(option.name);
836
+ const name = json ? option.name.slice(0, -1) : option.name;
837
+ return { name, json };
838
+ }
839
+ function appendCliFieldValue(raw, jsonFields, name, value, info, json) {
840
+ appendCliOptionValue(raw, name, value, json || jsonFields.has(name) ? { kind: "other" } : info);
841
+ if (json)
842
+ jsonFields.add(name);
843
+ }
844
+ function coerceCliFieldValue(info, values, label, json) {
845
+ if (!json)
846
+ return coerceField(info, values, label);
847
+ try {
848
+ return safeJsonParse(values[0] ?? "");
849
+ } catch (cause) {
850
+ throw new CliArgumentError2(`${label} expects valid JSON`, { cause });
910
851
  }
911
- throw new CliArgumentError2("--top needs --sort, --by, --count-by or --sum to rank");
912
852
  }
913
853
 
914
- // src/tools/cli/args.ts
854
+ // src/tools/cli/args-tokens.ts
915
855
  function readCliTokens(argv, fields, fieldFor, config) {
916
856
  const options = {
917
857
  json: false,
@@ -921,13 +861,14 @@ function readCliTokens(argv, fields, fieldFor, config) {
921
861
  help: false
922
862
  };
923
863
  const flags = new Map;
864
+ const jsonFields = new Set;
924
865
  const literalBooleanFlags = new Set;
925
866
  const frameworkFlags = new Map;
926
867
  const viewFlags = new Map;
927
868
  let ascending = false;
928
869
  const positionals = [];
929
- const pushFlag = (name, value) => {
930
- appendCliOptionValue(flags, name, value, fieldFor(name));
870
+ const pushFlag = (name, value, json = false) => {
871
+ appendCliFieldValue(flags, jsonFields, name, value, fieldFor(name), json);
931
872
  };
932
873
  let optionsEnded = false;
933
874
  for (let i = 0;i < argv.length; i++) {
@@ -980,10 +921,13 @@ function readCliTokens(argv, fields, fieldFor, config) {
980
921
  const option = classifyLongOptionToken(tok);
981
922
  if (!option)
982
923
  throw new CliArgumentError2(`Unknown option "${tok}"`);
983
- const { name } = option;
924
+ const { name, json } = cliFieldOption(option, fields);
984
925
  let { value } = option;
985
926
  if (name.length === 0)
986
927
  throw new CliArgumentError2("Invalid empty option name");
928
+ if (json && RESERVED_CLI_OPTIONS.has(name)) {
929
+ throw new CliArgumentError2(`--${name} is a framework option and does not accept :=JSON`);
930
+ }
987
931
  if (option.globalKind === "boolean") {
988
932
  const separate = value === undefined ? separateBoolValue(argv[i + 1]) : undefined;
989
933
  if (separate !== undefined)
@@ -1061,12 +1005,103 @@ function readCliTokens(argv, fields, fieldFor, config) {
1061
1005
  throw new CliArgumentError2(`--${name} requires a value`);
1062
1006
  }
1063
1007
  }
1064
- pushFlag(name, value);
1008
+ pushFlag(name, value, json);
1065
1009
  }
1066
- return { options, flags, literalBooleanFlags, viewFlags, ascending, positionals };
1010
+ return {
1011
+ options,
1012
+ flags,
1013
+ jsonFields,
1014
+ literalBooleanFlags,
1015
+ viewFlags,
1016
+ ascending,
1017
+ positionals
1018
+ };
1067
1019
  }
1020
+
1021
+ // src/tools/cli/args-view.ts
1022
+ function resolveCliView(flags, ascending) {
1023
+ if (flags.size === 0) {
1024
+ if (ascending) {
1025
+ throw new CliArgumentError2("--ascending orders a record view; pass --sort with it");
1026
+ }
1027
+ return;
1028
+ }
1029
+ const countBy = flags.get("count-by");
1030
+ const sum = flags.get("sum");
1031
+ const table = flags.get("table");
1032
+ const by = flags.get("by");
1033
+ const rawTop = flags.get("top");
1034
+ const named = [
1035
+ ["--count-by", countBy],
1036
+ ["--sum", sum]
1037
+ ].filter(([, value]) => value !== undefined);
1038
+ if (named.length > 1) {
1039
+ throw new CliArgumentError2(`${named.map(([flag]) => flag).join(" and ")} ask for different shapes — pass one`);
1040
+ }
1041
+ let top;
1042
+ if (rawTop !== undefined) {
1043
+ top = Number(rawTop);
1044
+ if (!Number.isInteger(top) || top <= 0) {
1045
+ throw new CliArgumentError2("--top must be a positive whole number");
1046
+ }
1047
+ }
1048
+ const sort = flags.get("sort");
1049
+ if (table !== undefined || sort !== undefined) {
1050
+ if (countBy !== undefined || sum !== undefined) {
1051
+ throw new CliArgumentError2(`${table !== undefined ? "--table" : "--sort"} lists records; --count-by and --sum aggregate them — pass one`);
1052
+ }
1053
+ if (by !== undefined) {
1054
+ throw new CliArgumentError2("--by groups a view; a record view orders with --sort");
1055
+ }
1056
+ if (top !== undefined && sort === undefined) {
1057
+ throw new CliArgumentError2("--top needs --sort here: unordered records have no n largest");
1058
+ }
1059
+ let fields;
1060
+ if (table !== undefined) {
1061
+ fields = table.split(",").map((field) => field.trim()).filter(Boolean);
1062
+ if (fields.length === 0)
1063
+ throw new CliArgumentError2("--table needs at least one field");
1064
+ }
1065
+ return {
1066
+ kind: "records",
1067
+ ...sort !== undefined && { sort },
1068
+ ...ascending && { ascending },
1069
+ ...top !== undefined && { top },
1070
+ ...fields && { table: fields }
1071
+ };
1072
+ }
1073
+ if (ascending) {
1074
+ throw new CliArgumentError2("--ascending orders a record view; pass --sort with it");
1075
+ }
1076
+ if (sum !== undefined) {
1077
+ if (top !== undefined && by === undefined) {
1078
+ throw new CliArgumentError2("--top needs --by: a single sum has nothing to rank");
1079
+ }
1080
+ return {
1081
+ kind: "sum",
1082
+ field: sum,
1083
+ ...by !== undefined && { by },
1084
+ ...top !== undefined && { top }
1085
+ };
1086
+ }
1087
+ if (countBy !== undefined) {
1088
+ if (by !== undefined) {
1089
+ throw new CliArgumentError2("--count-by already names the grouping field; drop --by");
1090
+ }
1091
+ return { kind: "count", field: countBy, ...top !== undefined && { top } };
1092
+ }
1093
+ if (by !== undefined) {
1094
+ if (top === undefined) {
1095
+ throw new CliArgumentError2("--by groups a view; pass --count-by, --sum or --top with it");
1096
+ }
1097
+ return { kind: "count", field: by, top };
1098
+ }
1099
+ throw new CliArgumentError2("--top needs --sort, --by, --count-by or --sum to rank");
1100
+ }
1101
+
1102
+ // src/tools/cli/args.ts
1068
1103
  function buildToolArgs(tokens, fields, fieldFor, declaredPositionals, allowUnknown) {
1069
- const { flags, literalBooleanFlags, positionals } = tokens;
1104
+ const { flags, jsonFields, literalBooleanFlags, positionals } = tokens;
1070
1105
  const toolArgs = {};
1071
1106
  const fillable = declaredPositionals === undefined ? [...fields.entries()].filter(([, info]) => info.kind !== "boolean").map(([name]) => name) : [...declaredPositionals];
1072
1107
  const variadicTail = declaredPositionals !== undefined && fields.get(fillable[fillable.length - 1] ?? "")?.kind === "array" ? fillable[fillable.length - 1] : undefined;
@@ -1105,16 +1140,23 @@ function buildToolArgs(tokens, fields, fieldFor, declaredPositionals, allowUnkno
1105
1140
  throw new CliArgumentError2(`--${root} conflicts with --${dotted} — pass one form, not both`);
1106
1141
  }
1107
1142
  }
1143
+ for (const key of jsonFields) {
1144
+ for (const other of flags.keys()) {
1145
+ if (other.startsWith(`${key}.`) || key.startsWith(`${other}.`)) {
1146
+ throw new CliArgumentError2(`--${key} conflicts with --${other} — pass one form, not both`);
1147
+ }
1148
+ }
1149
+ }
1108
1150
  for (const [key, values] of flags) {
1109
1151
  const info = fieldFor(key);
1110
1152
  const exactLiteralBoolean = literalBooleanFlags.has(key) && fields.has(key);
1111
1153
  if (key.includes(".") && !exactLiteralBoolean) {
1112
1154
  const root = key.split(".")[0] ?? key;
1113
- const value = info === undefined && allowUnknown && !fields.has(root) ? looseCoerce(values[0] ?? "") : coerceField(info, values, `--${key}`);
1155
+ const value = !jsonFields.has(key) && info === undefined && allowUnknown && !fields.has(root) ? looseCoerce(values[0] ?? "") : coerceCliFieldValue(info, values, `--${key}`, jsonFields.has(key));
1114
1156
  setNested(toolArgs, key.split("."), value);
1115
1157
  continue;
1116
1158
  }
1117
- toolArgs[key] = coerceField(info, values, `--${key}`);
1159
+ toolArgs[key] = coerceCliFieldValue(info, values, `--${key}`, jsonFields.has(key));
1118
1160
  }
1119
1161
  return toolArgs;
1120
1162
  }
@@ -1146,6 +1188,7 @@ function extractCliGlobalOptions2(argv, schema) {
1146
1188
  const fields = describeSchemaFields(schema);
1147
1189
  const rest = [];
1148
1190
  const raw = new Map;
1191
+ const jsonFields = new Set;
1149
1192
  let ended = false;
1150
1193
  for (let i = 0;i < argv.length; i++) {
1151
1194
  const token = argv[i];
@@ -1154,8 +1197,9 @@ function extractCliGlobalOptions2(argv, schema) {
1154
1197
  if (!ended && token === "--")
1155
1198
  ended = true;
1156
1199
  const option = ended ? undefined : classifyLongOptionToken(token);
1157
- const info = option && option.globalKind === undefined ? fields.get(option.name) : undefined;
1158
- if (!option || !info) {
1200
+ const field = option ? cliFieldOption(option, fields) : undefined;
1201
+ const info = field && option?.globalKind === undefined ? fields.get(field.name) : undefined;
1202
+ if (!option || !field || !info) {
1159
1203
  rest.push(token);
1160
1204
  continue;
1161
1205
  }
@@ -1174,11 +1218,11 @@ function extractCliGlobalOptions2(argv, schema) {
1174
1218
  throw new CliArgumentError2(`--${option.name} requires a value`);
1175
1219
  }
1176
1220
  }
1177
- appendCliOptionValue(raw, option.name, value, info);
1221
+ appendCliFieldValue(raw, jsonFields, field.name, value, info, field.json);
1178
1222
  }
1179
1223
  const args = {};
1180
1224
  for (const [name, values] of raw) {
1181
- args[name] = coerceField(fields.get(name), values, `--${name}`);
1225
+ args[name] = coerceCliFieldValue(fields.get(name), values, `--${name}`, jsonFields.has(name));
1182
1226
  }
1183
1227
  let coerced;
1184
1228
  try {
@@ -1664,6 +1708,20 @@ function constraintLabel(schema) {
1664
1708
  function fieldTypeLabel(schema) {
1665
1709
  return `<${typeLabel(schema)}>${constraintLabel(schema)}`;
1666
1710
  }
1711
+ function nullableField(schema) {
1712
+ if (schema.type === "null")
1713
+ return true;
1714
+ if (Array.isArray(schema.type) && schema.type.includes("null"))
1715
+ return true;
1716
+ return Array.isArray(schema.anyOf) && schema.anyOf.some((member) => isRecord(member) && nullableField(member));
1717
+ }
1718
+ function jsonValueHelp(fields) {
1719
+ const example = fields.find((field) => nullableField(field.schema))?.name;
1720
+ return [
1721
+ "Assign a whole JSON value with --field:=JSON; the declared schema still validates it.",
1722
+ ...example === undefined ? [] : [`JSON null: --${example}:=null. The literal string stays --${example} null.`]
1723
+ ];
1724
+ }
1667
1725
  function padRight(text, width) {
1668
1726
  return text.length >= width ? text : text + " ".repeat(width - text.length);
1669
1727
  }
@@ -1717,6 +1775,7 @@ function renderTopHelp(input) {
1717
1775
  for (const [flag, desc] of GLOBAL_OPTIONS)
1718
1776
  lines.push(` ${padRight(flag, optWidth)} ${desc}`);
1719
1777
  lines.push(...applicationOptionLines(input.applicationOptions));
1778
+ lines.push("", ...jsonValueHelp(input.applicationOptions));
1720
1779
  lines.push("", `Run "${name} <command> --help" for command-specific flags.`);
1721
1780
  return `${lines.join(`
1722
1781
  `)}
@@ -1763,7 +1822,7 @@ function renderCommandHelp(name, command, descriptor, applicationOptions = []) {
1763
1822
  if (flag !== undefined) {
1764
1823
  lines.push("", `A boolean flag is on alone or takes true/false: --${flag}, --${flag} false, --no-${flag}`);
1765
1824
  }
1766
- lines.push("");
1825
+ lines.push("", ...jsonValueHelp(fields), "");
1767
1826
  }
1768
1827
  const applicationLines = applicationOptionLines(applicationOptions);
1769
1828
  if (applicationLines.length > 0)
@@ -0,0 +1,20 @@
1
+ import { z } from 'zod';
2
+ declare const ObservationSchema: z.ZodObject<{
3
+ failure: z.ZodEnum<{
4
+ deadline: "deadline";
5
+ observation: "observation";
6
+ }>;
7
+ groupId: z.ZodNumber;
8
+ observations: z.ZodNumber;
9
+ lastStates: z.ZodArray<z.ZodString>;
10
+ elapsedMs: z.ZodNumber;
11
+ }, z.core.$strip>;
12
+ type Observation = z.infer<typeof ObservationSchema>;
13
+ /** Only this internal error carries process-state diagnostics safe to promote. */
14
+ export declare class GroupSettlementError extends Error {
15
+ constructor(message: string, observation: Observation, cause?: unknown);
16
+ }
17
+ /** Bounded cause traversal; arbitrary caller messages never become cleanup diagnostics. */
18
+ export declare function groupSettlementDiagnostics(cause: unknown): Observation[];
19
+ export {};
20
+ //# sourceMappingURL=group-diagnostics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"group-diagnostics.d.ts","sourceRoot":"","sources":["../../src/process/group-diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,QAAA,MAAM,iBAAiB;;;;;;;;;iBAMrB,CAAC;AACH,KAAK,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAGrD,kFAAkF;AAClF,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,YAAY,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,GAAE,OAAqB,EAKlF;CACF;AAQD,2FAA2F;AAC3F,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,EAAE,CA+BxE"}
@@ -1,5 +1,5 @@
1
1
  /** `killpg(..., 0)` also sees Linux zombies; only live members can still perform work. */
2
2
  export declare function hasLiveGroupMember(table: string, group: number): boolean;
3
3
  /** A delivered SIGKILL is asynchronous; do not report cleanup until every group member is dead. */
4
- export declare function waitForProcessGroupExit(pid: number | undefined, deadline: number): Promise<void>;
4
+ export declare function waitForProcessGroupExit(pid: number | undefined, deadline: number, killLiveMembers?: () => Promise<boolean>): Promise<void>;
5
5
  //# sourceMappingURL=group-settlement.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"group-settlement.d.ts","sourceRoot":"","sources":["../../src/process/group-settlement.ts"],"names":[],"mappings":"AAIA,0FAA0F;AAC1F,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAQxE;AAmBD,mGAAmG;AACnG,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CA0Bf"}
1
+ {"version":3,"file":"group-settlement.d.ts","sourceRoot":"","sources":["../../src/process/group-settlement.ts"],"names":[],"mappings":"AAKA,0FAA0F;AAC1F,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAQxE;AAgBD,mGAAmG;AACnG,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,QAAQ,EAAE,MAAM,EAChB,eAAe,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GACvC,OAAO,CAAC,IAAI,CAAC,CAmDf"}
@@ -1 +1 @@
1
- {"version":3,"file":"group.d.ts","sourceRoot":"","sources":["../../src/process/group.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAE,KAAK,6BAA6B,EAAE,MAAM,YAAY,CAAC;AAIpF,+FAA+F;AAC/F,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO;IAYpE,MAAM;IACN,MAAM;EAIT;AAeD,gGAAgG;AAChG,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,OAAO,CASpF;AAsCD,sGAAsG;AACtG,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,6BAA6B,CAAC;IAC/C,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,gEAAgE;IAChE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAmB/E;AAED,gGAAgG;AAChG,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAED;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,gBAAgB,GAAG;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,UAAU,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;CAAE,GAC/E,OAAO,CAAC,OAAO,CAAC,CAsBlB;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,EAAE,6BAA6B,CAAC;IACtC,UAAU,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,OAAO,CAAC,CAyBnB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB,CAItE;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAMxF"}
1
+ {"version":3,"file":"group.d.ts","sourceRoot":"","sources":["../../src/process/group.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAE,KAAK,6BAA6B,EAAE,MAAM,YAAY,CAAC;AAKpF,+FAA+F;AAC/F,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO;IAYpE,MAAM;IACN,MAAM;EAIT;AAeD,gGAAgG;AAChG,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,OAAO,CASpF;AAyCD,sGAAsG;AACtG,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,6BAA6B,CAAC;IAC/C,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,gEAAgE;IAChE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAmB/E;AAED,gGAAgG;AAChG,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAED;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,gBAAgB,GAAG;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,UAAU,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;CAAE,GAC/E,OAAO,CAAC,OAAO,CAAC,CAsBlB;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,EAAE,6BAA6B,CAAC;IACtC,UAAU,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,OAAO,CAAC,CAyBnB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB,CAQtE;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAMxF"}
@@ -1,3 +1,4 @@
1
+ import { type ProxyOriginConfig } from './proxy-origin.js';
1
2
  import { type ManagedServerHandle } from './shutdown.js';
2
3
  import type { SocketIOServerLifecycle } from './socket-io.js';
3
4
  import type { FetchComposition, FetchHandler, HandlerConfig, RawRoute, RawRouteContext } from './types.js';
@@ -26,6 +27,14 @@ export type UnixListenConfig = string | {
26
27
  };
27
28
  /** Bun-specific server config layered over the Fetch-clean handler config. */
28
29
  export interface BunServerConfig extends BunHandlerConfig, BunFetchComposition {
30
+ /**
31
+ * Restore the external scheme behind one trusted TCP ingress, before composition.
32
+ * The ingress must overwrite Host and X-Forwarded-Proto and remove Forwarded,
33
+ * X-Forwarded-Host and X-Forwarded-Port. Trusted requests require exactly one
34
+ * `http` or `https` proto; malformed/conflicting headers receive 400.
35
+ * Host/tenant authorization remains application-owned. Independent of trustProxy.
36
+ */
37
+ proxyOrigin?: ProxyOriginConfig;
29
38
  port?: number;
30
39
  hostname?: string;
31
40
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"bun.d.ts","sourceRoot":"","sources":["../../src/server/bun.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,mBAAmB,EAEzB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,eAAe,EAChB,MAAM,SAAS,CAAC;AAEjB,yEAAyE;AACzE,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC;AACrD,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;AAC9C,MAAM,MAAM,kBAAkB,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;AAC5D,MAAM,MAAM,eAAe,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;AACtD,MAAM,MAAM,mBAAmB,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;AAC9D,MAAM,MAAM,gBAAgB,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;AAExD,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACvD,KAAK,oBAAoB,GAAG,GAAG,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;AAC1D,KAAK,qBAAqB,GAAG,eAAe,SAAS;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,CAAC,GAAG,KAAK,CAAC;AAE3F,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAClC,eAAe,EACf,OAAO,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,aAAa,CAChF,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAExE,8EAA8E;AAC9E,MAAM,WAAW,eAAgB,SAAQ,gBAAgB,EAAE,mBAAmB;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,SAAS,CAAC,EAAE,oBAAoB,CAAC;IACjC,iGAAiG;IACjG,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC,WAAW,CAAC,EAAE,qBAAqB,CAAC;IACpC,GAAG,CAAC,EAAE,iBAAiB,CAAC;CACzB;AAED,MAAM,MAAM,eAAe,GAAG,mBAAmB,CAAC,SAAS,CAAC,CAAC;AA+F7D,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,eAAe,CAgMrE"}
1
+ {"version":3,"file":"bun.d.ts","sourceRoot":"","sources":["../../src/server/bun.ts"],"names":[],"mappings":"AAGA,OAAO,EAAqB,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAEL,KAAK,mBAAmB,EAEzB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,eAAe,EAChB,MAAM,SAAS,CAAC;AAEjB,yEAAyE;AACzE,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC;AACrD,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;AAC9C,MAAM,MAAM,kBAAkB,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;AAC5D,MAAM,MAAM,eAAe,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;AACtD,MAAM,MAAM,mBAAmB,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;AAC9D,MAAM,MAAM,gBAAgB,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;AAExD,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACvD,KAAK,oBAAoB,GAAG,GAAG,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;AAC1D,KAAK,qBAAqB,GAAG,eAAe,SAAS;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,CAAC,GAAG,KAAK,CAAC;AAE3F,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAClC,eAAe,EACf,OAAO,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,aAAa,CAChF,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAExE,8EAA8E;AAC9E,MAAM,WAAW,eAAgB,SAAQ,gBAAgB,EAAE,mBAAmB;IAC5E;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,SAAS,CAAC,EAAE,oBAAoB,CAAC;IACjC,iGAAiG;IACjG,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC,WAAW,CAAC,EAAE,qBAAqB,CAAC;IACpC,GAAG,CAAC,EAAE,iBAAiB,CAAC;CACzB;AAED,MAAM,MAAM,eAAe,GAAG,mBAAmB,CAAC,SAAS,CAAC,CAAC;AA+F7D,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,eAAe,CAqMrE"}
@@ -0,0 +1,12 @@
1
+ import type { BunServer } from './bun.js';
2
+ /** One TCP ingress that overwrites Host/proto and strips competing URL headers. */
3
+ export interface ProxyOriginConfig {
4
+ /** Match the real socket peer, never a forwarded client IP. */
5
+ trustedPeer: (socketIp: string) => boolean;
6
+ }
7
+ /** Bun associates requestIP, timeout and upgrade with the original native request. */
8
+ export declare function createProxyOrigin(policy: ProxyOriginConfig): {
9
+ bind(server: BunServer): void;
10
+ normalize(request: Request, server: BunServer): Request | Response;
11
+ };
12
+ //# sourceMappingURL=proxy-origin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy-origin.d.ts","sourceRoot":"","sources":["../../src/server/proxy-origin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,mFAAmF;AACnF,MAAM,WAAW,iBAAiB;IAChC,+DAA+D;IAC/D,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CAC5C;AAUD,sFAAsF;AACtF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB;IAKvD,IAAI,SAAS,SAAS,GAAG,IAAI;IAQ7B,SAAS,UAAU,OAAO,UAAU,SAAS,GAAG,OAAO,GAAG,QAAQ;EAgCrE"}
@@ -0,0 +1,12 @@
1
+ import { type FieldInfo } from './args-fields.js';
2
+ import type { CliLongOptionToken } from './args-route.js';
3
+ /** An inline := assigns a whole JSON value; an exact declared colon name stays literal. */
4
+ export declare function cliFieldOption(option: CliLongOptionToken, fields: ReadonlyMap<string, FieldInfo>): {
5
+ name: string;
6
+ json: boolean;
7
+ };
8
+ /** Whole JSON assignments cannot accumulate or mix with repeated element flags. */
9
+ export declare function appendCliFieldValue(raw: Map<string, string[]>, jsonFields: Set<string>, name: string, value: string, info: FieldInfo | undefined, json: boolean): void;
10
+ /** JSON assigns a value without scalar coercion; the command schema still validates it. */
11
+ export declare function coerceCliFieldValue(info: FieldInfo | undefined, values: string[], label: string, json: boolean): unknown;
12
+ //# sourceMappingURL=args-json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args-json.d.ts","sourceRoot":"","sources":["../../../src/tools/cli/args-json.ts"],"names":[],"mappings":"AACA,OAAO,EAAqC,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAClF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGvD,2FAA2F;AAC3F,wBAAgB,cAAc,CAC5B,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,GACrC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAIjC;AAED,mFAAmF;AACnF,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAC1B,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,EACvB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,SAAS,GAAG,SAAS,EAC3B,IAAI,EAAE,OAAO,GACZ,IAAI,CAQN;AAED,2FAA2F;AAC3F,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,SAAS,GAAG,SAAS,EAC3B,MAAM,EAAE,MAAM,EAAE,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,OAAO,GACZ,OAAO,CAOT"}
@@ -0,0 +1,27 @@
1
+ import type { CliRunOptions } from './args.js';
2
+ import { type describeSchemaFields, type FieldInfo } from './args-fields.js';
3
+ type CliConfigForParse = {
4
+ allowUnknown?: boolean;
5
+ optionAliases?: ReadonlyMap<string, string>;
6
+ };
7
+ type FieldResolver = (name: string) => FieldInfo | undefined;
8
+ /** One invocation's argv, sorted into what each token is for. */
9
+ export interface CliTokens {
10
+ options: CliRunOptions;
11
+ /** Raw values per flag, in order; only an array field may have several. */
12
+ flags: Map<string, string[]>;
13
+ jsonFields: Set<string>;
14
+ /** Boolean presence and aliases name exact fields, even when the name has a dot. */
15
+ literalBooleanFlags: Set<string>;
16
+ viewFlags: Map<string, string>;
17
+ ascending: boolean;
18
+ positionals: string[];
19
+ }
20
+ /**
21
+ * Phase one: tokenise. Every refusal about the SHAPE of the command line —
22
+ * an unknown option, a missing value, a prototype-polluting name, a repeated
23
+ * non-array flag — happens here, before its raw multiplicity can be lost.
24
+ */
25
+ export declare function readCliTokens(argv: readonly string[], fields: ReturnType<typeof describeSchemaFields>, fieldFor: FieldResolver, config: CliConfigForParse): CliTokens;
26
+ export {};
27
+ //# sourceMappingURL=args-tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args-tokens.d.ts","sourceRoot":"","sources":["../../../src/tools/cli/args-tokens.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,SAAS,EAGf,MAAM,eAAe,CAAC;AAWvB,KAAK,iBAAiB,GAAG;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7C,CAAC;AACF,KAAK,aAAa,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,SAAS,GAAG,SAAS,CAAC;AAE7D,iEAAiE;AACjE,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,aAAa,CAAC;IACvB,2EAA2E;IAC3E,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7B,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACxB,oFAAoF;IACpF,mBAAmB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACjC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,MAAM,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,EAC/C,QAAQ,EAAE,aAAa,EACvB,MAAM,EAAE,iBAAiB,GACxB,SAAS,CAqKX"}
@@ -44,6 +44,10 @@ export interface ParsedCliArgs {
44
44
  /** The CLI-behaviour flags. */
45
45
  options: CliRunOptions;
46
46
  }
47
+ /**
48
+ * Parse one command's argv against its schema: lexical/coerced flags, explicit
49
+ * `--field:=JSON`, dotted paths, boolean presence and declared positionals.
50
+ */
47
51
  export declare function parseCliArgs(argv: string[], schema: z.ZodType | undefined, config?: {
48
52
  allowUnknown?: boolean;
49
53
  knownFields?: readonly string[];
@@ -1 +1 @@
1
- {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../../src/tools/cli/args.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAoBxB,OAAO,EAAE,KAAK,aAAa,EAAkB,MAAM,aAAa,CAAC;AAGjE,yEAAyE;AACzE,MAAM,WAAW,aAAa;IAC5B,sEAAsE;IACtE,IAAI,EAAE,OAAO,CAAC;IACd,iEAAiE;IACjE,IAAI,EAAE,OAAO,CAAC;IACd,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,KAAK,EAAE,OAAO,CAAC;IACf,qEAAqE;IACrE,MAAM,EAAE,OAAO,CAAC;IAChB,qDAAqD;IACrD,IAAI,EAAE,OAAO,CAAC;IACd,0FAA0F;IAC1F,IAAI,CAAC,EAAE,aAAa,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,+BAA+B;IAC/B,OAAO,EAAE,aAAa,CAAC;CACxB;AAiSD,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EAAE,EACd,MAAM,EAAE,CAAC,CAAC,OAAO,GAAG,SAAS,EAC7B,MAAM,GAAE;IACN,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,aAAa,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5B,GACL,aAAa,CAsBf;AAED,iFAAiF;AACjF,MAAM,WAAW,qBAAqB;IACpC,0EAA0E;IAC1E,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AASD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,MAAM,EAAE,CAAC,CAAC,SAAS,GAAG,SAAS,GAC9B,qBAAqB,CAkDvB"}
1
+ {"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../../../src/tools/cli/args.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAcxB,OAAO,EAAE,KAAK,aAAa,EAAkB,MAAM,aAAa,CAAC;AAMjE,yEAAyE;AACzE,MAAM,WAAW,aAAa;IAC5B,sEAAsE;IACtE,IAAI,EAAE,OAAO,CAAC;IACd,iEAAiE;IACjE,IAAI,EAAE,OAAO,CAAC;IACd,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,KAAK,EAAE,OAAO,CAAC;IACf,qEAAqE;IACrE,MAAM,EAAE,OAAO,CAAC;IAChB,qDAAqD;IACrD,IAAI,EAAE,OAAO,CAAC;IACd,0FAA0F;IAC1F,IAAI,CAAC,EAAE,aAAa,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,+BAA+B;IAC/B,OAAO,EAAE,aAAa,CAAC;CACxB;AA6GD;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EAAE,EACd,MAAM,EAAE,CAAC,CAAC,OAAO,GAAG,SAAS,EAC7B,MAAM,GAAE;IACN,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,aAAa,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5B,GACL,aAAa,CAsBf;AAED,iFAAiF;AACjF,MAAM,WAAW,qBAAqB;IACpC,0EAA0E;IAC1E,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AASD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,MAAM,EAAE,CAAC,CAAC,SAAS,GAAG,SAAS,GAC9B,qBAAqB,CAyDvB"}
@@ -1 +1 @@
1
- {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../../src/tools/cli/help.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,eAAe,EAAoB,MAAM,+BAA+B,CAAC;AAEvF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AA+GvD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,sBAAsB,CAAC,EAC7C,MAAM,EAAE,MAAM,GACb,GAAG,CAAC,MAAM,EAAE,sBAAsB,CAAC,CASrC;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;IAC9C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,SAAS,eAAe,EAAE,CAAC;IAC/C,wEAAwE;IACxE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,MAAM,CAqCT;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,sBAAsB,EAClC,kBAAkB,GAAE,SAAS,eAAe,EAAO,GAClD,MAAM,CA6DR"}
1
+ {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../../src/tools/cli/help.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,eAAe,EAAoB,MAAM,+BAA+B,CAAC;AAEvF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAkIvD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,sBAAsB,CAAC,EAC7C,MAAM,EAAE,MAAM,GACb,GAAG,CAAC,MAAM,EAAE,sBAAsB,CAAC,CASrC;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;IAC9C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,SAAS,eAAe,EAAE,CAAC;IAC/C,wEAAwE;IACxE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,MAAM,CAsCT;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,sBAAsB,EAClC,kBAAkB,GAAE,SAAS,eAAe,EAAO,GAClD,MAAM,CA6DR"}
package/llms/cli.2.txt CHANGED
@@ -183,11 +183,16 @@ the code (so `exitCodes` can map it instead of every remote failure exiting `1`)
183
183
  the message the operator needs, and the error's own class — a plain `Error` is
184
184
  an *unexpected* error to the runner, which would print a code frame of the framework
185
185
  bundle before the JSON failure and scrub it to `INTERNAL_SERVER_ERROR`.
186
- A structured `{ error, details }` body is relayed as the contract error it
186
+ A `tools/call` response with `isError: true` and a structured `{ error, details }` body is relayed as the contract error it
187
187
  is, on every transport; anything else fails as `UPSTREAM_TOOL_ERROR` carrying
188
188
  what the server did send. Not `INTERNAL_SERVER_ERROR`, because nothing of ours
189
189
  broke.
190
190
 
191
+ The CLI writes this refusal to stderr, leaves stdout empty and exits with the
192
+ mapped nonzero error code (`1` for an unmapped code). A successful response may
193
+ contain an ordinary field named `error`; its payload alone does not establish a
194
+ tool failure.
195
+
191
196
  **On the CLI a discovered command prints the answer, not the envelope.**
192
197
  `tools/call` returns `{ content: [...], structuredContent? }`, and an agent mount
193
198
  needs exactly that — the parts are what a model is shown. The CLI is different in
@@ -266,7 +271,7 @@ SDK nor the `ai` peer.
266
271
  |--------|------|---------|
267
272
  | `createCli` | function | build and run a CLI from contracts — [guide](../guide/cli.md) |
268
273
  | `defineCliCommand` | function | define one Zod-typed CLI-only executable command with optional validated-result presentation/exit policy |
269
- | `parseCliArgs` | function | argv → typed tool args against a schema (advanced) |
274
+ | `parseCliArgs` | function | argv → typed tool args against a schema; inline `--field:=JSON` assigns a whole JSON value, including null, while ordinary string flags remain lexical (advanced) |
270
275
  | `routeCliArgv` | function | select the command out of argv without duplicating the global-option grammar (advanced) |
271
276
  | `extractCliGlobalOptions` | function | lift the application's own global options out of argv before routing (advanced) |
272
277
  | `coerceJsonArgs` | function | the second half of `parseCliArgs` — parse array/object values a consumer sends itself, including discovered MCP object guards restored from JSON Schema, without the `stitchkit/tools` barrel |
package/llms/cli.txt CHANGED
@@ -247,6 +247,23 @@ string, the schema says what it should be:
247
247
  | `z.record(z.string(), z.unknown())` | `--data '{"code":"007"}'` or `--data.code=007` → `"007"` |
248
248
  | `.optional()` / `.default()` | not required |
249
249
 
250
+ Use the inline `:=` form to assign a whole JSON value without scalar coercion:
251
+
252
+ ```bash
253
+ myapp upsert --productId:=null --count:=null
254
+ myapp upsert --productId null # the literal string "null"
255
+ myapp upsert --productId:='"null"' # the same string, written as JSON
256
+ ```
257
+
258
+ `null` is accepted only when the unchanged command schema permits it. Omitting an
259
+ optional field leaves it absent; it does not imply `null`. The same syntax works
260
+ for application global options and dotted leaves (`--settings.note:=null`). A
261
+ JSON assignment supplies the whole field, so an array uses one assignment such as
262
+ `--tags:='["a","b"]'`; mixing it with repeated element flags or another assignment
263
+ is refused. Invalid JSON is a usage error before the handler runs. Framework
264
+ options such as `--json` retain their existing grammar. An exact declared field
265
+ name ending in `:` retains its existing inline spelling.
266
+
250
267
  Primitive literals use the same coercion through optional, nullable and default wrappers and as
251
268
  array elements. A literal set whose members have different primitive types stays lexical because
252
269
  argv has no type tag: for `z.literal([7, '007'])`, `--value 007` remains the string `"007"` rather