@vauban-org/agent-sdk 0.17.3 → 1.0.0
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/events/catalogue.d.ts +319 -22
- package/dist/events/catalogue.d.ts.map +1 -1
- package/dist/events/catalogue.js +18 -0
- package/dist/events/catalogue.js.map +1 -1
- package/dist/events/index.d.ts +9 -0
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +9 -0
- package/dist/events/index.js.map +1 -1
- package/dist/events/schemas/citadel.sprint.analyzed.v1.d.ts +55 -0
- package/dist/events/schemas/citadel.sprint.analyzed.v1.d.ts.map +1 -0
- package/dist/events/schemas/citadel.sprint.analyzed.v1.js +22 -0
- package/dist/events/schemas/citadel.sprint.analyzed.v1.js.map +1 -0
- package/dist/events/schemas/forge.inbox.reply_classified.v1.d.ts +33 -0
- package/dist/events/schemas/forge.inbox.reply_classified.v1.d.ts.map +1 -0
- package/dist/events/schemas/forge.inbox.reply_classified.v1.js +15 -0
- package/dist/events/schemas/forge.inbox.reply_classified.v1.js.map +1 -0
- package/dist/events/schemas/vauban-finance.forecast.generated.v1.d.ts +21 -0
- package/dist/events/schemas/vauban-finance.forecast.generated.v1.d.ts.map +1 -0
- package/dist/events/schemas/vauban-finance.forecast.generated.v1.js +11 -0
- package/dist/events/schemas/vauban-finance.forecast.generated.v1.js.map +1 -0
- package/dist/events/schemas/vauban-finance.trade.executed.v1.d.ts +24 -0
- package/dist/events/schemas/vauban-finance.trade.executed.v1.d.ts.map +1 -0
- package/dist/events/schemas/vauban-finance.trade.executed.v1.js +12 -0
- package/dist/events/schemas/vauban-finance.trade.executed.v1.js.map +1 -0
- package/dist/events/schemas/vauban.goal.checked.v1.d.ts +21 -0
- package/dist/events/schemas/vauban.goal.checked.v1.d.ts.map +1 -0
- package/dist/events/schemas/vauban.goal.checked.v1.js +11 -0
- package/dist/events/schemas/vauban.goal.checked.v1.js.map +1 -0
- package/dist/events/schemas/vauban.rebalancing.checked.v1.d.ts +21 -0
- package/dist/events/schemas/vauban.rebalancing.checked.v1.d.ts.map +1 -0
- package/dist/events/schemas/vauban.rebalancing.checked.v1.js +11 -0
- package/dist/events/schemas/vauban.rebalancing.checked.v1.js.map +1 -0
- package/dist/events/schemas/vauban.tax.checked.v1.d.ts +21 -0
- package/dist/events/schemas/vauban.tax.checked.v1.d.ts.map +1 -0
- package/dist/events/schemas/vauban.tax.checked.v1.js +11 -0
- package/dist/events/schemas/vauban.tax.checked.v1.js.map +1 -0
- package/dist/events/schemas/vauban.vault.analyzed.v1.d.ts +59 -0
- package/dist/events/schemas/vauban.vault.analyzed.v1.d.ts.map +1 -0
- package/dist/events/schemas/vauban.vault.analyzed.v1.js +19 -0
- package/dist/events/schemas/vauban.vault.analyzed.v1.js.map +1 -0
- package/dist/events/schemas/vauban.vault.compounded.v1.d.ts +24 -0
- package/dist/events/schemas/vauban.vault.compounded.v1.d.ts.map +1 -0
- package/dist/events/schemas/vauban.vault.compounded.v1.js +12 -0
- package/dist/events/schemas/vauban.vault.compounded.v1.js.map +1 -0
- package/dist/loop/index.d.ts +1 -1
- package/dist/loop/index.d.ts.map +1 -1
- package/dist/loop/index.js.map +1 -1
- package/dist/loop/sdk-loop.d.ts +1 -3
- package/dist/loop/sdk-loop.d.ts.map +1 -1
- package/dist/loop/sdk-loop.js +1 -1
- package/dist/loop/sdk-loop.js.map +1 -1
- package/dist/orchestration/ooda/run-step-persistence.d.ts.map +1 -1
- package/dist/orchestration/ooda/run-step-persistence.js +17 -1
- package/dist/orchestration/ooda/run-step-persistence.js.map +1 -1
- package/dist/orchestration/ooda/types.d.ts +3 -8
- package/dist/orchestration/ooda/types.d.ts.map +1 -1
- package/dist/ports/event-bus.d.ts +0 -13
- package/dist/ports/event-bus.d.ts.map +1 -1
- package/dist/testing/contracts/event-bus.contract.d.ts.map +1 -1
- package/dist/testing/contracts/event-bus.contract.js +14 -12
- package/dist/testing/contracts/event-bus.contract.js.map +1 -1
- package/package.json +22 -18
- package/src/events/catalogue.ts +54 -0
- package/src/events/index.ts +9 -0
- package/src/events/schemas/citadel.sprint.analyzed.v1.ts +23 -0
- package/src/events/schemas/forge.inbox.reply_classified.v1.ts +15 -0
- package/src/events/schemas/vauban-finance.forecast.generated.v1.ts +11 -0
- package/src/events/schemas/vauban-finance.trade.executed.v1.ts +12 -0
- package/src/events/schemas/vauban.goal.checked.v1.ts +11 -0
- package/src/events/schemas/vauban.rebalancing.checked.v1.ts +11 -0
- package/src/events/schemas/vauban.tax.checked.v1.ts +11 -0
- package/src/events/schemas/vauban.vault.analyzed.v1.ts +21 -0
- package/src/events/schemas/vauban.vault.compounded.v1.ts +12 -0
- package/src/loop/index.ts +0 -1
- package/src/loop/sdk-loop.ts +5 -8
- package/src/orchestration/ooda/run-step-persistence.ts +20 -1
- package/src/orchestration/ooda/types.ts +3 -9
- package/src/ports/event-bus.ts +0 -18
- package/src/testing/contracts/event-bus.contract.ts +16 -14
package/src/loop/sdk-loop.ts
CHANGED
|
@@ -45,9 +45,6 @@ import type { RenewalManager } from "../permissions/renewal-manager.js";
|
|
|
45
45
|
import type { AgentTool, ToolRegistry } from "../tools/types.js";
|
|
46
46
|
|
|
47
47
|
export type SdkToolRegistry = ToolRegistry;
|
|
48
|
-
/** @deprecated Use AgentTool from "@vauban-org/agent-sdk" directly. */
|
|
49
|
-
export type SdkToolEntry = AgentTool;
|
|
50
|
-
|
|
51
48
|
// ─── Capability annotation on tools ────────────────────────────────────────
|
|
52
49
|
|
|
53
50
|
export interface AgentToolCapabilityMarker {
|
|
@@ -252,7 +249,7 @@ class SdkAgentLoopImpl {
|
|
|
252
249
|
}
|
|
253
250
|
|
|
254
251
|
const toolUses = response.content.filter(
|
|
255
|
-
(b): b is Anthropic.Messages.ToolUseBlock => b.type === "tool_use"
|
|
252
|
+
(b): b is Anthropic.Messages.ToolUseBlock => b.type === "tool_use"
|
|
256
253
|
);
|
|
257
254
|
|
|
258
255
|
if (toolUses.length === 0) {
|
|
@@ -362,7 +359,7 @@ class SdkAgentLoopImpl {
|
|
|
362
359
|
|
|
363
360
|
private async authoriseCall(
|
|
364
361
|
call: Anthropic.Messages.ToolUseBlock,
|
|
365
|
-
budgetUsedUsd: number
|
|
362
|
+
budgetUsedUsd: number
|
|
366
363
|
): Promise<"allow" | "deny" | "capability_denied" | "cancelled"> {
|
|
367
364
|
const tool = this.config.tools.get(call.name);
|
|
368
365
|
if (!tool) return "deny";
|
|
@@ -414,7 +411,7 @@ class SdkAgentLoopImpl {
|
|
|
414
411
|
|
|
415
412
|
private async awaitApproval(
|
|
416
413
|
tool: AgentTool,
|
|
417
|
-
args: unknown
|
|
414
|
+
args: unknown
|
|
418
415
|
): Promise<boolean> {
|
|
419
416
|
const channel = this.config.approvalChannel;
|
|
420
417
|
if (!channel) return false;
|
|
@@ -480,7 +477,7 @@ function cryptoRandomId(): string {
|
|
|
480
477
|
}
|
|
481
478
|
|
|
482
479
|
function extractText(
|
|
483
|
-
content: readonly Anthropic.Messages.ContentBlock[]
|
|
480
|
+
content: readonly Anthropic.Messages.ContentBlock[]
|
|
484
481
|
): string {
|
|
485
482
|
return content
|
|
486
483
|
.filter((b): b is Anthropic.Messages.TextBlock => b.type === "text")
|
|
@@ -490,7 +487,7 @@ function extractText(
|
|
|
490
487
|
|
|
491
488
|
function safeStringify(v: unknown): string {
|
|
492
489
|
try {
|
|
493
|
-
return typeof v === "string" ? v :
|
|
490
|
+
return typeof v === "string" ? v : JSON.stringify(v) ?? "null";
|
|
494
491
|
} catch {
|
|
495
492
|
return "[unserialisable]";
|
|
496
493
|
}
|
|
@@ -15,10 +15,28 @@
|
|
|
15
15
|
* @public
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import { computeLeafHash } from "@vauban-org/proof-core";
|
|
19
18
|
import type { DbClient } from "../../tracking/agent-run-tracker.js";
|
|
20
19
|
import type { OODAPhaseKind } from "./types.js";
|
|
21
20
|
|
|
21
|
+
// Lazy singleton — proof-core is an optional peerDep; SHA-256 fallback when absent
|
|
22
|
+
type LeafHashFn = (payload: Record<string, unknown>) => string;
|
|
23
|
+
let _computeLeafHash: LeafHashFn | null = null;
|
|
24
|
+
|
|
25
|
+
async function getComputeLeafHash(): Promise<LeafHashFn> {
|
|
26
|
+
if (_computeLeafHash !== null) return _computeLeafHash;
|
|
27
|
+
try {
|
|
28
|
+
const mod = await import("@vauban-org/proof-core") as { computeLeafHash: LeafHashFn };
|
|
29
|
+
_computeLeafHash = mod.computeLeafHash;
|
|
30
|
+
} catch {
|
|
31
|
+
// proof-core not installed (optional peer) — fall back to sync node:crypto SHA-256
|
|
32
|
+
const { createHash } = await import("node:crypto");
|
|
33
|
+
_computeLeafHash = (payload) =>
|
|
34
|
+
createHash("sha256").update(JSON.stringify(payload)).digest("hex");
|
|
35
|
+
}
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
37
|
+
return _computeLeafHash!;
|
|
38
|
+
}
|
|
39
|
+
|
|
22
40
|
export interface InsertRunStepInput {
|
|
23
41
|
type: OODAPhaseKind;
|
|
24
42
|
/** Human-readable phase tag (e.g. "observe", "orient", "decide", "act"). */
|
|
@@ -97,6 +115,7 @@ export async function completeRunStep(
|
|
|
97
115
|
throw new Error("[ooda] completeRunStep: payload must be a plain object");
|
|
98
116
|
}
|
|
99
117
|
|
|
118
|
+
const computeLeafHash = await getComputeLeafHash();
|
|
100
119
|
const leafHash = computeLeafHash(payload);
|
|
101
120
|
|
|
102
121
|
await db.query(
|
|
@@ -250,16 +250,10 @@ export interface OODAAgentConfig<
|
|
|
250
250
|
/**
|
|
251
251
|
* Port dependencies injected at boot (BYOM — plan v6 §3.7).
|
|
252
252
|
*
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
*
|
|
256
|
-
* When `SDK_STRICT_DEPS !== "false"` (default), boot validation throws
|
|
257
|
-
* `MissingDependencyError` if this field is absent or `deps.llm` is missing.
|
|
258
|
-
*
|
|
259
|
-
* @deprecated Omitting `deps` is supported only in legacy mode. Will be required in 1.0.
|
|
253
|
+
* Required since SDK 1.0. Boot validation throws `MissingDependencyError`
|
|
254
|
+
* if this field is absent or `deps.llm` is missing.
|
|
260
255
|
*/
|
|
261
|
-
|
|
262
|
-
readonly deps?: OODAAgentDeps;
|
|
256
|
+
readonly deps: OODAAgentDeps;
|
|
263
257
|
|
|
264
258
|
readonly phases: {
|
|
265
259
|
readonly observe: PhaseDef<void, TObs>;
|
package/src/ports/event-bus.ts
CHANGED
|
@@ -136,24 +136,6 @@ export interface EventBusPort {
|
|
|
136
136
|
key: string
|
|
137
137
|
): Promise<void>;
|
|
138
138
|
|
|
139
|
-
/**
|
|
140
|
-
* Subscribe to a stream with a consumer group.
|
|
141
|
-
*
|
|
142
|
-
* Returns an unsubscribe function. The handler receives each event after
|
|
143
|
-
* dedup (based on `event.id`). Implementation MUST:
|
|
144
|
-
* 1. Create consumer group if it doesn't exist (XGROUP CREATE).
|
|
145
|
-
* 2. XREADGROUP → handler → XACK.
|
|
146
|
-
* 3. On 3 consecutive XAUTOCLAIM failures → XADD to DLQ stream.
|
|
147
|
-
* 4. Extract `traceparent` and set as parent span context.
|
|
148
|
-
*
|
|
149
|
-
* @deprecated Prefer the overload returning Subscription for CloudEvent streams.
|
|
150
|
-
*/
|
|
151
|
-
subscribe(
|
|
152
|
-
stream: string,
|
|
153
|
-
consumerGroup: string,
|
|
154
|
-
handler: (event: CloudEvent) => Promise<void>
|
|
155
|
-
): Promise<() => void>;
|
|
156
|
-
|
|
157
139
|
/**
|
|
158
140
|
* Subscribe to DomainEvents of a specific type.
|
|
159
141
|
*
|
|
@@ -49,31 +49,33 @@ export function eventBusContract(
|
|
|
49
49
|
const testStream = "vauban.test.contract";
|
|
50
50
|
const testGroup = "test-consumer-group";
|
|
51
51
|
|
|
52
|
-
it("publishes and consumes
|
|
52
|
+
it("publishes and consumes a domain event", async () => {
|
|
53
53
|
const received: unknown[] = [];
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
testGroup,
|
|
54
|
+
const sub = port.subscribeDomain<{ message: string }>(
|
|
55
|
+
"tech.vauban.test.event",
|
|
57
56
|
async (event) => {
|
|
58
|
-
received.push(event.
|
|
59
|
-
}
|
|
57
|
+
received.push(event.payload);
|
|
58
|
+
},
|
|
59
|
+
{ groupId: testGroup }
|
|
60
60
|
);
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
const testKey = "test-hmac-key-32-bytes-minimum!!";
|
|
63
|
+
await port.publishWithIdempotency<{ message: string }>(
|
|
63
64
|
{
|
|
64
|
-
id: "test-event-1",
|
|
65
|
-
specversion: "1.0",
|
|
66
|
-
source: "test",
|
|
67
65
|
type: "tech.vauban.test.event",
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
source: "cc" as const,
|
|
67
|
+
correlationId: "contract-test-corr-1",
|
|
68
|
+
idempotencyKey: "contract-test-1",
|
|
69
|
+
timestamp: new Date().toISOString(),
|
|
70
|
+
schemaVersion: "1.0.0",
|
|
71
|
+
payload: { message: "hello" },
|
|
70
72
|
},
|
|
71
|
-
|
|
73
|
+
testKey
|
|
72
74
|
);
|
|
73
75
|
|
|
74
76
|
// Allow async delivery
|
|
75
77
|
await new Promise((r) => setTimeout(r, 100));
|
|
76
|
-
await
|
|
78
|
+
await sub.unsubscribe();
|
|
77
79
|
|
|
78
80
|
expect(received.length).toBeGreaterThanOrEqual(1);
|
|
79
81
|
});
|