@agentium/harness 4.1.0 → 4.6.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 (49) hide show
  1. package/CONVERSATIONAL-RUNS.md +173 -0
  2. package/README.md +13 -5
  3. package/dist/definition.d.cts +39 -0
  4. package/dist/{driver-Cr2BGG4h.cjs → driver-Bh_wLWCP.cjs} +285 -15
  5. package/dist/{driver-BvzvqvpB.js → driver-reTLBJ_o.js} +280 -16
  6. package/dist/drivers.d.cts +14 -0
  7. package/dist/drivers.d.ts.map +1 -1
  8. package/dist/index.cjs +103 -46
  9. package/dist/index.d.cts +19 -0
  10. package/dist/index.d.ts +4 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +103 -48
  13. package/dist/input-tool.d.cts +7 -0
  14. package/dist/input-tool.d.ts +7 -0
  15. package/dist/input-tool.d.ts.map +1 -0
  16. package/dist/mcp-resources.d.cts +42 -0
  17. package/dist/policies.d.cts +31 -0
  18. package/dist/policies.d.ts +2 -0
  19. package/dist/policies.d.ts.map +1 -1
  20. package/dist/presets.d.cts +41 -0
  21. package/dist/runtime/context-policy.d.cts +21 -0
  22. package/dist/runtime/context-policy.d.ts +1 -0
  23. package/dist/runtime/context-policy.d.ts.map +1 -1
  24. package/dist/runtime/context.d.cts +15 -0
  25. package/dist/runtime/controller.d.cts +51 -0
  26. package/dist/runtime/driver.d.cts +157 -0
  27. package/dist/runtime/driver.d.ts +14 -3
  28. package/dist/runtime/driver.d.ts.map +1 -1
  29. package/dist/runtime/events.d.cts +116 -0
  30. package/dist/runtime/events.d.ts +35 -2
  31. package/dist/runtime/events.d.ts.map +1 -1
  32. package/dist/runtime/index.d.cts +9 -0
  33. package/dist/runtime/input.d.cts +46 -0
  34. package/dist/runtime/input.d.ts +46 -0
  35. package/dist/runtime/input.d.ts.map +1 -0
  36. package/dist/runtime/middleware.d.cts +10 -0
  37. package/dist/runtime/resolve.d.cts +20 -0
  38. package/dist/runtime/runtime-registry.d.cts +35 -0
  39. package/dist/runtime/session-bindings.d.cts +60 -0
  40. package/dist/runtime/types.d.cts +176 -0
  41. package/dist/testing.cjs +1 -1
  42. package/dist/testing.d.cts +7 -0
  43. package/dist/testing.js +1 -1
  44. package/dist/watch/definition.d.cts +11 -0
  45. package/dist/watch/gmail.d.cts +104 -0
  46. package/dist/watch/quiet-hours.d.cts +10 -0
  47. package/dist/watch/runtime.d.cts +42 -0
  48. package/dist/watch/types.d.cts +147 -0
  49. package/package.json +21 -10
@@ -0,0 +1,35 @@
1
+ import type { ContextPolicy } from "./context-policy.cjs";
2
+ import type { CompletionPolicy, StepController } from "./controller.cjs";
3
+ import type { ExecutionDriver } from "./driver.cjs";
4
+ import type { HarnessDefinition } from "./types.cjs";
5
+ export interface HarnessRegistryReference {
6
+ id: string;
7
+ version: number;
8
+ }
9
+ export interface HarnessRuntimeReferences {
10
+ driver?: HarnessRegistryReference;
11
+ controller?: HarnessRegistryReference;
12
+ contextPolicy?: HarnessRegistryReference;
13
+ completionPolicy?: HarnessRegistryReference;
14
+ /** Role -> approved host binding name; credentials/providers stay host-owned. */
15
+ modelRoles?: Readonly<Record<string, string>>;
16
+ }
17
+ export interface HarnessRuntimeBindings {
18
+ driver?: ExecutionDriver;
19
+ controller?: StepController;
20
+ contextPolicy?: ContextPolicy;
21
+ completionPolicy?: CompletionPolicy;
22
+ modelRoles?: Readonly<Record<string, string>>;
23
+ }
24
+ export interface HarnessRegistryEntry<T> extends HarnessRegistryReference {
25
+ implementation: T;
26
+ }
27
+ export interface HarnessRuntimeRegistry {
28
+ driver?: readonly HarnessRegistryEntry<ExecutionDriver>[];
29
+ controller?: readonly HarnessRegistryEntry<StepController>[];
30
+ contextPolicy?: readonly HarnessRegistryEntry<ContextPolicy>[];
31
+ completionPolicy?: readonly HarnessRegistryEntry<CompletionPolicy>[];
32
+ }
33
+ /** Registry resolution is static; it never initializes providers or executes drivers. */
34
+ export declare function resolveHarnessRuntime(definition: HarnessDefinition): HarnessRuntimeBindings;
35
+ //# sourceMappingURL=runtime-registry.d.ts.map
@@ -0,0 +1,60 @@
1
+ import type { ChatMessage } from "@agentium/core";
2
+ export interface HarnessIdentity {
3
+ userId: string;
4
+ tenantId: string;
5
+ }
6
+ export interface HarnessSessionSnapshot {
7
+ conversations?: Record<string, ChatMessage[]>;
8
+ history: ChatMessage[];
9
+ state: Record<string, unknown>;
10
+ revision: number;
11
+ replayable: boolean;
12
+ }
13
+ export interface HarnessSessionLease {
14
+ read(): HarnessSessionSnapshot;
15
+ commit(snapshot: Omit<HarnessSessionSnapshot, "revision">): void;
16
+ release(): void;
17
+ }
18
+ export declare class HarnessSessionConflict extends Error {
19
+ readonly code = "session_conflict";
20
+ constructor();
21
+ }
22
+ export interface HarnessSessionStore {
23
+ readonly guarantees: {
24
+ durable: boolean;
25
+ compareAndSwap: boolean;
26
+ singleWriter: "process" | "distributed";
27
+ };
28
+ acquire(identity: HarnessIdentity, sessionId: string): Promise<HarnessSessionLease>;
29
+ }
30
+ export declare function harnessSessionKey(identity: HarnessIdentity, sessionId: string): string;
31
+ /** One writer per scoped session; deliberately rejects rather than silently interleaving. */
32
+ export declare class InMemoryHarnessSessionStore implements HarnessSessionStore {
33
+ readonly guarantees: {
34
+ durable: boolean;
35
+ compareAndSwap: boolean;
36
+ singleWriter: "process";
37
+ };
38
+ private records;
39
+ private active;
40
+ acquire(identity: HarnessIdentity, sessionId: string): Promise<HarnessSessionLease>;
41
+ /** Imported display-only transcripts are readable but never represented as complete replay state. */
42
+ importLegacy(identity: HarnessIdentity, sessionId: string, history: ChatMessage[]): void;
43
+ }
44
+ export interface ScopedResource<T = unknown> {
45
+ value: T;
46
+ ownership: "host" | "runtime";
47
+ dispose?: () => Promise<void>;
48
+ }
49
+ export interface SessionResourceLease<T> {
50
+ value: T;
51
+ release: () => Promise<void>;
52
+ }
53
+ /** Session resources live until explicit closeSession; run resources use their returned lease. */
54
+ export declare class HarnessResourcePool {
55
+ private sessions;
56
+ private pending;
57
+ acquire<T>(identity: HarnessIdentity, sessionId: string, id: string, scope: "host" | "session" | "run", initialize: () => Promise<ScopedResource<T>>): Promise<SessionResourceLease<T>>;
58
+ closeSession(identity: HarnessIdentity, sessionId: string): Promise<readonly string[]>;
59
+ }
60
+ //# sourceMappingURL=session-bindings.d.ts.map
@@ -0,0 +1,176 @@
1
+ import type { ChatMessage, ModelResponse, RunContext, ToolCallResult, ToolDef } from "@agentium/core";
2
+ import type { HarnessRuntimeBindings, HarnessRuntimeReferences, HarnessRuntimeRegistry } from "./runtime-registry.cjs";
3
+ export type JsonValue = null | boolean | number | string | JsonValue[] | {
4
+ [key: string]: JsonValue;
5
+ };
6
+ export type JsonObject = {
7
+ [key: string]: JsonValue;
8
+ };
9
+ export interface AbilitySelection {
10
+ instanceId: string;
11
+ type: string;
12
+ version: number;
13
+ options: JsonObject;
14
+ }
15
+ export interface HarnessDefaults {
16
+ workspace?: false | {
17
+ path: string;
18
+ mode: "read" | "write";
19
+ };
20
+ skillDirs?: readonly string[] | false;
21
+ contextFiles?: boolean;
22
+ filesystem?: boolean;
23
+ subagents?: boolean;
24
+ fileMemory?: boolean;
25
+ searchPastSessions?: boolean;
26
+ }
27
+ export interface HarnessManifest {
28
+ contractVersion: 1;
29
+ runtime?: HarnessRuntimeReferences;
30
+ id: string;
31
+ abilities: readonly AbilitySelection[];
32
+ defaults?: HarnessDefaults;
33
+ limits?: {
34
+ toolRoundtrips?: number;
35
+ maxChildDepth?: number;
36
+ };
37
+ }
38
+ export interface PromptFragment {
39
+ id: string;
40
+ text: string;
41
+ }
42
+ export interface HarnessContextBudget {
43
+ maxEntries: number;
44
+ maxBytes: number;
45
+ maxTokens?: number;
46
+ deadlineMs: number;
47
+ }
48
+ export interface HarnessContextEntry {
49
+ id: string;
50
+ text: string;
51
+ trust: "host" | "source";
52
+ source?: {
53
+ uri: string;
54
+ version?: string;
55
+ locator?: string;
56
+ };
57
+ expiresAt?: number;
58
+ estimatedTokens?: number;
59
+ byteLength: number;
60
+ }
61
+ export interface HarnessContextSource {
62
+ id: string;
63
+ fetch: (query: string, ctx: RunContext, budget: HarnessContextBudget) => Promise<readonly HarnessContextEntry[]>;
64
+ }
65
+ export interface HarnessMiddleware {
66
+ id: string;
67
+ before?: readonly string[];
68
+ after?: readonly string[];
69
+ beforeModel?: (messages: readonly ChatMessage[], ctx: RunContext) => Promise<ChatMessage[]>;
70
+ afterModel?: (response: ModelResponse, ctx: RunContext) => Promise<void>;
71
+ afterTool?: (result: ToolCallResult, ctx: RunContext) => Promise<void>;
72
+ }
73
+ export interface AbilityBinding {
74
+ tools: readonly ToolDef[];
75
+ promptFragments?: readonly PromptFragment[];
76
+ contextSources?: readonly HarnessContextSource[];
77
+ middleware?: readonly HarnessMiddleware[];
78
+ dispose?: () => Promise<void>;
79
+ }
80
+ export interface AbilityDescription {
81
+ toolNames: readonly string[];
82
+ requirements: readonly string[];
83
+ runtimeDependent?: boolean;
84
+ }
85
+ export interface AbilityFactory {
86
+ type: string;
87
+ version: number;
88
+ validateOptions: (input: JsonObject) => JsonObject;
89
+ describe: (options: JsonObject) => AbilityDescription;
90
+ bind: (options: JsonObject, ctx: RunContext) => Promise<AbilityBinding>;
91
+ }
92
+ export interface LocalAbilityUse {
93
+ instanceId: string;
94
+ validate: () => void;
95
+ describe: () => AbilityDescription;
96
+ bind: (ctx: RunContext) => Promise<AbilityBinding>;
97
+ portable?: AbilitySelection;
98
+ /** Trusted factory approved by the creator/host, never recovered from JSON. */
99
+ factory?: AbilityFactory;
100
+ }
101
+ export type HarnessDefinition = {
102
+ readonly kind: "portable";
103
+ readonly manifest: HarnessManifest;
104
+ readonly factories: readonly AbilityFactory[];
105
+ readonly runtimeRegistry?: HarnessRuntimeRegistry;
106
+ } | {
107
+ readonly kind: "local";
108
+ readonly id?: string;
109
+ readonly abilities: readonly LocalAbilityUse[];
110
+ readonly defaults?: HarnessDefaults;
111
+ readonly limits?: HarnessManifest["limits"];
112
+ readonly runtime?: HarnessRuntimeBindings;
113
+ readonly runtimeReferences?: HarnessRuntimeReferences;
114
+ readonly runtimeRegistry?: HarnessRuntimeRegistry;
115
+ };
116
+ export type HarnessDefinitionInput = HarnessDefinition | {
117
+ id?: string;
118
+ abilities?: readonly LocalAbilityUse[];
119
+ defaults?: HarnessDefaults;
120
+ limits?: HarnessManifest["limits"];
121
+ runtime?: HarnessRuntimeBindings;
122
+ runtimeReferences?: HarnessRuntimeReferences;
123
+ runtimeRegistry?: HarnessRuntimeRegistry;
124
+ };
125
+ export interface HarnessExtension {
126
+ runtime?: HarnessRuntimeBindings;
127
+ runtimeReferences?: HarnessRuntimeReferences;
128
+ runtimeRegistry?: HarnessRuntimeRegistry;
129
+ id?: string;
130
+ abilities?: readonly LocalAbilityUse[];
131
+ disable?: readonly string[];
132
+ replaceAbilities?: readonly LocalAbilityUse[];
133
+ defaults?: HarnessDefaults;
134
+ limits?: HarnessManifest["limits"];
135
+ }
136
+ export interface HarnessDiagnostic {
137
+ code: string;
138
+ path: string;
139
+ message: string;
140
+ severity: "info" | "warning" | "error";
141
+ }
142
+ export interface HarnessDescription {
143
+ id: string;
144
+ kind: "portable" | "local";
145
+ contractVersion: 1;
146
+ abilities: readonly (AbilityDescription & {
147
+ instanceId: string;
148
+ type?: string;
149
+ version?: number;
150
+ })[];
151
+ toolNames: readonly string[];
152
+ requirements: readonly string[];
153
+ runtimeDependent: boolean;
154
+ defaults: HarnessDefaults;
155
+ limits: NonNullable<HarnessManifest["limits"]>;
156
+ diagnostics: readonly HarnessDiagnostic[];
157
+ }
158
+ export interface HarnessProvenance {
159
+ path: string;
160
+ origin: string;
161
+ }
162
+ export interface ResolvedHarness {
163
+ readonly definition: HarnessDefinition;
164
+ readonly defaults: HarnessDefaults;
165
+ readonly limits: NonNullable<HarnessManifest["limits"]>;
166
+ readonly description: HarnessDescription;
167
+ readonly provenance: readonly HarnessProvenance[];
168
+ }
169
+ export interface BoundHarness {
170
+ readonly tools: ToolDef[];
171
+ readonly promptFragments: PromptFragment[];
172
+ readonly contextSources: HarnessContextSource[];
173
+ readonly middleware: HarnessMiddleware[];
174
+ dispose: () => Promise<readonly HarnessDiagnostic[]>;
175
+ }
176
+ //# sourceMappingURL=types.d.ts.map
package/dist/testing.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_driver = require("./driver-Cr2BGG4h.cjs");
2
+ const require_driver = require("./driver-Bh_wLWCP.cjs");
3
3
  let node_crypto = require("node:crypto");
4
4
  //#region src/testing.ts
5
5
  /** No test-framework dependency. Calls the driver once and throws on violated public lifecycle invariants. */
@@ -0,0 +1,7 @@
1
+ import { type ExecutionDriver, type HarnessResult, type HarnessRuntimeConfig } from "./runtime/index.cjs";
2
+ /** No test-framework dependency. Calls the driver once and throws on violated public lifecycle invariants. */
3
+ export declare function testDriverContract(driver: ExecutionDriver, config?: Omit<HarnessRuntimeConfig, "driver">): Promise<{
4
+ result: HarnessResult;
5
+ eventCount: number;
6
+ }>;
7
+ //# sourceMappingURL=testing.d.ts.map
package/dist/testing.js CHANGED
@@ -1,4 +1,4 @@
1
- import { n as HarnessRuntime } from "./driver-BvzvqvpB.js";
1
+ import { n as HarnessRuntime } from "./driver-reTLBJ_o.js";
2
2
  import { randomUUID } from "node:crypto";
3
3
  //#region src/testing.ts
4
4
  /** No test-framework dependency. Calls the driver once and throws on violated public lifecycle invariants. */
@@ -0,0 +1,11 @@
1
+ import type { WatchDefinition, WatchDefinitionInput } from "./types.cjs";
2
+ export declare function watchId(value: unknown): asserts value is string;
3
+ /** Pure definition: validates/copies JSON, without binding services or activating anything. */
4
+ export declare function defineWatch(input: WatchDefinitionInput): WatchDefinition;
5
+ export declare function describeWatch(definition: WatchDefinitionInput): {
6
+ definition: WatchDefinition;
7
+ hash: string;
8
+ activation: "explicit";
9
+ modelCalls: false;
10
+ };
11
+ //# sourceMappingURL=definition.d.ts.map
@@ -0,0 +1,104 @@
1
+ import type { WatchIdentity, WatchSource } from "./types.cjs";
2
+ type Result<T> = Promise<{
3
+ data: T;
4
+ }>;
5
+ type RequestOptions = {
6
+ signal: AbortSignal;
7
+ };
8
+ interface GmailMessage {
9
+ id?: string | null;
10
+ internalDate?: string | null;
11
+ snippet?: string | null;
12
+ payload?: {
13
+ headers?: Array<{
14
+ name?: string | null;
15
+ value?: string | null;
16
+ }>;
17
+ } | null;
18
+ }
19
+ /** Structural subset of an already-authenticated Gmail client; no SDK or credentials are loaded. */
20
+ export interface GmailWatchClient {
21
+ users: {
22
+ getProfile(params: {
23
+ userId: string;
24
+ }, options: RequestOptions): Result<{
25
+ historyId?: string | null;
26
+ emailAddress?: string | null;
27
+ }>;
28
+ watch(params: {
29
+ userId: string;
30
+ requestBody: {
31
+ topicName: string;
32
+ labelIds?: string[];
33
+ labelFilterBehavior?: "INCLUDE";
34
+ };
35
+ }, options: RequestOptions): Result<{
36
+ historyId?: string | null;
37
+ expiration?: string | null;
38
+ }>;
39
+ stop(params: {
40
+ userId: string;
41
+ }, options: RequestOptions): Promise<unknown>;
42
+ history: {
43
+ list(params: {
44
+ userId: string;
45
+ startHistoryId: string;
46
+ historyTypes: string[];
47
+ maxResults: number;
48
+ pageToken?: string;
49
+ }, options: RequestOptions): Result<{
50
+ historyId?: string | null;
51
+ nextPageToken?: string | null;
52
+ history?: Array<{
53
+ id?: string | null;
54
+ messagesAdded?: Array<{
55
+ message?: {
56
+ id?: string | null;
57
+ labelIds?: string[] | null;
58
+ } | null;
59
+ }>;
60
+ }>;
61
+ }>;
62
+ };
63
+ messages: {
64
+ list(params: {
65
+ userId: string;
66
+ maxResults: number;
67
+ pageToken?: string;
68
+ labelIds?: string[];
69
+ }, options: RequestOptions): Result<{
70
+ messages?: Array<{
71
+ id?: string | null;
72
+ }>;
73
+ nextPageToken?: string | null;
74
+ }>;
75
+ get(params: {
76
+ userId: string;
77
+ id: string;
78
+ format: "metadata";
79
+ metadataHeaders: string[];
80
+ }, options: RequestOptions): Result<GmailMessage>;
81
+ };
82
+ };
83
+ }
84
+ export interface GmailWatchOptions {
85
+ id: string;
86
+ mailbox: string;
87
+ identity: WatchIdentity;
88
+ topicName: string;
89
+ labelIds?: string[];
90
+ client: GmailWatchClient;
91
+ /** Host verifies Pub/Sub signature, audience and subscription ownership before decoding. */
92
+ verifyPush?: (raw: unknown) => Promise<{
93
+ identity: WatchIdentity;
94
+ messageId: string;
95
+ data: {
96
+ emailAddress: string;
97
+ historyId: string;
98
+ };
99
+ }>;
100
+ }
101
+ /** Optional Gmail source: daily renewal/polling are scheduled by DurableWatch, not in this constructor. */
102
+ export declare function gmailWatchSource(options: GmailWatchOptions): WatchSource;
103
+ export {};
104
+ //# sourceMappingURL=gmail.d.ts.map
@@ -0,0 +1,10 @@
1
+ import type { WatchQuietHours } from "./types.cjs";
2
+ export declare function watchClock(now: number, timeZone: string): {
3
+ day: string;
4
+ minute: number;
5
+ };
6
+ export declare function quietMinute(value: string): number;
7
+ export declare function isWatchQuiet(now: number, timeZone: string, quiet?: WatchQuietHours): boolean;
8
+ /** Scan actual instants: repeated local hours are both quiet; skipped boundaries advance naturally. */
9
+ export declare function nextWatchDelivery(now: number, timeZone: string, quiet?: WatchQuietHours, nextDay?: boolean): number;
10
+ //# sourceMappingURL=quiet-hours.d.ts.map
@@ -0,0 +1,42 @@
1
+ import type { WatchDefinition, WatchDefinitionInput, WatchServices, WatchState } from "./types.cjs";
2
+ /** A bounded, versioned watch. Construction is inert; all I/O requires an explicit method call. */
3
+ export declare class DurableWatch {
4
+ private readonly services;
5
+ readonly definition: WatchDefinition;
6
+ readonly key: {
7
+ tenantId: string;
8
+ taskId: string;
9
+ };
10
+ private readonly hash;
11
+ private readonly supervisor;
12
+ private readonly connectorVersion;
13
+ constructor(definition: WatchDefinitionInput, services: WatchServices);
14
+ private checkBindings;
15
+ private authorize;
16
+ private state;
17
+ private read;
18
+ private mutate;
19
+ private ensureRecord;
20
+ private owned;
21
+ private scheduleKey;
22
+ private syncSchedules;
23
+ private start;
24
+ private renewAt;
25
+ private deliveryAt;
26
+ activate(): Promise<void>;
27
+ resume(): Promise<void>;
28
+ inspect(): Promise<WatchState>;
29
+ pause(): Promise<void>;
30
+ delete(): Promise<void>;
31
+ /** Explicit fail-closed rollout. Old pending/unknown sends stay bound to the old definition. */
32
+ update(definition: WatchDefinitionInput, services?: WatchServices): Promise<DurableWatch>;
33
+ private validateCursor;
34
+ trigger(raw: unknown): Promise<void>;
35
+ poll(): Promise<void>;
36
+ renew(): Promise<void>;
37
+ /** Delivers at most one digest. It never retries an unresolved external effect. */
38
+ flush(): Promise<void>;
39
+ /** Reconciliation remains available after pause/delete/update; it never dispatches a send. */
40
+ reconcile(outboxId: string): Promise<void>;
41
+ }
42
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1,147 @@
1
+ import type { DurableActionConnector, DurableJSON, DurableTaskStore } from "@agentium/core";
2
+ export interface WatchIdentity {
3
+ tenantId: string;
4
+ actorId: string;
5
+ }
6
+ export interface WatchQuietHours {
7
+ start: string;
8
+ end: string;
9
+ }
10
+ export interface WatchLimits {
11
+ maxOperations: number;
12
+ maxWakes: number;
13
+ maxEventsPerWake: number;
14
+ maxPagesPerWake: number;
15
+ maxResyncEvents: number;
16
+ maxPendingEvents: number;
17
+ maxDecisions: number;
18
+ maxOutbox: number;
19
+ maxEventBytes: number;
20
+ maxStateBytes: number;
21
+ maxNotificationsPerDay: number;
22
+ }
23
+ export interface WatchDefinition {
24
+ id: string;
25
+ version: number;
26
+ identity: WatchIdentity;
27
+ sourceId: string;
28
+ sourceScope: string;
29
+ destination: string;
30
+ channel: string;
31
+ policyRevision: number;
32
+ grantRefs: string[];
33
+ timeZone: string;
34
+ quietHours?: WatchQuietHours;
35
+ pollIntervalMs: number;
36
+ renewalIntervalMs: number;
37
+ cooldownMs: number;
38
+ limits: WatchLimits;
39
+ }
40
+ export type WatchDefinitionInput = Omit<WatchDefinition, "limits" | "pollIntervalMs" | "renewalIntervalMs" | "cooldownMs"> & {
41
+ limits?: Partial<WatchLimits>;
42
+ pollIntervalMs?: number;
43
+ renewalIntervalMs?: number;
44
+ cooldownMs?: number;
45
+ };
46
+ export interface WatchEvent {
47
+ id: string;
48
+ occurredAt: number;
49
+ data: DurableJSON;
50
+ }
51
+ export interface WatchSubscription {
52
+ reference: string;
53
+ expiresAt: number;
54
+ }
55
+ export interface WatchSourceBatch {
56
+ cursor: string;
57
+ events: WatchEvent[];
58
+ resynced: boolean;
59
+ }
60
+ export interface VerifiedWatchTrigger extends WatchIdentity {
61
+ sourceId: string;
62
+ sourceScope: string;
63
+ eventId: string;
64
+ cursor: string;
65
+ }
66
+ /** A scoped, host-owned source. Implementations must honor read bounds before returning a cursor. */
67
+ export interface WatchSource {
68
+ id: string;
69
+ scope: string;
70
+ capabilities: {
71
+ idempotentActivation: true;
72
+ polling: true;
73
+ push: boolean;
74
+ };
75
+ baseline(signal: AbortSignal): Promise<string>;
76
+ activate(key: string, signal: AbortSignal): Promise<WatchSubscription>;
77
+ stop(subscription: WatchSubscription | null, signal: AbortSignal): Promise<void>;
78
+ read(cursor: string, limits: Pick<WatchLimits, "maxEventsPerWake" | "maxPagesPerWake" | "maxResyncEvents">, signal: AbortSignal): Promise<WatchSourceBatch>;
79
+ compareCursors(left: string, right: string): number;
80
+ /** Verify signature/audience and authenticated mailbox ownership before returning a trusted hint. */
81
+ verifyTrigger?(raw: unknown): Promise<VerifiedWatchTrigger>;
82
+ }
83
+ export type WatchScheduleKind = "poll" | "renew" | "flush";
84
+ export interface WatchSchedule {
85
+ key: string;
86
+ identity: WatchIdentity;
87
+ watchId: string;
88
+ configVersion: number;
89
+ kind: WatchScheduleKind;
90
+ at: number;
91
+ }
92
+ export interface WatchScheduler {
93
+ capabilities: {
94
+ durable: boolean;
95
+ idempotentUpsert: true;
96
+ };
97
+ schedule(job: WatchSchedule): Promise<void>;
98
+ cancel(key: string): Promise<void>;
99
+ }
100
+ export type WatchOperation = "activate" | "update" | "pause" | "resume" | "delete" | "trigger" | "poll" | "renew" | "flush" | "reconcile" | "inspect";
101
+ export interface WatchAuthorization {
102
+ operation: WatchOperation;
103
+ definition: Readonly<WatchDefinition>;
104
+ /** Notification count includes digests; authorization must validate destination/channel and amount. */
105
+ notifications: number;
106
+ events: number;
107
+ }
108
+ export interface WatchServices {
109
+ store: DurableTaskStore;
110
+ source: WatchSource;
111
+ scheduler: WatchScheduler;
112
+ notifications: DurableActionConnector & {
113
+ channel: string;
114
+ destination: string;
115
+ };
116
+ /** Trusted host authority, including exclusive ownership of a source mailbox where required. */
117
+ authorize(request: WatchAuthorization): Promise<boolean>;
118
+ /** Deterministic local classification only; no model/network work in this callback. */
119
+ filter?(event: Readonly<WatchEvent>): boolean;
120
+ leaseMs?: number;
121
+ requireDurability?: boolean;
122
+ }
123
+ export interface WatchOutbox {
124
+ id: string;
125
+ eventIds: string[];
126
+ events: WatchEvent[];
127
+ state: "pending" | "confirmed";
128
+ reservedDay: string | null;
129
+ resultRef: string | null;
130
+ }
131
+ export interface WatchState {
132
+ status: "inactive" | "activating" | "active" | "paused" | "deleted";
133
+ cursor: string | null;
134
+ subscription: WatchSubscription | null;
135
+ wakes: number;
136
+ decisions: Record<string, {
137
+ id: string;
138
+ decision: "pending" | "ignored" | "resync" | "outbox";
139
+ at: number;
140
+ }>;
141
+ pending: WatchEvent[];
142
+ outbox: Record<string, WatchOutbox>;
143
+ daily: Record<string, number>;
144
+ cooldownUntil: number;
145
+ schedules: Partial<Record<WatchScheduleKind, number>>;
146
+ }
147
+ //# sourceMappingURL=types.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentium/harness",
3
- "version": "4.1.0",
3
+ "version": "4.6.0",
4
4
  "description": "Composable harness developer kit for Agentium tools, context, middleware and presets",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -25,29 +25,40 @@
25
25
  "types": "./dist/index.d.ts",
26
26
  "exports": {
27
27
  ".": {
28
- "types": "./dist/index.d.ts",
29
- "import": "./dist/index.js",
30
- "require": "./dist/index.cjs",
28
+ "import": {
29
+ "types": "./dist/index.d.ts",
30
+ "default": "./dist/index.js"
31
+ },
32
+ "require": {
33
+ "types": "./dist/index.d.cts",
34
+ "default": "./dist/index.cjs"
35
+ },
31
36
  "default": "./dist/index.js"
32
37
  },
33
38
  "./testing": {
34
- "types": "./dist/testing.d.ts",
35
- "import": "./dist/testing.js",
36
- "require": "./dist/testing.cjs",
39
+ "import": {
40
+ "types": "./dist/testing.d.ts",
41
+ "default": "./dist/testing.js"
42
+ },
43
+ "require": {
44
+ "types": "./dist/testing.d.cts",
45
+ "default": "./dist/testing.cjs"
46
+ },
37
47
  "default": "./dist/testing.js"
38
48
  }
39
49
  },
40
50
  "files": [
41
- "dist"
51
+ "dist",
52
+ "CONVERSATIONAL-RUNS.md"
42
53
  ],
43
54
  "scripts": {
44
- "build": "tsdown --config ../../tsdown.config.ts && tsc -p tsconfig.build.json --emitDeclarationOnly --declaration --pretty false",
55
+ "build": "tsdown --config ../../tsdown.config.ts && tsc -p tsconfig.build.json --emitDeclarationOnly --declaration --pretty false && node ../../scripts/cjs-declarations.mjs",
45
56
  "dev": "tsdown --config ../../tsdown.config.ts --watch",
46
57
  "prepublishOnly": "npm run build",
47
58
  "test:package": "cd ../.. && AGENTIUM_TEST_PACKAGES=1 vitest run packages/harness/src/__tests__/package-consumption.test.ts"
48
59
  },
49
60
  "peerDependencies": {
50
- "@agentium/core": "^4.1.0"
61
+ "@agentium/core": "^4.6.0"
51
62
  },
52
63
  "dependencies": {
53
64
  "zod": "^4.6.5"