@senpi/runtime 3.0.173 → 3.0.181
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/actions/close-position/close-position.action.d.ts.map +1 -1
- package/dist/actions/close-position/close-position.action.js +48 -3
- package/dist/actions/close-position/close-position.action.js.map +1 -1
- package/dist/actions/llm-decision/openclaw-llm-decision.d.ts +8 -0
- package/dist/actions/llm-decision/openclaw-llm-decision.d.ts.map +1 -1
- package/dist/actions/llm-decision/openclaw-llm-decision.js +56 -1
- package/dist/actions/llm-decision/openclaw-llm-decision.js.map +1 -1
- package/dist/actions/open-position/open-position.action.d.ts.map +1 -1
- package/dist/actions/open-position/open-position.action.js +42 -6
- package/dist/actions/open-position/open-position.action.js.map +1 -1
- package/dist/actions/open-position/resolve-margin.d.ts +1 -1
- package/dist/actions/open-position/resolve-margin.d.ts.map +1 -1
- package/dist/actions/open-position/resolve-margin.js +7 -0
- package/dist/actions/open-position/resolve-margin.js.map +1 -1
- package/dist/approvals/approval-store.d.ts +37 -7
- package/dist/approvals/approval-store.d.ts.map +1 -1
- package/dist/approvals/approval-store.js +127 -23
- package/dist/approvals/approval-store.js.map +1 -1
- package/dist/approvals/manifest.d.ts.map +1 -1
- package/dist/approvals/manifest.js +0 -5
- package/dist/approvals/manifest.js.map +1 -1
- package/dist/approvals/telemetry.d.ts +27 -3
- package/dist/approvals/telemetry.d.ts.map +1 -1
- package/dist/approvals/telemetry.js +8 -4
- package/dist/approvals/telemetry.js.map +1 -1
- package/dist/approvals/tool-approval-gate.d.ts +79 -0
- package/dist/approvals/tool-approval-gate.d.ts.map +1 -1
- package/dist/approvals/tool-approval-gate.js +184 -21
- package/dist/approvals/tool-approval-gate.js.map +1 -1
- package/dist/approvals/tool-approvals-manifest.json +0 -2
- package/dist/approvals/turn-context.d.ts +271 -0
- package/dist/approvals/turn-context.d.ts.map +1 -0
- package/dist/approvals/turn-context.js +551 -0
- package/dist/approvals/turn-context.js.map +1 -0
- package/dist/cli/guide-commands.d.ts.map +1 -1
- package/dist/cli/guide-commands.js +43 -8
- package/dist/cli/guide-commands.js.map +1 -1
- package/dist/cli/senpi-commands.d.ts.map +1 -1
- package/dist/cli/senpi-commands.js +91 -12
- package/dist/cli/senpi-commands.js.map +1 -1
- package/dist/constants/dsl/index.d.ts +2 -0
- package/dist/constants/dsl/index.d.ts.map +1 -1
- package/dist/constants/dsl/index.js +2 -0
- package/dist/constants/dsl/index.js.map +1 -1
- package/dist/constants/order-types.d.ts.map +1 -1
- package/dist/constants/order-types.js +4 -1
- package/dist/constants/order-types.js.map +1 -1
- package/dist/deploy/job.d.ts +32 -0
- package/dist/deploy/job.d.ts.map +1 -1
- package/dist/deploy/job.js +72 -7
- package/dist/deploy/job.js.map +1 -1
- package/dist/deploy/messages.d.ts +15 -1
- package/dist/deploy/messages.d.ts.map +1 -1
- package/dist/deploy/messages.js +78 -0
- package/dist/deploy/messages.js.map +1 -1
- package/dist/deploy/orchestrator.d.ts +11 -1
- package/dist/deploy/orchestrator.d.ts.map +1 -1
- package/dist/deploy/orchestrator.js +111 -15
- package/dist/deploy/orchestrator.js.map +1 -1
- package/dist/deploy/register.d.ts +18 -0
- package/dist/deploy/register.d.ts.map +1 -1
- package/dist/deploy/register.js +93 -2
- package/dist/deploy/register.js.map +1 -1
- package/dist/dsl/engine/exchange-stop.d.ts +21 -1
- package/dist/dsl/engine/exchange-stop.d.ts.map +1 -1
- package/dist/dsl/engine/exchange-stop.js +27 -1
- package/dist/dsl/engine/exchange-stop.js.map +1 -1
- package/dist/dsl/engine/floors.d.ts +2 -1
- package/dist/dsl/engine/floors.d.ts.map +1 -1
- package/dist/dsl/engine/floors.js +2 -1
- package/dist/dsl/engine/floors.js.map +1 -1
- package/dist/dsl/engine/index.d.ts +1 -1
- package/dist/dsl/engine/index.d.ts.map +1 -1
- package/dist/dsl/engine/index.js +1 -1
- package/dist/dsl/engine/index.js.map +1 -1
- package/dist/dsl/engine/tick.d.ts.map +1 -1
- package/dist/dsl/engine/tick.js +4 -3
- package/dist/dsl/engine/tick.js.map +1 -1
- package/dist/dsl/events/handlers.d.ts +7 -3
- package/dist/dsl/events/handlers.d.ts.map +1 -1
- package/dist/dsl/events/handlers.js +10 -4
- package/dist/dsl/events/handlers.js.map +1 -1
- package/dist/dsl/events/initial-state.d.ts.map +1 -1
- package/dist/dsl/events/initial-state.js +2 -0
- package/dist/dsl/events/initial-state.js.map +1 -1
- package/dist/dsl/monitor/exchange-sync.d.ts +1 -0
- package/dist/dsl/monitor/exchange-sync.d.ts.map +1 -1
- package/dist/dsl/monitor/exchange-sync.js +7 -14
- package/dist/dsl/monitor/exchange-sync.js.map +1 -1
- package/dist/dsl/monitor/process-one-position.d.ts.map +1 -1
- package/dist/dsl/monitor/process-one-position.js +108 -17
- package/dist/dsl/monitor/process-one-position.js.map +1 -1
- package/dist/dsl/notifications/formatter.d.ts +2 -1
- package/dist/dsl/notifications/formatter.d.ts.map +1 -1
- package/dist/dsl/notifications/formatter.js +18 -1
- package/dist/dsl/notifications/formatter.js.map +1 -1
- package/dist/health/types.d.ts +6 -1
- package/dist/health/types.d.ts.map +1 -1
- package/dist/health/types.js.map +1 -1
- package/dist/host/openclaw-host.d.ts +138 -0
- package/dist/host/openclaw-host.d.ts.map +1 -0
- package/dist/host/openclaw-host.js +177 -0
- package/dist/host/openclaw-host.js.map +1 -0
- package/dist/index.d.ts +46 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +318 -38
- package/dist/index.js.map +1 -1
- package/dist/leverage/max-leverage-cache.d.ts +25 -0
- package/dist/leverage/max-leverage-cache.d.ts.map +1 -1
- package/dist/leverage/max-leverage-cache.js +77 -0
- package/dist/leverage/max-leverage-cache.js.map +1 -1
- package/dist/runtime/auto-update/coordinator.d.ts +203 -0
- package/dist/runtime/auto-update/coordinator.d.ts.map +1 -1
- package/dist/runtime/auto-update/coordinator.js +621 -12
- package/dist/runtime/auto-update/coordinator.js.map +1 -1
- package/dist/runtime/auto-update/gateway-restart.d.ts +60 -1
- package/dist/runtime/auto-update/gateway-restart.d.ts.map +1 -1
- package/dist/runtime/auto-update/gateway-restart.js +95 -21
- package/dist/runtime/auto-update/gateway-restart.js.map +1 -1
- package/dist/runtime/auto-update/idle-gate.d.ts +139 -0
- package/dist/runtime/auto-update/idle-gate.d.ts.map +1 -0
- package/dist/runtime/auto-update/idle-gate.js +217 -0
- package/dist/runtime/auto-update/idle-gate.js.map +1 -0
- package/dist/runtime/auto-update/install-results.d.ts +130 -0
- package/dist/runtime/auto-update/install-results.d.ts.map +1 -0
- package/dist/runtime/auto-update/install-results.js +264 -0
- package/dist/runtime/auto-update/install-results.js.map +1 -0
- package/dist/runtime/auto-update/money-call-tracker.d.ts +36 -0
- package/dist/runtime/auto-update/money-call-tracker.d.ts.map +1 -0
- package/dist/runtime/auto-update/money-call-tracker.js +129 -0
- package/dist/runtime/auto-update/money-call-tracker.js.map +1 -0
- package/dist/runtime/auto-update/register-idle-gate.d.ts +70 -0
- package/dist/runtime/auto-update/register-idle-gate.d.ts.map +1 -0
- package/dist/runtime/auto-update/register-idle-gate.js +123 -0
- package/dist/runtime/auto-update/register-idle-gate.js.map +1 -0
- package/dist/runtime/auto-update/run-update-command.d.ts +13 -0
- package/dist/runtime/auto-update/run-update-command.d.ts.map +1 -1
- package/dist/runtime/auto-update/run-update-command.js +18 -0
- package/dist/runtime/auto-update/run-update-command.js.map +1 -1
- package/dist/runtime/auto-update/state-store.d.ts +14 -1
- package/dist/runtime/auto-update/state-store.d.ts.map +1 -1
- package/dist/runtime/auto-update/state-store.js +37 -3
- package/dist/runtime/auto-update/state-store.js.map +1 -1
- package/dist/runtime/auto-update/types.d.ts +51 -0
- package/dist/runtime/auto-update/types.d.ts.map +1 -1
- package/dist/runtime/auto-update/types.js.map +1 -1
- package/dist/runtime/auto-update/update-marker.d.ts +95 -0
- package/dist/runtime/auto-update/update-marker.d.ts.map +1 -0
- package/dist/runtime/auto-update/update-marker.js +185 -0
- package/dist/runtime/auto-update/update-marker.js.map +1 -0
- package/dist/runtime/auto-update/update-schedule.d.ts +57 -0
- package/dist/runtime/auto-update/update-schedule.d.ts.map +1 -0
- package/dist/runtime/auto-update/update-schedule.js +75 -0
- package/dist/runtime/auto-update/update-schedule.js.map +1 -0
- package/dist/runtime/create-scanner-module.d.ts +1 -1
- package/dist/runtime/create-scanner-module.d.ts.map +1 -1
- package/dist/runtime/create-scanner-module.js +2 -1
- package/dist/runtime/create-scanner-module.js.map +1 -1
- package/dist/runtime/decision-errors.d.ts +7 -0
- package/dist/runtime/decision-errors.d.ts.map +1 -1
- package/dist/runtime/decision-errors.js +15 -0
- package/dist/runtime/decision-errors.js.map +1 -1
- package/dist/runtime/lifecycle-events.d.ts +1 -1
- package/dist/runtime/lifecycle-events.d.ts.map +1 -1
- package/dist/runtime/lifecycle-events.js +10 -1
- package/dist/runtime/lifecycle-events.js.map +1 -1
- package/dist/runtime/runtime-descriptor.d.ts +11 -2
- package/dist/runtime/runtime-descriptor.d.ts.map +1 -1
- package/dist/runtime/runtime-descriptor.js +11 -2
- package/dist/runtime/runtime-descriptor.js.map +1 -1
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +4 -3
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/strategy-lifecycle.js +1 -1
- package/dist/runtime/strategy-lifecycle.js.map +1 -1
- package/dist/runtime/supervisor/long-running-supervisor.js +1 -1
- package/dist/runtime/supervisor/long-running-supervisor.js.map +1 -1
- package/dist/runtime-api/intake/acceptance-record.d.ts +17 -3
- package/dist/runtime-api/intake/acceptance-record.d.ts.map +1 -1
- package/dist/runtime-api/intake/acceptance-record.js +57 -32
- package/dist/runtime-api/intake/acceptance-record.js.map +1 -1
- package/dist/runtime-api/intake/intake-events.d.ts +6 -5
- package/dist/runtime-api/intake/intake-events.d.ts.map +1 -1
- package/dist/runtime-api/intake/intake-events.js +9 -3
- package/dist/runtime-api/intake/intake-events.js.map +1 -1
- package/dist/runtime-api/intake/process-signal-post.d.ts +1 -1
- package/dist/runtime-api/intake/process-signal-post.d.ts.map +1 -1
- package/dist/runtime-api/intake/process-signal-post.js +34 -31
- package/dist/runtime-api/intake/process-signal-post.js.map +1 -1
- package/dist/runtime-api/intake/scaffold-error-router.d.ts +8 -0
- package/dist/runtime-api/intake/scaffold-error-router.d.ts.map +1 -1
- package/dist/runtime-api/intake/scaffold-error-router.js +9 -0
- package/dist/runtime-api/intake/scaffold-error-router.js.map +1 -1
- package/dist/runtime-api/intake/types.d.ts +9 -0
- package/dist/runtime-api/intake/types.d.ts.map +1 -1
- package/dist/runtime-api/intake/types.js +5 -1
- package/dist/runtime-api/intake/types.js.map +1 -1
- package/dist/runtime-api/routes/signals.d.ts.map +1 -1
- package/dist/runtime-api/routes/signals.js +25 -1
- package/dist/runtime-api/routes/signals.js.map +1 -1
- package/dist/runtime-api/routes/signals.schema.d.ts +2 -0
- package/dist/runtime-api/routes/signals.schema.d.ts.map +1 -1
- package/dist/runtime-api/routes/signals.schema.js +4 -0
- package/dist/runtime-api/routes/signals.schema.js.map +1 -1
- package/dist/scanners/engine/data-providers.d.ts +6 -0
- package/dist/scanners/engine/data-providers.d.ts.map +1 -1
- package/dist/scanners/engine/data-providers.js.map +1 -1
- package/dist/scanners/engine/engine.d.ts +9 -0
- package/dist/scanners/engine/engine.d.ts.map +1 -1
- package/dist/scanners/engine/engine.js +29 -6
- package/dist/scanners/engine/engine.js.map +1 -1
- package/dist/scanners/external/scaffold/ctx.py +55 -1
- package/dist/scanners/external/scaffold/delivery.py +92 -28
- package/dist/scanners/external/scaffold/preflight.py +1 -1
- package/dist/scanners/external/scaffold/scaffold.py +75 -2
- package/dist/scanners/runtime-module.d.ts +2 -0
- package/dist/scanners/runtime-module.d.ts.map +1 -1
- package/dist/scanners/runtime-module.js +14 -0
- package/dist/scanners/runtime-module.js.map +1 -1
- package/dist/senpi/client.d.ts +36 -1
- package/dist/senpi/client.d.ts.map +1 -1
- package/dist/senpi/client.js +100 -8
- package/dist/senpi/client.js.map +1 -1
- package/dist/senpi/types.d.ts +54 -2
- package/dist/senpi/types.d.ts.map +1 -1
- package/dist/telemetry/metrics.d.ts +15 -1
- package/dist/telemetry/metrics.d.ts.map +1 -1
- package/dist/telemetry/metrics.js +25 -1
- package/dist/telemetry/metrics.js.map +1 -1
- package/dist/telemetry/otel-sdk.d.ts +12 -0
- package/dist/telemetry/otel-sdk.d.ts.map +1 -1
- package/dist/telemetry/otel-sdk.js +47 -1
- package/dist/telemetry/otel-sdk.js.map +1 -1
- package/dist/telemetry/spans/span-hooks.d.ts +18 -1
- package/dist/telemetry/spans/span-hooks.d.ts.map +1 -1
- package/dist/telemetry/spans/span-hooks.js +306 -96
- package/dist/telemetry/spans/span-hooks.js.map +1 -1
- package/dist/telemetry/tool-plane.d.ts +2 -0
- package/dist/telemetry/tool-plane.d.ts.map +1 -1
- package/dist/telemetry/tool-plane.js +1 -0
- package/dist/telemetry/tool-plane.js.map +1 -1
- package/dist/tool-surface/crib-cache.d.ts +21 -0
- package/dist/tool-surface/crib-cache.d.ts.map +1 -0
- package/dist/tool-surface/crib-cache.js +54 -0
- package/dist/tool-surface/crib-cache.js.map +1 -0
- package/dist/tool-surface/crib-hook.d.ts +78 -0
- package/dist/tool-surface/crib-hook.d.ts.map +1 -0
- package/dist/tool-surface/crib-hook.js +217 -0
- package/dist/tool-surface/crib-hook.js.map +1 -0
- package/dist/tool-surface/crib-sheet.d.ts +56 -0
- package/dist/tool-surface/crib-sheet.d.ts.map +1 -0
- package/dist/tool-surface/crib-sheet.js +129 -0
- package/dist/tool-surface/crib-sheet.js.map +1 -0
- package/dist/tool-surface/mcp-tool-source.d.ts +64 -0
- package/dist/tool-surface/mcp-tool-source.d.ts.map +1 -0
- package/dist/tool-surface/mcp-tool-source.js +189 -0
- package/dist/tool-surface/mcp-tool-source.js.map +1 -0
- package/dist/types/dsl/index.d.ts +4 -0
- package/dist/types/dsl/index.d.ts.map +1 -1
- package/dist/utils/event-catalog.d.ts +141 -10
- package/dist/utils/event-catalog.d.ts.map +1 -1
- package/dist/utils/event-catalog.js +23 -1
- package/dist/utils/event-catalog.js.map +1 -1
- package/dist/utils/perp-coin.d.ts.map +1 -1
- package/dist/utils/perp-coin.js +2 -1
- package/dist/utils/perp-coin.js.map +1 -1
- package/dist/utils/resolve-order-type.d.ts.map +1 -1
- package/dist/utils/resolve-order-type.js +5 -1
- package/dist/utils/resolve-order-type.js.map +1 -1
- package/dist/validate/codes.d.ts +2 -0
- package/dist/validate/codes.d.ts.map +1 -1
- package/dist/validate/codes.js +6 -0
- package/dist/validate/codes.js.map +1 -1
- package/dist/validate/index.d.ts +1 -1
- package/dist/validate/index.d.ts.map +1 -1
- package/dist/validate/index.js +1 -1
- package/dist/validate/index.js.map +1 -1
- package/dist/validate/recipe-checks.d.ts +7 -0
- package/dist/validate/recipe-checks.d.ts.map +1 -1
- package/dist/validate/recipe-checks.js +18 -0
- package/dist/validate/recipe-checks.js.map +1 -1
- package/dist/validate/recipe.d.ts.map +1 -1
- package/dist/validate/recipe.js +2 -1
- package/dist/validate/recipe.js.map +1 -1
- package/dist/widgets/tool.d.ts +9 -0
- package/dist/widgets/tool.d.ts.map +1 -1
- package/dist/widgets/tool.js +1 -0
- package/dist/widgets/tool.js.map +1 -1
- package/examples/strategies/README.md +2 -1
- package/examples/strategies/iguana/README.md +3 -3
- package/examples/strategies/raptor/README.md +3 -3
- package/openclaw.plugin.json +11 -1
- package/package.json +5 -2
|
@@ -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
|
-
*
|
|
20
|
-
*
|
|
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
|
|
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
|
|
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
|
-
/**
|
|
31
|
-
|
|
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;
|
|
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
|
-
*
|
|
18
|
-
*
|
|
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.
|
|
40
|
+
this.refresh();
|
|
28
41
|
}
|
|
29
|
-
|
|
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
|
-
|
|
36
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
/**
|
|
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
|
|
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
|
-
|
|
70
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"approval-store.js","sourceRoot":"","sources":["../../src/approvals/approval-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACnG,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAO1C,qEAAqE;AACrE,MAAM,CAAC,MAAM,yBAAyB,GAAG,qBAAqB,CAAC;AAY/D,MAAM,OAAO,GAAkB,SAAS,CAAC;AAEzC;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,OAAO,iBAAiB;IAUT;IATF,QAAQ,CAAS;IAC1B,WAAW,GAAG,IAAI,GAAG,EAA4B,CAAC;IAC1D,yFAAyF;IACjF,eAAe,CAA4B;IACnD,iFAAiF;IACzE,yBAAyB,CAA4B;IAE7D,YACE,QAAgB,EACC,MAAmB;QAAnB,WAAM,GAAN,MAAM,CAAa;QAEpC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,yBAAyB,CAAC,CAAC;QAC1D,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAEO,SAAS,CAAC,OAAe,IAAI,CAAC,QAAQ;QAC5C,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC1B,OAAO,GAAG,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC;QAC9C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACpB,OAAO,OAAO,CAAC;YACjB,CAAC;YACD,uEAAuE;YACvE,8DAA8D;YAC9D,OAAO,cAAc,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACzC,CAAC;IACH,CAAC;IAED,0EAA0E;IAClE,OAAO;QACb,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAC7B,IAAI,GAAG,KAAK,IAAI,CAAC,eAAe,EAAE,CAAC;YACjC,OAAO;QACT,CAAC;QACD,yEAAyE;QACzE,wCAAwC;QACxC,IAAI,CAAC,eAAe,GAAG,GAAG,CAAC;QAC3B,IAAI,CAAC,WAAW,GAAG,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;IAC9E,CAAC;IAED;;;OAGG;IACK,QAAQ,CAAC,IAAa;QAC5B,MAAM,MAAM,GAAG,IAAI,GAAG,EAA4B,CAAC;QACnD,IAAI,GAAW,CAAC;QAChB,IAAI,CAAC;YACH,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC5C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACpB,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;YAC9B,CAAC;YACD,IAAI,IAAI,EAAE,CAAC;gBACT,IAAI,CAAC,MAAM,EAAE,IAAI,CACf,mHAAmH,IAAI,CAAC,QAAQ,QAAQ,UAAU,CAAC,GAAG,CAAC,EAAE,CAC1J,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;QAC/B,CAAC;QACD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA2B,CAAC;YACzD,MAAM,OAAO,GAAG,MAAM,EAAE,WAAW,CAAC;YACpC,IAAI,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;gBACtE,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;oBACpD,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBAChD,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE;4BACf,SAAS,EAAE,OAAO,KAAK,EAAE,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;yBACvE,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,IAAI,EAAE,CAAC;gBACT,IAAI,CAAC,MAAM,EAAE,IAAI,CACf,4GAA4G,IAAI,CAAC,QAAQ,QAAQ,UAAU,CAAC,GAAG,CAAC,EAAE,CACnJ,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,MAAM,EAAE,IAAI,GAAG,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;QAC1C,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IAC9B,CAAC;IAED,eAAe,CAAC,IAAY;QAC1B,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,IAAI,IAAI;QACN,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;IAC/B,CAAC;IAED;;;;;OAKG;IACH,mBAAmB,CAAC,IAAY;QAC9B,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,gFAAgF;YAChF,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YAC5C,OAAO,EAAE,IAAI,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChC,CAAC;QACD,MAAM,KAAK,GAAqB,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;QACxE,0EAA0E;QAC1E,4EAA4E;QAC5E,6BAA6B;QAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAChC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACpD,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,wEAAwE;YACxE,qEAAqE;YACrE,IAAI,IAAI,CAAC,yBAAyB,KAAK,MAAM,EAAE,CAAC;gBAC9C,IAAI,CAAC,yBAAyB,GAAG,MAAM,CAAC;gBACxC,IAAI,CAAC,MAAM,EAAE,IAAI,CACf,yHAAyH,IAAI,CAAC,QAAQ,SAAS,IAAI,EAAE,CACtJ,CAAC;YACJ,CAAC;YACD,8DAA8D;YAC9D,iEAAiE;YACjE,0EAA0E;YAC1E,wCAAwC;YACxC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAClC,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACxB,2EAA2E;QAC3E,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC;QAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACrC,IAAI,CAAC,eAAe,GAAG,OAAO,IAAI,MAAM,CAAC;QACzC,OAAO,OAAO,KAAK,SAAS,CAAC;IAC/B,CAAC;IAED;;;;;OAKG;IACK,OAAO,CAAC,MAAqC;QACnD,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;QAC7F,IAAI,CAAC;YACH,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACvD,MAAM,KAAK,GAA2B,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;YAClF,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;YAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACxC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;YACnC,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC;gBACH,UAAU,CAAC,OAAO,CAAC,CAAC;YACtB,CAAC;YAAC,MAAM,CAAC;gBACP,uBAAuB;YACzB,CAAC;YACD,IAAI,CAAC,MAAM,EAAE,IAAI,CACf,wFAAwF,IAAI,CAAC,QAAQ,QAAQ,UAAU,CAAC,GAAG,CAAC,EAAE,CAC/H,CAAC;YACF,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;CACF;AAED,SAAS,UAAU,CAAC,GAAY;IAC9B,OAAO,GAAG,YAAY,KAAK,IAAI,MAAM,IAAI,GAAG,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,CAAC;AACnG,CAAC;AAED,SAAS,UAAU,CAAC,GAAY;IAC9B,OAAO,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAC1D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/approvals/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAOH,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEzD,yCAAyC;AACzC,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE;QACR,IAAI,EAAE,iBAAiB,CAAC;QACxB,yEAAyE;QACzE,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,8EAA8E;IAC9E,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAWD;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,EAAE,
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/approvals/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAOH,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEzD,yCAAyC;AACzC,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE;QACR,IAAI,EAAE,iBAAiB,CAAC;QACxB,yEAAyE;QACzE,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,8EAA8E;IAC9E,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAWD;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC,EAAE,qBAqB9C,CAAC;AAIF;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,IAAI,qBAAqB,CAcjE;AAED,2CAA2C;AAC3C,wBAAgB,uCAAuC,IAAI,IAAI,CAE9D"}
|
|
@@ -47,12 +47,7 @@ export const FALLBACK_TOOL_APPROVALS_MANIFEST = {
|
|
|
47
47
|
"strategy_pause",
|
|
48
48
|
"strategy_top_up",
|
|
49
49
|
"strategy_withdraw_funds",
|
|
50
|
-
"strategy_bridge_funds_from_hyperliquid_to_evm",
|
|
51
50
|
"transfer_spot_to_perps",
|
|
52
|
-
// Not currently exposed by the senpi MCP server, but senpi-web's permission
|
|
53
|
-
// registry lists it — gating a tool that does not exist is a no-op, and it
|
|
54
|
-
// must not slip through unapproved if it ever ships.
|
|
55
|
-
"send_usdc",
|
|
56
51
|
"ratchet_stop_add",
|
|
57
52
|
"ratchet_stop_edit",
|
|
58
53
|
"ratchet_stop_delete",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/approvals/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAgBlD,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9B,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;IACzB,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC;QACjB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QACxE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC;KACpD,CAAC;IACF,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;CAC9C,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gCAAgC,GAA0B;IACrE,aAAa,EAAE,CAAC;IAChB,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE;IAChD,UAAU,EAAE;QACV,iBAAiB;QACjB,gBAAgB;QAChB,eAAe;QACf,cAAc;QACd,iBAAiB;QACjB,iCAAiC;QACjC,gBAAgB;QAChB,0BAA0B;QAC1B,iBAAiB;QACjB,gBAAgB;QAChB,iBAAiB;QACjB,yBAAyB;QACzB
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/approvals/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAgBlD,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9B,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;IACzB,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC;QACjB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QACxE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC;KACpD,CAAC;IACF,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;CAC9C,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gCAAgC,GAA0B;IACrE,aAAa,EAAE,CAAC;IAChB,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE;IAChD,UAAU,EAAE;QACV,iBAAiB;QACjB,gBAAgB;QAChB,eAAe;QACf,cAAc;QACd,iBAAiB;QACjB,iCAAiC;QACjC,gBAAgB;QAChB,0BAA0B;QAC1B,iBAAiB;QACjB,gBAAgB;QAChB,iBAAiB;QACjB,yBAAyB;QACzB,wBAAwB;QACxB,kBAAkB;QAClB,mBAAmB;QACnB,qBAAqB;KACtB;CACF,CAAC;AAEF,IAAI,MAAM,GAAiC,IAAI,CAAC;AAEhD;;;;;;;;GAQG;AACH,MAAM,UAAU,yBAAyB;IACvC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,gCAAgC,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3F,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;QACnE,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,YAAY,CAAC,kCAAkC,CAAC,CAAC,IAAI,CACnD,yEAAyE,OAAO,EAAE,CACnF,CAAC;QACF,MAAM,GAAG,gCAAgC,CAAC;IAC5C,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,2CAA2C;AAC3C,MAAM,UAAU,uCAAuC;IACrD,MAAM,GAAG,IAAI,CAAC;AAChB,CAAC"}
|
|
@@ -1,5 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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":"
|
|
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
|
|
10
|
-
eventLogger.event(EVENT_NAME.toolApprovalResolved,
|
|
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;
|
|
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,
|
|
1
|
+
{"version":3,"file":"tool-approval-gate.d.ts","sourceRoot":"","sources":["../../src/approvals/tool-approval-gate.ts"],"names":[],"mappings":"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"}
|