@botbotgo/agent-harness 0.0.129 → 0.0.130

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/README.md CHANGED
@@ -109,7 +109,11 @@ Boundary documents live in:
109
109
 
110
110
  - `docs/upstream-feature-matrix.md`
111
111
  - `docs/product-boundary.md`
112
+ - `docs/runtime-blueprint-assessment.md`
113
+ - `docs/policy-engine-scope.md`
112
114
  - `docs/acp-support-plan.md`
115
+ - `docs/recovery-policy-matrix.md`
116
+ - `docs/operator-timeline.md`
113
117
  - `docs/feature-checklist.md`
114
118
  - `docs/long-term-memory.md`
115
119
  - `docs/app-task-pattern.md`
package/README.zh.md CHANGED
@@ -109,7 +109,11 @@ AI 让 agent 逻辑、工具调用和工作流代码更容易生成,真正变
109
109
 
110
110
  - `docs/upstream-feature-matrix.md`
111
111
  - `docs/product-boundary.md`
112
+ - `docs/runtime-blueprint-assessment.md`
113
+ - `docs/policy-engine-scope.md`
112
114
  - `docs/acp-support-plan.md`
115
+ - `docs/recovery-policy-matrix.md`
116
+ - `docs/operator-timeline.md`
113
117
  - `docs/feature-checklist.md`
114
118
  - `docs/long-term-memory.md`
115
119
  - `docs/app-task-pattern.md`
@@ -40,6 +40,25 @@ export type HarnessEventProjection = {
40
40
  shouldHandle?: (event: HarnessEvent) => boolean;
41
41
  handleEvent: HarnessEventListener;
42
42
  };
43
+ /**
44
+ * Operator-facing timeline item projected from persisted runtime events.
45
+ * This is an inspection convenience over runtime records, not a new execution protocol.
46
+ */
47
+ export type RuntimeTimelineItem = {
48
+ eventId: string;
49
+ threadId: string;
50
+ runId: string;
51
+ eventType: HarnessEventType;
52
+ timestamp: string;
53
+ sequence: number;
54
+ source: HarnessEvent["source"];
55
+ kind: "run" | "queue" | "approval" | "recovery" | "artifact" | "other";
56
+ payload: Record<string, unknown>;
57
+ };
58
+ export type RuntimeTimelineProjectionOptions = {
59
+ threadId?: string;
60
+ runId?: string;
61
+ };
43
62
  export type RuntimeEventSink = {
44
63
  publish: (event: HarnessEvent) => void;
45
64
  subscribe: (listener: HarnessEventListener) => () => void;
@@ -1 +1 @@
1
- export declare const AGENT_HARNESS_VERSION = "0.0.128";
1
+ export declare const AGENT_HARNESS_VERSION = "0.0.129";
@@ -1 +1 @@
1
- export const AGENT_HARNESS_VERSION = "0.0.128";
1
+ export const AGENT_HARNESS_VERSION = "0.0.129";
@@ -0,0 +1,2 @@
1
+ import type { HarnessEvent, RuntimeTimelineItem, RuntimeTimelineProjectionOptions } from "../../../contracts/types.js";
2
+ export declare function projectRuntimeTimeline(events: readonly HarnessEvent[], options?: RuntimeTimelineProjectionOptions): RuntimeTimelineItem[];
@@ -0,0 +1,52 @@
1
+ function classifyTimelineItem(event) {
2
+ switch (event.eventType) {
3
+ case "run.queued":
4
+ case "run.dequeued":
5
+ return "queue";
6
+ case "approval.requested":
7
+ case "approval.resolved":
8
+ return "approval";
9
+ case "run.resumed":
10
+ return "recovery";
11
+ case "artifact.created":
12
+ return "artifact";
13
+ case "run.created":
14
+ case "run.state.changed":
15
+ return "run";
16
+ default:
17
+ return "other";
18
+ }
19
+ }
20
+ export function projectRuntimeTimeline(events, options = {}) {
21
+ const filtered = events.filter((event) => {
22
+ if (options.threadId && event.threadId !== options.threadId) {
23
+ return false;
24
+ }
25
+ if (options.runId && event.runId !== options.runId) {
26
+ return false;
27
+ }
28
+ return true;
29
+ });
30
+ return [...filtered]
31
+ .sort((left, right) => {
32
+ const timestampComparison = left.timestamp.localeCompare(right.timestamp);
33
+ if (timestampComparison !== 0) {
34
+ return timestampComparison;
35
+ }
36
+ if (left.sequence !== right.sequence) {
37
+ return left.sequence - right.sequence;
38
+ }
39
+ return left.eventId.localeCompare(right.eventId);
40
+ })
41
+ .map((event) => ({
42
+ eventId: event.eventId,
43
+ threadId: event.threadId,
44
+ runId: event.runId,
45
+ eventType: event.eventType,
46
+ timestamp: event.timestamp,
47
+ sequence: event.sequence,
48
+ source: event.source,
49
+ kind: classifyTimelineItem(event),
50
+ payload: event.payload,
51
+ }));
52
+ }
@@ -1,6 +1,7 @@
1
1
  export * from "./events/event-bus.js";
2
2
  export * from "./events/event-sink.js";
3
3
  export * from "./events/events.js";
4
+ export * from "./events/timeline.js";
4
5
  export * from "./system/health-monitor.js";
5
6
  export * from "./run/helpers.js";
6
7
  export * from "./system/inventory.js";
@@ -1,6 +1,7 @@
1
1
  export * from "./events/event-bus.js";
2
2
  export * from "./events/event-sink.js";
3
3
  export * from "./events/events.js";
4
+ export * from "./events/timeline.js";
4
5
  export * from "./system/health-monitor.js";
5
6
  export * from "./run/helpers.js";
6
7
  export * from "./system/inventory.js";
@@ -41,6 +41,17 @@ async function executeRecoveredRun(context, input) {
41
41
  }
42
42
  return true;
43
43
  }
44
+ async function failResumingRecovery(context, thread, checkpointRef, error) {
45
+ await context.persistence.setRunState(thread.threadId, thread.latestRunId, "failed", checkpointRef);
46
+ await context.persistence.clearRecoveryIntent(thread.threadId, thread.latestRunId);
47
+ await context.emit(thread.threadId, thread.latestRunId, 101, "run.state.changed", {
48
+ previousState: "resuming",
49
+ state: "failed",
50
+ checkpointRef,
51
+ ...(error ? { error } : {}),
52
+ });
53
+ return true;
54
+ }
44
55
  export async function recoverQueuedStartupRun(context, thread) {
45
56
  if (thread.status !== "queued") {
46
57
  return false;
@@ -113,9 +124,7 @@ export async function recoverResumingStartupRun(context, thread) {
113
124
  return true;
114
125
  }
115
126
  if (recoveryIntent.attempts >= context.recoveryConfig.maxRecoveryAttempts) {
116
- await context.persistence.setRunState(thread.threadId, thread.latestRunId, "failed", recoveryIntent.checkpointRef);
117
- await context.persistence.clearRecoveryIntent(thread.threadId, thread.latestRunId);
118
- return true;
127
+ return failResumingRecovery(context, thread, recoveryIntent.checkpointRef, "recovery attempts exhausted");
119
128
  }
120
129
  await context.persistence.saveRecoveryIntent(thread.threadId, thread.latestRunId, {
121
130
  ...recoveryIntent,
@@ -143,14 +152,7 @@ export async function recoverResumingStartupRun(context, thread) {
143
152
  catch (error) {
144
153
  context.recordLlmFailure(startedAt);
145
154
  if (recoveryIntent.attempts + 1 >= context.recoveryConfig.maxRecoveryAttempts) {
146
- await context.persistence.setRunState(thread.threadId, thread.latestRunId, "failed", recoveryIntent.checkpointRef);
147
- await context.persistence.clearRecoveryIntent(thread.threadId, thread.latestRunId);
148
- await context.emit(thread.threadId, thread.latestRunId, 101, "run.state.changed", {
149
- previousState: "resuming",
150
- state: "failed",
151
- checkpointRef: recoveryIntent.checkpointRef,
152
- error: error instanceof Error ? error.message : String(error),
153
- });
155
+ await failResumingRecovery(context, thread, recoveryIntent.checkpointRef, error instanceof Error ? error.message : String(error));
154
156
  }
155
157
  }
156
158
  return true;
@@ -4,6 +4,11 @@ export type PolicyEngineDecision = {
4
4
  reasons: string[];
5
5
  };
6
6
  export declare class PolicyEngine {
7
+ /**
8
+ * Runtime governance gate for a compiled binding.
9
+ * This engine may allow or block execution with reasons, but it must not
10
+ * redefine upstream planning or execution semantics.
11
+ */
7
12
  evaluate(binding: CompiledAgentBinding): PolicyEngineDecision;
8
13
  }
9
14
  export { PolicyEngineDecision as GovernanceDecision, PolicyEngine as GovernanceEngine, };
@@ -1,5 +1,10 @@
1
1
  import { getPolicyEvaluators } from "../../../extensions.js";
2
2
  export class PolicyEngine {
3
+ /**
4
+ * Runtime governance gate for a compiled binding.
5
+ * This engine may allow or block execution with reasons, but it must not
6
+ * redefine upstream planning or execution semantics.
7
+ */
3
8
  evaluate(binding) {
4
9
  const reasons = [];
5
10
  let allowed = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbotgo/agent-harness",
3
- "version": "0.0.129",
3
+ "version": "0.0.130",
4
4
  "description": "Workspace runtime for multi-agent applications",
5
5
  "type": "module",
6
6
  "packageManager": "npm@10.9.2",