aos-harness 0.8.0 → 0.8.1
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/package.json +7 -7
- package/src/adapter-session.ts +16 -13
- package/src/env-scanner.ts +8 -0
- package/src/init-types.ts +2 -0
- package/src/prompts.ts +6 -3
- package/src/utils.ts +72 -31
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aos-harness",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "Agentic Orchestration System — assemble AI agents into deliberation and execution teams",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"publishConfig": {
|
|
@@ -38,18 +38,18 @@
|
|
|
38
38
|
"test": "bun run src/index.ts validate"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@aos-harness/adapter-shared": "0.8.
|
|
42
|
-
"@aos-harness/runtime": "0.8.
|
|
41
|
+
"@aos-harness/adapter-shared": "0.8.1",
|
|
42
|
+
"@aos-harness/runtime": "0.8.1",
|
|
43
43
|
"@clack/prompts": "^1.2.0",
|
|
44
44
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
45
45
|
"js-yaml": "^4.1.0",
|
|
46
46
|
"yaml": "^2.8.3"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
|
-
"@aos-harness/claude-code-adapter": ">=0.8.
|
|
50
|
-
"@aos-harness/codex-adapter": ">=0.8.
|
|
51
|
-
"@aos-harness/gemini-adapter": ">=0.8.
|
|
52
|
-
"@aos-harness/pi-adapter": ">=0.8.
|
|
49
|
+
"@aos-harness/claude-code-adapter": ">=0.8.1 <1.0.0",
|
|
50
|
+
"@aos-harness/codex-adapter": ">=0.8.1 <1.0.0",
|
|
51
|
+
"@aos-harness/gemini-adapter": ">=0.8.1 <1.0.0",
|
|
52
|
+
"@aos-harness/pi-adapter": ">=0.8.1 <1.0.0"
|
|
53
53
|
},
|
|
54
54
|
"peerDependenciesMeta": {
|
|
55
55
|
"@aos-harness/claude-code-adapter": {
|
package/src/adapter-session.ts
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
import { join, dirname } from "node:path";
|
|
16
16
|
import { fileURLToPath } from "node:url";
|
|
17
|
+
import { pathToFileURL } from "node:url";
|
|
17
18
|
import { tmpdir } from "node:os";
|
|
18
19
|
import { readFileSync } from "node:fs";
|
|
19
20
|
import readline from "node:readline";
|
|
@@ -31,6 +32,7 @@ import { loadAgent } from "@aos-harness/runtime/config-loader";
|
|
|
31
32
|
import { resolveTemplate } from "@aos-harness/runtime/template-resolver";
|
|
32
33
|
import { startBridgeServer } from "./bridge-server";
|
|
33
34
|
import { renderTextGauge, renderRoundOneLiner } from "./gauges";
|
|
35
|
+
import { getAdapterDir } from "./utils";
|
|
34
36
|
|
|
35
37
|
export interface AdapterSessionConfig {
|
|
36
38
|
platform: string; // "claude-code" | "gemini" | "codex"
|
|
@@ -147,29 +149,30 @@ async function loadAdapterRuntime(platform: string): Promise<any> {
|
|
|
147
149
|
const entry = ADAPTER_MAP[platform];
|
|
148
150
|
if (!entry) throw new Error(`Unknown adapter: ${platform}`);
|
|
149
151
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
const raw = await readFile(new URL(pkgUrl), "utf-8");
|
|
155
|
-
return (JSON.parse(raw) as { version: string }).version ?? "unknown";
|
|
156
|
-
} catch {
|
|
157
|
-
return "unknown";
|
|
158
|
-
}
|
|
152
|
+
const adapterDir = getAdapterDir(platform);
|
|
153
|
+
if (!adapterDir) {
|
|
154
|
+
printMissingAdapterError(entry.package);
|
|
155
|
+
process.exit(2);
|
|
159
156
|
}
|
|
160
157
|
|
|
161
158
|
let mod: any;
|
|
162
159
|
try {
|
|
163
|
-
mod = await import(
|
|
160
|
+
mod = await import(pathToFileURL(join(adapterDir, "src", "index.ts")).href);
|
|
164
161
|
} catch (err) {
|
|
165
162
|
if (isModuleNotFound(err)) {
|
|
166
163
|
printMissingAdapterError(entry.package);
|
|
167
164
|
process.exit(2);
|
|
168
165
|
}
|
|
169
|
-
throw err;
|
|
166
|
+
throw err;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
let version = "unknown";
|
|
170
|
+
try {
|
|
171
|
+
const raw = readFileSync(join(adapterDir, "package.json"), "utf-8");
|
|
172
|
+
version = (JSON.parse(raw) as { version?: string }).version ?? "unknown";
|
|
173
|
+
} catch {
|
|
174
|
+
version = "unknown";
|
|
170
175
|
}
|
|
171
|
-
const resolved = (import.meta as any).resolve?.(entry.package) ?? entry.package;
|
|
172
|
-
const version = await readAdapterVersion(resolved);
|
|
173
176
|
console.error(`[adapter] loaded ${entry.package}@${version}`);
|
|
174
177
|
maybeWarnVersionMismatch(entry.package, version);
|
|
175
178
|
return mod[entry.className];
|
package/src/env-scanner.ts
CHANGED
|
@@ -63,6 +63,7 @@ export interface ScanEnvironmentOptions {
|
|
|
63
63
|
npmGlobalDir?: string | null;
|
|
64
64
|
probeVendorCli?: (adapter: AdapterName, meta: AdapterMetadata) => Promise<VendorCliReadiness>;
|
|
65
65
|
resolveAdapterDir?: (adapter: AdapterName) => string | null;
|
|
66
|
+
findBinary?: (name: string) => string | null;
|
|
66
67
|
}
|
|
67
68
|
|
|
68
69
|
function detectPackageManager(): PackageManager {
|
|
@@ -310,6 +311,7 @@ export async function scanEnvironment(options: ScanEnvironmentOptions = {}): Pro
|
|
|
310
311
|
const resolveAdapterDir = options.resolveAdapterDir ?? getAdapterDir;
|
|
311
312
|
const bunGlobalDir = getBunGlobalDir(env, options.bunGlobalDir);
|
|
312
313
|
const npmGlobalDir = getNpmGlobalDir(env, options.npmGlobalDir);
|
|
314
|
+
const findBinary = options.findBinary ?? ((name: string) => Bun.which(name) ?? null);
|
|
313
315
|
|
|
314
316
|
const adapters = {} as Record<AdapterName, AdapterReadiness>;
|
|
315
317
|
const notes: string[] = [];
|
|
@@ -341,6 +343,10 @@ export async function scanEnvironment(options: ScanEnvironmentOptions = {}): Pro
|
|
|
341
343
|
}
|
|
342
344
|
|
|
343
345
|
const socketPath = getMempalaceSocket(env);
|
|
346
|
+
const mempalaceBinary = findBinary("mempalace");
|
|
347
|
+
if (mempalaceBinary && !existsSync(socketPath)) {
|
|
348
|
+
notes.push(`mempalace: binary found at ${mempalaceBinary}, but socket ${socketPath} was not detected. Set MEMPALACE_SOCKET if MemPalace uses a custom socket path.`);
|
|
349
|
+
}
|
|
344
350
|
|
|
345
351
|
return {
|
|
346
352
|
packageManager: detectPackageManager(),
|
|
@@ -349,6 +355,8 @@ export async function scanEnvironment(options: ScanEnvironmentOptions = {}): Pro
|
|
|
349
355
|
mempalace: {
|
|
350
356
|
available: existsSync(socketPath),
|
|
351
357
|
socketPath,
|
|
358
|
+
binaryInstalled: !!mempalaceBinary,
|
|
359
|
+
binaryPath: mempalaceBinary ?? undefined,
|
|
352
360
|
},
|
|
353
361
|
},
|
|
354
362
|
notes,
|
package/src/init-types.ts
CHANGED
package/src/prompts.ts
CHANGED
|
@@ -38,6 +38,11 @@ function formatAdapterLine(adapter: AdapterName, readiness: AdapterReadiness): s
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
export function renderScanReport(scan: ScanReport): string {
|
|
41
|
+
const memorySummary = scan.memory.mempalace.available
|
|
42
|
+
? `available (${scan.memory.mempalace.socketPath})`
|
|
43
|
+
: scan.memory.mempalace.binaryInstalled
|
|
44
|
+
? `installed at ${scan.memory.mempalace.binaryPath}; socket not detected at ${scan.memory.mempalace.socketPath}`
|
|
45
|
+
: `not-detected (${scan.memory.mempalace.socketPath})`;
|
|
41
46
|
const lines = [
|
|
42
47
|
`Package manager: ${scan.packageManager}`,
|
|
43
48
|
"",
|
|
@@ -49,9 +54,7 @@ export function renderScanReport(scan: ScanReport): string {
|
|
|
49
54
|
}
|
|
50
55
|
|
|
51
56
|
lines.push("");
|
|
52
|
-
lines.push(
|
|
53
|
-
`Memory: mempalace ${scan.memory.mempalace.available ? "available" : "not-detected"} (${scan.memory.mempalace.socketPath})`,
|
|
54
|
-
);
|
|
57
|
+
lines.push(`Memory: mempalace ${memorySummary}`);
|
|
55
58
|
|
|
56
59
|
if (scan.notes.length > 0) {
|
|
57
60
|
lines.push("");
|
package/src/utils.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { join, normalize, resolve, sep, dirname } from "node:path";
|
|
6
6
|
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { homedir } from "node:os";
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
/**
|
|
@@ -129,7 +130,65 @@ export function detectProject(startDir: string): string | null {
|
|
|
129
130
|
* (via import.meta.resolve). Post-0.6.0 this is the primary path —
|
|
130
131
|
* the CLI no longer bundles adapter source.
|
|
131
132
|
*/
|
|
132
|
-
|
|
133
|
+
function resolvePackageRootFromEntry(pkgName: string, entryRef: string): string | null {
|
|
134
|
+
const pathRef = entryRef.startsWith("file://") ? fileURLToPath(entryRef) : entryRef;
|
|
135
|
+
let dir = resolve(pathRef, "..");
|
|
136
|
+
const fsRoot = resolve("/");
|
|
137
|
+
|
|
138
|
+
while (dir !== fsRoot) {
|
|
139
|
+
const pkgJson = join(dir, "package.json");
|
|
140
|
+
if (existsSync(pkgJson)) {
|
|
141
|
+
try {
|
|
142
|
+
const contents = JSON.parse(readFileSync(pkgJson, "utf-8")) as { name?: string };
|
|
143
|
+
if (contents.name === pkgName) {
|
|
144
|
+
return dir;
|
|
145
|
+
}
|
|
146
|
+
} catch {
|
|
147
|
+
// Keep walking up.
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const parent = resolve(dir, "..");
|
|
151
|
+
if (parent === dir) break;
|
|
152
|
+
dir = parent;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function getGlobalPackageDir(pkgName: string, env: Record<string, string | undefined> = process.env): string | null {
|
|
159
|
+
const searchRoots = [
|
|
160
|
+
env.AOS_BUN_GLOBAL_DIR,
|
|
161
|
+
join(homedir(), ".bun", "install", "global", "node_modules"),
|
|
162
|
+
env.AOS_NPM_GLOBAL_DIR,
|
|
163
|
+
env.npm_config_prefix ? join(env.npm_config_prefix, "lib", "node_modules") : null,
|
|
164
|
+
].filter((value): value is string => typeof value === "string" && value.length > 0);
|
|
165
|
+
|
|
166
|
+
if (!env.AOS_NPM_GLOBAL_DIR && !env.npm_config_prefix) {
|
|
167
|
+
const npmPrefix = Bun.spawnSync(["npm", "prefix", "-g"], {
|
|
168
|
+
stdin: "ignore",
|
|
169
|
+
stdout: "pipe",
|
|
170
|
+
stderr: "ignore",
|
|
171
|
+
});
|
|
172
|
+
const out = npmPrefix.stdout.toString().trim();
|
|
173
|
+
if (out) {
|
|
174
|
+
searchRoots.push(join(out, "lib", "node_modules"));
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const seen = new Set<string>();
|
|
179
|
+
for (const root of searchRoots) {
|
|
180
|
+
if (seen.has(root)) continue;
|
|
181
|
+
seen.add(root);
|
|
182
|
+
const candidate = join(root, pkgName);
|
|
183
|
+
if (existsSync(join(candidate, "package.json"))) {
|
|
184
|
+
return candidate;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export function getAdapterDir(adapterName: string, env: Record<string, string | undefined> = process.env): string | null {
|
|
133
192
|
// 1. Monorepo dev layout
|
|
134
193
|
const monorepoDir = resolve(import.meta.dir, "../..", "adapters", adapterName);
|
|
135
194
|
if (existsSync(join(monorepoDir, "src", "index.ts"))) {
|
|
@@ -137,42 +196,24 @@ export function getAdapterDir(adapterName: string): string | null {
|
|
|
137
196
|
}
|
|
138
197
|
|
|
139
198
|
// 2. Installed @aos-harness/<name>-adapter package
|
|
199
|
+
const pkgName = `@aos-harness/${adapterName}-adapter`;
|
|
140
200
|
try {
|
|
141
|
-
const pkgName = `@aos-harness/${adapterName}-adapter`;
|
|
142
201
|
const resolver = (import.meta as any).resolve;
|
|
143
|
-
if (typeof resolver
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
const mainUrl: string = resolver(pkgName);
|
|
148
|
-
if (!mainUrl.startsWith("file://")) return null;
|
|
149
|
-
const mainPath = mainUrl.slice("file://".length);
|
|
150
|
-
// Walk up until we find a package.json with the matching name
|
|
151
|
-
let dir = resolve(mainPath, "..");
|
|
152
|
-
const fsRoot = resolve("/");
|
|
153
|
-
while (dir !== fsRoot) {
|
|
154
|
-
const pkgJson = join(dir, "package.json");
|
|
155
|
-
if (existsSync(pkgJson)) {
|
|
156
|
-
try {
|
|
157
|
-
// Confirm it's the right package; if so, return dir.
|
|
158
|
-
const contents = JSON.parse(
|
|
159
|
-
require("node:fs").readFileSync(pkgJson, "utf-8"),
|
|
160
|
-
) as { name?: string };
|
|
161
|
-
if (contents.name === pkgName) {
|
|
162
|
-
if (existsSync(join(dir, "src", "index.ts"))) return dir;
|
|
163
|
-
}
|
|
164
|
-
} catch {
|
|
165
|
-
// Fall through — keep walking up.
|
|
166
|
-
}
|
|
202
|
+
if (typeof resolver === "function") {
|
|
203
|
+
const resolvedDir = resolvePackageRootFromEntry(pkgName, resolver(pkgName));
|
|
204
|
+
if (resolvedDir && existsSync(join(resolvedDir, "src", "index.ts"))) {
|
|
205
|
+
return resolvedDir;
|
|
167
206
|
}
|
|
168
|
-
const parent = resolve(dir, "..");
|
|
169
|
-
if (parent === dir) break;
|
|
170
|
-
dir = parent;
|
|
171
207
|
}
|
|
172
208
|
} catch {
|
|
173
|
-
//
|
|
174
|
-
return null;
|
|
209
|
+
// Fall through to explicit global package directory detection.
|
|
175
210
|
}
|
|
211
|
+
|
|
212
|
+
const globalDir = getGlobalPackageDir(pkgName, env);
|
|
213
|
+
if (globalDir && existsSync(join(globalDir, "src", "index.ts"))) {
|
|
214
|
+
return globalDir;
|
|
215
|
+
}
|
|
216
|
+
|
|
176
217
|
return null;
|
|
177
218
|
}
|
|
178
219
|
|