@botbotgo/agent-harness 0.0.155 → 0.0.157
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 +34 -6
- package/README.zh.md +34 -6
- package/dist/acp.d.ts +86 -0
- package/dist/acp.js +208 -0
- package/dist/api.d.ts +17 -2
- package/dist/api.js +19 -0
- package/dist/contracts/runtime.d.ts +79 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1 -1
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/persistence/file-store.d.ts +1 -0
- package/dist/persistence/file-store.js +10 -1
- package/dist/persistence/types.d.ts +2 -0
- package/dist/runtime/agent-runtime-adapter.d.ts +5 -1
- package/dist/runtime/agent-runtime-adapter.js +61 -24
- package/dist/runtime/harness/run/governance.d.ts +2 -0
- package/dist/runtime/harness/run/governance.js +76 -0
- package/dist/runtime/harness/run/inspection.js +4 -0
- package/dist/runtime/harness/system/policy-engine.d.ts +2 -1
- package/dist/runtime/harness/system/policy-engine.js +5 -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 +11 -1
- package/dist/runtime/harness.js +221 -2
- package/dist/workspace/agent-binding-compiler.js +7 -1
- 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 +6 -1
|
@@ -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, ArtifactListing, CancelOptions, HarnessEvent, HarnessStreamItem, RuntimeHealthSnapshot, ListMemoriesInput, ListMemoriesResult, MessageContent, RemoveMemoryInput, RunRecord, RunStartOptions, RestartConversationOptions, RuntimeAdapterOptions, RuntimeEvaluationExport, RuntimeEvaluationExportInput, 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>;
|
|
@@ -79,6 +82,10 @@ export declare class AgentHarnessRuntime {
|
|
|
79
82
|
runId?: string;
|
|
80
83
|
}): Promise<ApprovalRecord[]>;
|
|
81
84
|
getApproval(approvalId: string): Promise<ApprovalRecord | null>;
|
|
85
|
+
listArtifacts(threadId: string, runId: string): Promise<ArtifactListing>;
|
|
86
|
+
readArtifact(threadId: string, runId: string, artifactPath: string): Promise<unknown>;
|
|
87
|
+
listRunEvents(threadId: string, runId: string): Promise<HarnessEvent[]>;
|
|
88
|
+
exportEvaluationBundle(input: RuntimeEvaluationExportInput): Promise<RuntimeEvaluationExport>;
|
|
82
89
|
listAgentSkills(agentId: string, options?: RequirementAssessmentOptions): InventorySkillRecord[];
|
|
83
90
|
getAgent(agentId: string, options?: RequirementAssessmentOptions): InventoryAgentRecord | null;
|
|
84
91
|
describeWorkspaceInventory(options?: RequirementAssessmentOptions): {
|
|
@@ -102,6 +109,8 @@ export declare class AgentHarnessRuntime {
|
|
|
102
109
|
private invokeWithHistory;
|
|
103
110
|
private resolveMemoryNamespace;
|
|
104
111
|
private getWorkspaceId;
|
|
112
|
+
private summarizeMemoryContent;
|
|
113
|
+
private matchesMemoryFilters;
|
|
105
114
|
private resolveRecallScopes;
|
|
106
115
|
private matchesRecallScope;
|
|
107
116
|
private getMemoryScopeBoost;
|
|
@@ -113,6 +122,7 @@ export declare class AgentHarnessRuntime {
|
|
|
113
122
|
private createMem0MemoryRecord;
|
|
114
123
|
private rankRecallCandidates;
|
|
115
124
|
private rebuildRuntimeMemoryVectorIndex;
|
|
125
|
+
private refreshStructuredMemoryScope;
|
|
116
126
|
private buildRuntimeMemoryContext;
|
|
117
127
|
private persistRuntimeMemoryCandidates;
|
|
118
128
|
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
|
}
|
|
@@ -383,6 +475,51 @@ export class AgentHarnessRuntime {
|
|
|
383
475
|
persistence: this.persistence,
|
|
384
476
|
}, approvalId);
|
|
385
477
|
}
|
|
478
|
+
async listArtifacts(threadId, runId) {
|
|
479
|
+
return this.persistence.listArtifacts(threadId, runId);
|
|
480
|
+
}
|
|
481
|
+
async readArtifact(threadId, runId, artifactPath) {
|
|
482
|
+
return this.persistence.readArtifact(threadId, runId, artifactPath);
|
|
483
|
+
}
|
|
484
|
+
async listRunEvents(threadId, runId) {
|
|
485
|
+
return this.persistence.listRunEvents(threadId, runId);
|
|
486
|
+
}
|
|
487
|
+
async exportEvaluationBundle(input) {
|
|
488
|
+
const thread = await this.getThread(input.sessionId);
|
|
489
|
+
const run = await this.getRun(input.requestId);
|
|
490
|
+
const approvals = await this.listApprovals({ threadId: input.sessionId, runId: input.requestId });
|
|
491
|
+
const transcript = await this.persistence.listThreadMessages(input.sessionId, 500);
|
|
492
|
+
const events = await this.persistence.listRunEvents(input.sessionId, input.requestId);
|
|
493
|
+
const runtimeHealth = await this.getHealth();
|
|
494
|
+
const artifactsListing = input.includeArtifacts === false
|
|
495
|
+
? { items: [] }
|
|
496
|
+
: await this.persistence.listArtifacts(input.sessionId, input.requestId);
|
|
497
|
+
const artifacts = await Promise.all(artifactsListing.items.map(async (artifact) => ({
|
|
498
|
+
...artifact,
|
|
499
|
+
...(input.includeArtifactContents === true
|
|
500
|
+
? { content: await this.persistence.readArtifact(input.sessionId, input.requestId, artifact.path) }
|
|
501
|
+
: {}),
|
|
502
|
+
})));
|
|
503
|
+
return {
|
|
504
|
+
session: thread ? toSessionRecord(thread) : null,
|
|
505
|
+
request: run ? toRequestRecord(run) : null,
|
|
506
|
+
approvals,
|
|
507
|
+
transcript,
|
|
508
|
+
events,
|
|
509
|
+
artifacts,
|
|
510
|
+
runtimeHealth,
|
|
511
|
+
...(typeof input.expectedOutput === "string" && input.expectedOutput.trim().length > 0
|
|
512
|
+
? { expectedOutput: input.expectedOutput.trim() }
|
|
513
|
+
: {}),
|
|
514
|
+
rubric: Array.isArray(input.rubric)
|
|
515
|
+
? input.rubric.filter((item) => typeof item === "string" && item.trim().length > 0).map((item) => item.trim())
|
|
516
|
+
: [],
|
|
517
|
+
tags: Array.isArray(input.tags)
|
|
518
|
+
? input.tags.filter((item) => typeof item === "string" && item.trim().length > 0).map((item) => item.trim())
|
|
519
|
+
: [],
|
|
520
|
+
...(input.metadata ? { metadata: { ...input.metadata } } : {}),
|
|
521
|
+
};
|
|
522
|
+
}
|
|
386
523
|
listAgentSkills(agentId, options = {}) {
|
|
387
524
|
return listWorkspaceAgentSkills(this.workspace, agentId, {
|
|
388
525
|
assessRequirements: isInventoryEnabled(this.workspace),
|
|
@@ -514,7 +651,7 @@ export class AgentHarnessRuntime {
|
|
|
514
651
|
const template = this.runtimeMemoryPolicy?.namespaces[scope] ?? `memories/${scope}s/{${scope}Id}`;
|
|
515
652
|
return resolveMemoryNamespace(template, {
|
|
516
653
|
threadId: options.threadId,
|
|
517
|
-
agentId: binding.agent.id,
|
|
654
|
+
agentId: options.agentId ?? binding.agent.id,
|
|
518
655
|
workspaceId,
|
|
519
656
|
userId: options.userId ?? "default",
|
|
520
657
|
projectId: options.projectId ?? workspaceId,
|
|
@@ -524,6 +661,27 @@ export class AgentHarnessRuntime {
|
|
|
524
661
|
const workspaceRoot = binding.harnessRuntime.workspaceRoot ?? this.workspace.workspaceRoot;
|
|
525
662
|
return path.basename(workspaceRoot) || "default";
|
|
526
663
|
}
|
|
664
|
+
summarizeMemoryContent(content) {
|
|
665
|
+
return (content.trim().split("\n")[0] || content.trim()).slice(0, 240);
|
|
666
|
+
}
|
|
667
|
+
matchesMemoryFilters(record, filters) {
|
|
668
|
+
if (filters.threadId && record.provenance.threadId !== filters.threadId) {
|
|
669
|
+
return false;
|
|
670
|
+
}
|
|
671
|
+
if (filters.agentId && record.provenance.agentId !== filters.agentId) {
|
|
672
|
+
return false;
|
|
673
|
+
}
|
|
674
|
+
if (filters.workspaceId && record.provenance.workspaceId !== filters.workspaceId) {
|
|
675
|
+
return false;
|
|
676
|
+
}
|
|
677
|
+
if (filters.userId && record.provenance.userId !== filters.userId) {
|
|
678
|
+
return false;
|
|
679
|
+
}
|
|
680
|
+
if (filters.projectId && record.provenance.projectId !== filters.projectId) {
|
|
681
|
+
return false;
|
|
682
|
+
}
|
|
683
|
+
return true;
|
|
684
|
+
}
|
|
527
685
|
resolveRecallScopes(input) {
|
|
528
686
|
if (Array.isArray(input.scopes) && input.scopes.length > 0) {
|
|
529
687
|
return Array.from(new Set(input.scopes));
|
|
@@ -755,6 +913,30 @@ export class AgentHarnessRuntime {
|
|
|
755
913
|
// Fail open: vector indexing must not break durable memory writes.
|
|
756
914
|
}
|
|
757
915
|
}
|
|
916
|
+
async refreshStructuredMemoryScope(binding, record) {
|
|
917
|
+
const provenance = record.provenance;
|
|
918
|
+
const maxEntries = record.scope === "thread" ? 12 : 20;
|
|
919
|
+
const titleByScope = {
|
|
920
|
+
thread: "Thread Structured Memory",
|
|
921
|
+
agent: "Agent Structured Memory",
|
|
922
|
+
workspace: "Workspace Structured Memory",
|
|
923
|
+
user: "User Structured Memory",
|
|
924
|
+
project: "Project Structured Memory",
|
|
925
|
+
};
|
|
926
|
+
await consolidateStructuredMemoryScope({
|
|
927
|
+
store: this.runtimeMemoryStore,
|
|
928
|
+
namespace: this.resolveMemoryNamespace(record.scope, binding, {
|
|
929
|
+
threadId: provenance.threadId,
|
|
930
|
+
agentId: provenance.agentId,
|
|
931
|
+
userId: provenance.userId,
|
|
932
|
+
projectId: provenance.projectId,
|
|
933
|
+
}),
|
|
934
|
+
title: titleByScope[record.scope],
|
|
935
|
+
scope: record.scope,
|
|
936
|
+
maxEntries,
|
|
937
|
+
config: this.runtimeMemoryMaintenanceConfig ?? undefined,
|
|
938
|
+
});
|
|
939
|
+
}
|
|
758
940
|
async buildRuntimeMemoryContext(binding, threadId, input) {
|
|
759
941
|
const query = typeof input === "string" ? input : JSON.stringify(input ?? "");
|
|
760
942
|
const workspaceId = this.getWorkspaceId(binding);
|
|
@@ -1256,3 +1438,40 @@ export class AgentHarnessRuntime {
|
|
|
1256
1438
|
}, thread, nowMs);
|
|
1257
1439
|
}
|
|
1258
1440
|
}
|
|
1441
|
+
function toRequestSummary(summary) {
|
|
1442
|
+
return {
|
|
1443
|
+
requestId: summary.runId,
|
|
1444
|
+
sessionId: summary.threadId,
|
|
1445
|
+
agentId: summary.agentId,
|
|
1446
|
+
executionMode: summary.executionMode,
|
|
1447
|
+
adapterKind: summary.adapterKind,
|
|
1448
|
+
createdAt: summary.createdAt,
|
|
1449
|
+
updatedAt: summary.updatedAt,
|
|
1450
|
+
state: summary.state,
|
|
1451
|
+
checkpointRef: summary.checkpointRef,
|
|
1452
|
+
resumable: summary.resumable,
|
|
1453
|
+
startedAt: summary.startedAt,
|
|
1454
|
+
endedAt: summary.endedAt,
|
|
1455
|
+
lastActivityAt: summary.lastActivityAt,
|
|
1456
|
+
currentAgentId: summary.currentAgentId,
|
|
1457
|
+
delegationChain: summary.delegationChain,
|
|
1458
|
+
runtimeSnapshot: summary.runtimeSnapshot,
|
|
1459
|
+
};
|
|
1460
|
+
}
|
|
1461
|
+
function toSessionRecord(record) {
|
|
1462
|
+
return {
|
|
1463
|
+
sessionId: record.threadId,
|
|
1464
|
+
entryAgentId: record.entryAgentId,
|
|
1465
|
+
currentAgentId: record.currentAgentId,
|
|
1466
|
+
currentState: record.currentState,
|
|
1467
|
+
latestRequestId: record.latestRunId,
|
|
1468
|
+
createdAt: record.createdAt,
|
|
1469
|
+
updatedAt: record.updatedAt,
|
|
1470
|
+
messages: record.messages,
|
|
1471
|
+
requests: record.runs.map(toRequestSummary),
|
|
1472
|
+
pendingDecision: record.pendingDecision,
|
|
1473
|
+
};
|
|
1474
|
+
}
|
|
1475
|
+
function toRequestRecord(record) {
|
|
1476
|
+
return toRequestSummary(record);
|
|
1477
|
+
}
|
|
@@ -337,6 +337,12 @@ export function compileBinding(workspaceRoot, agent, agents, referencedSubagentI
|
|
|
337
337
|
const store = resolveStoreConfig(agent, refs);
|
|
338
338
|
const checkpointer = resolveCheckpointerConfig(agent, refs);
|
|
339
339
|
const runtimeMemory = resolveRuntimeMemoryConfig(agent, refs);
|
|
340
|
+
const runtimeFilesystemDefaults = agent.executionMode === "langchain-v1"
|
|
341
|
+
? asObject(runtimeDefaults?.filesystem)
|
|
342
|
+
: undefined;
|
|
343
|
+
const compiledFilesystemConfig = agent.executionMode === "langchain-v1"
|
|
344
|
+
? mergeConfigObjects(runtimeFilesystemDefaults, getAgentExecutionObject(agent, "filesystem", { executionMode: "langchain-v1" }))
|
|
345
|
+
: undefined;
|
|
340
346
|
const runRoot = typeof agent.runRoot === "string" && agent.runRoot.trim().length > 0
|
|
341
347
|
? path.resolve(workspaceRoot, agent.runRoot)
|
|
342
348
|
: typeof runtimeDefaults?.runRoot === "string" && runtimeDefaults.runRoot.trim().length > 0
|
|
@@ -362,7 +368,7 @@ export function compileBinding(workspaceRoot, agent, agents, referencedSubagentI
|
|
|
362
368
|
langchain: {
|
|
363
369
|
passthrough,
|
|
364
370
|
interruptOn: resolveInterruptOn(agent),
|
|
365
|
-
filesystem:
|
|
371
|
+
filesystem: compiledFilesystemConfig,
|
|
366
372
|
subagents: compileSubagents(agent, agents, workspaceRoot, models, tools, compiledAgentSkills, compiledAgentModel),
|
|
367
373
|
memory: compiledAgentMemory,
|
|
368
374
|
skills: compiledAgentSkills,
|
|
@@ -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
|
-
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@botbotgo/agent-harness",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.157",
|
|
4
4
|
"description": "Workspace runtime for multi-agent applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "npm@10.9.2",
|
|
@@ -28,6 +28,11 @@
|
|
|
28
28
|
"import": "./dist/index.js",
|
|
29
29
|
"default": "./dist/index.js"
|
|
30
30
|
},
|
|
31
|
+
"./acp": {
|
|
32
|
+
"types": "./dist/acp.d.ts",
|
|
33
|
+
"import": "./dist/acp.js",
|
|
34
|
+
"default": "./dist/acp.js"
|
|
35
|
+
},
|
|
31
36
|
"./tools": {
|
|
32
37
|
"types": "./dist/tools.d.ts",
|
|
33
38
|
"import": "./dist/tools.js",
|