@diffexai/diffex 0.3.0 → 0.3.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/CHANGELOG.md +17 -0
- package/dist/cli/args.d.ts +2 -0
- package/dist/cli/args.js +39 -0
- package/dist/core/agent-session-services.d.ts +1 -0
- package/dist/core/agent-session-services.js +1 -0
- package/dist/core/agent-session.d.ts +4 -0
- package/dist/core/agent-session.js +5 -1
- package/dist/core/sdk.d.ts +3 -0
- package/dist/core/sdk.js +1 -0
- package/dist/core/subagents/services.d.ts +2 -0
- package/dist/core/subagents/services.js +2 -0
- package/dist/core/tools/bash.js +47 -12
- package/dist/index.d.ts +1 -0
- package/dist/main.js +4 -0
- package/dist/modes/print-mode.js +16 -13
- package/dist/node_modules/@diffexai/diffex-agent-core/distribution-components.json +4 -4
- package/dist/node_modules/@diffexai/diffex-agent-core/distribution-files.json +1 -1
- package/dist/node_modules/@diffexai/diffex-agent-core/package.json +1 -1
- package/dist/node_modules/@diffexai/diffex-ai/dist/providers/data/.manifest.json +1 -1
- package/dist/node_modules/@diffexai/diffex-ai/dist/providers/data/opencode-go.json +1 -1
- package/dist/node_modules/@diffexai/diffex-ai/dist/providers/data/openrouter.json +1 -1
- package/dist/node_modules/@diffexai/diffex-ai/distribution-components.json +3 -3
- package/dist/node_modules/@diffexai/diffex-ai/distribution-files.json +4 -4
- package/dist/node_modules/@diffexai/diffex-ai/package.json +1 -1
- package/dist/node_modules/@diffexai/diffex-client/distribution-components.json +3 -3
- package/dist/node_modules/@diffexai/diffex-client/distribution-files.json +1 -1
- package/dist/node_modules/@diffexai/diffex-client/package.json +1 -1
- package/dist/node_modules/@diffexai/diffex-harness-state/distribution-components.json +2 -2
- package/dist/node_modules/@diffexai/diffex-harness-state/distribution-files.json +1 -1
- package/dist/node_modules/@diffexai/diffex-harness-state/package.json +1 -1
- package/dist/node_modules/@diffexai/diffex-protocol/distribution-components.json +2 -2
- package/dist/node_modules/@diffexai/diffex-protocol/distribution-files.json +1 -1
- package/dist/node_modules/@diffexai/diffex-protocol/package.json +1 -1
- package/dist/node_modules/@diffexai/diffex-telemetry/distribution-components.json +2 -2
- package/dist/node_modules/@diffexai/diffex-telemetry/distribution-files.json +1 -1
- package/dist/node_modules/@diffexai/diffex-telemetry/package.json +1 -1
- package/dist/node_modules/@diffexai/diffex-tui/distribution-components.json +2 -2
- package/dist/node_modules/@diffexai/diffex-tui/distribution-files.json +1 -1
- package/dist/node_modules/@diffexai/diffex-tui/package.json +1 -1
- package/dist/utils/child-process.d.ts +5 -1
- package/dist/utils/child-process.js +9 -1
- package/dist/utils/owned-shell-processes.d.ts +23 -2
- package/dist/utils/owned-shell-processes.js +149 -39
- package/dist/utils/shell-process-identity.d.ts +11 -0
- package/dist/utils/shell-process-identity.js +61 -0
- package/dist/utils/shell.d.ts +1 -1
- package/dist/utils/shell.js +5 -5
- package/distribution-components.json +11 -11
- package/distribution-files.json +53 -45
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/release/distribution-manifest.json +4 -4
- package/release/install-package-lock.json +5 -5
- package/release/install-package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.3.1] - 2026-09-20
|
|
4
|
+
|
|
5
|
+
### New Features
|
|
6
|
+
|
|
7
|
+
- Added opt-in background services that survive CLI and subagent exit, with explicit environment ownership.
|
|
8
|
+
See [Background process lifetime](docs/background-processes.md) ([#242](https://github.com/diffexai/diffex/pull/242)).
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Added CLI and SDK options for environment-owned background processes on Linux and macOS, with durable ownership records and inherited policy for child sessions.
|
|
13
|
+
See [Background process lifetime](docs/background-processes.md) ([#242](https://github.com/diffexai/diffex/pull/242)).
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- Fixed successful background services being terminated after ownership transfers to the environment, including on later failures, interruption, session replacement, and disposal ([#242](https://github.com/diffexai/diffex/pull/242)).
|
|
18
|
+
- Fixed print-mode shutdown to await shared runtime disposal and handle SIGINT cleanup ([#242](https://github.com/diffexai/diffex/pull/242)).
|
|
19
|
+
|
|
3
20
|
## [0.3.0] - 2026-09-20
|
|
4
21
|
|
|
5
22
|
### New Features
|
package/dist/cli/args.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ import type { ExtensionFlag } from "../core/extensions/types.ts";
|
|
|
6
6
|
import type { TuiMode } from "../core/settings-manager.ts";
|
|
7
7
|
export type Mode = "text" | "json" | "rpc";
|
|
8
8
|
export interface Args {
|
|
9
|
+
backgroundProcessLifetime?: "session" | "environment";
|
|
10
|
+
backgroundProcessOwnershipDir?: string;
|
|
9
11
|
provider?: string;
|
|
10
12
|
model?: string;
|
|
11
13
|
apiKey?: string;
|
package/dist/cli/args.js
CHANGED
|
@@ -28,6 +28,29 @@ export function parseArgs(args) {
|
|
|
28
28
|
result.mode = mode;
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
|
+
else if (arg === "--background-process-lifetime" || arg.startsWith("--background-process-lifetime=")) {
|
|
32
|
+
const value = arg.includes("=") ? arg.slice(arg.indexOf("=") + 1) : args[i + 1];
|
|
33
|
+
if (!arg.includes("=") && value !== undefined && !value.startsWith("-"))
|
|
34
|
+
i++;
|
|
35
|
+
if (value === "session" || value === "environment")
|
|
36
|
+
result.backgroundProcessLifetime = value;
|
|
37
|
+
else
|
|
38
|
+
result.diagnostics.push({
|
|
39
|
+
type: "error",
|
|
40
|
+
message: "--background-process-lifetime requires session or environment",
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
else if (arg === "--background-process-ownership-dir" ||
|
|
44
|
+
arg.startsWith("--background-process-ownership-dir=")) {
|
|
45
|
+
const value = arg.includes("=") ? arg.slice(arg.indexOf("=") + 1) : args[i + 1];
|
|
46
|
+
if (value && !value.startsWith("-")) {
|
|
47
|
+
result.backgroundProcessOwnershipDir = value;
|
|
48
|
+
if (!arg.includes("="))
|
|
49
|
+
i++;
|
|
50
|
+
}
|
|
51
|
+
else
|
|
52
|
+
result.diagnostics.push({ type: "error", message: "--background-process-ownership-dir requires a path" });
|
|
53
|
+
}
|
|
31
54
|
else if (arg === "--continue" || arg === "-c") {
|
|
32
55
|
result.continue = true;
|
|
33
56
|
}
|
|
@@ -213,6 +236,18 @@ export function parseArgs(args) {
|
|
|
213
236
|
result.messages.push(arg);
|
|
214
237
|
}
|
|
215
238
|
}
|
|
239
|
+
if (result.backgroundProcessLifetime === "environment" && !result.backgroundProcessOwnershipDir) {
|
|
240
|
+
result.diagnostics.push({
|
|
241
|
+
type: "error",
|
|
242
|
+
message: "Environment lifetime requires --background-process-ownership-dir",
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
if (result.backgroundProcessOwnershipDir && result.backgroundProcessLifetime !== "environment") {
|
|
246
|
+
result.diagnostics.push({
|
|
247
|
+
type: "error",
|
|
248
|
+
message: "--background-process-ownership-dir requires environment lifetime",
|
|
249
|
+
});
|
|
250
|
+
}
|
|
216
251
|
return result;
|
|
217
252
|
}
|
|
218
253
|
export function printHelp(extensionFlags) {
|
|
@@ -248,6 +283,10 @@ ${chalk.bold("Options:")}
|
|
|
248
283
|
--append-system-prompt <text> Append text or file contents to the system prompt (can be used multiple times)
|
|
249
284
|
--mode <mode> Output mode: text (default), json, or rpc
|
|
250
285
|
--print, -p Non-interactive mode: process prompt and exit
|
|
286
|
+
--background-process-lifetime <session|environment>
|
|
287
|
+
Background shell ownership (default: session)
|
|
288
|
+
--background-process-ownership-dir <path>
|
|
289
|
+
Supervisor handoff records (required for environment lifetime)
|
|
251
290
|
--continue, -c Continue previous session
|
|
252
291
|
--resume, -r Select a session to resume
|
|
253
292
|
--session <path|id> Use specific session file or partial UUID
|
|
@@ -46,6 +46,7 @@ export interface CreateAgentSessionServicesOptions {
|
|
|
46
46
|
* have been resolved against those services.
|
|
47
47
|
*/
|
|
48
48
|
export interface CreateAgentSessionFromServicesOptions {
|
|
49
|
+
backgroundProcessPolicy?: CreateAgentSessionOptions["backgroundProcessPolicy"];
|
|
49
50
|
services: AgentSessionServices;
|
|
50
51
|
sessionManager: SessionManager;
|
|
51
52
|
sessionStartEvent?: SessionStartEvent;
|
|
@@ -137,6 +137,7 @@ export async function createAgentSessionFromServices(options) {
|
|
|
137
137
|
export async function createInternalAgentSessionFromServices(options, internalCustomTools = []) {
|
|
138
138
|
registerSubagentRuntimeDiagnosticSink(options.sessionManager, options.services.diagnostics);
|
|
139
139
|
return createInternalAgentSession({
|
|
140
|
+
backgroundProcessPolicy: options.backgroundProcessPolicy,
|
|
140
141
|
cwd: options.services.cwd,
|
|
141
142
|
agentDir: options.services.agentDir,
|
|
142
143
|
modelRuntime: options.services.modelRuntime,
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import { type Agent, type AgentEvent, type AgentMessage, type AgentState, type AgentTool, type TelemetryContext, type ThinkingLevel } from "@diffexai/diffex-agent-core";
|
|
16
16
|
import type { ImageContent, Model, TextContent } from "@diffexai/diffex-ai/compat";
|
|
17
17
|
import type { HarnessStateStore, HarnessVersion, HarnessVersionBundle, HarnessVersionList, HarnessWorkspaceIdentity } from "@diffexai/diffex-harness-state";
|
|
18
|
+
import { type BackgroundProcessPolicy } from "../utils/owned-shell-processes.ts";
|
|
18
19
|
import type { AgentSessionLifecycleObserver } from "./agent-session-lifecycle.ts";
|
|
19
20
|
import { type BashResult } from "./bash-executor.ts";
|
|
20
21
|
import { CHANGE_COLLABORATION_MODE, type CollaborationMode, type CollaborationModeTransitionResult, GET_COLLABORATION_MODE, IS_COLLABORATION_MODE_BUSY, SUBSCRIBE_PROMPT_ADMISSION } from "./collaboration-mode.ts";
|
|
@@ -135,6 +136,8 @@ export type AgentSessionEvent = Exclude<AgentEvent, {
|
|
|
135
136
|
/** Listener function for agent session events */
|
|
136
137
|
export type AgentSessionEventListener = (event: AgentSessionEvent) => void;
|
|
137
138
|
export interface AgentSessionConfig {
|
|
139
|
+
/** Lifetime of background groups launched by successful local shell commands. */
|
|
140
|
+
backgroundProcessPolicy?: BackgroundProcessPolicy;
|
|
138
141
|
agent: Agent;
|
|
139
142
|
sessionManager: SessionManager;
|
|
140
143
|
settingsManager: SettingsManager;
|
|
@@ -565,6 +568,7 @@ export declare class AgentSession {
|
|
|
565
568
|
private _abort;
|
|
566
569
|
/** Stop and verify all shell processes owned by this session, including background jobs. */
|
|
567
570
|
terminateOwnedShellProcesses(): Promise<void>;
|
|
571
|
+
get backgroundProcessPolicy(): BackgroundProcessPolicy;
|
|
568
572
|
get ownedShellProcessCount(): number;
|
|
569
573
|
waitForIdle(): Promise<void>;
|
|
570
574
|
private _emitModelSelect;
|
|
@@ -162,7 +162,7 @@ export class AgentSession {
|
|
|
162
162
|
_bashAbortControllers = new Set();
|
|
163
163
|
_pendingBashMessages = [];
|
|
164
164
|
_ownedOperations = new Set();
|
|
165
|
-
_shellProcesses
|
|
165
|
+
_shellProcesses;
|
|
166
166
|
_bashOperations = new Set();
|
|
167
167
|
// Extension system
|
|
168
168
|
_extensionRunner;
|
|
@@ -220,6 +220,7 @@ export class AgentSession {
|
|
|
220
220
|
_agentRunAborted = false;
|
|
221
221
|
_disposePromise;
|
|
222
222
|
constructor(config) {
|
|
223
|
+
this._shellProcesses = new OwnedShellProcesses(config.backgroundProcessPolicy);
|
|
223
224
|
this.agent = config.agent;
|
|
224
225
|
this.sessionManager = config.sessionManager;
|
|
225
226
|
this.settingsManager = config.settingsManager;
|
|
@@ -2401,6 +2402,9 @@ export class AgentSession {
|
|
|
2401
2402
|
async terminateOwnedShellProcesses() {
|
|
2402
2403
|
await this._shellProcesses.terminateAll();
|
|
2403
2404
|
}
|
|
2405
|
+
get backgroundProcessPolicy() {
|
|
2406
|
+
return this._shellProcesses.policy;
|
|
2407
|
+
}
|
|
2404
2408
|
get ownedShellProcessCount() {
|
|
2405
2409
|
return this._shellProcesses.count;
|
|
2406
2410
|
}
|
package/dist/core/sdk.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type TelemetryContext, type ThinkingLevel } from "@diffexai/diffex-agent-core";
|
|
2
2
|
import { type Model } from "@diffexai/diffex-ai/compat";
|
|
3
3
|
import type { HarnessStateStore, HarnessVersionBundle } from "@diffexai/diffex-harness-state";
|
|
4
|
+
import type { BackgroundProcessPolicy } from "../utils/owned-shell-processes.ts";
|
|
4
5
|
import { AgentSession } from "./agent-session.ts";
|
|
5
6
|
import type { AgentSessionLifecycleObserver } from "./agent-session-lifecycle.ts";
|
|
6
7
|
import type { LoadExtensionsResult, SessionStartEvent, ToolDefinition } from "./extensions/index.ts";
|
|
@@ -15,6 +16,8 @@ export interface SubagentOptions extends SubagentSupervisionOptions {
|
|
|
15
16
|
maxConcurrent?: number;
|
|
16
17
|
}
|
|
17
18
|
export interface CreateAgentSessionOptions {
|
|
19
|
+
/** Local shell background lifetime. Defaults to session-owned cleanup. */
|
|
20
|
+
backgroundProcessPolicy?: BackgroundProcessPolicy;
|
|
18
21
|
/** Working directory for project-local discovery. Default: process.cwd() */
|
|
19
22
|
cwd?: string;
|
|
20
23
|
/** Global config directory. Default: ~/.diffex/agent */
|
package/dist/core/sdk.js
CHANGED
|
@@ -436,6 +436,7 @@ export async function createInternalAgentSession(options = {}, internalCustomToo
|
|
|
436
436
|
sessionManager.appendThinkingLevelChange(thinkingLevel);
|
|
437
437
|
}
|
|
438
438
|
const session = new AgentSession({
|
|
439
|
+
backgroundProcessPolicy: options.backgroundProcessPolicy,
|
|
439
440
|
agent,
|
|
440
441
|
sessionManager,
|
|
441
442
|
settingsManager,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { TelemetryContext, ThinkingLevel } from "@diffexai/diffex-agent-core";
|
|
2
2
|
import type { Model } from "@diffexai/diffex-ai";
|
|
3
3
|
import type { HarnessStateStore, HarnessVersionBundle } from "@diffexai/diffex-harness-state";
|
|
4
|
+
import type { BackgroundProcessPolicy } from "../../utils/owned-shell-processes.ts";
|
|
4
5
|
import type { AgentSession } from "../agent-session.ts";
|
|
5
6
|
import { type AgentSessionServices } from "../agent-session-services.ts";
|
|
6
7
|
import type { ModelRuntime } from "../model-runtime.ts";
|
|
@@ -19,6 +20,7 @@ export interface CreateSubagentServicesOptions {
|
|
|
19
20
|
telemetryContext?: TelemetryContext;
|
|
20
21
|
}
|
|
21
22
|
export interface SubagentSessionConfig {
|
|
23
|
+
readonly backgroundProcessPolicy?: BackgroundProcessPolicy;
|
|
22
24
|
readonly cwd: string;
|
|
23
25
|
readonly agentDir: string;
|
|
24
26
|
readonly modelRuntime: ModelRuntime;
|
|
@@ -39,6 +39,7 @@ export function captureSubagentSessionConfig(parent, agentDir) {
|
|
|
39
39
|
.getActiveToolNames()
|
|
40
40
|
.filter((name) => allToolNames.has(name) && toolsByName.get(name)?.sourceInfo.source === "builtin"));
|
|
41
41
|
return Object.freeze({
|
|
42
|
+
backgroundProcessPolicy: parent.backgroundProcessPolicy,
|
|
42
43
|
cwd: parent.sessionManager.getCwd(),
|
|
43
44
|
agentDir,
|
|
44
45
|
modelRuntime: parent.modelRuntime,
|
|
@@ -133,6 +134,7 @@ export async function createSubagentSession(config, options = {}) {
|
|
|
133
134
|
markFixedHarnessSubagentSession(sessionManager);
|
|
134
135
|
const { session } = await createInternalAgentSessionFromServices({
|
|
135
136
|
services,
|
|
137
|
+
backgroundProcessPolicy: config.backgroundProcessPolicy,
|
|
136
138
|
sessionManager,
|
|
137
139
|
model: config.model,
|
|
138
140
|
thinkingLevel: config.thinkingLevel,
|
package/dist/core/tools/bash.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
1
2
|
import { constants } from "node:fs";
|
|
2
3
|
import { access as fsAccess } from "node:fs/promises";
|
|
3
4
|
import { Container, Text, truncateToWidth } from "@diffexai/diffex-tui";
|
|
@@ -8,6 +9,7 @@ import { truncateToVisualLines } from "../../modes/interactive/components/visual
|
|
|
8
9
|
import { theme } from "../../modes/interactive/theme/theme.js";
|
|
9
10
|
import { waitForChildProcess } from "../../utils/child-process.js";
|
|
10
11
|
import { getShellConfig, getShellEnv, killProcessTree, trackDetachedChildPid, untrackDetachedChildPid, } from "../../utils/shell.js";
|
|
12
|
+
import { SHELL_EXECUTION_ID_ENV } from "../../utils/shell-process-identity.js";
|
|
11
13
|
import { OutputAccumulator } from "./output-accumulator.js";
|
|
12
14
|
import { getTextOutput, invalidArgText, str } from "./render-utils.js";
|
|
13
15
|
import { wrapToolDefinition } from "./tool-definition-wrapper.js";
|
|
@@ -56,10 +58,11 @@ export function createLocalBashOperations(options) {
|
|
|
56
58
|
}
|
|
57
59
|
signal?.throwIfAborted();
|
|
58
60
|
const commandFromStdin = shellConfig.commandTransport === "stdin";
|
|
61
|
+
const executionId = randomUUID();
|
|
59
62
|
const child = spawn(shellConfig.shell, commandFromStdin ? shellConfig.args : [...shellConfig.args, command], {
|
|
60
63
|
cwd,
|
|
61
64
|
detached: process.platform !== "win32",
|
|
62
|
-
env: env ?? getShellEnv(),
|
|
65
|
+
env: { ...(env ?? getShellEnv()), [SHELL_EXECUTION_ID_ENV]: executionId },
|
|
63
66
|
stdio: [commandFromStdin ? "pipe" : "ignore", "pipe", "pipe"],
|
|
64
67
|
windowsHide: true,
|
|
65
68
|
});
|
|
@@ -67,25 +70,52 @@ export function createLocalBashOperations(options) {
|
|
|
67
70
|
child.stdin?.on("error", () => { });
|
|
68
71
|
child.stdin?.end(command);
|
|
69
72
|
}
|
|
70
|
-
if (child.pid) {
|
|
71
|
-
if (options?.owner)
|
|
72
|
-
options.owner.track(child.pid);
|
|
73
|
-
else
|
|
74
|
-
trackDetachedChildPid(child.pid);
|
|
75
|
-
}
|
|
76
73
|
let timedOut = false;
|
|
74
|
+
const environmentLifetime = options?.owner?.policy.lifetime === "environment";
|
|
75
|
+
let completed = false;
|
|
76
|
+
let completionError;
|
|
77
77
|
let timeoutHandle;
|
|
78
78
|
const onAbort = () => {
|
|
79
|
-
if (child.pid)
|
|
80
|
-
|
|
79
|
+
if (child.pid) {
|
|
80
|
+
if (options?.owner)
|
|
81
|
+
options.owner.terminate(child.pid);
|
|
82
|
+
else
|
|
83
|
+
killProcessTree(child.pid);
|
|
84
|
+
}
|
|
81
85
|
};
|
|
86
|
+
const onExit = (code) => {
|
|
87
|
+
completed = true;
|
|
88
|
+
if (environmentLifetime && timeoutHandle)
|
|
89
|
+
clearTimeout(timeoutHandle);
|
|
90
|
+
try {
|
|
91
|
+
if (child.pid)
|
|
92
|
+
options?.owner?.complete(child.pid, code === 0 && !timedOut && !signal?.aborted);
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
completionError = error;
|
|
96
|
+
try {
|
|
97
|
+
onAbort();
|
|
98
|
+
}
|
|
99
|
+
catch (cleanupError) {
|
|
100
|
+
completionError = new AggregateError([error, cleanupError], "Shell ownership handoff failed");
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
child.once("exit", onExit);
|
|
82
105
|
try {
|
|
106
|
+
if (child.pid) {
|
|
107
|
+
if (options?.owner)
|
|
108
|
+
options.owner.track(child.pid, executionId);
|
|
109
|
+
else
|
|
110
|
+
trackDetachedChildPid(child.pid);
|
|
111
|
+
}
|
|
83
112
|
// Set timeout if provided.
|
|
84
113
|
if (timeoutMs !== undefined) {
|
|
85
114
|
timeoutHandle = setTimeout(() => {
|
|
115
|
+
if (environmentLifetime && completed)
|
|
116
|
+
return;
|
|
86
117
|
timedOut = true;
|
|
87
|
-
|
|
88
|
-
killProcessTree(child.pid);
|
|
118
|
+
onAbort();
|
|
89
119
|
}, timeoutMs);
|
|
90
120
|
}
|
|
91
121
|
// Stream stdout and stderr.
|
|
@@ -100,7 +130,11 @@ export function createLocalBashOperations(options) {
|
|
|
100
130
|
}
|
|
101
131
|
// Handle shell spawn errors and wait for the process to terminate without hanging
|
|
102
132
|
// on inherited stdio handles held by detached descendants.
|
|
103
|
-
const exitCode = await waitForChildProcess(child
|
|
133
|
+
const exitCode = await waitForChildProcess(child, {
|
|
134
|
+
maxPostExitMs: environmentLifetime ? 100 : undefined,
|
|
135
|
+
});
|
|
136
|
+
if (completionError)
|
|
137
|
+
throw completionError;
|
|
104
138
|
if (signal?.aborted) {
|
|
105
139
|
throw new Error("aborted");
|
|
106
140
|
}
|
|
@@ -110,6 +144,7 @@ export function createLocalBashOperations(options) {
|
|
|
110
144
|
return { exitCode };
|
|
111
145
|
}
|
|
112
146
|
finally {
|
|
147
|
+
child.removeListener("exit", onExit);
|
|
113
148
|
if (child.pid) {
|
|
114
149
|
if (options?.owner)
|
|
115
150
|
options.owner.releaseIfExited(child.pid);
|
package/dist/index.d.ts
CHANGED
|
@@ -33,4 +33,5 @@ export { copyToClipboard } from "./utils/clipboard.ts";
|
|
|
33
33
|
export { parseFrontmatter, stripFrontmatter } from "./utils/frontmatter.ts";
|
|
34
34
|
export { convertToPng } from "./utils/image-convert.ts";
|
|
35
35
|
export { formatDimensionNote, type ResizedImage, resizeImage } from "./utils/image-resize.ts";
|
|
36
|
+
export type { BackgroundProcessPolicy, ShellOwnershipRecord } from "./utils/owned-shell-processes.ts";
|
|
36
37
|
export { getShellConfig } from "./utils/shell.ts";
|
package/dist/main.js
CHANGED
|
@@ -439,6 +439,9 @@ export async function main(args, options) {
|
|
|
439
439
|
: undefined;
|
|
440
440
|
const trustPromptMode = parsed.help || parsed.listModels !== undefined ? "print" : appMode;
|
|
441
441
|
const projectTrustByCwd = new Map();
|
|
442
|
+
const backgroundProcessPolicy = parsed.backgroundProcessLifetime === "environment"
|
|
443
|
+
? { lifetime: "environment", ownershipDirectory: resolvePath(parsed.backgroundProcessOwnershipDir, cwd) }
|
|
444
|
+
: { lifetime: "session" };
|
|
442
445
|
const resolvedExtensionPaths = resolveCliPaths(cwd, parsed.extensions);
|
|
443
446
|
const resolvedSkillPaths = resolveCliPaths(cwd, parsed.skills);
|
|
444
447
|
const resolvedPromptTemplatePaths = resolveCliPaths(cwd, parsed.promptTemplates);
|
|
@@ -530,6 +533,7 @@ export async function main(args, options) {
|
|
|
530
533
|
}
|
|
531
534
|
}
|
|
532
535
|
const created = await createAgentSessionFromServices({
|
|
536
|
+
backgroundProcessPolicy,
|
|
533
537
|
services,
|
|
534
538
|
sessionManager,
|
|
535
539
|
sessionStartEvent,
|
package/dist/modes/print-mode.js
CHANGED
|
@@ -18,19 +18,19 @@ export async function runPrintMode(runtimeHost, options) {
|
|
|
18
18
|
let session = runtimeHost.session;
|
|
19
19
|
let unsubscribe;
|
|
20
20
|
let unsubscribeBackpressure;
|
|
21
|
-
let
|
|
21
|
+
let disposePromise;
|
|
22
22
|
let terminationStatus = "completed";
|
|
23
23
|
const signalCleanupHandlers = [];
|
|
24
24
|
const disposeRuntime = async (status = terminationStatus) => {
|
|
25
|
-
if (
|
|
26
|
-
return;
|
|
27
|
-
disposed = true;
|
|
25
|
+
if (disposePromise)
|
|
26
|
+
return disposePromise;
|
|
28
27
|
unsubscribe?.();
|
|
29
28
|
unsubscribeBackpressure?.();
|
|
30
|
-
|
|
29
|
+
disposePromise = runtimeHost.dispose(status);
|
|
30
|
+
return disposePromise;
|
|
31
31
|
};
|
|
32
32
|
const registerSignalHandlers = () => {
|
|
33
|
-
const signals = ["SIGTERM"];
|
|
33
|
+
const signals = ["SIGTERM", "SIGINT"];
|
|
34
34
|
if (process.platform !== "win32") {
|
|
35
35
|
signals.push("SIGHUP");
|
|
36
36
|
}
|
|
@@ -39,7 +39,7 @@ export async function runPrintMode(runtimeHost, options) {
|
|
|
39
39
|
killTrackedDetachedChildren();
|
|
40
40
|
terminationStatus = "aborted";
|
|
41
41
|
void disposeRuntime("aborted").finally(() => {
|
|
42
|
-
process.exit(signal === "SIGHUP" ? 129 : 143);
|
|
42
|
+
process.exit(signal === "SIGHUP" ? 129 : signal === "SIGINT" ? 130 : 143);
|
|
43
43
|
});
|
|
44
44
|
};
|
|
45
45
|
process.on(signal, handler);
|
|
@@ -133,12 +133,15 @@ export async function runPrintMode(runtimeHost, options) {
|
|
|
133
133
|
return 1;
|
|
134
134
|
}
|
|
135
135
|
finally {
|
|
136
|
-
|
|
137
|
-
|
|
136
|
+
try {
|
|
137
|
+
if (exitCode !== 0)
|
|
138
|
+
terminationStatus = "failed";
|
|
139
|
+
await disposeRuntime();
|
|
140
|
+
await flushRawStdout();
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
for (const cleanup of signalCleanupHandlers)
|
|
144
|
+
cleanup();
|
|
138
145
|
}
|
|
139
|
-
if (exitCode !== 0)
|
|
140
|
-
terminationStatus = "failed";
|
|
141
|
-
await disposeRuntime();
|
|
142
|
-
await flushRawStdout();
|
|
143
146
|
}
|
|
144
147
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
[
|
|
2
2
|
{
|
|
3
3
|
"name": "@diffexai/diffex-agent-core",
|
|
4
|
-
"version": "0.3.
|
|
5
|
-
"sourceCommit": "
|
|
4
|
+
"version": "0.3.1",
|
|
5
|
+
"sourceCommit": "9d59a28db4888b6824740505f0a16146667f036b",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"portions": "Diffex contributions; Pi-derived portions retain MIT terms in LICENSE",
|
|
8
8
|
"notice": "LICENSE",
|
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
},
|
|
11
11
|
{
|
|
12
12
|
"name": "@diffexai/diffex-ai",
|
|
13
|
-
"version": "^0.3.
|
|
13
|
+
"version": "^0.3.1",
|
|
14
14
|
"distribution": "resolved separately by package manager; not bundled in this npm tarball"
|
|
15
15
|
},
|
|
16
16
|
{
|
|
17
17
|
"name": "@diffexai/diffex-telemetry",
|
|
18
|
-
"version": "^0.3.
|
|
18
|
+
"version": "^0.3.1",
|
|
19
19
|
"distribution": "resolved separately by package manager; not bundled in this npm tarball"
|
|
20
20
|
},
|
|
21
21
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"schemaVersion":3,"generatedAt":"2026-09-
|
|
1
|
+
{"schemaVersion":3,"generatedAt":"2026-09-20T21:05:14.234Z","structureHash":"5ae57f6cf495fb2f4ede669bf128fd21195cd00e1fbb2c1e884764da807da5d2","files":{"amazon-bedrock.json":"9d3eed9613b9b56f0c5f202a61b279a7168edf01bae6c3218a7ab28664ff80ea","ant-ling.json":"4979fe79d99ed97382d7ce40170c6132e932e77906de1eb54464c042e7d63633","anthropic.json":"6937a397c6c7cf654990d072734efad023b652b294b04961d43a5835d7d08156","azure-openai-responses.json":"787ba62322c46fbc69bc1fcb7c7cfc100b8f74211c72adf9766b6dbf5eae0c41","baseten.json":"c7cf9a7e7e6bee9c53005acf4706c25f954adaa64a9058535fb7e5b1d6920852","cerebras.json":"9eaa554e1b02f3665f8f63e6432d253bf81351af7c72001054dd8108aa528a52","cloudflare-ai-gateway.json":"356a2892803067a5d042c5abb87051edba46f7209589c625f8bcea8c7c5ce5c9","cloudflare-workers-ai.json":"07ef63208ff7517fd1a80962f18143e21de399640423329490b157f459ccf995","deepseek.json":"0dcc807a4e5827b488c6ceac87884ff6e735e01cf4f2ddfec9dd812e6fde041b","fireworks.json":"4c9055f7a2c5345b808bb561b07b227fc29148e0fb774c0ac50db2b34ab89aaf","github-copilot.json":"37cfc1da3a6814e37e14c565ed0a1e41f2eb513b10aa8f11ac18f27fa392308c","google-vertex.json":"e1631109172dc1f7d7977570420a5bb86258bdd1088427e244a2c51545c4f24d","google.json":"7619bf03edd2a7acb06a2274a14b13c3a61354288abe029a758401d4de36a8fd","groq.json":"e4728fd72e358cd8f25e9a518e9b49a521ef44523d3debe38a7db9e0663c4077","huggingface.json":"a488b6f175b382277ccf7d487f877ef0c698994576bb55d2410838bf9c8c7c41","kimi-coding.json":"9da7ea8e9eb8df5d8f73acc25d3da5b41164f522c0f09b45265b4bf104743ac1","minimax-cn.json":"65d37e55a6d9585855f94b3fb7739308d107fe248ebd9e1001d1c5d4606ad2c4","minimax.json":"c7dc5765995ae77242916430929c7cc9a782589f7e483e13f7e01663190d028e","mistral.json":"be522597b22bceeb0bb9a0ba1781647649ffd19637d0c8e67b056d7b0ec33d52","moonshotai-cn.json":"63f77de8782dce6a8d4649b6075ee04c9732863ae85561e0867871220c558bde","moonshotai.json":"2a8dfb97eb905e991c22081dc09bd4a61c05b7fa9ac0d5c72d6930f601f490f1","nvidia.json":"2ff6862206269af88a694e627c4b54753055357710adaf49ac8518d102c17407","openai-codex.json":"4a73818291987693fcb53e9e61b4be3429ffd78b3f64ea877a34c5f9928c89e1","openai.json":"6fa1954abd6c5b301620a02a57412bd60bbfdf20465b9a3eb4d113f88dfb8f7b","opencode-go.json":"fa6d6737da943fbb9c36487cb4cd5bc152d1f2fd548280bbe9d35d0304e79f11","opencode.json":"43c5d9cc6fab109411e6ac8eebac4b9fb0b00cff844cf0eb6c1559a08586525f","openrouter.json":"a3375b66ad7b4bb61f22d867e132c991d3b9851436c529838c109b9794d59b93","qwen-token-plan-cn.json":"a50420854a624ea82155d9621cd88d6cbd7802498d28fb1fd317eb7a1bc26cc7","qwen-token-plan-individual.json":"0e1578a5c0e11d65644bb42d1d6efee5af97a55a4881d0421ab68bd970d4d4ef","qwen-token-plan.json":"24285f68b2350aa1d98ecaeafe0914bce97940fe8798eff20f2a5c6d8c26bd6f","together.json":"927c707d06f2236cdab13f14c870fb58bce0614ba7287bbcd57cc9fd66d191ed","vercel-ai-gateway.json":"03b0830a794af1bc921fb504565534bedec660fcc9482adcf56ec5fb27703e60","xai.json":"282838b0546d63106c81f1703cdf5ed31ebfe0c5f13a4bec0d590472cbbe03f2","xiaomi-token-plan-ams.json":"7ce8ed244672c45737d286ff3ca9c3a2686a5d4b2f0c5f71ab9348c14b14daf3","xiaomi-token-plan-cn.json":"684892b5fe6fa371d6040d2011c0fa33facd650d2eaf19f5dbee8efb33016200","xiaomi-token-plan-sgp.json":"b19e79b82ac4fdcb080e6d220106797504c885ed70b27fc2b3c1aa4810f32963","xiaomi.json":"810368d3828c8bb9498012a0d48639030c0c216b8c13e79da02daa515aa23448","zai-coding-cn.json":"abf4cbc22507b9d545842072b5e34bce230025fc20f7b1cc67db3782c1dc4b56","zai.json":"089af736a622b0a25e417493819f4e174884afba43235c5a1f17814057875627"}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"anthropic-messages":{"minimax-m3":{"id":"minimax-m3","name":"MiniMax-M3","api":"anthropic-messages","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go","reasoning":true,"input":["text","image"],"cost":{"input":0.3,"output":1.2,"cacheRead":0.06,"cacheWrite":0},"contextWindow":1000000,"maxTokens":131072},"qwen3.8-flash":{"id":"qwen3.8-flash","name":"Qwen3.8 Flash","api":"anthropic-messages","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go","reasoning":true,"input":["text","image"],"cost":{"input":0.15,"output":0.47,"cacheRead":0.016,"cacheWrite":0.2},"contextWindow":1000000,"maxTokens":131072}},"openai-completions":{"deepseek-v4-flash":{"id":"deepseek-v4-flash","name":"DeepSeek V4 Flash","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text"],"cost":{"input":0.15,"output":0.6,"cacheRead":0.003,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"contextWindow":1000000,"maxTokens":384000,"thinkingLevelMap":{"minimal":null,"low":null,"medium":null,"high":"high","max":"max"}},"deepseek-v4-flash-vision-exp":{"id":"deepseek-v4-flash-vision-exp","name":"DeepSeek V4 Flash Vision Exp","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.15,"output":0.6,"cacheRead":0.003,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"contextWindow":1000000,"maxTokens":384000,"thinkingLevelMap":{"minimal":null,"low":null,"medium":null,"high":"high","max":"max"}},"deepseek-v4-pro":{"id":"deepseek-v4-pro","name":"DeepSeek V4 Pro (New)","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text"],"cost":{"input":0.66,"output":1.98,"cacheRead":0.022,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"contextWindow":1000000,"maxTokens":384000,"thinkingLevelMap":{"minimal":null,"low":null,"medium":null,"high":"high","max":"max"}},"deepseek-v4.1-flash":{"id":"deepseek-v4.1-flash","name":"DeepSeek V4.1 Flash","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.15,"output":0.6,"cacheRead":0.003,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"contextWindow":1000000,"maxTokens":384000,"thinkingLevelMap":{"minimal":null,"low":null,"medium":null,"high":"high","max":"max"}},"glm-5.1":{"id":"glm-5.1","name":"GLM-5.1","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text"],"cost":{"input":1.4,"output":4.4,"cacheRead":0.26,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":202752,"maxTokens":32768},"glm-5.2":{"id":"glm-5.2","name":"GLM-5.2","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text"],"cost":{"input":1.4,"output":4.4,"cacheRead":0.26,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":1000000,"maxTokens":131072,"thinkingLevelMap":{"off":null,"minimal":null,"low":null,"medium":null,"high":"high","xhigh":null,"max":"max"}},"glm-5.3":{"id":"glm-5.3","name":"GLM-5.3","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text"],"cost":{"input":1.4,"output":4.4,"cacheRead":0.26,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":1000000,"maxTokens":131072,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":null,"high":"high","xhigh":null,"max":"max"}},"glm-5.3-flash":{"id":"glm-5.3-flash","name":"GLM-5.3-Flash","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.15,"output":0.5,"cacheRead":0.03,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":1000000,"maxTokens":131072,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":null,"high":"high","xhigh":null,"max":"max"}},"hy3":{"id":"hy3","name":"Hy3","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text"],"cost":{"input":0.14,"output":0.58,"cacheRead":0.035,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":256000,"maxTokens":128000,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":null,"high":"high","xhigh":null,"max":null}},"hy4-preview":{"id":"hy4-preview","name":"Hy4 preview","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text"],"cost":{"input":0.834,"output":2.501,"cacheRead":0.042,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":1024000,"maxTokens":64000,"thinkingLevelMap":{"off":"none","minimal":null,"low":null,"medium":null,"high":"high","xhigh":null,"max":null}},"kimi-k2.6":{"id":"kimi-k2.6","name":"Kimi K2.6","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.95,"output":4,"cacheRead":0.16,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"thinkingFormat":"deepseek","supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsLongCacheRetention":false},"contextWindow":262144,"maxTokens":65536,"thinkingLevelMap":{"minimal":null,"low":null,"medium":null}},"kimi-k2.7-code":{"id":"kimi-k2.7-code","name":"Kimi K2.7 Code","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.95,"output":4,"cacheRead":0.19,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":262144,"maxTokens":262144},"kimi-k3":{"id":"kimi-k3","name":"Kimi K3","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":3,"output":15,"cacheRead":0.3,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":1048576,"maxTokens":131072,"thinkingLevelMap":{"off":null,"minimal":null,"low":null,"medium":null,"high":null,"xhigh":null,"max":"max"}},"longcat-2.0":{"id":"longcat-2.0","name":"LongCat-2.0","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text"],"cost":{"input":0.3,"output":1.2,"cacheRead":0.006,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":1000000,"maxTokens":131072},"mimo-v2.5":{"id":"mimo-v2.5","name":"MiMo V2.5","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.14,"output":0.28,"cacheRead":0.0028,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":1000000,"maxTokens":128000},"mimo-v2.5-pro":{"id":"mimo-v2.5-pro","name":"MiMo V2.5 Pro","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text"],"cost":{"input":0.435,"output":0.87,"cacheRead":0.003625,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":1048576,"maxTokens":128000},"minimax-m2.7":{"id":"minimax-m2.7","name":"MiniMax-M2.7","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text"],"cost":{"input":0.3,"output":1.2,"cacheRead":0.06,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":204800,"maxTokens":131072},"qwen3.6-plus":{"id":"qwen3.6-plus","name":"Qwen3.6 Plus","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.5,"output":3,"cacheRead":0.05,"cacheWrite":0.625},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"thinkingFormat":"qwen","maxTokensField":"max_tokens"},"contextWindow":1000000,"maxTokens":65536},"qwen3.7-max":{"id":"qwen3.7-max","name":"Qwen3.7 Max","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text"],"cost":{"input":2.5,"output":7.5,"cacheRead":0.5,"cacheWrite":3.125},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":1000000,"maxTokens":65536},"qwen3.7-plus":{"id":"qwen3.7-plus","name":"Qwen3.7 Plus","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.4,"output":1.6,"cacheRead":0.04,"cacheWrite":0.5},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":1000000,"maxTokens":65536},"qwen3.8-max":{"id":"qwen3.8-max","name":"Qwen3.8 Max","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":2,"output":6,"cacheRead":0.25,"cacheWrite":2.5},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":1000000,"maxTokens":131072,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":null,"xhigh":"xhigh","max":null}}},"openai-responses":{"gpt-5.6-luna":{"id":"gpt-5.6-luna","name":"GPT-5.6 Luna","api":"openai-responses","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.2,"output":1.2,"cacheRead":0.02,"cacheWrite":0.25},"compat":{"sessionAffinityFormat":"openai-nosession"},"contextWindow":1050000,"maxTokens":128000,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":"max"}},"grok-4.6":{"id":"grok-4.6","name":"Grok 4.6","api":"openai-responses","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":2,"output":6,"cacheRead":0.5,"cacheWrite":0},"compat":{"sessionAffinityFormat":"openai-nosession"},"contextWindow":500000,"maxTokens":500000,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":null}},"muse-spark-1.2-contributor":{"id":"muse-spark-1.2-contributor","name":"Muse Spark 1.2 Contributor","api":"openai-responses","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.1,"output":0.2,"cacheRead":0.002,"cacheWrite":0},"compat":{"sessionAffinityFormat":"openai-nosession"},"contextWindow":1048576,"maxTokens":131072,"thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":null}},"muse-spark-1.3-contributor":{"id":"muse-spark-1.3-contributor","name":"Muse Spark 1.3 Contributor","api":"openai-responses","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.1,"output":0.2,"cacheRead":0.002,"cacheWrite":0},"compat":{"sessionAffinityFormat":"openai-nosession"},"contextWindow":1048576,"maxTokens":131072,"thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":null}}}}
|
|
1
|
+
{"anthropic-messages":{"minimax-m3":{"id":"minimax-m3","name":"MiniMax-M3","api":"anthropic-messages","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go","reasoning":true,"input":["text","image"],"cost":{"input":0.3,"output":1.2,"cacheRead":0.06,"cacheWrite":0},"contextWindow":1000000,"maxTokens":131072},"qwen3.8-flash":{"id":"qwen3.8-flash","name":"Qwen3.8 Flash","api":"anthropic-messages","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go","reasoning":true,"input":["text","image"],"cost":{"input":0.15,"output":0.47,"cacheRead":0.016,"cacheWrite":0.2},"contextWindow":1000000,"maxTokens":131072}},"openai-completions":{"deepseek-v4-flash":{"id":"deepseek-v4-flash","name":"DeepSeek V4 Flash","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text"],"cost":{"input":0.15,"output":0.6,"cacheRead":0.003,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"contextWindow":1000000,"maxTokens":384000,"thinkingLevelMap":{"minimal":null,"low":null,"medium":null,"high":"high","max":"max"}},"deepseek-v4-flash-vision-exp":{"id":"deepseek-v4-flash-vision-exp","name":"DeepSeek V4 Flash Vision Exp","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.15,"output":0.6,"cacheRead":0.003,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"contextWindow":1000000,"maxTokens":384000,"thinkingLevelMap":{"minimal":null,"low":null,"medium":null,"high":"high","max":"max"}},"deepseek-v4-pro":{"id":"deepseek-v4-pro","name":"DeepSeek V4 Pro (New)","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text"],"cost":{"input":0.66,"output":1.98,"cacheRead":0.022,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"contextWindow":1000000,"maxTokens":384000,"thinkingLevelMap":{"minimal":null,"low":null,"medium":null,"high":"high","max":"max"}},"deepseek-v4.1-flash":{"id":"deepseek-v4.1-flash","name":"DeepSeek V4.1 Flash","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.15,"output":0.6,"cacheRead":0.003,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens","requiresReasoningContentOnAssistantMessages":true,"thinkingFormat":"deepseek"},"contextWindow":1000000,"maxTokens":384000,"thinkingLevelMap":{"minimal":null,"low":null,"medium":null,"high":"high","max":"max"}},"glm-5.1":{"id":"glm-5.1","name":"GLM-5.1","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text"],"cost":{"input":1.4,"output":4.4,"cacheRead":0.26,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":202752,"maxTokens":32768},"glm-5.2":{"id":"glm-5.2","name":"GLM-5.2","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text"],"cost":{"input":1.4,"output":4.4,"cacheRead":0.26,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":1000000,"maxTokens":131072,"thinkingLevelMap":{"off":null,"minimal":null,"low":null,"medium":null,"high":"high","xhigh":null,"max":"max"}},"glm-5.3":{"id":"glm-5.3","name":"GLM-5.3","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text"],"cost":{"input":1.4,"output":4.4,"cacheRead":0.26,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":1000000,"maxTokens":131072,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":null,"high":"high","xhigh":null,"max":"max"}},"glm-5.3-flash":{"id":"glm-5.3-flash","name":"GLM-5.3-Flash","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.15,"output":0.5,"cacheRead":0.03,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":1000000,"maxTokens":131072,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":null,"high":"high","xhigh":null,"max":"max"}},"hy3":{"id":"hy3","name":"Hy3","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text"],"cost":{"input":0.14,"output":0.58,"cacheRead":0.035,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":256000,"maxTokens":128000,"thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":null,"high":"high","xhigh":null,"max":null}},"hy4-preview":{"id":"hy4-preview","name":"Hy4 preview","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text"],"cost":{"input":0.834,"output":2.501,"cacheRead":0.042,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":1024000,"maxTokens":64000,"thinkingLevelMap":{"off":"none","minimal":null,"low":null,"medium":null,"high":"high","xhigh":null,"max":null}},"kimi-k2.6":{"id":"kimi-k2.6","name":"Kimi K2.6","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.95,"output":4,"cacheRead":0.16,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"thinkingFormat":"deepseek","supportsReasoningEffort":false,"maxTokensField":"max_tokens","supportsLongCacheRetention":false},"contextWindow":262144,"maxTokens":65536,"thinkingLevelMap":{"minimal":null,"low":null,"medium":null}},"kimi-k2.7-code":{"id":"kimi-k2.7-code","name":"Kimi K2.7 Code","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.95,"output":4,"cacheRead":0.19,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":262144,"maxTokens":262144},"kimi-k3":{"id":"kimi-k3","name":"Kimi K3","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":3,"output":15,"cacheRead":0.3,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":1048576,"maxTokens":131072,"thinkingLevelMap":{"off":null,"minimal":null,"low":null,"medium":null,"high":null,"xhigh":null,"max":"max"}},"longcat-2.0":{"id":"longcat-2.0","name":"LongCat-2.0","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text"],"cost":{"input":0.3,"output":1.2,"cacheRead":0.006,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":1000000,"maxTokens":131072},"mimo-v2.5":{"id":"mimo-v2.5","name":"MiMo V2.5","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.14,"output":0.28,"cacheRead":0.0028,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":1000000,"maxTokens":128000},"mimo-v2.5-pro":{"id":"mimo-v2.5-pro","name":"MiMo V2.5 Pro","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text"],"cost":{"input":0.435,"output":0.87,"cacheRead":0.003625,"cacheWrite":0},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":1048576,"maxTokens":128000},"minimax-m2.7":{"id":"minimax-m2.7","name":"MiniMax-M2.7","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text"],"cost":{"input":0.3,"output":1.2,"cacheRead":0.06,"cacheWrite":0.375},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":204800,"maxTokens":131072},"qwen3.6-plus":{"id":"qwen3.6-plus","name":"Qwen3.6 Plus","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.5,"output":3,"cacheRead":0.05,"cacheWrite":0.625},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"thinkingFormat":"qwen","maxTokensField":"max_tokens"},"contextWindow":1000000,"maxTokens":65536},"qwen3.7-max":{"id":"qwen3.7-max","name":"Qwen3.7 Max","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text"],"cost":{"input":2.5,"output":7.5,"cacheRead":0.5,"cacheWrite":3.125},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":1000000,"maxTokens":65536},"qwen3.7-plus":{"id":"qwen3.7-plus","name":"Qwen3.7 Plus","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.4,"output":1.6,"cacheRead":0.04,"cacheWrite":0.5},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":1000000,"maxTokens":65536},"qwen3.8-max":{"id":"qwen3.8-max","name":"Qwen3.8 Max","api":"openai-completions","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":2,"output":6,"cacheRead":0.25,"cacheWrite":2.5},"compat":{"supportsStore":false,"supportsDeveloperRole":false,"maxTokensField":"max_tokens"},"contextWindow":1000000,"maxTokens":131072,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":null,"xhigh":"xhigh","max":null}}},"openai-responses":{"gpt-5.6-luna":{"id":"gpt-5.6-luna","name":"GPT-5.6 Luna","api":"openai-responses","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.2,"output":1.2,"cacheRead":0.02,"cacheWrite":0.25},"compat":{"sessionAffinityFormat":"openai-nosession"},"contextWindow":1050000,"maxTokens":128000,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":"max"}},"grok-4.6":{"id":"grok-4.6","name":"Grok 4.6","api":"openai-responses","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":2,"output":6,"cacheRead":0.5,"cacheWrite":0},"compat":{"sessionAffinityFormat":"openai-nosession"},"contextWindow":500000,"maxTokens":500000,"thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":null}},"muse-spark-1.2-contributor":{"id":"muse-spark-1.2-contributor","name":"Muse Spark 1.2 Contributor","api":"openai-responses","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.1,"output":0.2,"cacheRead":0.002,"cacheWrite":0},"compat":{"sessionAffinityFormat":"openai-nosession"},"contextWindow":1048576,"maxTokens":131072,"thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":null}},"muse-spark-1.3-contributor":{"id":"muse-spark-1.3-contributor","name":"Muse Spark 1.3 Contributor","api":"openai-responses","provider":"opencode-go","baseUrl":"https://opencode.ai/zen/go/v1","reasoning":true,"input":["text","image"],"cost":{"input":0.1,"output":0.2,"cacheRead":0.002,"cacheWrite":0},"compat":{"sessionAffinityFormat":"openai-nosession"},"contextWindow":1048576,"maxTokens":131072,"thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":"xhigh","max":null}}}}
|