lark-remote 0.1.6 → 0.1.8
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 +51 -1
- package/README.en.md +9 -1
- package/README.md +14 -2
- package/dist/bridge/approval-coordinator.d.ts +71 -34
- package/dist/bridge/approval-coordinator.js +225 -41
- package/dist/bridge/inbound-media.d.ts +62 -0
- package/dist/bridge/inbound-media.js +282 -0
- package/dist/bridge/index.d.ts +97 -13
- package/dist/bridge/index.js +227 -87
- package/dist/bridge/queue-manager.d.ts +2 -1
- package/dist/bridge/queue-manager.js +1 -0
- package/dist/card/approval-render.js +294 -36
- package/dist/card/bash-card-session.d.ts +2 -24
- package/dist/card/bash-card-session.js +6 -73
- package/dist/card/bash-renderer.js +2 -3
- package/dist/card/card-budget.js +29 -75
- package/dist/card/card-session.d.ts +48 -0
- package/dist/card/card-session.js +86 -0
- package/dist/card/card-shared.d.ts +7 -16
- package/dist/card/card-shared.js +7 -30
- package/dist/card/run-card-session.d.ts +2 -55
- package/dist/card/run-card-session.js +6 -104
- package/dist/card/run-renderer.d.ts +7 -0
- package/dist/card/run-renderer.js +116 -238
- package/dist/card/run-state.d.ts +13 -0
- package/dist/card/run-state.js +25 -16
- package/dist/card/text-truncate.d.ts +13 -12
- package/dist/card/text-truncate.js +13 -63
- package/dist/common/fs.d.ts +8 -0
- package/dist/common/fs.js +17 -0
- package/dist/common/guards.d.ts +0 -20
- package/dist/common/guards.js +0 -43
- package/dist/common/sleep.d.ts +2 -0
- package/dist/common/sleep.js +5 -0
- package/dist/common/truncate.d.ts +39 -0
- package/dist/common/truncate.js +92 -0
- package/dist/config/codex-config.d.ts +1 -1
- package/dist/config/codex-config.js +1 -1
- package/dist/config/index.d.ts +112 -24
- package/dist/config/index.js +139 -37
- package/dist/connector/index.d.ts +69 -2
- package/dist/connector/index.js +107 -1
- package/dist/index.js +150 -118
- package/dist/instance-lock.js +4 -12
- package/dist/order/alias-resolve.d.ts +13 -0
- package/dist/order/alias-resolve.js +22 -0
- package/dist/order/alias-store.d.ts +38 -0
- package/dist/order/alias-store.js +106 -0
- package/dist/persistence/atomic-write.d.ts +8 -2
- package/dist/persistence/atomic-write.js +23 -7
- package/dist/restart.js +2 -1
- package/dist/router/card-action-payload.d.ts +30 -0
- package/dist/router/card-action-payload.js +39 -0
- package/dist/router/card-helpers.d.ts +63 -0
- package/dist/router/card-helpers.js +146 -0
- package/dist/router/config/claude.js +30 -1
- package/dist/router/config/codex.js +29 -50
- package/dist/router/config/common/model-patch.d.ts +22 -0
- package/dist/router/config/common/model-patch.js +26 -0
- package/dist/router/config/common/render.js +5 -4
- package/dist/router/config/dsh.d.ts +51 -0
- package/dist/router/config/dsh.js +179 -0
- package/dist/router/config/index.d.ts +12 -0
- package/dist/router/config/index.js +28 -1
- package/dist/router/config/kimi.d.ts +4 -1
- package/dist/router/config/kimi.js +27 -0
- package/dist/router/config/opencode.js +18 -5
- package/dist/router/config/pi.js +4 -5
- package/dist/router/config/types.d.ts +17 -2
- package/dist/router/index.d.ts +76 -22
- package/dist/router/index.js +479 -548
- package/dist/router/utils.d.ts +2 -0
- package/dist/router/utils.js +16 -2
- package/dist/runner/agent-choices-common.d.ts +16 -0
- package/dist/runner/agent-choices-common.js +34 -0
- package/dist/runner/claude/runner.d.ts +47 -10
- package/dist/runner/claude/runner.js +117 -46
- package/dist/runner/claude/session.d.ts +166 -0
- package/dist/runner/claude/session.js +768 -0
- package/dist/runner/codex/app-server/protocol-types.d.ts +66 -39
- package/dist/runner/codex/app-server/protocol-types.js +2 -13
- package/dist/runner/codex/app-server/runner.d.ts +52 -59
- package/dist/runner/codex/app-server/runner.js +216 -338
- package/dist/runner/codex/app-server/translator.d.ts +8 -21
- package/dist/runner/codex/app-server/translator.js +45 -18
- package/dist/runner/codex/index.d.ts +0 -2
- package/dist/runner/codex/index.js +0 -2
- package/dist/runner/common/acp/protocol-helpers.d.ts +14 -0
- package/dist/runner/common/acp/protocol-helpers.js +21 -0
- package/dist/runner/common/acp/protocol-types.d.ts +271 -0
- package/dist/runner/common/acp/protocol-types.js +77 -0
- package/dist/runner/common/connection-based-runner.d.ts +111 -0
- package/dist/runner/common/connection-based-runner.js +261 -0
- package/dist/runner/{codex/app-server → common/jsonrpc}/client.d.ts +14 -7
- package/dist/runner/{codex/app-server → common/jsonrpc}/client.js +27 -18
- package/dist/runner/common/jsonrpc/connection-manager.d.ts +125 -0
- package/dist/runner/{codex/app-server → common/jsonrpc}/connection-manager.js +63 -28
- package/dist/runner/{codex/app-server → common/jsonrpc}/transport.d.ts +5 -4
- package/dist/runner/{codex/app-server → common/jsonrpc}/transport.js +18 -19
- package/dist/runner/common/jsonrpc/types.d.ts +32 -0
- package/dist/runner/common/jsonrpc/types.js +9 -0
- package/dist/runner/common/process-stopper.d.ts +2 -1
- package/dist/runner/common/process-stopper.js +1 -0
- package/dist/runner/common/runner-utils.d.ts +6 -13
- package/dist/runner/common/runner-utils.js +6 -47
- package/dist/runner/common/spawning-runner.d.ts +24 -70
- package/dist/runner/common/spawning-runner.js +98 -152
- package/dist/runner/dsh/client.d.ts +95 -0
- package/dist/runner/dsh/client.js +418 -0
- package/dist/runner/dsh/fake-dsh-server.d.ts +60 -0
- package/dist/runner/dsh/fake-dsh-server.js +156 -0
- package/dist/runner/dsh/index.d.ts +3 -0
- package/dist/runner/dsh/index.js +4 -0
- package/dist/runner/dsh/runner.d.ts +57 -0
- package/dist/runner/dsh/runner.js +191 -0
- package/dist/runner/dsh/translator.d.ts +28 -0
- package/dist/runner/dsh/translator.js +98 -0
- package/dist/runner/dsh/types.d.ts +155 -0
- package/dist/runner/dsh/types.js +14 -0
- package/dist/runner/index.d.ts +5 -4
- package/dist/runner/index.js +5 -4
- package/dist/runner/kimi/acp/runner.d.ts +106 -0
- package/dist/runner/kimi/acp/runner.js +516 -0
- package/dist/runner/kimi/acp/translator.d.ts +138 -0
- package/dist/runner/kimi/acp/translator.js +441 -0
- package/dist/runner/kimi/index.d.ts +1 -1
- package/dist/runner/kimi/index.js +1 -1
- package/dist/runner/opencode/acp/index.d.ts +1 -0
- package/dist/runner/opencode/acp/index.js +2 -0
- package/dist/runner/opencode/acp/runner.d.ts +121 -0
- package/dist/runner/opencode/acp/runner.js +429 -0
- package/dist/runner/opencode/acp/translator.d.ts +119 -0
- package/dist/runner/opencode/acp/translator.js +345 -0
- package/dist/runner/opencode/index.d.ts +1 -1
- package/dist/runner/opencode/index.js +1 -1
- package/dist/runner/pi/index.d.ts +1 -1
- package/dist/runner/pi/index.js +1 -1
- package/dist/runner/pi/rpc/client.d.ts +52 -0
- package/dist/runner/pi/rpc/client.js +114 -0
- package/dist/runner/pi/rpc/index.d.ts +4 -0
- package/dist/runner/pi/rpc/index.js +4 -0
- package/dist/runner/pi/rpc/protocol-types.d.ts +127 -0
- package/dist/runner/pi/rpc/protocol-types.js +21 -0
- package/dist/runner/pi/rpc/runner.d.ts +74 -0
- package/dist/runner/pi/rpc/runner.js +190 -0
- package/dist/runner/pi/rpc/translator.d.ts +55 -0
- package/dist/runner/pi/rpc/translator.js +258 -0
- package/dist/runner/probe.js +6 -1
- package/dist/runner/question-common.d.ts +26 -0
- package/dist/runner/question-common.js +42 -0
- package/dist/runner/registry.d.ts +7 -8
- package/dist/runner/registry.js +3 -4
- package/dist/runner/resolve-agent-choices.js +18 -59
- package/dist/runner/sync-agent-choices.js +16 -67
- package/dist/runner/types.d.ts +97 -14
- package/dist/session/claude/session-index.js +2 -3
- package/dist/session/claude/session-reader.js +3 -6
- package/dist/session/claude/sessions.js +43 -28
- package/dist/session/codex/rollout-reader.d.ts +2 -2
- package/dist/session/codex/rollout-reader.js +14 -17
- package/dist/session/codex/sessions.d.ts +1 -1
- package/dist/session/codex/sessions.js +2 -2
- package/dist/session/common/content-blocks.d.ts +7 -0
- package/dist/session/common/content-blocks.js +13 -9
- package/dist/session/common/jsonl.d.ts +8 -25
- package/dist/session/common/jsonl.js +126 -261
- package/dist/session/common/pagination.d.ts +28 -0
- package/dist/session/common/pagination.js +33 -0
- package/dist/session/dsh/index.d.ts +1 -0
- package/dist/session/dsh/index.js +2 -0
- package/dist/session/dsh/sessions.d.ts +39 -0
- package/dist/session/dsh/sessions.js +237 -0
- package/dist/session/index.d.ts +1 -0
- package/dist/session/index.js +1 -0
- package/dist/session/kimi/sessions.d.ts +34 -1
- package/dist/session/kimi/sessions.js +208 -98
- package/dist/session/opencode/sessions.d.ts +17 -3
- package/dist/session/opencode/sessions.js +29 -29
- package/dist/session/pi/sessions.d.ts +5 -1
- package/dist/session/pi/sessions.js +12 -16
- package/dist/session/session-store.d.ts +11 -1
- package/dist/session/session-store.js +75 -178
- package/dist/update/index.d.ts +2 -2
- package/dist/update/index.js +2 -2
- package/dist/update/install.d.ts +20 -2
- package/dist/update/install.js +51 -7
- package/dist/workspace/index.d.ts +4 -0
- package/dist/workspace/index.js +8 -1
- package/package.json +2 -1
- package/dist/runner/codex/app-server/connection-manager.d.ts +0 -56
- package/dist/runner/codex/argv.d.ts +0 -33
- package/dist/runner/codex/argv.js +0 -40
- package/dist/runner/codex/factory.d.ts +0 -29
- package/dist/runner/codex/factory.js +0 -39
- package/dist/runner/codex/jsonl.d.ts +0 -37
- package/dist/runner/codex/jsonl.js +0 -221
- package/dist/runner/codex/runner.d.ts +0 -66
- package/dist/runner/codex/runner.js +0 -129
- package/dist/runner/common/exec-translator.d.ts +0 -73
- package/dist/runner/common/exec-translator.js +0 -105
- package/dist/runner/kimi/jsonl.d.ts +0 -28
- package/dist/runner/kimi/jsonl.js +0 -143
- package/dist/runner/kimi/runner.d.ts +0 -49
- package/dist/runner/kimi/runner.js +0 -105
- package/dist/runner/opencode/argv.d.ts +0 -32
- package/dist/runner/opencode/argv.js +0 -35
- package/dist/runner/opencode/jsonl.d.ts +0 -68
- package/dist/runner/opencode/jsonl.js +0 -295
- package/dist/runner/opencode/runner.d.ts +0 -61
- package/dist/runner/opencode/runner.js +0 -93
- package/dist/runner/pi/jsonl.d.ts +0 -128
- package/dist/runner/pi/jsonl.js +0 -249
- package/dist/runner/pi/runner.d.ts +0 -36
- package/dist/runner/pi/runner.js +0 -76
- package/dist/session/common/catch-up.d.ts +0 -12
- package/dist/session/common/catch-up.js +0 -31
|
@@ -1,295 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Translates opencode `run --format json` ndjson output into lark-remote `AgentEvent`s.
|
|
3
|
-
*
|
|
4
|
-
* Key design decisions:
|
|
5
|
-
* - opencode uses step-level events (step_start/step_finish), not turn-level like codex.
|
|
6
|
-
* - Tool is a single-part state machine: state.status evolves pending→running→completed/error,
|
|
7
|
-
* input and output are in the same part.
|
|
8
|
-
* - Fail-fast: unknown types and missing fields return [] (no event emitted),
|
|
9
|
-
* never throw, never write back to opencode (root cause ② tolerance).
|
|
10
|
-
* - Stream ending before a terminal event records a terminal error via `finish()`
|
|
11
|
-
* (root cause ③ fail-fast); the runner's `buildResultEvent` emits the result.
|
|
12
|
-
* - Each `run()` must create a new translator instance (stateful: sessionId/terminal/startedTools).
|
|
13
|
-
*
|
|
14
|
-
* Terminal state (sessionId, lastUsage, terminalErrorMessage) is stored on
|
|
15
|
-
* the instance and exposed via getters; `OpencodeExecRunner.run()` folds
|
|
16
|
-
* this state into `SpawningRunner.buildResultEvent(...)` so result-event
|
|
17
|
-
* semantics are uniform across all 5 agents.
|
|
18
|
-
*
|
|
19
|
-
* Event mapping:
|
|
20
|
-
* | opencode ndjson | lark-remote AgentEvent |
|
|
21
|
-
* |--------------------------|------------------------------------------------------|
|
|
22
|
-
* | step_start | SystemInitEvent (first event only) |
|
|
23
|
-
* | text | AssistantEvent(text) |
|
|
24
|
-
* | reasoning | AssistantEvent(thinking) |
|
|
25
|
-
* | tool/tool_use (first) | AssistantEvent(tool_use) |
|
|
26
|
-
* | tool (status=completed) | UserEvent(tool_result, is_error=false) |
|
|
27
|
-
* | tool (status=error) | UserEvent(tool_result, is_error=true) |
|
|
28
|
-
* | patch | FileChangeEvent |
|
|
29
|
-
* | step_finish(reason=stop) | [] (terminal — usage stashed for runner) |
|
|
30
|
-
* | step_finish(reason=*) | [] (non-terminal, continues) |
|
|
31
|
-
* | error | [] (terminal - error message stashed for runner) |
|
|
32
|
-
* | unknown type | [] (no event) |
|
|
33
|
-
*/
|
|
34
|
-
import { getLogger } from '../../logger/index.js';
|
|
35
|
-
import { recordValue, stringValue, numberValue, extractErrorMessage } from '../../common/guards.js';
|
|
36
|
-
import { ExecTranslator } from '../common/exec-translator.js';
|
|
37
|
-
export class OpencodeExecTranslator extends ExecTranslator {
|
|
38
|
-
cwd;
|
|
39
|
-
/** Accumulate usage across all steps (not just terminal step). */
|
|
40
|
-
accumulatedUsage = {
|
|
41
|
-
input_tokens: 0,
|
|
42
|
-
output_tokens: 0,
|
|
43
|
-
cache_read_tokens: 0,
|
|
44
|
-
cache_creation_tokens: 0,
|
|
45
|
-
};
|
|
46
|
-
/** Track which tool results have already been emitted (idempotency). */
|
|
47
|
-
emittedResults = new Set();
|
|
48
|
-
logTag = '[opencode-exec-translator]';
|
|
49
|
-
streamEndedMessage() {
|
|
50
|
-
return 'opencode stream ended before a terminal step';
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* @param opts.cwd The session's real directory. Emitted on the synthesized
|
|
54
|
-
* SystemInitEvent so the bridge persists the correct cwd (was hardcoded '').
|
|
55
|
-
* Post-PWD-sync-fix this equals the runner's opts.cwd == opencode's directory.
|
|
56
|
-
*/
|
|
57
|
-
constructor(opts = {}) {
|
|
58
|
-
super();
|
|
59
|
-
this.cwd = opts.cwd ?? '';
|
|
60
|
-
}
|
|
61
|
-
/** Get accumulated usage across all steps (for diagnostics). */
|
|
62
|
-
getAccumulatedUsage() {
|
|
63
|
-
return { ...this.accumulatedUsage };
|
|
64
|
-
}
|
|
65
|
-
// --- translateEvent: opencode-specific dispatch ---
|
|
66
|
-
translateEvent(raw) {
|
|
67
|
-
// Stash sessionId from the very first event (every event carries it)
|
|
68
|
-
const sid = stringValue(raw.sessionID ?? raw.sessionId);
|
|
69
|
-
if (sid && !this.sessionId) {
|
|
70
|
-
this.sessionId = sid;
|
|
71
|
-
}
|
|
72
|
-
switch (raw.type) {
|
|
73
|
-
case 'step_start':
|
|
74
|
-
return this.onStepStart(raw);
|
|
75
|
-
case 'text':
|
|
76
|
-
return this.onText(raw);
|
|
77
|
-
case 'reasoning':
|
|
78
|
-
return this.onReasoning(raw);
|
|
79
|
-
case 'tool':
|
|
80
|
-
case 'tool_use':
|
|
81
|
-
case 'tool_output':
|
|
82
|
-
return this.onTool(raw);
|
|
83
|
-
case 'patch':
|
|
84
|
-
return this.onPatch(raw);
|
|
85
|
-
case 'step_finish':
|
|
86
|
-
return this.onStepFinish(raw);
|
|
87
|
-
case 'error':
|
|
88
|
-
return this.onError(raw);
|
|
89
|
-
default:
|
|
90
|
-
return this.recordUnknownEvent(raw.type);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
// --- Private handlers ---
|
|
94
|
-
/** SystemInitEvent: synthesize from first event with sessionId. */
|
|
95
|
-
synthesizeInit() {
|
|
96
|
-
return {
|
|
97
|
-
type: 'system',
|
|
98
|
-
subtype: 'init',
|
|
99
|
-
session_id: this.sessionId ?? '',
|
|
100
|
-
cwd: this.cwd,
|
|
101
|
-
model: '',
|
|
102
|
-
timestamp: new Date().toISOString(),
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
onStepStart(_raw) {
|
|
106
|
-
// Internal marker, no lark-remote event
|
|
107
|
-
// But this is the first event, so synthesize SystemInitEvent
|
|
108
|
-
return this.sessionId && !this.terminal ? [this.synthesizeInit()] : [];
|
|
109
|
-
}
|
|
110
|
-
onText(raw) {
|
|
111
|
-
const part = recordValue(raw.part);
|
|
112
|
-
if (!part) {
|
|
113
|
-
return [];
|
|
114
|
-
}
|
|
115
|
-
const text = stringValue(part.text);
|
|
116
|
-
if (!text) {
|
|
117
|
-
return [];
|
|
118
|
-
}
|
|
119
|
-
return [
|
|
120
|
-
{
|
|
121
|
-
type: 'assistant',
|
|
122
|
-
message: {
|
|
123
|
-
content: [{ type: 'text', text }],
|
|
124
|
-
},
|
|
125
|
-
timestamp: new Date().toISOString(),
|
|
126
|
-
},
|
|
127
|
-
];
|
|
128
|
-
}
|
|
129
|
-
onReasoning(raw) {
|
|
130
|
-
const part = recordValue(raw.part);
|
|
131
|
-
if (!part) {
|
|
132
|
-
return [];
|
|
133
|
-
}
|
|
134
|
-
const text = stringValue(part.text);
|
|
135
|
-
if (!text) {
|
|
136
|
-
return [];
|
|
137
|
-
}
|
|
138
|
-
return [
|
|
139
|
-
{
|
|
140
|
-
type: 'assistant',
|
|
141
|
-
message: {
|
|
142
|
-
content: [{ type: 'thinking', thinking: text }],
|
|
143
|
-
},
|
|
144
|
-
timestamp: new Date().toISOString(),
|
|
145
|
-
},
|
|
146
|
-
];
|
|
147
|
-
}
|
|
148
|
-
onTool(raw) {
|
|
149
|
-
const part = recordValue(raw.part);
|
|
150
|
-
if (!part) {
|
|
151
|
-
return [];
|
|
152
|
-
}
|
|
153
|
-
const tool = stringValue(part.tool);
|
|
154
|
-
const callId = stringValue(part.callID ?? part.callId);
|
|
155
|
-
const state = recordValue(part.state);
|
|
156
|
-
if (!callId) {
|
|
157
|
-
return [];
|
|
158
|
-
}
|
|
159
|
-
const events = [];
|
|
160
|
-
// First time seeing this tool call: emit tool_use
|
|
161
|
-
if (!this.startedTools.has(callId)) {
|
|
162
|
-
this.startedTools.add(callId);
|
|
163
|
-
const input = state ? recordValue(state.input) : undefined;
|
|
164
|
-
const toolUseContent = {
|
|
165
|
-
type: 'tool_use',
|
|
166
|
-
id: callId,
|
|
167
|
-
name: tool ?? '',
|
|
168
|
-
input: input ?? {},
|
|
169
|
-
};
|
|
170
|
-
events.push({
|
|
171
|
-
type: 'assistant',
|
|
172
|
-
message: {
|
|
173
|
-
content: [toolUseContent],
|
|
174
|
-
},
|
|
175
|
-
timestamp: new Date().toISOString(),
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
// Check for completion or error status
|
|
179
|
-
if (state) {
|
|
180
|
-
const status = stringValue(state.status);
|
|
181
|
-
// completed: emit tool_result with output
|
|
182
|
-
if (status === 'completed' && !this.emittedResults.has(callId)) {
|
|
183
|
-
this.emittedResults.add(callId);
|
|
184
|
-
const output = stringValue(state.output) ?? '';
|
|
185
|
-
events.push({
|
|
186
|
-
type: 'user',
|
|
187
|
-
message: {
|
|
188
|
-
content: [
|
|
189
|
-
{
|
|
190
|
-
type: 'tool_result',
|
|
191
|
-
tool_use_id: callId,
|
|
192
|
-
content: output,
|
|
193
|
-
is_error: false,
|
|
194
|
-
},
|
|
195
|
-
],
|
|
196
|
-
},
|
|
197
|
-
timestamp: new Date().toISOString(),
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
|
-
// error: emit tool_result with error
|
|
201
|
-
if (status === 'error' && !this.emittedResults.has(callId)) {
|
|
202
|
-
this.emittedResults.add(callId);
|
|
203
|
-
const error = stringValue(state.error) ?? stringValue(state.output) ?? 'unknown error';
|
|
204
|
-
events.push({
|
|
205
|
-
type: 'user',
|
|
206
|
-
message: {
|
|
207
|
-
content: [
|
|
208
|
-
{
|
|
209
|
-
type: 'tool_result',
|
|
210
|
-
tool_use_id: callId,
|
|
211
|
-
content: error,
|
|
212
|
-
is_error: true,
|
|
213
|
-
},
|
|
214
|
-
],
|
|
215
|
-
},
|
|
216
|
-
timestamp: new Date().toISOString(),
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
return events;
|
|
221
|
-
}
|
|
222
|
-
onPatch(raw) {
|
|
223
|
-
const part = recordValue(raw.part);
|
|
224
|
-
if (!part) {
|
|
225
|
-
return [];
|
|
226
|
-
}
|
|
227
|
-
const files = part.files;
|
|
228
|
-
if (!Array.isArray(files) || files.length === 0) {
|
|
229
|
-
return [];
|
|
230
|
-
}
|
|
231
|
-
// Emit a FileChangeEvent for each file
|
|
232
|
-
const events = [];
|
|
233
|
-
for (const file of files) {
|
|
234
|
-
const path = stringValue(file.path ?? file.file_path);
|
|
235
|
-
if (!path)
|
|
236
|
-
continue;
|
|
237
|
-
events.push({
|
|
238
|
-
type: 'file_change',
|
|
239
|
-
path,
|
|
240
|
-
operation: 'edit', // patch implies edit
|
|
241
|
-
timestamp: new Date().toISOString(),
|
|
242
|
-
});
|
|
243
|
-
}
|
|
244
|
-
return events;
|
|
245
|
-
}
|
|
246
|
-
onStepFinish(raw) {
|
|
247
|
-
const part = recordValue(raw.part);
|
|
248
|
-
if (!part) {
|
|
249
|
-
return [];
|
|
250
|
-
}
|
|
251
|
-
const reason = stringValue(part.reason);
|
|
252
|
-
// Extract tokens from this step (both terminal and non-terminal steps contribute usage).
|
|
253
|
-
const tokens = recordValue(part.tokens);
|
|
254
|
-
if (tokens) {
|
|
255
|
-
const cache = recordValue(tokens.cache);
|
|
256
|
-
// Accumulate usage across ALL steps (not just terminal step).
|
|
257
|
-
// This fixes the systematic undercount for multi-step runs.
|
|
258
|
-
this.accumulatedUsage.input_tokens += numberValue(tokens.input) ?? 0;
|
|
259
|
-
this.accumulatedUsage.output_tokens += numberValue(tokens.output) ?? 0;
|
|
260
|
-
this.accumulatedUsage.cache_read_tokens += cache ? (numberValue(cache.read) ?? 0) : 0;
|
|
261
|
-
this.accumulatedUsage.cache_creation_tokens += cache ? (numberValue(cache.write) ?? 0) : 0;
|
|
262
|
-
// Only reason='stop' is terminal
|
|
263
|
-
if (reason === 'stop') {
|
|
264
|
-
// Mark terminal and stash accumulated usage; the runner emits the result event
|
|
265
|
-
// via buildResultEvent({...usage}) so success/error is uniform across agents.
|
|
266
|
-
this.terminal = true;
|
|
267
|
-
// Use accumulated usage (all steps) for the final result
|
|
268
|
-
const total = numberValue(tokens.total);
|
|
269
|
-
this.lastUsage = {
|
|
270
|
-
input_tokens: this.accumulatedUsage.input_tokens,
|
|
271
|
-
output_tokens: this.accumulatedUsage.output_tokens,
|
|
272
|
-
cache_read_tokens: this.accumulatedUsage.cache_read_tokens,
|
|
273
|
-
cache_creation_tokens: this.accumulatedUsage.cache_creation_tokens,
|
|
274
|
-
...(total !== undefined ? { total_tokens: total } : {}),
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
return [];
|
|
279
|
-
}
|
|
280
|
-
onError(raw) {
|
|
281
|
-
// opencode error events are terminal in practice: opencode exits with
|
|
282
|
-
// code=1 immediately after emitting one, without a step_finish(reason=stop).
|
|
283
|
-
// Mark terminal so the real error message reaches the user via
|
|
284
|
-
// buildResultEvent({translatorError}) instead of the generic
|
|
285
|
-
// "opencode exited code=1" fallback.
|
|
286
|
-
const message = extractErrorMessage(raw, 'opencode error');
|
|
287
|
-
getLogger().warn(`[opencode-exec-translator] error: ${message.slice(0, 500)}`);
|
|
288
|
-
getLogger().warn(`[opencode-exec-translator] RAW ERROR EVENT: ${JSON.stringify(raw).slice(0, 2000)}`);
|
|
289
|
-
this.terminal = true;
|
|
290
|
-
this.terminalErrorFromAgent = true;
|
|
291
|
-
this.terminalErrorMessage = message;
|
|
292
|
-
return [];
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
//# sourceMappingURL=jsonl.js.map
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OpencodeExecRunner: spawn-per-message runner using `opencode run --format json --auto`.
|
|
3
|
-
*
|
|
4
|
-
* Architecture:
|
|
5
|
-
* - Each `run()` spawns a fresh `opencode run` process, writes prompt to stdin,
|
|
6
|
-
* reads ndjson from stdout, translates to AgentEvent via OpencodeExecTranslator.
|
|
7
|
-
* - No singleton, no long-lived process, no HTTP server, no approval handshake.
|
|
8
|
-
* - Structurally identical to other exec runners (spawn-per-message + ProcessStopper + SpawnHeartbeat).
|
|
9
|
-
*
|
|
10
|
-
* The entire spawn + completion + cleanup orchestration is inherited
|
|
11
|
-
* from SpawningRunner. This subclass overrides only the 5 hooks:
|
|
12
|
-
* - getStdio() → ['pipe','pipe','pipe'] (writes prompt to stdin)
|
|
13
|
-
* - getSpawnEnv(opts) → sync PWD=opts.cwd (opencode reads PWD, not cwd)
|
|
14
|
-
* - setupStdin(proc, msg) → proc.stdin.end(msg, 'utf-8')
|
|
15
|
-
* - handleBadStreamLine() → empty override (silently skip non-JSON lines)
|
|
16
|
-
* - createTranslator(opts) → new OpencodeExecTranslator({ cwd: opts.cwd })
|
|
17
|
-
*
|
|
18
|
-
* Key invariants:
|
|
19
|
-
* 1. argv includes `--auto` (root cause ①).
|
|
20
|
-
* 2. stdin is written once via `stdin.end(prompt)` and never written again (root cause ②).
|
|
21
|
-
* 3. Translator parse failures → return [] (no event), never throw, never write back (root cause ②).
|
|
22
|
-
* 4. Stream ending early → finish() yields terminal event, never leaves consumer waiting (root cause ③).
|
|
23
|
-
*
|
|
24
|
-
* Verified (2026-07-13): opencode run reads prompt from stdin.
|
|
25
|
-
* Command: `echo 'msg' | opencode run --format json --auto`
|
|
26
|
-
* Result: stdout outputs ndjson with step_start → text → step_finish
|
|
27
|
-
*/
|
|
28
|
-
import type { ChildProcess } from 'node:child_process';
|
|
29
|
-
import type { AgentKind, AgentSessionReader, AgentRunner, AgentStatusInfo } from '../types.js';
|
|
30
|
-
import type { SpawnOptions } from '../types.js';
|
|
31
|
-
import { SpawningRunner, type RunnerTranslator } from '../common/spawning-runner.js';
|
|
32
|
-
interface OpencodeExecRunnerOptions {
|
|
33
|
-
/** Model override in provider/model format (e.g. 'anthropic/claude-sonnet-4-20250514'). Omitted → opencode config default. */
|
|
34
|
-
model?: string;
|
|
35
|
-
/** Grace period (ms) for SIGTERM→SIGKILL. Default: 5000. */
|
|
36
|
-
stopGraceMs?: number;
|
|
37
|
-
/** Directory for pid files. Default: `~/.lark-remote`. */
|
|
38
|
-
pidDir?: string;
|
|
39
|
-
/** Workspace identifier, scoped into the pid file name so concurrent
|
|
40
|
-
* workspaces do not share one `<prefix>.pid` (P1-9). */
|
|
41
|
-
workspace: string;
|
|
42
|
-
/** Spawn heartbeat interval (ms). Default: 30_000. */
|
|
43
|
-
spawnHeartbeatMs?: number;
|
|
44
|
-
/** Injected session reader (CLI-based OpencodeSessionReader). */
|
|
45
|
-
sessionReader: AgentSessionReader;
|
|
46
|
-
}
|
|
47
|
-
export declare class OpencodeExecRunner extends SpawningRunner implements AgentRunner {
|
|
48
|
-
readonly kind: AgentKind;
|
|
49
|
-
readonly sessionReader: AgentSessionReader;
|
|
50
|
-
private readonly defaultModel?;
|
|
51
|
-
constructor(opts: OpencodeExecRunnerOptions);
|
|
52
|
-
getStatusInfo(): AgentStatusInfo;
|
|
53
|
-
protected buildArgv(opts: SpawnOptions): string[];
|
|
54
|
-
protected getStdio(): ('ignore' | 'pipe')[];
|
|
55
|
-
protected getSpawnEnv(opts: SpawnOptions): NodeJS.ProcessEnv;
|
|
56
|
-
protected setupStdin(proc: ChildProcess, message: string): void;
|
|
57
|
-
/** Silently skip non-JSON lines from opencode stdout (e.g. warnings). */
|
|
58
|
-
protected handleBadStreamLine(_line: string): void;
|
|
59
|
-
protected createTranslator(opts: SpawnOptions): RunnerTranslator;
|
|
60
|
-
}
|
|
61
|
-
export {};
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OpencodeExecRunner: spawn-per-message runner using `opencode run --format json --auto`.
|
|
3
|
-
*
|
|
4
|
-
* Architecture:
|
|
5
|
-
* - Each `run()` spawns a fresh `opencode run` process, writes prompt to stdin,
|
|
6
|
-
* reads ndjson from stdout, translates to AgentEvent via OpencodeExecTranslator.
|
|
7
|
-
* - No singleton, no long-lived process, no HTTP server, no approval handshake.
|
|
8
|
-
* - Structurally identical to other exec runners (spawn-per-message + ProcessStopper + SpawnHeartbeat).
|
|
9
|
-
*
|
|
10
|
-
* The entire spawn + completion + cleanup orchestration is inherited
|
|
11
|
-
* from SpawningRunner. This subclass overrides only the 5 hooks:
|
|
12
|
-
* - getStdio() → ['pipe','pipe','pipe'] (writes prompt to stdin)
|
|
13
|
-
* - getSpawnEnv(opts) → sync PWD=opts.cwd (opencode reads PWD, not cwd)
|
|
14
|
-
* - setupStdin(proc, msg) → proc.stdin.end(msg, 'utf-8')
|
|
15
|
-
* - handleBadStreamLine() → empty override (silently skip non-JSON lines)
|
|
16
|
-
* - createTranslator(opts) → new OpencodeExecTranslator({ cwd: opts.cwd })
|
|
17
|
-
*
|
|
18
|
-
* Key invariants:
|
|
19
|
-
* 1. argv includes `--auto` (root cause ①).
|
|
20
|
-
* 2. stdin is written once via `stdin.end(prompt)` and never written again (root cause ②).
|
|
21
|
-
* 3. Translator parse failures → return [] (no event), never throw, never write back (root cause ②).
|
|
22
|
-
* 4. Stream ending early → finish() yields terminal event, never leaves consumer waiting (root cause ③).
|
|
23
|
-
*
|
|
24
|
-
* Verified (2026-07-13): opencode run reads prompt from stdin.
|
|
25
|
-
* Command: `echo 'msg' | opencode run --format json --auto`
|
|
26
|
-
* Result: stdout outputs ndjson with step_start → text → step_finish
|
|
27
|
-
*/
|
|
28
|
-
import { SpawningRunner } from '../common/spawning-runner.js';
|
|
29
|
-
import { pipeAllStdio, endStdinWithPrompt } from '../common/runner-utils.js';
|
|
30
|
-
import { buildOpencodeRunArgs } from './argv.js';
|
|
31
|
-
import { OpencodeExecTranslator } from './jsonl.js';
|
|
32
|
-
export class OpencodeExecRunner extends SpawningRunner {
|
|
33
|
-
kind = 'opencode';
|
|
34
|
-
sessionReader;
|
|
35
|
-
defaultModel;
|
|
36
|
-
constructor(opts) {
|
|
37
|
-
super({
|
|
38
|
-
pidDir: opts.pidDir,
|
|
39
|
-
workspace: opts.workspace,
|
|
40
|
-
stopGraceMs: opts.stopGraceMs,
|
|
41
|
-
spawnHeartbeatMs: opts.spawnHeartbeatMs,
|
|
42
|
-
pidFilePrefix: 'opencode',
|
|
43
|
-
logTag: 'opencode-exec-runner',
|
|
44
|
-
});
|
|
45
|
-
this.binary = 'opencode';
|
|
46
|
-
this.defaultModel = opts.model;
|
|
47
|
-
this.sessionReader = opts.sessionReader;
|
|
48
|
-
}
|
|
49
|
-
getStatusInfo() {
|
|
50
|
-
return {
|
|
51
|
-
kind: 'opencode',
|
|
52
|
-
model: this.defaultModel ?? '(未配置)',
|
|
53
|
-
provider: this.defaultModel?.split('/')[0],
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
buildArgv(opts) {
|
|
57
|
-
const model = opts.model ?? this.defaultModel;
|
|
58
|
-
return buildOpencodeRunArgs({
|
|
59
|
-
model,
|
|
60
|
-
sessionId: opts.sessionId,
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
// --- Hooks ---
|
|
64
|
-
getStdio() {
|
|
65
|
-
// ['pipe','pipe','pipe'] so we can write the prompt to stdin via setupStdin.
|
|
66
|
-
return pipeAllStdio();
|
|
67
|
-
}
|
|
68
|
-
getSpawnEnv(opts) {
|
|
69
|
-
// Sync PWD env to opts.cwd: Node spawn's `cwd` option only chdir's the
|
|
70
|
-
// child, it does NOT update the PWD env var (a shell convention).
|
|
71
|
-
// opencode `run` reads PWD (not process.cwd()) for project/directory
|
|
72
|
-
// detection in its 2nd instance phase, so an inherited PWD (e.g. bridge
|
|
73
|
-
// started from "/") would orphan sessions under directory="/" /
|
|
74
|
-
// project=global, making /resume unable to find them.
|
|
75
|
-
const spawnEnv = { ...process.env };
|
|
76
|
-
if (opts.cwd)
|
|
77
|
-
spawnEnv.PWD = opts.cwd;
|
|
78
|
-
return spawnEnv;
|
|
79
|
-
}
|
|
80
|
-
setupStdin(proc, message) {
|
|
81
|
-
// Write prompt once and close (invariant: write once, never again).
|
|
82
|
-
endStdinWithPrompt(proc, message);
|
|
83
|
-
}
|
|
84
|
-
/** Silently skip non-JSON lines from opencode stdout (e.g. warnings). */
|
|
85
|
-
handleBadStreamLine(_line) { }
|
|
86
|
-
createTranslator(opts) {
|
|
87
|
-
// Fresh translator per run. Pass opts.cwd so the synthesized
|
|
88
|
-
// SystemInitEvent carries the session's real directory (the bridge
|
|
89
|
-
// persists this into last-session.json).
|
|
90
|
-
return new OpencodeExecTranslator({ cwd: opts.cwd });
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
//# sourceMappingURL=runner.js.map
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import type { RunnerTranslator } from '../common/spawning-runner.js';
|
|
2
|
-
import type { AgentEvent } from '../types.js';
|
|
3
|
-
interface PiSessionEvent {
|
|
4
|
-
type: 'session';
|
|
5
|
-
id: string;
|
|
6
|
-
cwd: string;
|
|
7
|
-
model?: string;
|
|
8
|
-
}
|
|
9
|
-
interface PiMessageStartEvent {
|
|
10
|
-
type: 'message_start';
|
|
11
|
-
message: {
|
|
12
|
-
role: 'user' | 'assistant' | 'toolResult';
|
|
13
|
-
content?: unknown[];
|
|
14
|
-
model?: string;
|
|
15
|
-
usage?: PiUsage;
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
interface PiMessageUpdateEvent {
|
|
19
|
-
type: 'message_update';
|
|
20
|
-
assistantMessageEvent: {
|
|
21
|
-
type: 'text_start' | 'text_delta' | 'text_end' | 'thinking_start' | 'thinking_delta' | 'thinking_end' | 'toolcall_start' | 'toolcall_delta' | 'toolcall_end';
|
|
22
|
-
contentIndex?: number;
|
|
23
|
-
delta?: string;
|
|
24
|
-
content?: string;
|
|
25
|
-
toolCall?: {
|
|
26
|
-
id: string;
|
|
27
|
-
name: string;
|
|
28
|
-
arguments: Record<string, unknown>;
|
|
29
|
-
};
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
interface PiMessageEndEvent {
|
|
33
|
-
type: 'message_end';
|
|
34
|
-
message: {
|
|
35
|
-
role: 'user' | 'assistant' | 'toolResult';
|
|
36
|
-
content?: unknown[];
|
|
37
|
-
usage?: PiUsage;
|
|
38
|
-
toolCallId?: string;
|
|
39
|
-
toolName?: string;
|
|
40
|
-
isError?: boolean;
|
|
41
|
-
/** pi reports provider/LLM failures via stopReason="error" + errorMessage
|
|
42
|
-
* (content empty, usage zeros). e.g. "Connection error." on transient
|
|
43
|
-
* provider outage. */
|
|
44
|
-
stopReason?: string;
|
|
45
|
-
errorMessage?: string;
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
interface PiTurnEndEvent {
|
|
49
|
-
type: 'turn_end';
|
|
50
|
-
message?: {
|
|
51
|
-
usage?: PiUsage;
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
interface PiAgentEndEvent {
|
|
55
|
-
type: 'agent_end';
|
|
56
|
-
messages?: unknown[];
|
|
57
|
-
}
|
|
58
|
-
interface PiUsage {
|
|
59
|
-
input?: number;
|
|
60
|
-
output?: number;
|
|
61
|
-
cacheRead?: number;
|
|
62
|
-
cacheWrite?: number;
|
|
63
|
-
totalTokens?: number;
|
|
64
|
-
/** Reasoning tokens (display-only, not added to total). */
|
|
65
|
-
reasoning?: number;
|
|
66
|
-
}
|
|
67
|
-
type PiEvent = PiSessionEvent | PiMessageStartEvent | PiMessageUpdateEvent | PiMessageEndEvent | PiTurnEndEvent | PiAgentEndEvent | {
|
|
68
|
-
type: string;
|
|
69
|
-
};
|
|
70
|
-
/** ccusage-aligned usage: pi's `input` is non-cached; cacheRead/cacheWrite map to cache read/creation. */
|
|
71
|
-
type PiResultUsage = {
|
|
72
|
-
input_tokens: number;
|
|
73
|
-
output_tokens: number;
|
|
74
|
-
cache_read_tokens: number;
|
|
75
|
-
cache_creation_tokens: number;
|
|
76
|
-
total_tokens?: number;
|
|
77
|
-
};
|
|
78
|
-
/**
|
|
79
|
-
* Accumulates pi's incremental message_update events and emits normalized
|
|
80
|
-
* AgentEvents. Content mapping: text→TextContent, thinking→ThinkingContent,
|
|
81
|
-
* toolCall→ToolUseContent (input:arguments), toolResult→ToolResultContent.
|
|
82
|
-
*
|
|
83
|
-
* Implements RunnerTranslator so the base SpawningRunner can drive it
|
|
84
|
-
* uniformly. pi has no agent-reported terminal error (no equivalent of codex
|
|
85
|
-
* `turn.failed`), so isTerminal/finish/getTerminalError/hasAgentTerminalError
|
|
86
|
-
* are no-ops — pi relies entirely on the base class's signal/code-based
|
|
87
|
-
* result event classification.
|
|
88
|
-
*/
|
|
89
|
-
export declare class PiEventAccumulator implements RunnerTranslator {
|
|
90
|
-
private content;
|
|
91
|
-
private currentContentIndex;
|
|
92
|
-
private sessionId;
|
|
93
|
-
/**
|
|
94
|
-
* Accumulated (summed) token usage across all assistant messages in this run.
|
|
95
|
-
* pi emits per-message (non-cumulative) usage on each assistant `message_end`;
|
|
96
|
-
* summing yields the run's total consumption, aligned with ccusage (which sums
|
|
97
|
-
* per-message entries).
|
|
98
|
-
* `totalTokens` is NOT summed: it tracks the last message's total as the
|
|
99
|
-
* context-length water level (summing would overcount - design.md §usage:
|
|
100
|
-
* "N turn 累加得 N×context 虚假巨值").
|
|
101
|
-
*/
|
|
102
|
-
private accInput;
|
|
103
|
-
private accOutput;
|
|
104
|
-
private accCacheRead;
|
|
105
|
-
private accCacheCreation;
|
|
106
|
-
private lastTotalTokens;
|
|
107
|
-
/** stopReason of the most recent assistant message_end. "error" indicates a
|
|
108
|
-
* provider/LLM failure (pi retries internally; a later message_end may
|
|
109
|
-
* overwrite this with "stop" on eventual success). */
|
|
110
|
-
private lastAssistantStopReason;
|
|
111
|
-
/** errorMessage paired with the last assistant message_end whose
|
|
112
|
-
* stopReason==="error". Surfaces the provider's failure text (e.g.
|
|
113
|
-
* "Connection error.") to the user via the result event. */
|
|
114
|
-
private lastAssistantErrorMessage;
|
|
115
|
-
translate(raw: unknown): AgentEvent | null;
|
|
116
|
-
isTerminal(): boolean;
|
|
117
|
-
finish(_reason: 'failed' | 'interrupted' | 'timeout'): void;
|
|
118
|
-
getTerminalError(): string | undefined;
|
|
119
|
-
hasAgentTerminalError(): boolean;
|
|
120
|
-
getSessionId(): string;
|
|
121
|
-
getLastUsage(): PiResultUsage | undefined;
|
|
122
|
-
/** Accumulate a per-message usage record into the run's cumulative totals. */
|
|
123
|
-
private addUsage;
|
|
124
|
-
normalize(raw: PiEvent): AgentEvent | null;
|
|
125
|
-
private applyUpdate;
|
|
126
|
-
private normalizeToolResult;
|
|
127
|
-
}
|
|
128
|
-
export {};
|