@senpi/runtime 3.0.180 → 3.0.182

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 (135) hide show
  1. package/dist/actions/llm-decision/openclaw-llm-decision.d.ts +8 -0
  2. package/dist/actions/llm-decision/openclaw-llm-decision.d.ts.map +1 -1
  3. package/dist/actions/llm-decision/openclaw-llm-decision.js +56 -1
  4. package/dist/actions/llm-decision/openclaw-llm-decision.js.map +1 -1
  5. package/dist/approvals/approval-store.d.ts +37 -7
  6. package/dist/approvals/approval-store.d.ts.map +1 -1
  7. package/dist/approvals/approval-store.js +127 -23
  8. package/dist/approvals/approval-store.js.map +1 -1
  9. package/dist/approvals/telemetry.d.ts +27 -3
  10. package/dist/approvals/telemetry.d.ts.map +1 -1
  11. package/dist/approvals/telemetry.js +8 -4
  12. package/dist/approvals/telemetry.js.map +1 -1
  13. package/dist/approvals/tool-approval-gate.d.ts +79 -0
  14. package/dist/approvals/tool-approval-gate.d.ts.map +1 -1
  15. package/dist/approvals/tool-approval-gate.js +184 -15
  16. package/dist/approvals/tool-approval-gate.js.map +1 -1
  17. package/dist/approvals/turn-context.d.ts +271 -0
  18. package/dist/approvals/turn-context.d.ts.map +1 -0
  19. package/dist/approvals/turn-context.js +551 -0
  20. package/dist/approvals/turn-context.js.map +1 -0
  21. package/dist/cli/guide-commands.d.ts.map +1 -1
  22. package/dist/cli/guide-commands.js +17 -3
  23. package/dist/cli/guide-commands.js.map +1 -1
  24. package/dist/cli/senpi-commands.d.ts.map +1 -1
  25. package/dist/cli/senpi-commands.js +71 -4
  26. package/dist/cli/senpi-commands.js.map +1 -1
  27. package/dist/deploy/job.d.ts +32 -0
  28. package/dist/deploy/job.d.ts.map +1 -1
  29. package/dist/deploy/job.js +72 -7
  30. package/dist/deploy/job.js.map +1 -1
  31. package/dist/deploy/register.d.ts +11 -0
  32. package/dist/deploy/register.d.ts.map +1 -1
  33. package/dist/deploy/register.js +84 -2
  34. package/dist/deploy/register.js.map +1 -1
  35. package/dist/host/openclaw-host.d.ts +138 -0
  36. package/dist/host/openclaw-host.d.ts.map +1 -0
  37. package/dist/host/openclaw-host.js +177 -0
  38. package/dist/host/openclaw-host.js.map +1 -0
  39. package/dist/index.d.ts +46 -2
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +220 -12
  42. package/dist/index.js.map +1 -1
  43. package/dist/runtime/auto-update/coordinator.d.ts +203 -0
  44. package/dist/runtime/auto-update/coordinator.d.ts.map +1 -1
  45. package/dist/runtime/auto-update/coordinator.js +621 -12
  46. package/dist/runtime/auto-update/coordinator.js.map +1 -1
  47. package/dist/runtime/auto-update/gateway-restart.d.ts +60 -1
  48. package/dist/runtime/auto-update/gateway-restart.d.ts.map +1 -1
  49. package/dist/runtime/auto-update/gateway-restart.js +95 -21
  50. package/dist/runtime/auto-update/gateway-restart.js.map +1 -1
  51. package/dist/runtime/auto-update/idle-gate.d.ts +139 -0
  52. package/dist/runtime/auto-update/idle-gate.d.ts.map +1 -0
  53. package/dist/runtime/auto-update/idle-gate.js +217 -0
  54. package/dist/runtime/auto-update/idle-gate.js.map +1 -0
  55. package/dist/runtime/auto-update/install-results.d.ts +130 -0
  56. package/dist/runtime/auto-update/install-results.d.ts.map +1 -0
  57. package/dist/runtime/auto-update/install-results.js +264 -0
  58. package/dist/runtime/auto-update/install-results.js.map +1 -0
  59. package/dist/runtime/auto-update/money-call-tracker.d.ts +36 -0
  60. package/dist/runtime/auto-update/money-call-tracker.d.ts.map +1 -0
  61. package/dist/runtime/auto-update/money-call-tracker.js +129 -0
  62. package/dist/runtime/auto-update/money-call-tracker.js.map +1 -0
  63. package/dist/runtime/auto-update/register-idle-gate.d.ts +70 -0
  64. package/dist/runtime/auto-update/register-idle-gate.d.ts.map +1 -0
  65. package/dist/runtime/auto-update/register-idle-gate.js +123 -0
  66. package/dist/runtime/auto-update/register-idle-gate.js.map +1 -0
  67. package/dist/runtime/auto-update/run-update-command.d.ts +13 -0
  68. package/dist/runtime/auto-update/run-update-command.d.ts.map +1 -1
  69. package/dist/runtime/auto-update/run-update-command.js +18 -0
  70. package/dist/runtime/auto-update/run-update-command.js.map +1 -1
  71. package/dist/runtime/auto-update/state-store.d.ts +14 -1
  72. package/dist/runtime/auto-update/state-store.d.ts.map +1 -1
  73. package/dist/runtime/auto-update/state-store.js +37 -3
  74. package/dist/runtime/auto-update/state-store.js.map +1 -1
  75. package/dist/runtime/auto-update/types.d.ts +51 -0
  76. package/dist/runtime/auto-update/types.d.ts.map +1 -1
  77. package/dist/runtime/auto-update/types.js.map +1 -1
  78. package/dist/runtime/auto-update/update-marker.d.ts +95 -0
  79. package/dist/runtime/auto-update/update-marker.d.ts.map +1 -0
  80. package/dist/runtime/auto-update/update-marker.js +185 -0
  81. package/dist/runtime/auto-update/update-marker.js.map +1 -0
  82. package/dist/runtime/auto-update/update-schedule.d.ts +57 -0
  83. package/dist/runtime/auto-update/update-schedule.d.ts.map +1 -0
  84. package/dist/runtime/auto-update/update-schedule.js +75 -0
  85. package/dist/runtime/auto-update/update-schedule.js.map +1 -0
  86. package/dist/runtime/decision-errors.d.ts +7 -0
  87. package/dist/runtime/decision-errors.d.ts.map +1 -1
  88. package/dist/runtime/decision-errors.js +15 -0
  89. package/dist/runtime/decision-errors.js.map +1 -1
  90. package/dist/senpi/client.d.ts +25 -0
  91. package/dist/senpi/client.d.ts.map +1 -1
  92. package/dist/senpi/client.js +56 -0
  93. package/dist/senpi/client.js.map +1 -1
  94. package/dist/telemetry/metrics.d.ts +14 -0
  95. package/dist/telemetry/metrics.d.ts.map +1 -1
  96. package/dist/telemetry/metrics.js +24 -0
  97. package/dist/telemetry/metrics.js.map +1 -1
  98. package/dist/telemetry/otel-sdk.d.ts +12 -0
  99. package/dist/telemetry/otel-sdk.d.ts.map +1 -1
  100. package/dist/telemetry/otel-sdk.js +47 -1
  101. package/dist/telemetry/otel-sdk.js.map +1 -1
  102. package/dist/telemetry/spans/span-hooks.d.ts +18 -1
  103. package/dist/telemetry/spans/span-hooks.d.ts.map +1 -1
  104. package/dist/telemetry/spans/span-hooks.js +306 -96
  105. package/dist/telemetry/spans/span-hooks.js.map +1 -1
  106. package/dist/telemetry/tool-plane.d.ts +2 -0
  107. package/dist/telemetry/tool-plane.d.ts.map +1 -1
  108. package/dist/telemetry/tool-plane.js +1 -0
  109. package/dist/telemetry/tool-plane.js.map +1 -1
  110. package/dist/tool-surface/crib-cache.d.ts +21 -0
  111. package/dist/tool-surface/crib-cache.d.ts.map +1 -0
  112. package/dist/tool-surface/crib-cache.js +54 -0
  113. package/dist/tool-surface/crib-cache.js.map +1 -0
  114. package/dist/tool-surface/crib-hook.d.ts +78 -0
  115. package/dist/tool-surface/crib-hook.d.ts.map +1 -0
  116. package/dist/tool-surface/crib-hook.js +217 -0
  117. package/dist/tool-surface/crib-hook.js.map +1 -0
  118. package/dist/tool-surface/crib-sheet.d.ts +56 -0
  119. package/dist/tool-surface/crib-sheet.d.ts.map +1 -0
  120. package/dist/tool-surface/crib-sheet.js +129 -0
  121. package/dist/tool-surface/crib-sheet.js.map +1 -0
  122. package/dist/tool-surface/mcp-tool-source.d.ts +64 -0
  123. package/dist/tool-surface/mcp-tool-source.d.ts.map +1 -0
  124. package/dist/tool-surface/mcp-tool-source.js +189 -0
  125. package/dist/tool-surface/mcp-tool-source.js.map +1 -0
  126. package/dist/utils/event-catalog.d.ts +117 -5
  127. package/dist/utils/event-catalog.d.ts.map +1 -1
  128. package/dist/utils/event-catalog.js +19 -0
  129. package/dist/utils/event-catalog.js.map +1 -1
  130. package/dist/widgets/tool.d.ts +9 -0
  131. package/dist/widgets/tool.d.ts.map +1 -1
  132. package/dist/widgets/tool.js +1 -0
  133. package/dist/widgets/tool.js.map +1 -1
  134. package/openclaw.plugin.json +11 -1
  135. package/package.json +5 -2
@@ -34,6 +34,14 @@ export declare function splitProviderModel(raw: string | undefined): {
34
34
  provider?: string;
35
35
  model?: string;
36
36
  };
37
+ /**
38
+ * Whether the host's llm-task plugin accepts a `provider`/`model` in the call:
39
+ * `plugins.entries["llm-task"].llm.allowModelOverride === true` in a whole
40
+ * OpenClaw config. OpenClaw 10.x refuses any override without it
41
+ * (`openclaw-worktrees/v2026.10.10-beta.3/src/plugins/runtime/runtime-llm.runtime.ts:414-463`,
42
+ * policy owner = the calling plugin, `llm-task`). senpi-agent sets it (A7).
43
+ */
44
+ export declare function llmTaskModelOverrideAllowed(config: unknown): boolean;
37
45
  export declare class OpenClawLlmDecision implements LlmDecision {
38
46
  private readonly gatewayUrl;
39
47
  private readonly gatewayToken?;
@@ -1 +1 @@
1
- {"version":3,"file":"openclaw-llm-decision.d.ts","sourceRoot":"","sources":["../../../src/actions/llm-decision/openclaw-llm-decision.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAuBxF,MAAM,WAAW,0BAA0B;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CASjG;AAED,qBAAa,mBAAoB,YAAW,WAAW;IACrD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAS;gBAE3B,OAAO,CAAC,EAAE,0BAA0B;IAM1C,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;CAyF9E"}
1
+ {"version":3,"file":"openclaw-llm-decision.d.ts","sourceRoot":"","sources":["../../../src/actions/llm-decision/openclaw-llm-decision.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAwBxF,MAAM,WAAW,0BAA0B;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CASjG;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAUpE;AAoCD,qBAAa,mBAAoB,YAAW,WAAW;IACrD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAS;gBAE3B,OAAO,CAAC,EAAE,0BAA0B;IAM1C,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;CA2F9E"}
@@ -5,6 +5,7 @@ import { HEADER_ADDRESS, HEADER_CORRELATION_ID, HEADER_RECIPE_NAME, HEADER_RUNTI
5
5
  import { withRetry } from '../../utils/retry.js';
6
6
  import { isRetryableDecisionError } from '../../runtime/decision-errors.js';
7
7
  import { context as otelContext, propagation } from '@opentelemetry/api';
8
+ import { getOpenClawHost } from '../../host/openclaw-host.js';
8
9
  /** Max retries (total attempts = MAX_DECISION_RETRIES + 1) for transient llm-task failures. */
9
10
  const MAX_DECISION_RETRIES = 2;
10
11
  /** Fixed delay between retry attempts (ms). Backoff is intentionally simple for now. */
@@ -47,6 +48,57 @@ export function splitProviderModel(raw) {
47
48
  }
48
49
  return { provider: trimmed.slice(0, idx), model: trimmed.slice(idx + 1) };
49
50
  }
51
+ /**
52
+ * Whether the host's llm-task plugin accepts a `provider`/`model` in the call:
53
+ * `plugins.entries["llm-task"].llm.allowModelOverride === true` in a whole
54
+ * OpenClaw config. OpenClaw 10.x refuses any override without it
55
+ * (`openclaw-worktrees/v2026.10.10-beta.3/src/plugins/runtime/runtime-llm.runtime.ts:414-463`,
56
+ * policy owner = the calling plugin, `llm-task`). senpi-agent sets it (A7).
57
+ */
58
+ export function llmTaskModelOverrideAllowed(config) {
59
+ const rec = (v) => v && typeof v === 'object' && !Array.isArray(v) ? v : undefined;
60
+ const entries = rec(rec(rec(config)?.plugins)?.entries);
61
+ if (!entries)
62
+ return false;
63
+ // The host trims and lowercases plugin entry keys (`normalizePluginPolicyId`,
64
+ // 10.10 `src/plugins/plugin-policy-id.ts:11-13`), so ` LLM-Task ` is the same entry.
65
+ return Object.entries(entries).some(([key, entry]) => key.trim().toLowerCase() === 'llm-task' && rec(rec(entry)?.llm)?.allowModelOverride === true);
66
+ }
67
+ /**
68
+ * The 10.x preflight: throws when a model override is about to be sent to a
69
+ * modern host whose live config does not allow one. 10.x masks the host's
70
+ * refusal as a generic retryable 500, so without this every decision of such
71
+ * a strategy would retry twice and then report a transient hiccup. The thrown
72
+ * text classifies as the non-retryable {@link DecisionErrorCode} MODEL_OVERRIDE_NOT_ALLOWED.
73
+ *
74
+ * No-op on a legacy host, with no host record, or when no config can be read
75
+ * (neither `runtime.config.current()` nor the registration snapshot); the host
76
+ * still enforces its own policy then.
77
+ */
78
+ function assertModelOverrideAllowed(rawModel) {
79
+ const host = getOpenClawHost();
80
+ if (!host?.modern)
81
+ return;
82
+ let config;
83
+ try {
84
+ config = host.currentConfig();
85
+ }
86
+ catch {
87
+ return;
88
+ }
89
+ // Neither the live config nor the registration snapshot could be read.
90
+ if (!config || typeof config !== 'object')
91
+ return;
92
+ if (llmTaskModelOverrideAllowed(config))
93
+ return;
94
+ // Read by the agent and the user (raw cause in status and logs). It names the
95
+ // fix that works, a box update or Senpi support, and no config path: the
96
+ // flag is part of the box setup the Senpi agent image writes at boot, and a
97
+ // hand edit of the gateway config is not a fix the agent should make.
98
+ throw new Error(`llm-task model override not allowed: decision_model "${rawModel}" was not used because ` +
99
+ "this box's OpenClaw setup does not allow llm-task model overrides, a setting the Senpi agent image applies at boot. " +
100
+ 'This is a box setup problem, not a strategy problem: a box update from Senpi support fixes it; it cannot be fixed from inside the agent.');
101
+ }
50
102
  export class OpenClawLlmDecision {
51
103
  gatewayUrl;
52
104
  gatewayToken;
@@ -73,7 +125,10 @@ export class OpenClawLlmDecision {
73
125
  // (extensions/llm-task/src/llm-task-tool.ts).
74
126
  timeoutMs: 90_000,
75
127
  };
76
- const { provider, model } = splitProviderModel(request.model ?? this.defaultModel);
128
+ const rawModel = request.model ?? this.defaultModel;
129
+ const { provider, model } = splitProviderModel(rawModel);
130
+ if (provider || model)
131
+ assertModelOverrideAllowed(rawModel?.trim() ?? '');
77
132
  if (provider)
78
133
  args.provider = provider;
79
134
  if (model)
@@ -1 +1 @@
1
- {"version":3,"file":"openclaw-llm-decision.js","sourceRoot":"","sources":["../../../src/actions/llm-decision/openclaw-llm-decision.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"openclaw-llm-decision.js","sourceRoot":"","sources":["../../../src/actions/llm-decision/openclaw-llm-decision.ts"],"names":[],"mappings":"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"}
@@ -14,21 +14,51 @@ export declare const TOOL_APPROVALS_STATE_FILE = "tool-approvals.json";
14
14
  * redeploys, and plugin auto-updates.
15
15
  *
16
16
  * To make a tool prompt again, delete its entry from `tool-approvals.json`
17
- * (or the whole file) in the state dir.
17
+ * (or the whole file) in the state dir. That takes effect at the next gated
18
+ * call, with no restart.
18
19
  *
19
- * Load is synchronous (once, at plugin register()); writes are synchronous
20
- * atomic temp → rename, and only happen on an explicit user decision.
20
+ * The file is the source of truth, shared by every registry the host builds
21
+ * (chat, cron, …), each with its own store (RT566-02, RT566-10):
22
+ * - before every decision the store `stat`s the file and re-reads it only when
23
+ * its mtime, size or inode changed since the last read;
24
+ * - a missing file, or one that cannot be read or parsed, means no grants
25
+ * (every gated tool prompts); a bad file is logged once per version;
26
+ * - a write is read-modify-write: re-read the file, add this one grant, write
27
+ * atomically (temp → rename). It never drops a grant another registry wrote
28
+ * and never brings back one the user revoked.
21
29
  */
22
30
  export declare class ToolApprovalStore {
23
31
  private readonly logger?;
24
32
  private readonly filePath;
25
- private readonly allowAlways;
33
+ private allowAlways;
34
+ /** Signature of the file version `allowAlways` was read from (undefined: never read). */
35
+ private loadedSignature;
36
+ /** File version a grant was last refused a write for (warn once per version). */
37
+ private unwritableWarnedSignature;
26
38
  constructor(stateDir: string, logger?: LoggerLike | undefined);
27
- private load;
39
+ private signature;
40
+ /** One `stat`; re-read only when the file changed since the last read. */
41
+ private refresh;
42
+ /**
43
+ * Read and parse the file; any failure is no grants. `ok` is false when the
44
+ * file exists but cannot be read or parsed (a missing file is ok and empty).
45
+ */
46
+ private readFile;
28
47
  isAllowedAlways(tool: string): boolean;
29
48
  get size(): number;
30
- /** Record a user's allow-always decision and persist it immediately. */
31
- rememberAllowAlways(tool: string): void;
49
+ /**
50
+ * Record a user's allow-always decision and persist it immediately.
51
+ *
52
+ * @returns true when the grant is in the state file, false when it is kept in
53
+ * memory only (the file could not be read or written; a warn names why).
54
+ */
55
+ rememberAllowAlways(tool: string): boolean;
56
+ /**
57
+ * Write atomically. Returns the written file's signature, taken from the temp
58
+ * file before the rename (rename keeps inode, mtime and size), so a write by
59
+ * someone else right after the rename is seen at the next decision; undefined
60
+ * when the write failed.
61
+ */
32
62
  private persist;
33
63
  }
34
64
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"approval-store.d.ts","sourceRoot":"","sources":["../../src/approvals/approval-store.ts"],"names":[],"mappings":"AAGA,iFAAiF;AACjF,UAAU,UAAU;IAClB,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CAChC;AAED,qEAAqE;AACrE,eAAO,MAAM,yBAAyB,wBAAwB,CAAC;AAU/D;;;;;;;;;;;;;;GAcG;AACH,qBAAa,iBAAiB;IAM1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IAL1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuC;gBAGjE,QAAQ,EAAE,MAAM,EACC,MAAM,CAAC,EAAE,UAAU,YAAA;IAMtC,OAAO,CAAC,IAAI;IAiCZ,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAItC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,wEAAwE;IACxE,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQvC,OAAO,CAAC,OAAO;CAehB"}
1
+ {"version":3,"file":"approval-store.d.ts","sourceRoot":"","sources":["../../src/approvals/approval-store.ts"],"names":[],"mappings":"AAGA,iFAAiF;AACjF,UAAU,UAAU;IAClB,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CAChC;AAED,qEAAqE;AACrE,eAAO,MAAM,yBAAyB,wBAAwB,CAAC;AAc/D;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,iBAAiB;IAU1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IAT1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,WAAW,CAAuC;IAC1D,yFAAyF;IACzF,OAAO,CAAC,eAAe,CAA4B;IACnD,iFAAiF;IACjF,OAAO,CAAC,yBAAyB,CAA4B;gBAG3D,QAAQ,EAAE,MAAM,EACC,MAAM,CAAC,EAAE,UAAU,YAAA;IAMtC,OAAO,CAAC,SAAS;IAcjB,0EAA0E;IAC1E,OAAO,CAAC,OAAO;IAWf;;;OAGG;IACH,OAAO,CAAC,QAAQ;IAuChB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAKtC,IAAI,IAAI,IAAI,MAAM,CAGjB;IAED;;;;;OAKG;IACH,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAuC1C;;;;;OAKG;IACH,OAAO,CAAC,OAAO;CAqBhB"}
@@ -1,7 +1,8 @@
1
- import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
1
+ import { mkdirSync, readFileSync, renameSync, statSync, unlinkSync, writeFileSync } from "node:fs";
2
2
  import { dirname, join } from "node:path";
3
3
  /** File name inside the plugin state dir (volume-backed in prod). */
4
4
  export const TOOL_APPROVALS_STATE_FILE = "tool-approvals.json";
5
+ const MISSING = "missing";
5
6
  /**
6
7
  * Persistent per-tool "always allow" decisions for the MCP tool approval gate.
7
8
  *
@@ -12,31 +13,75 @@ export const TOOL_APPROVALS_STATE_FILE = "tool-approvals.json";
12
13
  * redeploys, and plugin auto-updates.
13
14
  *
14
15
  * To make a tool prompt again, delete its entry from `tool-approvals.json`
15
- * (or the whole file) in the state dir.
16
+ * (or the whole file) in the state dir. That takes effect at the next gated
17
+ * call, with no restart.
16
18
  *
17
- * Load is synchronous (once, at plugin register()); writes are synchronous
18
- * atomic temp → rename, and only happen on an explicit user decision.
19
+ * The file is the source of truth, shared by every registry the host builds
20
+ * (chat, cron, …), each with its own store (RT566-02, RT566-10):
21
+ * - before every decision the store `stat`s the file and re-reads it only when
22
+ * its mtime, size or inode changed since the last read;
23
+ * - a missing file, or one that cannot be read or parsed, means no grants
24
+ * (every gated tool prompts); a bad file is logged once per version;
25
+ * - a write is read-modify-write: re-read the file, add this one grant, write
26
+ * atomically (temp → rename). It never drops a grant another registry wrote
27
+ * and never brings back one the user revoked.
19
28
  */
20
29
  export class ToolApprovalStore {
21
30
  logger;
22
31
  filePath;
23
32
  allowAlways = new Map();
33
+ /** Signature of the file version `allowAlways` was read from (undefined: never read). */
34
+ loadedSignature;
35
+ /** File version a grant was last refused a write for (warn once per version). */
36
+ unwritableWarnedSignature;
24
37
  constructor(stateDir, logger) {
25
38
  this.logger = logger;
26
39
  this.filePath = join(stateDir, TOOL_APPROVALS_STATE_FILE);
27
- this.load();
40
+ this.refresh();
28
41
  }
29
- load() {
42
+ signature(path = this.filePath) {
43
+ try {
44
+ const st = statSync(path);
45
+ return `${st.mtimeMs}:${st.size}:${st.ino}`;
46
+ }
47
+ catch (err) {
48
+ if (isNotFound(err)) {
49
+ return MISSING;
50
+ }
51
+ // Unknown state: a fresh signature forces a read, which fails the same
52
+ // way and reads as no grants (fail closed: the tool prompts).
53
+ return `stat-error:${errMessage(err)}`;
54
+ }
55
+ }
56
+ /** One `stat`; re-read only when the file changed since the last read. */
57
+ refresh() {
58
+ const sig = this.signature();
59
+ if (sig === this.loadedSignature) {
60
+ return;
61
+ }
62
+ // Taken before the read: if the file changes in between, the next call's
63
+ // signature differs and it reads again.
64
+ this.loadedSignature = sig;
65
+ this.allowAlways = sig === MISSING ? new Map() : this.readFile(true).grants;
66
+ }
67
+ /**
68
+ * Read and parse the file; any failure is no grants. `ok` is false when the
69
+ * file exists but cannot be read or parsed (a missing file is ok and empty).
70
+ */
71
+ readFile(warn) {
72
+ const grants = new Map();
30
73
  let raw;
31
74
  try {
32
75
  raw = readFileSync(this.filePath, "utf8");
33
76
  }
34
77
  catch (err) {
35
- const isNotFound = err instanceof Error && "code" in err && err.code === "ENOENT";
36
- if (!isNotFound) {
37
- this.logger?.warn(`[senpi-tool-approvals] failed to read state file, starting empty | path=${this.filePath} err=${err instanceof Error ? err.message : String(err)}`);
78
+ if (isNotFound(err)) {
79
+ return { grants, ok: true };
38
80
  }
39
- return;
81
+ if (warn) {
82
+ this.logger?.warn(`[senpi-tool-approvals] failed to read state file, treating it as no grants (all gated tools will prompt) | path=${this.filePath} err=${errMessage(err)}`);
83
+ }
84
+ return { grants, ok: false };
40
85
  }
41
86
  try {
42
87
  const parsed = JSON.parse(raw);
@@ -44,7 +89,7 @@ export class ToolApprovalStore {
44
89
  if (entries && typeof entries === "object" && !Array.isArray(entries)) {
45
90
  for (const [tool, entry] of Object.entries(entries)) {
46
91
  if (typeof tool === "string" && tool.length > 0) {
47
- this.allowAlways.set(tool, {
92
+ grants.set(tool, {
48
93
  decidedAt: typeof entry?.decidedAt === "string" ? entry.decidedAt : "",
49
94
  });
50
95
  }
@@ -52,36 +97,95 @@ export class ToolApprovalStore {
52
97
  }
53
98
  }
54
99
  catch (err) {
55
- this.logger?.warn(`[senpi-tool-approvals] corrupt state file, starting empty (all gated tools will prompt again) | path=${this.filePath} err=${err instanceof Error ? err.message : String(err)}`);
100
+ if (warn) {
101
+ this.logger?.warn(`[senpi-tool-approvals] corrupt state file, treating it as no grants (all gated tools will prompt) | path=${this.filePath} err=${errMessage(err)}`);
102
+ }
103
+ return { grants: new Map(), ok: false };
56
104
  }
105
+ return { grants, ok: true };
57
106
  }
58
107
  isAllowedAlways(tool) {
108
+ this.refresh();
59
109
  return this.allowAlways.has(tool);
60
110
  }
61
111
  get size() {
112
+ this.refresh();
62
113
  return this.allowAlways.size;
63
114
  }
64
- /** Record a user's allow-always decision and persist it immediately. */
115
+ /**
116
+ * Record a user's allow-always decision and persist it immediately.
117
+ *
118
+ * @returns true when the grant is in the state file, false when it is kept in
119
+ * memory only (the file could not be read or written; a warn names why).
120
+ */
65
121
  rememberAllowAlways(tool) {
66
- if (!tool || this.allowAlways.has(tool)) {
67
- return;
122
+ if (!tool) {
123
+ return false;
124
+ }
125
+ if (this.isAllowedAlways(tool)) {
126
+ // Already granted: in the file unless an earlier grant was kept in memory only.
127
+ const { grants, ok } = this.readFile(false);
128
+ return ok && grants.has(tool);
129
+ }
130
+ const entry = { decidedAt: new Date().toISOString() };
131
+ // Read-modify-write against the file as it is now, not this store's copy.
132
+ // The signature is taken before the read, so a write landing after it makes
133
+ // the next decision re-read.
134
+ const before = this.signature();
135
+ const { grants: merged, ok } = this.readFile(false);
136
+ if (!ok) {
137
+ // Writing now would replace the user's other grants with this one. Keep
138
+ // it in memory until the file next changes; the file stays as it is.
139
+ if (this.unwritableWarnedSignature !== before) {
140
+ this.unwritableWarnedSignature = before;
141
+ this.logger?.warn(`[senpi-tool-approvals] state file unreadable, allow-always not written (kept in memory until the file changes) | path=${this.filePath} tool=${tool}`);
142
+ }
143
+ // Add to what this store holds for this file version (earlier
144
+ // in-memory-only grants included), not to the empty failed read.
145
+ // loadedSignature stays the one from the refresh above, so a change since
146
+ // then is re-read at the next decision.
147
+ this.allowAlways.set(tool, entry);
148
+ return false;
68
149
  }
69
- this.allowAlways.set(tool, { decidedAt: new Date().toISOString() });
70
- this.persist();
150
+ merged.set(tool, entry);
151
+ // On a failed write the grant stays in memory until the file next changes.
152
+ this.allowAlways = merged;
153
+ const written = this.persist(merged);
154
+ this.loadedSignature = written ?? before;
155
+ return written !== undefined;
71
156
  }
72
- persist() {
157
+ /**
158
+ * Write atomically. Returns the written file's signature, taken from the temp
159
+ * file before the rename (rename keeps inode, mtime and size), so a write by
160
+ * someone else right after the rename is seen at the next decision; undefined
161
+ * when the write failed.
162
+ */
163
+ persist(grants) {
164
+ const tmpPath = `${this.filePath}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
73
165
  try {
74
166
  mkdirSync(dirname(this.filePath), { recursive: true });
75
- const shape = {
76
- allowAlways: Object.fromEntries(this.allowAlways),
77
- };
78
- const tmpPath = `${this.filePath}.tmp`;
167
+ const shape = { allowAlways: Object.fromEntries(grants) };
79
168
  writeFileSync(tmpPath, JSON.stringify(shape, null, 2), "utf8");
169
+ const written = this.signature(tmpPath);
80
170
  renameSync(tmpPath, this.filePath);
171
+ return written;
81
172
  }
82
173
  catch (err) {
83
- this.logger?.warn(`[senpi-tool-approvals] failed to persist state (decision kept in memory only) | path=${this.filePath} err=${err instanceof Error ? err.message : String(err)}`);
174
+ try {
175
+ unlinkSync(tmpPath);
176
+ }
177
+ catch {
178
+ // Nothing to clean up.
179
+ }
180
+ this.logger?.warn(`[senpi-tool-approvals] failed to persist state (decision kept in memory only) | path=${this.filePath} err=${errMessage(err)}`);
181
+ return undefined;
84
182
  }
85
183
  }
86
184
  }
185
+ function isNotFound(err) {
186
+ return err instanceof Error && "code" in err && err.code === "ENOENT";
187
+ }
188
+ function errMessage(err) {
189
+ return err instanceof Error ? err.message : String(err);
190
+ }
87
191
  //# sourceMappingURL=approval-store.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"approval-store.js","sourceRoot":"","sources":["../../src/approvals/approval-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"approval-store.js","sourceRoot":"","sources":["../../src/approvals/approval-store.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,25 @@
1
- /** Terminal user choice at the approval gate. */
2
- export type ApprovalDecision = "allow-once" | "allow-always" | "deny" | "timeout";
1
+ import type { TurnKind } from "./turn-context.js";
2
+ /**
3
+ * How an approval ended: a user choice (`allow-once`, `allow-always`,
4
+ * `deny`), a missed prompt (`timeout`), or `cancelled`: the run was aborted
5
+ * while the prompt was open, the host had no route or surface to ask (on
6
+ * 10.x, before any tool runs), or the gate itself stopped a gated call in a
7
+ * scheduled turn (`cancelReason: "scheduled_turn"`) or in another run that is
8
+ * not a direct chat turn (`"not_chat_turn"`, D15). The wait time tells a user
9
+ * abort (long) from a no-route cancellation (milliseconds). `granted` is not a
10
+ * prompt outcome: the call ran under a stored "Always allow" grant with no
11
+ * prompt (D16), recorded with its run kind.
12
+ */
13
+ export type ApprovalDecision = "allow-once" | "allow-always" | "deny" | "timeout" | "cancelled" | "granted";
14
+ /** Where an approval happened, for O7's per-turn-kind queries. Every field is optional. */
15
+ export interface ApprovalResolutionContext {
16
+ /** The turn's session key; stamped as `gen_ai.conversation.id` (the span convention). */
17
+ sessionKey?: string;
18
+ /** `chat` | `cron` | `heartbeat` | `other` | `unknown`; stamped as `senpi.turn.kind`. */
19
+ turnKind?: TurnKind;
20
+ /** Why the gate cancelled the call itself; stamped as `senpi.tool_approval.cancel_reason`. */
21
+ cancelReason?: "scheduled_turn" | "not_chat_turn";
22
+ }
3
23
  /**
4
24
  * Telemetry seam for the MCP tool approval gate.
5
25
  *
@@ -17,8 +37,12 @@ export interface GateTelemetry {
17
37
  * deny path, `deny` vs `timeout`). Emits the `tool_approval.resolved` event
18
38
  * (info for allows, warn for deny/timeout) + `tool_approval.decisions` metric,
19
39
  * so allow-always adoption and deny/timeout rates per tool are chartable.
40
+ *
41
+ * @param waitMs - From the gate's `requireApproval` to the resolution (0 when
42
+ * the gate cancelled the call itself); `senpi.tool_approval.wait_ms`.
43
+ * @param context - The turn's session key and kind (see {@link ApprovalResolutionContext}).
20
44
  */
21
- resolved(toolName: string, decision: ApprovalDecision, isTrade: boolean): void;
45
+ resolved(toolName: string, decision: ApprovalDecision, isTrade: boolean, waitMs?: number, context?: ApprovalResolutionContext): void;
22
46
  /**
23
47
  * A user deny or a 10-minute timeout — a state-changing tool the user did NOT
24
48
  * authorize, so it did not run. Recorded on the origin-uniform `tool.called`
@@ -1 +1 @@
1
- {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../src/approvals/telemetry.ts"],"names":[],"mappings":"AAKA,iDAAiD;AACjD,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG,cAAc,GAAG,MAAM,GAAG,SAAS,CAAC;AAElF;;;;;;;;;GASG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;;;OAMG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAC/E;;;;;;;;OAQG;IACH,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,kBAAkB,GAAG,IAAI,CAAC;IAC3E;;;;OAIG;IACH,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;CAC7D;AAID,qDAAqD;AACrD,eAAO,MAAM,oBAAoB,EAAE,aA2BlC,CAAC"}
1
+ {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../src/approvals/telemetry.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAElD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG,cAAc,GAAG,MAAM,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;AAE5G,2FAA2F;AAC3F,MAAM,WAAW,yBAAyB;IACxC,yFAAyF;IACzF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yFAAyF;IACzF,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,8FAA8F;IAC9F,YAAY,CAAC,EAAE,gBAAgB,GAAG,eAAe,CAAC;CACnD;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;;;;;;;OAUG;IACH,QAAQ,CACN,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,gBAAgB,EAC1B,OAAO,EAAE,OAAO,EAChB,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,yBAAyB,GAClC,IAAI,CAAC;IACR;;;;;;;;OAQG;IACH,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,kBAAkB,GAAG,IAAI,CAAC;IAC3E;;;;OAIG;IACH,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;CAC7D;AAID,qDAAqD;AACrD,eAAO,MAAM,oBAAoB,EAAE,aAgClC,CAAC"}
@@ -5,17 +5,21 @@ import { createLogger } from "../utils/logger.js";
5
5
  const eventLogger = createLogger("[senpi-tool-approvals]");
6
6
  /** Production wiring: real event + metric planes. */
7
7
  export const defaultGateTelemetry = {
8
- resolved(toolName, decision, isTrade) {
9
- const denyish = decision === "deny" || decision === "timeout";
10
- eventLogger.event(EVENT_NAME.toolApprovalResolved, denyish ? "warn" : "info", {
8
+ resolved(toolName, decision, isTrade, waitMs, context) {
9
+ const notRun = decision === "deny" || decision === "timeout" || decision === "cancelled";
10
+ eventLogger.event(EVENT_NAME.toolApprovalResolved, notRun ? "warn" : "info", {
11
11
  body: `tool approval ${decision} for ${toolName}`,
12
12
  attributes: eventAttrs({
13
13
  "gen_ai.tool.name": toolName,
14
14
  "senpi.tool_approval.decision": decision,
15
15
  "senpi.tool.is_trade": String(isTrade),
16
+ "senpi.tool_approval.wait_ms": typeof waitMs === "number" && Number.isFinite(waitMs) ? Math.max(0, Math.round(waitMs)) : undefined,
17
+ "gen_ai.conversation.id": context?.sessionKey,
18
+ "senpi.turn.kind": context?.turnKind,
19
+ "senpi.tool_approval.cancel_reason": context?.cancelReason,
16
20
  }),
17
21
  });
18
- recordApprovalDecision({ toolName, decision, isTrade });
22
+ recordApprovalDecision({ toolName, decision, isTrade, turnKind: context?.turnKind });
19
23
  },
20
24
  denied(toolName, reason) {
21
25
  emitToolCalled({ name: toolName, origin: "agent", outcome: "denied", errorType: reason });
@@ -1 +1 @@
1
- {"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../src/approvals/telemetry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,UAAU,EAAiB,MAAM,2BAA2B,CAAC;AAClF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AA0ClD,MAAM,WAAW,GAAG,YAAY,CAAC,wBAAwB,CAAC,CAAC;AAE3D,qDAAqD;AACrD,MAAM,CAAC,MAAM,oBAAoB,GAAkB;IACjD,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO;QAClC,MAAM,OAAO,GAAG,QAAQ,KAAK,MAAM,IAAI,QAAQ,KAAK,SAAS,CAAC;QAC9D,WAAW,CAAC,KAAK,CAAC,UAAU,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE;YAC5E,IAAI,EAAE,iBAAiB,QAAQ,QAAQ,QAAQ,EAAE;YACjD,UAAU,EAAE,UAAU,CAAmD;gBACvE,kBAAkB,EAAE,QAAQ;gBAC5B,8BAA8B,EAAE,QAAQ;gBACxC,qBAAqB,EAAE,MAAM,CAAC,OAAO,CAAC;aACvC,CAAC;SACH,CAAC,CAAC;QACH,sBAAsB,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IAC1D,CAAC;IACD,MAAM,CAAC,QAAQ,EAAE,MAAM;QACrB,cAAc,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;QAC1F,cAAc,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;IACtF,CAAC;IACD,SAAS,CAAC,GAAG,EAAE,QAAQ;QACrB,WAAW,CAAC,KAAK,CAAC,UAAU,CAAC,qBAAqB,EAAE,OAAO,EAAE;YAC3D,IAAI,EAAE,iCAAiC,QAAQ,CAAC,CAAC,CAAC,QAAQ,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;YAC3E,UAAU,EAAE,UAAU,CAAoD;gBACxE,kBAAkB,EAAE,QAAQ;gBAC5B,YAAY,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;aAC1D,CAAC;YACF,MAAM,EAAE,EAAE,aAAa,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;SAC5E,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../src/approvals/telemetry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,UAAU,EAAiB,MAAM,2BAA2B,CAAC;AAClF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAyElD,MAAM,WAAW,GAAG,YAAY,CAAC,wBAAwB,CAAC,CAAC;AAE3D,qDAAqD;AACrD,MAAM,CAAC,MAAM,oBAAoB,GAAkB;IACjD,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO;QACnD,MAAM,MAAM,GAAG,QAAQ,KAAK,MAAM,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,WAAW,CAAC;QACzF,WAAW,CAAC,KAAK,CAAC,UAAU,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE;YAC3E,IAAI,EAAE,iBAAiB,QAAQ,QAAQ,QAAQ,EAAE;YACjD,UAAU,EAAE,UAAU,CAAmD;gBACvE,kBAAkB,EAAE,QAAQ;gBAC5B,8BAA8B,EAAE,QAAQ;gBACxC,qBAAqB,EAAE,MAAM,CAAC,OAAO,CAAC;gBACtC,6BAA6B,EAC3B,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;gBACrG,wBAAwB,EAAE,OAAO,EAAE,UAAU;gBAC7C,iBAAiB,EAAE,OAAO,EAAE,QAAQ;gBACpC,mCAAmC,EAAE,OAAO,EAAE,YAAY;aAC3D,CAAC;SACH,CAAC,CAAC;QACH,sBAAsB,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;IACvF,CAAC;IACD,MAAM,CAAC,QAAQ,EAAE,MAAM;QACrB,cAAc,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;QAC1F,cAAc,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;IACtF,CAAC;IACD,SAAS,CAAC,GAAG,EAAE,QAAQ;QACrB,WAAW,CAAC,KAAK,CAAC,UAAU,CAAC,qBAAqB,EAAE,OAAO,EAAE;YAC3D,IAAI,EAAE,iCAAiC,QAAQ,CAAC,CAAC,CAAC,QAAQ,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;YAC3E,UAAU,EAAE,UAAU,CAAoD;gBACxE,kBAAkB,EAAE,QAAQ;gBAC5B,YAAY,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;aAC1D,CAAC;YACF,MAAM,EAAE,EAAE,aAAa,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;SAC5E,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import { ToolApprovalStore } from "./approval-store.js";
2
2
  import { type ToolApprovalsManifest, type ToolApprovalsMode } from "./manifest.js";
3
3
  import { type GateTelemetry } from "./telemetry.js";
4
+ import type { TurnContextReader, TurnKind } from "./turn-context.js";
4
5
  /**
5
6
  * Tool approval gate: requires an interactive user approval before
6
7
  * state-changing senpi MCP tools execute.
@@ -77,6 +78,37 @@ export declare function describeSenpiToolCall(tool: string, params: unknown): st
77
78
  * gateway's description limit, which rejects (not truncates) anything longer.
78
79
  */
79
80
  export declare function buildApprovalDescription(tool: string, params: unknown): string;
81
+ /**
82
+ * Counts approval prompts the gate has asked for and not yet seen resolved
83
+ * (trade tools, and in `all` mode every gated Senpi tool).
84
+ *
85
+ * Read by the self-update idle gate (`runtime/auto-update/idle-gate.ts`): a
86
+ * restart while a user is looking at an approval prompt would cancel it. An
87
+ * entry ends on any `onResolution` decision (including `cancelled`), or
88
+ * expires `timeoutMs + slackMs` after it began, so a prompt the gateway never
89
+ * resolved cannot keep the box busy forever.
90
+ */
91
+ export declare class PendingApprovalTracker {
92
+ private readonly slackMs;
93
+ private readonly now;
94
+ private readonly open;
95
+ private nextId;
96
+ /**
97
+ * @param slackMs - Grace past the prompt's own timeout before an unresolved entry is dropped.
98
+ * @param now - Clock, for tests.
99
+ */
100
+ constructor(slackMs?: number, now?: () => number);
101
+ /**
102
+ * Records a prompt that will time out after `timeoutMs`.
103
+ *
104
+ * @returns A handle for {@link end}.
105
+ */
106
+ begin(timeoutMs: number): number;
107
+ /** Marks a prompt resolved. Unknown or repeated handles are ignored. */
108
+ end(id: number): void;
109
+ /** Prompts still waiting for an answer. */
110
+ count(): number;
111
+ }
80
112
  export interface RegisterToolApprovalGateOptions {
81
113
  api: ToolApprovalGatePluginApi;
82
114
  mode: ToolApprovalsMode;
@@ -87,7 +119,54 @@ export interface RegisterToolApprovalGateOptions {
87
119
  manifest?: ToolApprovalsManifest;
88
120
  /** Injectable for tests; defaults to the real event/metric planes. */
89
121
  telemetry?: GateTelemetry;
122
+ /** Counts open prompts for the self-update idle gate. Optional; nothing is counted without it. */
123
+ pendingApprovals?: PendingApprovalTracker;
124
+ /**
125
+ * The turn of each gated call (session key, chat / cron / heartbeat), for
126
+ * approval telemetry and the scheduled-turn block. Without it every call
127
+ * reads `unknown` and nothing is blocked.
128
+ */
129
+ turnContext?: TurnContextReader;
130
+ /**
131
+ * The host lets the runtime classify runs (`turnClassificationAvailable`,
132
+ * one boot-time fact). Only then is a gated call outside a direct chat turn
133
+ * blocked with {@link scheduledTurnBlockReason}; without it every run reads
134
+ * `unknown` and keeps the prompt, as before this release, so a box missing
135
+ * the setting never blocks a chat trade.
136
+ */
137
+ turnClassification?: boolean;
138
+ /** Clock for the approval wait time. Default `Date.now`. */
139
+ now?: () => number;
90
140
  }
141
+ /**
142
+ * The text the model reads when the gate stops a gated call in a scheduled
143
+ * turn (D13). On 10.10-beta.3 the host's own outcome for such an approval is
144
+ * a sentence the plugin cannot change and the model cannot act on: for a tool
145
+ * whose hook context carries the run trigger it cancels with "Plugin approval
146
+ * unavailable: cron runs have no approval-capable initiating surface."
147
+ * (`openclaw-worktrees/v2026.10.10-beta.3/src/agents/agent-tools.before-tool-call.approval.ts:161-189,310-320`);
148
+ * the `senpi__` MCP tools are wrapped without the trigger
149
+ * (`src/agents/embedded-agent-runner/run/attempt-tool-prepare.ts:468-485`), so
150
+ * the host asks the gateway instead, which fails with "Plugin approval
151
+ * unavailable (no approval route)" (`:371`) when no approval client is
152
+ * connected. The gate blocks first, in every scheduled turn. This text says
153
+ * what happened and the one step that works: the user asks in chat, where the
154
+ * approval prompt can be shown. It names no other route.
155
+ *
156
+ * D14 (ruled 2026-10-24): the block is outright. When an approval client is
157
+ * connected, 10.10 would route a `senpi__` approval from a scheduled run to
158
+ * it; scheduled runs still never get a prompt, even with the user online.
159
+ * D15: the same block covers every run not positively classified as a direct
160
+ * chat turn (`other`, `unknown`, a call with no run id), with the
161
+ * not-a-chat-turn wording. D16: a stored "Always allow" grant is checked
162
+ * first and wins in every run kind; this block only stops prompts.
163
+ */
164
+ export declare function scheduledTurnBlockReason(params: {
165
+ wireName: string;
166
+ kind: Exclude<TurnKind, "chat">;
167
+ isTrade: boolean;
168
+ summary?: string;
169
+ }): string;
91
170
  /**
92
171
  * Register the `before_tool_call` approval gate. No-op in `off` mode.
93
172
  * Returns the store (for tests/introspection) when registered.
@@ -1 +1 @@
1
- {"version":3,"file":"tool-approval-gate.d.ts","sourceRoot":"","sources":["../../src/approvals/tool-approval-gate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAEL,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACvB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,UAAU,UAAU;IAClB,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC/B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CAChC;AAED,uEAAuE;AACvE,MAAM,WAAW,yBAAyB;IACxC,EAAE,CACA,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,EACxC,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAC3B,IAAI,CAAC;CACT;AAED,YAAY,EAAE,iBAAiB,EAAE,CAAC;AAElC,yFAAyF;AACzF,eAAO,MAAM,sBAAsB,yBAAyB,CAAC;AAO7D;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAM/D;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,iBAAiB,CAE9E;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,QAAQ,CAAC,EAAE,qBAAqB,CAAC;CAClC,GAAG,iBAAiB,CAqBpB;AAYD;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAqDvF;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,CAY9E;AAED,MAAM,WAAW,+BAA+B;IAC9C,GAAG,EAAE,yBAAyB,CAAC;IAC/B,IAAI,EAAE,iBAAiB,CAAC;IACxB,qEAAqE;IACrE,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,iEAAiE;IACjE,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IACjC,sEAAsE;IACtE,SAAS,CAAC,EAAE,aAAa,CAAC;CAC3B;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,+BAA+B,GACvC,iBAAiB,GAAG,SAAS,CAgF/B"}
1
+ {"version":3,"file":"tool-approval-gate.d.ts","sourceRoot":"","sources":["../../src/approvals/tool-approval-gate.ts"],"names":[],"mappings":"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"}