@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.
Files changed (79) hide show
  1. package/dist/events/catalogue.d.ts +319 -22
  2. package/dist/events/catalogue.d.ts.map +1 -1
  3. package/dist/events/catalogue.js +18 -0
  4. package/dist/events/catalogue.js.map +1 -1
  5. package/dist/events/index.d.ts +9 -0
  6. package/dist/events/index.d.ts.map +1 -1
  7. package/dist/events/index.js +9 -0
  8. package/dist/events/index.js.map +1 -1
  9. package/dist/events/schemas/citadel.sprint.analyzed.v1.d.ts +55 -0
  10. package/dist/events/schemas/citadel.sprint.analyzed.v1.d.ts.map +1 -0
  11. package/dist/events/schemas/citadel.sprint.analyzed.v1.js +22 -0
  12. package/dist/events/schemas/citadel.sprint.analyzed.v1.js.map +1 -0
  13. package/dist/events/schemas/forge.inbox.reply_classified.v1.d.ts +33 -0
  14. package/dist/events/schemas/forge.inbox.reply_classified.v1.d.ts.map +1 -0
  15. package/dist/events/schemas/forge.inbox.reply_classified.v1.js +15 -0
  16. package/dist/events/schemas/forge.inbox.reply_classified.v1.js.map +1 -0
  17. package/dist/events/schemas/vauban-finance.forecast.generated.v1.d.ts +21 -0
  18. package/dist/events/schemas/vauban-finance.forecast.generated.v1.d.ts.map +1 -0
  19. package/dist/events/schemas/vauban-finance.forecast.generated.v1.js +11 -0
  20. package/dist/events/schemas/vauban-finance.forecast.generated.v1.js.map +1 -0
  21. package/dist/events/schemas/vauban-finance.trade.executed.v1.d.ts +24 -0
  22. package/dist/events/schemas/vauban-finance.trade.executed.v1.d.ts.map +1 -0
  23. package/dist/events/schemas/vauban-finance.trade.executed.v1.js +12 -0
  24. package/dist/events/schemas/vauban-finance.trade.executed.v1.js.map +1 -0
  25. package/dist/events/schemas/vauban.goal.checked.v1.d.ts +21 -0
  26. package/dist/events/schemas/vauban.goal.checked.v1.d.ts.map +1 -0
  27. package/dist/events/schemas/vauban.goal.checked.v1.js +11 -0
  28. package/dist/events/schemas/vauban.goal.checked.v1.js.map +1 -0
  29. package/dist/events/schemas/vauban.rebalancing.checked.v1.d.ts +21 -0
  30. package/dist/events/schemas/vauban.rebalancing.checked.v1.d.ts.map +1 -0
  31. package/dist/events/schemas/vauban.rebalancing.checked.v1.js +11 -0
  32. package/dist/events/schemas/vauban.rebalancing.checked.v1.js.map +1 -0
  33. package/dist/events/schemas/vauban.tax.checked.v1.d.ts +21 -0
  34. package/dist/events/schemas/vauban.tax.checked.v1.d.ts.map +1 -0
  35. package/dist/events/schemas/vauban.tax.checked.v1.js +11 -0
  36. package/dist/events/schemas/vauban.tax.checked.v1.js.map +1 -0
  37. package/dist/events/schemas/vauban.vault.analyzed.v1.d.ts +59 -0
  38. package/dist/events/schemas/vauban.vault.analyzed.v1.d.ts.map +1 -0
  39. package/dist/events/schemas/vauban.vault.analyzed.v1.js +19 -0
  40. package/dist/events/schemas/vauban.vault.analyzed.v1.js.map +1 -0
  41. package/dist/events/schemas/vauban.vault.compounded.v1.d.ts +24 -0
  42. package/dist/events/schemas/vauban.vault.compounded.v1.d.ts.map +1 -0
  43. package/dist/events/schemas/vauban.vault.compounded.v1.js +12 -0
  44. package/dist/events/schemas/vauban.vault.compounded.v1.js.map +1 -0
  45. package/dist/loop/index.d.ts +1 -1
  46. package/dist/loop/index.d.ts.map +1 -1
  47. package/dist/loop/index.js.map +1 -1
  48. package/dist/loop/sdk-loop.d.ts +1 -3
  49. package/dist/loop/sdk-loop.d.ts.map +1 -1
  50. package/dist/loop/sdk-loop.js +1 -1
  51. package/dist/loop/sdk-loop.js.map +1 -1
  52. package/dist/orchestration/ooda/run-step-persistence.d.ts.map +1 -1
  53. package/dist/orchestration/ooda/run-step-persistence.js +17 -1
  54. package/dist/orchestration/ooda/run-step-persistence.js.map +1 -1
  55. package/dist/orchestration/ooda/types.d.ts +3 -8
  56. package/dist/orchestration/ooda/types.d.ts.map +1 -1
  57. package/dist/ports/event-bus.d.ts +0 -13
  58. package/dist/ports/event-bus.d.ts.map +1 -1
  59. package/dist/testing/contracts/event-bus.contract.d.ts.map +1 -1
  60. package/dist/testing/contracts/event-bus.contract.js +14 -12
  61. package/dist/testing/contracts/event-bus.contract.js.map +1 -1
  62. package/package.json +22 -18
  63. package/src/events/catalogue.ts +54 -0
  64. package/src/events/index.ts +9 -0
  65. package/src/events/schemas/citadel.sprint.analyzed.v1.ts +23 -0
  66. package/src/events/schemas/forge.inbox.reply_classified.v1.ts +15 -0
  67. package/src/events/schemas/vauban-finance.forecast.generated.v1.ts +11 -0
  68. package/src/events/schemas/vauban-finance.trade.executed.v1.ts +12 -0
  69. package/src/events/schemas/vauban.goal.checked.v1.ts +11 -0
  70. package/src/events/schemas/vauban.rebalancing.checked.v1.ts +11 -0
  71. package/src/events/schemas/vauban.tax.checked.v1.ts +11 -0
  72. package/src/events/schemas/vauban.vault.analyzed.v1.ts +21 -0
  73. package/src/events/schemas/vauban.vault.compounded.v1.ts +12 -0
  74. package/src/loop/index.ts +0 -1
  75. package/src/loop/sdk-loop.ts +5 -8
  76. package/src/orchestration/ooda/run-step-persistence.ts +20 -1
  77. package/src/orchestration/ooda/types.ts +3 -9
  78. package/src/ports/event-bus.ts +0 -18
  79. package/src/testing/contracts/event-bus.contract.ts +16 -14
@@ -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 : (JSON.stringify(v) ?? "null");
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
- * Optional in SDK 0.17 for backward compatibility.
254
- * Will be required in SDK 1.0.
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
- // Will be required in 1.0
262
- readonly deps?: OODAAgentDeps;
256
+ readonly deps: OODAAgentDeps;
263
257
 
264
258
  readonly phases: {
265
259
  readonly observe: PhaseDef<void, TObs>;
@@ -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 an event", async () => {
52
+ it("publishes and consumes a domain event", async () => {
53
53
  const received: unknown[] = [];
54
- const unsub = await port.subscribe(
55
- testStream,
56
- testGroup,
54
+ const sub = port.subscribeDomain<{ message: string }>(
55
+ "tech.vauban.test.event",
57
56
  async (event) => {
58
- received.push(event.data);
59
- }
57
+ received.push(event.payload);
58
+ },
59
+ { groupId: testGroup }
60
60
  );
61
61
 
62
- await port.publish(
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
- time: new Date().toISOString(),
69
- data: { message: "hello" },
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
- testStream
73
+ testKey
72
74
  );
73
75
 
74
76
  // Allow async delivery
75
77
  await new Promise((r) => setTimeout(r, 100));
76
- await unsub();
78
+ await sub.unsubscribe();
77
79
 
78
80
  expect(received.length).toBeGreaterThanOrEqual(1);
79
81
  });