@kafca/agentdock 0.1.29 → 0.1.30

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 (55) hide show
  1. package/dist/renderer/assets/{Badge-ngf0eCzI.js → Badge-DlVJI1Ys.js} +1 -1
  2. package/dist/renderer/assets/{Chat-tCGY5odh.js → Chat-oa8OjaHQ.js} +1 -1
  3. package/dist/renderer/assets/{ChatMarkdown-vqDWgVNb.js → ChatMarkdown-C-N8KS5C.js} +1 -1
  4. package/dist/renderer/assets/{Config-YsVDQmIs.js → Config-D9sL_d4D.js} +1 -1
  5. package/dist/renderer/assets/{CronList-DQN0T7Yc.js → CronList-Z5JU3DHk.js} +1 -1
  6. package/dist/renderer/assets/{Dashboard-C2O6Yxq3.js → Dashboard-D3BwbG43.js} +2 -2
  7. package/dist/renderer/assets/{EmptyState-CTkA-fBQ.js → EmptyState-QOj765Ul.js} +1 -1
  8. package/dist/renderer/assets/{KnowledgeDetail-DjLZDItQ.js → KnowledgeDetail-J7n01mPu.js} +1 -1
  9. package/dist/renderer/assets/{KnowledgeHome-2NHeRZxW.js → KnowledgeHome-BFnH0NVk.js} +1 -1
  10. package/dist/renderer/assets/{Logs-CQ6j-Sct.js → Logs-DfSUifXc.js} +1 -1
  11. package/dist/renderer/assets/{Modal-9g1uWJfC.js → Modal-QjEGhyru.js} +1 -1
  12. package/dist/renderer/assets/{Page-B4mPLn6n.js → Page-qdHFSw7x.js} +1 -1
  13. package/dist/renderer/assets/{ProjectDetail-pBXOAeL4.js → ProjectDetail-DS_rfvhh.js} +1 -1
  14. package/dist/renderer/assets/{ProjectList-B9PYfZaS.js → ProjectList-COtyZd7H.js} +1 -1
  15. package/dist/renderer/assets/{Select-BWFQJ2R8.js → Select-BQ8mncVu.js} +1 -1
  16. package/dist/renderer/assets/{SessionChat-fBrzJs3A.js → SessionChat-DjVnjuQy.js} +1 -1
  17. package/dist/renderer/assets/{SessionList-DjHOsk7X.js → SessionList-88dgGZJ8.js} +1 -1
  18. package/dist/renderer/assets/{ThreadChat-MagPeJD0.js → ThreadChat-BCdbTxBo.js} +1 -1
  19. package/dist/renderer/assets/{Workspace-nfTcxlhw.js → Workspace-D_hzSJjX.js} +1 -1
  20. package/dist/renderer/assets/{arrow-left-CIWZ6JEB.js → arrow-left-BMpknulW.js} +1 -1
  21. package/dist/renderer/assets/{book-open-Ck6BgBhN.js → book-open-CiaOeQbU.js} +1 -1
  22. package/dist/renderer/assets/{check-CtB2ZLVE.js → check-CgwYH4GF.js} +1 -1
  23. package/dist/renderer/assets/{chevron-down--8lODnN0.js → chevron-down-BzD2S1OO.js} +1 -1
  24. package/dist/renderer/assets/{circle-CKQOJcbh.js → circle-BDHD7g7l.js} +1 -1
  25. package/dist/renderer/assets/{desktop-Do2I28CT.js → desktop-BiR5LPL5.js} +1 -1
  26. package/dist/renderer/assets/{funnel-CkZuFIwa.js → funnel-Bruf5FYA.js} +1 -1
  27. package/dist/renderer/assets/{heart-CAX_CqFQ.js → heart-D7Mz04B0.js} +1 -1
  28. package/dist/renderer/assets/{index-DvAYflFj.js → index-CL1e8m3U.js} +2 -2
  29. package/dist/renderer/assets/{index--_L0Y77h.js → index-gZIRr4_o.js} +1 -1
  30. package/dist/renderer/assets/{pencil-sIRhtchu.js → pencil-C6gzDMse.js} +1 -1
  31. package/dist/renderer/assets/{play-CJNRbCL5.js → play-DqTXX-Pr.js} +1 -1
  32. package/dist/renderer/assets/{plug-DsFe9GBx.js → plug-ykmbeaO3.js} +1 -1
  33. package/dist/renderer/assets/{plus-KDwEI-Rs.js → plus-DHE60vMX.js} +1 -1
  34. package/dist/renderer/assets/projects-Bx5p10th.js +1 -0
  35. package/dist/renderer/assets/{save-C-p5r3K-.js → save-CGIvrdQI.js} +1 -1
  36. package/dist/renderer/assets/{search-BZxQJb2k.js → search-D7IFAwyE.js} +1 -1
  37. package/dist/renderer/assets/{server-BV-K022I.js → server-aOsirp7I.js} +1 -1
  38. package/dist/renderer/assets/{session-utils-ClQTa8yS.js → session-utils-Dxfp4ohQ.js} +1 -1
  39. package/dist/renderer/assets/{sessions-B0FSCA9O.js → sessions-Db1XPbG2.js} +1 -1
  40. package/dist/renderer/assets/{shield-check-B6AjkXUd.js → shield-check-ChXeQK-d.js} +1 -1
  41. package/dist/renderer/assets/{trash-2-41Pv4qRx.js → trash-2-CfN-c1zw.js} +1 -1
  42. package/dist/renderer/assets/{user-NKKHCKm9.js → user-C7OHaBp4.js} +1 -1
  43. package/dist/renderer/assets/{wifi-off-E1ZNhLG5.js → wifi-off-CpaJigye.js} +1 -1
  44. package/dist/renderer/index.html +1 -1
  45. package/dist-electron/electron/local-core-refactor.test.js +301 -18
  46. package/dist-electron/electron/workspace-task-store.test.js +7 -1
  47. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-backend.js +7 -2
  48. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-progress.js +239 -7
  49. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-session-coordinator.js +10 -6
  50. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-transport.js +1 -0
  51. package/dist-electron/services/local-ai-core/src/acp/local-core-acp-turn-coordinator.js +79 -2
  52. package/dist-electron/services/local-ai-core/src/channel/lark/runtime-state.js +1 -1
  53. package/dist-electron/services/local-ai-core/src/channel/weixin/local-core-weixin-gateway.js +13 -1
  54. package/package.json +1 -1
  55. package/dist/renderer/assets/projects-CJUs2vaq.js +0 -1
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.applyAssistantMessageChunk = applyAssistantMessageChunk;
4
4
  exports.applyThoughtChunk = applyThoughtChunk;
5
+ exports.closeThoughtSegment = closeThoughtSegment;
5
6
  exports.registerPendingToolCall = registerPendingToolCall;
6
7
  exports.resolveToolCallForUpdate = resolveToolCallForUpdate;
7
8
  exports.resolveFallbackToolCall = resolveFallbackToolCall;
@@ -16,6 +17,8 @@ exports.isTerminalToolStatus = isTerminalToolStatus;
16
17
  exports.formatPlanProgress = formatPlanProgress;
17
18
  exports.extractToolCallKey = extractToolCallKey;
18
19
  exports.extractToolCallInput = extractToolCallInput;
20
+ exports.recordToolObservation = recordToolObservation;
21
+ exports.stripObservedToolTranscriptsFromAssistantText = stripObservedToolTranscriptsFromAssistantText;
19
22
  function applyAssistantMessageChunk(currentTurn, text) {
20
23
  if (!text) {
21
24
  return null;
@@ -41,8 +44,12 @@ function applyThoughtChunk(currentTurn, text) {
41
44
  if (!text) {
42
45
  return null;
43
46
  }
44
- currentTurn.thoughtText = mergeStreamingText(currentTurn.thoughtText, text);
47
+ const projection = mergeThoughtSegment(currentTurn.thoughtText, text);
48
+ currentTurn.thoughtText = projection.fullText;
45
49
  const content = currentTurn.thoughtText.trim();
50
+ if (!content) {
51
+ return null;
52
+ }
46
53
  if (!currentTurn.thoughtPreviewStarted) {
47
54
  currentTurn.thoughtPreviewStarted = true;
48
55
  return {
@@ -61,23 +68,67 @@ function applyThoughtChunk(currentTurn, text) {
61
68
  bridgeKind: 'thought',
62
69
  };
63
70
  }
64
- function mergeStreamingText(current, next) {
71
+ function closeThoughtSegment(currentTurn) {
72
+ const thoughtText = currentTurn.thoughtText || '';
73
+ if (!thoughtText.trim()) {
74
+ return;
75
+ }
76
+ const nextSequence = (currentTurn.thoughtSequence || 1) + 1;
77
+ const runId = currentTurn.runId || 'thought';
78
+ currentTurn.thoughtSequence = nextSequence;
79
+ currentTurn.thoughtText = '';
80
+ currentTurn.thoughtPreviewStarted = false;
81
+ currentTurn.thoughtMessageId = `${runId}-thought-${nextSequence}`;
82
+ currentTurn.thoughtPreviewHandle = `${runId}-thought-preview-${nextSequence}`;
83
+ }
84
+ function mergeThoughtSegment(current, next) {
65
85
  if (!current) {
66
- return next;
86
+ return { fullText: next, segmentText: next };
67
87
  }
68
88
  if (next.startsWith(current)) {
69
- return next;
89
+ return {
90
+ fullText: next,
91
+ segmentText: next.slice(current.length),
92
+ };
70
93
  }
71
94
  if (current.endsWith(next)) {
72
- return current;
95
+ return {
96
+ fullText: current,
97
+ segmentText: '',
98
+ };
73
99
  }
74
100
  const maxOverlap = Math.min(current.length, next.length);
75
101
  for (let size = maxOverlap; size > 0; size -= 1) {
76
102
  if (current.endsWith(next.slice(0, size))) {
77
- return current + next.slice(size);
103
+ const suffix = next.slice(size);
104
+ return {
105
+ fullText: current + suffix,
106
+ segmentText: suffix,
107
+ };
78
108
  }
79
109
  }
80
- return current + next;
110
+ return {
111
+ fullText: appendThoughtPiece(current, next),
112
+ segmentText: next,
113
+ };
114
+ }
115
+ function appendThoughtPiece(current, next) {
116
+ if (!current.trim()) {
117
+ return next;
118
+ }
119
+ if (!next.trim()) {
120
+ return current;
121
+ }
122
+ if (/^[,.;:!?,。;:!?、)】》]/.test(next.trimStart())) {
123
+ return current.trimEnd() + next.trimStart();
124
+ }
125
+ if (/^[-/]/.test(next.trimStart()) || /[-/][A-Za-z0-9]*$/.test(current.trimEnd())) {
126
+ return current.trimEnd() + next.trimStart();
127
+ }
128
+ if (/\s$/.test(current) || /^\s/.test(next)) {
129
+ return current + next;
130
+ }
131
+ return `${current.trimEnd()} ${next.trimStart()}`;
81
132
  }
82
133
  function registerPendingToolCall(input) {
83
134
  const title = String(input.update.title || 'Running tool').trim();
@@ -203,3 +254,184 @@ function extractToolCallInput(update) {
203
254
  }
204
255
  return undefined;
205
256
  }
257
+ function recordToolObservation(currentTurn, observation) {
258
+ const normalized = {
259
+ ...observation,
260
+ name: observation.name?.trim() || undefined,
261
+ title: observation.title?.trim() || undefined,
262
+ status: observation.status?.trim() || undefined,
263
+ outputText: observation.outputText?.trim() || undefined,
264
+ };
265
+ if (!normalized.name && !normalized.title && normalized.input === undefined && !normalized.outputText) {
266
+ return;
267
+ }
268
+ currentTurn.toolObservations = [
269
+ ...(currentTurn.toolObservations || []),
270
+ normalized,
271
+ ];
272
+ }
273
+ function stripObservedToolTranscriptsFromAssistantText(text, observations) {
274
+ let remaining = String(text || '');
275
+ const knownObservations = observations || [];
276
+ for (let guard = 0; guard < knownObservations.length; guard += 1) {
277
+ const stripped = stripOneObservedToolTranscriptPrefix(remaining, knownObservations);
278
+ if (stripped === remaining) {
279
+ break;
280
+ }
281
+ remaining = stripped;
282
+ }
283
+ return remaining.trim();
284
+ }
285
+ function stripOneObservedToolTranscriptPrefix(text, observations) {
286
+ const trimmedStart = text.replace(/^\s+/, '');
287
+ if (!trimmedStart) {
288
+ return text;
289
+ }
290
+ const matchingEvidence = observations
291
+ .map((observation) => createToolObservationEvidence(observation))
292
+ .find((evidence) => matchesObservedToolTranscriptPrefix(trimmedStart, evidence));
293
+ if (!matchingEvidence) {
294
+ return text;
295
+ }
296
+ const boundary = findToolTranscriptPrefixBoundary(trimmedStart, matchingEvidence);
297
+ if (boundary <= 0) {
298
+ return text;
299
+ }
300
+ return trimmedStart.slice(boundary);
301
+ }
302
+ function createToolObservationEvidence(observation) {
303
+ const serializedInput = serializeObservationValue(observation.input);
304
+ const serializedOutput = observation.outputText || '';
305
+ const structuredValues = collectStructuredStringValues(serializedOutput);
306
+ return {
307
+ toolNames: uniqueNonEmpty([
308
+ observation.name,
309
+ observation.title,
310
+ ].map((value) => normalizeEvidencePhrase(value || ''))),
311
+ urls: uniqueNonEmpty([
312
+ ...extractUrls(serializedInput),
313
+ ...extractUrls(serializedOutput),
314
+ ]),
315
+ phrases: uniqueNonEmpty([
316
+ ...structuredValues,
317
+ observation.title,
318
+ serializedInput.length <= 300 ? serializedInput : '',
319
+ ].map((value) => normalizeEvidencePhrase(value || '')).filter((value) => value.length >= 12)),
320
+ };
321
+ }
322
+ function matchesObservedToolTranscriptPrefix(text, evidence) {
323
+ const prefix = text.slice(0, 3000);
324
+ const normalizedPrefix = normalizeEvidencePhrase(prefix);
325
+ const hasToolName = evidence.toolNames.some((name) => name && normalizedPrefix.includes(name));
326
+ const urlMatches = evidence.urls.filter((url) => prefix.includes(url)).length;
327
+ const phraseMatches = evidence.phrases.filter((phrase) => normalizedPrefix.includes(phrase)).length;
328
+ if (hasToolName && (urlMatches > 0 || phraseMatches > 0)) {
329
+ return true;
330
+ }
331
+ return urlMatches > 0 && phraseMatches > 0;
332
+ }
333
+ function findToolTranscriptPrefixBoundary(text, evidence) {
334
+ const lines = text.split(/\n/);
335
+ const firstContentLine = lines.find((line) => line.trim());
336
+ if (!firstContentLine || !isTranscriptStartLine(firstContentLine, evidence)) {
337
+ return 0;
338
+ }
339
+ let offset = 0;
340
+ let seenEvidence = false;
341
+ for (let index = 0; index < lines.length; index += 1) {
342
+ const line = lines[index] || '';
343
+ const lineWithNewlineLength = line.length + (index < lines.length - 1 ? 1 : 0);
344
+ if (lineContainsObservationEvidence(line, evidence)) {
345
+ seenEvidence = true;
346
+ }
347
+ if (seenEvidence && index > 0 && line.trim() && !isStructuredTranscriptLine(line, evidence)) {
348
+ return offset;
349
+ }
350
+ offset += lineWithNewlineLength;
351
+ }
352
+ return 0;
353
+ }
354
+ function isTranscriptStartLine(line, evidence) {
355
+ const trimmed = line.trim();
356
+ return lineContainsObservationEvidence(line, evidence) &&
357
+ (/^(```|\{|\[|\*\*[^*]+\*\*|#+\s)/.test(trimmed) || /^[A-Za-z0-9_.-]+:/.test(trimmed));
358
+ }
359
+ function isStructuredTranscriptLine(line, evidence) {
360
+ const trimmed = line.trim();
361
+ if (!trimmed) {
362
+ return true;
363
+ }
364
+ if (lineContainsObservationEvidence(line, evidence)) {
365
+ return true;
366
+ }
367
+ return /^(```|\{|\}|\[|\]|".+":|\*\*[^*]+:\*\*|\*[^*]+\*|#+\s)/.test(trimmed) ||
368
+ /[::]\s*$/.test(trimmed) ||
369
+ /[{}\[\]"]/g.test(trimmed) ||
370
+ /^[A-Za-z0-9_.-]+:/.test(trimmed);
371
+ }
372
+ function lineContainsObservationEvidence(line, evidence) {
373
+ const normalizedLine = normalizeEvidencePhrase(line);
374
+ return evidence.toolNames.some((name) => name && normalizedLine.includes(name)) ||
375
+ evidence.urls.some((url) => line.includes(url)) ||
376
+ evidence.phrases.some((phrase) => phrase && normalizedLine.includes(phrase));
377
+ }
378
+ function serializeObservationValue(value) {
379
+ if (value == null) {
380
+ return '';
381
+ }
382
+ if (typeof value === 'string') {
383
+ return value;
384
+ }
385
+ try {
386
+ return JSON.stringify(value);
387
+ }
388
+ catch {
389
+ return String(value);
390
+ }
391
+ }
392
+ function collectStructuredStringValues(text) {
393
+ const values = [];
394
+ try {
395
+ collectStringValues(JSON.parse(text), values);
396
+ }
397
+ catch {
398
+ const matches = text.matchAll(/"(title|description|url|name|summary)"\s*:\s*"([^"]{12,})"/gi);
399
+ for (const match of matches) {
400
+ values.push(match[2] || '');
401
+ }
402
+ }
403
+ return values;
404
+ }
405
+ function collectStringValues(value, values) {
406
+ if (typeof value === 'string') {
407
+ values.push(value);
408
+ return;
409
+ }
410
+ if (Array.isArray(value)) {
411
+ for (const item of value) {
412
+ collectStringValues(item, values);
413
+ }
414
+ return;
415
+ }
416
+ if (!value || typeof value !== 'object') {
417
+ return;
418
+ }
419
+ for (const entry of Object.values(value)) {
420
+ collectStringValues(entry, values);
421
+ }
422
+ }
423
+ function extractUrls(text) {
424
+ return [...text.matchAll(/https?:\/\/[^\s"'`<>),\]}]+/g)]
425
+ .map((match) => match[0])
426
+ .filter(Boolean);
427
+ }
428
+ function normalizeEvidencePhrase(value) {
429
+ return String(value || '')
430
+ .replace(/\\[nrt]/g, ' ')
431
+ .replace(/\s+/g, ' ')
432
+ .trim()
433
+ .toLowerCase();
434
+ }
435
+ function uniqueNonEmpty(values) {
436
+ return [...new Set(values.map((value) => value.trim()).filter(Boolean))];
437
+ }
@@ -194,14 +194,18 @@ class LocalCoreAcpSessionCoordinator {
194
194
  }
195
195
  buildSessionMeta(threadId, permissionModeOverride = '') {
196
196
  const mode = this.resolveLaunchPermissionMode(threadId, permissionModeOverride);
197
- if (!mode) {
198
- return undefined;
199
- }
200
197
  return {
201
198
  claudeCode: {
202
- options: {
203
- permissionMode: mode,
204
- },
199
+ emitRawSDKMessages: [
200
+ { type: 'system', subtype: 'local_command_output' },
201
+ ],
202
+ ...(mode
203
+ ? {
204
+ options: {
205
+ permissionMode: mode,
206
+ },
207
+ }
208
+ : {}),
205
209
  },
206
210
  };
207
211
  }
@@ -35,6 +35,7 @@ class LocalCoreAcpTransport {
35
35
  loadReplayMode: false,
36
36
  pendingPermissionByRun: new Map(),
37
37
  schedulerJobCreatedByRun: new Map(),
38
+ pendingRawAssistantProgressChunks: [],
38
39
  closed: false,
39
40
  closeReason: null,
40
41
  promptPromise: null,
@@ -11,6 +11,11 @@ class LocalCoreAcpTurnCoordinator {
11
11
  constructor(options) {
12
12
  this.options = options;
13
13
  }
14
+ closePendingThoughtSegment(session) {
15
+ const currentTurn = session.currentTurn;
16
+ if (currentTurn)
17
+ (0, local_core_acp_progress_js_1.closeThoughtSegment)(currentTurn);
18
+ }
14
19
  flushPendingToolCall(session) {
15
20
  const currentTurn = session.currentTurn;
16
21
  const currentRunId = session.currentRunId;
@@ -97,6 +102,7 @@ class LocalCoreAcpTurnCoordinator {
97
102
  }
98
103
  const options = (0, local_core_acp_permission_lifecycle_js_1.parsePermissionOptions)(payload.params?.options);
99
104
  const toolTitle = (0, workspace_acp_permissions_js_1.formatToolCallContent)(payload.params?.toolCall);
105
+ this.closePendingThoughtSegment(session);
100
106
  if ((this.options.getThreadAgentMode?.(session.threadId) || local_core_slash_commands_js_1.DEFAULT_AGENT_MODE) === 'bypassPermissions') {
101
107
  const selected = options.find((option) => option.normalizedAction === 'allow all')
102
108
  || options.find((option) => option.normalizedAction === 'allow')
@@ -172,7 +178,14 @@ class LocalCoreAcpTurnCoordinator {
172
178
  });
173
179
  }
174
180
  handleAgentNotification(session, payload) {
175
- if (session.loadReplayMode || payload.method !== 'session/update') {
181
+ if (session.loadReplayMode) {
182
+ return;
183
+ }
184
+ if (payload.method === '_claude/sdkMessage') {
185
+ this.handleClaudeSdkMessage(session, payload.params?.message);
186
+ return;
187
+ }
188
+ if (payload.method !== 'session/update') {
176
189
  return;
177
190
  }
178
191
  const update = payload.params?.update;
@@ -183,10 +196,25 @@ class LocalCoreAcpTurnCoordinator {
183
196
  }
184
197
  switch (String(update.sessionUpdate || '')) {
185
198
  case 'agent_message_chunk': {
199
+ this.closePendingThoughtSegment(session);
186
200
  this.flushPendingToolCall(session);
187
201
  if (update.content?.type !== 'text') {
188
202
  return;
189
203
  }
204
+ if (isToolScopedAssistantUpdate(update) || consumeRawAssistantProgressChunk(session, String(update.content.text || ''))) {
205
+ const content = String(update.content.text || '').trim();
206
+ if (content) {
207
+ this.options.appendMessage(session.threadId, 'assistant', content, 'progress', undefined, 'tool');
208
+ this.options.emitBridge({
209
+ type: 'reply',
210
+ sessionKey: session.bridgeSessionKey,
211
+ replyCtx: currentRunId,
212
+ bridgeKind: 'tool',
213
+ content,
214
+ });
215
+ }
216
+ return;
217
+ }
190
218
  const projection = (0, local_core_acp_progress_js_1.applyAssistantMessageChunk)(currentTurn, String(update.content.text || ''));
191
219
  if (!projection) {
192
220
  return;
@@ -202,7 +230,6 @@ class LocalCoreAcpTurnCoordinator {
202
230
  return;
203
231
  }
204
232
  case 'agent_thought_chunk': {
205
- this.flushPendingToolCall(session);
206
233
  if (update.content?.type !== 'text') {
207
234
  return;
208
235
  }
@@ -224,11 +251,18 @@ class LocalCoreAcpTurnCoordinator {
224
251
  return;
225
252
  }
226
253
  case 'tool_call': {
254
+ this.closePendingThoughtSegment(session);
227
255
  const toolCall = (0, local_core_acp_progress_js_1.registerPendingToolCall)({ currentTurn, runId: currentRunId, update });
256
+ (0, local_core_acp_progress_js_1.recordToolObservation)(currentTurn, {
257
+ name: toolCall.title,
258
+ title: toolCall.title,
259
+ input: toolCall.input,
260
+ });
228
261
  (0, local_core_acp_progress_js_1.syncLegacyPendingToolCall)(currentTurn, toolCall);
229
262
  return;
230
263
  }
231
264
  case 'tool_call_update': {
265
+ this.closePendingThoughtSegment(session);
232
266
  const title = String(update.title || 'Tool update').trim();
233
267
  const status = String(update.status || '').trim();
234
268
  const content = (0, local_core_acp_progress_js_1.extractToolUpdateContent)(update.content);
@@ -280,11 +314,19 @@ class LocalCoreAcpTurnCoordinator {
280
314
  detail: displayTitle,
281
315
  content,
282
316
  });
317
+ (0, local_core_acp_progress_js_1.recordToolObservation)(currentTurn, {
318
+ name: toolName || displayTitle || title,
319
+ title: displayTitle || title,
320
+ status,
321
+ input: updateInput === undefined ? toolCall?.input : updateInput,
322
+ outputText: content,
323
+ });
283
324
  this.emitProgress(session, currentRunId, (0, local_core_acp_progress_js_1.formatToolProgressMessage)({ toolName, title: displayTitle, status, content }), messageId, toolCallPayload);
284
325
  (0, local_core_acp_progress_js_1.syncLegacyPendingToolCall)(currentTurn, (0, local_core_acp_progress_js_1.resolveFallbackToolCall)(currentTurn));
285
326
  return;
286
327
  }
287
328
  case 'plan': {
329
+ this.closePendingThoughtSegment(session);
288
330
  this.flushPendingToolCall(session);
289
331
  const entries = Array.isArray(update.entries) ? update.entries : [];
290
332
  if (entries.length === 0) {
@@ -308,6 +350,19 @@ class LocalCoreAcpTurnCoordinator {
308
350
  return;
309
351
  }
310
352
  }
353
+ handleClaudeSdkMessage(session, message) {
354
+ if (!session.currentTurn || message?.type !== 'system' || message?.subtype !== 'local_command_output') {
355
+ return;
356
+ }
357
+ const content = typeof message.content === 'string' ? message.content : '';
358
+ if (!content) {
359
+ return;
360
+ }
361
+ session.pendingRawAssistantProgressChunks = [
362
+ ...(session.pendingRawAssistantProgressChunks || []),
363
+ content,
364
+ ];
365
+ }
311
366
  emitProgress(session, currentRunId, content, messageId, toolCall) {
312
367
  if (messageId && this.options.upsertMessage) {
313
368
  this.options.upsertMessage(session.threadId, messageId, 'assistant', content, 'progress', toolCall, toolCall ? 'tool' : undefined);
@@ -327,6 +382,28 @@ class LocalCoreAcpTurnCoordinator {
327
382
  }
328
383
  }
329
384
  exports.LocalCoreAcpTurnCoordinator = LocalCoreAcpTurnCoordinator;
385
+ function isToolScopedAssistantUpdate(update) {
386
+ const meta = update._meta;
387
+ if (!meta || typeof meta !== 'object') {
388
+ return false;
389
+ }
390
+ const claudeCode = meta.claudeCode;
391
+ if (!claudeCode || typeof claudeCode !== 'object') {
392
+ return false;
393
+ }
394
+ const parentToolUseId = claudeCode.parentToolUseId;
395
+ return typeof parentToolUseId === 'string' && parentToolUseId.trim().length > 0;
396
+ }
397
+ function consumeRawAssistantProgressChunk(session, text) {
398
+ const pending = session.pendingRawAssistantProgressChunks || [];
399
+ const index = pending.findIndex((candidate) => candidate === text);
400
+ if (index < 0) {
401
+ return false;
402
+ }
403
+ pending.splice(index, 1);
404
+ session.pendingRawAssistantProgressChunks = pending;
405
+ return true;
406
+ }
330
407
  function createToolCallPayload(input) {
331
408
  const status = input.status.trim() || 'running';
332
409
  return {
@@ -188,7 +188,7 @@ function takePendingLarkThoughtRender(turn) {
188
188
  }
189
189
  function getLarkRenderedMessageId(turn, rendered) {
190
190
  if (rendered.isFinal) {
191
- return turn.finalMessageId || turn.replyMessageId;
191
+ return undefined;
192
192
  }
193
193
  return turn.progressMessageIds[rendered.key];
194
194
  }
@@ -1058,6 +1058,7 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
1058
1058
  previewText: '',
1059
1059
  finalText: '',
1060
1060
  thinkingSteps: [],
1061
+ pendingThoughtText: undefined,
1061
1062
  statusLines: [],
1062
1063
  buttonRows: [],
1063
1064
  lastSentAt: 0,
@@ -1077,6 +1078,7 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
1077
1078
  turn.previewText = '';
1078
1079
  turn.finalText = '';
1079
1080
  turn.thinkingSteps = [];
1081
+ turn.pendingThoughtText = undefined;
1080
1082
  turn.statusLines = [];
1081
1083
  turn.buttonRows = [];
1082
1084
  return;
@@ -1087,12 +1089,15 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
1087
1089
  }
1088
1090
  if (event.type === 'preview_start' || event.type === 'update_message') {
1089
1091
  if (bridgeKind === 'thought') {
1090
- this.pushUnique(turn.thinkingSteps, content);
1092
+ turn.pendingThoughtText = content;
1091
1093
  return;
1092
1094
  }
1093
1095
  turn.previewText = content;
1094
1096
  return;
1095
1097
  }
1098
+ if (bridgeKind !== 'thought') {
1099
+ this.flushPendingThought(turn);
1100
+ }
1096
1101
  if (event.type === 'status') {
1097
1102
  if (content) {
1098
1103
  this.pushUnique(turn.statusLines, content);
@@ -1148,6 +1153,13 @@ class LocalCoreWeixinGateway extends node_events_1.EventEmitter {
1148
1153
  }
1149
1154
  return sections.join('\n\n').trim();
1150
1155
  }
1156
+ flushPendingThought(turn) {
1157
+ const text = String(turn.pendingThoughtText || '').trim();
1158
+ if (!text)
1159
+ return;
1160
+ this.pushUnique(turn.thinkingSteps, text);
1161
+ turn.pendingThoughtText = undefined;
1162
+ }
1151
1163
  isTerminalBridgeMessage(event, rendered) {
1152
1164
  if (event.type === 'buttons')
1153
1165
  return true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kafca/agentdock",
3
- "version": "0.1.29",
3
+ "version": "0.1.30",
4
4
  "type": "module",
5
5
  "main": "dist-electron/electron/main.js",
6
6
  "bin": {
@@ -1 +0,0 @@
1
- import{z as t}from"./index-DvAYflFj.js";const e=()=>t.get("/projects"),r=o=>t.get(`/projects/${o}`);export{r as g,e as l};