shennian 0.2.88 → 0.2.90
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/wechat-channel/macos/manifest.json +22 -0
- package/dist/assets/wechat-channel/macos/shennian-wechat-channel-helper +0 -0
- package/dist/bin/shennian.js +1 -1
- package/dist/publish-build-manifest.json +548 -0
- package/dist/scripts/wechat-rpa-confirmation.mjs +5 -97
- package/dist/src/agent-env.js +4 -105
- package/dist/src/agents/adapter.d.ts +6 -0
- package/dist/src/agents/adapter.js +1 -19
- package/dist/src/agents/claude.js +8 -305
- package/dist/src/agents/codex-control.d.ts +35 -0
- package/dist/src/agents/codex-control.js +2 -0
- package/dist/src/agents/codex-utils.js +7 -200
- package/dist/src/agents/codex.d.ts +8 -0
- package/dist/src/agents/codex.js +15 -863
- package/dist/src/agents/command-spec.js +2 -413
- package/dist/src/agents/config-status.js +1 -226
- package/dist/src/agents/cursor.js +1 -249
- package/dist/src/agents/custom.js +4 -271
- package/dist/src/agents/detect.js +1 -56
- package/dist/src/agents/external-channel-instructions.js +10 -94
- package/dist/src/agents/gemini.js +1 -173
- package/dist/src/agents/manager.js +13 -157
- package/dist/src/agents/model-registry/cache.js +1 -37
- package/dist/src/agents/model-registry/discovery.js +2 -187
- package/dist/src/agents/model-registry/parsers.js +4 -447
- package/dist/src/agents/model-registry/runner.js +1 -30
- package/dist/src/agents/model-registry/service.js +1 -78
- package/dist/src/agents/model-registry/types.js +1 -8
- package/dist/src/agents/model-registry.js +1 -18
- package/dist/src/agents/openclaw.js +2 -275
- package/dist/src/agents/opencode.js +1 -231
- package/dist/src/agents/pi-context.js +12 -217
- package/dist/src/agents/pi.js +14 -723
- package/dist/src/agents/platform-instructions.js +9 -54
- package/dist/src/channels/base.d.ts +4 -1
- package/dist/src/channels/base.js +1 -3
- package/dist/src/channels/registry.js +1 -30
- package/dist/src/channels/reply-split.js +10 -89
- package/dist/src/channels/runtime.d.ts +1 -0
- package/dist/src/channels/runtime.js +5 -533
- package/dist/src/channels/secret-registry.d.ts +1 -0
- package/dist/src/channels/secret-registry.js +1 -46
- package/dist/src/channels/websocket.js +8 -378
- package/dist/src/channels/wechat-channel/anchor.d.ts +10 -0
- package/dist/src/channels/wechat-channel/anchor.js +1 -0
- package/dist/src/channels/wechat-channel/client.d.ts +74 -0
- package/dist/src/channels/wechat-channel/client.js +1 -0
- package/dist/src/channels/wechat-channel/cooldown.d.ts +15 -0
- package/dist/src/channels/wechat-channel/cooldown.js +1 -0
- package/dist/src/channels/wechat-channel/fingerprint.d.ts +28 -0
- package/dist/src/channels/wechat-channel/fingerprint.js +1 -0
- package/dist/src/channels/wechat-channel/helper-assets.d.ts +37 -0
- package/dist/src/channels/wechat-channel/helper-assets.js +1 -0
- package/dist/src/channels/wechat-channel/helper-client.d.ts +25 -0
- package/dist/src/channels/wechat-channel/helper-client.js +3 -0
- package/dist/src/channels/wechat-channel/helper-protocol.d.ts +84 -0
- package/dist/src/channels/wechat-channel/helper-protocol.js +1 -0
- package/dist/src/channels/wechat-channel/index.d.ts +17 -0
- package/dist/src/channels/wechat-channel/index.js +1 -0
- package/dist/src/channels/wechat-channel/ledger.d.ts +33 -0
- package/dist/src/channels/wechat-channel/ledger.js +1 -0
- package/dist/src/channels/wechat-channel/media-resolver.d.ts +32 -0
- package/dist/src/channels/wechat-channel/media-resolver.js +1 -0
- package/dist/src/channels/wechat-channel/message-key.d.ts +19 -0
- package/dist/src/channels/wechat-channel/message-key.js +1 -0
- package/dist/src/channels/wechat-channel/observer.d.ts +64 -0
- package/dist/src/channels/wechat-channel/observer.js +1 -0
- package/dist/src/channels/wechat-channel/outbound-ledger.d.ts +69 -0
- package/dist/src/channels/wechat-channel/outbound-ledger.js +2 -0
- package/dist/src/channels/wechat-channel/outbound-sender.d.ts +26 -0
- package/dist/src/channels/wechat-channel/outbound-sender.js +1 -0
- package/dist/src/channels/wechat-channel/preflight.d.ts +37 -0
- package/dist/src/channels/wechat-channel/preflight.js +1 -0
- package/dist/src/channels/wechat-channel/runner.d.ts +34 -0
- package/dist/src/channels/wechat-channel/runner.js +1 -0
- package/dist/src/channels/wechat-channel/runtime.d.ts +45 -0
- package/dist/src/channels/wechat-channel/runtime.js +1 -0
- package/dist/src/channels/wechat-channel/scheduler.d.ts +35 -0
- package/dist/src/channels/wechat-channel/scheduler.js +1 -0
- package/dist/src/channels/wechat-rpa/macos-flow.js +1 -96
- package/dist/src/channels/wechat-rpa/macos.js +6 -48
- package/dist/src/channels/wechat-rpa/normalizer.js +7 -127
- package/dist/src/channels/wechat-rpa.d.ts +21 -0
- package/dist/src/channels/wechat-rpa.js +6 -1022
- package/dist/src/channels/wecom.js +4 -357
- package/dist/src/commands/agent.js +6 -131
- package/dist/src/commands/daemon-windows.js +8 -48
- package/dist/src/commands/daemon.js +19 -1013
- package/dist/src/commands/external-attachments.js +1 -51
- package/dist/src/commands/external.js +1 -137
- package/dist/src/commands/manager.js +2 -389
- package/dist/src/commands/pair-qr.js +1 -6
- package/dist/src/commands/pair.js +9 -287
- package/dist/src/commands/tools.js +1 -34
- package/dist/src/commands/upgrade.js +1 -198
- package/dist/src/config/index.js +1 -35
- package/dist/src/daemon-log.js +6 -58
- package/dist/src/env-path.js +1 -64
- package/dist/src/fs/boundary.js +1 -126
- package/dist/src/fs/handler.js +1 -130
- package/dist/src/fs/security.js +1 -32
- package/dist/src/fs/text-decoder.d.ts +10 -0
- package/dist/src/fs/text-decoder.js +1 -0
- package/dist/src/index.js +2 -404
- package/dist/src/log-reporter.js +1 -16
- package/dist/src/manager/prompt.js +29 -34
- package/dist/src/manager/registry.js +2 -269
- package/dist/src/manager/runtime.js +19 -1003
- package/dist/src/native-fusion/config.js +1 -5
- package/dist/src/native-fusion/opencode-parser.js +3 -123
- package/dist/src/native-fusion/parser-common.js +8 -264
- package/dist/src/native-fusion/parsers.js +8 -729
- package/dist/src/native-fusion/service.d.ts +10 -0
- package/dist/src/native-fusion/service.js +2 -198
- package/dist/src/native-fusion/state.js +1 -22
- package/dist/src/native-fusion/types.js +1 -1
- package/dist/src/region.js +1 -88
- package/dist/src/relay/client.js +1 -343
- package/dist/src/session/archive-zip.js +1 -220
- package/dist/src/session/handlers/agent-config.js +1 -150
- package/dist/src/session/handlers/agents.js +1 -55
- package/dist/src/session/handlers/chat.js +2 -733
- package/dist/src/session/handlers/control.js +1 -55
- package/dist/src/session/handlers/fs.js +1 -747
- package/dist/src/session/handlers/session-refresh.js +1 -35
- package/dist/src/session/handlers/skills.js +1 -121
- package/dist/src/session/handlers/title.js +1 -60
- package/dist/src/session/handlers/tool-detail.d.ts +3 -0
- package/dist/src/session/handlers/tool-detail.js +1 -0
- package/dist/src/session/manager.d.ts +3 -0
- package/dist/src/session/manager.js +1 -261
- package/dist/src/session/projection.js +1 -54
- package/dist/src/session/queue.js +4 -317
- package/dist/src/session/remote-attachments.js +1 -72
- package/dist/src/session/store.js +3 -109
- package/dist/src/session/types.d.ts +4 -0
- package/dist/src/session/types.js +1 -4
- package/dist/src/skills/registry.js +15 -148
- package/dist/src/skills/setup.js +1 -101
- package/dist/src/tools/markdown-to-pdf.js +10 -346
- package/dist/src/upgrade/engine.js +3 -347
- package/package.json +3 -2
- package/dist/scripts/wechat-rpa-download-candidates.mjs +0 -105
package/dist/src/agent-env.js
CHANGED
|
@@ -1,109 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
// @test src/__tests__/agent-env.test.ts
|
|
3
|
-
import os from 'node:os';
|
|
4
|
-
import path from 'node:path';
|
|
5
|
-
import { spawnSync } from 'node:child_process';
|
|
6
|
-
import { buildAugmentedPath } from './env-path.js';
|
|
7
|
-
const SHELL_ENV_START = '__SHENNIAN_AGENT_ENV_START__';
|
|
8
|
-
const SHELL_ENV_END = '__SHENNIAN_AGENT_ENV_END__';
|
|
9
|
-
function quotePosix(value) {
|
|
10
|
-
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
11
|
-
}
|
|
12
|
-
function parseEnvJson(stdout) {
|
|
13
|
-
const start = stdout.indexOf(SHELL_ENV_START);
|
|
14
|
-
const end = stdout.indexOf(SHELL_ENV_END, start + SHELL_ENV_START.length);
|
|
15
|
-
if (start === -1 || end === -1)
|
|
16
|
-
return null;
|
|
17
|
-
const json = stdout.slice(start + SHELL_ENV_START.length, end);
|
|
18
|
-
try {
|
|
19
|
-
const parsed = JSON.parse(json);
|
|
20
|
-
const env = {};
|
|
21
|
-
for (const [key, value] of Object.entries(parsed)) {
|
|
22
|
-
if (typeof value === 'string')
|
|
23
|
-
env[key] = value;
|
|
24
|
-
}
|
|
25
|
-
return env;
|
|
26
|
-
}
|
|
27
|
-
catch {
|
|
28
|
-
return null;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
function readPosixShellEnv() {
|
|
32
|
-
const shell = process.env.SHELL?.trim() || '/bin/sh';
|
|
33
|
-
const script = [
|
|
34
|
-
`printf ${quotePosix(SHELL_ENV_START)}`,
|
|
35
|
-
`${quotePosix(process.execPath)} -e ${quotePosix('process.stdout.write(JSON.stringify(process.env))')}`,
|
|
36
|
-
`printf ${quotePosix(SHELL_ENV_END)}`,
|
|
37
|
-
].join('; ');
|
|
38
|
-
for (const args of [['-ilc', script], ['-lc', script]]) {
|
|
39
|
-
const result = spawnSync(shell, args, {
|
|
40
|
-
env: process.env,
|
|
41
|
-
encoding: 'utf-8',
|
|
42
|
-
stdio: ['ignore', 'pipe', 'ignore'],
|
|
43
|
-
timeout: 1500,
|
|
44
|
-
windowsHide: true,
|
|
45
|
-
});
|
|
46
|
-
const parsed = typeof result.stdout === 'string' ? parseEnvJson(result.stdout) : null;
|
|
47
|
-
if (parsed)
|
|
48
|
-
return parsed;
|
|
49
|
-
}
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
function readWindowsGlobalEnv() {
|
|
53
|
-
const script = `
|
|
1
|
+
import v from"node:os";import l from"node:path";import{spawnSync as d}from"node:child_process";import{buildAugmentedPath as m}from"./env-path.js";const c="__SHENNIAN_AGENT_ENV_START__",f="__SHENNIAN_AGENT_ENV_END__";function u(e){return`'${e.replace(/'/g,"'\\''")}'`}function E(e){const n=e.indexOf(c),r=e.indexOf(f,n+c.length);if(n===-1||r===-1)return null;const o=e.slice(n+c.length,r);try{const t=JSON.parse(o),s={};for(const[a,i]of Object.entries(t))typeof i=="string"&&(s[a]=i);return s}catch{return null}}function h(){const e=process.env.SHELL?.trim()||"/bin/sh",n=[`printf ${u(c)}`,`${u(process.execPath)} -e ${u("process.stdout.write(JSON.stringify(process.env))")}`,`printf ${u(f)}`].join("; ");for(const r of[["-ilc",n],["-lc",n]]){const o=d(e,r,{env:process.env,encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:1500,windowsHide:!0}),t=typeof o.stdout=="string"?E(o.stdout):null;if(t)return t}return null}function _(){const e=`
|
|
54
2
|
$envs = @{}
|
|
55
3
|
[Environment]::GetEnvironmentVariables('Machine').GetEnumerator() | ForEach-Object { $envs[$_.Key] = [string]$_.Value }
|
|
56
4
|
[Environment]::GetEnvironmentVariables('User').GetEnumerator() | ForEach-Object { $envs[$_.Key] = [string]$_.Value }
|
|
57
|
-
Write-Output '${
|
|
5
|
+
Write-Output '${c}'
|
|
58
6
|
$envs | ConvertTo-Json -Compress
|
|
59
|
-
Write-Output '${
|
|
60
|
-
|
|
61
|
-
const result = spawnSync('powershell.exe', ['-NoProfile', '-Command', script], {
|
|
62
|
-
encoding: 'utf-8',
|
|
63
|
-
stdio: ['ignore', 'pipe', 'ignore'],
|
|
64
|
-
timeout: 1500,
|
|
65
|
-
windowsHide: true,
|
|
66
|
-
});
|
|
67
|
-
return typeof result.stdout === 'string' ? parseEnvJson(result.stdout) : null;
|
|
68
|
-
}
|
|
69
|
-
export function readLatestUserEnv() {
|
|
70
|
-
const env = os.platform() === 'win32' ? readWindowsGlobalEnv() : readPosixShellEnv();
|
|
71
|
-
return env ?? {};
|
|
72
|
-
}
|
|
73
|
-
export function mergeAgentProcessEnv(input) {
|
|
74
|
-
const env = {
|
|
75
|
-
...input.daemonEnv,
|
|
76
|
-
...input.userEnv,
|
|
77
|
-
...input.extra,
|
|
78
|
-
};
|
|
79
|
-
env.PATH = mergePathEnv(input.daemonEnv, input.userEnv, input.extra, env);
|
|
80
|
-
delete env.Path;
|
|
81
|
-
delete env.path;
|
|
82
|
-
return env;
|
|
83
|
-
}
|
|
84
|
-
export function buildAgentProcessEnv(extra = {}) {
|
|
85
|
-
return mergeAgentProcessEnv({
|
|
86
|
-
daemonEnv: process.env,
|
|
87
|
-
userEnv: readLatestUserEnv(),
|
|
88
|
-
extra,
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
function readPathValue(env) {
|
|
92
|
-
return env?.PATH ?? env?.Path ?? env?.path;
|
|
93
|
-
}
|
|
94
|
-
function mergePathEnv(daemonEnv, userEnv, extra, mergedEnv) {
|
|
95
|
-
const parts = [];
|
|
96
|
-
for (const value of [readPathValue(daemonEnv), readPathValue(userEnv), readPathValue(extra)]) {
|
|
97
|
-
for (const part of (value ?? '').split(path.delimiter)) {
|
|
98
|
-
if (part && !parts.includes(part))
|
|
99
|
-
parts.push(part);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
const nodeDir = path.dirname(process.execPath);
|
|
103
|
-
if (nodeDir && !parts.includes(nodeDir))
|
|
104
|
-
parts.unshift(nodeDir);
|
|
105
|
-
return buildAugmentedPath({
|
|
106
|
-
pathValue: parts.join(path.delimiter),
|
|
107
|
-
env: mergedEnv,
|
|
108
|
-
});
|
|
109
|
-
}
|
|
7
|
+
Write-Output '${f}'
|
|
8
|
+
`,n=d("powershell.exe",["-NoProfile","-Command",e],{encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:1500,windowsHide:!0});return typeof n.stdout=="string"?E(n.stdout):null}function g(){return(v.platform()==="win32"?_():h())??{}}function N(e){const n={...e.daemonEnv,...e.userEnv,...e.extra};return n.PATH=$(e.daemonEnv,e.userEnv,e.extra,n),delete n.Path,delete n.path,n}function V(e={}){return N({daemonEnv:process.env,userEnv:g(),extra:e})}function p(e){return e?.PATH??e?.Path??e?.path}function $(e,n,r,o){const t=[];for(const a of[p(e),p(n),p(r)])for(const i of(a??"").split(l.delimiter))i&&!t.includes(i)&&t.push(i);const s=l.dirname(process.execPath);return s&&!t.includes(s)&&t.unshift(s),m({pathValue:t.join(l.delimiter),env:o})}export{V as buildAgentProcessEnv,N as mergeAgentProcessEnv,g as readLatestUserEnv};
|
|
@@ -36,6 +36,12 @@ export declare abstract class AgentAdapter extends EventEmitter<AgentAdapterEven
|
|
|
36
36
|
externalChannel?: ExternalChannelSessionStatus | null;
|
|
37
37
|
env?: NodeJS.ProcessEnv;
|
|
38
38
|
}): void;
|
|
39
|
+
getStatus?(): Promise<{
|
|
40
|
+
active: boolean;
|
|
41
|
+
runId?: string | null;
|
|
42
|
+
runPhase?: SessionRunPhase | null;
|
|
43
|
+
canStop?: boolean;
|
|
44
|
+
}>;
|
|
39
45
|
setTitle?(agentSessionId: string, title: string, workDir?: string): Promise<void>;
|
|
40
46
|
abstract start(sessionId: string, workDir: string, agentSessionId?: string | null): Promise<void>;
|
|
41
47
|
abstract send(text: string, modelId?: string, reasoningEffort?: string, attachments?: ChatAttachmentMeta[]): Promise<void>;
|
|
@@ -1,19 +1 @@
|
|
|
1
|
-
|
|
2
|
-
// @test src/__tests__/agents-e2e.ts
|
|
3
|
-
import { EventEmitter } from 'node:events';
|
|
4
|
-
export class AgentAdapter extends EventEmitter {
|
|
5
|
-
}
|
|
6
|
-
const registry = new Map();
|
|
7
|
-
export function registerAgent(type, factory) {
|
|
8
|
-
registry.set(type, factory);
|
|
9
|
-
}
|
|
10
|
-
export function unregisterAgent(type) {
|
|
11
|
-
registry.delete(type);
|
|
12
|
-
}
|
|
13
|
-
export function createAgent(type) {
|
|
14
|
-
const factory = registry.get(type);
|
|
15
|
-
return factory ? factory() : null;
|
|
16
|
-
}
|
|
17
|
-
export function getRegisteredAgents() {
|
|
18
|
-
return [...registry.keys()];
|
|
19
|
-
}
|
|
1
|
+
import{EventEmitter as r}from"node:events";class s extends r{}const n=new Map;function g(e,t){n.set(e,t)}function i(e){n.delete(e)}function c(e){const t=n.get(e);return t?t():null}function p(){return[...n.keys()]}export{s as AgentAdapter,c as createAgent,p as getRegisteredAgents,g as registerAgent,i as unregisterAgent};
|
|
@@ -1,305 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
return trimmed || 'default';
|
|
10
|
-
}
|
|
11
|
-
const CLAUDE_REASONING_EFFORTS = new Set(['low', 'medium', 'high', 'xhigh', 'max']);
|
|
12
|
-
const claudeEffortSupportCache = new Map();
|
|
13
|
-
export function normalizeClaudeReasoningEffort(reasoningEffort) {
|
|
14
|
-
const trimmed = reasoningEffort?.trim();
|
|
15
|
-
if (!trimmed)
|
|
16
|
-
return undefined;
|
|
17
|
-
if (CLAUDE_REASONING_EFFORTS.has(trimmed))
|
|
18
|
-
return trimmed;
|
|
19
|
-
throw new Error(`Unsupported Claude reasoning effort "${trimmed}". Supported values: low, medium, high, xhigh, max.`);
|
|
20
|
-
}
|
|
21
|
-
export function resetClaudeCapabilityCacheForTests() {
|
|
22
|
-
claudeEffortSupportCache.clear();
|
|
23
|
-
}
|
|
24
|
-
export function supportsClaudeReasoningEffort() {
|
|
25
|
-
const spec = resolveBuiltinCommand('claude');
|
|
26
|
-
if (!spec)
|
|
27
|
-
return false;
|
|
28
|
-
const cacheKey = `${spec.kind}:${spec.path}:${spec.command}:${spec.args.join('\0')}`;
|
|
29
|
-
if (claudeEffortSupportCache.has(cacheKey)) {
|
|
30
|
-
return claudeEffortSupportCache.get(cacheKey) ?? false;
|
|
31
|
-
}
|
|
32
|
-
try {
|
|
33
|
-
const result = spawnResolvedCommandSync(spec, ['--help'], {
|
|
34
|
-
encoding: 'utf-8',
|
|
35
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
36
|
-
timeout: 3000,
|
|
37
|
-
env: buildAgentProcessEnv(),
|
|
38
|
-
});
|
|
39
|
-
const output = `${result.stdout ?? ''}\n${result.stderr ?? ''}`;
|
|
40
|
-
const supported = /(?:^|\s)--effort(?:\s|,|<)/.test(output);
|
|
41
|
-
claudeEffortSupportCache.set(cacheKey, supported);
|
|
42
|
-
return supported;
|
|
43
|
-
}
|
|
44
|
-
catch {
|
|
45
|
-
claudeEffortSupportCache.set(cacheKey, false);
|
|
46
|
-
return false;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
export class ClaudeAdapter extends AgentAdapter {
|
|
50
|
-
options;
|
|
51
|
-
type = 'claude';
|
|
52
|
-
process = null;
|
|
53
|
-
agentSessionId = null;
|
|
54
|
-
sessionId = null;
|
|
55
|
-
workDir = null;
|
|
56
|
-
seq = 0;
|
|
57
|
-
runId = '';
|
|
58
|
-
hasEmittedText = false;
|
|
59
|
-
terminalState = 'open';
|
|
60
|
-
constructor(options = {}) {
|
|
61
|
-
super();
|
|
62
|
-
this.options = options;
|
|
63
|
-
}
|
|
64
|
-
externalChannel = null;
|
|
65
|
-
shennianSessionId = null;
|
|
66
|
-
extraEnv = {};
|
|
67
|
-
configure(options) {
|
|
68
|
-
this.shennianSessionId = options.sessionId ?? null;
|
|
69
|
-
this.externalChannel = options.externalChannel ?? null;
|
|
70
|
-
this.extraEnv = options.env ?? {};
|
|
71
|
-
}
|
|
72
|
-
async start(sessionId, workDir, agentSessionId) {
|
|
73
|
-
this.sessionId = sessionId;
|
|
74
|
-
this.workDir = workDir;
|
|
75
|
-
this.seq = 0;
|
|
76
|
-
if (agentSessionId)
|
|
77
|
-
this.agentSessionId = agentSessionId;
|
|
78
|
-
}
|
|
79
|
-
async send(text, modelId, reasoningEffort) {
|
|
80
|
-
await this.killProcess();
|
|
81
|
-
this.runId = randomUUID();
|
|
82
|
-
this.resetRunState();
|
|
83
|
-
const args = ['-p', text, '--output-format', 'stream-json', '--verbose'];
|
|
84
|
-
const systemPrompt = this.options.systemPrompt ?? buildPlatformInstructions(this.workDir ?? process.cwd(), this.externalChannel, this.shennianSessionId ?? undefined);
|
|
85
|
-
if (systemPrompt) {
|
|
86
|
-
args.push('--append-system-prompt', systemPrompt);
|
|
87
|
-
}
|
|
88
|
-
if (this.options.hidden) {
|
|
89
|
-
args.push('--name', 'Shennian Manager Substrate');
|
|
90
|
-
}
|
|
91
|
-
if (process.getuid?.() !== 0) {
|
|
92
|
-
args.push('--dangerously-skip-permissions');
|
|
93
|
-
}
|
|
94
|
-
args.push('--model', normalizeClaudeModelId(modelId));
|
|
95
|
-
const effort = normalizeClaudeReasoningEffort(reasoningEffort);
|
|
96
|
-
if (effort && supportsClaudeReasoningEffort()) {
|
|
97
|
-
args.push('--effort', effort);
|
|
98
|
-
}
|
|
99
|
-
if (this.agentSessionId) {
|
|
100
|
-
args.push('--resume', this.agentSessionId);
|
|
101
|
-
}
|
|
102
|
-
this.spawnAndParse(args);
|
|
103
|
-
}
|
|
104
|
-
async resume(agentSessionId) {
|
|
105
|
-
await this.killProcess();
|
|
106
|
-
this.agentSessionId = agentSessionId;
|
|
107
|
-
this.runId = randomUUID();
|
|
108
|
-
this.resetRunState();
|
|
109
|
-
const resumeArgs = ['--resume', agentSessionId, '--output-format', 'stream-json', '--verbose'];
|
|
110
|
-
const systemPrompt = this.options.systemPrompt ?? buildPlatformInstructions(this.workDir ?? process.cwd(), this.externalChannel, this.shennianSessionId ?? undefined);
|
|
111
|
-
if (systemPrompt) {
|
|
112
|
-
resumeArgs.push('--append-system-prompt', systemPrompt);
|
|
113
|
-
}
|
|
114
|
-
if (this.options.hidden) {
|
|
115
|
-
resumeArgs.push('--name', 'Shennian Manager Substrate');
|
|
116
|
-
}
|
|
117
|
-
if (process.getuid?.() !== 0) {
|
|
118
|
-
resumeArgs.push('--dangerously-skip-permissions');
|
|
119
|
-
}
|
|
120
|
-
this.spawnAndParse(resumeArgs);
|
|
121
|
-
}
|
|
122
|
-
async stop() {
|
|
123
|
-
await this.killProcess();
|
|
124
|
-
}
|
|
125
|
-
spawnAndParse(args) {
|
|
126
|
-
const spec = resolveBuiltinCommand('claude');
|
|
127
|
-
if (!spec) {
|
|
128
|
-
this.emit('error', new Error('Command "claude" not found. Is Claude Code CLI installed?'));
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
const proc = spawnAgentCommand(spec, args, {
|
|
132
|
-
cwd: this.workDir ?? undefined,
|
|
133
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
134
|
-
env: buildAgentProcessEnv(this.extraEnv),
|
|
135
|
-
});
|
|
136
|
-
this.process = proc;
|
|
137
|
-
const rl = createInterface({ input: proc.stdout });
|
|
138
|
-
rl.on('line', (line) => {
|
|
139
|
-
if (!line.trim())
|
|
140
|
-
return;
|
|
141
|
-
try {
|
|
142
|
-
const obj = JSON.parse(line);
|
|
143
|
-
this.handleStreamEvent(obj);
|
|
144
|
-
}
|
|
145
|
-
catch {
|
|
146
|
-
// skip malformed lines
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
let stderrBuf = '';
|
|
150
|
-
proc.stderr?.on('data', (chunk) => {
|
|
151
|
-
const text = chunk.toString();
|
|
152
|
-
stderrBuf += text;
|
|
153
|
-
if (this.terminalState !== 'open')
|
|
154
|
-
return;
|
|
155
|
-
// Stream stderr lines in real-time so the app shows errors/retries immediately
|
|
156
|
-
for (const line of text.split('\n')) {
|
|
157
|
-
const trimmed = line.trim();
|
|
158
|
-
if (trimmed) {
|
|
159
|
-
this.emitEvent({ state: 'delta', text: trimmed + '\n' });
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
});
|
|
163
|
-
proc.on('close', (code) => {
|
|
164
|
-
if (this.process !== proc)
|
|
165
|
-
return;
|
|
166
|
-
this.process = null;
|
|
167
|
-
this.handleProcessClose(code, stderrBuf);
|
|
168
|
-
});
|
|
169
|
-
proc.on('error', (err) => {
|
|
170
|
-
if (this.process !== proc)
|
|
171
|
-
return;
|
|
172
|
-
this.process = null;
|
|
173
|
-
if (err.code === 'ENOENT') {
|
|
174
|
-
this.emit('error', new Error('Command "claude" not found. Is Claude Code CLI installed?'));
|
|
175
|
-
}
|
|
176
|
-
else {
|
|
177
|
-
this.emit('error', err);
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
handleStreamEvent(obj) {
|
|
182
|
-
if (obj.type === 'system' && obj.subtype === 'init' && obj.session_id) {
|
|
183
|
-
this.agentSessionId = obj.session_id;
|
|
184
|
-
this.emitEvent({ state: 'start', agentSessionId: this.agentSessionId });
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
if (obj.type === 'system' &&
|
|
188
|
-
obj.subtype === 'api_retry' &&
|
|
189
|
-
obj.error === 'authentication_failed') {
|
|
190
|
-
this.emitErrorIfOpen({
|
|
191
|
-
state: 'error',
|
|
192
|
-
message: 'Claude authentication failed. Run "claude auth login" and retry.',
|
|
193
|
-
});
|
|
194
|
-
return;
|
|
195
|
-
}
|
|
196
|
-
if (obj.type === 'assistant') {
|
|
197
|
-
// New format (claude >= 2.1): content is in message.content[]
|
|
198
|
-
if (obj.message?.content) {
|
|
199
|
-
for (const block of obj.message.content) {
|
|
200
|
-
if (block.type === 'text' && block.text) {
|
|
201
|
-
const prefix = this.hasEmittedText ? '\n\n' : '';
|
|
202
|
-
this.emitEvent({ state: 'delta', text: prefix + block.text });
|
|
203
|
-
this.hasEmittedText = true;
|
|
204
|
-
}
|
|
205
|
-
else if (block.type === 'thinking' && block.thinking) {
|
|
206
|
-
this.emitEvent({ state: 'delta', text: block.thinking, thinking: true });
|
|
207
|
-
}
|
|
208
|
-
else if (block.type === 'tool_use') {
|
|
209
|
-
this.emitEvent({ state: 'tool-call', name: block.name, args: block.input });
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
// Legacy flat format (pre-2.1)
|
|
215
|
-
if (obj.subtype === 'text' && obj.text) {
|
|
216
|
-
const prefix = this.hasEmittedText ? '\n\n' : '';
|
|
217
|
-
this.emitEvent({ state: 'delta', text: prefix + obj.text });
|
|
218
|
-
this.hasEmittedText = true;
|
|
219
|
-
}
|
|
220
|
-
else if (obj.subtype === 'thinking' && obj.thinking) {
|
|
221
|
-
this.emitEvent({ state: 'delta', text: obj.thinking, thinking: true });
|
|
222
|
-
}
|
|
223
|
-
else if (obj.subtype === 'tool_use') {
|
|
224
|
-
this.emitEvent({ state: 'tool-call', name: obj.name, args: obj.input });
|
|
225
|
-
}
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
if (obj.type === 'result') {
|
|
229
|
-
if (obj.subtype === 'tool_result') {
|
|
230
|
-
const content = typeof obj.content === 'string' ? obj.content : JSON.stringify(obj.content);
|
|
231
|
-
this.emitEvent({ state: 'tool-result', name: obj.name, result: content });
|
|
232
|
-
}
|
|
233
|
-
else if (obj.subtype === 'success') {
|
|
234
|
-
if (obj.session_id) {
|
|
235
|
-
this.agentSessionId = obj.session_id;
|
|
236
|
-
}
|
|
237
|
-
const usage = obj.usage ?? obj.message?.usage;
|
|
238
|
-
this.emitFinalIfOpen({
|
|
239
|
-
state: 'final',
|
|
240
|
-
agentSessionId: this.agentSessionId ?? undefined,
|
|
241
|
-
usage: usage
|
|
242
|
-
? { inputTokens: usage.input_tokens, outputTokens: usage.output_tokens }
|
|
243
|
-
: undefined,
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
else if (obj.subtype === 'error') {
|
|
247
|
-
this.emitErrorIfOpen({
|
|
248
|
-
state: 'error',
|
|
249
|
-
message: obj.error ?? obj.result ?? 'unknown error',
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
handleProcessClose(code, stderrBuf) {
|
|
255
|
-
if (code !== 0 && code !== null) {
|
|
256
|
-
const msg = stderrBuf.trim() || `claude exited with code ${code}`;
|
|
257
|
-
this.emitErrorIfOpen({ state: 'error', message: msg });
|
|
258
|
-
return;
|
|
259
|
-
}
|
|
260
|
-
this.emitFinalIfOpen({
|
|
261
|
-
state: 'final',
|
|
262
|
-
agentSessionId: this.agentSessionId ?? undefined,
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
emitFinalIfOpen(partial) {
|
|
266
|
-
if (this.terminalState !== 'open')
|
|
267
|
-
return;
|
|
268
|
-
this.terminalState = 'final';
|
|
269
|
-
this.emitEvent(partial);
|
|
270
|
-
}
|
|
271
|
-
emitErrorIfOpen(partial) {
|
|
272
|
-
if (this.terminalState !== 'open')
|
|
273
|
-
return;
|
|
274
|
-
this.terminalState = 'error';
|
|
275
|
-
this.emitEvent(partial);
|
|
276
|
-
}
|
|
277
|
-
resetRunState() {
|
|
278
|
-
this.seq = 0;
|
|
279
|
-
this.hasEmittedText = false;
|
|
280
|
-
this.terminalState = 'open';
|
|
281
|
-
}
|
|
282
|
-
emitEvent(partial) {
|
|
283
|
-
const event = {
|
|
284
|
-
...partial,
|
|
285
|
-
runId: this.runId,
|
|
286
|
-
seq: this.seq++,
|
|
287
|
-
};
|
|
288
|
-
this.emit('agentEvent', event);
|
|
289
|
-
}
|
|
290
|
-
async killProcess() {
|
|
291
|
-
const proc = this.process;
|
|
292
|
-
if (!proc)
|
|
293
|
-
return;
|
|
294
|
-
this.process = null;
|
|
295
|
-
proc.kill('SIGTERM');
|
|
296
|
-
await new Promise((resolve) => {
|
|
297
|
-
proc.on('close', resolve);
|
|
298
|
-
setTimeout(() => {
|
|
299
|
-
proc.kill('SIGKILL');
|
|
300
|
-
resolve();
|
|
301
|
-
}, 3000);
|
|
302
|
-
});
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
registerAgent('claude', () => new ClaudeAdapter());
|
|
1
|
+
import{createInterface as f}from"node:readline";import{randomUUID as h}from"node:crypto";import{AgentAdapter as g,registerAgent as I}from"./adapter.js";import{resolveBuiltinCommand as d,spawnAgentCommand as S,spawnResolvedCommandSync as E}from"./command-spec.js";import{buildAgentProcessEnv as p}from"../agent-env.js";import{buildPlatformInstructions as m}from"./platform-instructions.js";function y(i){return i?.trim()||"default"}const x=new Set(["low","medium","high","xhigh","max"]),o=new Map;function w(i){const t=i?.trim();if(t){if(x.has(t))return t;throw new Error(`Unsupported Claude reasoning effort "${t}". Supported values: low, medium, high, xhigh, max.`)}}function R(){o.clear()}function C(){const i=d("claude");if(!i)return!1;const t=`${i.kind}:${i.path}:${i.command}:${i.args.join("\0")}`;if(o.has(t))return o.get(t)??!1;try{const e=E(i,["--help"],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:3e3,env:p()}),s=`${e.stdout??""}
|
|
2
|
+
${e.stderr??""}`,r=/(?:^|\s)--effort(?:\s|,|<)/.test(s);return o.set(t,r),r}catch{return o.set(t,!1),!1}}class k extends g{options;type="claude";process=null;agentSessionId=null;sessionId=null;workDir=null;seq=0;runId="";hasEmittedText=!1;terminalState="open";constructor(t={}){super(),this.options=t}externalChannel=null;shennianSessionId=null;extraEnv={};configure(t){this.shennianSessionId=t.sessionId??null,this.externalChannel=t.externalChannel??null,this.extraEnv=t.env??{}}async start(t,e,s){this.sessionId=t,this.workDir=e,this.seq=0,s&&(this.agentSessionId=s)}async send(t,e,s){await this.killProcess(),this.runId=h(),this.resetRunState();const r=["-p",t,"--output-format","stream-json","--verbose"],a=this.options.systemPrompt??m(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0);a&&r.push("--append-system-prompt",a),this.options.hidden&&r.push("--name","Shennian Manager Substrate"),process.getuid?.()!==0&&r.push("--dangerously-skip-permissions"),r.push("--model",y(e));const n=w(s);n&&C()&&r.push("--effort",n),this.agentSessionId&&r.push("--resume",this.agentSessionId),this.spawnAndParse(r)}async resume(t){await this.killProcess(),this.agentSessionId=t,this.runId=h(),this.resetRunState();const e=["--resume",t,"--output-format","stream-json","--verbose"],s=this.options.systemPrompt??m(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0);s&&e.push("--append-system-prompt",s),this.options.hidden&&e.push("--name","Shennian Manager Substrate"),process.getuid?.()!==0&&e.push("--dangerously-skip-permissions"),this.spawnAndParse(e)}async stop(){await this.killProcess()}spawnAndParse(t){const e=d("claude");if(!e){this.emit("error",new Error('Command "claude" not found. Is Claude Code CLI installed?'));return}const s=S(e,t,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:p(this.extraEnv)});this.process=s,f({input:s.stdout}).on("line",n=>{if(n.trim())try{const u=JSON.parse(n);this.handleStreamEvent(u)}catch{}});let a="";s.stderr?.on("data",n=>{const u=n.toString();if(a+=u,this.terminalState==="open")for(const c of u.split(`
|
|
3
|
+
`)){const l=c.trim();l&&this.emitEvent({state:"delta",text:l+`
|
|
4
|
+
`})}}),s.on("close",n=>{this.process===s&&(this.process=null,this.handleProcessClose(n,a))}),s.on("error",n=>{this.process===s&&(this.process=null,n.code==="ENOENT"?this.emit("error",new Error('Command "claude" not found. Is Claude Code CLI installed?')):this.emit("error",n))})}handleStreamEvent(t){if(t.type==="system"&&t.subtype==="init"&&t.session_id){this.agentSessionId=t.session_id,this.emitEvent({state:"start",agentSessionId:this.agentSessionId});return}if(t.type==="system"&&t.subtype==="api_retry"&&t.error==="authentication_failed"){this.emitErrorIfOpen({state:"error",message:'Claude authentication failed. Run "claude auth login" and retry.'});return}if(t.type==="assistant"){if(t.message?.content){for(const e of t.message.content)if(e.type==="text"&&e.text){const s=this.hasEmittedText?`
|
|
5
|
+
|
|
6
|
+
`:"";this.emitEvent({state:"delta",text:s+e.text}),this.hasEmittedText=!0}else e.type==="thinking"&&e.thinking?this.emitEvent({state:"delta",text:e.thinking,thinking:!0}):e.type==="tool_use"&&this.emitEvent({state:"tool-call",name:e.name,args:e.input});return}if(t.subtype==="text"&&t.text){const e=this.hasEmittedText?`
|
|
7
|
+
|
|
8
|
+
`:"";this.emitEvent({state:"delta",text:e+t.text}),this.hasEmittedText=!0}else t.subtype==="thinking"&&t.thinking?this.emitEvent({state:"delta",text:t.thinking,thinking:!0}):t.subtype==="tool_use"&&this.emitEvent({state:"tool-call",name:t.name,args:t.input});return}if(t.type==="result")if(t.subtype==="tool_result"){const e=typeof t.content=="string"?t.content:JSON.stringify(t.content);this.emitEvent({state:"tool-result",name:t.name,result:e})}else if(t.subtype==="success"){t.session_id&&(this.agentSessionId=t.session_id);const e=t.usage??t.message?.usage;this.emitFinalIfOpen({state:"final",agentSessionId:this.agentSessionId??void 0,usage:e?{inputTokens:e.input_tokens,outputTokens:e.output_tokens}:void 0})}else t.subtype==="error"&&this.emitErrorIfOpen({state:"error",message:t.error??t.result??"unknown error"})}handleProcessClose(t,e){if(t!==0&&t!==null){const s=e.trim()||`claude exited with code ${t}`;this.emitErrorIfOpen({state:"error",message:s});return}this.emitFinalIfOpen({state:"final",agentSessionId:this.agentSessionId??void 0})}emitFinalIfOpen(t){this.terminalState==="open"&&(this.terminalState="final",this.emitEvent(t))}emitErrorIfOpen(t){this.terminalState==="open"&&(this.terminalState="error",this.emitEvent(t))}resetRunState(){this.seq=0,this.hasEmittedText=!1,this.terminalState="open"}emitEvent(t){const e={...t,runId:this.runId,seq:this.seq++};this.emit("agentEvent",e)}async killProcess(){const t=this.process;t&&(this.process=null,t.kill("SIGTERM"),await new Promise(e=>{t.on("close",e),setTimeout(()=>{t.kill("SIGKILL"),e()},3e3)}))}}I("claude",()=>new k);export{k as ClaudeAdapter,y as normalizeClaudeModelId,w as normalizeClaudeReasoningEffort,R as resetClaudeCapabilityCacheForTests,C as supportsClaudeReasoningEffort};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { SessionRunPhase } from '@shennian/wire';
|
|
2
|
+
export type CodexThreadActivity = {
|
|
3
|
+
active: boolean;
|
|
4
|
+
turnId: string | null;
|
|
5
|
+
runPhase: SessionRunPhase | null;
|
|
6
|
+
canStop: boolean;
|
|
7
|
+
};
|
|
8
|
+
export declare class CodexAppServerProxyClient {
|
|
9
|
+
private readonly opts;
|
|
10
|
+
private process;
|
|
11
|
+
private rpcSeq;
|
|
12
|
+
private pendingRequests;
|
|
13
|
+
private stderr;
|
|
14
|
+
private initialized;
|
|
15
|
+
constructor(opts?: {
|
|
16
|
+
workDir?: string;
|
|
17
|
+
timeoutMs?: number;
|
|
18
|
+
});
|
|
19
|
+
start(): Promise<void>;
|
|
20
|
+
initialize(): Promise<void>;
|
|
21
|
+
readThreadActivity(threadId: string): Promise<CodexThreadActivity>;
|
|
22
|
+
interruptThread(threadId: string): Promise<CodexThreadActivity>;
|
|
23
|
+
close(): Promise<void>;
|
|
24
|
+
private sendRpc;
|
|
25
|
+
private handleMessage;
|
|
26
|
+
private rejectAllPending;
|
|
27
|
+
}
|
|
28
|
+
export declare function probeCodexThreadActivity(params: {
|
|
29
|
+
threadId: string;
|
|
30
|
+
workDir?: string;
|
|
31
|
+
}): Promise<CodexThreadActivity | null>;
|
|
32
|
+
export declare function interruptCodexThread(params: {
|
|
33
|
+
threadId: string;
|
|
34
|
+
workDir?: string;
|
|
35
|
+
}): Promise<CodexThreadActivity | null>;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{createInterface as l}from"node:readline";import{resolveBuiltinCommand as h,spawnAgentCommand as f}from"./command-spec.js";import{buildAgentProcessEnv as w}from"../agent-env.js";import{CODEX_APP_SERVER_CLIENT_INFO as y}from"./codex-utils.js";function g(i){const e=i?.type==="active"&&Array.isArray(i.activeFlags)?i.activeFlags:[];return e.includes("waitingOnApproval")?"waiting_approval":e.includes("waitingOnUserInput")?"waiting_user_input":"thinking"}function m(i){if(!Array.isArray(i))return null;for(let e=i.length-1;e>=0;e--){const t=i[e];if(!t||typeof t!="object")continue;const n=t;if(n.status==="inProgress")return typeof n.id=="string"?n.id:null}return null}class d{opts;process=null;rpcSeq=1;pendingRequests=new Map;stderr="";initialized=!1;constructor(e={}){this.opts=e}async start(){if(this.process)return;const e=h("codex");if(!e)throw new Error('Command "codex" not found. Is OpenAI Codex CLI installed?');const t=f(e,["app-server","proxy"],{cwd:this.opts.workDir||void 0,stdio:["pipe","pipe","pipe"],env:w({NO_COLOR:"1"})});this.process=t,this.stderr="",l({input:t.stdout}).on("line",r=>{if(!r.trim())return;let s;try{s=JSON.parse(r)}catch{return}this.handleMessage(s)}),t.stderr?.on("data",r=>{this.stderr+=r.toString()}),t.on("close",r=>{this.process===t&&(this.process=null,this.rejectAllPending(new Error(this.stderr.trim()||`codex app-server proxy exited with code ${r}`)))}),t.on("error",r=>{this.process===t&&(this.process=null,this.rejectAllPending(r))})}async initialize(){this.initialized||(await this.start(),await this.sendRpc("initialize",{clientInfo:y,capabilities:{experimentalApi:!0}}),this.initialized=!0)}async readThreadActivity(e){await this.initialize();const t=await this.sendRpc("thread/read",{threadId:e,includeTurns:!0}),n=t.thread?.status??null,r=n?.type==="active",s=m(t.thread?.turns);return{active:r,turnId:s,runPhase:r?g(n):null,canStop:!!(r&&s)}}async interruptThread(e){const t=await this.readThreadActivity(e);return t.turnId?(await this.sendRpc("turn/interrupt",{threadId:e,turnId:t.turnId},5e3),{active:!1,turnId:t.turnId,runPhase:null,canStop:!1}):t}async close(){const e=this.process;this.process=null,e&&(e.kill("SIGTERM"),await new Promise(t=>{e.on("close",t),setTimeout(()=>{e.kill("SIGKILL"),t()},1e3).unref?.()}),this.rejectAllPending(new Error("codex app-server proxy stopped")))}sendRpc(e,t,n=this.opts.timeoutMs??8e3){const r=this.process;if(!r?.stdin)return Promise.reject(new Error("codex app-server proxy is not running"));const s=this.rpcSeq++,u=JSON.stringify({id:s,method:e,params:t});return new Promise((p,o)=>{const a=setTimeout(()=>{this.pendingRequests.delete(s),o(new Error(`codex app-server proxy request timed out: ${e}`))},n);this.pendingRequests.set(s,{resolve:p,reject:o,timer:a}),r.stdin.write(`${u}
|
|
2
|
+
`,c=>{c&&(clearTimeout(a),this.pendingRequests.delete(s),o(c))})})}handleMessage(e){if(e.id==null)return;const t=this.pendingRequests.get(e.id);t&&(clearTimeout(t.timer),this.pendingRequests.delete(e.id),e.error?t.reject(new Error(e.error.message||`codex app-server proxy error ${e.error.code??""}`.trim())):t.resolve(e.result))}rejectAllPending(e){for(const[t,n]of this.pendingRequests.entries())clearTimeout(n.timer),n.reject(e),this.pendingRequests.delete(t)}}async function T(i){const e=new d({workDir:i.workDir,timeoutMs:5e3});try{return await e.readThreadActivity(i.threadId)}catch{return null}finally{await e.close().catch(()=>{})}}async function R(i){const e=new d({workDir:i.workDir,timeoutMs:8e3});try{return await e.interruptThread(i.threadId)}finally{await e.close().catch(()=>{})}}export{d as CodexAppServerProxyClient,R as interruptCodexThread,T as probeCodexThreadActivity};
|