omk-agent-core 0.98.2 → 0.98.3
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 +644 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +3 -5
- package/dist/agent.js.map +1 -1
- package/dist/effects/effect-journal.d.ts +43 -0
- package/dist/effects/effect-journal.d.ts.map +1 -0
- package/dist/effects/effect-journal.js +186 -0
- package/dist/effects/effect-journal.js.map +1 -0
- package/dist/effects/effect-recovery.d.ts +70 -0
- package/dist/effects/effect-recovery.d.ts.map +1 -0
- package/dist/effects/effect-recovery.js +120 -0
- package/dist/effects/effect-recovery.js.map +1 -0
- package/dist/effects/effect-transitions.d.ts +34 -0
- package/dist/effects/effect-transitions.d.ts.map +1 -0
- package/dist/effects/effect-transitions.js +148 -0
- package/dist/effects/effect-transitions.js.map +1 -0
- package/dist/effects/effect-types.d.ts +135 -0
- package/dist/effects/effect-types.d.ts.map +1 -0
- package/dist/effects/effect-types.js +32 -0
- package/dist/effects/effect-types.js.map +1 -0
- package/dist/harness/abort-delivery.d.ts +26 -0
- package/dist/harness/abort-delivery.d.ts.map +1 -0
- package/dist/harness/abort-delivery.js +36 -0
- package/dist/harness/abort-delivery.js.map +1 -0
- package/dist/harness/agent-harness.d.ts +18 -0
- package/dist/harness/agent-harness.d.ts.map +1 -1
- package/dist/harness/agent-harness.js +37 -28
- package/dist/harness/agent-harness.js.map +1 -1
- package/dist/harness/canonical-digest.d.ts +32 -0
- package/dist/harness/canonical-digest.d.ts.map +1 -0
- package/dist/harness/canonical-digest.js +164 -0
- package/dist/harness/canonical-digest.js.map +1 -0
- package/dist/harness/deferred-commands.d.ts +53 -0
- package/dist/harness/deferred-commands.d.ts.map +1 -0
- package/dist/harness/deferred-commands.js +96 -0
- package/dist/harness/deferred-commands.js.map +1 -0
- package/dist/harness/operation-outcome.d.ts +18 -10
- package/dist/harness/operation-outcome.d.ts.map +1 -1
- package/dist/harness/operation-outcome.js +71 -35
- package/dist/harness/operation-outcome.js.map +1 -1
- package/dist/harness/operation-trace-divergence.d.ts +60 -0
- package/dist/harness/operation-trace-divergence.d.ts.map +1 -0
- package/dist/harness/operation-trace-divergence.js +199 -0
- package/dist/harness/operation-trace-divergence.js.map +1 -0
- package/dist/harness/operation-trace.d.ts +134 -0
- package/dist/harness/operation-trace.d.ts.map +1 -0
- package/dist/harness/operation-trace.js +161 -0
- package/dist/harness/operation-trace.js.map +1 -0
- package/dist/harness/subscriber-fanout.d.ts +14 -1
- package/dist/harness/subscriber-fanout.d.ts.map +1 -1
- package/dist/harness/subscriber-fanout.js +25 -6
- package/dist/harness/subscriber-fanout.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/listener-delivery.d.ts +22 -0
- package/dist/listener-delivery.d.ts.map +1 -0
- package/dist/listener-delivery.js +36 -0
- package/dist/listener-delivery.js.map +1 -0
- package/package.json +4 -3
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Operation trace vocabulary: the normalized event stream two runtimes must
|
|
3
|
+
* agree on before either can be called the operation authority.
|
|
4
|
+
*
|
|
5
|
+
* The CLI `AgentSession` and the core `AgentHarness` both drive an operation
|
|
6
|
+
* lifecycle today. Converging them (FND-003, Stage A) needs a common, timing-
|
|
7
|
+
* free record of what each one did: which operations started, which attempts
|
|
8
|
+
* ran and how they closed, which effects were left uncertain, which deferred
|
|
9
|
+
* commands and session writes were accepted, and how the operation settled.
|
|
10
|
+
* This module fixes that vocabulary and derives it mechanically from the pure
|
|
11
|
+
* lifecycle reducer, so a trace is a function of the command stream and not of
|
|
12
|
+
* whichever runtime happened to emit it.
|
|
13
|
+
*
|
|
14
|
+
* Traces carry no wall-clock data and no human wording: `TraceOutcome` keeps
|
|
15
|
+
* the public failure `code` (a blocker dimension) and drops the message (a
|
|
16
|
+
* non-blocker). Two runtimes that produce the same trace digest for the same
|
|
17
|
+
* scenario are behaviourally indistinguishable at the lifecycle boundary.
|
|
18
|
+
*/
|
|
19
|
+
import { canonicalDigest } from "./canonical-digest.js";
|
|
20
|
+
import { initialHarnessLifecycleState, reduceHarnessLifecycle } from "./operation-lifecycle-reducer.js";
|
|
21
|
+
export const OPERATION_TRACE_SCHEMA_VERSION = "omk.operation-trace.v1";
|
|
22
|
+
export function projectTraceOutcome(outcome) {
|
|
23
|
+
switch (outcome.status) {
|
|
24
|
+
case "completed":
|
|
25
|
+
return { status: "completed" };
|
|
26
|
+
case "failed":
|
|
27
|
+
return { status: "failed", code: outcome.code };
|
|
28
|
+
case "aborted":
|
|
29
|
+
return { status: "aborted" };
|
|
30
|
+
case "cancelled":
|
|
31
|
+
return { status: "cancelled" };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The trace events one accepted lifecycle command produces. Pure: it reads the
|
|
36
|
+
* pre-transition state only to recover identities the command omits (the
|
|
37
|
+
* operation of an `attempt_end`, the outcome recorded at `settle_begin`).
|
|
38
|
+
*/
|
|
39
|
+
export function traceEventsForCommand(before, command) {
|
|
40
|
+
switch (command.type) {
|
|
41
|
+
case "begin":
|
|
42
|
+
return [
|
|
43
|
+
{
|
|
44
|
+
type: "operation_started",
|
|
45
|
+
operationId: command.operation.operationId,
|
|
46
|
+
kind: command.operation.kind,
|
|
47
|
+
sequence: command.operation.sequence,
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
case "stage":
|
|
51
|
+
return [{ type: "stage_changed", operationId: command.operationId, stage: command.stage }];
|
|
52
|
+
case "attempt_begin":
|
|
53
|
+
return [
|
|
54
|
+
{
|
|
55
|
+
type: "attempt_started",
|
|
56
|
+
operationId: command.attempt.operationId,
|
|
57
|
+
attemptId: command.attempt.attemptId,
|
|
58
|
+
index: command.attempt.index,
|
|
59
|
+
reason: command.attempt.reason,
|
|
60
|
+
},
|
|
61
|
+
];
|
|
62
|
+
case "attempt_end":
|
|
63
|
+
if (before.tag === "idle")
|
|
64
|
+
return [];
|
|
65
|
+
return [
|
|
66
|
+
{
|
|
67
|
+
type: "attempt_finished",
|
|
68
|
+
operationId: before.operation.operationId,
|
|
69
|
+
attemptId: command.attemptId,
|
|
70
|
+
outcome: command.outcome,
|
|
71
|
+
},
|
|
72
|
+
];
|
|
73
|
+
case "abort_request":
|
|
74
|
+
return [{ type: "abort_requested", operationId: command.operationId }];
|
|
75
|
+
case "settle_begin":
|
|
76
|
+
return [
|
|
77
|
+
{
|
|
78
|
+
type: "settlement_started",
|
|
79
|
+
operationId: command.operationId,
|
|
80
|
+
outcome: projectTraceOutcome(command.outcome),
|
|
81
|
+
},
|
|
82
|
+
];
|
|
83
|
+
case "settle_finish":
|
|
84
|
+
if (before.tag !== "settling")
|
|
85
|
+
return [];
|
|
86
|
+
return [
|
|
87
|
+
{
|
|
88
|
+
type: "operation_settled",
|
|
89
|
+
operationId: command.operationId,
|
|
90
|
+
outcome: projectTraceOutcome(before.outcome),
|
|
91
|
+
},
|
|
92
|
+
];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Drives the pure lifecycle reducer and appends the derived trace. A rejected
|
|
97
|
+
* command records nothing: the trace only ever describes accepted transitions,
|
|
98
|
+
* so two recorders fed the same accepted command stream produce byte-identical
|
|
99
|
+
* traces regardless of how many illegal commands were refused in between.
|
|
100
|
+
*/
|
|
101
|
+
export class OperationTraceRecorder {
|
|
102
|
+
events = [];
|
|
103
|
+
state;
|
|
104
|
+
constructor(initial = initialHarnessLifecycleState()) {
|
|
105
|
+
this.state = initial;
|
|
106
|
+
}
|
|
107
|
+
get lifecycleState() {
|
|
108
|
+
return this.state;
|
|
109
|
+
}
|
|
110
|
+
get size() {
|
|
111
|
+
return this.events.length;
|
|
112
|
+
}
|
|
113
|
+
apply(command) {
|
|
114
|
+
const result = reduceHarnessLifecycle(this.state, command);
|
|
115
|
+
if (!result.ok)
|
|
116
|
+
return result;
|
|
117
|
+
for (const body of traceEventsForCommand(this.state, command))
|
|
118
|
+
this.push(body);
|
|
119
|
+
this.state = result.value;
|
|
120
|
+
return result;
|
|
121
|
+
}
|
|
122
|
+
/** Record a subsystem event. Effect events must name the current operation. */
|
|
123
|
+
record(body) {
|
|
124
|
+
if (body.operationId !== undefined) {
|
|
125
|
+
if (this.state.tag === "idle") {
|
|
126
|
+
return {
|
|
127
|
+
ok: false,
|
|
128
|
+
code: "no_active_operation",
|
|
129
|
+
message: `${body.type} names ${body.operationId} while idle`,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
if (this.state.operation.operationId !== body.operationId) {
|
|
133
|
+
return {
|
|
134
|
+
ok: false,
|
|
135
|
+
code: "stale_operation",
|
|
136
|
+
message: `${body.type} names ${body.operationId} but current operation is ${this.state.operation.operationId}`,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
else if (body.type.startsWith("effect_")) {
|
|
141
|
+
return { ok: false, code: "no_active_operation", message: `${body.type} requires an operationId` };
|
|
142
|
+
}
|
|
143
|
+
return { ok: true, event: this.push(body) };
|
|
144
|
+
}
|
|
145
|
+
snapshot() {
|
|
146
|
+
return { schemaVersion: OPERATION_TRACE_SCHEMA_VERSION, events: [...this.events] };
|
|
147
|
+
}
|
|
148
|
+
digest() {
|
|
149
|
+
return computeTraceDigest(this.events);
|
|
150
|
+
}
|
|
151
|
+
push(body) {
|
|
152
|
+
const event = Object.freeze({ ...body, seq: this.events.length + 1 });
|
|
153
|
+
this.events.push(event);
|
|
154
|
+
return event;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/** Canonical SHA-256 over the schema version and the ordered event list. */
|
|
158
|
+
export function computeTraceDigest(events) {
|
|
159
|
+
return canonicalDigest({ schemaVersion: OPERATION_TRACE_SCHEMA_VERSION, events });
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=operation-trace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operation-trace.js","sourceRoot":"","sources":["../../src/harness/operation-trace.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Operation trace vocabulary: the normalized event stream two runtimes must\n * agree on before either can be called the operation authority.\n *\n * The CLI `AgentSession` and the core `AgentHarness` both drive an operation\n * lifecycle today. Converging them (FND-003, Stage A) needs a common, timing-\n * free record of what each one did: which operations started, which attempts\n * ran and how they closed, which effects were left uncertain, which deferred\n * commands and session writes were accepted, and how the operation settled.\n * This module fixes that vocabulary and derives it mechanically from the pure\n * lifecycle reducer, so a trace is a function of the command stream and not of\n * whichever runtime happened to emit it.\n *\n * Traces carry no wall-clock data and no human wording: `TraceOutcome` keeps\n * the public failure `code` (a blocker dimension) and drops the message (a\n * non-blocker). Two runtimes that produce the same trace digest for the same\n * scenario are behaviourally indistinguishable at the lifecycle boundary.\n */\n\nimport { canonicalDigest } from \"./canonical-digest.ts\";\nimport { initialHarnessLifecycleState, reduceHarnessLifecycle } from \"./operation-lifecycle-reducer.ts\";\nimport type {\n\tHarnessAttemptOutcome,\n\tHarnessAttemptReason,\n\tHarnessLifecycleCommand,\n\tHarnessLifecycleResult,\n\tHarnessLifecycleState,\n\tHarnessOperationKind,\n\tHarnessOperationOutcome,\n\tHarnessOperationStage,\n} from \"./operation-lifecycle-types.ts\";\n\nexport const OPERATION_TRACE_SCHEMA_VERSION = \"omk.operation-trace.v1\" as const;\n\n/** Public outcome projection: status and failure code only, never wording. */\nexport type TraceOutcome =\n\t| { readonly status: \"completed\" }\n\t| { readonly status: \"failed\"; readonly code: string }\n\t| { readonly status: \"aborted\" }\n\t| { readonly status: \"cancelled\" };\n\n/** Events derived from lifecycle commands. Emitted only by `OperationTraceRecorder.apply`. */\nexport type LifecycleTraceEventBody =\n\t| {\n\t\t\treadonly type: \"operation_started\";\n\t\t\treadonly operationId: string;\n\t\t\treadonly kind: HarnessOperationKind;\n\t\t\treadonly sequence: number;\n\t }\n\t| { readonly type: \"stage_changed\"; readonly operationId: string; readonly stage: HarnessOperationStage }\n\t| {\n\t\t\treadonly type: \"attempt_started\";\n\t\t\treadonly operationId: string;\n\t\t\treadonly attemptId: string;\n\t\t\treadonly index: number;\n\t\t\treadonly reason: HarnessAttemptReason;\n\t }\n\t| {\n\t\t\treadonly type: \"attempt_finished\";\n\t\t\treadonly operationId: string;\n\t\t\treadonly attemptId: string;\n\t\t\treadonly outcome: HarnessAttemptOutcome;\n\t }\n\t| { readonly type: \"abort_requested\"; readonly operationId: string }\n\t| { readonly type: \"settlement_started\"; readonly operationId: string; readonly outcome: TraceOutcome }\n\t| { readonly type: \"operation_settled\"; readonly operationId: string; readonly outcome: TraceOutcome };\n\n/** Events reported by subsystems around the lifecycle (effects, deferred commands, session writes). */\nexport type ExternalTraceEventBody =\n\t| { readonly type: \"effect_prepared\"; readonly operationId: string; readonly effectId: string }\n\t| { readonly type: \"effect_uncertain\"; readonly operationId: string; readonly effectId: string }\n\t| { readonly type: \"effect_reconciled\"; readonly operationId: string; readonly effectId: string }\n\t| {\n\t\t\treadonly type: \"deferred_command_accepted\";\n\t\t\treadonly commandId: string;\n\t\t\treadonly name: string;\n\t\t\treadonly operationId?: string;\n\t }\n\t| {\n\t\t\treadonly type: \"session_write_accepted\";\n\t\t\treadonly writeSequence: number;\n\t\t\treadonly writeType: string;\n\t\t\treadonly operationId?: string;\n\t };\n\nexport type OperationTraceEventBody = LifecycleTraceEventBody | ExternalTraceEventBody;\n\n/** One trace entry. `seq` is 1-based and strictly increasing within a trace. */\nexport type OperationTraceEvent = OperationTraceEventBody & { readonly seq: number };\n\nexport interface OperationTraceDocument {\n\treadonly schemaVersion: typeof OPERATION_TRACE_SCHEMA_VERSION;\n\treadonly events: readonly OperationTraceEvent[];\n}\n\nexport function projectTraceOutcome(outcome: HarnessOperationOutcome): TraceOutcome {\n\tswitch (outcome.status) {\n\t\tcase \"completed\":\n\t\t\treturn { status: \"completed\" };\n\t\tcase \"failed\":\n\t\t\treturn { status: \"failed\", code: outcome.code };\n\t\tcase \"aborted\":\n\t\t\treturn { status: \"aborted\" };\n\t\tcase \"cancelled\":\n\t\t\treturn { status: \"cancelled\" };\n\t}\n}\n\n/**\n * The trace events one accepted lifecycle command produces. Pure: it reads the\n * pre-transition state only to recover identities the command omits (the\n * operation of an `attempt_end`, the outcome recorded at `settle_begin`).\n */\nexport function traceEventsForCommand(\n\tbefore: HarnessLifecycleState,\n\tcommand: HarnessLifecycleCommand,\n): readonly LifecycleTraceEventBody[] {\n\tswitch (command.type) {\n\t\tcase \"begin\":\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\ttype: \"operation_started\",\n\t\t\t\t\toperationId: command.operation.operationId,\n\t\t\t\t\tkind: command.operation.kind,\n\t\t\t\t\tsequence: command.operation.sequence,\n\t\t\t\t},\n\t\t\t];\n\t\tcase \"stage\":\n\t\t\treturn [{ type: \"stage_changed\", operationId: command.operationId, stage: command.stage }];\n\t\tcase \"attempt_begin\":\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\ttype: \"attempt_started\",\n\t\t\t\t\toperationId: command.attempt.operationId,\n\t\t\t\t\tattemptId: command.attempt.attemptId,\n\t\t\t\t\tindex: command.attempt.index,\n\t\t\t\t\treason: command.attempt.reason,\n\t\t\t\t},\n\t\t\t];\n\t\tcase \"attempt_end\":\n\t\t\tif (before.tag === \"idle\") return [];\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\ttype: \"attempt_finished\",\n\t\t\t\t\toperationId: before.operation.operationId,\n\t\t\t\t\tattemptId: command.attemptId,\n\t\t\t\t\toutcome: command.outcome,\n\t\t\t\t},\n\t\t\t];\n\t\tcase \"abort_request\":\n\t\t\treturn [{ type: \"abort_requested\", operationId: command.operationId }];\n\t\tcase \"settle_begin\":\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\ttype: \"settlement_started\",\n\t\t\t\t\toperationId: command.operationId,\n\t\t\t\t\toutcome: projectTraceOutcome(command.outcome),\n\t\t\t\t},\n\t\t\t];\n\t\tcase \"settle_finish\":\n\t\t\tif (before.tag !== \"settling\") return [];\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\ttype: \"operation_settled\",\n\t\t\t\t\toperationId: command.operationId,\n\t\t\t\t\toutcome: projectTraceOutcome(before.outcome),\n\t\t\t\t},\n\t\t\t];\n\t}\n}\n\nexport type TraceRecordResult =\n\t| { readonly ok: true; readonly event: OperationTraceEvent }\n\t| { readonly ok: false; readonly code: \"stale_operation\" | \"no_active_operation\"; readonly message: string };\n\n/**\n * Drives the pure lifecycle reducer and appends the derived trace. A rejected\n * command records nothing: the trace only ever describes accepted transitions,\n * so two recorders fed the same accepted command stream produce byte-identical\n * traces regardless of how many illegal commands were refused in between.\n */\nexport class OperationTraceRecorder {\n\tprivate readonly events: OperationTraceEvent[] = [];\n\tprivate state: HarnessLifecycleState;\n\n\tconstructor(initial: HarnessLifecycleState = initialHarnessLifecycleState()) {\n\t\tthis.state = initial;\n\t}\n\n\tget lifecycleState(): HarnessLifecycleState {\n\t\treturn this.state;\n\t}\n\n\tget size(): number {\n\t\treturn this.events.length;\n\t}\n\n\tapply(command: HarnessLifecycleCommand): HarnessLifecycleResult<HarnessLifecycleState> {\n\t\tconst result = reduceHarnessLifecycle(this.state, command);\n\t\tif (!result.ok) return result;\n\t\tfor (const body of traceEventsForCommand(this.state, command)) this.push(body);\n\t\tthis.state = result.value;\n\t\treturn result;\n\t}\n\n\t/** Record a subsystem event. Effect events must name the current operation. */\n\trecord(body: ExternalTraceEventBody): TraceRecordResult {\n\t\tif (body.operationId !== undefined) {\n\t\t\tif (this.state.tag === \"idle\") {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tcode: \"no_active_operation\",\n\t\t\t\t\tmessage: `${body.type} names ${body.operationId} while idle`,\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (this.state.operation.operationId !== body.operationId) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tcode: \"stale_operation\",\n\t\t\t\t\tmessage: `${body.type} names ${body.operationId} but current operation is ${this.state.operation.operationId}`,\n\t\t\t\t};\n\t\t\t}\n\t\t} else if (body.type.startsWith(\"effect_\")) {\n\t\t\treturn { ok: false, code: \"no_active_operation\", message: `${body.type} requires an operationId` };\n\t\t}\n\t\treturn { ok: true, event: this.push(body) };\n\t}\n\n\tsnapshot(): OperationTraceDocument {\n\t\treturn { schemaVersion: OPERATION_TRACE_SCHEMA_VERSION, events: [...this.events] };\n\t}\n\n\tdigest(): string {\n\t\treturn computeTraceDigest(this.events);\n\t}\n\n\tprivate push(body: OperationTraceEventBody): OperationTraceEvent {\n\t\tconst event: OperationTraceEvent = Object.freeze({ ...body, seq: this.events.length + 1 });\n\t\tthis.events.push(event);\n\t\treturn event;\n\t}\n}\n\n/** Canonical SHA-256 over the schema version and the ordered event list. */\nexport function computeTraceDigest(events: readonly OperationTraceEvent[]): string {\n\treturn canonicalDigest({ schemaVersion: OPERATION_TRACE_SCHEMA_VERSION, events });\n}\n"]}
|
|
@@ -9,6 +9,9 @@
|
|
|
9
9
|
* falsely rejecting an unrelated concurrent caller that runs later while the
|
|
10
10
|
* listener's promise is merely pending.
|
|
11
11
|
*
|
|
12
|
+
* Delivery is observational: every subscriber runs even when an earlier one
|
|
13
|
+
* fails, and the failures are raised together afterwards.
|
|
14
|
+
*
|
|
12
15
|
* This module imports no harness or session types so it stays a leaf for the
|
|
13
16
|
* import-cycle ratchet; the harness passes the current operation id in.
|
|
14
17
|
*/
|
|
@@ -22,7 +25,17 @@ export declare class SubscriberFanout<TEvent extends {
|
|
|
22
25
|
private operationId;
|
|
23
26
|
private eventType;
|
|
24
27
|
subscribe(listener: SubscriberListener<TEvent>): () => void;
|
|
25
|
-
/**
|
|
28
|
+
/**
|
|
29
|
+
* Deliver `event` to every subscriber in registration order, then fail the
|
|
30
|
+
* emission once the fanout has completed.
|
|
31
|
+
*
|
|
32
|
+
* Observational subscribers must not starve each other: one throwing telemetry
|
|
33
|
+
* or audit listener cannot hide `settled` / `attempt_finished` from the
|
|
34
|
+
* listeners registered after it. Failures are collected and raised after the
|
|
35
|
+
* last listener ran — a single failure keeps its own classification, several
|
|
36
|
+
* become one `AggregateError` classified by the first. Policy and mutation
|
|
37
|
+
* hooks live on `AgentHarness.on()` and stay fail-fast.
|
|
38
|
+
*/
|
|
26
39
|
emit(event: TEvent, currentOperationId: string | undefined, signal?: AbortSignal): Promise<void>;
|
|
27
40
|
/**
|
|
28
41
|
* Fail closed when an awaited listener tries to wait on its own operation.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscriber-fanout.d.ts","sourceRoot":"","sources":["../../src/harness/subscriber-fanout.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"subscriber-fanout.d.ts","sourceRoot":"","sources":["../../src/harness/subscriber-fanout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,MAAM,MAAM,kBAAkB,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAEvG,qBAAa,gBAAgB,CAAC,MAAM,SAAS;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE;IACrE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyC;IACnE,+EAA+E;IAC/E,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,SAAS,CAAqB;IAEtC,SAAS,CAAC,QAAQ,EAAE,kBAAkB,CAAC,MAAM,CAAC,GAAG,MAAM,IAAI,CAG1D;IAED;;;;;;;;;;OAUG;IACG,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BrG;IAED;;;;;;;OAOG;IACH,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAQ3E;CACD","sourcesContent":["/**\n * Subscriber fan-out with a self-wait barrier, extracted from `AgentHarness`.\n *\n * A listener that awaits the end of the very operation whose emission it is\n * blocking forms a cycle. The call that closes that cycle (`waitForIdle()`,\n * `abort()`) is always made during the listener's *synchronous* prologue — an\n * async function body runs synchronously up to its first `await` — so marking\n * just that window identifies callback-originated waits exactly, without\n * falsely rejecting an unrelated concurrent caller that runs later while the\n * listener's promise is merely pending.\n *\n * Delivery is observational: every subscriber runs even when an earlier one\n * fails, and the failures are raised together afterwards.\n *\n * This module imports no harness or session types so it stays a leaf for the\n * import-cycle ratchet; the harness passes the current operation id in.\n */\n\nimport { AgentHarnessError } from \"./errors.ts\";\nimport { normalizeHarnessError } from \"./operation-outcome.ts\";\n\nexport type SubscriberListener<TEvent> = (event: TEvent, signal?: AbortSignal) => Promise<void> | void;\n\nexport class SubscriberFanout<TEvent extends { readonly type: string }> {\n\tprivate readonly listeners = new Set<SubscriberListener<TEvent>>();\n\t/** Non-zero only while a subscriber's synchronous prologue is on the stack. */\n\tprivate syncFrameDepth = 0;\n\tprivate operationId: string | undefined;\n\tprivate eventType: string | undefined;\n\n\tsubscribe(listener: SubscriberListener<TEvent>): () => void {\n\t\tthis.listeners.add(listener);\n\t\treturn () => this.listeners.delete(listener);\n\t}\n\n\t/**\n\t * Deliver `event` to every subscriber in registration order, then fail the\n\t * emission once the fanout has completed.\n\t *\n\t * Observational subscribers must not starve each other: one throwing telemetry\n\t * or audit listener cannot hide `settled` / `attempt_finished` from the\n\t * listeners registered after it. Failures are collected and raised after the\n\t * last listener ran — a single failure keeps its own classification, several\n\t * become one `AggregateError` classified by the first. Policy and mutation\n\t * hooks live on `AgentHarness.on()` and stay fail-fast.\n\t */\n\tasync emit(event: TEvent, currentOperationId: string | undefined, signal?: AbortSignal): Promise<void> {\n\t\tconst failures: unknown[] = [];\n\t\tfor (const listener of this.listeners) {\n\t\t\tconst previousOperationId = this.operationId;\n\t\t\tconst previousEventType = this.eventType;\n\t\t\tthis.operationId = currentOperationId;\n\t\t\tthis.eventType = event.type;\n\t\t\tlet pending: Promise<unknown> | unknown;\n\t\t\tthis.syncFrameDepth += 1;\n\t\t\ttry {\n\t\t\t\tpending = listener(event, signal);\n\t\t\t} catch (error) {\n\t\t\t\tfailures.push(error);\n\t\t\t} finally {\n\t\t\t\tthis.syncFrameDepth -= 1;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait pending;\n\t\t\t} catch (error) {\n\t\t\t\tfailures.push(error);\n\t\t\t} finally {\n\t\t\t\tthis.operationId = previousOperationId;\n\t\t\t\tthis.eventType = previousEventType;\n\t\t\t}\n\t\t}\n\t\tif (failures.length === 1) throw normalizeHarnessError(failures[0], \"hook\");\n\t\tif (failures.length > 1) {\n\t\t\tconst cause = new AggregateError(failures, `${failures.length} subscribers failed for ${event.type}`);\n\t\t\tthrow new AgentHarnessError(normalizeHarnessError(failures[0], \"hook\").code, cause.message, cause);\n\t\t}\n\t}\n\n\t/**\n\t * Fail closed when an awaited listener tries to wait on its own operation.\n\t * Rejecting immediately turns a permanent deadlock into a classified error.\n\t *\n\t * Scope: this catches a wait issued from the listener's synchronous prologue,\n\t * which covers `await harness.waitForIdle()` / `await harness.abort()`. A wait\n\t * deferred behind an unrelated `await` inside the listener is not detected.\n\t */\n\tassertNotSelfWait(api: string, currentOperationId: string | undefined): void {\n\t\tif (this.syncFrameDepth > 0 && currentOperationId !== undefined && currentOperationId === this.operationId) {\n\t\t\tthrow new AgentHarnessError(\n\t\t\t\t\"invalid_state\",\n\t\t\t\t`${api} cannot await the current operation from an awaited ${this.eventType ?? \"unknown\"} callback; ` +\n\t\t\t\t\t\"use runWhenIdle() to schedule work for after it settles\",\n\t\t\t);\n\t\t}\n\t}\n}\n"]}
|
|
@@ -9,6 +9,9 @@
|
|
|
9
9
|
* falsely rejecting an unrelated concurrent caller that runs later while the
|
|
10
10
|
* listener's promise is merely pending.
|
|
11
11
|
*
|
|
12
|
+
* Delivery is observational: every subscriber runs even when an earlier one
|
|
13
|
+
* fails, and the failures are raised together afterwards.
|
|
14
|
+
*
|
|
12
15
|
* This module imports no harness or session types so it stays a leaf for the
|
|
13
16
|
* import-cycle ratchet; the harness passes the current operation id in.
|
|
14
17
|
*/
|
|
@@ -24,8 +27,19 @@ export class SubscriberFanout {
|
|
|
24
27
|
this.listeners.add(listener);
|
|
25
28
|
return () => this.listeners.delete(listener);
|
|
26
29
|
}
|
|
27
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* Deliver `event` to every subscriber in registration order, then fail the
|
|
32
|
+
* emission once the fanout has completed.
|
|
33
|
+
*
|
|
34
|
+
* Observational subscribers must not starve each other: one throwing telemetry
|
|
35
|
+
* or audit listener cannot hide `settled` / `attempt_finished` from the
|
|
36
|
+
* listeners registered after it. Failures are collected and raised after the
|
|
37
|
+
* last listener ran — a single failure keeps its own classification, several
|
|
38
|
+
* become one `AggregateError` classified by the first. Policy and mutation
|
|
39
|
+
* hooks live on `AgentHarness.on()` and stay fail-fast.
|
|
40
|
+
*/
|
|
28
41
|
async emit(event, currentOperationId, signal) {
|
|
42
|
+
const failures = [];
|
|
29
43
|
for (const listener of this.listeners) {
|
|
30
44
|
const previousOperationId = this.operationId;
|
|
31
45
|
const previousEventType = this.eventType;
|
|
@@ -37,9 +51,7 @@ export class SubscriberFanout {
|
|
|
37
51
|
pending = listener(event, signal);
|
|
38
52
|
}
|
|
39
53
|
catch (error) {
|
|
40
|
-
|
|
41
|
-
this.eventType = previousEventType;
|
|
42
|
-
throw normalizeHarnessError(error, "hook");
|
|
54
|
+
failures.push(error);
|
|
43
55
|
}
|
|
44
56
|
finally {
|
|
45
57
|
this.syncFrameDepth -= 1;
|
|
@@ -48,13 +60,19 @@ export class SubscriberFanout {
|
|
|
48
60
|
await pending;
|
|
49
61
|
}
|
|
50
62
|
catch (error) {
|
|
51
|
-
|
|
63
|
+
failures.push(error);
|
|
52
64
|
}
|
|
53
65
|
finally {
|
|
54
66
|
this.operationId = previousOperationId;
|
|
55
67
|
this.eventType = previousEventType;
|
|
56
68
|
}
|
|
57
69
|
}
|
|
70
|
+
if (failures.length === 1)
|
|
71
|
+
throw normalizeHarnessError(failures[0], "hook");
|
|
72
|
+
if (failures.length > 1) {
|
|
73
|
+
const cause = new AggregateError(failures, `${failures.length} subscribers failed for ${event.type}`);
|
|
74
|
+
throw new AgentHarnessError(normalizeHarnessError(failures[0], "hook").code, cause.message, cause);
|
|
75
|
+
}
|
|
58
76
|
}
|
|
59
77
|
/**
|
|
60
78
|
* Fail closed when an awaited listener tries to wait on its own operation.
|
|
@@ -66,7 +84,8 @@ export class SubscriberFanout {
|
|
|
66
84
|
*/
|
|
67
85
|
assertNotSelfWait(api, currentOperationId) {
|
|
68
86
|
if (this.syncFrameDepth > 0 && currentOperationId !== undefined && currentOperationId === this.operationId) {
|
|
69
|
-
throw new AgentHarnessError("invalid_state", `${api} cannot await the current operation from an awaited ${this.eventType ?? "unknown"} callback`
|
|
87
|
+
throw new AgentHarnessError("invalid_state", `${api} cannot await the current operation from an awaited ${this.eventType ?? "unknown"} callback; ` +
|
|
88
|
+
"use runWhenIdle() to schedule work for after it settles");
|
|
70
89
|
}
|
|
71
90
|
}
|
|
72
91
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscriber-fanout.js","sourceRoot":"","sources":["../../src/harness/subscriber-fanout.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"subscriber-fanout.js","sourceRoot":"","sources":["../../src/harness/subscriber-fanout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAI/D,MAAM,OAAO,gBAAgB;IACX,SAAS,GAAG,IAAI,GAAG,EAA8B,CAAC;IACnE,+EAA+E;IACvE,cAAc,GAAG,CAAC,CAAC;IACnB,WAAW,CAAqB;IAChC,SAAS,CAAqB;IAEtC,SAAS,CAAC,QAAoC,EAAc;QAC3D,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAAA,CAC7C;IAED;;;;;;;;;;OAUG;IACH,KAAK,CAAC,IAAI,CAAC,KAAa,EAAE,kBAAsC,EAAE,MAAoB,EAAiB;QACtG,MAAM,QAAQ,GAAc,EAAE,CAAC;QAC/B,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACvC,MAAM,mBAAmB,GAAG,IAAI,CAAC,WAAW,CAAC;YAC7C,MAAM,iBAAiB,GAAG,IAAI,CAAC,SAAS,CAAC;YACzC,IAAI,CAAC,WAAW,GAAG,kBAAkB,CAAC;YACtC,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC;YAC5B,IAAI,OAAmC,CAAC;YACxC,IAAI,CAAC,cAAc,IAAI,CAAC,CAAC;YACzB,IAAI,CAAC;gBACJ,OAAO,GAAG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YACnC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC;oBAAS,CAAC;gBACV,IAAI,CAAC,cAAc,IAAI,CAAC,CAAC;YAC1B,CAAC;YACD,IAAI,CAAC;gBACJ,MAAM,OAAO,CAAC;YACf,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC;oBAAS,CAAC;gBACV,IAAI,CAAC,WAAW,GAAG,mBAAmB,CAAC;gBACvC,IAAI,CAAC,SAAS,GAAG,iBAAiB,CAAC;YACpC,CAAC;QACF,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,qBAAqB,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QAC5E,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,MAAM,KAAK,GAAG,IAAI,cAAc,CAAC,QAAQ,EAAE,GAAG,QAAQ,CAAC,MAAM,2BAA2B,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YACtG,MAAM,IAAI,iBAAiB,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACpG,CAAC;IAAA,CACD;IAED;;;;;;;OAOG;IACH,iBAAiB,CAAC,GAAW,EAAE,kBAAsC,EAAQ;QAC5E,IAAI,IAAI,CAAC,cAAc,GAAG,CAAC,IAAI,kBAAkB,KAAK,SAAS,IAAI,kBAAkB,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;YAC5G,MAAM,IAAI,iBAAiB,CAC1B,eAAe,EACf,GAAG,GAAG,uDAAuD,IAAI,CAAC,SAAS,IAAI,SAAS,aAAa;gBACpG,yDAAyD,CAC1D,CAAC;QACH,CAAC;IAAA,CACD;CACD","sourcesContent":["/**\n * Subscriber fan-out with a self-wait barrier, extracted from `AgentHarness`.\n *\n * A listener that awaits the end of the very operation whose emission it is\n * blocking forms a cycle. The call that closes that cycle (`waitForIdle()`,\n * `abort()`) is always made during the listener's *synchronous* prologue — an\n * async function body runs synchronously up to its first `await` — so marking\n * just that window identifies callback-originated waits exactly, without\n * falsely rejecting an unrelated concurrent caller that runs later while the\n * listener's promise is merely pending.\n *\n * Delivery is observational: every subscriber runs even when an earlier one\n * fails, and the failures are raised together afterwards.\n *\n * This module imports no harness or session types so it stays a leaf for the\n * import-cycle ratchet; the harness passes the current operation id in.\n */\n\nimport { AgentHarnessError } from \"./errors.ts\";\nimport { normalizeHarnessError } from \"./operation-outcome.ts\";\n\nexport type SubscriberListener<TEvent> = (event: TEvent, signal?: AbortSignal) => Promise<void> | void;\n\nexport class SubscriberFanout<TEvent extends { readonly type: string }> {\n\tprivate readonly listeners = new Set<SubscriberListener<TEvent>>();\n\t/** Non-zero only while a subscriber's synchronous prologue is on the stack. */\n\tprivate syncFrameDepth = 0;\n\tprivate operationId: string | undefined;\n\tprivate eventType: string | undefined;\n\n\tsubscribe(listener: SubscriberListener<TEvent>): () => void {\n\t\tthis.listeners.add(listener);\n\t\treturn () => this.listeners.delete(listener);\n\t}\n\n\t/**\n\t * Deliver `event` to every subscriber in registration order, then fail the\n\t * emission once the fanout has completed.\n\t *\n\t * Observational subscribers must not starve each other: one throwing telemetry\n\t * or audit listener cannot hide `settled` / `attempt_finished` from the\n\t * listeners registered after it. Failures are collected and raised after the\n\t * last listener ran — a single failure keeps its own classification, several\n\t * become one `AggregateError` classified by the first. Policy and mutation\n\t * hooks live on `AgentHarness.on()` and stay fail-fast.\n\t */\n\tasync emit(event: TEvent, currentOperationId: string | undefined, signal?: AbortSignal): Promise<void> {\n\t\tconst failures: unknown[] = [];\n\t\tfor (const listener of this.listeners) {\n\t\t\tconst previousOperationId = this.operationId;\n\t\t\tconst previousEventType = this.eventType;\n\t\t\tthis.operationId = currentOperationId;\n\t\t\tthis.eventType = event.type;\n\t\t\tlet pending: Promise<unknown> | unknown;\n\t\t\tthis.syncFrameDepth += 1;\n\t\t\ttry {\n\t\t\t\tpending = listener(event, signal);\n\t\t\t} catch (error) {\n\t\t\t\tfailures.push(error);\n\t\t\t} finally {\n\t\t\t\tthis.syncFrameDepth -= 1;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait pending;\n\t\t\t} catch (error) {\n\t\t\t\tfailures.push(error);\n\t\t\t} finally {\n\t\t\t\tthis.operationId = previousOperationId;\n\t\t\t\tthis.eventType = previousEventType;\n\t\t\t}\n\t\t}\n\t\tif (failures.length === 1) throw normalizeHarnessError(failures[0], \"hook\");\n\t\tif (failures.length > 1) {\n\t\t\tconst cause = new AggregateError(failures, `${failures.length} subscribers failed for ${event.type}`);\n\t\t\tthrow new AgentHarnessError(normalizeHarnessError(failures[0], \"hook\").code, cause.message, cause);\n\t\t}\n\t}\n\n\t/**\n\t * Fail closed when an awaited listener tries to wait on its own operation.\n\t * Rejecting immediately turns a permanent deadlock into a classified error.\n\t *\n\t * Scope: this catches a wait issued from the listener's synchronous prologue,\n\t * which covers `await harness.waitForIdle()` / `await harness.abort()`. A wait\n\t * deferred behind an unrelated `await` inside the listener is not detected.\n\t */\n\tassertNotSelfWait(api: string, currentOperationId: string | undefined): void {\n\t\tif (this.syncFrameDepth > 0 && currentOperationId !== undefined && currentOperationId === this.operationId) {\n\t\t\tthrow new AgentHarnessError(\n\t\t\t\t\"invalid_state\",\n\t\t\t\t`${api} cannot await the current operation from an awaited ${this.eventType ?? \"unknown\"} callback; ` +\n\t\t\t\t\t\"use runWhenIdle() to schedule work for after it settles\",\n\t\t\t);\n\t\t}\n\t}\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export * from "./agent.ts";
|
|
2
2
|
export * from "./agent-loop.ts";
|
|
3
|
+
export * from "./harness/abort-delivery.ts";
|
|
3
4
|
export * from "./harness/agent-harness.ts";
|
|
4
5
|
export { type BranchPreparation, type BranchSummaryDetails, type CollectEntriesResult, collectEntriesForBranchSummary, generateBranchSummary, prepareBranchEntries, } from "./harness/compaction/branch-summarization.ts";
|
|
5
6
|
export { calculateContextTokens, compact, DEFAULT_COMPACTION_SETTINGS, estimateContextTokens, estimateTokens, findCutPoint, findTurnStartIndex, generateSummary, getLastAssistantUsage, prepareCompaction, serializeConversation, shouldCompact, } from "./harness/compaction/compaction.ts";
|
|
7
|
+
export * from "./harness/deferred-commands.ts";
|
|
6
8
|
export * from "./harness/messages.ts";
|
|
7
9
|
export * from "./harness/prompt-templates.ts";
|
|
8
10
|
export * from "./harness/reverse-skill.ts";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAC;AAE3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EACN,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,8BAA8B,EAC9B,qBAAqB,EACrB,oBAAoB,GACpB,MAAM,8CAA8C,CAAC;AACtD,OAAO,EACN,sBAAsB,EACtB,OAAO,EACP,2BAA2B,EAC3B,qBAAqB,EACrB,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,GACb,MAAM,oCAAoC,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iCAAiC,CAAC;AAChD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AACnD,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAE3C,cAAc,oBAAoB,CAAC;AACnC,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAE5C,OAAO,EACN,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,YAAY,EACZ,0BAA0B,GAC1B,MAAM,0BAA0B,CAAC;AAElC,cAAc,YAAY,CAAC;AAE3B,OAAO,EACN,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,kBAAkB,EAClB,KAAK,wBAAwB,EAC7B,iBAAiB,GACjB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACN,KAAK,iBAAiB,EACtB,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,KAAK,wBAAwB,EAC7B,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,GACtB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACN,uBAAuB,EACvB,uBAAuB,EACvB,0BAA0B,EAC1B,oBAAoB,EACpB,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACN,yBAAyB,EACzB,0BAA0B,EAC1B,yBAAyB,EACzB,wBAAwB,EACxB,KAAK,wBAAwB,EAC7B,KAAK,4BAA4B,EACjC,KAAK,yBAAyB,GAC9B,MAAM,gCAAgC,CAAC;AAExC,cAAc,YAAY,CAAC","sourcesContent":["// Core Agent\nexport * from \"./agent.ts\";\n// Loop functions\nexport * from \"./agent-loop.ts\";\nexport * from \"./harness/agent-harness.ts\";\nexport {\n\ttype BranchPreparation,\n\ttype BranchSummaryDetails,\n\ttype CollectEntriesResult,\n\tcollectEntriesForBranchSummary,\n\tgenerateBranchSummary,\n\tprepareBranchEntries,\n} from \"./harness/compaction/branch-summarization.ts\";\nexport {\n\tcalculateContextTokens,\n\tcompact,\n\tDEFAULT_COMPACTION_SETTINGS,\n\testimateContextTokens,\n\testimateTokens,\n\tfindCutPoint,\n\tfindTurnStartIndex,\n\tgenerateSummary,\n\tgetLastAssistantUsage,\n\tprepareCompaction,\n\tserializeConversation,\n\tshouldCompact,\n} from \"./harness/compaction/compaction.ts\";\nexport * from \"./harness/messages.ts\";\nexport * from \"./harness/prompt-templates.ts\";\nexport * from \"./harness/reverse-skill.ts\";\nexport * from \"./harness/session/jsonl-repo.ts\";\nexport * from \"./harness/session/memory-repo.ts\";\nexport * from \"./harness/session/repo-utils.ts\";\nexport * from \"./harness/session/session.ts\";\nexport { uuidv7 } from \"./harness/session/uuid.ts\";\nexport * from \"./harness/skills.ts\";\nexport * from \"./harness/system-prompt.ts\";\n// Harness\nexport * from \"./harness/types.ts\";\nexport * from \"./harness/utils/shell-output.ts\";\nexport * from \"./harness/utils/truncate.ts\";\n// Parallel tool batch policy\nexport {\n\tNEVER_PARALLEL_TOOLS,\n\tPARALLEL_SAFE_TOOLS,\n\tPATH_SCOPED_TOOLS,\n\tpartitionToolBatchWaves,\n\tpathsOverlap,\n\tshouldParallelizeToolBatch,\n} from \"./parallel-tool-batch.ts\";\n// Proxy utilities\nexport * from \"./proxy.ts\";\n// Deterministic resource-claim DAG scheduler (dag-v2)\nexport {\n\tapplyConcurrencyCap,\n\tassignDagLevels,\n\tcomputePlanKey,\n\ttype DagSchedulePlan,\n\ttype ResolvedClaimEntry,\n\tresolveBatchClaims,\n\ttype ScheduleDagLevelsOptions,\n\tscheduleDagLevels,\n} from \"./tool-dag-scheduler.ts\";\n// Resource-claim model (dag-v2)\nexport {\n\ttype ClaimableToolCall,\n\tcanonicalizeClaims,\n\tclaimsConflict,\n\tcompareClaims,\n\ttype ResolveToolClaimsOptions,\n\tresolutionsConflict,\n\tresolvePathClaimKey,\n\tresolveToolClaims,\n\ttype ToolClaimResolution,\n\ttype ToolResourceAccess,\n\ttype ToolResourceClaim,\n} from \"./tool-resource-claims.ts\";\n// Per-call timeout / cancellation / late settlement (ALG-004)\nexport {\n\tcreateAbortedToolResult,\n\tcreateTimeoutToolResult,\n\tresolveToolExecutionPolicy,\n\tresolveToolTimeoutMs,\n\ttype ToolDispositionEnvelope,\n\ttype ToolLateSettlement,\n} from \"./tool-timeout.ts\";\nexport {\n\tcreateSyntheticToolResult,\n\tinspectTranscriptIntegrity,\n\trepairTranscriptIntegrity,\n\tTranscriptIntegrityError,\n\ttype TranscriptIntegrityIssue,\n\ttype TranscriptIntegrityIssueKind,\n\ttype TranscriptIntegrityReport,\n} from \"./tool-transcript-integrity.ts\";\n// Types\nexport * from \"./types.ts\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAC;AAE3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EACN,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,8BAA8B,EAC9B,qBAAqB,EACrB,oBAAoB,GACpB,MAAM,8CAA8C,CAAC;AACtD,OAAO,EACN,sBAAsB,EACtB,OAAO,EACP,2BAA2B,EAC3B,qBAAqB,EACrB,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,GACb,MAAM,oCAAoC,CAAC;AAC5C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,uBAAuB,CAAC;AACtC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iCAAiC,CAAC;AAChD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AACnD,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAE3C,cAAc,oBAAoB,CAAC;AACnC,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAE5C,OAAO,EACN,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,YAAY,EACZ,0BAA0B,GAC1B,MAAM,0BAA0B,CAAC;AAElC,cAAc,YAAY,CAAC;AAE3B,OAAO,EACN,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,kBAAkB,EAClB,KAAK,wBAAwB,EAC7B,iBAAiB,GACjB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACN,KAAK,iBAAiB,EACtB,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,KAAK,wBAAwB,EAC7B,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,GACtB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACN,uBAAuB,EACvB,uBAAuB,EACvB,0BAA0B,EAC1B,oBAAoB,EACpB,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACN,yBAAyB,EACzB,0BAA0B,EAC1B,yBAAyB,EACzB,wBAAwB,EACxB,KAAK,wBAAwB,EAC7B,KAAK,4BAA4B,EACjC,KAAK,yBAAyB,GAC9B,MAAM,gCAAgC,CAAC;AAExC,cAAc,YAAY,CAAC","sourcesContent":["// Core Agent\nexport * from \"./agent.ts\";\n// Loop functions\nexport * from \"./agent-loop.ts\";\nexport * from \"./harness/abort-delivery.ts\";\nexport * from \"./harness/agent-harness.ts\";\nexport {\n\ttype BranchPreparation,\n\ttype BranchSummaryDetails,\n\ttype CollectEntriesResult,\n\tcollectEntriesForBranchSummary,\n\tgenerateBranchSummary,\n\tprepareBranchEntries,\n} from \"./harness/compaction/branch-summarization.ts\";\nexport {\n\tcalculateContextTokens,\n\tcompact,\n\tDEFAULT_COMPACTION_SETTINGS,\n\testimateContextTokens,\n\testimateTokens,\n\tfindCutPoint,\n\tfindTurnStartIndex,\n\tgenerateSummary,\n\tgetLastAssistantUsage,\n\tprepareCompaction,\n\tserializeConversation,\n\tshouldCompact,\n} from \"./harness/compaction/compaction.ts\";\nexport * from \"./harness/deferred-commands.ts\";\nexport * from \"./harness/messages.ts\";\nexport * from \"./harness/prompt-templates.ts\";\nexport * from \"./harness/reverse-skill.ts\";\nexport * from \"./harness/session/jsonl-repo.ts\";\nexport * from \"./harness/session/memory-repo.ts\";\nexport * from \"./harness/session/repo-utils.ts\";\nexport * from \"./harness/session/session.ts\";\nexport { uuidv7 } from \"./harness/session/uuid.ts\";\nexport * from \"./harness/skills.ts\";\nexport * from \"./harness/system-prompt.ts\";\n// Harness\nexport * from \"./harness/types.ts\";\nexport * from \"./harness/utils/shell-output.ts\";\nexport * from \"./harness/utils/truncate.ts\";\n// Parallel tool batch policy\nexport {\n\tNEVER_PARALLEL_TOOLS,\n\tPARALLEL_SAFE_TOOLS,\n\tPATH_SCOPED_TOOLS,\n\tpartitionToolBatchWaves,\n\tpathsOverlap,\n\tshouldParallelizeToolBatch,\n} from \"./parallel-tool-batch.ts\";\n// Proxy utilities\nexport * from \"./proxy.ts\";\n// Deterministic resource-claim DAG scheduler (dag-v2)\nexport {\n\tapplyConcurrencyCap,\n\tassignDagLevels,\n\tcomputePlanKey,\n\ttype DagSchedulePlan,\n\ttype ResolvedClaimEntry,\n\tresolveBatchClaims,\n\ttype ScheduleDagLevelsOptions,\n\tscheduleDagLevels,\n} from \"./tool-dag-scheduler.ts\";\n// Resource-claim model (dag-v2)\nexport {\n\ttype ClaimableToolCall,\n\tcanonicalizeClaims,\n\tclaimsConflict,\n\tcompareClaims,\n\ttype ResolveToolClaimsOptions,\n\tresolutionsConflict,\n\tresolvePathClaimKey,\n\tresolveToolClaims,\n\ttype ToolClaimResolution,\n\ttype ToolResourceAccess,\n\ttype ToolResourceClaim,\n} from \"./tool-resource-claims.ts\";\n// Per-call timeout / cancellation / late settlement (ALG-004)\nexport {\n\tcreateAbortedToolResult,\n\tcreateTimeoutToolResult,\n\tresolveToolExecutionPolicy,\n\tresolveToolTimeoutMs,\n\ttype ToolDispositionEnvelope,\n\ttype ToolLateSettlement,\n} from \"./tool-timeout.ts\";\nexport {\n\tcreateSyntheticToolResult,\n\tinspectTranscriptIntegrity,\n\trepairTranscriptIntegrity,\n\tTranscriptIntegrityError,\n\ttype TranscriptIntegrityIssue,\n\ttype TranscriptIntegrityIssueKind,\n\ttype TranscriptIntegrityReport,\n} from \"./tool-transcript-integrity.ts\";\n// Types\nexport * from \"./types.ts\";\n"]}
|
package/dist/index.js
CHANGED
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
export * from "./agent.js";
|
|
3
3
|
// Loop functions
|
|
4
4
|
export * from "./agent-loop.js";
|
|
5
|
+
export * from "./harness/abort-delivery.js";
|
|
5
6
|
export * from "./harness/agent-harness.js";
|
|
6
7
|
export { collectEntriesForBranchSummary, generateBranchSummary, prepareBranchEntries, } from "./harness/compaction/branch-summarization.js";
|
|
7
8
|
export { calculateContextTokens, compact, DEFAULT_COMPACTION_SETTINGS, estimateContextTokens, estimateTokens, findCutPoint, findTurnStartIndex, generateSummary, getLastAssistantUsage, prepareCompaction, serializeConversation, shouldCompact, } from "./harness/compaction/compaction.js";
|
|
9
|
+
export * from "./harness/deferred-commands.js";
|
|
8
10
|
export * from "./harness/messages.js";
|
|
9
11
|
export * from "./harness/prompt-templates.js";
|
|
10
12
|
export * from "./harness/reverse-skill.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,cAAc,YAAY,CAAC;AAC3B,iBAAiB;AACjB,cAAc,iBAAiB,CAAC;AAChC,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EAIN,8BAA8B,EAC9B,qBAAqB,EACrB,oBAAoB,GACpB,MAAM,8CAA8C,CAAC;AACtD,OAAO,EACN,sBAAsB,EACtB,OAAO,EACP,2BAA2B,EAC3B,qBAAqB,EACrB,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,GACb,MAAM,oCAAoC,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iCAAiC,CAAC;AAChD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AACnD,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,UAAU;AACV,cAAc,oBAAoB,CAAC;AACnC,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAC5C,6BAA6B;AAC7B,OAAO,EACN,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,YAAY,EACZ,0BAA0B,GAC1B,MAAM,0BAA0B,CAAC;AAClC,kBAAkB;AAClB,cAAc,YAAY,CAAC;AAC3B,sDAAsD;AACtD,OAAO,EACN,mBAAmB,EACnB,eAAe,EACf,cAAc,EAGd,kBAAkB,EAElB,iBAAiB,GACjB,MAAM,yBAAyB,CAAC;AACjC,gCAAgC;AAChC,OAAO,EAEN,kBAAkB,EAClB,cAAc,EACd,aAAa,EAEb,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,GAIjB,MAAM,2BAA2B,CAAC;AACnC,8DAA8D;AAC9D,OAAO,EACN,uBAAuB,EACvB,uBAAuB,EACvB,0BAA0B,EAC1B,oBAAoB,GAGpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACN,yBAAyB,EACzB,0BAA0B,EAC1B,yBAAyB,EACzB,wBAAwB,GAIxB,MAAM,gCAAgC,CAAC;AACxC,QAAQ;AACR,cAAc,YAAY,CAAC","sourcesContent":["// Core Agent\nexport * from \"./agent.ts\";\n// Loop functions\nexport * from \"./agent-loop.ts\";\nexport * from \"./harness/agent-harness.ts\";\nexport {\n\ttype BranchPreparation,\n\ttype BranchSummaryDetails,\n\ttype CollectEntriesResult,\n\tcollectEntriesForBranchSummary,\n\tgenerateBranchSummary,\n\tprepareBranchEntries,\n} from \"./harness/compaction/branch-summarization.ts\";\nexport {\n\tcalculateContextTokens,\n\tcompact,\n\tDEFAULT_COMPACTION_SETTINGS,\n\testimateContextTokens,\n\testimateTokens,\n\tfindCutPoint,\n\tfindTurnStartIndex,\n\tgenerateSummary,\n\tgetLastAssistantUsage,\n\tprepareCompaction,\n\tserializeConversation,\n\tshouldCompact,\n} from \"./harness/compaction/compaction.ts\";\nexport * from \"./harness/messages.ts\";\nexport * from \"./harness/prompt-templates.ts\";\nexport * from \"./harness/reverse-skill.ts\";\nexport * from \"./harness/session/jsonl-repo.ts\";\nexport * from \"./harness/session/memory-repo.ts\";\nexport * from \"./harness/session/repo-utils.ts\";\nexport * from \"./harness/session/session.ts\";\nexport { uuidv7 } from \"./harness/session/uuid.ts\";\nexport * from \"./harness/skills.ts\";\nexport * from \"./harness/system-prompt.ts\";\n// Harness\nexport * from \"./harness/types.ts\";\nexport * from \"./harness/utils/shell-output.ts\";\nexport * from \"./harness/utils/truncate.ts\";\n// Parallel tool batch policy\nexport {\n\tNEVER_PARALLEL_TOOLS,\n\tPARALLEL_SAFE_TOOLS,\n\tPATH_SCOPED_TOOLS,\n\tpartitionToolBatchWaves,\n\tpathsOverlap,\n\tshouldParallelizeToolBatch,\n} from \"./parallel-tool-batch.ts\";\n// Proxy utilities\nexport * from \"./proxy.ts\";\n// Deterministic resource-claim DAG scheduler (dag-v2)\nexport {\n\tapplyConcurrencyCap,\n\tassignDagLevels,\n\tcomputePlanKey,\n\ttype DagSchedulePlan,\n\ttype ResolvedClaimEntry,\n\tresolveBatchClaims,\n\ttype ScheduleDagLevelsOptions,\n\tscheduleDagLevels,\n} from \"./tool-dag-scheduler.ts\";\n// Resource-claim model (dag-v2)\nexport {\n\ttype ClaimableToolCall,\n\tcanonicalizeClaims,\n\tclaimsConflict,\n\tcompareClaims,\n\ttype ResolveToolClaimsOptions,\n\tresolutionsConflict,\n\tresolvePathClaimKey,\n\tresolveToolClaims,\n\ttype ToolClaimResolution,\n\ttype ToolResourceAccess,\n\ttype ToolResourceClaim,\n} from \"./tool-resource-claims.ts\";\n// Per-call timeout / cancellation / late settlement (ALG-004)\nexport {\n\tcreateAbortedToolResult,\n\tcreateTimeoutToolResult,\n\tresolveToolExecutionPolicy,\n\tresolveToolTimeoutMs,\n\ttype ToolDispositionEnvelope,\n\ttype ToolLateSettlement,\n} from \"./tool-timeout.ts\";\nexport {\n\tcreateSyntheticToolResult,\n\tinspectTranscriptIntegrity,\n\trepairTranscriptIntegrity,\n\tTranscriptIntegrityError,\n\ttype TranscriptIntegrityIssue,\n\ttype TranscriptIntegrityIssueKind,\n\ttype TranscriptIntegrityReport,\n} from \"./tool-transcript-integrity.ts\";\n// Types\nexport * from \"./types.ts\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,cAAc,YAAY,CAAC;AAC3B,iBAAiB;AACjB,cAAc,iBAAiB,CAAC;AAChC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EAIN,8BAA8B,EAC9B,qBAAqB,EACrB,oBAAoB,GACpB,MAAM,8CAA8C,CAAC;AACtD,OAAO,EACN,sBAAsB,EACtB,OAAO,EACP,2BAA2B,EAC3B,qBAAqB,EACrB,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,GACb,MAAM,oCAAoC,CAAC;AAC5C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,uBAAuB,CAAC;AACtC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iCAAiC,CAAC;AAChD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AACnD,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,UAAU;AACV,cAAc,oBAAoB,CAAC;AACnC,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAC5C,6BAA6B;AAC7B,OAAO,EACN,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,YAAY,EACZ,0BAA0B,GAC1B,MAAM,0BAA0B,CAAC;AAClC,kBAAkB;AAClB,cAAc,YAAY,CAAC;AAC3B,sDAAsD;AACtD,OAAO,EACN,mBAAmB,EACnB,eAAe,EACf,cAAc,EAGd,kBAAkB,EAElB,iBAAiB,GACjB,MAAM,yBAAyB,CAAC;AACjC,gCAAgC;AAChC,OAAO,EAEN,kBAAkB,EAClB,cAAc,EACd,aAAa,EAEb,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,GAIjB,MAAM,2BAA2B,CAAC;AACnC,8DAA8D;AAC9D,OAAO,EACN,uBAAuB,EACvB,uBAAuB,EACvB,0BAA0B,EAC1B,oBAAoB,GAGpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACN,yBAAyB,EACzB,0BAA0B,EAC1B,yBAAyB,EACzB,wBAAwB,GAIxB,MAAM,gCAAgC,CAAC;AACxC,QAAQ;AACR,cAAc,YAAY,CAAC","sourcesContent":["// Core Agent\nexport * from \"./agent.ts\";\n// Loop functions\nexport * from \"./agent-loop.ts\";\nexport * from \"./harness/abort-delivery.ts\";\nexport * from \"./harness/agent-harness.ts\";\nexport {\n\ttype BranchPreparation,\n\ttype BranchSummaryDetails,\n\ttype CollectEntriesResult,\n\tcollectEntriesForBranchSummary,\n\tgenerateBranchSummary,\n\tprepareBranchEntries,\n} from \"./harness/compaction/branch-summarization.ts\";\nexport {\n\tcalculateContextTokens,\n\tcompact,\n\tDEFAULT_COMPACTION_SETTINGS,\n\testimateContextTokens,\n\testimateTokens,\n\tfindCutPoint,\n\tfindTurnStartIndex,\n\tgenerateSummary,\n\tgetLastAssistantUsage,\n\tprepareCompaction,\n\tserializeConversation,\n\tshouldCompact,\n} from \"./harness/compaction/compaction.ts\";\nexport * from \"./harness/deferred-commands.ts\";\nexport * from \"./harness/messages.ts\";\nexport * from \"./harness/prompt-templates.ts\";\nexport * from \"./harness/reverse-skill.ts\";\nexport * from \"./harness/session/jsonl-repo.ts\";\nexport * from \"./harness/session/memory-repo.ts\";\nexport * from \"./harness/session/repo-utils.ts\";\nexport * from \"./harness/session/session.ts\";\nexport { uuidv7 } from \"./harness/session/uuid.ts\";\nexport * from \"./harness/skills.ts\";\nexport * from \"./harness/system-prompt.ts\";\n// Harness\nexport * from \"./harness/types.ts\";\nexport * from \"./harness/utils/shell-output.ts\";\nexport * from \"./harness/utils/truncate.ts\";\n// Parallel tool batch policy\nexport {\n\tNEVER_PARALLEL_TOOLS,\n\tPARALLEL_SAFE_TOOLS,\n\tPATH_SCOPED_TOOLS,\n\tpartitionToolBatchWaves,\n\tpathsOverlap,\n\tshouldParallelizeToolBatch,\n} from \"./parallel-tool-batch.ts\";\n// Proxy utilities\nexport * from \"./proxy.ts\";\n// Deterministic resource-claim DAG scheduler (dag-v2)\nexport {\n\tapplyConcurrencyCap,\n\tassignDagLevels,\n\tcomputePlanKey,\n\ttype DagSchedulePlan,\n\ttype ResolvedClaimEntry,\n\tresolveBatchClaims,\n\ttype ScheduleDagLevelsOptions,\n\tscheduleDagLevels,\n} from \"./tool-dag-scheduler.ts\";\n// Resource-claim model (dag-v2)\nexport {\n\ttype ClaimableToolCall,\n\tcanonicalizeClaims,\n\tclaimsConflict,\n\tcompareClaims,\n\ttype ResolveToolClaimsOptions,\n\tresolutionsConflict,\n\tresolvePathClaimKey,\n\tresolveToolClaims,\n\ttype ToolClaimResolution,\n\ttype ToolResourceAccess,\n\ttype ToolResourceClaim,\n} from \"./tool-resource-claims.ts\";\n// Per-call timeout / cancellation / late settlement (ALG-004)\nexport {\n\tcreateAbortedToolResult,\n\tcreateTimeoutToolResult,\n\tresolveToolExecutionPolicy,\n\tresolveToolTimeoutMs,\n\ttype ToolDispositionEnvelope,\n\ttype ToolLateSettlement,\n} from \"./tool-timeout.ts\";\nexport {\n\tcreateSyntheticToolResult,\n\tinspectTranscriptIntegrity,\n\trepairTranscriptIntegrity,\n\tTranscriptIntegrityError,\n\ttype TranscriptIntegrityIssue,\n\ttype TranscriptIntegrityIssueKind,\n\ttype TranscriptIntegrityReport,\n} from \"./tool-transcript-integrity.ts\";\n// Types\nexport * from \"./types.ts\";\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Observational listener delivery for `Agent`.
|
|
3
|
+
*
|
|
4
|
+
* Kept as a leaf module (no agent state, no loop imports) so the delivery
|
|
5
|
+
* contract stays readable next to the harness' own `SubscriberFanout`.
|
|
6
|
+
*/
|
|
7
|
+
import type { AgentEvent } from "./types.ts";
|
|
8
|
+
export type AgentListener = (event: AgentEvent, signal: AbortSignal) => Promise<void> | void;
|
|
9
|
+
/**
|
|
10
|
+
* Deliver `event` to every listener in subscription order, then raise the
|
|
11
|
+
* failures together.
|
|
12
|
+
*
|
|
13
|
+
* Observation listeners must not starve each other: a throwing extension cannot
|
|
14
|
+
* hide `agent_start`, `turn_end`, or `agent_end` from the listeners registered
|
|
15
|
+
* after it. A single failure surfaces untouched so its own classification
|
|
16
|
+
* survives; several become one `AggregateError`.
|
|
17
|
+
*
|
|
18
|
+
* Each listener receives its own immutable snapshot, so one observer's view can
|
|
19
|
+
* never be rewritten into another's.
|
|
20
|
+
*/
|
|
21
|
+
export declare function deliverToListeners(listeners: Iterable<AgentListener>, event: AgentEvent, signal: AbortSignal): Promise<void>;
|
|
22
|
+
//# sourceMappingURL=listener-delivery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listener-delivery.d.ts","sourceRoot":"","sources":["../src/listener-delivery.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAE7F;;;;;;;;;;;GAWG;AACH,wBAAsB,kBAAkB,CACvC,SAAS,EAAE,QAAQ,CAAC,aAAa,CAAC,EAClC,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,WAAW,GACjB,OAAO,CAAC,IAAI,CAAC,CAaf","sourcesContent":["/**\n * Observational listener delivery for `Agent`.\n *\n * Kept as a leaf module (no agent state, no loop imports) so the delivery\n * contract stays readable next to the harness' own `SubscriberFanout`.\n */\n\nimport { createImmutableSnapshot } from \"./tool-execution-boundary.ts\";\nimport type { AgentEvent } from \"./types.ts\";\n\nexport type AgentListener = (event: AgentEvent, signal: AbortSignal) => Promise<void> | void;\n\n/**\n * Deliver `event` to every listener in subscription order, then raise the\n * failures together.\n *\n * Observation listeners must not starve each other: a throwing extension cannot\n * hide `agent_start`, `turn_end`, or `agent_end` from the listeners registered\n * after it. A single failure surfaces untouched so its own classification\n * survives; several become one `AggregateError`.\n *\n * Each listener receives its own immutable snapshot, so one observer's view can\n * never be rewritten into another's.\n */\nexport async function deliverToListeners(\n\tlisteners: Iterable<AgentListener>,\n\tevent: AgentEvent,\n\tsignal: AbortSignal,\n): Promise<void> {\n\tconst failures: unknown[] = [];\n\tfor (const listener of listeners) {\n\t\ttry {\n\t\t\tawait listener(createImmutableSnapshot(event), signal);\n\t\t} catch (error) {\n\t\t\tfailures.push(error);\n\t\t}\n\t}\n\tif (failures.length === 1) throw failures[0];\n\tif (failures.length > 1) {\n\t\tthrow new AggregateError(failures, `${failures.length} agent listeners failed for ${event.type}`);\n\t}\n}\n"]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Observational listener delivery for `Agent`.
|
|
3
|
+
*
|
|
4
|
+
* Kept as a leaf module (no agent state, no loop imports) so the delivery
|
|
5
|
+
* contract stays readable next to the harness' own `SubscriberFanout`.
|
|
6
|
+
*/
|
|
7
|
+
import { createImmutableSnapshot } from "./tool-execution-boundary.js";
|
|
8
|
+
/**
|
|
9
|
+
* Deliver `event` to every listener in subscription order, then raise the
|
|
10
|
+
* failures together.
|
|
11
|
+
*
|
|
12
|
+
* Observation listeners must not starve each other: a throwing extension cannot
|
|
13
|
+
* hide `agent_start`, `turn_end`, or `agent_end` from the listeners registered
|
|
14
|
+
* after it. A single failure surfaces untouched so its own classification
|
|
15
|
+
* survives; several become one `AggregateError`.
|
|
16
|
+
*
|
|
17
|
+
* Each listener receives its own immutable snapshot, so one observer's view can
|
|
18
|
+
* never be rewritten into another's.
|
|
19
|
+
*/
|
|
20
|
+
export async function deliverToListeners(listeners, event, signal) {
|
|
21
|
+
const failures = [];
|
|
22
|
+
for (const listener of listeners) {
|
|
23
|
+
try {
|
|
24
|
+
await listener(createImmutableSnapshot(event), signal);
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
failures.push(error);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (failures.length === 1)
|
|
31
|
+
throw failures[0];
|
|
32
|
+
if (failures.length > 1) {
|
|
33
|
+
throw new AggregateError(failures, `${failures.length} agent listeners failed for ${event.type}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=listener-delivery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listener-delivery.js","sourceRoot":"","sources":["../src/listener-delivery.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAKvE;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACvC,SAAkC,EAClC,KAAiB,EACjB,MAAmB,EACH;IAChB,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QAClC,IAAI,CAAC;YACJ,MAAM,QAAQ,CAAC,uBAAuB,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,CAAC;QACxD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACF,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC7C,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,cAAc,CAAC,QAAQ,EAAE,GAAG,QAAQ,CAAC,MAAM,+BAA+B,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IACnG,CAAC;AAAA,CACD","sourcesContent":["/**\n * Observational listener delivery for `Agent`.\n *\n * Kept as a leaf module (no agent state, no loop imports) so the delivery\n * contract stays readable next to the harness' own `SubscriberFanout`.\n */\n\nimport { createImmutableSnapshot } from \"./tool-execution-boundary.ts\";\nimport type { AgentEvent } from \"./types.ts\";\n\nexport type AgentListener = (event: AgentEvent, signal: AbortSignal) => Promise<void> | void;\n\n/**\n * Deliver `event` to every listener in subscription order, then raise the\n * failures together.\n *\n * Observation listeners must not starve each other: a throwing extension cannot\n * hide `agent_start`, `turn_end`, or `agent_end` from the listeners registered\n * after it. A single failure surfaces untouched so its own classification\n * survives; several become one `AggregateError`.\n *\n * Each listener receives its own immutable snapshot, so one observer's view can\n * never be rewritten into another's.\n */\nexport async function deliverToListeners(\n\tlisteners: Iterable<AgentListener>,\n\tevent: AgentEvent,\n\tsignal: AbortSignal,\n): Promise<void> {\n\tconst failures: unknown[] = [];\n\tfor (const listener of listeners) {\n\t\ttry {\n\t\t\tawait listener(createImmutableSnapshot(event), signal);\n\t\t} catch (error) {\n\t\t\tfailures.push(error);\n\t\t}\n\t}\n\tif (failures.length === 1) throw failures[0];\n\tif (failures.length > 1) {\n\t\tthrow new AggregateError(failures, `${failures.length} agent listeners failed for ${event.type}`);\n\t}\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omk-agent-core",
|
|
3
|
-
"version": "0.98.
|
|
3
|
+
"version": "0.98.3",
|
|
4
4
|
"description": "General-purpose agent with transport abstraction, state management, and attachment support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
},
|
|
19
19
|
"files": [
|
|
20
20
|
"dist",
|
|
21
|
-
"README.md"
|
|
21
|
+
"README.md",
|
|
22
|
+
"CHANGELOG.md"
|
|
22
23
|
],
|
|
23
24
|
"scripts": {
|
|
24
25
|
"clean": "shx rm -rf dist",
|
|
@@ -29,7 +30,7 @@
|
|
|
29
30
|
"prepublishOnly": "npm run clean && npm run build"
|
|
30
31
|
},
|
|
31
32
|
"dependencies": {
|
|
32
|
-
"omk-ai": "^0.98.
|
|
33
|
+
"omk-ai": "^0.98.3",
|
|
33
34
|
"ignore": "7.0.6",
|
|
34
35
|
"typebox": "1.3.11",
|
|
35
36
|
"yaml": "2.9.0"
|