@botbotgo/agent-harness 0.0.64 → 0.0.66

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
@@ -69,6 +69,7 @@ Boundary documents live in:
69
69
  - `docs/product-boundary.md`
70
70
  - `docs/feature-checklist.md`
71
71
  - `docs/long-term-memory.md`
72
+ - `docs/app-task-pattern.md`
72
73
 
73
74
  ## Why This Exists
74
75
 
@@ -206,6 +207,8 @@ const result = await run(runtime, {
206
207
 
207
208
  `run(runtime, { ... })` creates or continues a persisted thread and returns `threadId`, `runId`, `state`, and compact text `output`. Richer upstream result shapes stay available through `outputContent`, `contentBlocks`, and `structuredResponse`.
208
209
 
210
+ Use `listRuns(runtime)` and `getRun(runtime, runId)` when a product needs a run-centric operations surface such as a review queue or execution dashboard.
211
+
209
212
  Use `invocation` as the runtime-facing request envelope:
210
213
 
211
214
  - `invocation.context` for request-scoped execution context
@@ -560,6 +563,7 @@ For backend-specific options, prefer the upstream concept directly inside `spec.
560
563
  - upstream LangChain v1 and DeepAgents concepts should be expressed as directly as possible in YAML
561
564
  - when a feature can be expressed in YAML, prefer YAML over expanding the public API
562
565
  - recovery, approvals, threads, runs, and events are runtime concepts, not backend escape hatches
566
+ - application task centers should be built on the existing store plus runtime ids instead of expanding the public runtime contract
563
567
  - new LangChain v1 or DeepAgents config should land in YAML mapping and tests before adding public runtime APIs
564
568
 
565
569
  In short, the product model stays stable while the execution semantics remain upstream-owned.
@@ -573,6 +577,8 @@ Primary exports:
573
577
  - `run`
574
578
  - `resolveApproval`
575
579
  - `subscribe`
580
+ - `listRuns`
581
+ - `getRun`
576
582
  - `listThreads`
577
583
  - `getThread`
578
584
  - `deleteThread`
package/README.zh.md CHANGED
@@ -68,6 +68,8 @@
68
68
  - `docs/upstream-feature-matrix.md`
69
69
  - `docs/product-boundary.md`
70
70
  - `docs/feature-checklist.md`
71
+ - `docs/long-term-memory.md`
72
+ - `docs/app-task-pattern.md`
71
73
 
72
74
  ## 为何需要它
73
75
 
@@ -204,6 +206,8 @@ const result = await run(runtime, {
204
206
 
205
207
  `run(runtime, { ... })` 会创建或延续持久化线程,并返回 `threadId`、`runId`、`state` 以及紧凑文本 `output`。更丰富的上游结果形态仍可通过 `outputContent`、`contentBlocks`、`structuredResponse` 等获得。
206
208
 
209
+ 如果产品需要 run 视角的操作界面,例如 review queue 或执行看板,可使用 `listRuns(runtime)` 与 `getRun(runtime, runId)`。
210
+
207
211
  将 `invocation` 作为面向运行时的请求信封:
208
212
 
209
213
  - `invocation.context`:请求级执行上下文
@@ -551,6 +555,7 @@ spec:
551
555
  - 应尽量在 YAML 中直接表达 LangChain v1 与 DeepAgents 的概念
552
556
  - 能用 YAML 表达的能力,优先 YAML 而非扩张公共 API
553
557
  - 恢复、审批、线程、运行与事件是运行时概念,不是后端逃生舱
558
+ - 应用里的 task center 应基于现有 store 与 runtime id 建模,而不是把 task 扩成公共运行时契约
554
559
  - 新的 LangChain v1 或 DeepAgents 配置应先落在 YAML 映射与测试中,再考虑公共运行时 API
555
560
 
556
561
  简言之:产品模型稳定,执行语义仍归上游。
@@ -564,6 +569,8 @@ spec:
564
569
  - `run`
565
570
  - `resolveApproval`
566
571
  - `subscribe`
572
+ - `listRuns`
573
+ - `getRun`
567
574
  - `listThreads`
568
575
  - `getThread`
569
576
  - `deleteThread`
package/dist/api.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ApprovalRecord, RunOptions, ResumeOptions, RuntimeAdapterOptions, ThreadSummary, ThreadRecord, WorkspaceLoadOptions } from "./contracts/types.js";
1
+ import type { ApprovalRecord, RunRecord, RunOptions, RunSummary, ResumeOptions, RuntimeAdapterOptions, ThreadSummary, ThreadRecord, WorkspaceLoadOptions } from "./contracts/types.js";
2
2
  import { AgentHarnessRuntime } from "./runtime/harness.js";
3
3
  import type { InventoryAgentRecord, InventorySkillRecord } from "./runtime/inventory.js";
4
4
  import type { RequirementAssessmentOptions } from "./runtime/skill-requirements.js";
@@ -13,7 +13,9 @@ export declare function createAgentHarness(workspaceRoot: string, options?: Crea
13
13
  export declare function run(runtime: AgentHarnessRuntime, options: RunOptions): Promise<import("./contracts/types.js").RunResult>;
14
14
  export declare function subscribe(runtime: AgentHarnessRuntime, listener: Parameters<AgentHarnessRuntime["subscribe"]>[0]): () => void;
15
15
  export declare function listThreads(runtime: AgentHarnessRuntime, filter?: Parameters<AgentHarnessRuntime["listThreads"]>[0]): Promise<ThreadSummary[]>;
16
+ export declare function listRuns(runtime: AgentHarnessRuntime, filter?: Parameters<AgentHarnessRuntime["listRuns"]>[0]): Promise<RunSummary[]>;
16
17
  export declare function getThread(runtime: AgentHarnessRuntime, threadId: string): Promise<ThreadRecord | null>;
18
+ export declare function getRun(runtime: AgentHarnessRuntime, runId: string): Promise<RunRecord | null>;
17
19
  export declare function deleteThread(runtime: AgentHarnessRuntime, threadId: string): Promise<boolean>;
18
20
  export declare function listApprovals(runtime: AgentHarnessRuntime, filter?: Parameters<AgentHarnessRuntime["listApprovals"]>[0]): Promise<ApprovalRecord[]>;
19
21
  export declare function getApproval(runtime: AgentHarnessRuntime, approvalId: string): Promise<ApprovalRecord | null>;
package/dist/api.js CHANGED
@@ -16,9 +16,15 @@ export function subscribe(runtime, listener) {
16
16
  export async function listThreads(runtime, filter) {
17
17
  return runtime.listThreads(filter);
18
18
  }
19
+ export async function listRuns(runtime, filter) {
20
+ return runtime.listRuns(filter);
21
+ }
19
22
  export async function getThread(runtime, threadId) {
20
23
  return runtime.getThread(threadId);
21
24
  }
25
+ export async function getRun(runtime, runId) {
26
+ return runtime.getRun(runId);
27
+ }
22
28
  export async function deleteThread(runtime, threadId) {
23
29
  return runtime.deleteThread(threadId);
24
30
  }
@@ -361,6 +361,7 @@ export type TranscriptMessage = {
361
361
  };
362
362
  export type ThreadRunRecord = {
363
363
  runId: string;
364
+ threadId: string;
364
365
  agentId: string;
365
366
  executionMode: string;
366
367
  adapterKind?: string;
@@ -370,6 +371,8 @@ export type ThreadRunRecord = {
370
371
  checkpointRef: string | null;
371
372
  resumable: boolean;
372
373
  };
374
+ export type RunSummary = ThreadRunRecord;
375
+ export type RunRecord = RunSummary;
373
376
  export type ThreadRecord = {
374
377
  threadId: string;
375
378
  entryAgentId: string;
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { AgentHarnessRuntime, createAgentHarness, createToolMcpServer, deleteThread, describeInventory, getApproval, getThread, listAgentSkills, listApprovals, listThreads, resolveApproval, run, serveToolsOverStdio, subscribe, stop, } from "./api.js";
1
+ export { AgentHarnessRuntime, createAgentHarness, createToolMcpServer, deleteThread, describeInventory, getApproval, getRun, getThread, listAgentSkills, listApprovals, listRuns, listThreads, resolveApproval, run, serveToolsOverStdio, subscribe, stop, } from "./api.js";
2
2
  export type { ToolMcpServerOptions } from "./mcp.js";
3
3
  export { tool } from "./tools.js";
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export { AgentHarnessRuntime, createAgentHarness, createToolMcpServer, deleteThread, describeInventory, getApproval, getThread, listAgentSkills, listApprovals, listThreads, resolveApproval, run, serveToolsOverStdio, subscribe, stop, } from "./api.js";
1
+ export { AgentHarnessRuntime, createAgentHarness, createToolMcpServer, deleteThread, describeInventory, getApproval, getRun, getThread, listAgentSkills, listApprovals, listRuns, listThreads, resolveApproval, run, serveToolsOverStdio, subscribe, stop, } from "./api.js";
2
2
  export { tool } from "./tools.js";
@@ -1 +1 @@
1
- export declare const AGENT_HARNESS_VERSION = "0.0.63";
1
+ export declare const AGENT_HARNESS_VERSION = "0.0.65";
@@ -1 +1 @@
1
- export const AGENT_HARNESS_VERSION = "0.0.63";
1
+ export const AGENT_HARNESS_VERSION = "0.0.65";
@@ -1,4 +1,4 @@
1
- import type { ArtifactListing, ArtifactRecord, DelegationRecord, HarnessEvent, InternalApprovalRecord, InvocationEnvelope, MessageContent, RunState, ThreadSummary, ThreadRunRecord, TranscriptMessage } from "../contracts/types.js";
1
+ import type { ArtifactListing, ArtifactRecord, DelegationRecord, HarnessEvent, InternalApprovalRecord, InvocationEnvelope, MessageContent, RunSummary, RunState, ThreadSummary, ThreadRunRecord, TranscriptMessage } from "../contracts/types.js";
2
2
  type ThreadMeta = {
3
3
  threadId: string;
4
4
  workspaceId: string;
@@ -73,6 +73,9 @@ export declare class FilePersistence {
73
73
  appendEvent(event: HarnessEvent): Promise<void>;
74
74
  listSessions(): Promise<ThreadSummary[]>;
75
75
  listRunIndexes(): Promise<RunIndexRecord[]>;
76
+ private readRunSummary;
77
+ listRuns(): Promise<RunSummary[]>;
78
+ getRun(runId: string): Promise<RunSummary | null>;
76
79
  getSession(threadId: string): Promise<ThreadSummary | null>;
77
80
  getThreadMeta(threadId: string): Promise<ThreadMeta | null>;
78
81
  listThreadRuns(threadId: string): Promise<ThreadRunRecord[]>;
@@ -190,6 +190,38 @@ export class FilePersistence {
190
190
  const entries = (await readdir(runIndexDir)).sort();
191
191
  return Promise.all(entries.map((entry) => readJson(path.join(runIndexDir, entry))));
192
192
  }
193
+ async readRunSummary(threadId, runId) {
194
+ const runDir = this.runDir(threadId, runId);
195
+ const [meta, lifecycle] = await Promise.all([
196
+ readJson(path.join(runDir, "meta.json")),
197
+ readJson(path.join(runDir, "lifecycle.json")),
198
+ ]);
199
+ return {
200
+ runId: meta.runId,
201
+ threadId: meta.threadId,
202
+ agentId: meta.agentId,
203
+ executionMode: meta.executionMode,
204
+ adapterKind: meta.adapterKind ?? meta.executionMode,
205
+ createdAt: meta.createdAt,
206
+ updatedAt: meta.updatedAt,
207
+ state: lifecycle.state,
208
+ checkpointRef: lifecycle.checkpointRef,
209
+ resumable: lifecycle.resumable,
210
+ };
211
+ }
212
+ async listRuns() {
213
+ const indexes = await this.listRunIndexes();
214
+ const runs = await Promise.all(indexes.map((record) => this.readRunSummary(record.threadId, record.runId)));
215
+ return runs.sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
216
+ }
217
+ async getRun(runId) {
218
+ const indexPath = this.runIndexPath(runId);
219
+ if (!(await fileExists(indexPath))) {
220
+ return null;
221
+ }
222
+ const index = await readJson(indexPath);
223
+ return this.readRunSummary(index.threadId, index.runId);
224
+ }
193
225
  async getSession(threadId) {
194
226
  const filePath = path.join(this.runRoot, "indexes", "threads", `${threadId}.json`);
195
227
  if (!(await fileExists(filePath))) {
@@ -221,24 +253,7 @@ export class FilePersistence {
221
253
  return [];
222
254
  }
223
255
  const runIds = (await readdir(runsDir)).sort();
224
- const runs = await Promise.all(runIds.map(async (runId) => {
225
- const runDir = this.runDir(threadId, runId);
226
- const [meta, lifecycle] = await Promise.all([
227
- readJson(path.join(runDir, "meta.json")),
228
- readJson(path.join(runDir, "lifecycle.json")),
229
- ]);
230
- return {
231
- runId: meta.runId,
232
- agentId: meta.agentId,
233
- executionMode: meta.executionMode,
234
- adapterKind: meta.adapterKind ?? meta.executionMode,
235
- createdAt: meta.createdAt,
236
- updatedAt: meta.updatedAt,
237
- state: lifecycle.state,
238
- checkpointRef: lifecycle.checkpointRef,
239
- resumable: lifecycle.resumable,
240
- };
241
- }));
256
+ const runs = await Promise.all(runIds.map(async (runId) => this.readRunSummary(threadId, runId)));
242
257
  return runs.sort((left, right) => right.createdAt.localeCompare(left.createdAt));
243
258
  }
244
259
  async listRunEvents(threadId, runId) {
@@ -1,4 +1,4 @@
1
- import type { ApprovalRecord, HarnessEvent, HarnessStreamItem, MessageContent, RunStartOptions, RestartConversationOptions, RuntimeAdapterOptions, ResumeOptions, RunOptions, RunResult, ThreadSummary, ThreadRecord, WorkspaceBundle } from "../contracts/types.js";
1
+ import type { ApprovalRecord, HarnessEvent, HarnessStreamItem, MessageContent, RunRecord, RunStartOptions, RestartConversationOptions, RuntimeAdapterOptions, ResumeOptions, RunOptions, RunResult, RunSummary, ThreadSummary, ThreadRecord, WorkspaceBundle } from "../contracts/types.js";
2
2
  import { type ToolMcpServerOptions } from "../mcp.js";
3
3
  import { type InventoryAgentRecord, type InventorySkillRecord } from "./inventory.js";
4
4
  import type { RequirementAssessmentOptions } from "./skill-requirements.js";
@@ -49,6 +49,12 @@ export declare class AgentHarnessRuntime {
49
49
  listThreads(filter?: {
50
50
  agentId?: string;
51
51
  }): Promise<ThreadSummary[]>;
52
+ listRuns(filter?: {
53
+ agentId?: string;
54
+ threadId?: string;
55
+ state?: RunSummary["state"];
56
+ }): Promise<RunSummary[]>;
57
+ getRun(runId: string): Promise<RunRecord | null>;
52
58
  private getSession;
53
59
  getThread(threadId: string): Promise<ThreadRecord | null>;
54
60
  listApprovals(filter?: {
@@ -234,6 +234,24 @@ export class AgentHarnessRuntime {
234
234
  }
235
235
  return threadSummaries.filter((thread) => thread.agentId === filter.agentId);
236
236
  }
237
+ async listRuns(filter) {
238
+ const runs = await this.persistence.listRuns();
239
+ return runs.filter((run) => {
240
+ if (filter?.agentId && run.agentId !== filter.agentId) {
241
+ return false;
242
+ }
243
+ if (filter?.threadId && run.threadId !== filter.threadId) {
244
+ return false;
245
+ }
246
+ if (filter?.state && run.state !== filter.state) {
247
+ return false;
248
+ }
249
+ return true;
250
+ });
251
+ }
252
+ async getRun(runId) {
253
+ return this.persistence.getRun(runId);
254
+ }
237
255
  async getSession(threadId) {
238
256
  return this.persistence.getSession(threadId);
239
257
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbotgo/agent-harness",
3
- "version": "0.0.64",
3
+ "version": "0.0.66",
4
4
  "description": "Workspace runtime for multi-agent applications",
5
5
  "type": "module",
6
6
  "packageManager": "npm@10.9.2",