@botbotgo/agent-harness 0.0.155 → 0.0.156
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 +25 -6
- package/README.zh.md +25 -6
- package/dist/api.d.ts +5 -2
- package/dist/api.js +9 -0
- package/dist/contracts/runtime.d.ts +31 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/runtime/harness/system/runtime-memory-records.d.ts +3 -0
- package/dist/runtime/harness/system/runtime-memory-records.js +48 -2
- package/dist/runtime/harness.d.ts +7 -1
- package/dist/runtime/harness.js +139 -2
- package/dist/workspace/object-loader.js +9 -44
- package/dist/workspace/yaml-object-reader.d.ts +0 -4
- package/dist/workspace/yaml-object-reader.js +4 -32
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -118,7 +118,7 @@ That means:
|
|
|
118
118
|
|
|
119
119
|
The runtime provides:
|
|
120
120
|
|
|
121
|
-
- `createAgentHarness(workspaceRoot)`, `run(...)`, `memorize(...)`, `recall(...)`, `resolveApproval(...)`, `subscribe(...)`, inspection methods, and `stop(...)`
|
|
121
|
+
- `createAgentHarness(workspaceRoot)`, `run(...)`, `memorize(...)`, `recall(...)`, `listMemories(...)`, `updateMemory(...)`, `removeMemory(...)`, `resolveApproval(...)`, `subscribe(...)`, inspection methods, and `stop(...)`
|
|
122
122
|
- YAML-defined workspace assembly for routing, models, tools, stores, backends, MCP, recovery, and maintenance
|
|
123
123
|
- backend-adapted execution with current LangChain v1 and DeepAgents adapters
|
|
124
124
|
- local `resources/tools/` `tool({...})` modules and `resources/skills/` discovery
|
|
@@ -414,10 +414,13 @@ const recalled = await recall(runtime, {
|
|
|
414
414
|
});
|
|
415
415
|
```
|
|
416
416
|
|
|
417
|
-
Use `memorize(...)` and `
|
|
417
|
+
Use `memorize(...)`, `recall(...)`, `listMemories(...)`, `updateMemory(...)`, and `removeMemory(...)` when an application needs a stable public runtime memory surface without importing internal `runtime/harness/system/*` modules.
|
|
418
418
|
|
|
419
419
|
- `memorize(...)` returns stable `MemoryRecord` and `MemoryDecision` results while leaving merge, review, archive, and storage layout runtime-managed
|
|
420
420
|
- `recall(...)` returns ranked `MemoryRecord` items filtered by runtime memory scope and kind
|
|
421
|
+
- `listMemories(...)` returns stable `MemoryRecord` items for inspection and admin workflows, defaulting to `active` records unless status filters are provided
|
|
422
|
+
- `updateMemory(...)` edits one durable memory record by `memoryId` without exposing internal store namespaces
|
|
423
|
+
- `removeMemory(...)` deletes one durable memory record by `memoryId` and rebuilds runtime-managed projections
|
|
421
424
|
- app-specific knowledge taxonomy, review UI, and admin surfaces still belong in the application layer
|
|
422
425
|
|
|
423
426
|
### Let The Runtime Route
|
|
@@ -467,6 +470,7 @@ The runtime event stream includes:
|
|
|
467
470
|
|
|
468
471
|
```ts
|
|
469
472
|
import {
|
|
473
|
+
deleteSession,
|
|
470
474
|
getSession,
|
|
471
475
|
getApproval,
|
|
472
476
|
listSessions,
|
|
@@ -485,6 +489,10 @@ if (approval) {
|
|
|
485
489
|
decision: "approve",
|
|
486
490
|
});
|
|
487
491
|
}
|
|
492
|
+
|
|
493
|
+
if (session && session.currentState === "completed") {
|
|
494
|
+
await deleteSession(runtime, session.sessionId);
|
|
495
|
+
}
|
|
488
496
|
```
|
|
489
497
|
|
|
490
498
|
These methods return runtime-facing records, not raw checkpoint or backend objects.
|
|
@@ -548,6 +556,13 @@ Core workspace files:
|
|
|
548
556
|
- `resources/tools/`
|
|
549
557
|
- `resources/skills/`
|
|
550
558
|
|
|
559
|
+
Discovery rules:
|
|
560
|
+
|
|
561
|
+
- every YAML document under `config/**` is discovered recursively; filenames and subfolders are organizational only
|
|
562
|
+
- YAML object semantics come from `kind`, `metadata.name` or `id`, and object content rather than the file path
|
|
563
|
+
- local tools are auto-discovered from `resources/tools/**/*.js|*.mjs|*.cjs` when they export `tool({...})`
|
|
564
|
+
- skills are auto-discovered from `resources/skills/**/SKILL.md`
|
|
565
|
+
|
|
551
566
|
Workspace-local tool modules in `resources/tools/` should be exported with `tool({...})`.
|
|
552
567
|
Any other local module shape is not supported, and unsupported shapes are rejected at load time.
|
|
553
568
|
|
|
@@ -563,7 +578,7 @@ There are three main configuration layers:
|
|
|
563
578
|
|
|
564
579
|
- runtime policy in `config/runtime/workspace.yaml`
|
|
565
580
|
- reusable object catalogs in `config/catalogs/*.yaml`
|
|
566
|
-
- agent assembly in `config
|
|
581
|
+
- agent assembly in `config/**/*.yaml`
|
|
567
582
|
|
|
568
583
|
### Backend Guidance
|
|
569
584
|
|
|
@@ -633,7 +648,7 @@ Use this file for shared bootstrap memory loaded at agent construction time.
|
|
|
633
648
|
|
|
634
649
|
Keep stable project context here. Treat it as startup context, not mutable long-term memory.
|
|
635
650
|
|
|
636
|
-
### `config
|
|
651
|
+
### Models Catalogs In `config/**`
|
|
637
652
|
|
|
638
653
|
Use named chat-model presets:
|
|
639
654
|
|
|
@@ -649,7 +664,9 @@ spec:
|
|
|
649
664
|
|
|
650
665
|
These load as `model/default`.
|
|
651
666
|
|
|
652
|
-
|
|
667
|
+
You can place `kind: Models` catalogs anywhere under `config/`; `config/catalogs/models.yaml` is only the recommended layout.
|
|
668
|
+
|
|
669
|
+
### Embedding Model Catalogs In `config/**`
|
|
653
670
|
|
|
654
671
|
Use named embedding-model presets for retrieval-oriented tools.
|
|
655
672
|
|
|
@@ -740,10 +757,12 @@ spec:
|
|
|
740
757
|
|
|
741
758
|
`spec[].kind` can be omitted here; catalog entries default to `McpServer`.
|
|
742
759
|
|
|
743
|
-
### `config
|
|
760
|
+
### Agents In `config/**`
|
|
744
761
|
|
|
745
762
|
Agents always use `kind: Agent` plus `spec.backend`.
|
|
746
763
|
|
|
764
|
+
Agent YAML can live anywhere under `config/`; `config/agents/*.yaml` is the recommended layout, not a loader requirement.
|
|
765
|
+
|
|
747
766
|
Use two sections:
|
|
748
767
|
|
|
749
768
|
- `spec.runtime` for harness-owned runtime placement such as `spec.runtime.runRoot`
|
package/README.zh.md
CHANGED
|
@@ -118,7 +118,7 @@ AI 让 agent 逻辑、工具调用和工作流代码更容易生成,真正更
|
|
|
118
118
|
|
|
119
119
|
运行时提供:
|
|
120
120
|
|
|
121
|
-
- `createAgentHarness(workspaceRoot)`、`run(...)`、`memorize(...)`、`recall(...)`、`resolveApproval(...)`、`subscribe(...)`、各类查询方法,以及 `stop(...)`
|
|
121
|
+
- `createAgentHarness(workspaceRoot)`、`run(...)`、`memorize(...)`、`recall(...)`、`listMemories(...)`、`updateMemory(...)`、`removeMemory(...)`、`resolveApproval(...)`、`subscribe(...)`、各类查询方法,以及 `stop(...)`
|
|
122
122
|
- 以 YAML 描述的工作区装配:路由、模型、工具、存储、后端、MCP、恢复与维护等
|
|
123
123
|
- 通过适配器对接当前的 LangChain v1 与 DeepAgents 执行
|
|
124
124
|
- 本地 `resources/tools/` 中 `tool({...})` 工具模块与 `resources/skills/` 的发现
|
|
@@ -386,10 +386,13 @@ const recalled = await recall(runtime, {
|
|
|
386
386
|
});
|
|
387
387
|
```
|
|
388
388
|
|
|
389
|
-
当应用需要稳定的公开 runtime memory 接口,而不想依赖内部 `runtime/harness/system/*` 模块时,使用 `memorize(...)` 与 `
|
|
389
|
+
当应用需要稳定的公开 runtime memory 接口,而不想依赖内部 `runtime/harness/system/*` 模块时,使用 `memorize(...)`、`recall(...)`、`listMemories(...)`、`updateMemory(...)` 与 `removeMemory(...)`。
|
|
390
390
|
|
|
391
391
|
- `memorize(...)` 返回稳定的 `MemoryRecord` 与 `MemoryDecision` 结果,而 merge、review、archive 与存储布局仍由 runtime 内部托管
|
|
392
392
|
- `recall(...)` 返回按相关性排序、并按 scope / kind 过滤后的 `MemoryRecord`
|
|
393
|
+
- `listMemories(...)` 返回稳定的 `MemoryRecord`,用于 inspection / admin 场景;如果不传 status 过滤器,默认只返回 `active`
|
|
394
|
+
- `updateMemory(...)` 通过 `memoryId` 更新单条 durable memory,而不暴露内部 store namespace
|
|
395
|
+
- `removeMemory(...)` 通过 `memoryId` 删除单条 durable memory,并重建运行时托管的 projection
|
|
393
396
|
- 业务知识分类、review UI 与管理后台仍应留在应用层
|
|
394
397
|
|
|
395
398
|
### 由运行时路由
|
|
@@ -439,6 +442,7 @@ const result = await run(runtime, {
|
|
|
439
442
|
|
|
440
443
|
```ts
|
|
441
444
|
import {
|
|
445
|
+
deleteSession,
|
|
442
446
|
getApproval,
|
|
443
447
|
getSession,
|
|
444
448
|
listApprovals,
|
|
@@ -457,6 +461,10 @@ if (approval) {
|
|
|
457
461
|
decision: "approve",
|
|
458
462
|
});
|
|
459
463
|
}
|
|
464
|
+
|
|
465
|
+
if (session && session.currentState === "completed") {
|
|
466
|
+
await deleteSession(runtime, session.sessionId);
|
|
467
|
+
}
|
|
460
468
|
```
|
|
461
469
|
|
|
462
470
|
这些方法返回面向运行时的记录,而非原始 checkpoint 或后端对象。
|
|
@@ -520,6 +528,13 @@ await stop(runtime);
|
|
|
520
528
|
- `resources/tools/`
|
|
521
529
|
- `resources/skills/`
|
|
522
530
|
|
|
531
|
+
发现规则:
|
|
532
|
+
|
|
533
|
+
- `config/**` 下的所有 YAML 文档都会被递归发现;文件名与子目录只用于组织,不参与语义
|
|
534
|
+
- YAML 对象语义由 `kind`、`metadata.name` 或 `id` 以及对象内容决定,而不是由文件路径决定
|
|
535
|
+
- 本地工具会从 `resources/tools/**/*.js|*.mjs|*.cjs` 中自动发现,前提是模块导出 `tool({...})`
|
|
536
|
+
- skills 会从 `resources/skills/**/SKILL.md` 自动发现
|
|
537
|
+
|
|
523
538
|
`resources/tools/` 下的工作区本地工具模块应统一用 `tool({...})` 导出。
|
|
524
539
|
不支持历史/兼容写法,任何不带该导出形式的工具模块都会在工作区加载时被拒绝。
|
|
525
540
|
|
|
@@ -529,7 +544,7 @@ await stop(runtime);
|
|
|
529
544
|
- agent 再按名字白名单选择 tools 与 skills
|
|
530
545
|
- `config/runtime/workspace.yaml` 中的运行时策略
|
|
531
546
|
- `config/catalogs/*.yaml` 中的可复用对象目录
|
|
532
|
-
- `config
|
|
547
|
+
- `config/**/*.yaml` 中的 agent 装配
|
|
533
548
|
|
|
534
549
|
### Backend 选择建议
|
|
535
550
|
|
|
@@ -602,7 +617,7 @@ spec:
|
|
|
602
617
|
|
|
603
618
|
在此放置稳定的项目上下文;视为启动上下文,而非可变长期记忆。
|
|
604
619
|
|
|
605
|
-
### `config
|
|
620
|
+
### `config/**` 下的 Models Catalog
|
|
606
621
|
|
|
607
622
|
命名聊天模型预设:
|
|
608
623
|
|
|
@@ -618,7 +633,9 @@ spec:
|
|
|
618
633
|
|
|
619
634
|
加载为 `model/default`。
|
|
620
635
|
|
|
621
|
-
|
|
636
|
+
`kind: Models` catalog 可以放在 `config/` 下任意位置;`config/catalogs/models.yaml` 只是推荐布局。
|
|
637
|
+
|
|
638
|
+
### `config/**` 下的 Embedding Model Catalog
|
|
622
639
|
|
|
623
640
|
面向检索类工具的命名嵌入模型预设。
|
|
624
641
|
|
|
@@ -707,10 +724,12 @@ spec:
|
|
|
707
724
|
|
|
708
725
|
这里可以省略 `spec[].kind`;catalog 项会默认按 `McpServer` 处理。
|
|
709
726
|
|
|
710
|
-
### `config
|
|
727
|
+
### `config/**` 下的 Agent YAML
|
|
711
728
|
|
|
712
729
|
Agent 始终使用 `kind: Agent` 以及 `spec.backend`。
|
|
713
730
|
|
|
731
|
+
Agent YAML 可以放在 `config/` 下任意位置;`config/agents/*.yaml` 是推荐布局,不是 loader 的硬性要求。
|
|
732
|
+
|
|
714
733
|
两个区块:
|
|
715
734
|
|
|
716
735
|
- `spec.runtime`:harness 侧运行时放置,例如 `spec.runtime.runRoot`
|
package/dist/api.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type { CancelOptions, InvocationEnvelope, MemorizeInput, MemorizeResult, MessageContent, RecallInput, RecallResult, RequestRecord, RequestSummary, ResumeOptions, RunDecisionOptions, RunResult, RunStartOptions, RuntimeHealthSnapshot, RuntimeAdapterOptions, SessionRecord, SessionSummary, WorkspaceLoadOptions } from "./contracts/types.js";
|
|
1
|
+
import type { CancelOptions, InvocationEnvelope, ListMemoriesInput, ListMemoriesResult, MemoryRecord, MemorizeInput, MemorizeResult, MessageContent, RecallInput, RecallResult, RemoveMemoryInput, RequestRecord, RequestSummary, ResumeOptions, RunDecisionOptions, RunResult, RunStartOptions, RuntimeHealthSnapshot, RuntimeAdapterOptions, SessionRecord, SessionSummary, UpdateMemoryInput, WorkspaceLoadOptions } from "./contracts/types.js";
|
|
2
2
|
import { AgentHarnessRuntime } from "./runtime/harness.js";
|
|
3
3
|
import type { InventoryAgentRecord, InventorySkillRecord } from "./runtime/harness/system/inventory.js";
|
|
4
4
|
import type { RequirementAssessmentOptions } from "./runtime/harness/system/skill-requirements.js";
|
|
5
5
|
import type { ToolMcpServerOptions } from "./mcp.js";
|
|
6
6
|
export { AgentHarnessRuntime } from "./runtime/harness.js";
|
|
7
7
|
export { createUpstreamTimelineReducer } from "./upstream-events.js";
|
|
8
|
-
export type { MemoryDecision, MemoryKind, MemoryRecord, MemoryScope, MemorizeInput, MemorizeResult, RecallInput, RecallResult, } from "./contracts/types.js";
|
|
8
|
+
export type { ListMemoriesInput, ListMemoriesResult, MemoryDecision, MemoryKind, MemoryRecord, MemoryScope, MemorizeInput, MemorizeResult, RecallInput, RecallResult, RemoveMemoryInput, UpdateMemoryInput, } from "./contracts/types.js";
|
|
9
9
|
type PublicApprovalRecord = {
|
|
10
10
|
approvalId: string;
|
|
11
11
|
pendingActionId: string;
|
|
@@ -57,6 +57,9 @@ export declare function normalizeUserChatInput(input: UserChatInput, options?: N
|
|
|
57
57
|
export declare function run(runtime: AgentHarnessRuntime, options: PublicRunOptions): Promise<PublicRunResult>;
|
|
58
58
|
export declare function memorize(runtime: AgentHarnessRuntime, input: MemorizeInput): Promise<MemorizeResult>;
|
|
59
59
|
export declare function recall(runtime: AgentHarnessRuntime, input: RecallInput): Promise<RecallResult>;
|
|
60
|
+
export declare function listMemories(runtime: AgentHarnessRuntime, input?: ListMemoriesInput): Promise<ListMemoriesResult>;
|
|
61
|
+
export declare function updateMemory(runtime: AgentHarnessRuntime, input: UpdateMemoryInput): Promise<MemoryRecord>;
|
|
62
|
+
export declare function removeMemory(runtime: AgentHarnessRuntime, input: RemoveMemoryInput): Promise<MemoryRecord>;
|
|
60
63
|
export declare function subscribe(runtime: AgentHarnessRuntime, listener: Parameters<AgentHarnessRuntime["subscribe"]>[0]): () => void;
|
|
61
64
|
export declare function listSessions(runtime: AgentHarnessRuntime, filter?: Parameters<AgentHarnessRuntime["listThreads"]>[0]): Promise<SessionSummary[]>;
|
|
62
65
|
export declare function listRequests(runtime: AgentHarnessRuntime, filter?: {
|
package/dist/api.js
CHANGED
|
@@ -134,6 +134,15 @@ export async function memorize(runtime, input) {
|
|
|
134
134
|
export async function recall(runtime, input) {
|
|
135
135
|
return runtime.recall(input);
|
|
136
136
|
}
|
|
137
|
+
export async function listMemories(runtime, input = {}) {
|
|
138
|
+
return runtime.listMemories(input);
|
|
139
|
+
}
|
|
140
|
+
export async function updateMemory(runtime, input) {
|
|
141
|
+
return runtime.updateMemory(input);
|
|
142
|
+
}
|
|
143
|
+
export async function removeMemory(runtime, input) {
|
|
144
|
+
return runtime.removeMemory(input);
|
|
145
|
+
}
|
|
137
146
|
export function subscribe(runtime, listener) {
|
|
138
147
|
return runtime.subscribe(listener);
|
|
139
148
|
}
|
|
@@ -195,6 +195,37 @@ export type RecallInput = {
|
|
|
195
195
|
export type RecallResult = {
|
|
196
196
|
items: MemoryRecord[];
|
|
197
197
|
};
|
|
198
|
+
export type ListMemoriesInput = {
|
|
199
|
+
scopes?: MemoryScope[];
|
|
200
|
+
kinds?: MemoryKind[];
|
|
201
|
+
status?: MemoryRecordStatus[];
|
|
202
|
+
threadId?: string;
|
|
203
|
+
agentId?: string;
|
|
204
|
+
workspaceId?: string;
|
|
205
|
+
userId?: string;
|
|
206
|
+
projectId?: string;
|
|
207
|
+
limit?: number;
|
|
208
|
+
};
|
|
209
|
+
export type ListMemoriesResult = {
|
|
210
|
+
items: MemoryRecord[];
|
|
211
|
+
};
|
|
212
|
+
export type UpdateMemoryInput = {
|
|
213
|
+
memoryId: string;
|
|
214
|
+
content?: string;
|
|
215
|
+
summary?: string;
|
|
216
|
+
status?: MemoryRecordStatus;
|
|
217
|
+
confidence?: number;
|
|
218
|
+
expiresAt?: string | null;
|
|
219
|
+
sourceType?: string;
|
|
220
|
+
sourceRefs?: string[];
|
|
221
|
+
tags?: string[];
|
|
222
|
+
observedAt?: string;
|
|
223
|
+
lastConfirmedAt?: string;
|
|
224
|
+
provenance?: Record<string, unknown>;
|
|
225
|
+
};
|
|
226
|
+
export type RemoveMemoryInput = {
|
|
227
|
+
memoryId: string;
|
|
228
|
+
};
|
|
198
229
|
/**
|
|
199
230
|
* Operator-facing projection of tool execution policy already compiled into a binding.
|
|
200
231
|
* This summarizes existing timeout, retry, validation, and retry-safety hints without
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { AgentHarnessRuntime, cancelRun, createAgentHarness, createUpstreamTimelineReducer, createToolMcpServer, deleteSession, describeInventory, getAgent, getApproval, getRequest, getHealth, getSession, listAgentSkills, listApprovals, listRequests, listSessions, memorize, normalizeUserChatInput, recall, resolveApproval, run, serveToolsOverStdio, subscribe, stop, } from "./api.js";
|
|
2
|
-
export type { MemoryDecision, MemoryKind, MemoryRecord, MemoryScope, MemorizeInput, MemorizeResult, NormalizeUserChatInputOptions, RecallInput, RecallResult, UserChatInput, UserChatMessage, } from "./api.js";
|
|
1
|
+
export { AgentHarnessRuntime, cancelRun, createAgentHarness, createUpstreamTimelineReducer, createToolMcpServer, deleteSession, describeInventory, getAgent, getApproval, getRequest, getHealth, listMemories, getSession, listAgentSkills, listApprovals, listRequests, listSessions, memorize, normalizeUserChatInput, recall, removeMemory, resolveApproval, run, serveToolsOverStdio, subscribe, stop, updateMemory, } from "./api.js";
|
|
2
|
+
export type { ListMemoriesInput, ListMemoriesResult, MemoryDecision, MemoryKind, MemoryRecord, MemoryScope, MemorizeInput, MemorizeResult, NormalizeUserChatInputOptions, RecallInput, RecallResult, RemoveMemoryInput, UpdateMemoryInput, UserChatInput, UserChatMessage, } from "./api.js";
|
|
3
3
|
export type { ToolMcpServerOptions } from "./mcp.js";
|
|
4
4
|
export { tool } from "./tools.js";
|
|
5
5
|
export type { UpstreamTimelineProjection, UpstreamTimelineReducer } from "./upstream-events.js";
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { AgentHarnessRuntime, cancelRun, createAgentHarness, createUpstreamTimelineReducer, createToolMcpServer, deleteSession, describeInventory, getAgent, getApproval, getRequest, getHealth, getSession, listAgentSkills, listApprovals, listRequests, listSessions, memorize, normalizeUserChatInput, recall, resolveApproval, run, serveToolsOverStdio, subscribe, stop, } from "./api.js";
|
|
1
|
+
export { AgentHarnessRuntime, cancelRun, createAgentHarness, createUpstreamTimelineReducer, createToolMcpServer, deleteSession, describeInventory, getAgent, getApproval, getRequest, getHealth, listMemories, getSession, listAgentSkills, listApprovals, listRequests, listSessions, memorize, normalizeUserChatInput, recall, removeMemory, resolveApproval, run, serveToolsOverStdio, subscribe, stop, updateMemory, } from "./api.js";
|
|
2
2
|
export { tool } from "./tools.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export declare const AGENT_HARNESS_VERSION = "0.0.155";
|
package/dist/package-version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export const AGENT_HARNESS_VERSION = "0.0.155";
|
|
@@ -15,6 +15,9 @@ export declare function renderMemoryRecordsMarkdown(title: string, records: Memo
|
|
|
15
15
|
export declare function rebuildStructuredMemoryProjections(store: StoreLike, namespace: string[], title: string, scope: MemoryScope, maxEntries: number): Promise<void>;
|
|
16
16
|
export declare function listMemoryRecordsForScopes(store: StoreLike, scopes: MemoryScope[]): Promise<MemoryRecord[]>;
|
|
17
17
|
export declare function getMemoryRecord(store: StoreLike, scope: MemoryScope, recordId: string): Promise<MemoryRecord | null>;
|
|
18
|
+
export declare function findMemoryRecordById(store: StoreLike, recordId: string): Promise<MemoryRecord | null>;
|
|
19
|
+
export declare function updateMemoryRecord(store: StoreLike, record: MemoryRecord, updatedAt: string): Promise<MemoryRecord>;
|
|
20
|
+
export declare function removeMemoryRecord(store: StoreLike, scope: MemoryScope, recordId: string): Promise<MemoryRecord | null>;
|
|
18
21
|
export declare function persistStructuredMemoryRecords(options: PersistMemoryRecordsOptions): Promise<{
|
|
19
22
|
records: MemoryRecord[];
|
|
20
23
|
decisions: MemoryDecision[];
|
|
@@ -34,6 +34,12 @@ function createCanonicalKey(candidate, kind, scope) {
|
|
|
34
34
|
function buildScopeNamespace(scope) {
|
|
35
35
|
return ["memories", "records", scope];
|
|
36
36
|
}
|
|
37
|
+
function buildCanonicalIndexNamespace(scope) {
|
|
38
|
+
return ["memories", "indexes", "canonical", scope];
|
|
39
|
+
}
|
|
40
|
+
function buildSourceRefIndexNamespace(scope) {
|
|
41
|
+
return ["memories", "indexes", "source-ref", scope];
|
|
42
|
+
}
|
|
37
43
|
function normalizeTextForCompare(value) {
|
|
38
44
|
return value.toLowerCase().replace(/\s+/g, " ").trim();
|
|
39
45
|
}
|
|
@@ -312,7 +318,7 @@ function evaluateDecision(existing, incoming, recordedAt) {
|
|
|
312
318
|
async function putRecordWithIndexes(store, record, updatedAt) {
|
|
313
319
|
const canonicalKeyId = createFingerprint(record.canonicalKey);
|
|
314
320
|
await store.put(buildScopeNamespace(record.scope), `${record.id}.json`, record);
|
|
315
|
-
await store.put(
|
|
321
|
+
await store.put(buildCanonicalIndexNamespace(record.scope), `${canonicalKeyId}-${record.id}.json`, {
|
|
316
322
|
canonicalKey: record.canonicalKey,
|
|
317
323
|
recordId: record.id,
|
|
318
324
|
scope: record.scope,
|
|
@@ -321,7 +327,7 @@ async function putRecordWithIndexes(store, record, updatedAt) {
|
|
|
321
327
|
});
|
|
322
328
|
await Promise.all(record.sourceRefs.map((sourceRef) => {
|
|
323
329
|
const sourceRefId = createFingerprint(sourceRef);
|
|
324
|
-
return store.put(
|
|
330
|
+
return store.put(buildSourceRefIndexNamespace(record.scope), `${sourceRefId}-${record.id}.json`, {
|
|
325
331
|
sourceRef,
|
|
326
332
|
recordId: record.id,
|
|
327
333
|
scope: record.scope,
|
|
@@ -384,6 +390,46 @@ export async function getMemoryRecord(store, scope, recordId) {
|
|
|
384
390
|
const candidate = record;
|
|
385
391
|
return typeof candidate.id === "string" && typeof candidate.content === "string" ? candidate : null;
|
|
386
392
|
}
|
|
393
|
+
export async function findMemoryRecordById(store, recordId) {
|
|
394
|
+
for (const scope of MEMORY_SCOPES) {
|
|
395
|
+
const record = await getMemoryRecord(store, scope, recordId);
|
|
396
|
+
if (record) {
|
|
397
|
+
return record;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
return null;
|
|
401
|
+
}
|
|
402
|
+
async function deleteRecordIndexes(store, record) {
|
|
403
|
+
const [canonicalEntries, sourceRefEntries] = await Promise.all([
|
|
404
|
+
store.search(buildCanonicalIndexNamespace(record.scope)),
|
|
405
|
+
store.search(buildSourceRefIndexNamespace(record.scope)),
|
|
406
|
+
]);
|
|
407
|
+
await Promise.all([
|
|
408
|
+
...canonicalEntries
|
|
409
|
+
.filter((entry) => entry.value?.recordId === record.id)
|
|
410
|
+
.map((entry) => store.delete(entry.namespace, entry.key)),
|
|
411
|
+
...sourceRefEntries
|
|
412
|
+
.filter((entry) => entry.value?.recordId === record.id)
|
|
413
|
+
.map((entry) => store.delete(entry.namespace, entry.key)),
|
|
414
|
+
]);
|
|
415
|
+
}
|
|
416
|
+
export async function updateMemoryRecord(store, record, updatedAt) {
|
|
417
|
+
const existing = await getMemoryRecord(store, record.scope, record.id);
|
|
418
|
+
if (existing) {
|
|
419
|
+
await deleteRecordIndexes(store, existing);
|
|
420
|
+
}
|
|
421
|
+
await putRecordWithIndexes(store, record, updatedAt);
|
|
422
|
+
return record;
|
|
423
|
+
}
|
|
424
|
+
export async function removeMemoryRecord(store, scope, recordId) {
|
|
425
|
+
const existing = await getMemoryRecord(store, scope, recordId);
|
|
426
|
+
if (!existing) {
|
|
427
|
+
return null;
|
|
428
|
+
}
|
|
429
|
+
await deleteRecordIndexes(store, existing);
|
|
430
|
+
await store.delete(buildScopeNamespace(scope), `${recordId}.json`);
|
|
431
|
+
return existing;
|
|
432
|
+
}
|
|
387
433
|
export async function persistStructuredMemoryRecords(options) {
|
|
388
434
|
const existingRecords = await listStoredRecords(options.store);
|
|
389
435
|
const persistedRecords = [];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ApprovalRecord, CancelOptions, HarnessEvent, HarnessStreamItem, RuntimeHealthSnapshot, MessageContent, RunRecord, RunStartOptions, RestartConversationOptions, RuntimeAdapterOptions, ResumeOptions, RunOptions, RunResult, RunSummary, MemorizeInput, MemorizeResult, RecallInput, RecallResult, ThreadSummary, ThreadRecord, WorkspaceBundle } from "../contracts/types.js";
|
|
1
|
+
import type { ApprovalRecord, CancelOptions, HarnessEvent, HarnessStreamItem, RuntimeHealthSnapshot, ListMemoriesInput, ListMemoriesResult, MessageContent, RemoveMemoryInput, RunRecord, RunStartOptions, RestartConversationOptions, RuntimeAdapterOptions, ResumeOptions, RunOptions, RunResult, RunSummary, MemoryRecord, MemorizeInput, MemorizeResult, RecallInput, RecallResult, UpdateMemoryInput, ThreadSummary, ThreadRecord, WorkspaceBundle } from "../contracts/types.js";
|
|
2
2
|
import { type ToolMcpServerOptions } from "../mcp.js";
|
|
3
3
|
import { type InventoryAgentRecord, type InventorySkillRecord } from "./harness/system/inventory.js";
|
|
4
4
|
import type { RequirementAssessmentOptions } from "./harness/system/skill-requirements.js";
|
|
@@ -70,6 +70,9 @@ export declare class AgentHarnessRuntime {
|
|
|
70
70
|
}): Promise<RunSummary[]>;
|
|
71
71
|
memorize(input: MemorizeInput): Promise<MemorizeResult>;
|
|
72
72
|
recall(input: RecallInput): Promise<RecallResult>;
|
|
73
|
+
listMemories(input?: ListMemoriesInput): Promise<ListMemoriesResult>;
|
|
74
|
+
updateMemory(input: UpdateMemoryInput): Promise<MemoryRecord>;
|
|
75
|
+
removeMemory(input: RemoveMemoryInput): Promise<MemoryRecord>;
|
|
73
76
|
getRun(runId: string): Promise<RunRecord | null>;
|
|
74
77
|
private getSession;
|
|
75
78
|
getThread(threadId: string): Promise<ThreadRecord | null>;
|
|
@@ -102,6 +105,8 @@ export declare class AgentHarnessRuntime {
|
|
|
102
105
|
private invokeWithHistory;
|
|
103
106
|
private resolveMemoryNamespace;
|
|
104
107
|
private getWorkspaceId;
|
|
108
|
+
private summarizeMemoryContent;
|
|
109
|
+
private matchesMemoryFilters;
|
|
105
110
|
private resolveRecallScopes;
|
|
106
111
|
private matchesRecallScope;
|
|
107
112
|
private getMemoryScopeBoost;
|
|
@@ -113,6 +118,7 @@ export declare class AgentHarnessRuntime {
|
|
|
113
118
|
private createMem0MemoryRecord;
|
|
114
119
|
private rankRecallCandidates;
|
|
115
120
|
private rebuildRuntimeMemoryVectorIndex;
|
|
121
|
+
private refreshStructuredMemoryScope;
|
|
116
122
|
private buildRuntimeMemoryContext;
|
|
117
123
|
private persistRuntimeMemoryCandidates;
|
|
118
124
|
private persistStructuredMemoryCandidates;
|
package/dist/runtime/harness.js
CHANGED
|
@@ -31,7 +31,7 @@ import { createDefaultHealthSnapshot, isInventoryEnabled, isThreadMemorySyncEnab
|
|
|
31
31
|
import { Mem0IngestionSync, Mem0SemanticRecall, readMem0RuntimeConfig, } from "./harness/system/mem0-ingestion-sync.js";
|
|
32
32
|
import { createRuntimeMemoryManager, RuntimeMemoryFormationSync, readRuntimeMemoryFormationConfig, } from "./harness/system/runtime-memory-manager.js";
|
|
33
33
|
import { renderMemoryCandidatesMarkdown } from "./harness/system/runtime-memory-candidates.js";
|
|
34
|
-
import { getMemoryRecord, listMemoryRecordsForScopes, persistStructuredMemoryRecords, } from "./harness/system/runtime-memory-records.js";
|
|
34
|
+
import { findMemoryRecordById, getMemoryRecord, listMemoryRecordsForScopes, persistStructuredMemoryRecords, removeMemoryRecord, updateMemoryRecord, } from "./harness/system/runtime-memory-records.js";
|
|
35
35
|
import { consolidateStructuredMemoryScope } from "./harness/system/runtime-memory-consolidation.js";
|
|
36
36
|
import { normalizeLangMemMemoryKind, readRuntimeMemoryMaintenanceConfig, readRuntimeMemoryPolicyConfig, resolveMemoryNamespace, scoreMemoryText, } from "./harness/system/runtime-memory-policy.js";
|
|
37
37
|
import { resolveRuntimeAdapterOptions } from "./support/runtime-adapter-options.js";
|
|
@@ -361,6 +361,98 @@ export class AgentHarnessRuntime {
|
|
|
361
361
|
.map(({ record }) => record);
|
|
362
362
|
return { items };
|
|
363
363
|
}
|
|
364
|
+
async listMemories(input = {}) {
|
|
365
|
+
const binding = this.defaultRuntimeEntryBinding;
|
|
366
|
+
if (!binding) {
|
|
367
|
+
throw new Error("listMemories requires a runtime entry binding.");
|
|
368
|
+
}
|
|
369
|
+
const workspaceId = this.getWorkspaceId(binding);
|
|
370
|
+
const scopes = Array.isArray(input.scopes) && input.scopes.length > 0
|
|
371
|
+
? Array.from(new Set(input.scopes))
|
|
372
|
+
: ["thread", "agent", "workspace", "user", "project"];
|
|
373
|
+
const kinds = input.kinds?.length ? new Set(input.kinds) : null;
|
|
374
|
+
const statuses = input.status?.length ? new Set(input.status) : new Set(["active"]);
|
|
375
|
+
const limit = typeof input.limit === "number" && Number.isInteger(input.limit) && input.limit > 0
|
|
376
|
+
? input.limit
|
|
377
|
+
: Number.POSITIVE_INFINITY;
|
|
378
|
+
const items = (await listMemoryRecordsForScopes(this.runtimeMemoryStore, scopes))
|
|
379
|
+
.filter((record) => statuses.has(record.status))
|
|
380
|
+
.filter((record) => !kinds || kinds.has(record.kind))
|
|
381
|
+
.filter((record) => this.matchesMemoryFilters(record, {
|
|
382
|
+
threadId: input.threadId,
|
|
383
|
+
agentId: input.agentId,
|
|
384
|
+
workspaceId: input.workspaceId ?? workspaceId,
|
|
385
|
+
userId: input.userId,
|
|
386
|
+
projectId: input.projectId,
|
|
387
|
+
}))
|
|
388
|
+
.sort((left, right) => right.lastConfirmedAt.localeCompare(left.lastConfirmedAt))
|
|
389
|
+
.slice(0, limit);
|
|
390
|
+
return { items };
|
|
391
|
+
}
|
|
392
|
+
async updateMemory(input) {
|
|
393
|
+
const binding = this.defaultRuntimeEntryBinding;
|
|
394
|
+
if (!binding) {
|
|
395
|
+
throw new Error("updateMemory requires a runtime entry binding.");
|
|
396
|
+
}
|
|
397
|
+
if (typeof input.memoryId !== "string" || input.memoryId.trim().length === 0) {
|
|
398
|
+
throw new Error("updateMemory requires a non-empty memoryId.");
|
|
399
|
+
}
|
|
400
|
+
const existing = await findMemoryRecordById(this.runtimeMemoryStore, input.memoryId.trim());
|
|
401
|
+
if (!existing) {
|
|
402
|
+
throw new Error(`Memory record not found: ${input.memoryId}`);
|
|
403
|
+
}
|
|
404
|
+
const updatedAt = new Date().toISOString();
|
|
405
|
+
const nextContent = typeof input.content === "string"
|
|
406
|
+
? input.content.trim()
|
|
407
|
+
: existing.content;
|
|
408
|
+
if (nextContent.length === 0) {
|
|
409
|
+
throw new Error("updateMemory requires content to remain non-empty.");
|
|
410
|
+
}
|
|
411
|
+
const next = {
|
|
412
|
+
...existing,
|
|
413
|
+
content: nextContent,
|
|
414
|
+
summary: typeof input.summary === "string"
|
|
415
|
+
? input.summary.trim() || this.summarizeMemoryContent(nextContent)
|
|
416
|
+
: (typeof input.content === "string" ? this.summarizeMemoryContent(nextContent) : existing.summary),
|
|
417
|
+
status: input.status ?? existing.status,
|
|
418
|
+
confidence: typeof input.confidence === "number" ? Math.max(0, Math.min(1, input.confidence)) : existing.confidence,
|
|
419
|
+
expiresAt: input.expiresAt === undefined ? existing.expiresAt : (input.expiresAt ?? undefined),
|
|
420
|
+
sourceType: typeof input.sourceType === "string" && input.sourceType.trim().length > 0 ? input.sourceType.trim() : existing.sourceType,
|
|
421
|
+
sourceRefs: Array.isArray(input.sourceRefs)
|
|
422
|
+
? Array.from(new Set(input.sourceRefs.map((item) => item.trim()).filter((item) => item.length > 0)))
|
|
423
|
+
: existing.sourceRefs,
|
|
424
|
+
tags: Array.isArray(input.tags)
|
|
425
|
+
? Array.from(new Set(input.tags.map((item) => item.trim()).filter((item) => item.length > 0)))
|
|
426
|
+
: existing.tags,
|
|
427
|
+
observedAt: typeof input.observedAt === "string" && input.observedAt.trim().length > 0 ? input.observedAt : existing.observedAt,
|
|
428
|
+
lastConfirmedAt: typeof input.lastConfirmedAt === "string" && input.lastConfirmedAt.trim().length > 0
|
|
429
|
+
? input.lastConfirmedAt
|
|
430
|
+
: updatedAt,
|
|
431
|
+
provenance: input.provenance ? { ...existing.provenance, ...input.provenance } : existing.provenance,
|
|
432
|
+
revision: existing.revision + 1,
|
|
433
|
+
};
|
|
434
|
+
await updateMemoryRecord(this.runtimeMemoryStore, next, updatedAt);
|
|
435
|
+
await this.rebuildRuntimeMemoryVectorIndex();
|
|
436
|
+
await this.refreshStructuredMemoryScope(binding, next);
|
|
437
|
+
return next;
|
|
438
|
+
}
|
|
439
|
+
async removeMemory(input) {
|
|
440
|
+
const binding = this.defaultRuntimeEntryBinding;
|
|
441
|
+
if (!binding) {
|
|
442
|
+
throw new Error("removeMemory requires a runtime entry binding.");
|
|
443
|
+
}
|
|
444
|
+
if (typeof input.memoryId !== "string" || input.memoryId.trim().length === 0) {
|
|
445
|
+
throw new Error("removeMemory requires a non-empty memoryId.");
|
|
446
|
+
}
|
|
447
|
+
const existing = await findMemoryRecordById(this.runtimeMemoryStore, input.memoryId.trim());
|
|
448
|
+
if (!existing) {
|
|
449
|
+
throw new Error(`Memory record not found: ${input.memoryId}`);
|
|
450
|
+
}
|
|
451
|
+
await removeMemoryRecord(this.runtimeMemoryStore, existing.scope, existing.id);
|
|
452
|
+
await this.rebuildRuntimeMemoryVectorIndex();
|
|
453
|
+
await this.refreshStructuredMemoryScope(binding, existing);
|
|
454
|
+
return existing;
|
|
455
|
+
}
|
|
364
456
|
async getRun(runId) {
|
|
365
457
|
return this.persistence.getRun(runId);
|
|
366
458
|
}
|
|
@@ -514,7 +606,7 @@ export class AgentHarnessRuntime {
|
|
|
514
606
|
const template = this.runtimeMemoryPolicy?.namespaces[scope] ?? `memories/${scope}s/{${scope}Id}`;
|
|
515
607
|
return resolveMemoryNamespace(template, {
|
|
516
608
|
threadId: options.threadId,
|
|
517
|
-
agentId: binding.agent.id,
|
|
609
|
+
agentId: options.agentId ?? binding.agent.id,
|
|
518
610
|
workspaceId,
|
|
519
611
|
userId: options.userId ?? "default",
|
|
520
612
|
projectId: options.projectId ?? workspaceId,
|
|
@@ -524,6 +616,27 @@ export class AgentHarnessRuntime {
|
|
|
524
616
|
const workspaceRoot = binding.harnessRuntime.workspaceRoot ?? this.workspace.workspaceRoot;
|
|
525
617
|
return path.basename(workspaceRoot) || "default";
|
|
526
618
|
}
|
|
619
|
+
summarizeMemoryContent(content) {
|
|
620
|
+
return (content.trim().split("\n")[0] || content.trim()).slice(0, 240);
|
|
621
|
+
}
|
|
622
|
+
matchesMemoryFilters(record, filters) {
|
|
623
|
+
if (filters.threadId && record.provenance.threadId !== filters.threadId) {
|
|
624
|
+
return false;
|
|
625
|
+
}
|
|
626
|
+
if (filters.agentId && record.provenance.agentId !== filters.agentId) {
|
|
627
|
+
return false;
|
|
628
|
+
}
|
|
629
|
+
if (filters.workspaceId && record.provenance.workspaceId !== filters.workspaceId) {
|
|
630
|
+
return false;
|
|
631
|
+
}
|
|
632
|
+
if (filters.userId && record.provenance.userId !== filters.userId) {
|
|
633
|
+
return false;
|
|
634
|
+
}
|
|
635
|
+
if (filters.projectId && record.provenance.projectId !== filters.projectId) {
|
|
636
|
+
return false;
|
|
637
|
+
}
|
|
638
|
+
return true;
|
|
639
|
+
}
|
|
527
640
|
resolveRecallScopes(input) {
|
|
528
641
|
if (Array.isArray(input.scopes) && input.scopes.length > 0) {
|
|
529
642
|
return Array.from(new Set(input.scopes));
|
|
@@ -755,6 +868,30 @@ export class AgentHarnessRuntime {
|
|
|
755
868
|
// Fail open: vector indexing must not break durable memory writes.
|
|
756
869
|
}
|
|
757
870
|
}
|
|
871
|
+
async refreshStructuredMemoryScope(binding, record) {
|
|
872
|
+
const provenance = record.provenance;
|
|
873
|
+
const maxEntries = record.scope === "thread" ? 12 : 20;
|
|
874
|
+
const titleByScope = {
|
|
875
|
+
thread: "Thread Structured Memory",
|
|
876
|
+
agent: "Agent Structured Memory",
|
|
877
|
+
workspace: "Workspace Structured Memory",
|
|
878
|
+
user: "User Structured Memory",
|
|
879
|
+
project: "Project Structured Memory",
|
|
880
|
+
};
|
|
881
|
+
await consolidateStructuredMemoryScope({
|
|
882
|
+
store: this.runtimeMemoryStore,
|
|
883
|
+
namespace: this.resolveMemoryNamespace(record.scope, binding, {
|
|
884
|
+
threadId: provenance.threadId,
|
|
885
|
+
agentId: provenance.agentId,
|
|
886
|
+
userId: provenance.userId,
|
|
887
|
+
projectId: provenance.projectId,
|
|
888
|
+
}),
|
|
889
|
+
title: titleByScope[record.scope],
|
|
890
|
+
scope: record.scope,
|
|
891
|
+
maxEntries,
|
|
892
|
+
config: this.runtimeMemoryMaintenanceConfig ?? undefined,
|
|
893
|
+
});
|
|
894
|
+
}
|
|
758
895
|
async buildRuntimeMemoryContext(binding, threadId, input) {
|
|
759
896
|
const query = typeof input === "string" ? input : JSON.stringify(input ?? "");
|
|
760
897
|
const workspaceId = this.getWorkspaceId(binding);
|
|
@@ -6,7 +6,7 @@ import { resolveIsolatedResourceModulePath } from "../resource/isolation.js";
|
|
|
6
6
|
import { isExternalSourceLocator, resolveResourcePackageRoot } from "../resource/sources.js";
|
|
7
7
|
import { discoverToolModuleDefinitions, isSupportedToolModulePath } from "../tool-modules.js";
|
|
8
8
|
import { fileExists } from "../utils/fs.js";
|
|
9
|
-
import {
|
|
9
|
+
import { readNamedYamlItems, readYamlItems, } from "./yaml-object-reader.js";
|
|
10
10
|
export { normalizeYamlItem, readYamlItems } from "./yaml-object-reader.js";
|
|
11
11
|
const CONVENTIONAL_OBJECT_DIRECTORIES = ["tools"];
|
|
12
12
|
const MODULE_AGENT_FILENAMES = ["agent.yaml", "agent.yml"];
|
|
@@ -39,16 +39,10 @@ function conventionalConfigRoot(root) {
|
|
|
39
39
|
}
|
|
40
40
|
function conventionalDirectoryRoots(root, relativeDir) {
|
|
41
41
|
const resourceRoot = resolveResourcePackageRoot(root);
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
path.join(root, "agents"),
|
|
47
|
-
]
|
|
48
|
-
: [
|
|
49
|
-
...(resourceRoot ? [path.join(resourceRoot, relativeDir)] : []),
|
|
50
|
-
path.join(root, relativeDir),
|
|
51
|
-
];
|
|
42
|
+
const candidates = [
|
|
43
|
+
...(resourceRoot ? [path.join(resourceRoot, relativeDir)] : []),
|
|
44
|
+
path.join(root, relativeDir),
|
|
45
|
+
];
|
|
52
46
|
return Array.from(new Set(candidates));
|
|
53
47
|
}
|
|
54
48
|
export function conventionalPackageRoots(root, relativeDir) {
|
|
@@ -569,20 +563,6 @@ function mergeAgentRecord(records, item, sourcePath) {
|
|
|
569
563
|
function mergeWorkspaceObjectRecord(records, workspaceObject, item, sourcePath) {
|
|
570
564
|
mergeRawItemRecord(records, `${workspaceObject.kind}/${workspaceObject.id}`, item, sourcePath);
|
|
571
565
|
}
|
|
572
|
-
async function loadNamedModelsForRoot(configRoot, mergedObjects) {
|
|
573
|
-
for (const { item, sourcePath } of await readNamedModelItems(configRoot)) {
|
|
574
|
-
const workspaceObject = parseWorkspaceObject(item, sourcePath);
|
|
575
|
-
if (!workspaceObject || workspaceObject.kind !== "model") {
|
|
576
|
-
continue;
|
|
577
|
-
}
|
|
578
|
-
mergeWorkspaceObjectRecord(mergedObjects, workspaceObject, item, sourcePath);
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
async function loadConfigAgentsForRoot(configRoot, mergedAgents) {
|
|
582
|
-
for (const { item, sourcePath } of await readConfigAgentItems(configRoot)) {
|
|
583
|
-
mergeAgentRecord(mergedAgents, item, sourcePath);
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
566
|
async function loadModuleAgentsForRoot(root, mergedAgents) {
|
|
587
567
|
const modulesRoot = moduleCollectionRoot(root, "agents");
|
|
588
568
|
if (!(await fileExists(modulesRoot))) {
|
|
@@ -675,7 +655,7 @@ async function loadModuleObjectsForRoot(root, mergedObjects) {
|
|
|
675
655
|
mergeWorkspaceObjectRecord(mergedObjects, workspaceObject, item, sourcePath);
|
|
676
656
|
}
|
|
677
657
|
}
|
|
678
|
-
async function
|
|
658
|
+
async function loadConfigYamlForRoot(root, configRoot, mergedAgents, mergedObjects) {
|
|
679
659
|
if (!conventionalConfigRoot(root)) {
|
|
680
660
|
return;
|
|
681
661
|
}
|
|
@@ -684,7 +664,8 @@ async function loadConfigObjectsForRoot(root, configRoot, mergedObjects) {
|
|
|
684
664
|
if (!workspaceObject) {
|
|
685
665
|
continue;
|
|
686
666
|
}
|
|
687
|
-
if (isAgentKind(workspaceObject.kind)
|
|
667
|
+
if (isAgentKind(workspaceObject.kind)) {
|
|
668
|
+
mergeAgentRecord(mergedAgents, item, sourcePath);
|
|
688
669
|
continue;
|
|
689
670
|
}
|
|
690
671
|
mergeWorkspaceObjectRecord(mergedObjects, workspaceObject, item, sourcePath);
|
|
@@ -708,20 +689,6 @@ async function loadRootObjects(root, mergedObjects) {
|
|
|
708
689
|
function isAgentKind(kind) {
|
|
709
690
|
return kind === "agent";
|
|
710
691
|
}
|
|
711
|
-
async function readConfigAgentItems(configRoot) {
|
|
712
|
-
const records = await readYamlItems(configRoot, undefined, { recursive: true });
|
|
713
|
-
return records.filter(({ item, sourcePath }) => {
|
|
714
|
-
const kind = typeof item.kind === "string" ? item.kind : undefined;
|
|
715
|
-
if (!isAgentKind(kind)) {
|
|
716
|
-
return false;
|
|
717
|
-
}
|
|
718
|
-
const relativePath = path.relative(configRoot, sourcePath);
|
|
719
|
-
if (!relativePath || relativePath.startsWith("..")) {
|
|
720
|
-
return false;
|
|
721
|
-
}
|
|
722
|
-
return !relativePath.includes(path.sep) || relativePath.startsWith(`agents${path.sep}`);
|
|
723
|
-
});
|
|
724
|
-
}
|
|
725
692
|
export async function readToolModuleItems(root) {
|
|
726
693
|
if (!(await fileExists(root))) {
|
|
727
694
|
return [];
|
|
@@ -792,11 +759,9 @@ export async function loadWorkspaceObjects(workspaceRoot, options = {}) {
|
|
|
792
759
|
const roots = [frameworkWorkspaceRoot(), ...(options.overlayRoots ?? []), workspaceRoot];
|
|
793
760
|
for (const root of roots) {
|
|
794
761
|
const configRoot = conventionalConfigRoot(root) ?? root;
|
|
795
|
-
await
|
|
796
|
-
await loadConfigAgentsForRoot(configRoot, mergedAgents);
|
|
762
|
+
await loadConfigYamlForRoot(root, configRoot, mergedAgents, mergedObjects);
|
|
797
763
|
await loadModuleAgentsForRoot(root, mergedAgents);
|
|
798
764
|
await loadConventionalObjectsForRoot(root, mergedObjects);
|
|
799
|
-
await loadConfigObjectsForRoot(root, configRoot, mergedObjects);
|
|
800
765
|
await loadModuleObjectsForRoot(root, mergedObjects);
|
|
801
766
|
await loadRootObjects(root, mergedObjects);
|
|
802
767
|
}
|
|
@@ -9,7 +9,3 @@ export declare function readNamedYamlItems(root: string, filenames: string[]): P
|
|
|
9
9
|
item: Record<string, unknown>;
|
|
10
10
|
sourcePath: string;
|
|
11
11
|
}>>;
|
|
12
|
-
export declare function readNamedModelItems(root: string): Promise<Array<{
|
|
13
|
-
item: Record<string, unknown>;
|
|
14
|
-
sourcePath: string;
|
|
15
|
-
}>>;
|
|
@@ -2,7 +2,6 @@ import path from "node:path";
|
|
|
2
2
|
import { readdir } from "node:fs/promises";
|
|
3
3
|
import { parseAllDocuments } from "yaml";
|
|
4
4
|
import { fileExists, listFilesRecursive, readYamlOrJson } from "../utils/fs.js";
|
|
5
|
-
const MODEL_FILENAMES = ["models.yaml", "models.yml"];
|
|
6
5
|
const ENV_PLACEHOLDER_PATTERN = /\$\{env:([A-Za-z_][A-Za-z0-9_]*)\}/g;
|
|
7
6
|
function asObject(value) {
|
|
8
7
|
return typeof value === "object" && value ? value : undefined;
|
|
@@ -165,7 +164,10 @@ export async function readYamlItems(root, relativeDir, options = {}) {
|
|
|
165
164
|
return [];
|
|
166
165
|
}
|
|
167
166
|
const files = options.recursive
|
|
168
|
-
?
|
|
167
|
+
? Array.from(new Set([
|
|
168
|
+
...(await listFilesRecursive(targetRoot, ".yaml")),
|
|
169
|
+
...(await listFilesRecursive(targetRoot, ".yml")),
|
|
170
|
+
])).sort()
|
|
169
171
|
: (await readdir(targetRoot, { withFileTypes: true }))
|
|
170
172
|
.filter((entry) => entry.isFile() && /\.ya?ml$/i.test(entry.name))
|
|
171
173
|
.map((entry) => path.join(targetRoot, entry.name))
|
|
@@ -199,33 +201,3 @@ export async function readNamedYamlItems(root, filenames) {
|
|
|
199
201
|
}
|
|
200
202
|
return records;
|
|
201
203
|
}
|
|
202
|
-
export async function readNamedModelItems(root) {
|
|
203
|
-
const filePaths = new Set();
|
|
204
|
-
for (const filename of MODEL_FILENAMES) {
|
|
205
|
-
const directPath = path.join(root, filename);
|
|
206
|
-
if (await fileExists(directPath)) {
|
|
207
|
-
filePaths.add(directPath);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
for (const extension of [".yaml", ".yml"]) {
|
|
211
|
-
for (const filePath of await listFilesRecursive(root, extension)) {
|
|
212
|
-
if (MODEL_FILENAMES.includes(path.basename(filePath))) {
|
|
213
|
-
filePaths.add(filePath);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
const records = [];
|
|
218
|
-
for (const filePath of [...filePaths].sort()) {
|
|
219
|
-
const parsedDocuments = parseAllDocuments(await readYamlOrJson(filePath));
|
|
220
|
-
for (const parsedDocument of parsedDocuments) {
|
|
221
|
-
const resolvedDocument = interpolateEnvPlaceholders(parsedDocument.toJSON(), filePath);
|
|
222
|
-
for (const item of await objectItemsFromDocument(resolvedDocument, filePath)) {
|
|
223
|
-
const normalized = normalizeYamlItem(item);
|
|
224
|
-
if (normalized.kind === "model" && typeof normalized.id === "string" && normalized.id.trim()) {
|
|
225
|
-
records.push({ item: normalized, sourcePath: filePath });
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
return records;
|
|
231
|
-
}
|