maka-agent 0.2.0-dev.26.20260909 → 0.2.0-dev.28.20260911

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 (125) hide show
  1. package/LICENSE +106 -0
  2. package/dist/cli-core.js +28 -0
  3. package/dist/runtime-host-cli.js +43 -3
  4. package/dist/runtime-host-handoff-surface.js +10 -8
  5. package/dist/runtime-host-lifecycle-transaction.js +28 -3
  6. package/dist/runtime-host-local-source-retirement.js +1 -1
  7. package/dist/runtime-host-run-command.js +15 -7
  8. package/dist/runtime-host-setup-command.js +29 -6
  9. package/dist/runtime-host-update-command.js +49 -5
  10. package/dist/session-export-command.js +72 -0
  11. package/dist/session-import-command.js +69 -0
  12. package/native/runtime-host-peer/prebuilds/darwin-arm64/maka_runtime_host_peer.node +0 -0
  13. package/native/runtime-host-peer/prebuilds/linux-arm64/maka_runtime_host_peer.node +0 -0
  14. package/native/runtime-host-peer/prebuilds/linux-x64/maka_runtime_host_peer.node +0 -0
  15. package/native/runtime-host-peer/prebuilds/win32-x64/maka_runtime_host_peer.node +0 -0
  16. package/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
  17. package/node_modules/@earendil-works/pi-tui/dist/components/editor.js +9 -4
  18. package/node_modules/@maka/core/dist/diagnostic-log.js +18 -7
  19. package/node_modules/@maka/core/dist/text-sanitize.js +8 -2
  20. package/node_modules/@maka/core/dist/usage-stats/types.js +2 -0
  21. package/node_modules/@maka/core/dist/workhub-routing.js +126 -0
  22. package/node_modules/@maka/core/package.json +2 -1
  23. package/node_modules/@maka/runtime/dist/ai-sdk-turn.js +15 -11
  24. package/node_modules/@maka/runtime/dist/archive-read-tool.js +3 -1
  25. package/node_modules/@maka/runtime/dist/bots/bot-test.js +2 -1
  26. package/node_modules/@maka/runtime/dist/bots/feishu-bridge.js +24 -20
  27. package/node_modules/@maka/runtime/dist/bots/slack-bridge.js +5 -3
  28. package/node_modules/@maka/runtime/dist/bots/wechat-bridge.js +87 -29
  29. package/node_modules/@maka/runtime/dist/bots/wecom-bridge.js +40 -36
  30. package/node_modules/@maka/runtime/dist/builtin-tools.js +21 -2
  31. package/node_modules/@maka/runtime/dist/computer-use-tools.js +4 -1
  32. package/node_modules/@maka/runtime/dist/deep-research-tools.js +11 -5
  33. package/node_modules/@maka/runtime/dist/edit-replace.js +2 -2
  34. package/node_modules/@maka/runtime/dist/filesystem-worker/operations.js +5 -6
  35. package/node_modules/@maka/runtime/dist/memory-extraction-evidence.js +7 -1
  36. package/node_modules/@maka/runtime/dist/memory-extraction.js +12 -7
  37. package/node_modules/@maka/runtime/dist/openai-responses-websocket.js +2 -5
  38. package/node_modules/@maka/runtime/dist/plugin-agent-service.js +131 -0
  39. package/node_modules/@maka/runtime/dist/plugin-approval-service.js +33 -0
  40. package/node_modules/@maka/runtime/dist/plugin-attachment-service.js +53 -0
  41. package/node_modules/@maka/runtime/dist/plugin-command-service.js +100 -0
  42. package/node_modules/@maka/runtime/dist/plugin-composition-loader.js +11 -2
  43. package/node_modules/@maka/runtime/dist/plugin-data-services.js +332 -0
  44. package/node_modules/@maka/runtime/dist/plugin-fs-service.js +62 -0
  45. package/node_modules/@maka/runtime/dist/plugin-goal-service.js +61 -0
  46. package/node_modules/@maka/runtime/dist/plugin-invocation-signal.js +24 -0
  47. package/node_modules/@maka/runtime/dist/plugin-llm-service.js +85 -0
  48. package/node_modules/@maka/runtime/dist/plugin-lsp-service.js +94 -0
  49. package/node_modules/@maka/runtime/dist/plugin-scope-registry.js +91 -0
  50. package/node_modules/@maka/runtime/dist/plugin-session-query-service.js +71 -0
  51. package/node_modules/@maka/runtime/dist/plugin-shell-env-service.js +87 -0
  52. package/node_modules/@maka/runtime/dist/plugin-shell-service.js +74 -0
  53. package/node_modules/@maka/runtime/dist/plugin-skill-service.js +93 -0
  54. package/node_modules/@maka/runtime/dist/plugin-system-prompt-service.js +346 -0
  55. package/node_modules/@maka/runtime/dist/plugin-tool-service.js +18 -52
  56. package/node_modules/@maka/runtime/dist/plugin-user-question-service.js +43 -0
  57. package/node_modules/@maka/runtime/dist/plugin-web-service.js +69 -0
  58. package/node_modules/@maka/runtime/dist/request-customization-fetch.js +14 -7
  59. package/node_modules/@maka/runtime/dist/session-export.js +178 -0
  60. package/node_modules/@maka/runtime/dist/session-import.js +100 -0
  61. package/node_modules/@maka/runtime/dist/session-manager.js +6 -1
  62. package/node_modules/@maka/runtime/dist/shell-run-manager.js +9 -6
  63. package/node_modules/@maka/runtime/dist/shell-run-tool-result.js +13 -6
  64. package/node_modules/@maka/runtime/dist/stream-graph-coordinator.js +43 -10
  65. package/node_modules/@maka/runtime/dist/stream-graph-handoff.js +6 -1
  66. package/node_modules/@maka/runtime/dist/subscription-model-fetch.js +1 -4
  67. package/node_modules/@maka/runtime/dist/system-prompt/workspace-instructions.js +11 -6
  68. package/node_modules/@maka/runtime/dist/tavily-search.js +8 -2
  69. package/node_modules/@maka/runtime/dist/text-line-window.js +49 -0
  70. package/node_modules/@maka/runtime/dist/tool-output.js +35 -12
  71. package/node_modules/@maka/runtime/dist/unified-diff.js +40 -10
  72. package/node_modules/@maka/runtime/dist/web-fetch-tool.js +4 -2
  73. package/node_modules/@maka/runtime/dist/workers/filesystem-worker.js +82 -33
  74. package/node_modules/@maka/runtime/dist/workspace-executor.js +2 -6
  75. package/node_modules/@maka/runtime/package.json +20 -1
  76. package/node_modules/@maka/runtime-host/dist/client/host-handoff-copy.js +73 -24
  77. package/node_modules/@maka/runtime-host/dist/client/host-handoff.js +46 -12
  78. package/node_modules/@maka/runtime-host/dist/operator/setup-frame.js +31 -21
  79. package/node_modules/@maka/runtime-host/dist/peer-mesh/node.js +7 -4
  80. package/node_modules/@maka/runtime-host/dist/protocol/artifact.js +2 -2
  81. package/node_modules/@maka/runtime-host/dist/protocol/index.js +10 -1
  82. package/node_modules/@maka/runtime-host/dist/protocol/plugin-platform.js +30 -5
  83. package/node_modules/@maka/runtime-host/dist/protocol/session-transcript.js +3 -2
  84. package/node_modules/@maka/runtime-host/dist/protocol/skill-catalog.js +2 -1
  85. package/node_modules/@maka/runtime-host/dist/protocol/workhub-coordination.js +25 -23
  86. package/node_modules/@maka/runtime-host/dist/server/artifact-coordinator.js +2 -0
  87. package/node_modules/@maka/runtime-host/dist/server/client-capability-coordinator.js +62 -4
  88. package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +481 -11
  89. package/node_modules/@maka/runtime-host/dist/server/execution-model-authority.js +74 -0
  90. package/node_modules/@maka/runtime-host/dist/server/goal-coordinator.js +6 -1
  91. package/node_modules/@maka/runtime-host/dist/server/hosted-execution-recovery.js +2 -2
  92. package/node_modules/@maka/runtime-host/dist/server/hosted-execution-tool-profile.js +30 -0
  93. package/node_modules/@maka/runtime-host/dist/server/interactive-run-composer.js +114 -20
  94. package/node_modules/@maka/runtime-host/dist/server/message-coordinator.js +49 -12
  95. package/node_modules/@maka/runtime-host/dist/server/plugin-data-runtime.js +234 -0
  96. package/node_modules/@maka/runtime-host/dist/server/plugin-platform-coordinator.js +6 -0
  97. package/node_modules/@maka/runtime-host/dist/server/plugin-platform.js +12 -0
  98. package/node_modules/@maka/runtime-host/dist/server/root-admission-owner.js +17 -8
  99. package/node_modules/@maka/runtime-host/dist/server/root-turn-coordinator.js +189 -92
  100. package/node_modules/@maka/runtime-host/dist/server/runtime-resource-projection.js +3 -9
  101. package/node_modules/@maka/runtime-host/dist/server/session-continuity-coordinator.js +20 -21
  102. package/node_modules/@maka/runtime-host/dist/server/session-transcript-pager.js +24 -2
  103. package/node_modules/@maka/runtime-host/dist/server/skill-catalog-coordinator.js +18 -2
  104. package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-action-gate.js +44 -35
  105. package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-coordinator.js +92 -10
  106. package/node_modules/@maka/runtime-host/dist/transport/framed-byte-stream-transport.js +4 -1
  107. package/node_modules/@maka/runtime-host/dist/transport/local-ipc-framing.js +4 -2
  108. package/node_modules/@maka/runtime-host/dist/transport/peer-native.js +9 -8
  109. package/node_modules/@maka/runtime-host/dist/transport/resumable-peer-stream.js +14 -9
  110. package/node_modules/@maka/storage/dist/agent-run-store.js +54 -10
  111. package/node_modules/@maka/storage/dist/context-offload-snapshot.js +32 -10
  112. package/node_modules/@maka/storage/dist/context-value-mutation-gate.js +59 -0
  113. package/node_modules/@maka/storage/dist/execution-stores.js +1 -1
  114. package/node_modules/@maka/storage/dist/session-bundle-policy.js +909 -34
  115. package/node_modules/@maka/storage/dist/session-message-projection.js +8 -4
  116. package/node_modules/@maka/storage/dist/session-store.js +2 -2
  117. package/node_modules/@maka/storage/dist/sqlite-context-offload-store.js +18 -4
  118. package/node_modules/@maka/storage/dist/sqlite-session-metadata-store.js +12 -5
  119. package/node_modules/@maka/storage/dist/stable-storage.js +2 -1
  120. package/node_modules/@maka/storage/package.json +2 -0
  121. package/node_modules/@modelcontextprotocol/client/dist/src-D_zzAWoS.mjs +22 -5
  122. package/node_modules/@modelcontextprotocol/client/dist/src-NAgB4Mp8.cjs +22 -5
  123. package/node_modules/zod/v4/core/memoizer.cjs +12 -16
  124. package/node_modules/zod/v4/core/memoizer.js +12 -16
  125. package/package.json +1 -1
@@ -47,9 +47,17 @@ function utf8Len(text) {
47
47
  * multi-byte sequence at the boundary with U+FFFD, which we strip.
48
48
  */
49
49
  function sliceLineByBytes(line, maxBytes, keep) {
50
- const buf = Buffer.from(line, 'utf8');
51
- if (buf.length <= maxBytes)
50
+ if (utf8Len(line) <= maxBytes)
52
51
  return line;
52
+ // One UTF-16 unit needs at least one UTF-8 byte. The extra unit keeps a
53
+ // surrogate pair crossing the window boundary outside the retained bytes.
54
+ // Preserve Buffer.subarray's original behavior for unusual numeric budgets.
55
+ const window = Number.isInteger(maxBytes) && maxBytes >= 0
56
+ ? keep === 'head'
57
+ ? line.slice(0, maxBytes + 1)
58
+ : line.slice(-(maxBytes + 1))
59
+ : line;
60
+ const buf = Buffer.from(window, 'utf8');
53
61
  const slice = keep === 'head' ? buf.subarray(0, maxBytes) : buf.subarray(buf.length - maxBytes);
54
62
  const decoded = slice.toString('utf8');
55
63
  return keep === 'head' ? decoded.replace(/�+$/, '') : decoded.replace(/^�+/, '');
@@ -68,33 +76,45 @@ export function truncateToolOutput(text, options = {}) {
68
76
  // A single trailing newline terminates the last line; it is not an extra
69
77
  // empty line, so it must not count against the line budget.
70
78
  const body = text.endsWith('\n') ? text.slice(0, -1) : text;
71
- const lines = body.split('\n');
72
- if (lines.length <= maxLines && totalBytes <= maxBytes) {
79
+ let lineCount = 1;
80
+ for (let index = body.indexOf('\n'); index !== -1; index = body.indexOf('\n', index + 1)) {
81
+ lineCount++;
82
+ }
83
+ if (lineCount <= maxLines && totalBytes <= maxBytes) {
73
84
  return { content: text, truncated: false, removed: 0, unit: 'lines' };
74
85
  }
75
86
  const out = [];
76
87
  let bytes = 0;
77
88
  let hitBytes = false;
78
89
  if (direction === 'head') {
79
- for (let i = 0; i < lines.length && i < maxLines; i++) {
80
- const size = utf8Len(lines[i]) + (i > 0 ? 1 : 0);
90
+ let start = 0;
91
+ for (let i = 0; i < lineCount && i < maxLines; i++) {
92
+ const newline = body.indexOf('\n', start);
93
+ const end = newline === -1 ? body.length : newline;
94
+ const line = body.slice(start, end);
95
+ const size = utf8Len(line) + (i > 0 ? 1 : 0);
81
96
  if (bytes + size > maxBytes) {
82
97
  hitBytes = true;
83
98
  break;
84
99
  }
85
- out.push(lines[i]);
100
+ out.push(line);
86
101
  bytes += size;
102
+ start = end + 1;
87
103
  }
88
104
  }
89
105
  else {
90
- for (let i = lines.length - 1; i >= 0 && out.length < maxLines; i--) {
91
- const size = utf8Len(lines[i]) + (out.length > 0 ? 1 : 0);
106
+ let end = body.length;
107
+ for (let i = lineCount - 1; i >= 0 && out.length < maxLines; i--) {
108
+ const start = end > 0 ? body.lastIndexOf('\n', end - 1) + 1 : 0;
109
+ const line = body.slice(start, end);
110
+ const size = utf8Len(line) + (out.length > 0 ? 1 : 0);
92
111
  if (bytes + size > maxBytes) {
93
112
  hitBytes = true;
94
113
  break;
95
114
  }
96
- out.unshift(lines[i]);
115
+ out.unshift(line);
97
116
  bytes += size;
117
+ end = start - 1;
98
118
  }
99
119
  }
100
120
  // The boundary line alone exceeds the byte budget. Rather than show only a
@@ -102,7 +122,10 @@ export function truncateToolOutput(text, options = {}) {
102
122
  // JSON/stack trace), keep a byte-safe slice of that line.
103
123
  let preview;
104
124
  if (out.length === 0) {
105
- const line = direction === 'head' ? lines[0] : lines[lines.length - 1];
125
+ const firstNewline = body.indexOf('\n');
126
+ const line = direction === 'head'
127
+ ? body.slice(0, firstNewline === -1 ? body.length : firstNewline)
128
+ : body.slice(body.lastIndexOf('\n') + 1);
106
129
  preview = sliceLineByBytes(line, maxBytes, direction);
107
130
  bytes = utf8Len(preview);
108
131
  hitBytes = true;
@@ -110,7 +133,7 @@ export function truncateToolOutput(text, options = {}) {
110
133
  else {
111
134
  preview = out.join('\n');
112
135
  }
113
- const removed = hitBytes ? Math.max(0, totalBytes - bytes) : lines.length - out.length;
136
+ const removed = hitBytes ? Math.max(0, totalBytes - bytes) : lineCount - out.length;
114
137
  if (removed <= 0) {
115
138
  // Nothing was actually dropped — e.g. content fits but a lone trailing
116
139
  // newline pushed totalBytes one over the byte budget. Don't emit a
@@ -58,19 +58,21 @@ export function createUnifiedDiff(path, oldContent, newContent) {
58
58
  export function createEditUnifiedDiff(path, oldContent, newContent, match) {
59
59
  if (oldContent.includes('\0') || newContent.includes('\0'))
60
60
  return undefined;
61
- const oldLines = splitLines(oldContent);
62
- const newLines = splitLines(newContent);
61
+ const oldLineCount = countLines(oldContent);
62
+ const newLineCount = countLines(newContent);
63
63
  const startIndex = match.startLine - 1;
64
64
  const oldEndIndex = match.endLine - 1;
65
- if (startIndex < 0 || oldEndIndex < startIndex || oldEndIndex >= oldLines.length) {
65
+ if (startIndex < 0 || oldEndIndex < startIndex || oldEndIndex >= oldLineCount) {
66
66
  return undefined;
67
67
  }
68
68
  const windowStart = Math.max(0, startIndex - CONTEXT_LINES);
69
69
  const oldAfterStart = oldEndIndex + 1;
70
- const newAfterStart = oldAfterStart + newLines.length - oldLines.length;
71
- const oldWindow = oldLines.slice(windowStart, Math.min(oldLines.length, oldAfterStart + CONTEXT_LINES));
72
- const newWindow = newLines.slice(windowStart, Math.min(newLines.length, Math.max(windowStart, newAfterStart) + CONTEXT_LINES));
73
- if (isDiffWindowTooLarge(oldWindow) || isDiffWindowTooLarge(newWindow))
70
+ const newAfterStart = oldAfterStart + newLineCount - oldLineCount;
71
+ const oldWindow = readDiffWindow(oldContent, windowStart, Math.min(oldLineCount, oldAfterStart + CONTEXT_LINES));
72
+ if (!oldWindow)
73
+ return undefined;
74
+ const newWindow = readDiffWindow(newContent, windowStart, Math.min(newLineCount, Math.max(windowStart, newAfterStart) + CONTEXT_LINES));
75
+ if (!newWindow)
74
76
  return undefined;
75
77
  const ops = diffLines(oldWindow, newWindow);
76
78
  if (ops.every((op) => op.kind === 'keep'))
@@ -85,9 +87,6 @@ export function createEditUnifiedDiff(path, oldContent, newContent, match) {
85
87
  function isUndiffable(content) {
86
88
  return content.includes('\0') || Buffer.byteLength(content, 'utf8') > MAX_DIFF_SOURCE_BYTES;
87
89
  }
88
- function isDiffWindowTooLarge(lines) {
89
- return lines.length > MAX_DIFF_SOURCE_LINES || isUndiffable(lines.join('\n'));
90
- }
91
90
  function splitLines(content) {
92
91
  const lines = content.split('\n');
93
92
  // A trailing newline terminates the last line rather than starting an empty
@@ -96,6 +95,37 @@ function splitLines(content) {
96
95
  lines.pop();
97
96
  return lines;
98
97
  }
98
+ function countLines(content) {
99
+ let count = content.length > 0 && !content.endsWith('\n') ? 1 : 0;
100
+ for (let index = content.indexOf('\n'); index !== -1; index = content.indexOf('\n', index + 1)) {
101
+ count += 1;
102
+ }
103
+ return count;
104
+ }
105
+ /** Collect only the requested lines, failing before an oversized window is materialized. */
106
+ function readDiffWindow(content, startLine, endLine) {
107
+ // Preserve Array.slice's fractional/NaN index normalization.
108
+ const from = Math.trunc(startLine) || 0;
109
+ const until = Math.trunc(endLine) || 0;
110
+ const lines = [];
111
+ let bytes = 0;
112
+ let offset = 0;
113
+ for (let lineIndex = 0; offset < content.length && lineIndex < until; lineIndex += 1) {
114
+ const newline = content.indexOf('\n', offset);
115
+ const end = newline === -1 ? content.length : newline;
116
+ if (lineIndex >= from) {
117
+ if (lines.length === MAX_DIFF_SOURCE_LINES)
118
+ return undefined;
119
+ const line = content.slice(offset, end);
120
+ bytes += Buffer.byteLength(line, 'utf8') + (lines.length > 0 ? 1 : 0);
121
+ if (bytes > MAX_DIFF_SOURCE_BYTES)
122
+ return undefined;
123
+ lines.push(line);
124
+ }
125
+ offset = end + 1;
126
+ }
127
+ return lines;
128
+ }
99
129
  /** Line-level edit script via LCS dynamic programming, bounded by the caps above. */
100
130
  function diffLines(oldLines, newLines) {
101
131
  const n = oldLines.length;
@@ -56,8 +56,10 @@ function truncateWebFetchOutput(content) {
56
56
  if (Buffer.byteLength(content, 'utf8') <= WEB_FETCH_MODEL_OUTPUT_MAX_BYTES)
57
57
  return content;
58
58
  const markerBytes = Buffer.byteLength(WEB_FETCH_TRUNCATION_MARKER, 'utf8');
59
- const kept = Buffer.from(content, 'utf8')
60
- .subarray(0, WEB_FETCH_MODEL_OUTPUT_MAX_BYTES - markerBytes)
59
+ const contentBytes = WEB_FETCH_MODEL_OUTPUT_MAX_BYTES - markerBytes;
60
+ // The extra UTF-16 unit keeps a split surrogate outside the retained bytes.
61
+ const kept = Buffer.from(content.slice(0, contentBytes + 1), 'utf8')
62
+ .subarray(0, contentBytes)
61
63
  .toString('utf8')
62
64
  .replace(/�+$/, '');
63
65
  return kept + WEB_FETCH_TRUNCATION_MARKER;
@@ -830,8 +830,8 @@ function computeEditedSource(source, oldString, newString, where) {
830
830
  function finish(content, span, replacement, matchedVia) {
831
831
  const index = content.indexOf(span);
832
832
  const before = content.slice(0, index);
833
- const startLine = before.split("\n").length;
834
- const spanLineCount = span.split("\n").length - (span.endsWith("\n") ? 1 : 0);
833
+ const startLine = countOccurrences(before, "\n") + 1;
834
+ const spanLineCount = countOccurrences(span, "\n") + 1 - (span.endsWith("\n") ? 1 : 0);
835
835
  const endLine = startLine + Math.max(spanLineCount, 1) - 1;
836
836
  const next = before + replacement + content.slice(index + span.length);
837
837
  return { content: next, matchedVia, startLine, endLine };
@@ -941,6 +941,33 @@ function computeEditedSource(source, oldString, newString, where) {
941
941
  }
942
942
  }
943
943
 
944
+ // src/text-line-window.ts
945
+ function readTextLineWindow(content, offset, limit) {
946
+ if (offset === void 0 && limit === void 0) return content;
947
+ let lineCount = 1;
948
+ for (let cursor2 = content.indexOf("\n"); cursor2 !== -1; cursor2 = content.indexOf("\n", cursor2 + 1)) {
949
+ lineCount++;
950
+ }
951
+ const start = offset ?? 0;
952
+ const end = limit ? start + limit : lineCount;
953
+ const from = sliceIndex(start, lineCount);
954
+ const to = sliceIndex(end, lineCount);
955
+ if (from >= to) return "";
956
+ const selected = [];
957
+ let cursor = 0;
958
+ for (let line = 0; line < to; line++) {
959
+ const newline = content.indexOf("\n", cursor);
960
+ const lineEnd = newline === -1 ? content.length : newline;
961
+ if (line >= from) selected.push(content.slice(cursor, lineEnd));
962
+ cursor = lineEnd + 1;
963
+ }
964
+ return selected.join("\n");
965
+ }
966
+ function sliceIndex(value, length) {
967
+ const integer2 = Math.trunc(value) || 0;
968
+ return integer2 < 0 ? Math.max(length + integer2, 0) : Math.min(integer2, length);
969
+ }
970
+
944
971
  // src/unified-diff.ts
945
972
  var MAX_DIFF_SOURCE_LINES = 800;
946
973
  var MAX_DIFF_SOURCE_BYTES = 32 * 1024;
@@ -960,25 +987,28 @@ function createUnifiedDiff(path2, oldContent, newContent) {
960
987
  }
961
988
  function createEditUnifiedDiff(path2, oldContent, newContent, match) {
962
989
  if (oldContent.includes("\0") || newContent.includes("\0")) return void 0;
963
- const oldLines = splitLines(oldContent);
964
- const newLines = splitLines(newContent);
990
+ const oldLineCount = countLines(oldContent);
991
+ const newLineCount = countLines(newContent);
965
992
  const startIndex = match.startLine - 1;
966
993
  const oldEndIndex = match.endLine - 1;
967
- if (startIndex < 0 || oldEndIndex < startIndex || oldEndIndex >= oldLines.length) {
994
+ if (startIndex < 0 || oldEndIndex < startIndex || oldEndIndex >= oldLineCount) {
968
995
  return void 0;
969
996
  }
970
997
  const windowStart = Math.max(0, startIndex - CONTEXT_LINES);
971
998
  const oldAfterStart = oldEndIndex + 1;
972
- const newAfterStart = oldAfterStart + newLines.length - oldLines.length;
973
- const oldWindow = oldLines.slice(
999
+ const newAfterStart = oldAfterStart + newLineCount - oldLineCount;
1000
+ const oldWindow = readDiffWindow(
1001
+ oldContent,
974
1002
  windowStart,
975
- Math.min(oldLines.length, oldAfterStart + CONTEXT_LINES)
1003
+ Math.min(oldLineCount, oldAfterStart + CONTEXT_LINES)
976
1004
  );
977
- const newWindow = newLines.slice(
1005
+ if (!oldWindow) return void 0;
1006
+ const newWindow = readDiffWindow(
1007
+ newContent,
978
1008
  windowStart,
979
- Math.min(newLines.length, Math.max(windowStart, newAfterStart) + CONTEXT_LINES)
1009
+ Math.min(newLineCount, Math.max(windowStart, newAfterStart) + CONTEXT_LINES)
980
1010
  );
981
- if (isDiffWindowTooLarge(oldWindow) || isDiffWindowTooLarge(newWindow)) return void 0;
1011
+ if (!newWindow) return void 0;
982
1012
  const ops = diffLines(oldWindow, newWindow);
983
1013
  if (ops.every((op) => op.kind === "keep")) return void 0;
984
1014
  const diff = [
@@ -991,14 +1021,38 @@ function createEditUnifiedDiff(path2, oldContent, newContent, match) {
991
1021
  function isUndiffable(content) {
992
1022
  return content.includes("\0") || Buffer.byteLength(content, "utf8") > MAX_DIFF_SOURCE_BYTES;
993
1023
  }
994
- function isDiffWindowTooLarge(lines) {
995
- return lines.length > MAX_DIFF_SOURCE_LINES || isUndiffable(lines.join("\n"));
996
- }
997
1024
  function splitLines(content) {
998
1025
  const lines = content.split("\n");
999
1026
  if (lines.at(-1) === "") lines.pop();
1000
1027
  return lines;
1001
1028
  }
1029
+ function countLines(content) {
1030
+ let count = content.length > 0 && !content.endsWith("\n") ? 1 : 0;
1031
+ for (let index = content.indexOf("\n"); index !== -1; index = content.indexOf("\n", index + 1)) {
1032
+ count += 1;
1033
+ }
1034
+ return count;
1035
+ }
1036
+ function readDiffWindow(content, startLine, endLine) {
1037
+ const from = Math.trunc(startLine) || 0;
1038
+ const until = Math.trunc(endLine) || 0;
1039
+ const lines = [];
1040
+ let bytes = 0;
1041
+ let offset = 0;
1042
+ for (let lineIndex = 0; offset < content.length && lineIndex < until; lineIndex += 1) {
1043
+ const newline = content.indexOf("\n", offset);
1044
+ const end = newline === -1 ? content.length : newline;
1045
+ if (lineIndex >= from) {
1046
+ if (lines.length === MAX_DIFF_SOURCE_LINES) return void 0;
1047
+ const line = content.slice(offset, end);
1048
+ bytes += Buffer.byteLength(line, "utf8") + (lines.length > 0 ? 1 : 0);
1049
+ if (bytes > MAX_DIFF_SOURCE_BYTES) return void 0;
1050
+ lines.push(line);
1051
+ }
1052
+ offset = end + 1;
1053
+ }
1054
+ return lines;
1055
+ }
1002
1056
  function diffLines(oldLines, newLines) {
1003
1057
  const n = oldLines.length;
1004
1058
  const m = newLines.length;
@@ -6747,8 +6801,6 @@ var memo = {
6747
6801
  attach(inst) {
6748
6802
  var _a3;
6749
6803
  let isRecursiveInst;
6750
- let lastCtx;
6751
- let lastBucket;
6752
6804
  (_a3 = inst._zod).deferred ?? (_a3.deferred = []);
6753
6805
  inst._zod.deferred.push(() => {
6754
6806
  const base = inst._zod.parse;
@@ -6770,14 +6822,7 @@ var memo = {
6770
6822
  state = { buckets: /* @__PURE__ */ new Map(), backEdges: void 0 };
6771
6823
  ctx[STATE] = state;
6772
6824
  }
6773
- let bucket;
6774
- if (lastCtx === ctx) {
6775
- bucket = lastBucket;
6776
- } else {
6777
- bucket = bucketFor(state, inst);
6778
- lastCtx = ctx;
6779
- lastBucket = bucket;
6780
- }
6825
+ const bucket = bucketFor(state, inst);
6781
6826
  const hit = bucket.get(input2);
6782
6827
  if (hit) {
6783
6828
  payload.value = hit.value;
@@ -6791,11 +6836,17 @@ var memo = {
6791
6836
  }
6792
6837
  return payload;
6793
6838
  }
6839
+ const previousHandoff = handoff;
6794
6840
  handoff = bucket;
6795
6841
  const depth = open2.length;
6796
- const result = base(payload, ctx);
6797
- handoff = void 0;
6798
- const entry = open2.length > depth ? open2.pop() : void 0;
6842
+ let result;
6843
+ let entry;
6844
+ try {
6845
+ result = base(payload, ctx);
6846
+ } finally {
6847
+ handoff = previousHandoff;
6848
+ entry = open2.length > depth ? open2.pop() : void 0;
6849
+ }
6799
6850
  if (result instanceof Promise) {
6800
6851
  return result.then((r) => {
6801
6852
  if (entry)
@@ -20815,12 +20866,10 @@ async function executeFilesystemOperation(operation, operationBoundary, dependen
20815
20866
  }
20816
20867
  }
20817
20868
  const content = await fs3.readFile(path2, "utf8");
20818
- if (operation.offset === void 0 && operation.limit === void 0)
20819
- return { kind: "read", content };
20820
- const lines = content.split("\n");
20821
- const start = operation.offset ?? 0;
20822
- const end = operation.limit ? start + operation.limit : lines.length;
20823
- return { kind: "read", content: lines.slice(start, end).join("\n") };
20869
+ return {
20870
+ kind: "read",
20871
+ content: readTextLineWindow(content, operation.offset, operation.limit)
20872
+ };
20824
20873
  }
20825
20874
  case "write": {
20826
20875
  const path2 = await resolveWritableAllowed(
@@ -26,6 +26,7 @@ import { compareAndDeleteEntry, hostVisibilityAfterWrite, openStableTarget, writ
26
26
  import { promisify } from 'node:util';
27
27
  import { runProcessWithBoundedTail, runShellWithBoundedTail } from './shell-exec.js';
28
28
  import { isSupportedImagePath, readWorkspaceImage } from './image-file.js';
29
+ import { readTextLineWindow } from './text-line-window.js';
29
30
  const execAsync = promisify(exec);
30
31
  const execFileAsync = promisify(execFile);
31
32
  export const LOCAL_WORKSPACE_EXECUTOR_FACTS = {
@@ -65,12 +66,7 @@ export class LocalWorkspaceExecutor {
65
66
  return await readWorkspaceImage(input.path);
66
67
  }
67
68
  const content = await fs.readFile(input.path, 'utf8');
68
- if (input.offset === undefined && input.limit === undefined)
69
- return { content };
70
- const lines = content.split('\n');
71
- const start = input.offset ?? 0;
72
- const end = input.limit ? start + input.limit : lines.length;
73
- return { content: lines.slice(start, end).join('\n') };
69
+ return { content: readTextLineWindow(content, input.offset, input.limit) };
74
70
  }
75
71
  async writeFile(input) {
76
72
  await fs.writeFile(input.path, input.content, 'utf8');
@@ -76,8 +76,25 @@
76
76
  "./plan-mode": "./dist/plan-mode.js",
77
77
  "./plan-tools": "./dist/plan-tools.js",
78
78
  "./plugin-composition-loader": "./dist/plugin-composition-loader.js",
79
+ "./plugin-command-service": "./dist/plugin-command-service.js",
80
+ "./plugin-data-services": "./dist/plugin-data-services.js",
81
+ "./plugin-goal-service": "./dist/plugin-goal-service.js",
82
+ "./plugin-lsp-service": "./dist/plugin-lsp-service.js",
83
+ "./plugin-session-query-service": "./dist/plugin-session-query-service.js",
84
+ "./plugin-shell-env-service": "./dist/plugin-shell-env-service.js",
85
+ "./plugin-skill-service": "./dist/plugin-skill-service.js",
86
+ "./plugin-agent-service": "./dist/plugin-agent-service.js",
87
+ "./plugin-attachment-service": "./dist/plugin-attachment-service.js",
88
+ "./plugin-approval-service": "./dist/plugin-approval-service.js",
89
+ "./plugin-fs-service": "./dist/plugin-fs-service.js",
79
90
  "./plugin-kernel": "./dist/plugin-kernel.js",
91
+ "./plugin-llm-service": "./dist/plugin-llm-service.js",
80
92
  "./plugin-runtime": "./dist/plugin-runtime.js",
93
+ "./plugin-scope-registry": "./dist/plugin-scope-registry.js",
94
+ "./plugin-system-prompt-service": "./dist/plugin-system-prompt-service.js",
95
+ "./plugin-shell-service": "./dist/plugin-shell-service.js",
96
+ "./plugin-user-question-service": "./dist/plugin-user-question-service.js",
97
+ "./plugin-web-service": "./dist/plugin-web-service.js",
81
98
  "./plugin-tool-service": "./dist/plugin-tool-service.js",
82
99
  "./process-tree-terminator": "./dist/process-tree-terminator.js",
83
100
  "./provider-request-telemetry": "./dist/provider-request-telemetry.js",
@@ -88,6 +105,7 @@
88
105
  "./sandbox-boundary-tool": "./dist/sandbox-boundary-tool.js",
89
106
  "./scheduled-task-tools": "./dist/scheduled-task-tools.js",
90
107
  "./session-recap": "./dist/session-recap.js",
108
+ "./session-export": "./dist/session-export.js",
91
109
  "./session-trace-projection": "./dist/session-trace-projection.js",
92
110
  "./shell-detect": "./dist/shell-detect.js",
93
111
  "./shell-run-contract": "./dist/shell-run-contract.js",
@@ -113,7 +131,8 @@
113
131
  "./tool-runtime": "./dist/tool-runtime.js",
114
132
  "./web-fetch-tool": "./dist/web-fetch-tool.js",
115
133
  "./web-search-tool": "./dist/web-search-tool.js",
116
- "./xai-oauth-enrollment": "./dist/xai-oauth-enrollment.js"
134
+ "./xai-oauth-enrollment": "./dist/xai-oauth-enrollment.js",
135
+ "./session-import": "./dist/session-import.js"
117
136
  },
118
137
  "dependencies": {
119
138
  "@ai-sdk/anthropic": "4.0.46",
@@ -22,6 +22,7 @@ export function formatHostHandoff(view, locale) {
22
22
  const tw = locale === 'zh-TW';
23
23
  const titles = tw
24
24
  ? {
25
+ replacement_required: '需要切換 WSL 背景服務',
25
26
  busy: '背景服務仍在使用中',
26
27
  activity_unknown: '需要確認是否停止背景服務',
27
28
  operator_required: '背景服務需要手動更新',
@@ -30,6 +31,7 @@ export function formatHostHandoff(view, locale) {
30
31
  }
31
32
  : zh
32
33
  ? {
34
+ replacement_required: '需要切换 WSL 后台服务',
33
35
  busy: '后台服务仍在使用中',
34
36
  activity_unknown: '需要确认是否停止后台服务',
35
37
  operator_required: '后台服务需要手动更新',
@@ -37,6 +39,7 @@ export function formatHostHandoff(view, locale) {
37
39
  retry_required: '暂时无法完成交接',
38
40
  }
39
41
  : {
42
+ replacement_required: 'Switch the WSL background service',
40
43
  busy: 'Your background service is still in use',
41
44
  activity_unknown: 'Confirm before stopping the service',
42
45
  operator_required: 'The background service needs a manual update',
@@ -45,50 +48,75 @@ export function formatHostHandoff(view, locale) {
45
48
  };
46
49
  const descriptions = tw
47
50
  ? {
51
+ replacement_required: '目前尚未更新。選擇繼續後,將透過已安裝的管理程式安全停止舊服務並啟動選定版本;有進行中的工作時會另行確認。',
48
52
  busy: '其他連線或正在執行的工作阻止了自動交接。停止並繼續可能中斷這些工作。',
49
53
  activity_unknown: '背景服務與目前用戶端不相容,且無法確認有哪些工作仍在執行。停止並繼續會重新啟動服務,可能中斷其他視窗或裝置上的工作。',
50
54
  operator_required: `目前無法從這裡更新背景服務。請透過 ${view.target.name} 上管理此服務的應用程式或命令更新,再重試。`,
51
- repair_required: '上次啟動或交接未能完成。可以安全重試;若仍失敗,請複製診斷資訊。',
55
+ repair_required: '上次啟動或交接失敗。請查看下方診斷資訊,修復原因後再重試;如果狀態沒有改變,重複重試通常不會解決問題。',
52
56
  retry_required: '服務狀態發生了變化,或交接尚未完成。可以安全重試,不會預設中斷工作。',
53
57
  }
54
58
  : zh
55
59
  ? {
60
+ replacement_required: '当前尚未更新。选择继续后,将通过已安装的管理程序安全停止旧服务并启动选定版本;有活动工作时会另行确认。',
56
61
  busy: '其它连接或正在执行的工作阻止了自动交接。停止并继续可能中断这些工作。',
57
62
  activity_unknown: '后台服务与当前客户端不兼容,且无法确认有哪些工作仍在运行。停止并继续会重新启动服务,可能中断其他窗口或设备上的工作。',
58
63
  operator_required: `目前无法从这里更新后台服务。请通过 ${view.target.name} 上管理此服务的应用或命令更新,然后重试。`,
59
- repair_required: '上次启动或交接未能完成。可以安全重试;若仍失败,请复制诊断信息。',
64
+ repair_required: '上次启动或交接失败。请查看下方诊断信息,修复原因后再重试;如果状态没有变化,重复重试通常不会解决问题。',
60
65
  retry_required: '服务状态发生了变化,或交接尚未完成。可以安全重试,不会默认中断工作。',
61
66
  }
62
67
  : {
68
+ replacement_required: 'No update is running. Continue to retire the old service through its installed operator and start the selected version. Interrupting active work requires a separate confirmation.',
63
69
  busy: 'Other connections or work in progress prevent an automatic handoff. Stopping the service may interrupt that work.',
64
70
  activity_unknown: 'The background service is incompatible with this client, and its active work is unknown. Stop and continue restarts it and may interrupt work in other windows or devices.',
65
71
  operator_required: `This client cannot update the background service here. Use its managing app or operator command on ${view.target.name}, then retry.`,
66
- repair_required: 'The last startup or handoff did not finish. Retry safely, or copy diagnostics if it still fails.',
72
+ repair_required: 'The last startup or handoff failed. Review the diagnostic below, correct the cause, then retry. Repeating the same action without a state change will usually fail again.',
67
73
  retry_required: 'The service changed or the handoff has not finished. A safe retry will not interrupt work by default.',
68
74
  };
69
75
  if (view.recoveryBlocker && view.reason === 'operator_required') {
70
76
  const guidance = zh
71
77
  ? tw
72
78
  ? {
73
- managed: '此背景服務由已安裝的管理程式維護。請在服務的管理應用程式中更新,再回到這裡重試。',
79
+ managed: '此背景服務由安裝它的 Maka 管理。如果由 Desktop 安裝,請在該 Desktop 中開啟此工作區,然後選擇「停止舊服務並繼續」;否則請使用安裝它的 Maka 更新服務,再回到這裡重試。',
74
80
  owner: '此背景服務屬於另一個 Maka 安裝。請使用管理它的 Maka 安裝更新,再重試。',
75
81
  installation: '這次啟動使用暫存安裝,無法接管現有背景服務。請使用已安裝的 Maka 更新服務,再重試。',
76
82
  identity: '無法確認舊背景服務的處理程序身分,因此不能安全停止它。請關閉啟動它的 Maka 或透過其管理程式停止服務,再重試。',
77
83
  }
78
84
  : {
79
- managed: '此后台服务由已安装的管理程序维护。请在服务的管理应用中更新,再回到这里重试。',
85
+ managed: '此后台服务由安装它的 Maka 管理。如果由 Desktop 安装,请在该 Desktop 中打开此工作区,然后选择“停止旧服务并继续”;否则请使用安装它的 Maka 更新服务,再回到这里重试。',
80
86
  owner: '此后台服务属于另一个 Maka 安装。请使用管理它的 Maka 安装更新,然后重试。',
81
87
  installation: '本次启动使用临时安装,无法接管现有后台服务。请使用已安装的 Maka 更新服务,然后重试。',
82
88
  identity: '无法确认旧后台服务的进程身份,因此不能安全停止它。请关闭启动它的 Maka 或通过其管理程序停止服务,然后重试。',
83
89
  }
84
90
  : {
85
- managed: 'An installed operator manages this background service. Update it through its managing app, then return here and retry.',
91
+ managed: 'This background service is managed by the Maka installation that created it. If Desktop installed it, open this workspace there and choose Stop old service and continue. Otherwise update the service with that Maka installation, then return here and retry.',
86
92
  owner: 'Another Maka installation owns this background service. Update it using that installation, then retry.',
87
93
  installation: 'This temporary installation cannot take over the existing background service. Update it using an installed Maka, then retry.',
88
94
  identity: 'The old background process could not be identified safely. Close the Maka instance that started it or stop it through its operator, then retry.',
89
95
  };
90
96
  descriptions.operator_required = guidance[view.recoveryBlocker];
91
97
  }
98
+ if (view.manualRecheck && view.reason === 'busy') {
99
+ descriptions.busy = zh
100
+ ? tw
101
+ ? '舊服務拒絕安全停止;這可能是其他連線或背景工作所致。關閉其他用戶端後可再次嘗試安全停止,或明確選擇中斷工作並繼續。'
102
+ : '旧服务拒绝安全停止;这可能是其他连接或后台工作所致。关闭其他客户端后可再次尝试安全停止,或明确选择中断工作并继续。'
103
+ : 'The old service refused safe retirement. Other connections or background work may be keeping it in use. Close other clients and try stopping safely again, or explicitly interrupt work and continue.';
104
+ }
105
+ if (view.manualRecheck && view.reason === 'operator_required') {
106
+ titles.operator_required = zh
107
+ ? tw
108
+ ? '無法連線到背景服務'
109
+ : '无法连接后台服务'
110
+ : 'Cannot connect to the background service';
111
+ descriptions.operator_required = zh
112
+ ? tw
113
+ ? '目前版本無法連線,且尚未執行更新。請查看診斷或更新用戶端,完成後重新檢查。'
114
+ : '当前版本无法连接,且尚未执行更新。请查看诊断或更新客户端,完成后重新检查。'
115
+ : 'These builds cannot connect and no update is running. Check the diagnostic or update the client, then recheck.';
116
+ }
117
+ const packageChange = view.packageChange
118
+ ? `${view.target.name}: ${view.packageChange.current} → ${view.packageChange.target}`
119
+ : '';
92
120
  const activity = view.activity;
93
121
  const background = activity?.drainResidencies;
94
122
  const backgroundFacts = !activity
@@ -111,17 +139,23 @@ export function formatHostHandoff(view, locale) {
111
139
  ? `${activity.connections} 个连接 · ${activity.activeOperations} 个进行中的操作`
112
140
  : `${activity.connections} connections · ${activity.activeOperations} operations in progress`
113
141
  : '';
114
- const waiting = view.mayExitNaturally
115
- ? tw
116
- ? 'Maka 會持續檢查,並在可以安全繼續時自動繼續。'
117
- : zh
118
- ? 'Maka 会持续检查,并在可以安全继续时自动继续。'
119
- : 'Maka keeps checking and continues automatically when it is safe.'
120
- : tw
121
- ? 'Maka 會持續檢查。若狀態沒有改變,等待或重試不會解決此問題。'
122
- : zh
123
- ? 'Maka 会持续检查。若状态没有变化,等待或重试不会解决此问题。'
124
- : 'Maka keeps checking. Waiting or retrying will not resolve this unless the service state changes.';
142
+ const waiting = view.manualRecheck
143
+ ? zh
144
+ ? tw
145
+ ? '重新檢查只會重試連線,不會更新服務。'
146
+ : '重新检查只会重试连接,不会更新服务。'
147
+ : 'Recheck retries the connection without updating the service.'
148
+ : view.mayExitNaturally
149
+ ? tw
150
+ ? 'Maka 會持續檢查,並在可以安全繼續時自動繼續。'
151
+ : zh
152
+ ? 'Maka 会持续检查,并在可以安全继续时自动继续。'
153
+ : 'Maka keeps checking and continues automatically when it is safe.'
154
+ : tw
155
+ ? 'Maka 會持續檢查。若狀態沒有改變,等待或重試不會解決此問題。'
156
+ : zh
157
+ ? 'Maka 会持续检查。若状态没有变化,等待或重试不会解决此问题。'
158
+ : 'Maka keeps checking. Waiting or retrying will not resolve this unless the service state changes.';
125
159
  const repairNotice = view.operation === 'repair'
126
160
  ? tw
127
161
  ? '修復將使用目前應用程式配套的版本,可能替換現有服務版本。'
@@ -132,19 +166,34 @@ export function formatHostHandoff(view, locale) {
132
166
  const labels = tw
133
167
  ? {
134
168
  cancel: '取消',
135
- retry: '安全重試',
136
- interrupt: view.operation === 'repair' ? '中斷並修復' : '停止並繼續',
169
+ retry: view.manualRecheck ? '重新檢查' : '安全重試',
170
+ replace: '停止舊服務並繼續',
171
+ interrupt: view.manualRecheck
172
+ ? '中斷工作並繼續'
173
+ : view.operation === 'repair'
174
+ ? '中斷並修復'
175
+ : '停止並繼續',
137
176
  }
138
177
  : zh
139
178
  ? {
140
179
  cancel: '取消',
141
- retry: '安全重试',
142
- interrupt: view.operation === 'repair' ? '中断并修复' : '停止并继续',
180
+ retry: view.manualRecheck ? '重新检查' : '安全重试',
181
+ replace: '停止旧服务并继续',
182
+ interrupt: view.manualRecheck
183
+ ? '中断工作并继续'
184
+ : view.operation === 'repair'
185
+ ? '中断并修复'
186
+ : '停止并继续',
143
187
  }
144
188
  : {
145
189
  cancel: 'Cancel',
146
- retry: 'Retry safely',
147
- interrupt: view.operation === 'repair' ? 'Interrupt and repair' : 'Stop and continue',
190
+ retry: view.manualRecheck ? 'Recheck' : 'Retry safely',
191
+ replace: 'Stop old service and continue',
192
+ interrupt: view.manualRecheck
193
+ ? 'Interrupt work and continue'
194
+ : view.operation === 'repair'
195
+ ? 'Interrupt and repair'
196
+ : 'Stop and continue',
148
197
  };
149
198
  const phases = tw
150
199
  ? {
@@ -187,7 +236,7 @@ export function formatHostHandoff(view, locale) {
187
236
  : zh
188
237
  ? '正在完成交接或安全收尾,请稍候。'
189
238
  : 'Finishing the handoff or its safe recovery. Please wait.'
190
- : [facts, backgroundFacts, waiting, repairNotice, view.operatorStep]
239
+ : [packageChange, facts, backgroundFacts, waiting, repairNotice, view.operatorStep]
191
240
  .filter(Boolean)
192
241
  .join('\n'),
193
242
  actions: view.actions.map((action) => ({ action, label: labels[action] })),