agent-nuvira 3.3.3 → 3.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -5
- package/dist/agent-sdk/src/agent.d.ts +2 -0
- package/dist/agent-sdk/src/agent.d.ts.map +1 -1
- package/dist/agent-sdk/src/define.d.ts +64 -0
- package/dist/agent-sdk/src/define.d.ts.map +1 -0
- package/dist/agent-sdk/src/define.js +76 -0
- package/dist/agent-sdk/src/define.js.map +1 -0
- package/dist/agent-sdk/src/index.d.ts +9 -0
- package/dist/agent-sdk/src/index.d.ts.map +1 -1
- package/dist/agent-sdk/src/index.js +9 -0
- package/dist/agent-sdk/src/index.js.map +1 -1
- package/dist/agent-sdk/src/scaffold.d.ts +11 -0
- package/dist/agent-sdk/src/scaffold.d.ts.map +1 -1
- package/dist/agent-sdk/src/scaffold.js +16 -6
- package/dist/agent-sdk/src/scaffold.js.map +1 -1
- package/dist/agents/long-form-plan.d.ts.map +1 -1
- package/dist/agents/long-form-plan.js +2 -1
- package/dist/agents/long-form-plan.js.map +1 -1
- package/dist/agents/orchestrator.d.ts.map +1 -1
- package/dist/agents/orchestrator.js +5 -4
- package/dist/agents/orchestrator.js.map +1 -1
- package/dist/cli/agent.d.ts +2 -2
- package/dist/cli/agent.js +10 -10
- package/dist/cli/chat.d.ts +94 -0
- package/dist/cli/chat.d.ts.map +1 -1
- package/dist/cli/chat.js +354 -20
- package/dist/cli/chat.js.map +1 -1
- package/dist/cli/cli-program.d.ts.map +1 -1
- package/dist/cli/cli-program.js +5 -0
- package/dist/cli/cli-program.js.map +1 -1
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +9 -1
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +3 -2
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/edit.js +2 -2
- package/dist/cli/eval.d.ts +17 -0
- package/dist/cli/eval.d.ts.map +1 -1
- package/dist/cli/eval.js +105 -2
- package/dist/cli/eval.js.map +1 -1
- package/dist/cli/execute.d.ts +16 -1
- package/dist/cli/execute.d.ts.map +1 -1
- package/dist/cli/execute.js +192 -22
- package/dist/cli/execute.js.map +1 -1
- package/dist/cli/loop-executor.d.ts +55 -0
- package/dist/cli/loop-executor.d.ts.map +1 -1
- package/dist/cli/loop-executor.js +212 -13
- package/dist/cli/loop-executor.js.map +1 -1
- package/dist/cli/model.d.ts.map +1 -1
- package/dist/cli/model.js +9 -8
- package/dist/cli/model.js.map +1 -1
- package/dist/cli/models.d.ts +1 -1
- package/dist/cli/models.js +4 -4
- package/dist/cli/parity.d.ts +85 -0
- package/dist/cli/parity.d.ts.map +1 -0
- package/dist/cli/parity.js +506 -0
- package/dist/cli/parity.js.map +1 -0
- package/dist/cli/plan.d.ts.map +1 -1
- package/dist/cli/plan.js +2 -1
- package/dist/cli/plan.js.map +1 -1
- package/dist/cli/retrieval.d.ts.map +1 -1
- package/dist/cli/retrieval.js +5 -4
- package/dist/cli/retrieval.js.map +1 -1
- package/dist/cli/sdk.js +4 -4
- package/dist/cli/sdk.js.map +1 -1
- package/dist/cli/trace.d.ts.map +1 -1
- package/dist/cli/trace.js +2 -1
- package/dist/cli/trace.js.map +1 -1
- package/dist/cli/workflow.js +2 -2
- package/dist/cli/workflow.js.map +1 -1
- package/dist/config/types.d.ts +44 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/findings/verdicts.d.ts +241 -0
- package/dist/findings/verdicts.d.ts.map +1 -0
- package/dist/findings/verdicts.js +284 -0
- package/dist/findings/verdicts.js.map +1 -0
- package/dist/gateway/adapters.d.ts +65 -0
- package/dist/gateway/adapters.d.ts.map +1 -1
- package/dist/gateway/adapters.js +216 -10
- package/dist/gateway/adapters.js.map +1 -1
- package/dist/gateway/channel-directory.d.ts +31 -0
- package/dist/gateway/channel-directory.d.ts.map +1 -1
- package/dist/gateway/channel-directory.js +40 -0
- package/dist/gateway/channel-directory.js.map +1 -1
- package/dist/gateway/gateway-log.d.ts +1 -1
- package/dist/gateway/gateway-log.d.ts.map +1 -1
- package/dist/gateway/gateway-log.js.map +1 -1
- package/dist/gateway/hooks.d.ts +87 -19
- package/dist/gateway/hooks.d.ts.map +1 -1
- package/dist/gateway/hooks.js +62 -23
- package/dist/gateway/hooks.js.map +1 -1
- package/dist/gateway/inbound-media.d.ts +147 -0
- package/dist/gateway/inbound-media.d.ts.map +1 -0
- package/dist/gateway/inbound-media.js +317 -0
- package/dist/gateway/inbound-media.js.map +1 -0
- package/dist/gateway/inbox.d.ts +8 -1
- package/dist/gateway/inbox.d.ts.map +1 -1
- package/dist/gateway/inbox.js.map +1 -1
- package/dist/gateway/platform-config.d.ts +14 -0
- package/dist/gateway/platform-config.d.ts.map +1 -1
- package/dist/gateway/platform-config.js +26 -8
- package/dist/gateway/platform-config.js.map +1 -1
- package/dist/gateway/realtime.d.ts +114 -0
- package/dist/gateway/realtime.d.ts.map +1 -0
- package/dist/gateway/realtime.js +402 -0
- package/dist/gateway/realtime.js.map +1 -0
- package/dist/gateway/registry.d.ts +31 -0
- package/dist/gateway/registry.d.ts.map +1 -1
- package/dist/gateway/registry.js +224 -4
- package/dist/gateway/registry.js.map +1 -1
- package/dist/gateway/whatsapp/baileys-bridge.d.ts +11 -1
- package/dist/gateway/whatsapp/baileys-bridge.d.ts.map +1 -1
- package/dist/gateway/whatsapp/baileys-bridge.js +123 -4
- package/dist/gateway/whatsapp/baileys-bridge.js.map +1 -1
- package/dist/gateway/whatsapp/bridge.d.ts +6 -2
- package/dist/gateway/whatsapp/bridge.d.ts.map +1 -1
- package/dist/gateway/whatsapp/bridge.js.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/inference/factory.d.ts +14 -0
- package/dist/inference/factory.d.ts.map +1 -1
- package/dist/inference/factory.js +17 -0
- package/dist/inference/factory.js.map +1 -1
- package/dist/inference/groq-adapter.d.ts +2 -0
- package/dist/inference/groq-adapter.d.ts.map +1 -1
- package/dist/inference/groq-adapter.js +16 -6
- package/dist/inference/groq-adapter.js.map +1 -1
- package/dist/inference/tools.d.ts.map +1 -1
- package/dist/inference/tools.js +29 -0
- package/dist/inference/tools.js.map +1 -1
- package/dist/learning/benchmark.d.ts.map +1 -1
- package/dist/learning/benchmark.js +3 -2
- package/dist/learning/benchmark.js.map +1 -1
- package/dist/learning/continuation.d.ts.map +1 -1
- package/dist/learning/continuation.js +2 -1
- package/dist/learning/continuation.js.map +1 -1
- package/dist/learning/cost-tracker.d.ts.map +1 -1
- package/dist/learning/cost-tracker.js +2 -1
- package/dist/learning/cost-tracker.js.map +1 -1
- package/dist/learning/deferred-task.d.ts.map +1 -1
- package/dist/learning/deferred-task.js +13 -4
- package/dist/learning/deferred-task.js.map +1 -1
- package/dist/learning/eval-framework.d.ts.map +1 -1
- package/dist/learning/eval-framework.js +2 -1
- package/dist/learning/eval-framework.js.map +1 -1
- package/dist/learning/long-form.d.ts.map +1 -1
- package/dist/learning/long-form.js +2 -1
- package/dist/learning/long-form.js.map +1 -1
- package/dist/learning/model-registry.d.ts.map +1 -1
- package/dist/learning/model-registry.js +2 -1
- package/dist/learning/model-registry.js.map +1 -1
- package/dist/learning/reasoning-cache.d.ts.map +1 -1
- package/dist/learning/reasoning-cache.js +2 -1
- package/dist/learning/reasoning-cache.js.map +1 -1
- package/dist/learning/reasoning-trace.d.ts +37 -1
- package/dist/learning/reasoning-trace.d.ts.map +1 -1
- package/dist/learning/reasoning-trace.js +66 -0
- package/dist/learning/reasoning-trace.js.map +1 -1
- package/dist/learning/resilient-call.d.ts.map +1 -1
- package/dist/learning/resilient-call.js +2 -1
- package/dist/learning/resilient-call.js.map +1 -1
- package/dist/learning/retrieval.d.ts.map +1 -1
- package/dist/learning/retrieval.js +2 -1
- package/dist/learning/retrieval.js.map +1 -1
- package/dist/learning/seeded-benchmark.d.ts +160 -0
- package/dist/learning/seeded-benchmark.d.ts.map +1 -0
- package/dist/learning/seeded-benchmark.js +321 -0
- package/dist/learning/seeded-benchmark.js.map +1 -0
- package/dist/learning/seeded-bugs.d.ts +142 -0
- package/dist/learning/seeded-bugs.d.ts.map +1 -0
- package/dist/learning/seeded-bugs.js +535 -0
- package/dist/learning/seeded-bugs.js.map +1 -0
- package/dist/learning/step-checkpoint.d.ts +127 -0
- package/dist/learning/step-checkpoint.d.ts.map +1 -0
- package/dist/learning/step-checkpoint.js +244 -0
- package/dist/learning/step-checkpoint.js.map +1 -0
- package/dist/nlu/intent-confirm.d.ts +23 -1
- package/dist/nlu/intent-confirm.d.ts.map +1 -1
- package/dist/nlu/intent-confirm.js +85 -2
- package/dist/nlu/intent-confirm.js.map +1 -1
- package/dist/nlu/learnings.d.ts +7 -0
- package/dist/nlu/learnings.d.ts.map +1 -1
- package/dist/nlu/learnings.js +7 -0
- package/dist/nlu/learnings.js.map +1 -1
- package/dist/observability/debug-log.d.ts +250 -0
- package/dist/observability/debug-log.d.ts.map +1 -0
- package/dist/observability/debug-log.js +500 -0
- package/dist/observability/debug-log.js.map +1 -0
- package/dist/observability/event-bus.d.ts.map +1 -1
- package/dist/observability/event-bus.js +4 -1
- package/dist/observability/event-bus.js.map +1 -1
- package/dist/observability/otel.d.ts +278 -0
- package/dist/observability/otel.d.ts.map +1 -0
- package/dist/observability/otel.js +590 -0
- package/dist/observability/otel.js.map +1 -0
- package/dist/parity/drivers.d.ts +99 -0
- package/dist/parity/drivers.d.ts.map +1 -0
- package/dist/parity/drivers.js +1362 -0
- package/dist/parity/drivers.js.map +1 -0
- package/dist/parity/graph.d.ts +73 -0
- package/dist/parity/graph.d.ts.map +1 -0
- package/dist/parity/graph.js +162 -0
- package/dist/parity/graph.js.map +1 -0
- package/dist/parity/matrix.d.ts +105 -0
- package/dist/parity/matrix.d.ts.map +1 -0
- package/dist/parity/matrix.js +352 -0
- package/dist/parity/matrix.js.map +1 -0
- package/dist/parity/observation.d.ts +444 -0
- package/dist/parity/observation.d.ts.map +1 -0
- package/dist/parity/observation.js +333 -0
- package/dist/parity/observation.js.map +1 -0
- package/dist/parity/scenarios.d.ts +229 -0
- package/dist/parity/scenarios.d.ts.map +1 -0
- package/dist/parity/scenarios.js +175 -0
- package/dist/parity/scenarios.js.map +1 -0
- package/dist/parity/surfaces.d.ts +122 -0
- package/dist/parity/surfaces.d.ts.map +1 -0
- package/dist/parity/surfaces.js +190 -0
- package/dist/parity/surfaces.js.map +1 -0
- package/dist/runtime/fault-injection.d.ts +173 -0
- package/dist/runtime/fault-injection.d.ts.map +1 -0
- package/dist/runtime/fault-injection.js +281 -0
- package/dist/runtime/fault-injection.js.map +1 -0
- package/dist/tools/child-agent-entry.d.ts +23 -0
- package/dist/tools/child-agent-entry.d.ts.map +1 -0
- package/dist/tools/child-agent-entry.js +129 -0
- package/dist/tools/child-agent-entry.js.map +1 -0
- package/dist/tools/child-agent-runtime.d.ts +124 -0
- package/dist/tools/child-agent-runtime.d.ts.map +1 -0
- package/dist/tools/child-agent-runtime.js +704 -0
- package/dist/tools/child-agent-runtime.js.map +1 -0
- package/dist/tools/coding-tools.d.ts.map +1 -1
- package/dist/tools/coding-tools.js +82 -10
- package/dist/tools/coding-tools.js.map +1 -1
- package/dist/tools/delegation-system.d.ts +31 -0
- package/dist/tools/delegation-system.d.ts.map +1 -1
- package/dist/tools/delegation-system.js +70 -9
- package/dist/tools/delegation-system.js.map +1 -1
- package/dist/tools/extract/docx.d.ts +27 -0
- package/dist/tools/extract/docx.d.ts.map +1 -0
- package/dist/tools/extract/docx.js +48 -0
- package/dist/tools/extract/docx.js.map +1 -0
- package/dist/tools/extract/html-text.d.ts +27 -0
- package/dist/tools/extract/html-text.d.ts.map +1 -0
- package/dist/tools/extract/html-text.js +86 -0
- package/dist/tools/extract/html-text.js.map +1 -0
- package/dist/tools/extract/pdf-ocr.d.ts +58 -0
- package/dist/tools/extract/pdf-ocr.d.ts.map +1 -0
- package/dist/tools/extract/pdf-ocr.js +116 -0
- package/dist/tools/extract/pdf-ocr.js.map +1 -0
- package/dist/tools/extract/pdf.d.ts +65 -0
- package/dist/tools/extract/pdf.d.ts.map +1 -0
- package/dist/tools/extract/pdf.js +197 -0
- package/dist/tools/extract/pdf.js.map +1 -0
- package/dist/tools/extract/pptx.d.ts +32 -0
- package/dist/tools/extract/pptx.d.ts.map +1 -0
- package/dist/tools/extract/pptx.js +77 -0
- package/dist/tools/extract/pptx.js.map +1 -0
- package/dist/tools/extract/xlsx.d.ts +47 -0
- package/dist/tools/extract/xlsx.d.ts.map +1 -0
- package/dist/tools/extract/xlsx.js +111 -0
- package/dist/tools/extract/xlsx.js.map +1 -0
- package/dist/tools/finding-tool.d.ts +76 -0
- package/dist/tools/finding-tool.d.ts.map +1 -0
- package/dist/tools/finding-tool.js +125 -0
- package/dist/tools/finding-tool.js.map +1 -0
- package/dist/tools/messaging-tools.d.ts +41 -11
- package/dist/tools/messaging-tools.d.ts.map +1 -1
- package/dist/tools/messaging-tools.js +104 -55
- package/dist/tools/messaging-tools.js.map +1 -1
- package/dist/tools/neutts-synth.d.ts +27 -3
- package/dist/tools/neutts-synth.d.ts.map +1 -1
- package/dist/tools/neutts-synth.js +57 -13
- package/dist/tools/neutts-synth.js.map +1 -1
- package/dist/tools/pipeline-tool.d.ts +43 -1
- package/dist/tools/pipeline-tool.d.ts.map +1 -1
- package/dist/tools/pipeline-tool.js +13 -2
- package/dist/tools/pipeline-tool.js.map +1 -1
- package/dist/tools/read-extract.d.ts +116 -45
- package/dist/tools/read-extract.d.ts.map +1 -1
- package/dist/tools/read-extract.js +494 -158
- package/dist/tools/read-extract.js.map +1 -1
- package/dist/tools/registry.d.ts +2 -2
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +152 -23
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/subagent-refusal.d.ts +15 -0
- package/dist/tools/subagent-refusal.d.ts.map +1 -0
- package/dist/tools/subagent-refusal.js +18 -0
- package/dist/tools/subagent-refusal.js.map +1 -0
- package/dist/tools/subagent-spawner.d.ts +122 -0
- package/dist/tools/subagent-spawner.d.ts.map +1 -1
- package/dist/tools/subagent-spawner.js +249 -28
- package/dist/tools/subagent-spawner.js.map +1 -1
- package/dist/tools/tool-hooks.d.ts +177 -0
- package/dist/tools/tool-hooks.d.ts.map +1 -0
- package/dist/tools/tool-hooks.js +427 -0
- package/dist/tools/tool-hooks.js.map +1 -0
- package/dist/tools/tool-loop.d.ts +82 -0
- package/dist/tools/tool-loop.d.ts.map +1 -1
- package/dist/tools/tool-loop.js +167 -9
- package/dist/tools/tool-loop.js.map +1 -1
- package/dist/tools/tool-refusal.d.ts +68 -0
- package/dist/tools/tool-refusal.d.ts.map +1 -0
- package/dist/tools/tool-refusal.js +78 -0
- package/dist/tools/tool-refusal.js.map +1 -0
- package/dist/tools/toolsets.d.ts +8 -0
- package/dist/tools/toolsets.d.ts.map +1 -1
- package/dist/tools/toolsets.js +12 -2
- package/dist/tools/toolsets.js.map +1 -1
- package/dist/tools/vision-tools.d.ts +88 -83
- package/dist/tools/vision-tools.d.ts.map +1 -1
- package/dist/tools/vision-tools.js +134 -103
- package/dist/tools/vision-tools.js.map +1 -1
- package/dist/tools/worktree.d.ts +210 -0
- package/dist/tools/worktree.d.ts.map +1 -0
- package/dist/tools/worktree.js +374 -0
- package/dist/tools/worktree.js.map +1 -0
- package/dist/utils/format.d.ts +3 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +32 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/web-dashboard/attachment-extract.d.ts +64 -0
- package/dist/web-dashboard/attachment-extract.d.ts.map +1 -0
- package/dist/web-dashboard/attachment-extract.js +154 -0
- package/dist/web-dashboard/attachment-extract.js.map +1 -0
- package/dist/web-dashboard/chat-console.d.ts +108 -1
- package/dist/web-dashboard/chat-console.d.ts.map +1 -1
- package/dist/web-dashboard/chat-console.js +36 -0
- package/dist/web-dashboard/chat-console.js.map +1 -1
- package/dist/web-dashboard/hub-data.d.ts +37 -0
- package/dist/web-dashboard/hub-data.d.ts.map +1 -1
- package/dist/web-dashboard/hub-data.js +61 -1
- package/dist/web-dashboard/hub-data.js.map +1 -1
- package/dist/web-dashboard/server.d.ts +14 -0
- package/dist/web-dashboard/server.d.ts.map +1 -1
- package/dist/web-dashboard/server.js +247 -13
- package/dist/web-dashboard/server.js.map +1 -1
- package/dist/web-dashboard/src/types.d.ts +196 -48
- package/dist/web-dashboard/src/types.d.ts.map +1 -1
- package/package.json +18 -3
- package/src/web-dashboard/public/assets/{index-Cyd6tIew.css → index-XJjj2cBX.css} +1 -1
- package/src/web-dashboard/public/assets/index-YWF9FpwQ.js +207 -0
- package/src/web-dashboard/public/assets/index-YWF9FpwQ.js.map +1 -0
- package/src/web-dashboard/public/index.html +2 -2
- package/dist/tools/child-agent-worker.js +0 -212
- package/src/web-dashboard/public/assets/index-CxDj7p6i.js +0 -207
- package/src/web-dashboard/public/assets/index-CxDj7p6i.js.map +0 -1
package/dist/gateway/hooks.d.ts
CHANGED
|
@@ -1,32 +1,83 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* I2 — Hook registry (`src/gateway/hooks.ts`).
|
|
3
3
|
*
|
|
4
|
-
* Lifecycle hooks the agent
|
|
5
|
-
*
|
|
4
|
+
* Lifecycle hooks the agent runtime fires at well-defined moments. The tool
|
|
5
|
+
* phases are the WS4 (#26) triple, in the order a call goes through them:
|
|
6
6
|
*
|
|
7
|
-
* - `
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* result, success flag and duration.
|
|
11
|
-
* - `
|
|
12
|
-
*
|
|
7
|
+
* - `before_tool_call` — BEFORE the call runs, and the ONLY phase that can stop
|
|
8
|
+
* it: a handler returns a {@link HookDecision} and the call is not made.
|
|
9
|
+
* - `after_tool_call` — the call ran and succeeded. Handlers receive the tool
|
|
10
|
+
* name, the result, the success flag and the duration.
|
|
11
|
+
* - `failed_tool_call` — the call ran and did NOT succeed (a thrown error, or a
|
|
12
|
+
* result the loop`s own convention marks as a failure).
|
|
13
|
+
* - `on_session_end` — after a pipeline run finishes (execute:completed /
|
|
14
|
+
* execute:failed). Handlers receive the run`s success + summary.
|
|
13
15
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
16
|
+
* `post_tool_call` was this event`s previous name. It is renamed rather than
|
|
17
|
+
* aliased so the three phases read exactly as the capability is stated
|
|
18
|
+
* (before/after/failed); nothing in production subscribed to it, and an alias
|
|
19
|
+
* would leave two names for one moment — the drift this repo removes elsewhere.
|
|
20
|
+
*
|
|
21
|
+
* THE TOOL PHASES ARE DRIVEN BY THE EXECUTION SEAM, not the event bus, and that
|
|
22
|
+
* is a deliberate reversal of the original wiring. A bus subscription is
|
|
23
|
+
* fire-and-forget: it cannot stop a call, it cannot tell the loop what a
|
|
24
|
+
* subscriber decided, and it only fires on a surface that happens to put
|
|
25
|
+
* `tool:called` on the bus — so a hook installed that way reached the gateway and
|
|
26
|
+
* nowhere else. `src/tools/tool-loop.ts` and `src/tools/child-agent-runtime.ts`
|
|
27
|
+
* call {@link HookRegistry.runBefore} / {@link HookRegistry.run} directly, which
|
|
28
|
+
* is what makes the hooks fire on all five surfaces and lets a veto be honoured.
|
|
29
|
+
*/
|
|
30
|
+
export type HookEvent = 'before_tool_call' | 'after_tool_call' | 'failed_tool_call' | 'on_session_end';
|
|
31
|
+
/**
|
|
32
|
+
* What a `before_tool_call` handler may return to stop the call.
|
|
33
|
+
*
|
|
34
|
+
* A RETURN VALUE rather than a mutation, because the registry has to hand the
|
|
35
|
+
* decision back to the caller that is about to run the tool: a subscriber that
|
|
36
|
+
* could only observe could not veto.
|
|
37
|
+
*/
|
|
38
|
+
export interface HookDecision {
|
|
39
|
+
/** `true` stops the call. There is no "deny: false" — an absent decision allows. */
|
|
40
|
+
deny: true;
|
|
41
|
+
/** Why, in the operator's words. Flows to the model and to the turn's trace. */
|
|
42
|
+
reason?: string;
|
|
43
|
+
/** Which hook decided (a declaration label, or a subscriber's own name). */
|
|
44
|
+
by?: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The call itself, as every tool phase sees it.
|
|
48
|
+
*
|
|
49
|
+
* `report` is how a subscriber says something went wrong in its OWN handling.
|
|
50
|
+
* It exists because the seam FAILS OPEN: a broken hook must not block work, so if
|
|
51
|
+
* there were no way to report one, a hook that silently stopped working would be
|
|
52
|
+
* indistinguishable from a hook that allowed everything.
|
|
17
53
|
*/
|
|
18
|
-
export
|
|
19
|
-
/** Context for `post_tool_call` handlers. */
|
|
20
|
-
export interface ToolCallHookContext {
|
|
54
|
+
export interface ToolCallRef {
|
|
21
55
|
tool: string;
|
|
56
|
+
/** The call's arguments, as the model produced them. */
|
|
57
|
+
args?: Record<string, unknown>;
|
|
58
|
+
/** The provider's call id, when there is one. */
|
|
59
|
+
callId?: string;
|
|
60
|
+
/** The surface label the turn declared (`cli-chat`, `subagent`, …). */
|
|
61
|
+
surface?: string;
|
|
62
|
+
cwd?: string;
|
|
63
|
+
report?: (message: string) => void;
|
|
64
|
+
}
|
|
65
|
+
/** Context for `after_tool_call` handlers. */
|
|
66
|
+
export interface ToolCallHookContext extends ToolCallRef {
|
|
22
67
|
ok: boolean;
|
|
23
68
|
/** The tool-result text fed back to the model (truncated for hooks). */
|
|
24
69
|
result?: string;
|
|
25
|
-
/** Error text when the tool failed. */
|
|
26
|
-
error?: string;
|
|
27
70
|
/** Execution duration in ms. */
|
|
28
71
|
durationMs?: number;
|
|
29
72
|
}
|
|
73
|
+
/** Context for `failed_tool_call` handlers. */
|
|
74
|
+
export interface FailedToolCallHookContext extends ToolCallRef {
|
|
75
|
+
/** Why it failed — the thrown message, or the failing result's own text. */
|
|
76
|
+
error: string;
|
|
77
|
+
/** The result text, when the tool returned a failure rather than throwing. */
|
|
78
|
+
result?: string;
|
|
79
|
+
durationMs?: number;
|
|
80
|
+
}
|
|
30
81
|
/** Context for `on_session_end` handlers. */
|
|
31
82
|
export interface SessionEndHookContext {
|
|
32
83
|
success: boolean;
|
|
@@ -34,8 +85,14 @@ export interface SessionEndHookContext {
|
|
|
34
85
|
/** The pipeline goal when known. */
|
|
35
86
|
goal?: string;
|
|
36
87
|
}
|
|
37
|
-
/**
|
|
38
|
-
|
|
88
|
+
/**
|
|
89
|
+
* A hook handler — sync or async; the registry runs them serially.
|
|
90
|
+
*
|
|
91
|
+
* A returned {@link HookDecision} is honoured for `before_tool_call` (the only
|
|
92
|
+
* phase where stopping the call is possible) and ignored elsewhere, so one
|
|
93
|
+
* handler type serves the whole registry.
|
|
94
|
+
*/
|
|
95
|
+
export type HookHandler<T> = (ctx: T) => void | HookDecision | Promise<void | HookDecision>;
|
|
39
96
|
declare class HookRegistry {
|
|
40
97
|
private handlers;
|
|
41
98
|
/** Register a handler for a hook event. Idempotent per (event, fn) pair. */
|
|
@@ -44,10 +101,21 @@ declare class HookRegistry {
|
|
|
44
101
|
unregister<T extends HookEvent>(event: T, handler: HookHandler<HookContextFor<T>>): void;
|
|
45
102
|
/** Run every handler for an event, serially, best-effort (never throws). */
|
|
46
103
|
run<T extends HookEvent>(event: T, ctx: HookContextFor<T>): Promise<void>;
|
|
104
|
+
/**
|
|
105
|
+
* Run the `before_tool_call` handlers and return the FIRST decision.
|
|
106
|
+
*
|
|
107
|
+
* Serial by construction: two hooks must not race over whether a call happens,
|
|
108
|
+
* and the first denial is the answer — a later hook cannot un-deny a call that
|
|
109
|
+
* has already been stopped. A handler that throws is reported and skipped
|
|
110
|
+
* (FAIL OPEN), so one broken hook cannot stop every tool call in the process.
|
|
111
|
+
*/
|
|
112
|
+
runBefore(ctx: BeforeToolCallHookContext): Promise<HookDecision | null>;
|
|
47
113
|
/** Registered handler counts per event (CLI/tests introspection). */
|
|
48
114
|
list(): Record<HookEvent, number>;
|
|
49
115
|
}
|
|
50
|
-
|
|
116
|
+
/** Context for `before_tool_call` handlers: the call, before it happens. */
|
|
117
|
+
export type BeforeToolCallHookContext = ToolCallRef;
|
|
118
|
+
type HookContextFor<T extends HookEvent> = T extends 'before_tool_call' ? BeforeToolCallHookContext : T extends 'after_tool_call' ? ToolCallHookContext : T extends 'failed_tool_call' ? FailedToolCallHookContext : SessionEndHookContext;
|
|
51
119
|
/** The singleton registry. */
|
|
52
120
|
export declare const hooks: HookRegistry;
|
|
53
121
|
/** Wire the registry to the event bus. Returns an unsubscribe function. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/gateway/hooks.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/gateway/hooks.ts"],"names":[],"mappings":"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"}
|
package/dist/gateway/hooks.js
CHANGED
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* I2 — Hook registry (`src/gateway/hooks.ts`).
|
|
3
3
|
*
|
|
4
|
-
* Lifecycle hooks the agent
|
|
5
|
-
*
|
|
4
|
+
* Lifecycle hooks the agent runtime fires at well-defined moments. The tool
|
|
5
|
+
* phases are the WS4 (#26) triple, in the order a call goes through them:
|
|
6
6
|
*
|
|
7
|
-
* - `
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* result, success flag and duration.
|
|
11
|
-
* - `
|
|
12
|
-
*
|
|
7
|
+
* - `before_tool_call` — BEFORE the call runs, and the ONLY phase that can stop
|
|
8
|
+
* it: a handler returns a {@link HookDecision} and the call is not made.
|
|
9
|
+
* - `after_tool_call` — the call ran and succeeded. Handlers receive the tool
|
|
10
|
+
* name, the result, the success flag and the duration.
|
|
11
|
+
* - `failed_tool_call` — the call ran and did NOT succeed (a thrown error, or a
|
|
12
|
+
* result the loop`s own convention marks as a failure).
|
|
13
|
+
* - `on_session_end` — after a pipeline run finishes (execute:completed /
|
|
14
|
+
* execute:failed). Handlers receive the run`s success + summary.
|
|
13
15
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
16
|
+
* `post_tool_call` was this event`s previous name. It is renamed rather than
|
|
17
|
+
* aliased so the three phases read exactly as the capability is stated
|
|
18
|
+
* (before/after/failed); nothing in production subscribed to it, and an alias
|
|
19
|
+
* would leave two names for one moment — the drift this repo removes elsewhere.
|
|
20
|
+
*
|
|
21
|
+
* THE TOOL PHASES ARE DRIVEN BY THE EXECUTION SEAM, not the event bus, and that
|
|
22
|
+
* is a deliberate reversal of the original wiring. A bus subscription is
|
|
23
|
+
* fire-and-forget: it cannot stop a call, it cannot tell the loop what a
|
|
24
|
+
* subscriber decided, and it only fires on a surface that happens to put
|
|
25
|
+
* `tool:called` on the bus — so a hook installed that way reached the gateway and
|
|
26
|
+
* nowhere else. `src/tools/tool-loop.ts` and `src/tools/child-agent-runtime.ts`
|
|
27
|
+
* call {@link HookRegistry.runBefore} / {@link HookRegistry.run} directly, which
|
|
28
|
+
* is what makes the hooks fire on all five surfaces and lets a veto be honoured.
|
|
17
29
|
*/
|
|
18
30
|
import { logger } from '../utils/logger.js';
|
|
19
31
|
import { getEventBus, EventNames } from '../observability/event-bus.js';
|
|
@@ -45,14 +57,46 @@ class HookRegistry {
|
|
|
45
57
|
await handler(ctx);
|
|
46
58
|
}
|
|
47
59
|
catch (err) {
|
|
48
|
-
|
|
60
|
+
const message = `hook '${event}' handler failed: ${err instanceof Error ? err.message : err}`;
|
|
61
|
+
// Told to the CALLER as well as the log, because a handler that throws is
|
|
62
|
+
// fail-open: without this, a broken subscriber is indistinguishable from
|
|
63
|
+
// one that approved.
|
|
64
|
+
ctx.report?.(message);
|
|
65
|
+
logger.debug(message);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Run the `before_tool_call` handlers and return the FIRST decision.
|
|
71
|
+
*
|
|
72
|
+
* Serial by construction: two hooks must not race over whether a call happens,
|
|
73
|
+
* and the first denial is the answer — a later hook cannot un-deny a call that
|
|
74
|
+
* has already been stopped. A handler that throws is reported and skipped
|
|
75
|
+
* (FAIL OPEN), so one broken hook cannot stop every tool call in the process.
|
|
76
|
+
*/
|
|
77
|
+
async runBefore(ctx) {
|
|
78
|
+
for (const handler of this.handlers.get('before_tool_call') ?? []) {
|
|
79
|
+
let decision;
|
|
80
|
+
try {
|
|
81
|
+
decision = await handler(ctx);
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
const message = `hook 'before_tool_call' handler failed: ${err instanceof Error ? err.message : err}`;
|
|
85
|
+
ctx.report?.(message);
|
|
86
|
+
logger.debug(message);
|
|
87
|
+
continue;
|
|
49
88
|
}
|
|
89
|
+
if (decision && decision.deny)
|
|
90
|
+
return decision;
|
|
50
91
|
}
|
|
92
|
+
return null;
|
|
51
93
|
}
|
|
52
94
|
/** Registered handler counts per event (CLI/tests introspection). */
|
|
53
95
|
list() {
|
|
54
96
|
return {
|
|
55
|
-
|
|
97
|
+
before_tool_call: this.handlers.get('before_tool_call')?.length ?? 0,
|
|
98
|
+
after_tool_call: this.handlers.get('after_tool_call')?.length ?? 0,
|
|
99
|
+
failed_tool_call: this.handlers.get('failed_tool_call')?.length ?? 0,
|
|
56
100
|
on_session_end: this.handlers.get('on_session_end')?.length ?? 0,
|
|
57
101
|
};
|
|
58
102
|
}
|
|
@@ -63,16 +107,11 @@ export const hooks = new HookRegistry();
|
|
|
63
107
|
/** Wire the registry to the event bus. Returns an unsubscribe function. */
|
|
64
108
|
export function installHooks(bus = getEventBus()) {
|
|
65
109
|
const unsubscribers = [];
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
result: typeof d.result === 'string' ? d.result.slice(0, 500) : undefined,
|
|
72
|
-
error: d.error,
|
|
73
|
-
durationMs: d.durationMs,
|
|
74
|
-
});
|
|
75
|
-
}));
|
|
110
|
+
// NOTE: there is deliberately no `tool:called` subscription here any more. The
|
|
111
|
+
// tool phases are driven by the execution seam (see the module header), and a
|
|
112
|
+
// bus subscription would fire every tool hook a SECOND time on any surface
|
|
113
|
+
// that puts the event on the bus — which is the kind of double-fire nobody
|
|
114
|
+
// notices until a hook has an external side effect.
|
|
76
115
|
unsubscribers.push(bus.on(EventNames.EXECUTE_COMPLETED, (record) => {
|
|
77
116
|
const d = (record.data ?? {});
|
|
78
117
|
void hooks.run('on_session_end', {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/gateway/hooks.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/gateway/hooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inbound document hydration for the gateway (`src/gateway/inbound-media.ts`).
|
|
3
|
+
*
|
|
4
|
+
* A messaging transport delivers a DOCUMENT (a PDF report, a DOCX contract, a
|
|
5
|
+
* spreadsheet) as bytes + a filename — never as text. The bridge only extracted
|
|
6
|
+
* `conversation` / `extendedTextMessage`, so a document message arrived with an
|
|
7
|
+
* empty `text` and was dropped at `if (!text) continue`: the sender's own file
|
|
8
|
+
* vanished with no reply and no record.
|
|
9
|
+
*
|
|
10
|
+
* This module is the fix for the inbound half of that gap. The bridge DOWNLOADS
|
|
11
|
+
* the bytes, they ride on `InboundMessage.media`, and `handleInbound` calls
|
|
12
|
+
* `hydrateInboundMedia` — which writes them to the artifact sandbox and runs the
|
|
13
|
+
* SAME `read_extract` the agent uses for a file in the project folder. The
|
|
14
|
+
* returned section is prepended to the turn's text, so a caption + a document
|
|
15
|
+
* becomes one request the model can act on.
|
|
16
|
+
*
|
|
17
|
+
* Extraction (not the download) is what makes the file usable: a document whose
|
|
18
|
+
* bytes never become text is still a message the agent cannot answer. When the
|
|
19
|
+
* file cannot be extracted the section says so, with the typed code and the
|
|
20
|
+
* concrete alternatives `read_extract` produces — never a silent empty result.
|
|
21
|
+
*
|
|
22
|
+
* Never throws: a media failure must not break the text turn it arrived with.
|
|
23
|
+
*/
|
|
24
|
+
/** A media attachment that rode in on an inbound message. */
|
|
25
|
+
export interface InboundMedia {
|
|
26
|
+
type: 'image' | 'video' | 'audio' | 'document';
|
|
27
|
+
/** The file's bytes (already downloaded by the transport). */
|
|
28
|
+
data: Uint8Array;
|
|
29
|
+
/** The sender's filename, when the transport provides one. */
|
|
30
|
+
filename?: string;
|
|
31
|
+
/** MIME type, when the transport provides one. */
|
|
32
|
+
mimetype?: string;
|
|
33
|
+
/** The transport's caption on the media message (may carry the instruction). */
|
|
34
|
+
caption?: string;
|
|
35
|
+
}
|
|
36
|
+
/** What we are willing to write + extract in one inbound turn. */
|
|
37
|
+
export declare const MAX_INBOUND_MEDIA_BYTES: number;
|
|
38
|
+
/** How long an extracted inbound attachment is kept before the sweep (ms). */
|
|
39
|
+
export declare const INBOUND_MEDIA_TTL_MS: number;
|
|
40
|
+
/**
|
|
41
|
+
* Sandbox size cap (bytes). Past this, the OLDEST remaining files are swept
|
|
42
|
+
* even if they are still inside the TTL — a long-running gateway fed scanned
|
|
43
|
+
* reports should not grow without bound.
|
|
44
|
+
*/
|
|
45
|
+
export declare const INBOUND_MEDIA_MAX_BYTES: number;
|
|
46
|
+
/**
|
|
47
|
+
* Reduce a sender-supplied name to a safe basename that keeps its extension —
|
|
48
|
+
* the name is untrusted and must never escape the artifact dir.
|
|
49
|
+
*/
|
|
50
|
+
export declare function safeInboundName(media: InboundMedia): string;
|
|
51
|
+
/** A document that arrived but could not be turned into text. */
|
|
52
|
+
export interface InboundMediaFailure {
|
|
53
|
+
/** The attachment's display name. */
|
|
54
|
+
name: string;
|
|
55
|
+
/** The media kind (only 'document' triggers the sender reply — see below). */
|
|
56
|
+
type: InboundMedia['type'];
|
|
57
|
+
/** A short, sender-safe reason (no stack traces, no not artifact paths). */
|
|
58
|
+
reason: string;
|
|
59
|
+
}
|
|
60
|
+
/** The outcome of hydrating one inbound attachment. */
|
|
61
|
+
export interface HydratedInboundMedia {
|
|
62
|
+
/**
|
|
63
|
+
* The labelled context section to prepend to the turn, or null when there is
|
|
64
|
+
* nothing to add. Never null in practice: extracted text, an image note, or a
|
|
65
|
+
* refusal note all produce a section.
|
|
66
|
+
*/
|
|
67
|
+
section: string | null;
|
|
68
|
+
/**
|
|
69
|
+
* Set when a DOCUMENT arrived but could not be turned into text. The registry
|
|
70
|
+
* auto-replies with this to the sender — a document that produces no text and
|
|
71
|
+
* no reply is precisely the failure this whole path exists to remove.
|
|
72
|
+
*/
|
|
73
|
+
failure?: InboundMediaFailure;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Render the sender-facing reply for a document that could not be extracted.
|
|
77
|
+
*
|
|
78
|
+
* Built from `reason` alone on purpose: the model-facing section carries the
|
|
79
|
+
* saved artifact path and agent-jargon alternatives (`call read_extract again
|
|
80
|
+
* with ocr:true`), neither of which belongs in a chat with the person who sent
|
|
81
|
+
* the file.
|
|
82
|
+
*/
|
|
83
|
+
export declare function formatMediaFailureReply(failure: InboundMediaFailure): string;
|
|
84
|
+
/**
|
|
85
|
+
* Extract an inbound media attachment into a labelled context section. Never
|
|
86
|
+
* throws — a failure is reported as `failure` (plus a refusal section) instead.
|
|
87
|
+
*
|
|
88
|
+
* The saved path is always included so the model can follow up on the ORIGINAL
|
|
89
|
+
* file (e.g. `read_extract` with `ocr:true` for a scanned PDF, or
|
|
90
|
+
* `describe_image` for an image) instead of only seeing the extracted text.
|
|
91
|
+
*/
|
|
92
|
+
export declare function hydrateInboundMedia(media: InboundMedia, opts?: {
|
|
93
|
+
maxBytes?: number;
|
|
94
|
+
}): Promise<HydratedInboundMedia>;
|
|
95
|
+
/** The effective inbound-attachment policy (config `gateway.inboundAttachments`). */
|
|
96
|
+
export interface InboundAttachmentPolicy {
|
|
97
|
+
/** When false, attachments are accepted but never downloaded or extracted. */
|
|
98
|
+
enabled: boolean;
|
|
99
|
+
/** Per-attachment byte cap (default MAX_INBOUND_MEDIA_BYTES). */
|
|
100
|
+
maxBytes: number;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Read the effective inbound-attachment policy from config. Never throws — an
|
|
104
|
+
* absent config (or a throwing ConfigManager) means the safe default: enabled,
|
|
105
|
+
* with the module's own cap.
|
|
106
|
+
*/
|
|
107
|
+
export declare function inboundAttachmentPolicy(cm?: {
|
|
108
|
+
getAll?: () => unknown;
|
|
109
|
+
}): InboundAttachmentPolicy;
|
|
110
|
+
/** A remote attachment to fetch before hydration (Discord CDN URL / Slack file). */
|
|
111
|
+
export interface RemoteAttachment {
|
|
112
|
+
/** The attachment's media kind (already classified by the caller). */
|
|
113
|
+
type: InboundMedia['type'];
|
|
114
|
+
url: string;
|
|
115
|
+
filename?: string;
|
|
116
|
+
mimetype?: string;
|
|
117
|
+
size?: number;
|
|
118
|
+
/** True when fetching the URL needs an Authorization bearer token (Slack). */
|
|
119
|
+
authenticated?: boolean;
|
|
120
|
+
/** The token to send when `authenticated` (the caller supplies its own). */
|
|
121
|
+
token?: string;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Download a remote attachment's bytes (never throws — null on any failure or
|
|
125
|
+
* an over-cap size). Shared by the webhook receiver and the real-time Discord
|
|
126
|
+
* gateway / Slack Socket Mode transports, so one code path fetches every
|
|
127
|
+
* inbound attachment.
|
|
128
|
+
*/
|
|
129
|
+
export declare function downloadInboundAttachment(att: RemoteAttachment): Promise<InboundMedia | null>;
|
|
130
|
+
/** What a sandbox sweep did (returned for the caller's log line). */
|
|
131
|
+
export interface InboundPruneResult {
|
|
132
|
+
removed: number;
|
|
133
|
+
bytesFreed: number;
|
|
134
|
+
kept: number;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Sweep the inbound artifact sandbox: remove files older than `maxAgeMs`, then
|
|
138
|
+
* (if still over `maxBytes`) the OLDEST of what remains until it fits. Safe to
|
|
139
|
+
* call on a schedule — never throws, and a file that cannot be removed is
|
|
140
|
+
* skipped rather than aborting the sweep.
|
|
141
|
+
*/
|
|
142
|
+
export declare function pruneInboundMedia(opts?: {
|
|
143
|
+
maxAgeMs?: number;
|
|
144
|
+
maxBytes?: number;
|
|
145
|
+
now?: number;
|
|
146
|
+
}): InboundPruneResult;
|
|
147
|
+
//# sourceMappingURL=inbound-media.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbound-media.d.ts","sourceRoot":"","sources":["../../src/gateway/inbound-media.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAMH,6DAA6D;AAC7D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,UAAU,CAAC;IAC/C,8DAA8D;IAC9D,IAAI,EAAE,UAAU,CAAC;IACjB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,kEAAkE;AAClE,eAAO,MAAM,uBAAuB,QAAmB,CAAC;AAExD,8EAA8E;AAC9E,eAAO,MAAM,oBAAoB,QAA0B,CAAC;AAE5D;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,QAAoB,CAAC;AAkCzD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAO3D;AAwBD,iEAAiE;AACjE,MAAM,WAAW,mBAAmB;IAClC,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;IAC3B,4EAA4E;IAC5E,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,uDAAuD;AACvD,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB;;;;OAIG;IACH,OAAO,CAAC,EAAE,mBAAmB,CAAC;CAC/B;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,CAM5E;AAED;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,YAAY,EACnB,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,OAAO,CAAC,oBAAoB,CAAC,CA+E/B;AAED,qFAAqF;AACrF,MAAM,WAAW,uBAAuB;IACtC,8EAA8E;IAC9E,OAAO,EAAE,OAAO,CAAC;IACjB,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,OAAO,CAAA;CAAE,GAAG,uBAAuB,CAahG;AAED,oFAAoF;AACpF,MAAM,WAAW,gBAAgB;IAC/B,sEAAsE;IACtE,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8EAA8E;IAC9E,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAgBnG;AAED,qEAAqE;AACrE,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAYD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GAChE,kBAAkB,CAuDpB"}
|