@botbotgo/agent-harness 0.0.71 → 0.0.72

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/dist/api.d.ts CHANGED
@@ -3,7 +3,9 @@ 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";
5
5
  import type { ToolMcpServerOptions } from "./mcp.js";
6
+ import type { PrepareWorkspaceMetadata, PrepareWorkspaceOptions } from "./workspace/bootstrap.js";
6
7
  export { AgentHarnessRuntime } from "./runtime/harness.js";
8
+ export type { PrepareWorkspaceMetadata, PrepareWorkspaceOptions };
7
9
  type CreateAgentHarnessOptions = {
8
10
  /**
9
11
  * Workspace loading behavior.
@@ -32,3 +34,4 @@ export declare function resolveApproval(runtime: AgentHarnessRuntime, options: R
32
34
  export declare function stop(runtime: AgentHarnessRuntime): Promise<void>;
33
35
  export declare function createToolMcpServer(runtime: AgentHarnessRuntime, options: ToolMcpServerOptions): Promise<import("@modelcontextprotocol/sdk/server/mcp.js").McpServer>;
34
36
  export declare function serveToolsOverStdio(runtime: AgentHarnessRuntime, options: ToolMcpServerOptions): Promise<import("@modelcontextprotocol/sdk/server/mcp.js").McpServer>;
37
+ export declare function prepareWorkspace(workspaceRoot: string, options?: PrepareWorkspaceOptions): Promise<PrepareWorkspaceMetadata>;
package/dist/api.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { AgentHarnessRuntime } from "./runtime/harness.js";
2
2
  import { loadWorkspace } from "./workspace/compile.js";
3
+ import { prepareWorkspace as prepareWorkspaceFromBootstrap } from "./workspace/bootstrap.js";
3
4
  export { AgentHarnessRuntime } from "./runtime/harness.js";
4
5
  export async function createAgentHarness(workspaceRoot = process.cwd(), options = {}) {
5
6
  const workspace = await loadWorkspace(workspaceRoot, options.load ?? {});
@@ -52,3 +53,6 @@ export async function createToolMcpServer(runtime, options) {
52
53
  export async function serveToolsOverStdio(runtime, options) {
53
54
  return runtime.serveToolsOverStdio(options);
54
55
  }
56
+ export function prepareWorkspace(workspaceRoot, options) {
57
+ return prepareWorkspaceFromBootstrap(workspaceRoot, options);
58
+ }
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { AgentHarnessRuntime, createAgentHarness, createToolMcpServer, deleteThread, describeInventory, getApproval, getRun, getThread, listAgentSkills, listApprovals, listRuns, listThreads, resolveApproval, run, serveToolsOverStdio, subscribe, stop, } from "./api.js";
1
+ export { AgentHarnessRuntime, createAgentHarness, prepareWorkspace, 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, getRun, getThread, listAgentSkills, listApprovals, listRuns, listThreads, resolveApproval, run, serveToolsOverStdio, subscribe, stop, } from "./api.js";
1
+ export { AgentHarnessRuntime, createAgentHarness, prepareWorkspace, 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.70";
1
+ export declare const AGENT_HARNESS_VERSION = "0.0.71";
@@ -1 +1 @@
1
- export const AGENT_HARNESS_VERSION = "0.0.70";
1
+ export const AGENT_HARNESS_VERSION = "0.0.71";
@@ -0,0 +1,29 @@
1
+ type WorkspaceBootstrapOptions = {
2
+ sourceConfigRoot?: string;
3
+ sourceResourcesRoot?: string;
4
+ removePatterns?: string[];
5
+ postCopyRemoveFiles?: string[];
6
+ lock?: {
7
+ enabled?: boolean;
8
+ path?: string;
9
+ maxAttempts?: number;
10
+ retryDelayMs?: number;
11
+ };
12
+ operations?: {
13
+ copy?: (source: string, destination: string) => Promise<void>;
14
+ remove?: (target: string) => Promise<void>;
15
+ mkdir?: (target: string) => Promise<void>;
16
+ };
17
+ };
18
+ export type PrepareWorkspaceOptions = WorkspaceBootstrapOptions;
19
+ export type PrepareWorkspaceMetadata = {
20
+ workspaceRoot: string;
21
+ configRoot: string;
22
+ resourcesRoot: string;
23
+ sourceConfigRoot: string;
24
+ sourceResourcesRoot: string;
25
+ removed: string[];
26
+ copied: string[];
27
+ };
28
+ export declare function prepareWorkspace(workspaceRoot: string, options?: PrepareWorkspaceOptions): Promise<PrepareWorkspaceMetadata>;
29
+ export {};
@@ -0,0 +1,131 @@
1
+ import { cp, mkdir, rm, stat } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ const DEFAULT_REMOVE_PATTERNS = [
5
+ "direct.yaml",
6
+ "orchestra.yaml",
7
+ "runtime.yaml",
8
+ "agent.yaml",
9
+ "memory.yaml",
10
+ "model.yaml",
11
+ "tool.yaml",
12
+ "toolkit.yaml",
13
+ "agents",
14
+ "config",
15
+ "resources",
16
+ ];
17
+ const DEFAULT_POST_COPY_REMOVE_FILES = ["agent.yaml", "memory.yaml", "model.yaml", "tool.yaml", "toolkit.yaml"];
18
+ function resolveFrameworkRoot() {
19
+ const base = path.dirname(fileURLToPath(import.meta.url));
20
+ const resolved = path.resolve(base, "..", "..");
21
+ return resolved;
22
+ }
23
+ function resolveFrameworkConfigRoot() {
24
+ return path.join(resolveFrameworkRoot(), "config");
25
+ }
26
+ function resolveFrameworkResourcesRoot() {
27
+ return path.join(resolveFrameworkRoot(), "resources");
28
+ }
29
+ function sleep(ms) {
30
+ return new Promise((resolve) => setTimeout(resolve, ms));
31
+ }
32
+ function isErrnoCode(error, code) {
33
+ return error?.code === code;
34
+ }
35
+ async function exists(filePath) {
36
+ try {
37
+ await stat(filePath);
38
+ return true;
39
+ }
40
+ catch (error) {
41
+ if (isErrnoCode(error, "ENOENT")) {
42
+ return false;
43
+ }
44
+ throw error;
45
+ }
46
+ }
47
+ async function acquireWorkspaceBootstrapLock(lockPath, options) {
48
+ let attempt = 0;
49
+ // eslint-disable-next-line no-constant-condition
50
+ while (true) {
51
+ try {
52
+ await mkdir(lockPath);
53
+ return async () => {
54
+ await rm(lockPath, { recursive: true, force: true });
55
+ };
56
+ }
57
+ catch (error) {
58
+ attempt += 1;
59
+ if (!isErrnoCode(error, "EEXIST") || attempt >= options.maxAttempts) {
60
+ throw new Error(`Failed to prepare workspace at ${lockPath}; lock was not released after ${attempt} attempts.`);
61
+ }
62
+ await sleep(options.retryDelayMs);
63
+ }
64
+ }
65
+ }
66
+ export async function prepareWorkspace(workspaceRoot, options = {}) {
67
+ const resolvedWorkspaceRoot = path.resolve(workspaceRoot);
68
+ const removePatterns = options.removePatterns && options.removePatterns.length > 0
69
+ ? [...new Set(options.removePatterns.map((entry) => entry.trim()).filter(Boolean))]
70
+ : [...DEFAULT_REMOVE_PATTERNS];
71
+ const postCopyRemoveFiles = options.postCopyRemoveFiles && options.postCopyRemoveFiles.length > 0
72
+ ? [...new Set(options.postCopyRemoveFiles.map((entry) => entry.trim()).filter(Boolean))]
73
+ : [...DEFAULT_POST_COPY_REMOVE_FILES];
74
+ const sourceConfigRoot = path.resolve(options.sourceConfigRoot ?? resolveFrameworkConfigRoot());
75
+ const sourceResourcesRoot = path.resolve(options.sourceResourcesRoot ?? resolveFrameworkResourcesRoot());
76
+ const configRoot = path.join(resolvedWorkspaceRoot, "config");
77
+ const resourcesRoot = path.join(resolvedWorkspaceRoot, "resources");
78
+ const lockOptions = options.lock?.enabled === false
79
+ ? null
80
+ : {
81
+ path: options.lock?.path ?? path.join(resolvedWorkspaceRoot, ".agent-harness-bootstrap.lock"),
82
+ maxAttempts: options.lock?.maxAttempts ?? 40,
83
+ retryDelayMs: options.lock?.retryDelayMs ?? 25,
84
+ };
85
+ const operations = {
86
+ copy: options.operations?.copy ?? ((source, destination) => cp(source, destination, { recursive: true, force: true })),
87
+ remove: options.operations?.remove ?? ((target) => rm(target, { recursive: true, force: true })),
88
+ mkdir: options.operations?.mkdir ?? ((target) => mkdir(target, { recursive: true })),
89
+ };
90
+ await operations.mkdir(resolvedWorkspaceRoot);
91
+ const lock = await (lockOptions
92
+ ? acquireWorkspaceBootstrapLock(lockOptions.path, lockOptions)
93
+ : async () => undefined);
94
+ const removed = [];
95
+ const copied = [];
96
+ try {
97
+ for (const pattern of removePatterns) {
98
+ const target = path.join(resolvedWorkspaceRoot, pattern);
99
+ removed.push(target);
100
+ await operations.remove(target);
101
+ }
102
+ await operations.mkdir(configRoot);
103
+ await operations.mkdir(path.join(configRoot, "agents"));
104
+ await operations.mkdir(resourcesRoot);
105
+ if (await exists(sourceConfigRoot)) {
106
+ await operations.copy(sourceConfigRoot, configRoot);
107
+ copied.push(configRoot);
108
+ }
109
+ if (await exists(sourceResourcesRoot)) {
110
+ await operations.copy(sourceResourcesRoot, resourcesRoot);
111
+ copied.push(resourcesRoot);
112
+ }
113
+ for (const file of postCopyRemoveFiles) {
114
+ await operations.remove(path.join(configRoot, file));
115
+ }
116
+ return {
117
+ workspaceRoot: resolvedWorkspaceRoot,
118
+ configRoot,
119
+ resourcesRoot,
120
+ sourceConfigRoot,
121
+ sourceResourcesRoot,
122
+ removed,
123
+ copied,
124
+ };
125
+ }
126
+ finally {
127
+ if (lockOptions) {
128
+ await lock();
129
+ }
130
+ }
131
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbotgo/agent-harness",
3
- "version": "0.0.71",
3
+ "version": "0.0.72",
4
4
  "description": "Workspace runtime for multi-agent applications",
5
5
  "type": "module",
6
6
  "packageManager": "npm@10.9.2",