@botiverse/oar 0.34.0 → 0.34.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/README.md +4 -4
- package/dist/contracts/session-options.d.ts +6 -5
- package/dist/contracts/session-options.d.ts.map +1 -1
- package/dist/runtimes/claude/launch.d.ts +5 -8
- package/dist/runtimes/claude/launch.d.ts.map +1 -1
- package/dist/runtimes/claude/launch.js +14 -36
- package/dist/runtimes/claude/launch.js.map +1 -1
- package/dist/runtimes/claude/mcp-config.d.ts +19 -0
- package/dist/runtimes/claude/mcp-config.d.ts.map +1 -0
- package/dist/runtimes/claude/mcp-config.js +137 -0
- package/dist/runtimes/claude/mcp-config.js.map +1 -0
- package/dist/runtimes/opencode/prompt-config.d.ts.map +1 -1
- package/dist/runtimes/opencode/prompt-config.js +8 -5
- package/dist/runtimes/opencode/prompt-config.js.map +1 -1
- package/dist/shared/private-temp.d.ts +10 -0
- package/dist/shared/private-temp.d.ts.map +1 -0
- package/dist/shared/private-temp.js +78 -0
- package/dist/shared/private-temp.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -97,10 +97,10 @@ opencode also refuse a `resume` in another directory than the session's own
|
|
|
97
97
|
`SessionOptions.mcpServers` attaches MCP servers (stdio `{name, command,
|
|
98
98
|
args?, env?}` or streamable HTTP `{name, type: "http", url, headers?}`) to
|
|
99
99
|
one session, on top of the runtime's own: claude reads them from a 0600
|
|
100
|
-
|
|
101
|
-
overrides, grok, kimi, opencode and antigravity from
|
|
102
|
-
`session/resume`, pi from an extension that registers
|
|
103
|
-
them. Give them again on `resume`. Their `env` and `headers` values never
|
|
100
|
+
FIFO that never puts them on a disk (a temporary file on Windows), codex
|
|
101
|
+
from its thread config overrides, grok, kimi, opencode and antigravity from
|
|
102
|
+
ACP `session/new` / `session/resume`, pi from an extension that registers
|
|
103
|
+
them; cursor refuses them. Give them again on `resume`. Their `env` and `headers` values never
|
|
104
104
|
appear in a record or an error; antigravity, which would store them in its
|
|
105
105
|
conversation database, refuses an entry carrying them. See the
|
|
106
106
|
[channels](https://github.com/botiverse/oar/blob/main/docs/spec/runtime-matrix.md#refused-session-options)
|
|
@@ -63,11 +63,12 @@ export interface SessionOptions {
|
|
|
63
63
|
/**
|
|
64
64
|
* MCP servers attached to THIS session, on top of the servers the runtime
|
|
65
65
|
* is configured with: oar never edits the runtime's configuration or
|
|
66
|
-
* drops the user's servers (claude reads the session's from a 0600
|
|
67
|
-
*
|
|
68
|
-
* `thread/start` / `thread/resume` config
|
|
69
|
-
* and antigravity from ACP `session/new` /
|
|
70
|
-
* pi from an extension that registers
|
|
66
|
+
* drops the user's servers (claude reads the session's from a 0600 FIFO
|
|
67
|
+
* oar removes once read, on Windows a temporary file removed when claude
|
|
68
|
+
* exits; codex from its `thread/start` / `thread/resume` config
|
|
69
|
+
* overrides; grok, kimi, opencode and antigravity from ACP `session/new` /
|
|
70
|
+
* `session/resume` `mcpServers`; pi from an extension that registers
|
|
71
|
+
* them). Not remembered: give them
|
|
71
72
|
* again on `resume`, where oar attaches them to the resumed session too. A
|
|
72
73
|
* server named like one the user configured meets it the runtime's way for
|
|
73
74
|
* this session (codex: merged into it field by field; pi: the open fails
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-options.d.ts","sourceRoot":"","sources":["../../src/contracts/session-options.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;GAUG;AACH,MAAM,MAAM,SAAS,GACjB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAAE,GACvI;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAAE,CAAC;AAEhI;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,0SAA0S;IAC1S,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,kPAAkP;IAClP,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,kyBAAkyB;IAClyB,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAChD,iXAAiX;IACjX,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,mZAAmZ;IACnZ,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC
|
|
1
|
+
{"version":3,"file":"session-options.d.ts","sourceRoot":"","sources":["../../src/contracts/session-options.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;GAUG;AACH,MAAM,MAAM,SAAS,GACjB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAAE,GACvI;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAAE,CAAC;AAEhI;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,0SAA0S;IAC1S,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,kPAAkP;IAClP,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,kyBAAkyB;IAClyB,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAChD,iXAAiX;IACjX,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,mZAAmZ;IACnZ,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;CAC5C"}
|
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SessionOptions } from "../../contracts/session.js";
|
|
2
2
|
import { type LineProcess } from "../../shared/executable/index.js";
|
|
3
3
|
/** The process a claude session drives. */
|
|
4
4
|
export type ClaudeProcess = LineProcess;
|
|
5
|
-
/** claude's `--mcp-config` document for the entries: stdio `{type, command, args, env}`, http `{type, url, headers}`. */
|
|
6
|
-
export declare function claudeMcpConfig(servers: readonly McpServer[]): {
|
|
7
|
-
readonly mcpServers: Record<string, unknown>;
|
|
8
|
-
};
|
|
9
5
|
/**
|
|
10
6
|
* Start claude for a session (`--session-id`, or `--resume` an existing one)
|
|
11
|
-
* and wait until it runs; with MCP servers, their config
|
|
12
|
-
*
|
|
13
|
-
*
|
|
7
|
+
* and wait until it runs; with MCP servers, their config is handed over as
|
|
8
|
+
* mcp-config.ts describes and gone at the latest when the process exits.
|
|
9
|
+
* Rejects on a list with an empty or repeated name before anything starts,
|
|
10
|
+
* and when claude cannot be spawned.
|
|
14
11
|
*/
|
|
15
12
|
export declare function launchClaude(command: string, sessionId: string, options: SessionOptions): Promise<ClaudeProcess>;
|
|
16
13
|
//# sourceMappingURL=launch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"launch.d.ts","sourceRoot":"","sources":["../../../src/runtimes/claude/launch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"launch.d.ts","sourceRoot":"","sources":["../../../src/runtimes/claude/launch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAgBtF,2CAA2C;AAC3C,MAAM,MAAM,aAAa,GAAG,WAAW,CAAC;AAwBxC;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAwBtH"}
|
|
@@ -1,34 +1,6 @@
|
|
|
1
|
-
import { rmSync } from "node:fs";
|
|
2
|
-
import { mkdtemp, writeFile } from "node:fs/promises";
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
4
|
-
import path from "node:path";
|
|
5
1
|
import { spawnLineProcess } from "../../shared/executable/index.js";
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
export function claudeMcpConfig(servers) {
|
|
9
|
-
return {
|
|
10
|
-
mcpServers: Object.fromEntries(servers.map((server) => [server.name, isHttpMcpServer(server)
|
|
11
|
-
? { type: "http", url: server.url, ...(server.headers === undefined ? {} : { headers: server.headers }) }
|
|
12
|
-
: { type: "stdio", command: server.command, args: server.args ?? [], ...(server.env === undefined ? {} : { env: server.env }) }])),
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
/** The entries' config in a 0600 file in a fresh temporary directory, and how to delete both (synchronously, so an exit handler finishes before `exited` resolves). */
|
|
16
|
-
async function writeMcpConfig(servers) {
|
|
17
|
-
checkMcpServerNames(servers);
|
|
18
|
-
const directory = await mkdtemp(path.join(tmpdir(), "oar-claude-mcp-"));
|
|
19
|
-
const file = path.join(directory, "mcp.json");
|
|
20
|
-
const remove = () => {
|
|
21
|
-
rmSync(directory, { recursive: true, force: true });
|
|
22
|
-
};
|
|
23
|
-
try {
|
|
24
|
-
await writeFile(file, JSON.stringify(claudeMcpConfig(servers)), { mode: 0o600, flag: "wx" });
|
|
25
|
-
}
|
|
26
|
-
catch (error) {
|
|
27
|
-
remove();
|
|
28
|
-
throw error;
|
|
29
|
-
}
|
|
30
|
-
return { path: file, remove };
|
|
31
|
-
}
|
|
2
|
+
import { givenMcpServers } from "../../shared/mcp-servers.js";
|
|
3
|
+
import { handOverMcpConfig, sweepAbandonedMcpConfigs } from "./mcp-config.js";
|
|
32
4
|
function spawnClaude(command, sessionId, options, mcpConfig) {
|
|
33
5
|
return spawnLineProcess(command, [
|
|
34
6
|
"-p",
|
|
@@ -52,27 +24,33 @@ function spawnClaude(command, sessionId, options, mcpConfig) {
|
|
|
52
24
|
}
|
|
53
25
|
/**
|
|
54
26
|
* Start claude for a session (`--session-id`, or `--resume` an existing one)
|
|
55
|
-
* and wait until it runs; with MCP servers, their config
|
|
56
|
-
*
|
|
57
|
-
*
|
|
27
|
+
* and wait until it runs; with MCP servers, their config is handed over as
|
|
28
|
+
* mcp-config.ts describes and gone at the latest when the process exits.
|
|
29
|
+
* Rejects on a list with an empty or repeated name before anything starts,
|
|
30
|
+
* and when claude cannot be spawned.
|
|
58
31
|
*/
|
|
59
32
|
export async function launchClaude(command, sessionId, options) {
|
|
60
33
|
const servers = givenMcpServers(options.mcpServers);
|
|
61
|
-
|
|
34
|
+
// Either way, what dead hosts left behind goes first (mcp-config.ts).
|
|
35
|
+
const mcpConfig = servers === null ? null : await handOverMcpConfig(servers);
|
|
36
|
+
if (mcpConfig === null) {
|
|
37
|
+
await sweepAbandonedMcpConfigs();
|
|
38
|
+
}
|
|
62
39
|
let child = null;
|
|
63
40
|
try {
|
|
64
41
|
child = spawnClaude(command, sessionId, options, mcpConfig?.path ?? null);
|
|
65
42
|
}
|
|
66
43
|
finally {
|
|
67
44
|
if (child === null) {
|
|
68
|
-
mcpConfig?.
|
|
45
|
+
mcpConfig?.end();
|
|
69
46
|
}
|
|
70
47
|
}
|
|
71
48
|
if (mcpConfig !== null) {
|
|
72
49
|
// Fires once, for an exit or a failed spawn alike, before `exited` resolves.
|
|
73
50
|
child.onExit(() => {
|
|
74
|
-
mcpConfig.
|
|
51
|
+
mcpConfig.end();
|
|
75
52
|
});
|
|
53
|
+
mcpConfig.start();
|
|
76
54
|
}
|
|
77
55
|
await child.spawned;
|
|
78
56
|
return child;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"launch.js","sourceRoot":"","sources":["../../../src/runtimes/claude/launch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"launch.js","sourceRoot":"","sources":["../../../src/runtimes/claude/launch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { McpServer } from "../../contracts/session.js";
|
|
2
|
+
/** How the config reaches one claude process: the `--mcp-config` path, `start()` once claude is spawned, `end()` once it has exited or failed to spawn (idempotent). */
|
|
3
|
+
export interface McpConfigHandoff {
|
|
4
|
+
readonly path: string;
|
|
5
|
+
start(): void;
|
|
6
|
+
end(): void;
|
|
7
|
+
}
|
|
8
|
+
/** claude's `--mcp-config` document for the entries: stdio `{type, command, args, env}`, http `{type, url, headers}`. */
|
|
9
|
+
export declare function claudeMcpConfig(servers: readonly McpServer[]): {
|
|
10
|
+
readonly mcpServers: Record<string, unknown>;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Before any claude starts, with servers or without: remove what hosts that
|
|
14
|
+
* died left behind, letting a claude still waiting on such a FIFO go.
|
|
15
|
+
*/
|
|
16
|
+
export declare function sweepAbandonedMcpConfigs(): Promise<void>;
|
|
17
|
+
/** The handoff for these entries (sweeping as above first). Rejects on an empty or repeated name before anything is created. */
|
|
18
|
+
export declare function handOverMcpConfig(servers: readonly McpServer[]): Promise<McpConfigHandoff>;
|
|
19
|
+
//# sourceMappingURL=mcp-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-config.d.ts","sourceRoot":"","sources":["../../../src/runtimes/claude/mcp-config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AA+B5D,wKAAwK;AACxK,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,KAAK,IAAI,IAAI,CAAC;IACd,GAAG,IAAI,IAAI,CAAC;CACb;AAED,yHAAyH;AACzH,wBAAgB,eAAe,CAAC,OAAO,EAAE,SAAS,SAAS,EAAE,GAAG;IAAE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAM/G;AA2FD;;;GAGG;AACH,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,IAAI,CAAC,CAE9D;AAED,gIAAgI;AAChI,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,SAAS,SAAS,EAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAuBhG"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { constants } from "node:fs";
|
|
2
|
+
import { open, writeFile } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
5
|
+
import { runExecutable } from "../../shared/executable/run.js";
|
|
6
|
+
import { checkMcpServerNames, isHttpMcpServer } from "../../shared/mcp-servers.js";
|
|
7
|
+
import { privateTempDir, sweepPrivateTempDirs } from "../../shared/private-temp.js";
|
|
8
|
+
/** claude's `--mcp-config` document for the entries: stdio `{type, command, args, env}`, http `{type, url, headers}`. */
|
|
9
|
+
export function claudeMcpConfig(servers) {
|
|
10
|
+
return {
|
|
11
|
+
mcpServers: Object.fromEntries(servers.map((server) => [server.name, isHttpMcpServer(server)
|
|
12
|
+
? { type: "http", url: server.url, ...(server.headers === undefined ? {} : { headers: server.headers }) }
|
|
13
|
+
: { type: "stdio", command: server.command, args: server.args ?? [], ...(server.env === undefined ? {} : { env: server.env }) }])),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function errorCode(error) {
|
|
17
|
+
return error instanceof Error && "code" in error ? error.code : undefined;
|
|
18
|
+
}
|
|
19
|
+
/** A 0600 FIFO at `file`; false where none can be made. */
|
|
20
|
+
async function makeFifo(file) {
|
|
21
|
+
if (process.platform === "win32") {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
const made = await runExecutable("mkfifo", ["-m", "600", file]);
|
|
25
|
+
return made.ok;
|
|
26
|
+
}
|
|
27
|
+
/** The write end once a reader has the FIFO open; undefined when `stopped()` first. */
|
|
28
|
+
async function openWhenRead(file, stopped) {
|
|
29
|
+
let wait = 5;
|
|
30
|
+
while (!stopped()) {
|
|
31
|
+
try {
|
|
32
|
+
// oxlint-disable-next-line no-await-in-loop -- polling: each attempt waits for the previous one.
|
|
33
|
+
return await open(file, constants.O_WRONLY | constants.O_NONBLOCK);
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
if (errorCode(error) !== "ENXIO") {
|
|
37
|
+
throw error;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// oxlint-disable-next-line no-await-in-loop -- as above; unref'd, so polling alone keeps no host alive.
|
|
41
|
+
await delay(wait, undefined, { ref: false });
|
|
42
|
+
wait = Math.min(wait * 2, 100);
|
|
43
|
+
}
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
/** Write all of `content` to a non-blocking pipe: a full pipe answers EAGAIN until the reader drains it. */
|
|
47
|
+
async function writeAll(handle, content, stopped) {
|
|
48
|
+
let rest = content;
|
|
49
|
+
while (rest.length > 0 && !stopped()) {
|
|
50
|
+
try {
|
|
51
|
+
// oxlint-disable-next-line no-await-in-loop -- sequential writes to one pipe.
|
|
52
|
+
const { bytesWritten } = await handle.write(rest);
|
|
53
|
+
rest = rest.subarray(bytesWritten);
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
if (errorCode(error) !== "EAGAIN") {
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
// oxlint-disable-next-line no-await-in-loop -- as above.
|
|
60
|
+
await delay(5, undefined, { ref: false });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function fifoHandoff(file, content, directory) {
|
|
65
|
+
let ended = false;
|
|
66
|
+
const stopped = () => ended;
|
|
67
|
+
const end = () => {
|
|
68
|
+
ended = true;
|
|
69
|
+
directory.remove();
|
|
70
|
+
};
|
|
71
|
+
const feed = async () => {
|
|
72
|
+
const handle = await openWhenRead(file, stopped);
|
|
73
|
+
if (handle === undefined) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
await writeAll(handle, Buffer.from(content), stopped);
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
await handle.close();
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
return {
|
|
84
|
+
path: file,
|
|
85
|
+
start: () => {
|
|
86
|
+
// A failed feed (claude closed its end early) leaves claude to report
|
|
87
|
+
// the config it could not read; the directory goes either way.
|
|
88
|
+
void (async () => {
|
|
89
|
+
try {
|
|
90
|
+
await feed();
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
// claude's own error is the report.
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
end();
|
|
97
|
+
}
|
|
98
|
+
})();
|
|
99
|
+
},
|
|
100
|
+
end,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
const PREFIX = "oar-claude-mcp-";
|
|
104
|
+
/**
|
|
105
|
+
* Before any claude starts, with servers or without: remove what hosts that
|
|
106
|
+
* died left behind, letting a claude still waiting on such a FIFO go.
|
|
107
|
+
*/
|
|
108
|
+
export async function sweepAbandonedMcpConfigs() {
|
|
109
|
+
await sweepPrivateTempDirs(PREFIX);
|
|
110
|
+
}
|
|
111
|
+
/** The handoff for these entries (sweeping as above first). Rejects on an empty or repeated name before anything is created. */
|
|
112
|
+
export async function handOverMcpConfig(servers) {
|
|
113
|
+
checkMcpServerNames(servers);
|
|
114
|
+
const directory = await privateTempDir(PREFIX);
|
|
115
|
+
const file = path.join(directory.path, "mcp.json");
|
|
116
|
+
const content = JSON.stringify(claudeMcpConfig(servers));
|
|
117
|
+
try {
|
|
118
|
+
if (await makeFifo(file)) {
|
|
119
|
+
return fifoHandoff(file, content, directory);
|
|
120
|
+
}
|
|
121
|
+
await writeFile(file, content, { mode: 0o600, flag: "wx" });
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
directory.remove();
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
path: file,
|
|
129
|
+
start: () => {
|
|
130
|
+
// claude reads the file at startup; it goes when claude exits (end).
|
|
131
|
+
},
|
|
132
|
+
end: () => {
|
|
133
|
+
directory.remove();
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=mcp-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-config.js","sourceRoot":"","sources":["../../../src/runtimes/claude/mcp-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt-config.d.ts","sourceRoot":"","sources":["../../../src/runtimes/opencode/prompt-config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"prompt-config.d.ts","sourceRoot":"","sources":["../../../src/runtimes/opencode/prompt-config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,EAAiB,KAAK,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACtF,OAAO,EAAY,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGjE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAYrE;AA2DD,4EAA4E;AAC5E,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,GAAE,gBAAgC,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA+B3J;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAMhF"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { tmpdir } from "node:os";
|
|
1
|
+
import { rm, writeFile } from "node:fs/promises";
|
|
3
2
|
import path from "node:path";
|
|
4
3
|
import { UnsupportedOptionError } from "../../contracts/errors.js";
|
|
5
4
|
import { processFailure } from "../../shared/executable/diagnostics.js";
|
|
6
5
|
import { runExecutable } from "../../shared/executable/run.js";
|
|
7
6
|
import { asRecord } from "../../shared/json.js";
|
|
7
|
+
import { privateTempDir } from "../../shared/private-temp.js";
|
|
8
8
|
export function validateOpenCodePrompts(options) {
|
|
9
9
|
const option = options.systemPrompt !== undefined ? "systemPrompt" : "appendSystemPrompt";
|
|
10
10
|
if (options.systemPrompt === undefined && options.appendSystemPrompt === undefined) {
|
|
@@ -76,16 +76,19 @@ async function activeAgent(command, options, run) {
|
|
|
76
76
|
export async function prepareOpenCodePrompts(command, options, run = runExecutable) {
|
|
77
77
|
validateOpenCodePrompts(options);
|
|
78
78
|
const agent = options.systemPrompt === undefined ? undefined : await activeAgent(command, options, run);
|
|
79
|
-
|
|
79
|
+
// privateTempDir: a host that ends without disposing leaves it to the backstops there.
|
|
80
|
+
const directory = options.appendSystemPrompt === undefined ? undefined : await privateTempDir("oar-opencode-prompt-");
|
|
80
81
|
let removal = undefined;
|
|
81
82
|
const cleanup = async () => {
|
|
82
83
|
if (directory !== undefined) {
|
|
83
|
-
removal ??= rm(directory, { recursive: true, force: true });
|
|
84
|
+
removal ??= rm(directory.path, { recursive: true, force: true });
|
|
84
85
|
await removal;
|
|
86
|
+
// Already gone; this only takes it off the exit backstop.
|
|
87
|
+
directory.remove();
|
|
85
88
|
}
|
|
86
89
|
};
|
|
87
90
|
try {
|
|
88
|
-
const instructions = directory === undefined ? undefined : path.join(directory, "instructions.md");
|
|
91
|
+
const instructions = directory === undefined ? undefined : path.join(directory.path, "instructions.md");
|
|
89
92
|
if (instructions !== undefined) {
|
|
90
93
|
await writeFile(instructions, options.appendSystemPrompt ?? "", { mode: 0o600 });
|
|
91
94
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt-config.js","sourceRoot":"","sources":["../../../src/runtimes/opencode/prompt-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"prompt-config.js","sourceRoot":"","sources":["../../../src/runtimes/opencode/prompt-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** A directory `privateTempDir` made: its path, and its removal (synchronous, idempotent). */
|
|
2
|
+
export interface PrivateTempDir {
|
|
3
|
+
readonly path: string;
|
|
4
|
+
remove(): void;
|
|
5
|
+
}
|
|
6
|
+
/** Remove `prefix` directories whose host pid no longer runs, releasing their FIFOs first; one that cannot be removed (another user's) stays. */
|
|
7
|
+
export declare function sweepPrivateTempDirs(prefix: string): Promise<void>;
|
|
8
|
+
/** A fresh 0700 directory for one runtime process, removed by `remove()` or, failing that, by the backstops above. */
|
|
9
|
+
export declare function privateTempDir(prefix: string): Promise<PrivateTempDir>;
|
|
10
|
+
//# sourceMappingURL=private-temp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"private-temp.d.ts","sourceRoot":"","sources":["../../src/shared/private-temp.ts"],"names":[],"mappings":"AAwBA,8FAA8F;AAC9F,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,MAAM,IAAI,IAAI,CAAC;CAChB;AA8CD,iJAAiJ;AACjJ,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYxE;AAED,sHAAsH;AACtH,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAe5E"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { closeSync, constants, lstatSync, openSync, readdirSync, rmSync } from "node:fs";
|
|
2
|
+
import { mkdtemp, readdir, rm } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
const live = new Set();
|
|
6
|
+
let hooked = false;
|
|
7
|
+
function releaseFifos(directory) {
|
|
8
|
+
let names = [];
|
|
9
|
+
try {
|
|
10
|
+
names = readdirSync(directory);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
for (const name of names) {
|
|
16
|
+
const file = path.join(directory, name);
|
|
17
|
+
try {
|
|
18
|
+
if (lstatSync(file).isFIFO()) {
|
|
19
|
+
closeSync(openSync(file, constants.O_WRONLY | constants.O_NONBLOCK));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// ENXIO: no reader is waiting.
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function removeDirectory(directory) {
|
|
28
|
+
releaseFifos(directory);
|
|
29
|
+
rmSync(directory, { recursive: true, force: true });
|
|
30
|
+
}
|
|
31
|
+
function removeLive() {
|
|
32
|
+
for (const directory of live) {
|
|
33
|
+
removeDirectory(directory);
|
|
34
|
+
}
|
|
35
|
+
live.clear();
|
|
36
|
+
}
|
|
37
|
+
function running(pid) {
|
|
38
|
+
try {
|
|
39
|
+
process.kill(pid, 0);
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
// EPERM: the pid runs, as another user.
|
|
44
|
+
return error instanceof Error && "code" in error && error.code === "EPERM";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/** Remove `prefix` directories whose host pid no longer runs, releasing their FIFOs first; one that cannot be removed (another user's) stays. */
|
|
48
|
+
export async function sweepPrivateTempDirs(prefix) {
|
|
49
|
+
const root = tmpdir();
|
|
50
|
+
const names = await readdir(root).catch(() => []);
|
|
51
|
+
await Promise.all(names.map(async (name) => {
|
|
52
|
+
const pid = name.startsWith(prefix) ? /^(\d+)-/u.exec(name.slice(prefix.length))?.[1] : undefined;
|
|
53
|
+
if (pid === undefined || Number(pid) === process.pid || running(Number(pid))) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const directory = path.join(root, name);
|
|
57
|
+
releaseFifos(directory);
|
|
58
|
+
await rm(directory, { recursive: true, force: true }).catch(() => undefined);
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
/** A fresh 0700 directory for one runtime process, removed by `remove()` or, failing that, by the backstops above. */
|
|
62
|
+
export async function privateTempDir(prefix) {
|
|
63
|
+
await sweepPrivateTempDirs(prefix);
|
|
64
|
+
const directory = await mkdtemp(path.join(tmpdir(), `${prefix}${String(process.pid)}-`));
|
|
65
|
+
if (!hooked) {
|
|
66
|
+
process.on("exit", removeLive);
|
|
67
|
+
hooked = true;
|
|
68
|
+
}
|
|
69
|
+
live.add(directory);
|
|
70
|
+
return {
|
|
71
|
+
path: directory,
|
|
72
|
+
remove: () => {
|
|
73
|
+
live.delete(directory);
|
|
74
|
+
removeDirectory(directory);
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=private-temp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"private-temp.js","sourceRoot":"","sources":["../../src/shared/private-temp.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@botiverse/oar",
|
|
3
|
-
"version": "0.34.
|
|
3
|
+
"version": "0.34.1",
|
|
4
4
|
"description": "A programming interface for all agent harnesses: provider-independent contracts for controlling and observing agent runtimes",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|