@namzu/sdk 0.4.2 → 0.4.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/CHANGELOG.md +46 -0
- package/dist/advisory/context.test.d.ts +16 -0
- package/dist/advisory/context.test.d.ts.map +1 -0
- package/dist/advisory/context.test.js +92 -0
- package/dist/advisory/context.test.js.map +1 -0
- package/dist/advisory/evaluator.test.d.ts +34 -0
- package/dist/advisory/evaluator.test.d.ts.map +1 -0
- package/dist/advisory/evaluator.test.js +172 -0
- package/dist/advisory/evaluator.test.js.map +1 -0
- package/dist/advisory/executor.test.d.ts +35 -0
- package/dist/advisory/executor.test.d.ts.map +1 -0
- package/dist/advisory/executor.test.js +233 -0
- package/dist/advisory/executor.test.js.map +1 -0
- package/dist/advisory/registry.test.d.ts +16 -0
- package/dist/advisory/registry.test.d.ts.map +1 -0
- package/dist/advisory/registry.test.js +62 -0
- package/dist/advisory/registry.test.js.map +1 -0
- package/dist/bridge/a2a/agent-card.test.d.ts +24 -0
- package/dist/bridge/a2a/agent-card.test.d.ts.map +1 -0
- package/dist/bridge/a2a/agent-card.test.js +118 -0
- package/dist/bridge/a2a/agent-card.test.js.map +1 -0
- package/dist/bridge/a2a/mapper.test.d.ts +29 -0
- package/dist/bridge/a2a/mapper.test.d.ts.map +1 -0
- package/dist/bridge/a2a/mapper.test.js +265 -0
- package/dist/bridge/a2a/mapper.test.js.map +1 -0
- package/dist/bridge/a2a/message.test.d.ts +20 -0
- package/dist/bridge/a2a/message.test.d.ts.map +1 -0
- package/dist/bridge/a2a/message.test.js +116 -0
- package/dist/bridge/a2a/message.test.js.map +1 -0
- package/dist/bridge/a2a/task.test.d.ts +29 -0
- package/dist/bridge/a2a/task.test.d.ts.map +1 -0
- package/dist/bridge/a2a/task.test.js +198 -0
- package/dist/bridge/a2a/task.test.js.map +1 -0
- package/dist/bridge/mcp/connector/adapter.test.d.ts +27 -0
- package/dist/bridge/mcp/connector/adapter.test.d.ts.map +1 -0
- package/dist/bridge/mcp/connector/adapter.test.js +203 -0
- package/dist/bridge/mcp/connector/adapter.test.js.map +1 -0
- package/dist/bridge/sse/mapper.test.d.ts +27 -0
- package/dist/bridge/sse/mapper.test.d.ts.map +1 -0
- package/dist/bridge/sse/mapper.test.js +271 -0
- package/dist/bridge/sse/mapper.test.js.map +1 -0
- package/dist/bridge/tools/connector/adapter.d.ts +2 -2
- package/dist/bridge/tools/connector/adapter.test.d.ts +28 -0
- package/dist/bridge/tools/connector/adapter.test.d.ts.map +1 -0
- package/dist/bridge/tools/connector/adapter.test.js +182 -0
- package/dist/bridge/tools/connector/adapter.test.js.map +1 -0
- package/dist/bridge/tools/connector/definitions.test.d.ts +23 -0
- package/dist/bridge/tools/connector/definitions.test.d.ts.map +1 -0
- package/dist/bridge/tools/connector/definitions.test.js +158 -0
- package/dist/bridge/tools/connector/definitions.test.js.map +1 -0
- package/dist/bridge/tools/connector/router.test.d.ts +21 -0
- package/dist/bridge/tools/connector/router.test.d.ts.map +1 -0
- package/dist/bridge/tools/connector/router.test.js +139 -0
- package/dist/bridge/tools/connector/router.test.js.map +1 -0
- package/dist/bus/breaker.test.d.ts +41 -0
- package/dist/bus/breaker.test.d.ts.map +1 -0
- package/dist/bus/breaker.test.js +242 -0
- package/dist/bus/breaker.test.js.map +1 -0
- package/dist/bus/index.d.ts +3 -1
- package/dist/bus/index.d.ts.map +1 -1
- package/dist/bus/index.js +18 -11
- package/dist/bus/index.js.map +1 -1
- package/dist/bus/index.test.d.ts +25 -0
- package/dist/bus/index.test.d.ts.map +1 -0
- package/dist/bus/index.test.js +151 -0
- package/dist/bus/index.test.js.map +1 -0
- package/dist/bus/lock.test.d.ts +44 -0
- package/dist/bus/lock.test.d.ts.map +1 -0
- package/dist/bus/lock.test.js +226 -0
- package/dist/bus/lock.test.js.map +1 -0
- package/dist/bus/ownership.test.d.ts +26 -0
- package/dist/bus/ownership.test.d.ts.map +1 -0
- package/dist/bus/ownership.test.js +205 -0
- package/dist/bus/ownership.test.js.map +1 -0
- package/dist/config/runtime.d.ts +28 -28
- package/dist/connector/BaseConnector.test.d.ts +21 -0
- package/dist/connector/BaseConnector.test.d.ts.map +1 -0
- package/dist/connector/BaseConnector.test.js +108 -0
- package/dist/connector/BaseConnector.test.js.map +1 -0
- package/dist/connector/builtins/http.test.d.ts +30 -0
- package/dist/connector/builtins/http.test.d.ts.map +1 -0
- package/dist/connector/builtins/http.test.js +232 -0
- package/dist/connector/builtins/http.test.js.map +1 -0
- package/dist/connector/builtins/webhook.test.d.ts +20 -0
- package/dist/connector/builtins/webhook.test.d.ts.map +1 -0
- package/dist/connector/builtins/webhook.test.js +113 -0
- package/dist/connector/builtins/webhook.test.js.map +1 -0
- package/dist/connector/execution/factory.test.d.ts +16 -0
- package/dist/connector/execution/factory.test.d.ts.map +1 -0
- package/dist/connector/execution/factory.test.js +64 -0
- package/dist/connector/execution/factory.test.js.map +1 -0
- package/dist/connector/execution/remote.test.d.ts +16 -0
- package/dist/connector/execution/remote.test.d.ts.map +1 -0
- package/dist/connector/execution/remote.test.js +53 -0
- package/dist/connector/execution/remote.test.js.map +1 -0
- package/dist/connector/mcp/adapter.test.d.ts +34 -0
- package/dist/connector/mcp/adapter.test.d.ts.map +1 -0
- package/dist/connector/mcp/adapter.test.js +199 -0
- package/dist/connector/mcp/adapter.test.js.map +1 -0
- package/dist/probe/context.d.ts +8 -0
- package/dist/probe/context.d.ts.map +1 -0
- package/dist/probe/context.js +7 -0
- package/dist/probe/context.js.map +1 -0
- package/dist/probe/errors.d.ts +12 -0
- package/dist/probe/errors.d.ts.map +1 -0
- package/dist/probe/errors.js +21 -0
- package/dist/probe/errors.js.map +1 -0
- package/dist/probe/index.d.ts +5 -0
- package/dist/probe/index.d.ts.map +1 -0
- package/dist/probe/index.js +4 -0
- package/dist/probe/index.js.map +1 -0
- package/dist/probe/registry.d.ts +24 -0
- package/dist/probe/registry.d.ts.map +1 -0
- package/dist/probe/registry.js +228 -0
- package/dist/probe/registry.js.map +1 -0
- package/dist/probe/registry.test.d.ts +7 -0
- package/dist/probe/registry.test.d.ts.map +1 -0
- package/dist/probe/registry.test.js +310 -0
- package/dist/probe/registry.test.js.map +1 -0
- package/dist/provider/instrumentation.d.ts +9 -0
- package/dist/provider/instrumentation.d.ts.map +1 -0
- package/dist/provider/instrumentation.js +104 -0
- package/dist/provider/instrumentation.js.map +1 -0
- package/dist/provider/instrumentation.test.d.ts +2 -0
- package/dist/provider/instrumentation.test.d.ts.map +1 -0
- package/dist/provider/instrumentation.test.js +152 -0
- package/dist/provider/instrumentation.test.js.map +1 -0
- package/dist/public-runtime.d.ts +5 -0
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +4 -0
- package/dist/public-runtime.js.map +1 -1
- package/dist/public-types.d.ts +3 -0
- package/dist/public-types.d.ts.map +1 -1
- package/dist/rag/chunking.test.d.ts +20 -0
- package/dist/rag/chunking.test.d.ts.map +1 -0
- package/dist/rag/chunking.test.js +92 -0
- package/dist/rag/chunking.test.js.map +1 -0
- package/dist/rag/context-assembler.test.d.ts +19 -0
- package/dist/rag/context-assembler.test.d.ts.map +1 -0
- package/dist/rag/context-assembler.test.js +98 -0
- package/dist/rag/context-assembler.test.js.map +1 -0
- package/dist/rag/embedding.test.d.ts +19 -0
- package/dist/rag/embedding.test.d.ts.map +1 -0
- package/dist/rag/embedding.test.js +115 -0
- package/dist/rag/embedding.test.js.map +1 -0
- package/dist/rag/ingestion.test.d.ts +22 -0
- package/dist/rag/ingestion.test.d.ts.map +1 -0
- package/dist/rag/ingestion.test.js +99 -0
- package/dist/rag/ingestion.test.js.map +1 -0
- package/dist/rag/knowledge-base.test.d.ts +17 -0
- package/dist/rag/knowledge-base.test.d.ts.map +1 -0
- package/dist/rag/knowledge-base.test.js +77 -0
- package/dist/rag/knowledge-base.test.js.map +1 -0
- package/dist/rag/rag-tool.test.d.ts +21 -0
- package/dist/rag/rag-tool.test.d.ts.map +1 -0
- package/dist/rag/rag-tool.test.js +149 -0
- package/dist/rag/rag-tool.test.js.map +1 -0
- package/dist/rag/retriever.test.d.ts +26 -0
- package/dist/rag/retriever.test.d.ts.map +1 -0
- package/dist/rag/retriever.test.js +180 -0
- package/dist/rag/retriever.test.js.map +1 -0
- package/dist/rag/vector-store.test.d.ts +38 -0
- package/dist/rag/vector-store.test.d.ts.map +1 -0
- package/dist/rag/vector-store.test.js +175 -0
- package/dist/rag/vector-store.test.js.map +1 -0
- package/dist/registry/ManagedRegistry.test.d.ts +21 -0
- package/dist/registry/ManagedRegistry.test.d.ts.map +1 -0
- package/dist/registry/ManagedRegistry.test.js +98 -0
- package/dist/registry/ManagedRegistry.test.js.map +1 -0
- package/dist/registry/Registry.test.d.ts +18 -0
- package/dist/registry/Registry.test.d.ts.map +1 -0
- package/dist/registry/Registry.test.js +79 -0
- package/dist/registry/Registry.test.js.map +1 -0
- package/dist/registry/agent/definitions.test.d.ts +15 -0
- package/dist/registry/agent/definitions.test.d.ts.map +1 -0
- package/dist/registry/agent/definitions.test.js +84 -0
- package/dist/registry/agent/definitions.test.js.map +1 -0
- package/dist/registry/connector/definitions.test.d.ts +13 -0
- package/dist/registry/connector/definitions.test.d.ts.map +1 -0
- package/dist/registry/connector/definitions.test.js +41 -0
- package/dist/registry/connector/definitions.test.js.map +1 -0
- package/dist/registry/connector/scoped.test.d.ts +21 -0
- package/dist/registry/connector/scoped.test.d.ts.map +1 -0
- package/dist/registry/connector/scoped.test.js +115 -0
- package/dist/registry/connector/scoped.test.js.map +1 -0
- package/dist/registry/plugin/index.test.d.ts +12 -0
- package/dist/registry/plugin/index.test.d.ts.map +1 -0
- package/dist/registry/plugin/index.test.js +69 -0
- package/dist/registry/plugin/index.test.js.map +1 -0
- package/dist/registry/tool/execute.test.d.ts +42 -0
- package/dist/registry/tool/execute.test.d.ts.map +1 -0
- package/dist/registry/tool/execute.test.js +281 -0
- package/dist/registry/tool/execute.test.js.map +1 -0
- package/dist/runtime/query/events.d.ts +3 -1
- package/dist/runtime/query/events.d.ts.map +1 -1
- package/dist/runtime/query/events.js +6 -1
- package/dist/runtime/query/events.js.map +1 -1
- package/dist/runtime/query/executor.d.ts +3 -1
- package/dist/runtime/query/executor.d.ts.map +1 -1
- package/dist/runtime/query/executor.js +30 -1
- package/dist/runtime/query/executor.js.map +1 -1
- package/dist/runtime/query/iteration/phases/advisory.test.d.ts +42 -0
- package/dist/runtime/query/iteration/phases/advisory.test.d.ts.map +1 -0
- package/dist/runtime/query/iteration/phases/advisory.test.js +334 -0
- package/dist/runtime/query/iteration/phases/advisory.test.js.map +1 -0
- package/dist/test-setup.d.ts +22 -0
- package/dist/test-setup.d.ts.map +1 -0
- package/dist/test-setup.js +23 -0
- package/dist/test-setup.js.map +1 -0
- package/dist/types/bus/index.d.ts +46 -2
- package/dist/types/bus/index.d.ts.map +1 -1
- package/dist/types/doctor/check.d.ts +41 -0
- package/dist/types/doctor/check.d.ts.map +1 -0
- package/dist/types/doctor/check.js +2 -0
- package/dist/types/doctor/check.js.map +1 -0
- package/dist/types/doctor/index.d.ts +2 -0
- package/dist/types/doctor/index.d.ts.map +1 -0
- package/dist/types/doctor/index.js +2 -0
- package/dist/types/doctor/index.js.map +1 -0
- package/dist/types/probe/event-kind.d.ts +6 -0
- package/dist/types/probe/event-kind.d.ts.map +1 -0
- package/dist/types/probe/event-kind.js +2 -0
- package/dist/types/probe/event-kind.js.map +1 -0
- package/dist/types/probe/event-of.d.ts +5 -0
- package/dist/types/probe/event-of.d.ts.map +1 -0
- package/dist/types/probe/event-of.js +2 -0
- package/dist/types/probe/event-of.js.map +1 -0
- package/dist/types/probe/index.d.ts +4 -0
- package/dist/types/probe/index.d.ts.map +1 -0
- package/dist/types/probe/index.js +2 -0
- package/dist/types/probe/index.js.map +1 -0
- package/dist/types/probe/registry.d.ts +27 -0
- package/dist/types/probe/registry.d.ts.map +1 -0
- package/dist/types/probe/registry.js +2 -0
- package/dist/types/probe/registry.js.map +1 -0
- package/dist/utils/logger.d.ts +1 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +5 -0
- package/dist/utils/logger.js.map +1 -1
- package/dist/vault/instrumentation.d.ts +11 -0
- package/dist/vault/instrumentation.d.ts.map +1 -0
- package/dist/vault/instrumentation.js +32 -0
- package/dist/vault/instrumentation.js.map +1 -0
- package/dist/vault/instrumentation.test.d.ts +2 -0
- package/dist/vault/instrumentation.test.d.ts.map +1 -0
- package/dist/vault/instrumentation.test.js +80 -0
- package/dist/vault/instrumentation.test.js.map +1 -0
- package/package.json +4 -1
- package/src/advisory/context.test.ts +109 -0
- package/src/advisory/evaluator.test.ts +192 -0
- package/src/advisory/executor.test.ts +272 -0
- package/src/advisory/registry.test.ts +75 -0
- package/src/bridge/a2a/agent-card.test.ts +140 -0
- package/src/bridge/a2a/mapper.test.ts +293 -0
- package/src/bridge/a2a/message.test.ts +138 -0
- package/src/bridge/a2a/task.test.ts +235 -0
- package/src/bridge/mcp/connector/adapter.test.ts +230 -0
- package/src/bridge/sse/mapper.test.ts +422 -0
- package/src/bridge/tools/connector/adapter.test.ts +224 -0
- package/src/bridge/tools/connector/definitions.test.ts +183 -0
- package/src/bridge/tools/connector/router.test.ts +159 -0
- package/src/bus/breaker.test.ts +274 -0
- package/src/bus/index.test.ts +183 -0
- package/src/bus/index.ts +21 -10
- package/src/bus/lock.test.ts +265 -0
- package/src/bus/ownership.test.ts +243 -0
- package/src/connector/BaseConnector.test.ts +130 -0
- package/src/connector/builtins/http.test.ts +290 -0
- package/src/connector/builtins/webhook.test.ts +138 -0
- package/src/connector/execution/factory.test.ts +75 -0
- package/src/connector/execution/remote.test.ts +63 -0
- package/src/connector/mcp/adapter.test.ts +249 -0
- package/src/probe/context.ts +14 -0
- package/src/probe/errors.ts +27 -0
- package/src/probe/index.ts +4 -0
- package/src/probe/registry.test.ts +480 -0
- package/src/probe/registry.ts +276 -0
- package/src/provider/instrumentation.test.ts +192 -0
- package/src/provider/instrumentation.ts +139 -0
- package/src/public-runtime.ts +17 -0
- package/src/public-types.ts +3 -0
- package/src/rag/chunking.test.ts +107 -0
- package/src/rag/context-assembler.test.ts +114 -0
- package/src/rag/embedding.test.ts +130 -0
- package/src/rag/ingestion.test.ts +114 -0
- package/src/rag/knowledge-base.test.ts +106 -0
- package/src/rag/rag-tool.test.ts +167 -0
- package/src/rag/retriever.test.ts +210 -0
- package/src/rag/vector-store.test.ts +196 -0
- package/src/registry/ManagedRegistry.test.ts +118 -0
- package/src/registry/Registry.test.ts +91 -0
- package/src/registry/agent/definitions.test.ts +100 -0
- package/src/registry/connector/definitions.test.ts +51 -0
- package/src/registry/connector/scoped.test.ts +129 -0
- package/src/registry/plugin/index.test.ts +85 -0
- package/src/registry/tool/execute.test.ts +330 -0
- package/src/runtime/query/events.ts +6 -1
- package/src/runtime/query/executor.ts +34 -0
- package/src/runtime/query/iteration/phases/advisory.test.ts +412 -0
- package/src/test-setup.ts +24 -0
- package/src/types/bus/index.ts +54 -2
- package/src/types/doctor/check.ts +53 -0
- package/src/types/doctor/index.ts +9 -0
- package/src/types/probe/event-kind.ts +8 -0
- package/src/types/probe/event-of.ts +3 -0
- package/src/types/probe/index.ts +11 -0
- package/src/types/probe/registry.ts +36 -0
- package/src/utils/logger.ts +6 -1
- package/src/vault/instrumentation.test.ts +98 -0
- package/src/vault/instrumentation.ts +56 -0
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Current-code invariants asserted (2026-04-21, ses_006 Phase 6 follow-up):
|
|
3
|
+
*
|
|
4
|
+
* This file pins the live mutation boundary that `src/advisory/*` tests
|
|
5
|
+
* intentionally do NOT cover: the advisory phase IS where advisories
|
|
6
|
+
* inject user messages into the run via `ctx.runMgr.pushMessage(...)`
|
|
7
|
+
* (Codex #6). A regression that drops the `pushMessage` call — silently
|
|
8
|
+
* dropping all advisor output — would pass `src/advisory` tests,
|
|
9
|
+
* typecheck, and lint. This file is the only thing that catches it.
|
|
10
|
+
*
|
|
11
|
+
* - **Early-return paths** (no side effects):
|
|
12
|
+
* - No `advisoryCtx` on the iteration ctx → returns immediately.
|
|
13
|
+
* - `advisoryCtx.checkBudget()` denies → returns; NO pushMessage.
|
|
14
|
+
* - Evaluator fires no triggers → returns; NO pushMessage.
|
|
15
|
+
* - Trigger fires but advisor not found in registry → warn log +
|
|
16
|
+
* return; NO pushMessage.
|
|
17
|
+
* - Executor throws → warn log + return; NO pushMessage (partial
|
|
18
|
+
* work NOT persisted).
|
|
19
|
+
* - **Happy path** — trigger fires + advisor resolves + executor
|
|
20
|
+
* succeeds:
|
|
21
|
+
* - Calls `executor.consult(advisor, request, callCtx)` exactly once.
|
|
22
|
+
* - Calls `evaluator.recordFiring(trigger.id, iteration)`.
|
|
23
|
+
* - Calls `advisoryCtx.recordCall(...)` with the full call record.
|
|
24
|
+
* - Calls `runMgr.pushMessage(createUserMessage(wrapped))` exactly
|
|
25
|
+
* once.
|
|
26
|
+
* - The wrapped message includes `<advisory-result advisor="..."
|
|
27
|
+
* trigger="...">` + the advice text + closing tag.
|
|
28
|
+
* - When the result carries `warnings`, they appear under a
|
|
29
|
+
* "Warnings:" section.
|
|
30
|
+
* - When the result carries `decisions`, they appear under a
|
|
31
|
+
* "Decisions:" section AND each decision is pushed to
|
|
32
|
+
* `workingStateManager.addDecision` (if a workingStateManager is
|
|
33
|
+
* present on ctx).
|
|
34
|
+
* - **Trigger selection**: only the first trigger from
|
|
35
|
+
* `evaluator.evaluate(state)[0]` is used per iteration; other fired
|
|
36
|
+
* triggers are discarded this round.
|
|
37
|
+
* - **Question resolution**: `trigger.questionTemplate` is used when
|
|
38
|
+
* set; otherwise the phase uses a default
|
|
39
|
+
* "Iteration N: Review the current progress..." string.
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
import { describe, expect, it, vi } from 'vitest'
|
|
43
|
+
|
|
44
|
+
import type { AdvisoryContext } from '../../../../advisory/context.js'
|
|
45
|
+
import type {
|
|
46
|
+
AdvisorDefinition,
|
|
47
|
+
AdvisoryResult,
|
|
48
|
+
AdvisoryTrigger,
|
|
49
|
+
} from '../../../../types/advisory/index.js'
|
|
50
|
+
import type { RunId } from '../../../../types/ids/index.js'
|
|
51
|
+
import type { Logger } from '../../../../utils/logger.js'
|
|
52
|
+
|
|
53
|
+
import { runAdvisoryPhase } from './advisory.js'
|
|
54
|
+
import type { IterationContext } from './context.js'
|
|
55
|
+
|
|
56
|
+
function makeLogger(): Logger {
|
|
57
|
+
const self = {
|
|
58
|
+
info: vi.fn(),
|
|
59
|
+
warn: vi.fn(),
|
|
60
|
+
error: vi.fn(),
|
|
61
|
+
debug: vi.fn(),
|
|
62
|
+
child: vi.fn(),
|
|
63
|
+
} as unknown as Logger
|
|
64
|
+
;(self as { child: (ctx: unknown) => Logger }).child = vi.fn(() => self)
|
|
65
|
+
return self
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
interface MockAdvisoryCtxOptions {
|
|
69
|
+
budgetAllowed?: boolean
|
|
70
|
+
firedTriggers?: AdvisoryTrigger[]
|
|
71
|
+
advisor?: AdvisorDefinition
|
|
72
|
+
consultResult?: AdvisoryResult
|
|
73
|
+
consultThrows?: Error
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function makeAdvisoryCtx(options: MockAdvisoryCtxOptions = {}) {
|
|
77
|
+
const {
|
|
78
|
+
budgetAllowed = true,
|
|
79
|
+
firedTriggers = [],
|
|
80
|
+
advisor,
|
|
81
|
+
consultResult = { advice: 'do the thing' },
|
|
82
|
+
consultThrows,
|
|
83
|
+
} = options
|
|
84
|
+
|
|
85
|
+
const consult = vi.fn(async () => {
|
|
86
|
+
if (consultThrows) throw consultThrows
|
|
87
|
+
return {
|
|
88
|
+
result: consultResult,
|
|
89
|
+
usage: {
|
|
90
|
+
promptTokens: 0,
|
|
91
|
+
completionTokens: 0,
|
|
92
|
+
totalTokens: 0,
|
|
93
|
+
cachedTokens: 0,
|
|
94
|
+
cacheWriteTokens: 0,
|
|
95
|
+
},
|
|
96
|
+
cost: { inputCostPer1M: 0, outputCostPer1M: 0, totalCost: 0, cacheDiscount: 0 },
|
|
97
|
+
durationMs: 1,
|
|
98
|
+
}
|
|
99
|
+
})
|
|
100
|
+
const evaluate = vi.fn(() => firedTriggers)
|
|
101
|
+
const recordFiring = vi.fn()
|
|
102
|
+
const resolve = vi.fn(() => advisor)
|
|
103
|
+
const checkBudget = vi.fn(() => ({
|
|
104
|
+
allowed: budgetAllowed,
|
|
105
|
+
reason: budgetAllowed ? undefined : 'exhausted',
|
|
106
|
+
}))
|
|
107
|
+
const recordCall = vi.fn()
|
|
108
|
+
|
|
109
|
+
return {
|
|
110
|
+
ctx: {
|
|
111
|
+
registry: { resolve },
|
|
112
|
+
executor: { consult },
|
|
113
|
+
evaluator: { evaluate, recordFiring },
|
|
114
|
+
checkBudget,
|
|
115
|
+
recordCall,
|
|
116
|
+
callHistory: [],
|
|
117
|
+
} as unknown as AdvisoryContext,
|
|
118
|
+
mocks: { consult, evaluate, recordFiring, resolve, checkBudget, recordCall },
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
interface MockCtxOptions {
|
|
123
|
+
advisoryCtx?: AdvisoryContext
|
|
124
|
+
withWorkingState?: boolean
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function makeCtx(options: MockCtxOptions = {}): {
|
|
128
|
+
ctx: IterationContext
|
|
129
|
+
pushMessage: ReturnType<typeof vi.fn>
|
|
130
|
+
addDecision: ReturnType<typeof vi.fn>
|
|
131
|
+
} {
|
|
132
|
+
const pushMessage = vi.fn()
|
|
133
|
+
const addDecision = vi.fn()
|
|
134
|
+
|
|
135
|
+
const ctx = {
|
|
136
|
+
advisoryCtx: options.advisoryCtx,
|
|
137
|
+
runConfig: { tokenBudget: 100_000, costLimitUsd: undefined },
|
|
138
|
+
tools: {
|
|
139
|
+
get: vi.fn(() => undefined),
|
|
140
|
+
toLLMTools: vi.fn(() => []),
|
|
141
|
+
},
|
|
142
|
+
runMgr: {
|
|
143
|
+
id: 'run_1' as RunId,
|
|
144
|
+
messages: [],
|
|
145
|
+
tokenUsage: {
|
|
146
|
+
promptTokens: 0,
|
|
147
|
+
completionTokens: 0,
|
|
148
|
+
totalTokens: 0,
|
|
149
|
+
cachedTokens: 0,
|
|
150
|
+
cacheWriteTokens: 0,
|
|
151
|
+
},
|
|
152
|
+
costInfo: {
|
|
153
|
+
inputCostPer1M: 0,
|
|
154
|
+
outputCostPer1M: 0,
|
|
155
|
+
totalCost: 0,
|
|
156
|
+
cacheDiscount: 0,
|
|
157
|
+
},
|
|
158
|
+
pushMessage,
|
|
159
|
+
},
|
|
160
|
+
log: makeLogger(),
|
|
161
|
+
workingStateManager: options.withWorkingState
|
|
162
|
+
? {
|
|
163
|
+
getState: vi.fn(() => ({
|
|
164
|
+
task: '',
|
|
165
|
+
plan: [],
|
|
166
|
+
files: new Map(),
|
|
167
|
+
decisions: [],
|
|
168
|
+
failures: [],
|
|
169
|
+
discoveries: [],
|
|
170
|
+
environment: [],
|
|
171
|
+
toolResults: [],
|
|
172
|
+
userRequirements: [],
|
|
173
|
+
assistantNotes: [],
|
|
174
|
+
})),
|
|
175
|
+
addDecision,
|
|
176
|
+
}
|
|
177
|
+
: undefined,
|
|
178
|
+
} as unknown as IterationContext
|
|
179
|
+
|
|
180
|
+
return { ctx, pushMessage, addDecision }
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const response = {
|
|
184
|
+
id: 'r',
|
|
185
|
+
model: 'm',
|
|
186
|
+
message: { role: 'assistant' as const, content: 'text' },
|
|
187
|
+
usage: {
|
|
188
|
+
promptTokens: 0,
|
|
189
|
+
completionTokens: 0,
|
|
190
|
+
totalTokens: 0,
|
|
191
|
+
cachedTokens: 0,
|
|
192
|
+
cacheWriteTokens: 0,
|
|
193
|
+
},
|
|
194
|
+
finishReason: 'stop' as const,
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const advisor: AdvisorDefinition = {
|
|
198
|
+
id: 'adv',
|
|
199
|
+
name: 'Advisor',
|
|
200
|
+
provider: {} as never,
|
|
201
|
+
model: 'opus',
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const trigger: AdvisoryTrigger = {
|
|
205
|
+
id: 'trig',
|
|
206
|
+
condition: { type: 'on_iteration', everyN: 1 },
|
|
207
|
+
advisorId: 'adv',
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
describe('runAdvisoryPhase — early-return paths (no pushMessage)', () => {
|
|
211
|
+
it('returns immediately when advisoryCtx is absent', async () => {
|
|
212
|
+
const { ctx, pushMessage } = makeCtx()
|
|
213
|
+
await runAdvisoryPhase(ctx, 1, response)
|
|
214
|
+
expect(pushMessage).not.toHaveBeenCalled()
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
it('returns when budget is denied', async () => {
|
|
218
|
+
const { ctx: advCtx, mocks } = makeAdvisoryCtx({ budgetAllowed: false })
|
|
219
|
+
const { ctx, pushMessage } = makeCtx({ advisoryCtx: advCtx })
|
|
220
|
+
await runAdvisoryPhase(ctx, 1, response)
|
|
221
|
+
expect(mocks.checkBudget).toHaveBeenCalled()
|
|
222
|
+
expect(mocks.evaluate).not.toHaveBeenCalled()
|
|
223
|
+
expect(pushMessage).not.toHaveBeenCalled()
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
it('returns when evaluator fires no triggers', async () => {
|
|
227
|
+
const { ctx: advCtx, mocks } = makeAdvisoryCtx({ firedTriggers: [] })
|
|
228
|
+
const { ctx, pushMessage } = makeCtx({ advisoryCtx: advCtx })
|
|
229
|
+
await runAdvisoryPhase(ctx, 1, response)
|
|
230
|
+
expect(mocks.evaluate).toHaveBeenCalled()
|
|
231
|
+
expect(mocks.resolve).not.toHaveBeenCalled()
|
|
232
|
+
expect(pushMessage).not.toHaveBeenCalled()
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
it('returns (warn) when trigger fires but advisor is not resolved', async () => {
|
|
236
|
+
const { ctx: advCtx, mocks } = makeAdvisoryCtx({
|
|
237
|
+
firedTriggers: [trigger],
|
|
238
|
+
advisor: undefined,
|
|
239
|
+
})
|
|
240
|
+
const { ctx, pushMessage } = makeCtx({ advisoryCtx: advCtx })
|
|
241
|
+
await runAdvisoryPhase(ctx, 1, response)
|
|
242
|
+
expect(mocks.resolve).toHaveBeenCalledWith('adv')
|
|
243
|
+
expect(mocks.consult).not.toHaveBeenCalled()
|
|
244
|
+
expect(pushMessage).not.toHaveBeenCalled()
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
it('returns when executor.consult throws — does NOT pushMessage partial work', async () => {
|
|
248
|
+
const { ctx: advCtx, mocks } = makeAdvisoryCtx({
|
|
249
|
+
firedTriggers: [trigger],
|
|
250
|
+
advisor,
|
|
251
|
+
consultThrows: new Error('provider timeout'),
|
|
252
|
+
})
|
|
253
|
+
const { ctx, pushMessage } = makeCtx({ advisoryCtx: advCtx })
|
|
254
|
+
await runAdvisoryPhase(ctx, 1, response)
|
|
255
|
+
expect(mocks.consult).toHaveBeenCalled()
|
|
256
|
+
expect(mocks.recordFiring).not.toHaveBeenCalled()
|
|
257
|
+
expect(mocks.recordCall).not.toHaveBeenCalled()
|
|
258
|
+
expect(pushMessage).not.toHaveBeenCalled()
|
|
259
|
+
})
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
describe('runAdvisoryPhase — happy path', () => {
|
|
263
|
+
it('calls executor + recordFiring + recordCall + pushMessage exactly once', async () => {
|
|
264
|
+
const { ctx: advCtx, mocks } = makeAdvisoryCtx({
|
|
265
|
+
firedTriggers: [trigger],
|
|
266
|
+
advisor,
|
|
267
|
+
consultResult: { advice: 'do the thing' },
|
|
268
|
+
})
|
|
269
|
+
const { ctx, pushMessage } = makeCtx({ advisoryCtx: advCtx })
|
|
270
|
+
|
|
271
|
+
await runAdvisoryPhase(ctx, 3, response)
|
|
272
|
+
|
|
273
|
+
expect(mocks.consult).toHaveBeenCalledTimes(1)
|
|
274
|
+
expect(mocks.recordFiring).toHaveBeenCalledWith('trig', 3)
|
|
275
|
+
expect(mocks.recordCall).toHaveBeenCalledTimes(1)
|
|
276
|
+
expect(pushMessage).toHaveBeenCalledTimes(1)
|
|
277
|
+
})
|
|
278
|
+
|
|
279
|
+
it('pushMessage wraps advice in <advisory-result> envelope with role user', async () => {
|
|
280
|
+
const { ctx: advCtx } = makeAdvisoryCtx({
|
|
281
|
+
firedTriggers: [trigger],
|
|
282
|
+
advisor,
|
|
283
|
+
consultResult: { advice: 'specific advice text' },
|
|
284
|
+
})
|
|
285
|
+
const { ctx, pushMessage } = makeCtx({ advisoryCtx: advCtx })
|
|
286
|
+
|
|
287
|
+
await runAdvisoryPhase(ctx, 1, response)
|
|
288
|
+
|
|
289
|
+
const pushed = pushMessage.mock.calls[0]?.[0] as { role: string; content: string }
|
|
290
|
+
expect(pushed.role).toBe('user')
|
|
291
|
+
expect(pushed.content).toContain('<advisory-result advisor="Advisor" trigger="trig">')
|
|
292
|
+
expect(pushed.content).toContain('specific advice text')
|
|
293
|
+
expect(pushed.content).toContain('</advisory-result>')
|
|
294
|
+
})
|
|
295
|
+
|
|
296
|
+
it('includes Warnings section when the result carries warnings', async () => {
|
|
297
|
+
const { ctx: advCtx } = makeAdvisoryCtx({
|
|
298
|
+
firedTriggers: [trigger],
|
|
299
|
+
advisor,
|
|
300
|
+
consultResult: {
|
|
301
|
+
advice: 'proceed',
|
|
302
|
+
warnings: ['slow response', 'retry likely'],
|
|
303
|
+
},
|
|
304
|
+
})
|
|
305
|
+
const { ctx, pushMessage } = makeCtx({ advisoryCtx: advCtx })
|
|
306
|
+
|
|
307
|
+
await runAdvisoryPhase(ctx, 1, response)
|
|
308
|
+
|
|
309
|
+
const pushed = pushMessage.mock.calls[0]?.[0] as { content: string }
|
|
310
|
+
expect(pushed.content).toContain('Warnings:')
|
|
311
|
+
expect(pushed.content).toContain('- slow response')
|
|
312
|
+
expect(pushed.content).toContain('- retry likely')
|
|
313
|
+
})
|
|
314
|
+
|
|
315
|
+
it('includes Decisions section + pushes each decision to workingStateManager', async () => {
|
|
316
|
+
const { ctx: advCtx } = makeAdvisoryCtx({
|
|
317
|
+
firedTriggers: [trigger],
|
|
318
|
+
advisor,
|
|
319
|
+
consultResult: {
|
|
320
|
+
advice: 'go',
|
|
321
|
+
decisions: ['use sqlite', 'skip migration'],
|
|
322
|
+
},
|
|
323
|
+
})
|
|
324
|
+
const { ctx, pushMessage, addDecision } = makeCtx({
|
|
325
|
+
advisoryCtx: advCtx,
|
|
326
|
+
withWorkingState: true,
|
|
327
|
+
})
|
|
328
|
+
|
|
329
|
+
await runAdvisoryPhase(ctx, 1, response)
|
|
330
|
+
|
|
331
|
+
const pushed = pushMessage.mock.calls[0]?.[0] as { content: string }
|
|
332
|
+
expect(pushed.content).toContain('Decisions:')
|
|
333
|
+
expect(pushed.content).toContain('- use sqlite')
|
|
334
|
+
expect(pushed.content).toContain('- skip migration')
|
|
335
|
+
|
|
336
|
+
expect(addDecision).toHaveBeenCalledTimes(2)
|
|
337
|
+
expect(addDecision).toHaveBeenCalledWith('use sqlite')
|
|
338
|
+
expect(addDecision).toHaveBeenCalledWith('skip migration')
|
|
339
|
+
})
|
|
340
|
+
|
|
341
|
+
it('does NOT attempt to addDecision when no workingStateManager is present', async () => {
|
|
342
|
+
const { ctx: advCtx } = makeAdvisoryCtx({
|
|
343
|
+
firedTriggers: [trigger],
|
|
344
|
+
advisor,
|
|
345
|
+
consultResult: {
|
|
346
|
+
advice: 'go',
|
|
347
|
+
decisions: ['a'],
|
|
348
|
+
},
|
|
349
|
+
})
|
|
350
|
+
const { ctx, pushMessage } = makeCtx({ advisoryCtx: advCtx, withWorkingState: false })
|
|
351
|
+
|
|
352
|
+
await runAdvisoryPhase(ctx, 1, response)
|
|
353
|
+
// pushMessage still carries the Decisions section in content
|
|
354
|
+
expect((pushMessage.mock.calls[0]?.[0] as { content: string }).content).toContain('- a')
|
|
355
|
+
})
|
|
356
|
+
})
|
|
357
|
+
|
|
358
|
+
describe('runAdvisoryPhase — trigger selection + question', () => {
|
|
359
|
+
it('uses only the first fired trigger per iteration', async () => {
|
|
360
|
+
const other: AdvisoryTrigger = {
|
|
361
|
+
id: 'other',
|
|
362
|
+
condition: { type: 'on_iteration', everyN: 1 },
|
|
363
|
+
advisorId: 'adv',
|
|
364
|
+
}
|
|
365
|
+
const { ctx: advCtx, mocks } = makeAdvisoryCtx({
|
|
366
|
+
firedTriggers: [trigger, other],
|
|
367
|
+
advisor,
|
|
368
|
+
})
|
|
369
|
+
const { ctx } = makeCtx({ advisoryCtx: advCtx })
|
|
370
|
+
|
|
371
|
+
await runAdvisoryPhase(ctx, 1, response)
|
|
372
|
+
|
|
373
|
+
expect(mocks.recordFiring).toHaveBeenCalledTimes(1)
|
|
374
|
+
expect(mocks.recordFiring).toHaveBeenCalledWith('trig', 1)
|
|
375
|
+
})
|
|
376
|
+
|
|
377
|
+
it('uses trigger.questionTemplate when present', async () => {
|
|
378
|
+
const custom: AdvisoryTrigger = {
|
|
379
|
+
...trigger,
|
|
380
|
+
questionTemplate: 'Custom question',
|
|
381
|
+
}
|
|
382
|
+
const { ctx: advCtx, mocks } = makeAdvisoryCtx({
|
|
383
|
+
firedTriggers: [custom],
|
|
384
|
+
advisor,
|
|
385
|
+
})
|
|
386
|
+
const { ctx } = makeCtx({ advisoryCtx: advCtx })
|
|
387
|
+
|
|
388
|
+
await runAdvisoryPhase(ctx, 7, response)
|
|
389
|
+
const consultArgs = mocks.consult.mock.calls[0] as unknown as [
|
|
390
|
+
unknown,
|
|
391
|
+
{ question: string },
|
|
392
|
+
unknown,
|
|
393
|
+
]
|
|
394
|
+
expect(consultArgs?.[1].question).toBe('Custom question')
|
|
395
|
+
})
|
|
396
|
+
|
|
397
|
+
it('falls back to the default "Iteration N: ..." question when no template', async () => {
|
|
398
|
+
const { ctx: advCtx, mocks } = makeAdvisoryCtx({
|
|
399
|
+
firedTriggers: [trigger],
|
|
400
|
+
advisor,
|
|
401
|
+
})
|
|
402
|
+
const { ctx } = makeCtx({ advisoryCtx: advCtx })
|
|
403
|
+
|
|
404
|
+
await runAdvisoryPhase(ctx, 7, response)
|
|
405
|
+
const consultArgs = mocks.consult.mock.calls[0] as unknown as [
|
|
406
|
+
unknown,
|
|
407
|
+
{ question: string },
|
|
408
|
+
unknown,
|
|
409
|
+
]
|
|
410
|
+
expect(consultArgs?.[1].question).toContain('Iteration 7')
|
|
411
|
+
})
|
|
412
|
+
})
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vitest `setupFiles` entry for `@namzu/sdk`.
|
|
3
|
+
*
|
|
4
|
+
* Silences the root logger for the entire test run. Tests that assert on
|
|
5
|
+
* log output use their own mocked Logger instances (constructed via the
|
|
6
|
+
* `makeLogger()` helpers colocated with each test) — those are not
|
|
7
|
+
* affected by the root-level silence.
|
|
8
|
+
*
|
|
9
|
+
* The only thing this suppresses is the stderr spam produced by
|
|
10
|
+
* production code paths that fall through to `getRootLogger()` — e.g.
|
|
11
|
+
* `ToolRegistry.execute`'s zod-validation and thrown-error branches,
|
|
12
|
+
* `ConnectorToolRouter.getTools`' per-instance error catch, the
|
|
13
|
+
* AgentBus listener-throw handler, and every connector's `connect()`
|
|
14
|
+
* info log. GitHub Actions annotates any `[ERROR]` stderr line as a
|
|
15
|
+
* workflow error; silencing the root logger during tests keeps the CI
|
|
16
|
+
* log clean.
|
|
17
|
+
*
|
|
18
|
+
* This is test-only configuration. It runs before every test file and
|
|
19
|
+
* does not affect consumers.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { configureLogger } from './utils/logger.js'
|
|
23
|
+
|
|
24
|
+
configureLogger({ level: 'silent' })
|
package/src/types/bus/index.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import type { RunId } from '../ids/index.js'
|
|
1
|
+
import type { CredentialId, LockId, RunId, SandboxId, TenantId } from '../ids/index.js'
|
|
2
2
|
|
|
3
|
-
export type LockId
|
|
3
|
+
export type { LockId } from '../ids/index.js'
|
|
4
|
+
|
|
5
|
+
export type ProviderCallId = `pcall_${string}`
|
|
4
6
|
|
|
5
7
|
export type CircuitBreakerState = 'closed' | 'open' | 'half_open'
|
|
6
8
|
|
|
@@ -35,6 +37,15 @@ export type OwnershipClaimResult =
|
|
|
35
37
|
| { claimed: true; ownership: FileOwnership }
|
|
36
38
|
| { claimed: false; currentOwner: RunId; filePath: string }
|
|
37
39
|
|
|
40
|
+
export interface ProviderCallUsage {
|
|
41
|
+
readonly inputTokens?: number
|
|
42
|
+
readonly outputTokens?: number
|
|
43
|
+
readonly totalTokens?: number
|
|
44
|
+
readonly costUsd?: number
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export type SandboxDecisionAction = 'allow' | 'deny'
|
|
48
|
+
|
|
38
49
|
export type AgentBusEvent =
|
|
39
50
|
| { type: 'lock_acquired'; lockId: LockId; filePath: string; owner: RunId }
|
|
40
51
|
| { type: 'lock_released'; lockId: LockId; filePath: string; owner: RunId }
|
|
@@ -49,5 +60,46 @@ export type AgentBusEvent =
|
|
|
49
60
|
| { type: 'breaker_half_open'; agentRunId: RunId }
|
|
50
61
|
| { type: 'breaker_probe_success'; agentRunId: RunId }
|
|
51
62
|
| { type: 'breaker_probe_failure'; agentRunId: RunId }
|
|
63
|
+
| {
|
|
64
|
+
type: 'provider_call_start'
|
|
65
|
+
providerId: string
|
|
66
|
+
model: string
|
|
67
|
+
callId: ProviderCallId
|
|
68
|
+
runId?: RunId
|
|
69
|
+
}
|
|
70
|
+
| {
|
|
71
|
+
type: 'provider_call_completed'
|
|
72
|
+
providerId: string
|
|
73
|
+
model: string
|
|
74
|
+
callId: ProviderCallId
|
|
75
|
+
runId?: RunId
|
|
76
|
+
durationMs: number
|
|
77
|
+
usage?: ProviderCallUsage
|
|
78
|
+
}
|
|
79
|
+
| {
|
|
80
|
+
type: 'provider_call_failed'
|
|
81
|
+
providerId: string
|
|
82
|
+
model: string
|
|
83
|
+
callId: ProviderCallId
|
|
84
|
+
runId?: RunId
|
|
85
|
+
durationMs: number
|
|
86
|
+
error: string
|
|
87
|
+
}
|
|
88
|
+
| {
|
|
89
|
+
type: 'vault_lookup'
|
|
90
|
+
vaultId: string
|
|
91
|
+
credentialId?: CredentialId
|
|
92
|
+
tenantId?: TenantId
|
|
93
|
+
found: boolean
|
|
94
|
+
runId?: RunId
|
|
95
|
+
}
|
|
96
|
+
| {
|
|
97
|
+
type: 'sandbox_decision'
|
|
98
|
+
sandboxId: SandboxId
|
|
99
|
+
action: SandboxDecisionAction
|
|
100
|
+
resource: string
|
|
101
|
+
ruleId?: string
|
|
102
|
+
runId?: RunId
|
|
103
|
+
}
|
|
52
104
|
|
|
53
105
|
export type AgentBusEventListener = (event: AgentBusEvent) => void
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export type DoctorStatus = 'pass' | 'fail' | 'inconclusive' | 'warn'
|
|
2
|
+
|
|
3
|
+
export type DoctorCategory =
|
|
4
|
+
| 'sandbox'
|
|
5
|
+
| 'providers'
|
|
6
|
+
| 'vault'
|
|
7
|
+
| 'telemetry'
|
|
8
|
+
| 'runtime'
|
|
9
|
+
| 'plugins'
|
|
10
|
+
| 'custom'
|
|
11
|
+
|
|
12
|
+
export interface DoctorCheckContext {
|
|
13
|
+
readonly cwd: string
|
|
14
|
+
readonly env: Readonly<Record<string, string | undefined>>
|
|
15
|
+
readonly projectRoot: string | null
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface DoctorCheckResult {
|
|
19
|
+
readonly status: DoctorStatus
|
|
20
|
+
readonly message?: string
|
|
21
|
+
readonly remediation?: string
|
|
22
|
+
readonly durationMs?: number
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface DoctorCheck {
|
|
26
|
+
readonly id: string
|
|
27
|
+
readonly category: DoctorCategory
|
|
28
|
+
readonly run: (ctx: DoctorCheckContext) => Promise<DoctorCheckResult>
|
|
29
|
+
readonly fix?: (ctx: DoctorCheckContext) => Promise<DoctorCheckResult>
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface DoctorCheckRecord {
|
|
33
|
+
readonly id: string
|
|
34
|
+
readonly category: DoctorCategory
|
|
35
|
+
readonly status: DoctorStatus
|
|
36
|
+
readonly message?: string
|
|
37
|
+
readonly remediation?: string
|
|
38
|
+
readonly durationMs: number
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface DoctorReport {
|
|
42
|
+
readonly version: string
|
|
43
|
+
readonly timestamp: string
|
|
44
|
+
readonly checks: readonly DoctorCheckRecord[]
|
|
45
|
+
readonly summary: {
|
|
46
|
+
readonly pass: number
|
|
47
|
+
readonly fail: number
|
|
48
|
+
readonly inconclusive: number
|
|
49
|
+
readonly warn: number
|
|
50
|
+
readonly total: number
|
|
51
|
+
}
|
|
52
|
+
readonly exit: 0 | 1 | 2 | 70
|
|
53
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AgentBusEvent } from '../bus/index.js'
|
|
2
|
+
import type { RunEvent } from '../run/events.js'
|
|
3
|
+
|
|
4
|
+
export type ProbeEventKind = RunEvent['type'] | AgentBusEvent['type']
|
|
5
|
+
|
|
6
|
+
export type VetoableEventKind = 'tool_executing'
|
|
7
|
+
|
|
8
|
+
export type ProbeEvent = RunEvent | AgentBusEvent
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type { ProbeEvent, ProbeEventKind, VetoableEventKind } from './event-kind.js'
|
|
2
|
+
export type { ProbeEventOf } from './event-of.js'
|
|
3
|
+
export type {
|
|
4
|
+
ProbeContext,
|
|
5
|
+
ProbeHandler,
|
|
6
|
+
ProbeOptions,
|
|
7
|
+
Unsubscribe,
|
|
8
|
+
VetoDecision,
|
|
9
|
+
VetoHandler,
|
|
10
|
+
VetoOutcome,
|
|
11
|
+
} from './registry.js'
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { RunId } from '../ids/index.js'
|
|
2
|
+
import type { ProbeEventKind, VetoableEventKind } from './event-kind.js'
|
|
3
|
+
import type { ProbeEventOf } from './event-of.js'
|
|
4
|
+
|
|
5
|
+
export type Unsubscribe = () => void
|
|
6
|
+
|
|
7
|
+
export interface ProbeContext {
|
|
8
|
+
readonly runId?: RunId
|
|
9
|
+
readonly isReplay: boolean
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type ProbeHandler<K extends ProbeEventKind> = (
|
|
13
|
+
event: ProbeEventOf<K>,
|
|
14
|
+
ctx: ProbeContext,
|
|
15
|
+
) => void
|
|
16
|
+
|
|
17
|
+
export type VetoDecision = 'allow' | 'deny' | { readonly action: 'deny'; readonly reason: string }
|
|
18
|
+
|
|
19
|
+
export type VetoHandler<K extends VetoableEventKind> = (
|
|
20
|
+
event: ProbeEventOf<K>,
|
|
21
|
+
ctx: ProbeContext,
|
|
22
|
+
) => VetoDecision
|
|
23
|
+
|
|
24
|
+
export interface VetoOutcome {
|
|
25
|
+
readonly action: 'allow' | 'deny'
|
|
26
|
+
readonly probeName?: string
|
|
27
|
+
readonly reason?: string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface ProbeOptions<K extends ProbeEventKind = ProbeEventKind> {
|
|
31
|
+
readonly where?: (event: ProbeEventOf<K>) => boolean
|
|
32
|
+
readonly priority?: number
|
|
33
|
+
readonly name?: string
|
|
34
|
+
readonly otel?: boolean
|
|
35
|
+
readonly override?: boolean
|
|
36
|
+
}
|
package/src/utils/logger.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type LogLevel = 'debug' | 'info' | 'warn' | 'error'
|
|
1
|
+
export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent'
|
|
2
2
|
|
|
3
3
|
export type LogContext = Record<string, unknown>
|
|
4
4
|
|
|
@@ -7,6 +7,11 @@ const LOG_LEVELS: Record<LogLevel, number> = {
|
|
|
7
7
|
info: 1,
|
|
8
8
|
warn: 2,
|
|
9
9
|
error: 3,
|
|
10
|
+
// `silent` sits above every emit level so the `level < minLevelNum`
|
|
11
|
+
// guard in `log()` always short-circuits when configured. Used by
|
|
12
|
+
// test harnesses to suppress unmocked `getRootLogger()` stderr
|
|
13
|
+
// writes; see packages/sdk/src/test-setup.ts.
|
|
14
|
+
silent: 4,
|
|
10
15
|
}
|
|
11
16
|
|
|
12
17
|
export interface Logger {
|