@typeship-ax/cli 0.9.1 → 0.20.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.
Files changed (70) hide show
  1. package/AGENTS.md +9 -4
  2. package/README.md +4 -4
  3. package/api.json +6257 -589
  4. package/api.md +475 -81
  5. package/dist/cli-agent.d.ts +5 -5
  6. package/dist/cli-agent.d.ts.map +1 -1
  7. package/dist/cli-agent.js +14 -10
  8. package/dist/cli.js +151 -75
  9. package/dist/core/http.d.ts +3 -2
  10. package/dist/core/http.d.ts.map +1 -1
  11. package/dist/core/http.js +18 -6
  12. package/dist/errors.d.ts +17 -10
  13. package/dist/errors.d.ts.map +1 -1
  14. package/dist/errors.js +24 -15
  15. package/dist/index.d.ts +7 -3
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +9 -5
  18. package/dist/ops.d.ts +4 -0
  19. package/dist/ops.d.ts.map +1 -1
  20. package/dist/ops.js +45 -31
  21. package/dist/polling-login.d.ts.map +1 -1
  22. package/dist/polling-login.js +11 -1
  23. package/dist/resources/account.d.ts +4 -4
  24. package/dist/resources/account.d.ts.map +1 -1
  25. package/dist/resources/account.js +10 -5
  26. package/dist/resources/api-keys.d.ts +40 -14
  27. package/dist/resources/api-keys.d.ts.map +1 -1
  28. package/dist/resources/api-keys.js +45 -13
  29. package/dist/resources/definition-revisions.d.ts +35 -18
  30. package/dist/resources/definition-revisions.d.ts.map +1 -1
  31. package/dist/resources/definition-revisions.js +43 -15
  32. package/dist/resources/definitions.d.ts +21 -6
  33. package/dist/resources/definitions.d.ts.map +1 -1
  34. package/dist/resources/definitions.js +16 -3
  35. package/dist/resources/generate.d.ts +44 -15
  36. package/dist/resources/generate.d.ts.map +1 -1
  37. package/dist/resources/generate.js +55 -13
  38. package/dist/resources/generations.d.ts +14 -6
  39. package/dist/resources/generations.d.ts.map +1 -1
  40. package/dist/resources/generations.js +26 -5
  41. package/dist/resources/projects.d.ts +106 -53
  42. package/dist/resources/projects.d.ts.map +1 -1
  43. package/dist/resources/projects.js +78 -31
  44. package/dist/resources/targets.d.ts +285 -22
  45. package/dist/resources/targets.d.ts.map +1 -1
  46. package/dist/resources/targets.js +408 -10
  47. package/dist/schemas.d.ts +1 -0
  48. package/dist/schemas.d.ts.map +1 -1
  49. package/dist/schemas.js +175 -102
  50. package/dist/types.d.ts +2162 -134
  51. package/dist/types.d.ts.map +1 -1
  52. package/dist/types.js +99 -2
  53. package/package.json +3 -3
  54. package/src/cli-agent.ts +17 -13
  55. package/src/cli.ts +138 -70
  56. package/src/core/http.ts +17 -6
  57. package/src/errors.ts +25 -15
  58. package/src/index.ts +9 -5
  59. package/src/ops.ts +49 -31
  60. package/src/polling-login.ts +10 -1
  61. package/src/resources/account.ts +11 -4
  62. package/src/resources/api-keys.ts +84 -13
  63. package/src/resources/definition-revisions.ts +74 -16
  64. package/src/resources/definitions.ts +28 -4
  65. package/src/resources/generate.ts +78 -13
  66. package/src/resources/generations.ts +31 -4
  67. package/src/resources/projects.ts +141 -39
  68. package/src/resources/targets.ts +756 -13
  69. package/src/schemas.ts +176 -103
  70. package/src/types.ts +2372 -189
@@ -94,8 +94,8 @@ export declare function upsertAgentBlock(file: string, marker: string, body: str
94
94
  file: string;
95
95
  updated: boolean;
96
96
  };
97
- /** AGENTS.md by default; CLAUDE.md when only it exists, or when running under Claude Code and AGENTS.md is absent. */
98
- export declare function agentInstructionsFile(cwd: string, harness: string | null): string;
97
+ /** AGENTS.md for every harness; preserve an existing CLAUDE.md when AGENTS.md is absent. */
98
+ export declare function agentInstructionsFile(cwd: string): string;
99
99
  export interface CommandFlagSummary {
100
100
  flag: string;
101
101
  /** string | number | boolean | array | object | json | file */
@@ -164,8 +164,8 @@ export declare function installSkills(repo: string | null, options?: {
164
164
  }): SkillsInstallResult;
165
165
  /**
166
166
  * A response that carries files: an array property whose items have string
167
- * `path` and `content`. typeship's own generate call is one; any API that
168
- * returns generated or exported files is another. `--out <dir>` writes them.
167
+ * `path` and `content`, as an API that returns generated or exported files
168
+ * does. `--out <dir>` writes them.
169
169
  */
170
170
  export declare function bundleProperty(outputSchema: Record<string, unknown> | undefined): string | null;
171
171
  /** A non-page response whose result is a collection wrapped in one array
@@ -182,7 +182,7 @@ export declare function writeBundle(dir: string, files: {
182
182
  };
183
183
  /**
184
184
  * A response that carries a claim: an object property `claim` with a string
185
- * `url` (typeship's anonymous generate is one). The CLI tells the person
185
+ * `url`, as an anonymous run that can later be saved has. The CLI tells the person
186
186
  * where to claim and leaves a breadcrumb in the working directory so a
187
187
  * later session (or `doctor`) can list what is still unclaimed.
188
188
  */
@@ -1 +1 @@
1
- {"version":3,"file":"cli-agent.d.ts","sourceRoot":"","sources":["../src/cli-agent.ts"],"names":[],"mappings":"AAgBA;;;GAGG;AACH,MAAM,MAAM,SAAS,GACjB,SAAS,GACT,cAAc,GACd,YAAY,GACZ,WAAW,GACX,iBAAiB,GACjB,cAAc,GACd,cAAc,GACd,cAAc,GACd,eAAe,GACf,mBAAmB,GACnB,cAAc,GACd,uBAAuB,GACvB,eAAe,GACf,iBAAiB,GACjB,cAAc,GACd,kBAAkB,GAClB,aAAa,CAAC;AAElB,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,QAAQ;IACvB,qGAAqG;IACrG,MAAM,EAAE,OAAO,GAAG,iBAAiB,CAAC;IACpC,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gFAAgF;IAChF,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,mFAAmF;IACnF,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC5B,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,QAAQ,CAQvD;AAED,4EAA4E;AAC5E,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,GAAG,CAAC,GAAG,CAAC,CAYlD;AAED,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,OAAO,EACd,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GACvE,aAAa,CAkDf;AAqCD,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IACvC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAMxD;AAED,uGAAuG;AACvG,wBAAgB,aAAa,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,GAAG,IAAI,CAUjF;AAID,MAAM,MAAM,WAAW,GAAG,aAAa,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,YAAY,GAAG,UAAU,GAAG,KAAK,GAAG,gBAAgB,CAAC;AAE5I,MAAM,WAAW,QAAQ;IACvB,sDAAsD;IACtD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,WAAW,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IAC9B,yEAAyE;IACzE,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACjC,+CAA+C;IAC/C,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,KAAK,MAAM,CAAC;IACnE,oFAAoF;IACpF,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAqDD,eAAO,MAAM,WAAW,EAAE,SAAS,EAqElC,CAAC;AAEF,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAE/D;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,iHAAiH;AACjH,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,GAAG,cAAc,CAU5G;AAED,sEAAsE;AACtE,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAGnF;AAID;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAiB/G;AAMD,sHAAsH;AACtH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAMjF;AAID,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,qCAAqC;IACrC,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC1C,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,kEAAkE;IAClE,IAAI,CAAC,EAAE,UAAU,GAAG,UAAU,GAAG,MAAM,CAAC;IACxC,KAAK,EAAE,kBAAkB,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,iBAAiB,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACtF,sDAAsD;IACtD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,+EAA+E;IAC/E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wFAAwF;AACxF,oGAAoG;AACpG,wBAAgB,aAAa,CAAC,CAAC,EAAE,kBAAkB,GAAG,MAAM,CAI3D;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,MAAM,CAO/D;AAED,gCAAgC;AAChC,wBAAgB,UAAU,CAAC,GAAG,EAAE,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,MAAM,CAqBhF;AAED,gDAAgD;AAChD,wBAAgB,UAAU,CAAC,GAAG,EAAE,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAuCjG;AAID,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC3C,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,yHAAyH;AACzH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAO,GAAG,mBAAmB,CAUjI;AAID;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAQ/F;AAED;;0EAE0E;AAC1E,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CASnG;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAWtI;AAID;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,OAAO,CAOxF;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED,mFAAmF;AACnF,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,MAAM,CAgBpF;AAED,4CAA4C;AAC5C,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,eAAe,EAAE,CAQzE;AAID,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG;IAAE,MAAM,EAAE,IAAI,GAAG,iBAAiB,CAAC;IAAC,MAAM,EAAE,WAAW,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,CAOxI"}
1
+ {"version":3,"file":"cli-agent.d.ts","sourceRoot":"","sources":["../src/cli-agent.ts"],"names":[],"mappings":"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"}
package/dist/cli-agent.js CHANGED
@@ -43,7 +43,12 @@ export function classifyApiError(error, context) {
43
43
  // (no such account)" said one thing three times.
44
44
  const base = e.message ? e.message : String(error);
45
45
  if (e.violations !== undefined) {
46
- return { code: "VALIDATION_FAILED", message: base, detail: { ...(e.name ? { error: e.name } : {}), violations: e.violations }, nextSteps: ["Fix the fields named in detail.violations, or drop --validate to send the body as is."] };
46
+ const nextStep = e.direction === "response"
47
+ ? "The API response does not match its schema. Check detail.violations and the API specification."
48
+ : e.target === "parameters"
49
+ ? "Correct the parameter values named in detail.violations to match their constraints, then run the command again."
50
+ : "Correct the body fields named in detail.violations to match their constraints, then run the command again.";
51
+ return { code: "VALIDATION_FAILED", message: base, detail: { ...(e.name ? { error: e.name } : {}), violations: e.violations }, nextSteps: [nextStep] };
47
52
  }
48
53
  if (e.name === "TransportError" || (typeof e.status !== "number" && /fetch|ECONN|ENOTFOUND|timed out|TLS|abort/i.test(base))) {
49
54
  return {
@@ -280,7 +285,6 @@ export const MCP_CLIENTS = [
280
285
  file: (cwd) => join(cwd, ".cursor", "mcp.json"),
281
286
  detect: () => existsSync(join(home(), ".cursor")),
282
287
  write: (existing, name, entry) => jsonMerge(existing, ["mcpServers"], name, standardEntry(entry)),
283
- incompatible: "Cursor does not yet speak MCP 2026-07-28, which is the only version this server serves; the entry is written but Cursor will not connect until it does.",
284
288
  },
285
289
  ];
286
290
  export function findMcpClient(id) {
@@ -332,15 +336,15 @@ export function upsertAgentBlock(file, marker, body) {
332
336
  function escapeRegExp(text) {
333
337
  return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
334
338
  }
335
- /** AGENTS.md by default; CLAUDE.md when only it exists, or when running under Claude Code and AGENTS.md is absent. */
336
- export function agentInstructionsFile(cwd, harness) {
339
+ /** AGENTS.md for every harness; preserve an existing CLAUDE.md when AGENTS.md is absent. */
340
+ export function agentInstructionsFile(cwd) {
337
341
  const agents = join(cwd, "AGENTS.md");
338
342
  const claude = join(cwd, "CLAUDE.md");
339
343
  if (existsSync(agents))
340
344
  return agents;
341
345
  if (existsSync(claude))
342
346
  return claude;
343
- return harness === "claude-code" ? claude : agents;
347
+ return agents;
344
348
  }
345
349
  /** One line per command, pipe-delimited: the compact index that goes into AGENTS.md. */
346
350
  /** string, number, usd|eur, string[], usd|eur[], object, json — the type as a reader expects it. */
@@ -365,7 +369,7 @@ export function agentBlock(ctx, commands) {
365
369
  return [
366
370
  "## " + ctx.bin + " CLI (" + ctx.apiTitle + ")",
367
371
  "",
368
- "Generated by typeship. API commands write JSON on stdout; discovery commands take --json. Errors are JSON on stderr ({status, issues[{code,message}], next_steps}), exit 0/1/2. Non-interactive under an agent: no prompts, no browsers.",
372
+ "API commands write JSON on stdout; discovery commands take --json. Errors are JSON on stderr ({status, issues[{code,message}], next_steps}), exit 0/1/2. Non-interactive under an agent: no prompts, no browsers.",
369
373
  "",
370
374
  ...((ctx.omittedOperations?.length ?? 0) > 0 ? ["- Plan limit: generated " + (ctx.generatedOperationCount ?? commands.length) + " of " + ((ctx.generatedOperationCount ?? commands.length) + ctx.omittedOperations.length) + " operations. Omitted: " + ctx.omittedOperations.map((op) => "`" + op.tool + "` (" + op.method + " " + op.path + ")").join(", ") + ". These return `PLAN_LIMIT`; upgrade and regenerate before use."] : []),
371
375
  "- Auth: " + auth + " in the environment, or `" + ctx.bin + " login`. Never write a key into a file in this repo.",
@@ -442,8 +446,8 @@ export function installSkills(repo, options = {}) {
442
446
  // ---- file bundles ------------------------------------------------------------------
443
447
  /**
444
448
  * A response that carries files: an array property whose items have string
445
- * `path` and `content`. typeship's own generate call is one; any API that
446
- * returns generated or exported files is another. `--out <dir>` writes them.
449
+ * `path` and `content`, as an API that returns generated or exported files
450
+ * does. `--out <dir>` writes them.
447
451
  */
448
452
  export function bundleProperty(outputSchema) {
449
453
  const props = outputSchema?.properties;
@@ -462,7 +466,7 @@ export function bundleProperty(outputSchema) {
462
466
  export function collectionProperty(outputSchema) {
463
467
  const props = outputSchema?.properties;
464
468
  // Response metadata is not part of the collection's domain shape. APIs
465
- // such as typeship put request_id beside the array on every JSON response.
469
+ // may put request_id beside the array on every JSON response.
466
470
  const names = props ? Object.keys(props).filter((name) => name !== "request_id" && name !== "requestId") : [];
467
471
  if (!props || names.length !== 1)
468
472
  return null;
@@ -486,7 +490,7 @@ export function writeBundle(dir, files) {
486
490
  // ---- claims ----------------------------------------------------------------------------
487
491
  /**
488
492
  * A response that carries a claim: an object property `claim` with a string
489
- * `url` (typeship's anonymous generate is one). The CLI tells the person
493
+ * `url`, as an anonymous run that can later be saved has. The CLI tells the person
490
494
  * where to claim and leaves a breadcrumb in the working directory so a
491
495
  * later session (or `doctor`) can list what is still unclaimed.
492
496
  */
package/dist/cli.js CHANGED
@@ -20,6 +20,8 @@ import { homedir, hostname } from "node:os";
20
20
  import { basename, join } from "node:path";
21
21
  import { fileURLToPath } from "node:url";
22
22
  import { TypeshipClient, formatDebugEvent } from "./index.js";
23
+ import { validateAgainstSchema, ValidationError } from "./core/http.js";
24
+ import { SCHEMAS, DEFS } from "./schemas.js";
23
25
  import { GLOBALS, OMITTED_OPS, OPS, buildArgs, findOp, missingRequired } from "./ops.js";
24
26
  import { MCP_CLIENTS, agentGuide, agentBlock, agentInstructionsFile, agentMode, bundleProperty, claimProperty, classifyApiError, collectionProperty, detectHarness, envelope, exitCodeFor, findMcpClient, installSkills, mcpConfigured, pendingClaims, recordClaim, summarizeDoctor, upsertAgentBlock, writeBundle, writeMcpConfig, } from "./cli-agent.js";
25
27
  import { relativeDate } from "./dates.js";
@@ -33,7 +35,7 @@ const BASIC = null;
33
35
  const EXCLUDED_OPS = 0;
34
36
  /** Generated CLI operations that are intentionally unavailable to MCP. */
35
37
  const MCP_EXCLUDED_OPS = 0;
36
- const VERSION = "0.9.1";
38
+ const VERSION = "0.20.0";
37
39
  const API_VERSION = "1.0.0";
38
40
  const SPEC_FORMAT = "openapi";
39
41
  const IDENTITY_POLICY = {};
@@ -43,7 +45,7 @@ const ENVIRONMENTS = {};
43
45
  const HAS_MCP = false;
44
46
  const PKG_NAME = "@typeship-ax/cli";
45
47
  const UPDATE_NOTICE = false;
46
- const API_DESCRIPTION = "Resolve an OpenAPI or GraphQL Definition, diagnose it, and keep every\nselected SDK, CLI, and MCP Target current.\n\nEvery operation but one requires a bearer credential: an organization\nAPI key from the console, or an OAuth access token carrying the operation's\nread, generate, or write capability and the organization selected during\nconsent. OAuth grants cannot switch organizations after consent. A browser\nsession is not a credential for this API. The exception is POST /generate,\nwhich works anonymously with the free plan's limits.\n";
48
+ const API_DESCRIPTION = "Resolve an OpenAPI or GraphQL Definition, diagnose it, and keep every\nselected CLI, MCP, and SDK Target current.\n\nEvery operation but one requires a bearer credential: an organization\nAPI key from the console, or an OAuth access token carrying the operation's\nread, generate, or write capability and the organization selected during\nconsent. OAuth grants cannot switch organizations after consent. A browser\nsession is not a credential for this API. The exception is POST /generate,\nwhich works anonymously with the free plan's limits.\n\nExamples use Parcel, a fictional delivery service. Replace its domains,\nrepository names, and resource identifiers with your own. The hosted\npetstore Definition is a runnable sample.\n";
47
49
  const DOCS_URL_DEFAULT = "https://typeship.dev";
48
50
  const DOCS_INDEX_URL_DEFAULT = null;
49
51
  const RELAY = null;
@@ -136,7 +138,8 @@ function parseArgv(argv) {
136
138
  }
137
139
  else if (isBooleanFlag(arg.slice(2), positionals)) {
138
140
  const next = argv[i + 1];
139
- if (next === "true" || next === "false") {
141
+ const nullable = positionals.length >= 2 && findOp(positionals[0], positionals[1])?.params.some((p) => p.flag === arg.slice(2) && p.nullable);
142
+ if (next === "true" || next === "false" || (next === "null" && nullable)) {
140
143
  setFlag(arg.slice(2), next);
141
144
  i++;
142
145
  }
@@ -215,33 +218,32 @@ function out(value) {
215
218
  /** --fields a,b.c: the dotted paths to keep in API results (null = everything). Set in main(). */
216
219
  let FIELDS = null;
217
220
  /** Keep only FIELDS of a result: arrays item by item, objects by dotted path; scalars untouched. */
218
- function project(value) {
219
- if (FIELDS === null)
221
+ function project(value, paths = FIELDS) {
222
+ if (paths === null)
220
223
  return value;
221
224
  if (Array.isArray(value))
222
- return value.map(project);
225
+ return value.map((item) => project(item, paths));
223
226
  if (value === null || typeof value !== "object")
224
227
  return value;
228
+ const groups = new Map();
229
+ for (const [key, ...rest] of paths) {
230
+ if (key === undefined)
231
+ continue;
232
+ const group = groups.get(key);
233
+ if (group)
234
+ group.push(rest);
235
+ else
236
+ groups.set(key, [rest]);
237
+ }
225
238
  const out = {};
226
- for (const path of FIELDS) {
227
- let cursor = value;
228
- for (const key of path) {
229
- if (cursor === null || typeof cursor !== "object" || Array.isArray(cursor)) {
230
- cursor = undefined;
231
- break;
232
- }
233
- cursor = cursor[key];
234
- }
235
- if (cursor === undefined)
239
+ for (const [key, rests] of groups) {
240
+ const child = value[key];
241
+ if (child === undefined)
236
242
  continue;
237
- let target = out;
238
- for (const key of path.slice(0, -1)) {
239
- const next = target[key];
240
- if (next === undefined || next === null || typeof next !== "object" || Array.isArray(next))
241
- target[key] = {};
242
- target = target[key];
243
- }
244
- target[path[path.length - 1]] = cursor;
243
+ if (rests.some((rest) => rest.length === 0))
244
+ out[key] = child;
245
+ else if (child !== null && typeof child === "object")
246
+ out[key] = project(child, rests);
245
247
  }
246
248
  return out;
247
249
  }
@@ -292,12 +294,24 @@ function humanError(body, code) {
292
294
  lines.push(" " + paintErr("dim", (v.path ? v.path + ": " : "") + (v.message ?? "")));
293
295
  }
294
296
  else if (detail?.body !== undefined) {
295
- // The API's own body, when the message above did not already come from
296
- // it; the request id always, for support tickets.
297
- const compact = typeof detail.body === "string" ? detail.body : JSON.stringify(detail.body);
298
- const firstWords = (issue?.message ?? "").slice(0, 40);
299
- if (compact && compact !== "{}" && !(firstWords && compact.includes(firstWords)))
300
- lines.push(" " + paintErr("dim", "API said: " + (compact.length > 300 ? compact.slice(0, 297) + "…" : compact)));
297
+ // Keep every API error and its field visible, even when the headline
298
+ // already used the first message. Unstructured bodies retain a summary.
299
+ const apiErrors = typeof detail.body === "object" && detail.body !== null
300
+ ? detail.body.errors : undefined;
301
+ const entries = Array.isArray(apiErrors) ? apiErrors.filter((entry) => entry !== null && typeof entry === "object" && typeof entry.message === "string") : [];
302
+ if (entries.length > 0) {
303
+ for (const entry of entries) {
304
+ const field = typeof entry.field === "string" ? entry.field : "";
305
+ const location = typeof entry.in === "string" ? entry.in + " " : "";
306
+ lines.push(" " + paintErr("dim", (field ? location + field + ": " : "") + entry.message));
307
+ }
308
+ }
309
+ else {
310
+ const compact = typeof detail.body === "string" ? detail.body : JSON.stringify(detail.body);
311
+ const firstWords = (issue?.message ?? "").slice(0, 40);
312
+ if (compact && compact !== "{}" && !(firstWords && compact.includes(firstWords)))
313
+ lines.push(" " + paintErr("dim", "API said: " + (compact.length > 300 ? compact.slice(0, 297) + "…" : compact)));
314
+ }
301
315
  const requestId = detail.request_id ?? detail.body?.request_id ?? detail.body?.requestId;
302
316
  if (typeof requestId === "string")
303
317
  lines.push(" " + paintErr("dim", "request id: " + requestId));
@@ -668,7 +682,6 @@ async function cmdLogin(parsed) {
668
682
  ...AUTH_SCALARS.map((a) => " " + BIN + " login --" + a.flag + " <value>"),
669
683
  ...(CLI_AUTH_URL ? [" " + BIN + " login approve in the browser: a key is minted for you (add --no-browser to print the link instead of opening it)"] : []),
670
684
  " " + BIN + " login --with-token read the credential from stdin (CI)",
671
- " " + BIN + " login --console-check <file> test browser login for your Typeship Console without replacing saved logins",
672
685
  ...(HAS_OAUTH_LOGIN ? [" " + BIN + " login --client-id <id> OAuth " + OAUTH_LOGIN_METHOD + " login" + (OAUTH_CLIENT_ID ? " (a default id is built in)" : "")] : []),
673
686
  ...(HAS_OAUTH_LOGIN ? [" " + BIN + " login --no-browser print the approval URL instead of opening a browser", " " + BIN + " login --device use device authorization when your provider supports it"] : []),
674
687
  ...(BASIC ? [" " + BIN + " login --username <u> --password <p>"] : []),
@@ -963,12 +976,11 @@ async function cmdMcp(parsed) {
963
976
  " " + BIN + " mcp install --codex Codex CLI (~/.codex/config.toml)",
964
977
  " " + BIN + " mcp install --vscode VS Code (./.vscode/mcp.json)",
965
978
  " " + BIN + " mcp install --windsurf | --gemini | --opencode | --zed | --claude-desktop",
966
- " " + BIN + " mcp install --cursor Cursor (./.cursor/mcp.json; see note below)",
979
+ " " + BIN + " mcp install --cursor Cursor (./.cursor/mcp.json)",
967
980
  " " + BIN + " mcp --url <https://...> use a remote MCP endpoint instead of the local server",
968
981
  " " + BIN + " mcp install --claude --read-only register a read-only server (writes are not callable)",
969
982
  "",
970
983
  (MCP_URL ? "Default entry: the hosted endpoint " + MCP_URL + " with the auth env var as a reference (never a literal key)." : "Default entry: this package's local stdio server, which reads credentials saved by '" + BIN + " login' or the CLI's auth env vars."),
971
- "--all skips Cursor until it speaks MCP 2026-07-28.",
972
984
  ];
973
985
  process.stdout.write(lines.join("\n") + "\n");
974
986
  await flushExit(0);
@@ -1066,7 +1078,7 @@ function commandSummaries() {
1066
1078
  paginated: op.paginated,
1067
1079
  destructive: op.safety === "destructive",
1068
1080
  auth: op.auth,
1069
- flags: op.params.filter((p) => p.kind !== "path").map((p) => ({ flag: p.flag, type: p.type, ...(p.items ? { items: p.items } : {}), ...(p.enum ? { enum: p.enum } : {}), required: p.required, ...(p.description ? { description: p.description.split("\n")[0] } : {}) })),
1081
+ flags: op.params.filter((p) => p.kind !== "path").map((p) => ({ flag: p.flag, type: p.type, ...(p.nullable ? { nullable: true } : {}), ...(p.items ? { items: p.items } : {}), ...(p.enum ? { enum: p.enum } : {}), required: p.required, ...(p.description ? { description: p.description.split("\n")[0] } : {}) })),
1070
1082
  }));
1071
1083
  }
1072
1084
  /**
@@ -1215,7 +1227,7 @@ async function cmdDoctor(parsed) {
1215
1227
  }
1216
1228
  const checks = [];
1217
1229
  const nodeMajor = Number(process.versions.node.split(".")[0]);
1218
- checks.push({ name: "node", ok: nodeMajor >= 18, detail: process.version, ...(nodeMajor >= 18 ? {} : { fix: "Install Node 18 or newer." }) });
1230
+ checks.push({ name: "node", ok: nodeMajor >= 20, detail: process.version, ...(nodeMajor >= 20 ? {} : { fix: "Install Node 20 or newer." }) });
1219
1231
  checks.push({ name: "cli", ok: true, detail: BIN + " " + VERSION + " (" + PKG_NAME + ")" });
1220
1232
  let source = null;
1221
1233
  let storageProblem;
@@ -1276,7 +1288,7 @@ async function cmdDoctor(parsed) {
1276
1288
  * init: the one command that connects a machine (or a repo) to this API.
1277
1289
  * Stores a credential when given one, installs the skills repository, writes
1278
1290
  * MCP config for every agent client found, and upserts a marked block into
1279
- * AGENTS.md (CLAUDE.md under Claude Code). Idempotent; --all takes the
1291
+ * AGENTS.md (or an existing CLAUDE.md when AGENTS.md is absent). Idempotent; --all takes the
1280
1292
  * defaults without asking; every part reports and none of them fails init.
1281
1293
  */
1282
1294
  async function cmdInit(parsed) {
@@ -1288,7 +1300,7 @@ async function cmdInit(parsed) {
1288
1300
  " --all do everything without prompting (implied under an agent)",
1289
1301
  " --no-skills | --no-mcp | --no-agents-md skip a part",
1290
1302
  "",
1291
- "Writes: " + credsPath() + " (credential), the skills directory of each agent on this machine" + (SKILLS_REPO ? " (npx skills add " + SKILLS_REPO + ")" : " (no skills repository configured)") + ", MCP config for detected clients, and a '" + BIN + "' block in ./AGENTS.md.",
1303
+ "Writes: " + credsPath() + " (credential), the skills directory of each agent on this machine" + (SKILLS_REPO ? " (npx skills add " + SKILLS_REPO + ")" : " (no skills repository configured)") + ", MCP config for detected clients, and a '" + BIN + "' block in ./AGENTS.md (or an existing ./CLAUDE.md when AGENTS.md is absent).",
1292
1304
  ].join("\n") + "\n");
1293
1305
  await flushExit(0);
1294
1306
  }
@@ -1361,7 +1373,7 @@ async function cmdInit(parsed) {
1361
1373
  report.agents_md = { status: "skipped" };
1362
1374
  }
1363
1375
  else {
1364
- const file = agentInstructionsFile(cwd, harness);
1376
+ const file = agentInstructionsFile(cwd);
1365
1377
  const result = upsertAgentBlock(file, BIN + " agent-contract", agentBlock(agentContext(), commandSummaries()));
1366
1378
  report.agents_md = { status: result.updated ? "updated" : "written", file: result.file };
1367
1379
  }
@@ -1928,6 +1940,8 @@ function helpSentence(description) {
1928
1940
  }
1929
1941
  /** Type column text for a param: string, number, string[], a|b|c, enum, object, json, path. */
1930
1942
  function typeLabel(p) {
1943
+ if (p.nullable)
1944
+ return typeLabel({ ...p, nullable: false }) + "|null";
1931
1945
  if (p.type === "file")
1932
1946
  return "path (uploaded)";
1933
1947
  if (p.format && p.type === "string")
@@ -2008,7 +2022,7 @@ function printRoot(stream = process.stdout) {
2008
2022
  }
2009
2023
  const width = termWidth();
2010
2024
  const lines = [];
2011
- lines.push(paintOut("bold", BIN) + ": " + "typeship API" + " (v" + "1.0.0" + "), package " + "0.9.1");
2025
+ lines.push(paintOut("bold", BIN) + ": " + "typeship API" + " (v" + "1.0.0" + "), package " + "0.20.0");
2012
2026
  lines.push("");
2013
2027
  lines.push(paintOut("bold", "Usage:") + " " + BIN + " <resource> <command> [args] [--flags]");
2014
2028
  lines.push("");
@@ -2033,7 +2047,7 @@ function printRoot(stream = process.stdout) {
2033
2047
  lines.push(...labeled("Upgrade: ", "https://typeship.dev/pricing, then regenerate without the operation cap", width, 14));
2034
2048
  }
2035
2049
  lines.push("");
2036
- const flagsText = "-v/--version, -h/--help, --debug, --non-interactive, --color on|off|auto, --base-url <url>, --profile <name>, --credentials @<file>|-, --data '<json>', --fields <a,b.c>, --all (paginated lists), --validate (schema-check bodies)" +
2050
+ const flagsText = "-v/--version, -h/--help, --debug, --non-interactive, --color on|off|auto, --base-url <url>, --profile <name>, --credentials @<file>|-, --data '<json>', --fields <a,b.c>, --all (paginated lists), --validate (schema-check parameters and JSON bodies)" +
2037
2051
  (AUTH_SCALARS.length > 0 ? ", " + AUTH_SCALARS.map((a) => "--" + a.flag + " <value>").join(", ") : "");
2038
2052
  lines.push(...labeled(paintOut("bold", "Global flags:") + " ", flagsText, width, 14).map((l, i) => (i === 0 ? l : l)));
2039
2053
  lines.push(...labeled("Credential env vars: ", [
@@ -2094,17 +2108,18 @@ function commandExtras(op) {
2094
2108
  extras.push(["--all", "stream every item from every page (NDJSON)"]);
2095
2109
  const collectionField = collectionProperty(op.outputSchema);
2096
2110
  extras.push(["--fields <a,b.c>", "keep only these fields of the result" + (op.paginated ? " (per item)" : collectionField ? " (per item in " + collectionField + ")" : "")]);
2097
- if (bundleProperty(op.outputSchema) !== null)
2111
+ if ((op.fileBundleProperty ?? bundleProperty(op.outputSchema)) !== null)
2098
2112
  extras.push(["--out <dir>", "write the response's files ({path, content}) into a directory"]);
2099
2113
  if (op.safety === "destructive")
2100
2114
  extras.push(["--force, -y", "destructive: required without a terminal, skips the prompt with one"]);
2101
2115
  return extras;
2102
2116
  }
2103
- /** One runnable example built from the required inputs. */
2117
+ /** One runnable example from required inputs and authored optional values. */
2104
2118
  function exampleLine(op) {
2105
2119
  const parts = [BIN, op.command[0], op.command[1]];
2106
2120
  for (const p of op.params) {
2107
- if (!p.required)
2121
+ const hasExample = p.type !== "file" && Object.hasOwn(op.exampleArguments, p.name);
2122
+ if (!p.required && !hasExample)
2108
2123
  continue;
2109
2124
  const generated = p.type === "file" ? undefined : op.exampleArguments[p.name];
2110
2125
  const values = p.type === "array" ? p.items?.enum : p.enum;
@@ -2115,7 +2130,7 @@ function exampleLine(op) {
2115
2130
  : p.type === "object" ? {}
2116
2131
  : p.type === "array" ? [p.items?.type === "number" ? 1 : "value"]
2117
2132
  : "value";
2118
- const value = generated ?? fallback;
2133
+ const value = hasExample ? generated : fallback;
2119
2134
  const sample = typeof value === "string" ? shellQuote(value)
2120
2135
  : typeof value === "object" ? shellQuote(JSON.stringify(value))
2121
2136
  : String(value);
@@ -2124,10 +2139,11 @@ function exampleLine(op) {
2124
2139
  else
2125
2140
  parts.push("--" + p.flag, sample);
2126
2141
  }
2127
- const required = op.bodyStyle === "data" && (op.inputSchema.required ?? []).includes("body");
2128
- if (required) {
2129
- const body = op.exampleArguments.body;
2130
- parts.push(op.bodyKind === "binary" ? "--file ./file" : "--data " + shellQuote(JSON.stringify(body ?? {})));
2142
+ const showBody = op.bodyStyle === "data" && (Object.hasOwn(op.exampleArguments, "body")
2143
+ || (op.inputSchema.required ?? []).includes("body"));
2144
+ if (showBody) {
2145
+ const body = Object.hasOwn(op.exampleArguments, "body") ? op.exampleArguments.body : {};
2146
+ parts.push(op.bodyKind === "binary" ? "--file ./file" : "--data " + shellQuote(JSON.stringify(body)));
2131
2147
  }
2132
2148
  if (op.safety === "destructive")
2133
2149
  parts.push("--force");
@@ -2158,6 +2174,9 @@ function printOp(op) {
2158
2174
  if (op.paginated)
2159
2175
  lines.push(" " + usageLine(op) + " --all | jq -r '.id'");
2160
2176
  const arrayFlag = rows.find((p) => p.type === "array");
2177
+ if (rows.some((p) => p.nullable)) {
2178
+ lines.push("", "Nullable body flags accept null for JSON null. Use --data to send the literal string null.");
2179
+ }
2161
2180
  if (arrayFlag) {
2162
2181
  const sample = arrayFlag.items?.enum ? arrayFlag.items.enum.slice(0, 2).join(",") : arrayFlag.items?.type === "number" ? "1,2" : "a,b";
2163
2182
  lines.push("", "Array flags take a comma list (--" + arrayFlag.flag + " " + sample + "), the flag repeated, or a JSON array.");
@@ -2246,6 +2265,8 @@ function coerceScalar(flag, type, enumValues, text) {
2246
2265
  * Objects must be JSON. Enum values are checked locally.
2247
2266
  */
2248
2267
  function coerce(spec, raw, repeated) {
2268
+ if (spec.nullable && raw === "null" && repeated === undefined)
2269
+ return null;
2249
2270
  if (spec.type === "file") {
2250
2271
  if (raw === true)
2251
2272
  fail(2, "--" + spec.flag + " expects a file path");
@@ -2310,8 +2331,66 @@ function coerce(spec, raw, repeated) {
2310
2331
  }
2311
2332
  return coerceScalar(spec.flag, spec.type === "json" ? "json" : spec.type === "number" ? "number" : "string", spec.enum, text);
2312
2333
  }
2334
+ /** Use validation schemas, not the shortened agent-facing schemas: every union
2335
+ * branch and referenced definition must remain valid input. */
2336
+ function validateParameters(op, values, flags) {
2337
+ if (flags.get("validate") !== true)
2338
+ return;
2339
+ const schemas = SCHEMAS[op.resource + "." + op.method]?.params;
2340
+ if (!schemas)
2341
+ return;
2342
+ const violations = [];
2343
+ for (const parameter of op.params) {
2344
+ if (parameter.kind === "body")
2345
+ continue;
2346
+ let value = values[parameter.name];
2347
+ if (value === undefined && parameter.global) {
2348
+ const global = GLOBALS.find((entry) => entry.name === parameter.name);
2349
+ const raw = global ? process.env["TYPESHIP_" + global.envSuffix] : undefined;
2350
+ if (raw !== undefined)
2351
+ value = coerce(parameter, raw);
2352
+ }
2353
+ if (value === undefined)
2354
+ continue;
2355
+ if (parameter.kind === "path")
2356
+ value = coerce(parameter, String(value));
2357
+ const key = parameter.kind + "." + parameter.name;
2358
+ validateAgainstSchema(value, schemas[key], key, violations, DEFS);
2359
+ }
2360
+ if (violations.length)
2361
+ failApi(new ValidationError("request", violations, "parameters"), false);
2362
+ }
2313
2363
  /** Whether the last client built carried any credential; failApi tells NO_AUTH from AUTH_INVALID with it. */
2314
2364
  let LAST_CLIENT_HAD_CREDENTIAL = false;
2365
+ /** Check the same complete alternatives the request runtime can select, after
2366
+ * per-scheme flag, environment, profile, and OAuth resolution. */
2367
+ function requireOperationCredentials(op, options) {
2368
+ if (op.auth !== "required")
2369
+ return;
2370
+ const supplied = (value) => typeof value === "function" || (typeof value === "string" && value.length > 0)
2371
+ || (value !== null && typeof value === "object" && "username" in value && "password" in value && typeof value.username === "string" && value.username.length > 0 && typeof value.password === "string" && value.password.length > 0);
2372
+ const named = Object.fromEntries(Object.entries(options.credentials ?? {}).filter(([, value]) => supplied(value)));
2373
+ const available = namedCredentialAvailability(NAMED_SCHEMES, new Set(Object.keys(options).filter((key) => supplied(options[key]))), named);
2374
+ if (op.credentialOptions?.some((alternative) => alternative.length > 0 && alternative.every((option) => available.has(option))))
2375
+ return;
2376
+ const alternatives = (op.credentialOptions ?? []).filter((alternative) => alternative.length > 0 && alternative.every((option) => option.startsWith("credentials.")));
2377
+ const missing = alternatives.map((alternative) => alternative.filter((option) => !available.has(option)).map((option) => option.slice("credentials.".length)));
2378
+ const names = new Set(missing.flat());
2379
+ const relevant = AUTH_SCALARS.filter((scalar) => [...names].some((name) => NAMED_SCHEMES[name]?.options.includes(scalar.option)));
2380
+ const needsBasic = [...names].some((name) => NAMED_SCHEMES[name]?.options.includes("basicAuth"));
2381
+ failWith({
2382
+ status: "action_required",
2383
+ code: "NO_AUTH",
2384
+ message: op.command.join(" ") + " needs one complete credential alternative (" + wireOf(op) + "). " + (missing.length
2385
+ ? "Missing security schemes: " + missing.map((names) => names.join(" + ")).join(" OR ") + "."
2386
+ : "The declared security requirements have no supported, compatible alternative in this CLI."),
2387
+ nextSteps: alternatives.length ? [
2388
+ ...relevant.map((a) => "Set " + a.env + " in the environment, pass --" + a.flag + " <value>, or run '" + BIN + " login'."),
2389
+ ...(needsBasic && BASIC ? ["Set " + BASIC.envUser + " and " + BASIC.envPass + ", or pass --username and --password."] : []),
2390
+ "Supply all schemes in one alternative through " + "TYPESHIP_CREDENTIALS" + " or --credentials @<JSON-file>: " + alternatives.map((alternative) => alternative.map((option) => option.slice("credentials.".length)).join(" + ")).join(" OR ") + ".",
2391
+ ] : ["Check the operation's security schemes in the API definition and regenerate with a supported, compatible alternative."],
2392
+ });
2393
+ }
2315
2394
  function validateCredentialsInput(flags) {
2316
2395
  const input = flags.get("credentials");
2317
2396
  if (BASIC && flags.has("username") !== flags.has("password"))
@@ -2444,18 +2523,17 @@ async function makeClient(flags, op, candidate, forIdentity = false) {
2444
2523
  options[g.option] = value;
2445
2524
  }
2446
2525
  LAST_CLIENT_HAD_CREDENTIAL = Object.keys(options.credentials ?? {}).length > 0 || AUTH_SCALARS.some((a) => options[a.option] !== undefined) || options.basicAuth !== undefined || options.bearerToken !== undefined;
2447
- // Who is calling: the CLI, under which agent harness, and whether an
2448
- // agent is driving. "agent" means a harness was detected or the caller
2449
- // said so (--mode agent / env); a bare non-TTY run (CI, a pipeline) is
2450
- // "non-interactive", so usage by surface does not count CI as agents.
2451
- // The API can read it back; it carries no secrets.
2526
+ requireOperationCredentials(op, options);
2527
+ // Identify the package and version. Optional harness and caller details
2528
+ // let the API distinguish agent traffic from other non-interactive use.
2452
2529
  const harness = detectHarness();
2453
2530
  const explicitAgent = flags.get("mode") === "agent" || process.env["TYPESHIP_MODE"] === "agent";
2454
2531
  const behaving = agentMode({ flagMode: flags.get("mode"), envMode: process.env["TYPESHIP_MODE"], stdoutIsTTY: process.stdout.isTTY === true, stdinIsTTY: process.stdin.isTTY === true });
2455
- const caller = harness || explicitAgent ? "; agent" : behaving ? "; non-interactive" : "";
2532
+ const caller = harness || explicitAgent ? "agent" : behaving ? "non-interactive" : null;
2533
+ const details = [harness ? "harness=" + harness : null, caller].filter(Boolean).join("; ");
2456
2534
  options.defaultHeaders = {
2457
2535
  ...options.defaultHeaders,
2458
- "User-Agent": PKG_NAME + "-cli/" + VERSION + " (typeship" + (harness ? "; harness=" + harness : "") + caller + ")",
2536
+ "User-Agent": PKG_NAME + "-cli/" + VERSION + (details ? " (" + details + ")" : ""),
2459
2537
  };
2460
2538
  if (forIdentity) {
2461
2539
  options.fetch = identityFetch(baseUrl);
@@ -2528,8 +2606,8 @@ async function main() {
2528
2606
  fail(2, "--format json is the only format; output is always JSON.");
2529
2607
  }
2530
2608
  if (parsed.flags.has("version") || parsed.positionals[0] === "version") {
2531
- // "typeship 1.0.0 (typeship 1.0.0, ...)" said the name three times; when
2532
- // the API's title is the bin, name the API version as such.
2609
+ // "acme 1.0.0 (acme 1.0.0)" would say the name twice; when the API's
2610
+ // title is the bin, name the API version as such.
2533
2611
  const apiLabel = API_TITLE.toLowerCase().replace(/[^a-z0-9]/g, "") === BIN.toLowerCase().replace(/[^a-z0-9]/g, "") ? "API " + API_VERSION : API_TITLE + " " + API_VERSION;
2534
2612
  process.stdout.write(BIN + " " + VERSION + " (" + apiLabel + ", generated by typeship)\n");
2535
2613
  await flushExit(0);
@@ -2697,27 +2775,14 @@ async function main() {
2697
2775
  fail(2, "--fields expects at least one field path");
2698
2776
  }
2699
2777
  // --out <dir> materializes a file-shaped response (see cli-agent.ts bundleProperty).
2700
- const bundleField = bundleProperty(op.outputSchema);
2778
+ const bundleField = op.fileBundleProperty ?? bundleProperty(op.outputSchema);
2701
2779
  const collectionField = collectionProperty(op.outputSchema);
2702
2780
  const outDir = typeof parsed.flags.get("out") === "string" ? parsed.flags.get("out") : undefined;
2703
2781
  if (outDir !== undefined && bundleField === null) {
2704
2782
  fail(2, "--out applies to commands whose response carries files ({path, content}); " + op.command.join(" ") + " does not.");
2705
2783
  }
2706
- // The spec says this operation needs a credential and none resolved:
2707
- // say so now, locally, instead of sending a request to learn it.
2708
- if (op.auth === "required" && (AUTH_SCALARS.length > 0 || BASIC || HAS_OAUTH_LOGIN) && credentialSource(parsed.flags) === null) {
2709
- failWith({
2710
- status: "action_required",
2711
- code: "NO_AUTH",
2712
- message: op.command.join(" ") + " needs a credential (" + wireOf(op) + " is authenticated) and none was found.",
2713
- nextSteps: [
2714
- ...AUTH_SCALARS.map((a) => "Set " + a.env + " in the environment, pass --" + a.flag + " <value>, or run '" + BIN + " login'."),
2715
- ...(BASIC ? ["Set " + BASIC.envUser + " and " + BASIC.envPass + ", or pass --username and --password."] : []),
2716
- ...(AUTH_SCALARS.length === 0 && !BASIC ? ["Run '" + BIN + " login'."] : []),
2717
- "'" + BIN + " auth check' shows what the CLI would send.",
2718
- ],
2719
- });
2720
- }
2784
+ validateParameters(op, values, parsed.flags);
2785
+ const client = await makeClient(parsed.flags, op);
2721
2786
  // Destructive commands need --force. A person gets asked; an agent gets
2722
2787
  // an action_required envelope with the exact command to run, so nothing
2723
2788
  // is deleted on a guess.
@@ -2736,7 +2801,6 @@ async function main() {
2736
2801
  if (answer !== "y" && answer !== "yes")
2737
2802
  failWith({ status: "action_required", code: "CONFIRMATION_REQUIRED", message: "Cancelled.", nextSteps: ["Run again with --force to skip the prompt: " + rerun] });
2738
2803
  }
2739
- const client = await makeClient(parsed.flags, op);
2740
2804
  const selectValue = typeof parsed.flags.get("select") === "string" ? parsed.flags.get("select") : undefined;
2741
2805
  const args = buildArgs(op, values, dataBody, selectValue);
2742
2806
  const target = client[op.resource];
@@ -2752,7 +2816,19 @@ async function main() {
2752
2816
  failApi(e, LAST_CLIENT_HAD_CREDENTIAL);
2753
2817
  }
2754
2818
  }
2755
- const result = await callResult;
2819
+ let result = await callResult;
2820
+ if (result.ok && op.httpMethod === "POST" && op.path === "/projects/{project_id}/generations") {
2821
+ const batch = result.data;
2822
+ const generations = client.generations;
2823
+ const completed = [];
2824
+ for (const generation of batch.data) {
2825
+ const waited = await generations.wait(generation.id);
2826
+ if (!waited.ok)
2827
+ failApi(waited.error, LAST_CLIENT_HAD_CREDENTIAL);
2828
+ completed.push(waited.data);
2829
+ }
2830
+ result = { ...result, data: { ...batch, data: completed } };
2831
+ }
2756
2832
  if (result.ok) {
2757
2833
  if (op.sse) {
2758
2834
  // Server-sent events as NDJSON, one line per event, until the stream ends.
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Runtime core. Generated by typeship — https://typeship.dev
3
- * Zero dependencies: built on the platform fetch API (Node 18+, browsers, edge).
3
+ * Zero dependencies: built on the platform fetch API (Node 20+, browsers, edge).
4
4
  */
5
5
  export interface RequestOptions {
6
6
  /** Abort the request (composed with the per-attempt timeout). */
@@ -81,8 +81,9 @@ export interface Violation {
81
81
  * ApiResult, like every other failure. */
82
82
  export declare class ValidationError extends Error {
83
83
  readonly direction: "request" | "response";
84
+ readonly target: "body" | "parameters";
84
85
  readonly violations: Violation[];
85
- constructor(direction: "request" | "response", violations: Violation[]);
86
+ constructor(direction: "request" | "response", violations: Violation[], target?: "body" | "parameters");
86
87
  }
87
88
  /**
88
89
  * Validates against the depth-capped JSON Schema subset emitted in