shennian 0.3.85 → 0.3.86

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.
Files changed (99) hide show
  1. package/dist/bin/shennian.js +1 -1
  2. package/dist/publish-build-manifest.json +28 -28
  3. package/dist/src/agents/adapter.js +19 -1
  4. package/dist/src/agents/claude-managed-permissions.js +248 -1
  5. package/dist/src/agents/claude.js +393 -8
  6. package/dist/src/agents/codex-managed-permissions.js +294 -1
  7. package/dist/src/agents/codex-managed-room-tools.js +249 -1
  8. package/dist/src/agents/codex-utils.js +200 -7
  9. package/dist/src/agents/codex.js +1352 -17
  10. package/dist/src/agents/config-status.js +226 -1
  11. package/dist/src/agents/cursor-managed-permissions.js +299 -2
  12. package/dist/src/agents/cursor.js +314 -1
  13. package/dist/src/agents/custom.js +418 -4
  14. package/dist/src/agents/external-channel-instructions.js +94 -11
  15. package/dist/src/agents/gemini.js +180 -1
  16. package/dist/src/agents/manager.d.ts +2 -0
  17. package/dist/src/agents/manager.js +250 -18
  18. package/dist/src/agents/model-registry/cache.js +37 -1
  19. package/dist/src/agents/model-registry/discovery.js +188 -2
  20. package/dist/src/agents/model-registry/parsers.js +521 -4
  21. package/dist/src/agents/model-registry/runner.js +30 -1
  22. package/dist/src/agents/model-registry/service.js +115 -1
  23. package/dist/src/agents/model-registry/types.js +8 -1
  24. package/dist/src/agents/model-registry.js +19 -1
  25. package/dist/src/agents/native-capabilities.js +237 -1
  26. package/dist/src/agents/openclaw.js +293 -2
  27. package/dist/src/agents/opencode-managed-permissions.js +187 -2
  28. package/dist/src/agents/opencode.js +298 -1
  29. package/dist/src/agents/platform-instructions.js +46 -17
  30. package/dist/src/agents/runtime-compatibility.js +44 -1
  31. package/dist/src/agents/workbuddy-managed-permissions.js +329 -2
  32. package/dist/src/agents/workbuddy.js +444 -3
  33. package/dist/src/commands/room.js +2 -2
  34. package/dist/src/fs/boundary.js +185 -1
  35. package/dist/src/fs/handler.js +130 -1
  36. package/dist/src/fs/security.js +32 -1
  37. package/dist/src/fs/text-decoder.js +110 -1
  38. package/dist/src/index.js +587 -3
  39. package/dist/src/manager/prompt.js +34 -29
  40. package/dist/src/manager/registry.js +317 -1
  41. package/dist/src/manager/retired-external-channel-compat.js +40 -1
  42. package/dist/src/manager/runtime.d.ts +4 -0
  43. package/dist/src/manager/runtime.js +1514 -23
  44. package/dist/src/native-fusion/codex-parser.js +660 -4
  45. package/dist/src/native-fusion/codex-user-input.js +102 -5
  46. package/dist/src/native-fusion/config.js +5 -1
  47. package/dist/src/native-fusion/file-watcher.js +191 -1
  48. package/dist/src/native-fusion/local-repository.js +569 -2
  49. package/dist/src/native-fusion/opencode-parser.js +130 -3
  50. package/dist/src/native-fusion/parsers.js +140 -3
  51. package/dist/src/native-fusion/service.js +739 -2
  52. package/dist/src/native-fusion/session-header.js +101 -2
  53. package/dist/src/native-fusion/state.js +104 -2
  54. package/dist/src/native-fusion/types.js +1 -1
  55. package/dist/src/personal-sync/machine-authority.js +34 -1
  56. package/dist/src/room/activation-audit.js +45 -2
  57. package/dist/src/room/activation-policy.js +30 -1
  58. package/dist/src/room/activation-service.d.ts +1 -0
  59. package/dist/src/room/activation-service.js +408 -8
  60. package/dist/src/room/invite-bootstrap.js +156 -1
  61. package/dist/src/room/managed-context.d.ts +1 -1
  62. package/dist/src/room/managed-context.js +1 -1
  63. package/dist/src/room/managed-prompt-composer.d.ts +1 -1
  64. package/dist/src/room/managed-prompt-composer.js +6 -5
  65. package/dist/src/room/managed-room-binding.js +167 -1
  66. package/dist/src/room/managed-room-ipc.d.ts +2 -2
  67. package/dist/src/room/managed-room-ipc.js +2 -2
  68. package/dist/src/room/mirror-sync-service.js +183 -1
  69. package/dist/src/room/room-action-client.d.ts +11 -0
  70. package/dist/src/room/room-action-client.js +1 -1
  71. package/dist/src/room/room-binding-client.d.ts +1 -0
  72. package/dist/src/room/room-binding-client.js +151 -1
  73. package/dist/src/security/managed-agent-policy.d.ts +3 -2
  74. package/dist/src/security/managed-agent-policy.js +1 -1
  75. package/dist/src/session/archive-zip.js +220 -1
  76. package/dist/src/session/deletion-sync-state.js +136 -2
  77. package/dist/src/session/handlers/agent-capabilities.js +14 -1
  78. package/dist/src/session/handlers/agent-config.js +150 -1
  79. package/dist/src/session/handlers/agents.js +55 -1
  80. package/dist/src/session/handlers/chat.d.ts +1 -1
  81. package/dist/src/session/handlers/chat.js +1030 -2
  82. package/dist/src/session/handlers/control.js +61 -1
  83. package/dist/src/session/handlers/fs.js +594 -1
  84. package/dist/src/session/handlers/message-status.js +15 -1
  85. package/dist/src/session/handlers/remote-access.js +43 -1
  86. package/dist/src/session/handlers/room-managed.js +101 -1
  87. package/dist/src/session/handlers/session-refresh.js +35 -1
  88. package/dist/src/session/handlers/title.js +79 -1
  89. package/dist/src/session/handlers/tool-detail.js +149 -1
  90. package/dist/src/session/handlers/voice-window.js +62 -1
  91. package/dist/src/session/history-subscriptions.js +470 -1
  92. package/dist/src/session/manager.js +658 -1
  93. package/dist/src/session/native-cleanup-outbox.js +287 -2
  94. package/dist/src/session/native-session-lifecycle.js +327 -6
  95. package/dist/src/session/queue.d.ts +5 -0
  96. package/dist/src/session/queue.js +8 -8
  97. package/dist/src/upgrade/scheduler.js +126 -1
  98. package/node_modules/@shennian/wire/dist/agent-workspace.js +1 -1
  99. package/package.json +1 -1
@@ -1 +1,314 @@
1
- import{createInterface as l}from"node:readline";import{randomUUID as d}from"node:crypto";import{AgentAdapter as c,registerAgent as h}from"./adapter.js";import{resolveBuiltinCommand as u,spawnResolvedCommand as m}from"./command-spec.js";import{buildAgentProcessEnv as g,buildManagedAgentProcessEnv as f}from"../agent-env.js";import{buildInlineChannelPreamble as p}from"./platform-instructions.js";import{resolveManagedAgentAdapterEnforcement as v}from"../security/managed-agent-policy.js";import{registerManagedAgentRuntimeSecurity as E}from"../security/managed-agent-runtime.js";import{compileCursorManagedPermissions as w,createCursorManagedConfigDirectory as k,CURSOR_MANAGED_RUNTIME_SECURITY as y,disposeCursorManagedConfigDirectory as C}from"./cursor-managed-permissions.js";E("cursor",y);class x extends c{type="cursor";process=null;chatId=null;workDir=null;seq=0;runId="";emittedText="";externalChannel=null;shennianSessionId=null;extraEnv={};managedAgentPolicy=null;managedConfigDir=null;configure(t){this.shennianSessionId=t.sessionId??null,this.externalChannel=t.externalChannel??null,this.extraEnv=t.env??{},"managedAgentPolicy"in t&&(this.managedAgentPolicy=t.managedAgentPolicy??null),this.managedAgentPolicy&&(this.workDir=this.managedAgentPolicy.adapterPolicy.workDir)}async start(t,s,e){this.workDir=this.managedAgentPolicy?.adapterPolicy.workDir??s,this.seq=0,e&&(this.chatId=e)}async send(t,s,e,n,o,r){if(r?.source==="room_activation"&&!this.managedAgentPolicy)throw new Error("managed_agent_policy_missing");await this.killProcess(),this.runId=d(),this.resetRunState();const a=["-p",`${p(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,o)}${t}`,"--output-format","stream-json","--stream-partial-output"];s&&a.push("--model",s),this.chatId&&a.push("--continue"),await this.spawnAndParse(a)}async resume(t){await this.killProcess(),this.chatId=t,this.runId=d(),this.resetRunState(),await this.spawnAndParse(["--resume",t,"--output-format","stream-json","--stream-partial-output"])}async stop(){await this.killProcess()}async spawnAndParse(t){const s=u("cursor");if(!s){this.emit("error",new Error('Cursor Agent CLI not found. Expected "agent" or "cursor agent".'));return}const e=await this.prepareManagedLaunch();let n;try{n=m(s,[...t,...e.args],{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:e.env})}catch(i){throw await this.disposeManagedConfig(e.configDir),i}this.process=n,this.managedConfigDir=e.configDir,l({input:n.stdout}).on("line",i=>{if(i.trim())try{const a=JSON.parse(i);this.handleStreamEvent(a)}catch{this.emitEvent({state:"delta",text:i})}});let r="";n.stderr?.on("data",i=>{r+=i.toString()}),n.on("close",i=>{if(this.process===n&&(this.process=null,this.disposeManagedConfig(e.configDir),i!==0&&i!==null)){const a=r.trim()||`cursor agent exited with code ${i}`;this.emitEvent({state:"error",message:a})}}),n.on("error",i=>{this.process===n&&(this.process=null,this.disposeManagedConfig(e.configDir),i.code==="ENOENT"?this.emit("error",new Error('Command "cursor" not found. Is Cursor CLI installed?')):this.emit("error",i))})}async prepareManagedLaunch(){const t=this.managedAgentPolicy;if(!t)return{args:["--trust"],env:g(this.extraEnv),configDir:null};const s=w(v(t),t.adapterPolicy.workDir),e=await k(s),n=f({agentType:"cursor",providerEnv:this.extraEnv,sessionEnv:this.extraEnv,runtimeEnv:{NO_COLOR:"1"}});return n.CURSOR_CONFIG_DIR=e,{args:s.args,env:n,configDir:e}}async disposeManagedConfig(t){t&&(this.managedConfigDir===t&&(this.managedConfigDir=null),await C(t).catch(()=>{}))}handleStreamEvent(t){switch(t.session_id&&!this.chatId&&(this.chatId=t.session_id),t.chat_id&&!this.chatId&&(this.chatId=t.chat_id),t.type??t.event){case"system":break;case"assistant":{if(t.message?.content){if(!this.isLiveAssistantDelta(t))break;for(const e of t.message.content)e.type==="text"&&e.text?this.emitTextDelta(e.text):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});break}(t.delta??t.text)&&this.emitEvent({state:"delta",text:t.delta??t.text});break}case"user":break;case"result":{if(t.subtype==="success"||!t.is_error){this.emitFinalResultDelta(t.result);const e=t.usage;this.emitEvent({state:"final",agentSessionId:this.chatId??void 0,usage:e?{inputTokens:e.inputTokens??e.input_tokens??0,outputTokens:e.outputTokens??e.output_tokens??0}:void 0})}else this.emitEvent({state:"error",message:t.result??t.error??"unknown error"});break}case"error":{this.emitEvent({state:"error",message:t.error??"unknown error"});break}case"text":case"delta":case"content":{const e=t.delta??t.text;e&&this.emitEvent({state:"delta",text:e});break}case"done":{this.emitEvent({state:"final",agentSessionId:this.chatId??void 0});break}default:t.done?this.emitEvent({state:"final",agentSessionId:this.chatId??void 0}):(t.delta??t.text)&&this.emitEvent({state:"delta",text:t.delta??t.text})}}emitEvent(t){const s={...t,runId:this.runId,seq:this.seq++};this.emit("agentEvent",s)}async killProcess(){const t=this.process;if(!t){await this.disposeManagedConfig(this.managedConfigDir);return}this.process=null,t.kill("SIGTERM"),await new Promise(s=>{t.on("close",s),setTimeout(()=>{t.kill("SIGKILL"),s()},3e3)}),await this.disposeManagedConfig(this.managedConfigDir)}resetRunState(){this.seq=0,this.emittedText=""}isLiveAssistantDelta(t){return t.timestamp_ms!=null&&!t.model_call_id}emitTextDelta(t){t&&(this.emittedText+=t,this.emitEvent({state:"delta",text:t}))}emitFinalResultDelta(t){if(!t)return;if(!this.emittedText){this.emitTextDelta(t);return}if(!t.startsWith(this.emittedText))return;const s=t.slice(this.emittedText.length);s&&this.emitTextDelta(s)}}h("cursor",()=>new x);export{x as CursorAdapter};
1
+ // @arch docs/architecture/cli/agent-adapters.md
2
+ // @test src/__tests__/cursor-adapter.test.ts
3
+ import { createInterface } from 'node:readline';
4
+ import { randomUUID } from 'node:crypto';
5
+ import { AgentAdapter, registerAgent } from './adapter.js';
6
+ import { resolveBuiltinCommand, spawnResolvedCommand } from './command-spec.js';
7
+ import { buildAgentProcessEnv, buildManagedAgentProcessEnv } from '../agent-env.js';
8
+ import { buildInlineChannelPreamble } from './platform-instructions.js';
9
+ import { resolveManagedAgentAdapterEnforcement, } from '../security/managed-agent-policy.js';
10
+ import { registerManagedAgentRuntimeSecurity } from '../security/managed-agent-runtime.js';
11
+ import { compileCursorManagedPermissions, createCursorManagedConfigDirectory, CURSOR_MANAGED_RUNTIME_SECURITY, disposeCursorManagedConfigDirectory, } from './cursor-managed-permissions.js';
12
+ registerManagedAgentRuntimeSecurity('cursor', CURSOR_MANAGED_RUNTIME_SECURITY);
13
+ export class CursorAdapter extends AgentAdapter {
14
+ type = 'cursor';
15
+ process = null;
16
+ chatId = null;
17
+ workDir = null;
18
+ seq = 0;
19
+ runId = '';
20
+ emittedText = '';
21
+ externalChannel = null;
22
+ shennianSessionId = null;
23
+ extraEnv = {};
24
+ managedAgentPolicy = null;
25
+ managedConfigDir = null;
26
+ configure(options) {
27
+ this.shennianSessionId = options.sessionId ?? null;
28
+ this.externalChannel = options.externalChannel ?? null;
29
+ this.extraEnv = options.env ?? {};
30
+ if ('managedAgentPolicy' in options) {
31
+ this.managedAgentPolicy = options.managedAgentPolicy ?? null;
32
+ }
33
+ if (this.managedAgentPolicy)
34
+ this.workDir = this.managedAgentPolicy.adapterPolicy.workDir;
35
+ }
36
+ async start(_sessionId, workDir, agentSessionId) {
37
+ this.workDir = this.managedAgentPolicy?.adapterPolicy.workDir ?? workDir;
38
+ this.seq = 0;
39
+ if (agentSessionId)
40
+ this.chatId = agentSessionId;
41
+ }
42
+ async send(text, modelId, _reasoningEffort, _attachments, agentSystemPrompt, context) {
43
+ if (context?.source === 'room_activation' && !this.managedAgentPolicy) {
44
+ throw new Error('managed_agent_policy_missing');
45
+ }
46
+ await this.killProcess();
47
+ this.runId = randomUUID();
48
+ this.resetRunState();
49
+ const outgoing = `${buildInlineChannelPreamble(this.workDir ?? process.cwd(), this.externalChannel, this.shennianSessionId ?? undefined, agentSystemPrompt)}${text}`;
50
+ const args = ['-p', outgoing, '--output-format', 'stream-json', '--stream-partial-output'];
51
+ if (modelId) {
52
+ args.push('--model', modelId);
53
+ }
54
+ if (this.chatId) {
55
+ args.push('--continue');
56
+ }
57
+ await this.spawnAndParse(args);
58
+ }
59
+ async resume(agentSessionId) {
60
+ await this.killProcess();
61
+ this.chatId = agentSessionId;
62
+ this.runId = randomUUID();
63
+ this.resetRunState();
64
+ await this.spawnAndParse([
65
+ '--resume',
66
+ agentSessionId,
67
+ '--output-format',
68
+ 'stream-json',
69
+ '--stream-partial-output',
70
+ ]);
71
+ }
72
+ async stop() {
73
+ await this.killProcess();
74
+ }
75
+ async spawnAndParse(args) {
76
+ const spec = resolveBuiltinCommand('cursor');
77
+ if (!spec) {
78
+ this.emit('error', new Error('Cursor Agent CLI not found. Expected "agent" or "cursor agent".'));
79
+ return;
80
+ }
81
+ const managedLaunch = await this.prepareManagedLaunch();
82
+ let proc;
83
+ try {
84
+ proc = spawnResolvedCommand(spec, [...args, ...managedLaunch.args], {
85
+ cwd: this.workDir ?? undefined,
86
+ stdio: ['ignore', 'pipe', 'pipe'],
87
+ env: managedLaunch.env,
88
+ });
89
+ }
90
+ catch (error) {
91
+ await this.disposeManagedConfig(managedLaunch.configDir);
92
+ throw error;
93
+ }
94
+ this.process = proc;
95
+ this.managedConfigDir = managedLaunch.configDir;
96
+ const rl = createInterface({ input: proc.stdout });
97
+ rl.on('line', (line) => {
98
+ if (!line.trim())
99
+ return;
100
+ try {
101
+ const obj = JSON.parse(line);
102
+ this.handleStreamEvent(obj);
103
+ }
104
+ catch {
105
+ // 非 JSON 行当作纯文本 delta
106
+ this.emitEvent({ state: 'delta', text: line });
107
+ }
108
+ });
109
+ let stderrBuf = '';
110
+ proc.stderr?.on('data', (chunk) => {
111
+ stderrBuf += chunk.toString();
112
+ });
113
+ proc.on('close', (code) => {
114
+ if (this.process !== proc)
115
+ return;
116
+ this.process = null;
117
+ void this.disposeManagedConfig(managedLaunch.configDir);
118
+ if (code !== 0 && code !== null) {
119
+ const msg = stderrBuf.trim() || `cursor agent exited with code ${code}`;
120
+ this.emitEvent({ state: 'error', message: msg });
121
+ }
122
+ });
123
+ proc.on('error', (err) => {
124
+ if (this.process !== proc)
125
+ return;
126
+ this.process = null;
127
+ void this.disposeManagedConfig(managedLaunch.configDir);
128
+ if (err.code === 'ENOENT') {
129
+ this.emit('error', new Error('Command "cursor" not found. Is Cursor CLI installed?'));
130
+ }
131
+ else {
132
+ this.emit('error', err);
133
+ }
134
+ });
135
+ }
136
+ async prepareManagedLaunch() {
137
+ const compiled = this.managedAgentPolicy;
138
+ if (!compiled) {
139
+ return {
140
+ args: ['--trust'],
141
+ env: buildAgentProcessEnv(this.extraEnv),
142
+ configDir: null,
143
+ };
144
+ }
145
+ const nativeConfig = compileCursorManagedPermissions(resolveManagedAgentAdapterEnforcement(compiled), compiled.adapterPolicy.workDir);
146
+ const configDir = await createCursorManagedConfigDirectory(nativeConfig);
147
+ const env = buildManagedAgentProcessEnv({
148
+ agentType: 'cursor',
149
+ providerEnv: this.extraEnv,
150
+ sessionEnv: this.extraEnv,
151
+ runtimeEnv: { NO_COLOR: '1' },
152
+ });
153
+ // CURSOR_CONFIG_DIR contains only Shennian-generated, non-secret policy.
154
+ // It is assigned after allowlist filtering so Cursor cannot fall back to
155
+ // the user's mutable global CLI configuration.
156
+ env.CURSOR_CONFIG_DIR = configDir;
157
+ return { args: nativeConfig.args, env, configDir };
158
+ }
159
+ async disposeManagedConfig(configDir) {
160
+ if (!configDir)
161
+ return;
162
+ if (this.managedConfigDir === configDir)
163
+ this.managedConfigDir = null;
164
+ await disposeCursorManagedConfigDirectory(configDir).catch(() => { });
165
+ }
166
+ handleStreamEvent(obj) {
167
+ if (obj.session_id && !this.chatId) {
168
+ this.chatId = obj.session_id;
169
+ }
170
+ if (obj.chat_id && !this.chatId) {
171
+ this.chatId = obj.chat_id;
172
+ }
173
+ const eventType = obj.type ?? obj.event;
174
+ switch (eventType) {
175
+ case 'system': {
176
+ // init event — session_id already captured above
177
+ break;
178
+ }
179
+ case 'assistant': {
180
+ // Cursor's --stream-partial-output currently emits duplicate buffered
181
+ // flushes. Only timestamped assistant events without model_call_id are
182
+ // safe to treat as live deltas; use result.result as the terminal
183
+ // canonical text.
184
+ if (obj.message?.content) {
185
+ if (!this.isLiveAssistantDelta(obj))
186
+ break;
187
+ for (const block of obj.message.content) {
188
+ if (block.type === 'text' && block.text) {
189
+ this.emitTextDelta(block.text);
190
+ }
191
+ else if (block.type === 'thinking' && block.thinking) {
192
+ this.emitEvent({ state: 'delta', text: block.thinking, thinking: true });
193
+ }
194
+ else if (block.type === 'tool_use') {
195
+ this.emitEvent({ state: 'tool-call', name: block.name, args: block.input });
196
+ }
197
+ }
198
+ break;
199
+ }
200
+ // Legacy flat
201
+ if (obj.delta ?? obj.text) {
202
+ this.emitEvent({ state: 'delta', text: (obj.delta ?? obj.text) });
203
+ }
204
+ break;
205
+ }
206
+ case 'user':
207
+ break; // echo of user message
208
+ case 'result': {
209
+ if (obj.subtype === 'success' || !obj.is_error) {
210
+ this.emitFinalResultDelta(obj.result);
211
+ const u = obj.usage;
212
+ this.emitEvent({
213
+ state: 'final',
214
+ agentSessionId: this.chatId ?? undefined,
215
+ usage: u
216
+ ? {
217
+ inputTokens: u.inputTokens ?? u.input_tokens ?? 0,
218
+ outputTokens: u.outputTokens ?? u.output_tokens ?? 0,
219
+ }
220
+ : undefined,
221
+ });
222
+ }
223
+ else {
224
+ this.emitEvent({
225
+ state: 'error',
226
+ message: obj.result ?? obj.error ?? 'unknown error',
227
+ });
228
+ }
229
+ break;
230
+ }
231
+ case 'error': {
232
+ this.emitEvent({
233
+ state: 'error',
234
+ message: obj.error ?? 'unknown error',
235
+ });
236
+ break;
237
+ }
238
+ // Legacy event types
239
+ case 'text':
240
+ case 'delta':
241
+ case 'content': {
242
+ const text = obj.delta ?? obj.text;
243
+ if (text)
244
+ this.emitEvent({ state: 'delta', text });
245
+ break;
246
+ }
247
+ case 'done': {
248
+ this.emitEvent({ state: 'final', agentSessionId: this.chatId ?? undefined });
249
+ break;
250
+ }
251
+ default: {
252
+ if (obj.done) {
253
+ this.emitEvent({ state: 'final', agentSessionId: this.chatId ?? undefined });
254
+ }
255
+ else if (obj.delta ?? obj.text) {
256
+ this.emitEvent({ state: 'delta', text: (obj.delta ?? obj.text) });
257
+ }
258
+ }
259
+ }
260
+ }
261
+ emitEvent(partial) {
262
+ const event = {
263
+ ...partial,
264
+ runId: this.runId,
265
+ seq: this.seq++,
266
+ };
267
+ this.emit('agentEvent', event);
268
+ }
269
+ async killProcess() {
270
+ const proc = this.process;
271
+ if (!proc) {
272
+ await this.disposeManagedConfig(this.managedConfigDir);
273
+ return;
274
+ }
275
+ this.process = null;
276
+ proc.kill('SIGTERM');
277
+ await new Promise((resolve) => {
278
+ proc.on('close', resolve);
279
+ setTimeout(() => {
280
+ proc.kill('SIGKILL');
281
+ resolve();
282
+ }, 3000);
283
+ });
284
+ await this.disposeManagedConfig(this.managedConfigDir);
285
+ }
286
+ resetRunState() {
287
+ this.seq = 0;
288
+ this.emittedText = '';
289
+ }
290
+ isLiveAssistantDelta(obj) {
291
+ return obj.timestamp_ms != null && !obj.model_call_id;
292
+ }
293
+ emitTextDelta(text) {
294
+ if (!text)
295
+ return;
296
+ this.emittedText += text;
297
+ this.emitEvent({ state: 'delta', text });
298
+ }
299
+ emitFinalResultDelta(result) {
300
+ if (!result)
301
+ return;
302
+ if (!this.emittedText) {
303
+ this.emitTextDelta(result);
304
+ return;
305
+ }
306
+ if (!result.startsWith(this.emittedText))
307
+ return;
308
+ const tail = result.slice(this.emittedText.length);
309
+ if (tail) {
310
+ this.emitTextDelta(tail);
311
+ }
312
+ }
313
+ }
314
+ registerAgent('cursor', () => new CursorAdapter());