@trydreamstate/cli 1.3.3 → 1.3.4

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 (65) hide show
  1. package/README.md +14 -7
  2. package/agent-plugin/.claude-plugin/plugin.json +1 -1
  3. package/agent-plugin/.codex-plugin/plugin.json +1 -1
  4. package/agent-plugin/hooks/approve-readonly.sh +2 -2
  5. package/agent-plugin/hooks/hooks.json +1 -1
  6. package/agent-plugin/skills/crm/SKILL.md +2 -2
  7. package/agent-plugin/skills/diagnostics/SKILL.md +3 -1
  8. package/agent-plugin/skills/dreamstate/SKILL.md +5 -3
  9. package/agent-plugin/skills/first-win/SKILL.md +2 -2
  10. package/agent-plugin/skills/inbox-replies/SKILL.md +3 -1
  11. package/agent-plugin/skills/knowledge/SKILL.md +3 -5
  12. package/agent-plugin/skills/linkedin-posts/SKILL.md +3 -1
  13. package/agent-plugin/skills/linkedin-warm-signals/SKILL.md +2 -2
  14. package/agent-plugin/skills/list-building/SKILL.md +3 -8
  15. package/agent-plugin/skills/list-building/column-authoring.md +1 -1
  16. package/agent-plugin/skills/list-building/sourcing.md +2 -2
  17. package/agent-plugin/skills/outreach/SKILL.md +2 -2
  18. package/agent-plugin/skills/plays/SKILL.md +3 -3
  19. package/agent-plugin/skills/reddit-posts/SKILL.md +3 -1
  20. package/agent-plugin/skills/skill-authoring/SKILL.md +3 -1
  21. package/agent-plugin/skills/social/SKILL.md +3 -5
  22. package/agent-plugin/skills/visibility/SKILL.md +2 -6
  23. package/agent-plugin/skills/workflows/SKILL.md +2 -2
  24. package/agent-plugin/skills/workflows/lifecycle-and-enrollment.md +1 -1
  25. package/agent-plugin/skills/worksheet-tidy/SKILL.md +3 -1
  26. package/agent-plugin/skills/writing/SKILL.md +3 -5
  27. package/agent-plugin/skills/x-posts/SKILL.md +3 -1
  28. package/dist/agentGuidance.generated.json +4 -4
  29. package/dist/capabilityPosture.d.ts +12 -0
  30. package/dist/capabilityPosture.d.ts.map +1 -0
  31. package/dist/capabilityPosture.js +39 -0
  32. package/dist/client.d.ts +5 -3
  33. package/dist/client.d.ts.map +1 -1
  34. package/dist/client.js +69 -60
  35. package/dist/commands/sequences.d.ts +3 -2
  36. package/dist/commands/sequences.d.ts.map +1 -1
  37. package/dist/commands/sequences.js +19 -37
  38. package/dist/commands/shared.d.ts.map +1 -1
  39. package/dist/commands/shared.js +20 -44
  40. package/dist/commands/workflows.d.ts +3 -2
  41. package/dist/commands/workflows.d.ts.map +1 -1
  42. package/dist/commands/workflows.js +19 -35
  43. package/dist/errors.d.ts +2 -6
  44. package/dist/errors.d.ts.map +1 -1
  45. package/dist/errors.js +10 -43
  46. package/dist/gatedRun.d.ts +0 -2
  47. package/dist/gatedRun.d.ts.map +1 -1
  48. package/dist/gatedRun.js +27 -51
  49. package/dist/generated/packVerbs.generated.json +492 -0
  50. package/dist/generated/runContract.generated.d.ts +4 -0
  51. package/dist/generated/runContract.generated.d.ts.map +1 -0
  52. package/dist/generated/runContract.generated.js +7 -0
  53. package/dist/index.d.ts +3 -2
  54. package/dist/index.d.ts.map +1 -1
  55. package/dist/index.js +49 -28
  56. package/dist/registryManifest.d.ts +6 -0
  57. package/dist/registryManifest.d.ts.map +1 -0
  58. package/dist/registryManifest.js +66 -0
  59. package/dist/runContract.d.ts +10 -0
  60. package/dist/runContract.d.ts.map +1 -0
  61. package/dist/runContract.js +13 -0
  62. package/dist/runWait.d.ts +0 -1
  63. package/dist/runWait.d.ts.map +1 -1
  64. package/dist/runWait.js +0 -13
  65. package/package.json +4 -2
@@ -1 +1 @@
1
- {"version":3,"file":"workflows.d.ts","sourceRoot":"","sources":["../../src/commands/workflows.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,cAAc,EAAe,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AAC5G,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAO3C,eAAO,MAAM,cAAc,EAAE,YAAY,EA4BxC,CAAC;AAEF,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,qBAAqB,gCAA4E,CAAC;AAC/G,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAG1J"}
1
+ {"version":3,"file":"workflows.d.ts","sourceRoot":"","sources":["../../src/commands/workflows.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiE,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AAC5G,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAInD,eAAO,MAAM,cAAc,EAAE,YAAY,EAMpC,CAAC;AAEN,eAAO,MAAM,eAAe,QAA+C,CAAC;AAC5E,eAAO,MAAM,qBAAqB,gCAA4E,CAAC;AAC/G,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,eAAe,GAAG,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAQjJ"}
@@ -1,45 +1,29 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.parseWorkflowsCommand = exports.WORKFLOWS_USAGE = exports.WORKFLOW_VERBS = void 0;
4
7
  exports.runWorkflowsCommand = runWorkflowsCommand;
5
8
  const shared_1 = require("./shared");
6
- const automation = [{ name: 'id', into: 'automation_id' }];
7
- const workflow = [{ name: 'id', into: 'workflow_id' }];
8
- // Route map only. `tools get` owns every remote parameter, type, requirement and
9
- // description. Positionals are documented CLI aliases for canonical input fields.
10
- exports.WORKFLOW_VERBS = [
11
- { verb: 'list', capabilityId: 'workflow.automations.list' },
12
- { verb: 'init', capabilityId: 'workflow.automations.lint', local: 'init' },
13
- { verb: 'get', capabilityId: 'workflow.automations.get', positional: automation },
14
- { verb: 'create', capabilityId: 'workflow.automations.compose' },
15
- { verb: 'update', capabilityId: 'workflow.automations.update', positional: automation },
16
- { verb: 'lint', capabilityId: 'workflow.automations.lint', positional: automation },
17
- { verb: 'preview', capabilityId: 'workflow.automations.preview', positional: automation },
18
- { verb: 'variables', capabilityId: 'workflow.automations.variables_list', positional: automation },
19
- { verb: 'node-catalog', capabilityId: 'workflow.automations.node_catalog' },
20
- { verb: 'node-inspect', capabilityId: 'workflow.automations.node_inspect' },
21
- { verb: 'node-add', capabilityId: 'workflow.automations.node_add', positional: automation },
22
- { verb: 'node-patch', capabilityId: 'workflow.automations.node_patch', positional: automation },
23
- { verb: 'node-remove', capabilityId: 'workflow.automations.node_remove', positional: automation },
24
- { verb: 'node-move', capabilityId: 'workflow.automations.node_move', positional: automation },
25
- { verb: 'field-options', capabilityId: 'workflow.automations.field_options' },
26
- { verb: 'draft-save', capabilityId: 'workflow.workflows.draft_save', positional: workflow },
27
- { verb: 'publish', capabilityId: 'workflow.workflows.draft_publish', positional: workflow },
28
- { verb: 'activate', capabilityId: 'workflow.workflows.activate', positional: workflow },
29
- { verb: 'deactivate', capabilityId: 'workflow.workflows.deactivate', positional: workflow },
30
- { verb: 'enroll', capabilityId: 'workflow.workflows.enroll_selection', positional: workflow },
31
- { verb: 'runs', capabilityId: 'workflow.workflows.runs_list', positional: workflow },
32
- { verb: 'run', capabilityId: 'workflow.workflows.run_trace_get', positional: workflow },
33
- { verb: 'retry', capabilityId: 'workflow.workflows.run_retry', positional: workflow },
34
- { verb: 'duplicate', capabilityId: 'workflow.automations.duplicate', positional: automation },
35
- { verb: 'archive', capabilityId: 'workflow.automations.archive', positional: automation },
36
- { verb: 'export', capabilityId: 'workflow.automations.export', positional: automation },
37
- { verb: 'import', capabilityId: 'workflow.automations.import' },
38
- ];
9
+ const errors_1 = require("../errors");
10
+ const packVerbs_generated_json_1 = __importDefault(require("../generated/packVerbs.generated.json"));
11
+ exports.WORKFLOW_VERBS = packVerbs_generated_json_1.default.verbs
12
+ .filter(({ command }) => command.startsWith('workflows '))
13
+ .map(({ command, capabilityId, positional, local }) => ({
14
+ verb: command.slice('workflows '.length), capabilityId,
15
+ ...(positional ? { positional } : {}),
16
+ ...(local === 'init' ? { local: 'init' } : {}),
17
+ }));
39
18
  exports.WORKFLOWS_USAGE = (0, shared_1.renderPackUsage)('workflows', exports.WORKFLOW_VERBS);
40
19
  exports.parseWorkflowsCommand = (0, shared_1.buildPackParser)('workflows', 'workflow', exports.WORKFLOW_VERBS, exports.WORKFLOWS_USAGE);
41
20
  async function runWorkflowsCommand(context, command, stdout) {
42
- if (command.command === 'pack' && command.verb === 'init')
43
- return (0, shared_1.runPackInit)('workflow', command, stdout);
21
+ // init writes a local file and calls no API, so it has no gated context.
22
+ if (command.command === 'pack' && command.verb === 'init') {
23
+ (0, shared_1.runPackInit)('workflow', command, stdout);
24
+ return;
25
+ }
26
+ if (!context)
27
+ throw new errors_1.CliUsageError('workflows commands other than init require an authenticated session.');
44
28
  await (0, shared_1.runPackCommand)(context, command, stdout);
45
29
  }
package/dist/errors.d.ts CHANGED
@@ -6,7 +6,7 @@ export declare class CliUsageError extends Error {
6
6
  * with a major version. `dreamstate --help` renders their stable meanings.
7
7
  *
8
8
  * Contract C5 (cross-surface): 0 ok, 1 generic, 2 usage, 3 auth, 4 not found,
9
- * 5 conflict/validation, 6 rate limited, 7 approval/consent/spend gate required,
9
+ * 5 conflict/validation, 6 rate limited, 7 repair.kind ask_user (a person must decide),
10
10
  * 8 cli_update_required, 9 other refusal. Where this CLI had already published a
11
11
  * different meaning it kept the published one and the mapping is documented:
12
12
  *
@@ -52,10 +52,6 @@ export declare const CLI_LOCAL_ERROR_REPAIRS: {
52
52
  readonly kind: "server_defect";
53
53
  readonly hint: "The API response was not a Dreamstate envelope; report the trace id if one was returned.";
54
54
  };
55
- readonly invalid_tool_turn_token: {
56
- readonly kind: "server_defect";
57
- readonly hint: "The API did not provide a runnable tool turn; retry after reporting the response trace id.";
58
- };
59
55
  readonly invalid_web_url: {
60
56
  readonly kind: "server_defect";
61
57
  readonly hint: "The API returned an invalid web URL; report the response trace id.";
@@ -73,6 +69,6 @@ export declare const CLI_LOCAL_ERROR_REPAIRS: {
73
69
  readonly hint: "Sign in with dreamstate login, then retry.";
74
70
  };
75
71
  };
76
- export declare function isApprovalGateCode(code: string | undefined): boolean;
72
+ export declare function isApprovalRepair(error: unknown): boolean;
77
73
  export declare function isLocalRefusalCode(code: string | undefined): boolean;
78
74
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,aAAc,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;CAaX,CAAC;AAEX;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CASlE,CAAC;AAEF,8EAA8E;AAC9E,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAS1B,CAAC;AAyCX,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEpE;AAQD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEpE"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,aAAc,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;CAaX,CAAC;AAEX;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQlE,CAAC;AAEF,8EAA8E;AAC9E,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAQ1B,CAAC;AAEX,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAMxD;AAQD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEpE"}
package/dist/errors.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CLI_LOCAL_ERROR_REPAIRS = exports.CLI_LOCAL_ERROR_CODES = exports.CLI_EXIT = exports.CliUsageError = void 0;
4
- exports.isApprovalGateCode = isApprovalGateCode;
4
+ exports.isApprovalRepair = isApprovalRepair;
5
5
  exports.isLocalRefusalCode = isLocalRefusalCode;
6
6
  class CliUsageError extends Error {
7
7
  constructor(message) {
@@ -15,7 +15,7 @@ exports.CliUsageError = CliUsageError;
15
15
  * with a major version. `dreamstate --help` renders their stable meanings.
16
16
  *
17
17
  * Contract C5 (cross-surface): 0 ok, 1 generic, 2 usage, 3 auth, 4 not found,
18
- * 5 conflict/validation, 6 rate limited, 7 approval/consent/spend gate required,
18
+ * 5 conflict/validation, 6 rate limited, 7 repair.kind ask_user (a person must decide),
19
19
  * 8 cli_update_required, 9 other refusal. Where this CLI had already published a
20
20
  * different meaning it kept the published one and the mapping is documented:
21
21
  *
@@ -50,7 +50,6 @@ exports.CLI_LOCAL_ERROR_CODES = {
50
50
  network_error: 'The request never reached the server (DNS, connection refused, TLS). Nothing executed.',
51
51
  request_timeout: 'The server did not answer in time. The effect may have happened. Read the target back first. If the effect is there, report it done. If not, repeat the identical call once with the first attempt\'s idempotency key, never a new one. If the read-back is inconclusive, or the repeat is refused pending acknowledgement, ask the person.',
52
52
  invalid_response: 'The server answered with something that is not a Dreamstate envelope.',
53
- invalid_tool_turn_token: 'tools get returned no tool_turn_token to run with.',
54
53
  invalid_web_url: 'The API returned a web_url that is not a safe http(s) URL.',
55
54
  web_url_unavailable: '--open was given but the response carries no web_url.',
56
55
  plugin_install_failed: 'dreamstate install could not install the plugin for any agent.',
@@ -61,51 +60,19 @@ exports.CLI_LOCAL_ERROR_REPAIRS = {
61
60
  network_error: { kind: 'wait', hint: 'Retry the unchanged request when network connectivity is available.' },
62
61
  request_timeout: { kind: 'ask_user', hint: 'Read the target back first. If absent, repeat once with the same idempotency key; otherwise ask the person.' },
63
62
  invalid_response: { kind: 'server_defect', hint: 'The API response was not a Dreamstate envelope; report the trace id if one was returned.' },
64
- invalid_tool_turn_token: { kind: 'server_defect', hint: 'The API did not provide a runnable tool turn; retry after reporting the response trace id.' },
65
63
  invalid_web_url: { kind: 'server_defect', hint: 'The API returned an invalid web URL; report the response trace id.' },
66
64
  web_url_unavailable: { kind: 'not_possible', hint: 'This result has no web URL to open.' },
67
65
  plugin_install_failed: { kind: 'ask_user', hint: 'Install a supported agent, then retry plugin installation.' },
68
66
  skills_authentication_required: { kind: 'ask_user', hint: 'Sign in with dreamstate login, then retry.' },
69
67
  };
70
- /**
71
- * Refusals that mean a person (or the caller's own spend decision) must supply
72
- * something before the run can proceed: an approval, a consent, a quote or a
73
- * spend ceiling. They exit 7, whatever HTTP status carried them, so a script
74
- * can stop and ask instead of retrying.
75
- */
76
- const GATE_CODES = new Set([
77
- 'approval_required',
78
- 'standing_approval_required',
79
- 'destructive_approval_required',
80
- 'owner_approval_required',
81
- 'knowledge_approval_required',
82
- 'content_approval_required',
83
- 'effect_unknown_approval_required',
84
- 'approval_cap_exceeded',
85
- 'approval_stale',
86
- 'agent_tool_policy_ask_before_changes',
87
- 'publish_confirmation_required',
88
- 'launch_authorization_required',
89
- 'publish_permission_required',
90
- 'delegation_grant_required',
91
- 'creator_consent_required',
92
- 'csv_replace_confirmation_required',
93
- 'quote_required',
94
- 'quote_mismatch',
95
- 'quote_stale',
96
- 'quote_already_used',
97
- 'spend_cap',
98
- 'spend_cap_required',
99
- 'spend_cap_too_low',
100
- 'cost_cap_exceeded',
101
- 'agent_paid_capability_requires_max_credits',
102
- 'max_rows_required',
103
- 'mode_required',
104
- 'sequence_send_cap_required',
105
- ]);
106
- const GATE_CODE_PATTERN = /(?:approval|consent|confirmation|authorization)_required$|requires_approval$/;
107
- function isApprovalGateCode(code) {
108
- return Boolean(code) && (GATE_CODES.has(code) || GATE_CODE_PATTERN.test(code));
68
+ function isApprovalRepair(error) {
69
+ if (!error || typeof error !== 'object')
70
+ return false;
71
+ const repair = error.repair;
72
+ if (!repair || typeof repair !== 'object')
73
+ return false;
74
+ const kind = repair.kind;
75
+ return kind === 'ask_user';
109
76
  }
110
77
  /**
111
78
  * Refusals the CLI decides locally, before running anything, that are not usage
@@ -1,8 +1,6 @@
1
1
  import { CliError, type DreamstateClient } from './client';
2
2
  import { type IdempotencyIdentity } from './idempotency';
3
3
  export declare function code(error: unknown): string | undefined;
4
- export declare function toolTurnToken(value: unknown): string;
5
- export declare function omitsToolTurnForInlineTableRead(capabilityId: string): boolean;
6
4
  /** The capability record inside a tools get response, or null when the shape is unknown. */
7
5
  export declare function capabilityRecord(fetched: unknown): Record<string, unknown> | null;
8
6
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"gatedRun.d.ts","sourceRoot":"","sources":["../src/gatedRun.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gatedRun.d.ts","sourceRoot":"","sources":["../src/gatedRun.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAA0B,KAAK,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEnF,OAAO,EAA4F,KAAK,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAoBnJ,wBAAgB,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAIvD;AAUD,4FAA4F;AAC5F,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAKjF;AAgBD;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,mBAAmB,GAAG,MAAM,GAAG,IAAI,CAKrI;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,SAAS,CAKzF;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAazF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAMrE;AAoCD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,gBAAgB,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,mGAAmG;IACnG,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B,KAAK,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD;AAED,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,sFAAsF;IACtF,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qFAAqF;IACrF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACzH;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,4EAA4E;IAC5E,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,qGAAqG;IACrG,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AASD,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC,CAsKvG;AAED,mGAAmG;AACnG,wBAAsB,cAAc,CAClC,OAAO,EAAE,eAAe,EACxB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,OAAO,CAAC,CAGlB"}
package/dist/gatedRun.js CHANGED
@@ -1,8 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.code = code;
4
- exports.toolTurnToken = toolTurnToken;
5
- exports.omitsToolTurnForInlineTableRead = omitsToolTurnForInlineTableRead;
6
4
  exports.capabilityRecord = capabilityRecord;
7
5
  exports.capabilityIdempotencyKey = capabilityIdempotencyKey;
8
6
  exports.parameterIdempotencyKey = parameterIdempotencyKey;
@@ -17,6 +15,9 @@ const idempotency_1 = require("./idempotency");
17
15
  const schemaCoercion_1 = require("./schemaCoercion");
18
16
  const runWait_1 = require("./runWait");
19
17
  const turnCache_1 = require("./turnCache");
18
+ const capabilityPosture_1 = require("./capabilityPosture");
19
+ const registryManifest_1 = require("./registryManifest");
20
+ const runContract_1 = require("./runContract");
20
21
  /**
21
22
  * The one path every capability run takes: `tools run` and every pack verb
22
23
  * (`sequences ...`, `workflows ...`) call runGated. Gating lives here and only
@@ -32,43 +33,12 @@ function code(error) {
32
33
  ? error.code
33
34
  : undefined;
34
35
  }
35
- function toolTurnToken(value) {
36
+ function optionalToolTurnToken(value) {
36
37
  const root = value && typeof value === 'object' ? value : {};
37
38
  const data = root.data && typeof root.data === 'object' ? root.data : {};
38
- if (typeof data.tool_turn_token === 'string' && data.tool_turn_token.trim())
39
- return data.tool_turn_token;
40
- throw new client_1.CliError('tools get did not return a tool_turn_token.', 'invalid_tool_turn_token', 0);
41
- }
42
- /**
43
- * Free sync reads. The server runs these on the inline read path when
44
- * the body has no tool_turn_token and the request has no Idempotency-Key
45
- * (isInlineReadEligible). A tools get before the run is a second HTTP the
46
- * read does not need. Measured 2026-10-04: tables.workbooks.get full live CLI
47
- * 0.726s against whoami 0.455s, about 0.27s of tools get per harness read-back.
48
- * knowledge.brain.context.get is the same class (catalog: credit_class free,
49
- * async_policy.mode sync, mutates not set). Live 2026-10-05 a standalone
50
- * tools get of that id was 0.400s including node startup, next to whoami
51
- * 0.422s, so the same-process skip is one HTTP, not a second process.
52
- * The set name is historical. Writes are not in this set: they stay fetch-first.
53
- */
54
- const INLINE_READ_CAPABILITIES = new Set([
55
- 'tables.workbooks.get',
56
- 'tables.workbooks.overview',
57
- 'tables.workbooks.list',
58
- 'tables.columns.list',
59
- 'tables.columns.stats',
60
- 'tables.rows.query',
61
- 'tables.rows.get',
62
- 'tables.rows.count',
63
- 'knowledge.brain.context.get',
64
- // Both are stored, free, synchronous inbox reads. Keeping either behind a
65
- // tools_get turns one list or thread open into two HTTP requests, while the
66
- // canonical inline-read gate already validates their read-only contract.
67
- 'unibox.inbox.unified_list',
68
- 'unibox.inbox.conversation_get',
69
- ]);
70
- function omitsToolTurnForInlineTableRead(capabilityId) {
71
- return INLINE_READ_CAPABILITIES.has(capabilityId);
39
+ return typeof data.tool_turn_token === 'string' && data.tool_turn_token.trim()
40
+ ? data.tool_turn_token
41
+ : undefined;
72
42
  }
73
43
  /** The capability record inside a tools get response, or null when the shape is unknown. */
74
44
  function capabilityRecord(fetched) {
@@ -138,7 +108,6 @@ function cliSurfaceRefusal(capabilityId, fetched) {
138
108
  return null;
139
109
  return new client_1.CliError(`${capabilityId} is not available on the CLI surface. Use the web app, MCP or the Architect for it.`, 'unsupported_capability', 0, { details: { capability_id: capabilityId, surface: 'cli' }, retryable: false });
140
110
  }
141
- const QUOTE_HASH_PATTERN = /^sha256:[a-f0-9]{64}$/;
142
111
  /**
143
112
  * What a quote prices: the params plus the ceiling. Keys that say how a call is
144
113
  * made, not what it does, are left out, like the server's own plan digest.
@@ -164,7 +133,7 @@ function quoteFromResult(value, depth = 0) {
164
133
  return null;
165
134
  }
166
135
  const entry = value;
167
- if (typeof entry.quote_hash === 'string' && QUOTE_HASH_PATTERN.test(entry.quote_hash)) {
136
+ if (typeof entry.quote_hash === 'string' && runContract_1.QUOTE_HASH_PATTERN.test(entry.quote_hash)) {
168
137
  const estimate = entry.estimate && typeof entry.estimate === 'object' ? entry.estimate : null;
169
138
  return {
170
139
  quote_hash: entry.quote_hash,
@@ -230,26 +199,32 @@ async function runGated(context, input) {
230
199
  // and a quote is bound to the turn that asked for it. So a turn is reused
231
200
  // only while a quote is pending, together with the quote its dry run
232
201
  // returned, and forgotten once the paid run is admitted.
202
+ const explicitKey = parameterIdempotencyKey(body) ?? input.idempotencyKey;
233
203
  const fingerprint = planFingerprint(body);
234
204
  const cached = input.turnToken
235
205
  ? null
236
206
  : await (0, turnCache_1.reusableTurn)(context.turnsPath, context.baseUrl, context.turnKey, capabilityId, fingerprint, Date.now(), warnTurnCache);
237
207
  const pending = cached?.token ?? null;
238
208
  const live = body.mode === 'live';
239
- const inlineRead = !input.turnToken && !pending && !input.idempotencyKey && omitsToolTurnForInlineTableRead(capabilityId);
240
- if (!input.turnToken && !pending && !inlineRead)
209
+ // --turn-token is the contract. Do not fetch tools get to invent one.
210
+ // A cached inline read also skips the fetch until registry_hash changes.
211
+ const cachedPosture = input.turnToken ? null : (0, registryManifest_1.lookupPosture)(capabilityId);
212
+ const inlineFromCache = !input.turnToken && !pending && !explicitKey && cachedPosture?.inlineRead === true;
213
+ if (!input.turnToken && !pending && !inlineFromCache)
241
214
  await contract();
215
+ const posture = fetched ? (0, capabilityPosture_1.postureFromContract)(fetched) : cachedPosture;
216
+ if (fetched && posture)
217
+ (0, registryManifest_1.rememberPosture)(capabilityId, posture);
242
218
  const refusal = fetched ? cliSurfaceRefusal(capabilityId, fetched) : null;
243
219
  if (refusal)
244
220
  throw refusal;
245
- let turnToken = input.turnToken ?? pending ?? (inlineRead ? undefined : toolTurnToken(fetched));
221
+ const inlineRead = !input.turnToken && !pending && !explicitKey && posture?.inlineRead === true;
222
+ let turnToken = input.turnToken ?? pending ?? (inlineRead ? undefined : optionalToolTurnToken(fetched));
246
223
  // Only a quote the caller named or a dry run of this exact input returned.
247
224
  // The server's refusal also shows a price, but that one is information, not consent.
248
225
  let quoteHash = typeof body.quote_hash === 'string'
249
226
  ? body.quote_hash
250
227
  : live ? cached?.quote_hash ?? undefined : undefined;
251
- const explicitKey = parameterIdempotencyKey(body) ?? input.idempotencyKey;
252
- let recoveredInlineRead = false;
253
228
  let ranDryRun = false;
254
229
  let sentKey = null;
255
230
  const requestBody = () => ({
@@ -287,13 +262,14 @@ async function runGated(context, input) {
287
262
  result = await run();
288
263
  }
289
264
  catch (error) {
290
- // The inline skip is only valid while the server still treats this
291
- // capability as a free sync read. capability_not_fetched means the
292
- // fetch-first fence is on, so retry once on the old get-then-run path.
293
- if (inlineRead && !recoveredInlineRead && code(error) === 'capability_not_fetched') {
294
- recoveredInlineRead = true;
265
+ if (!input.turnToken && code(error) === 'capability_not_fetched') {
266
+ // Capability posture can change between tools get and run. Refresh it
267
+ // once rather than maintaining a client-side list of token-free reads.
295
268
  fetched = await client.getTool(capabilityId);
296
- turnToken = toolTurnToken(fetched);
269
+ const refreshed = (0, capabilityPosture_1.postureFromContract)(fetched);
270
+ // The server just required a turn token, so this id is not an inline read.
271
+ (0, registryManifest_1.rememberPosture)(capabilityId, { ...refreshed, inlineRead: false });
272
+ turnToken = optionalToolTurnToken(fetched);
297
273
  result = await run();
298
274
  }
299
275
  else if (live && code(error) === 'quote_required' && !quoteHash && turnToken) {
@@ -352,7 +328,7 @@ async function runGated(context, input) {
352
328
  await (0, turnCache_1.forgetTurnToken)(context.turnsPath, context.baseUrl, context.turnKey, capabilityId, warnTurnCache);
353
329
  }
354
330
  let timedOut = false;
355
- if (!input.noWait && !(0, runWait_1.columnRunReturnsRunId)(capabilityId)) {
331
+ if (!input.noWait && !posture?.returnsRunId) {
356
332
  const waited = await (0, runWait_1.waitForRun)(client, result, input.waitTimeout, context.sleep);
357
333
  result = waited.value;
358
334
  timedOut = waited.timedOut;