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.
- package/LICENSE +106 -0
- package/dist/cli-core.js +28 -0
- package/dist/runtime-host-cli.js +43 -3
- package/dist/runtime-host-handoff-surface.js +10 -8
- package/dist/runtime-host-lifecycle-transaction.js +28 -3
- package/dist/runtime-host-local-source-retirement.js +1 -1
- package/dist/runtime-host-run-command.js +15 -7
- package/dist/runtime-host-setup-command.js +29 -6
- package/dist/runtime-host-update-command.js +49 -5
- package/dist/session-export-command.js +72 -0
- package/dist/session-import-command.js +69 -0
- package/native/runtime-host-peer/prebuilds/darwin-arm64/maka_runtime_host_peer.node +0 -0
- package/native/runtime-host-peer/prebuilds/linux-arm64/maka_runtime_host_peer.node +0 -0
- package/native/runtime-host-peer/prebuilds/linux-x64/maka_runtime_host_peer.node +0 -0
- package/native/runtime-host-peer/prebuilds/win32-x64/maka_runtime_host_peer.node +0 -0
- package/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.js +9 -4
- package/node_modules/@maka/core/dist/diagnostic-log.js +18 -7
- package/node_modules/@maka/core/dist/text-sanitize.js +8 -2
- package/node_modules/@maka/core/dist/usage-stats/types.js +2 -0
- package/node_modules/@maka/core/dist/workhub-routing.js +126 -0
- package/node_modules/@maka/core/package.json +2 -1
- package/node_modules/@maka/runtime/dist/ai-sdk-turn.js +15 -11
- package/node_modules/@maka/runtime/dist/archive-read-tool.js +3 -1
- package/node_modules/@maka/runtime/dist/bots/bot-test.js +2 -1
- package/node_modules/@maka/runtime/dist/bots/feishu-bridge.js +24 -20
- package/node_modules/@maka/runtime/dist/bots/slack-bridge.js +5 -3
- package/node_modules/@maka/runtime/dist/bots/wechat-bridge.js +87 -29
- package/node_modules/@maka/runtime/dist/bots/wecom-bridge.js +40 -36
- package/node_modules/@maka/runtime/dist/builtin-tools.js +21 -2
- package/node_modules/@maka/runtime/dist/computer-use-tools.js +4 -1
- package/node_modules/@maka/runtime/dist/deep-research-tools.js +11 -5
- package/node_modules/@maka/runtime/dist/edit-replace.js +2 -2
- package/node_modules/@maka/runtime/dist/filesystem-worker/operations.js +5 -6
- package/node_modules/@maka/runtime/dist/memory-extraction-evidence.js +7 -1
- package/node_modules/@maka/runtime/dist/memory-extraction.js +12 -7
- package/node_modules/@maka/runtime/dist/openai-responses-websocket.js +2 -5
- package/node_modules/@maka/runtime/dist/plugin-agent-service.js +131 -0
- package/node_modules/@maka/runtime/dist/plugin-approval-service.js +33 -0
- package/node_modules/@maka/runtime/dist/plugin-attachment-service.js +53 -0
- package/node_modules/@maka/runtime/dist/plugin-command-service.js +100 -0
- package/node_modules/@maka/runtime/dist/plugin-composition-loader.js +11 -2
- package/node_modules/@maka/runtime/dist/plugin-data-services.js +332 -0
- package/node_modules/@maka/runtime/dist/plugin-fs-service.js +62 -0
- package/node_modules/@maka/runtime/dist/plugin-goal-service.js +61 -0
- package/node_modules/@maka/runtime/dist/plugin-invocation-signal.js +24 -0
- package/node_modules/@maka/runtime/dist/plugin-llm-service.js +85 -0
- package/node_modules/@maka/runtime/dist/plugin-lsp-service.js +94 -0
- package/node_modules/@maka/runtime/dist/plugin-scope-registry.js +91 -0
- package/node_modules/@maka/runtime/dist/plugin-session-query-service.js +71 -0
- package/node_modules/@maka/runtime/dist/plugin-shell-env-service.js +87 -0
- package/node_modules/@maka/runtime/dist/plugin-shell-service.js +74 -0
- package/node_modules/@maka/runtime/dist/plugin-skill-service.js +93 -0
- package/node_modules/@maka/runtime/dist/plugin-system-prompt-service.js +346 -0
- package/node_modules/@maka/runtime/dist/plugin-tool-service.js +18 -52
- package/node_modules/@maka/runtime/dist/plugin-user-question-service.js +43 -0
- package/node_modules/@maka/runtime/dist/plugin-web-service.js +69 -0
- package/node_modules/@maka/runtime/dist/request-customization-fetch.js +14 -7
- package/node_modules/@maka/runtime/dist/session-export.js +178 -0
- package/node_modules/@maka/runtime/dist/session-import.js +100 -0
- package/node_modules/@maka/runtime/dist/session-manager.js +6 -1
- package/node_modules/@maka/runtime/dist/shell-run-manager.js +9 -6
- package/node_modules/@maka/runtime/dist/shell-run-tool-result.js +13 -6
- package/node_modules/@maka/runtime/dist/stream-graph-coordinator.js +43 -10
- package/node_modules/@maka/runtime/dist/stream-graph-handoff.js +6 -1
- package/node_modules/@maka/runtime/dist/subscription-model-fetch.js +1 -4
- package/node_modules/@maka/runtime/dist/system-prompt/workspace-instructions.js +11 -6
- package/node_modules/@maka/runtime/dist/tavily-search.js +8 -2
- package/node_modules/@maka/runtime/dist/text-line-window.js +49 -0
- package/node_modules/@maka/runtime/dist/tool-output.js +35 -12
- package/node_modules/@maka/runtime/dist/unified-diff.js +40 -10
- package/node_modules/@maka/runtime/dist/web-fetch-tool.js +4 -2
- package/node_modules/@maka/runtime/dist/workers/filesystem-worker.js +82 -33
- package/node_modules/@maka/runtime/dist/workspace-executor.js +2 -6
- package/node_modules/@maka/runtime/package.json +20 -1
- package/node_modules/@maka/runtime-host/dist/client/host-handoff-copy.js +73 -24
- package/node_modules/@maka/runtime-host/dist/client/host-handoff.js +46 -12
- package/node_modules/@maka/runtime-host/dist/operator/setup-frame.js +31 -21
- package/node_modules/@maka/runtime-host/dist/peer-mesh/node.js +7 -4
- package/node_modules/@maka/runtime-host/dist/protocol/artifact.js +2 -2
- package/node_modules/@maka/runtime-host/dist/protocol/index.js +10 -1
- package/node_modules/@maka/runtime-host/dist/protocol/plugin-platform.js +30 -5
- package/node_modules/@maka/runtime-host/dist/protocol/session-transcript.js +3 -2
- package/node_modules/@maka/runtime-host/dist/protocol/skill-catalog.js +2 -1
- package/node_modules/@maka/runtime-host/dist/protocol/workhub-coordination.js +25 -23
- package/node_modules/@maka/runtime-host/dist/server/artifact-coordinator.js +2 -0
- package/node_modules/@maka/runtime-host/dist/server/client-capability-coordinator.js +62 -4
- package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +481 -11
- package/node_modules/@maka/runtime-host/dist/server/execution-model-authority.js +74 -0
- package/node_modules/@maka/runtime-host/dist/server/goal-coordinator.js +6 -1
- package/node_modules/@maka/runtime-host/dist/server/hosted-execution-recovery.js +2 -2
- package/node_modules/@maka/runtime-host/dist/server/hosted-execution-tool-profile.js +30 -0
- package/node_modules/@maka/runtime-host/dist/server/interactive-run-composer.js +114 -20
- package/node_modules/@maka/runtime-host/dist/server/message-coordinator.js +49 -12
- package/node_modules/@maka/runtime-host/dist/server/plugin-data-runtime.js +234 -0
- package/node_modules/@maka/runtime-host/dist/server/plugin-platform-coordinator.js +6 -0
- package/node_modules/@maka/runtime-host/dist/server/plugin-platform.js +12 -0
- package/node_modules/@maka/runtime-host/dist/server/root-admission-owner.js +17 -8
- package/node_modules/@maka/runtime-host/dist/server/root-turn-coordinator.js +189 -92
- package/node_modules/@maka/runtime-host/dist/server/runtime-resource-projection.js +3 -9
- package/node_modules/@maka/runtime-host/dist/server/session-continuity-coordinator.js +20 -21
- package/node_modules/@maka/runtime-host/dist/server/session-transcript-pager.js +24 -2
- package/node_modules/@maka/runtime-host/dist/server/skill-catalog-coordinator.js +18 -2
- package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-action-gate.js +44 -35
- package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-coordinator.js +92 -10
- package/node_modules/@maka/runtime-host/dist/transport/framed-byte-stream-transport.js +4 -1
- package/node_modules/@maka/runtime-host/dist/transport/local-ipc-framing.js +4 -2
- package/node_modules/@maka/runtime-host/dist/transport/peer-native.js +9 -8
- package/node_modules/@maka/runtime-host/dist/transport/resumable-peer-stream.js +14 -9
- package/node_modules/@maka/storage/dist/agent-run-store.js +54 -10
- package/node_modules/@maka/storage/dist/context-offload-snapshot.js +32 -10
- package/node_modules/@maka/storage/dist/context-value-mutation-gate.js +59 -0
- package/node_modules/@maka/storage/dist/execution-stores.js +1 -1
- package/node_modules/@maka/storage/dist/session-bundle-policy.js +909 -34
- package/node_modules/@maka/storage/dist/session-message-projection.js +8 -4
- package/node_modules/@maka/storage/dist/session-store.js +2 -2
- package/node_modules/@maka/storage/dist/sqlite-context-offload-store.js +18 -4
- package/node_modules/@maka/storage/dist/sqlite-session-metadata-store.js +12 -5
- package/node_modules/@maka/storage/dist/stable-storage.js +2 -1
- package/node_modules/@maka/storage/package.json +2 -0
- package/node_modules/@modelcontextprotocol/client/dist/src-D_zzAWoS.mjs +22 -5
- package/node_modules/@modelcontextprotocol/client/dist/src-NAgB4Mp8.cjs +22 -5
- package/node_modules/zod/v4/core/memoizer.cjs +12 -16
- package/node_modules/zod/v4/core/memoizer.js +12 -16
- package/package.json +1 -1
|
@@ -172,10 +172,11 @@ export class WechatBridge extends BaseBotAdapter {
|
|
|
172
172
|
const baseUrl = normalizeWechatBridgeUrl(this.settings.webhookUrl);
|
|
173
173
|
if (!baseUrl)
|
|
174
174
|
return;
|
|
175
|
+
const cursor = { sinceEpochSeconds };
|
|
175
176
|
while (this.running) {
|
|
176
177
|
this.abortController = new AbortController();
|
|
177
178
|
try {
|
|
178
|
-
const response = await proxiedFetch(`${baseUrl}/messages/stream?since=${sinceEpochSeconds}`, {
|
|
179
|
+
const response = await proxiedFetch(`${baseUrl}/messages/stream?since=${cursor.sinceEpochSeconds}`, {
|
|
179
180
|
method: 'GET',
|
|
180
181
|
headers: wechatBridgeHeaders(this.settings),
|
|
181
182
|
signal: this.abortController.signal,
|
|
@@ -183,19 +184,8 @@ export class WechatBridge extends BaseBotAdapter {
|
|
|
183
184
|
});
|
|
184
185
|
if (!response.ok || !response.body)
|
|
185
186
|
throw new Error(`WeChat stream HTTP ${response.status}`);
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
for (const message of messages) {
|
|
189
|
-
const event = mapWechatBridgeMessage(message);
|
|
190
|
-
if (!event)
|
|
191
|
-
continue;
|
|
192
|
-
sinceEpochSeconds = Math.max(sinceEpochSeconds, Math.floor(event.receivedAt / 1000));
|
|
193
|
-
this.readiness = 'operational';
|
|
194
|
-
this.reason = undefined;
|
|
195
|
-
this.emitIncomingMessage(event);
|
|
196
|
-
this.emitStatusChange();
|
|
197
|
-
}
|
|
198
|
-
}
|
|
187
|
+
const messages = readSseJsonObjects(response.body);
|
|
188
|
+
while (await this.processNextLiveMessages(messages, cursor)) { }
|
|
199
189
|
if (this.running)
|
|
200
190
|
await sleep(1_000);
|
|
201
191
|
}
|
|
@@ -212,6 +202,31 @@ export class WechatBridge extends BaseBotAdapter {
|
|
|
212
202
|
}
|
|
213
203
|
}
|
|
214
204
|
}
|
|
205
|
+
async processNextLiveMessages(stream, cursor) {
|
|
206
|
+
// Keep the iterator result and mapped events out of the next idle read's frame.
|
|
207
|
+
const next = await stream.next();
|
|
208
|
+
if (next.done)
|
|
209
|
+
return false;
|
|
210
|
+
try {
|
|
211
|
+
const messages = Array.isArray(next.value) ? next.value : [next.value];
|
|
212
|
+
for (const message of messages) {
|
|
213
|
+
const event = mapWechatBridgeMessage(message);
|
|
214
|
+
if (!event)
|
|
215
|
+
continue;
|
|
216
|
+
cursor.sinceEpochSeconds = Math.max(cursor.sinceEpochSeconds, Math.floor(event.receivedAt / 1000));
|
|
217
|
+
this.readiness = 'operational';
|
|
218
|
+
this.reason = undefined;
|
|
219
|
+
this.emitIncomingMessage(event);
|
|
220
|
+
this.emitStatusChange();
|
|
221
|
+
}
|
|
222
|
+
return true;
|
|
223
|
+
}
|
|
224
|
+
catch (error) {
|
|
225
|
+
// Match for-await: close after processing failures, preserving the original error.
|
|
226
|
+
await stream.return(undefined).catch(() => { });
|
|
227
|
+
throw error;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
215
230
|
async streamIlinkMessages(cursor) {
|
|
216
231
|
const baseUrl = normalizeWechatIlinkBaseUrl(this.settings.webhookUrl);
|
|
217
232
|
const token = this.settings.token.trim();
|
|
@@ -402,24 +417,67 @@ export function mapWechatIlinkMessage(raw) {
|
|
|
402
417
|
}
|
|
403
418
|
export async function* readSseJsonObjects(body) {
|
|
404
419
|
const decoder = new TextDecoder();
|
|
420
|
+
const iterator = body[Symbol.asyncIterator]();
|
|
405
421
|
let buffer = '';
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
422
|
+
let closeIterator = false;
|
|
423
|
+
try {
|
|
424
|
+
while (true) {
|
|
425
|
+
// A rejected next() does not close its iterator under for-await semantics.
|
|
426
|
+
closeIterator = false;
|
|
427
|
+
let text = await readSseTextChunk(iterator, decoder);
|
|
428
|
+
if (text === undefined)
|
|
429
|
+
return;
|
|
430
|
+
closeIterator = true;
|
|
431
|
+
buffer += text;
|
|
432
|
+
text = undefined;
|
|
433
|
+
let boundary = findSseBoundary(buffer);
|
|
434
|
+
while (boundary) {
|
|
435
|
+
let data = sseEventData(buffer.slice(0, boundary.index));
|
|
436
|
+
buffer = buffer.slice(boundary.index + boundary.length);
|
|
437
|
+
if (data)
|
|
438
|
+
yield JSON.parse(data);
|
|
439
|
+
data = '';
|
|
440
|
+
boundary = findSseBoundary(buffer);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
catch (error) {
|
|
445
|
+
if (closeIterator) {
|
|
446
|
+
closeIterator = false;
|
|
447
|
+
try {
|
|
448
|
+
await iterator.return?.();
|
|
449
|
+
}
|
|
450
|
+
catch { }
|
|
421
451
|
}
|
|
452
|
+
throw error;
|
|
453
|
+
}
|
|
454
|
+
finally {
|
|
455
|
+
if (closeIterator)
|
|
456
|
+
await iterator.return?.();
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
async function readSseTextChunk(iterator, decoder) {
|
|
460
|
+
const next = await iterator.next();
|
|
461
|
+
if (next.done)
|
|
462
|
+
return;
|
|
463
|
+
try {
|
|
464
|
+
return decoder.decode(next.value, { stream: true });
|
|
422
465
|
}
|
|
466
|
+
catch (error) {
|
|
467
|
+
try {
|
|
468
|
+
await iterator.return?.();
|
|
469
|
+
}
|
|
470
|
+
catch { }
|
|
471
|
+
throw error;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
function sseEventData(event) {
|
|
475
|
+
return event
|
|
476
|
+
.split(/\r?\n/)
|
|
477
|
+
.filter((line) => line.startsWith('data:'))
|
|
478
|
+
.map((line) => line.slice(5).trimStart())
|
|
479
|
+
.join('\n')
|
|
480
|
+
.trim();
|
|
423
481
|
}
|
|
424
482
|
export async function testWechatBridge(channel) {
|
|
425
483
|
const baseUrl = normalizeWechatBridgeUrl(channel.webhookUrl);
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* specific language governing permissions and limitations
|
|
17
17
|
* under the License.
|
|
18
18
|
*/
|
|
19
|
-
import {
|
|
19
|
+
import { createRequire } from 'node:module';
|
|
20
20
|
import { BaseBotAdapter, botReadinessFromSettings } from './base-adapter.js';
|
|
21
21
|
const AUTH_TIMEOUT_MS = 15_000;
|
|
22
22
|
/** Detach bridge callbacks before disconnect can synchronously emit. */
|
|
@@ -78,36 +78,39 @@ export class WeComBotBridge extends BaseBotAdapter {
|
|
|
78
78
|
return;
|
|
79
79
|
}
|
|
80
80
|
this.explicitlyStopped = false;
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
81
|
+
let startedClient;
|
|
82
|
+
try {
|
|
83
|
+
const { WSClient } = createRequire(import.meta.url)('@wecom/aibot-node-sdk');
|
|
84
|
+
const client = new WSClient({
|
|
85
|
+
botId,
|
|
86
|
+
secret,
|
|
87
|
+
maxReconnectAttempts: -1,
|
|
88
|
+
logger: quietLogger,
|
|
89
|
+
});
|
|
90
|
+
startedClient = client;
|
|
91
|
+
this.client = client;
|
|
92
|
+
this.wire(client, botId);
|
|
93
|
+
await new Promise((resolve, reject) => {
|
|
94
|
+
let settled = false;
|
|
95
|
+
const onAuthenticated = () => finish(resolve);
|
|
96
|
+
const onError = (error) => finish(() => reject(error));
|
|
97
|
+
const cleanup = () => {
|
|
98
|
+
clearTimeout(timer);
|
|
99
|
+
client.off('authenticated', onAuthenticated);
|
|
100
|
+
client.off('error', onError);
|
|
101
|
+
};
|
|
102
|
+
const finish = (fn) => {
|
|
103
|
+
if (settled)
|
|
104
|
+
return;
|
|
105
|
+
settled = true;
|
|
106
|
+
cleanup();
|
|
107
|
+
fn();
|
|
108
|
+
};
|
|
109
|
+
const timer = setTimeout(() => finish(() => reject(new Error('WeCom authentication timed out'))), AUTH_TIMEOUT_MS);
|
|
110
|
+
client.once('authenticated', onAuthenticated);
|
|
111
|
+
client.once('error', onError);
|
|
112
|
+
client.connect();
|
|
113
|
+
});
|
|
111
114
|
if (this.explicitlyStopped || this.client !== client)
|
|
112
115
|
return;
|
|
113
116
|
this.running = true;
|
|
@@ -116,17 +119,18 @@ export class WeComBotBridge extends BaseBotAdapter {
|
|
|
116
119
|
this.reason = undefined;
|
|
117
120
|
this.readiness = 'credentials_valid';
|
|
118
121
|
this.emitStatusChange();
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (this.explicitlyStopped || this.client !==
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
if (this.explicitlyStopped || (startedClient && this.client !== startedClient))
|
|
122
125
|
return;
|
|
123
126
|
this.running = false;
|
|
124
127
|
this.recordFailure(error);
|
|
125
128
|
this.readiness = 'configured';
|
|
126
129
|
this.emitStatusChange();
|
|
127
130
|
this.client = null;
|
|
128
|
-
|
|
129
|
-
|
|
131
|
+
if (startedClient)
|
|
132
|
+
closeWeComClient(startedClient);
|
|
133
|
+
}
|
|
130
134
|
}
|
|
131
135
|
async stop() {
|
|
132
136
|
this.explicitlyStopped = true;
|
|
@@ -194,9 +194,28 @@ export function buildBuiltinTools(options = {}) {
|
|
|
194
194
|
shell,
|
|
195
195
|
...(options.sandboxManager
|
|
196
196
|
? {
|
|
197
|
-
transformCommand: ({ command, pty, requiredBoundary, ctx }) =>
|
|
197
|
+
transformCommand: ({ command, pty, requiredBoundary, ctx }) => {
|
|
198
|
+
const transformed = sandboxCommand(options.sandboxManager, options.permissionProfile, sandboxPlatform, command, pty, ctx, requiredBoundary, 'background_command');
|
|
199
|
+
if (!options.shellEnvironment)
|
|
200
|
+
return transformed;
|
|
201
|
+
return {
|
|
202
|
+
...(transformed ?? { cwd: ctx.cwd }),
|
|
203
|
+
env: {
|
|
204
|
+
...process.env,
|
|
205
|
+
...transformed?.env,
|
|
206
|
+
...options.shellEnvironment,
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
},
|
|
198
210
|
}
|
|
199
|
-
:
|
|
211
|
+
: options.shellEnvironment
|
|
212
|
+
? {
|
|
213
|
+
transformCommand: ({ ctx }) => ({
|
|
214
|
+
cwd: ctx.cwd,
|
|
215
|
+
env: { ...process.env, ...options.shellEnvironment },
|
|
216
|
+
}),
|
|
217
|
+
}
|
|
218
|
+
: {}),
|
|
200
219
|
}),
|
|
201
220
|
]
|
|
202
221
|
: [
|
|
@@ -945,6 +945,7 @@ export function buildComputerUseTools(deps) {
|
|
|
945
945
|
release();
|
|
946
946
|
if (invocationQueues.get(sessionId) === current) {
|
|
947
947
|
invocationQueues.delete(sessionId);
|
|
948
|
+
presentationGenerations.delete(sessionId);
|
|
948
949
|
}
|
|
949
950
|
}
|
|
950
951
|
}
|
|
@@ -2385,7 +2386,9 @@ export function buildComputerUseTools(deps) {
|
|
|
2385
2386
|
}
|
|
2386
2387
|
const tools = [tool];
|
|
2387
2388
|
tools.clearSession = (sessionId) => {
|
|
2388
|
-
|
|
2389
|
+
if (invocationQueues.has(sessionId)) {
|
|
2390
|
+
presentationGenerations.set(sessionId, (presentationGenerations.get(sessionId) ?? 0) + 1);
|
|
2391
|
+
}
|
|
2389
2392
|
for (const wake of presentationQueueWaiters.get(sessionId) ?? [])
|
|
2390
2393
|
wake();
|
|
2391
2394
|
for (const wake of presentationWaiters.get(sessionId) ?? [])
|
|
@@ -142,14 +142,20 @@ function buildReadArtifactTool(deps) {
|
|
|
142
142
|
}
|
|
143
143
|
const offset = input.offset_chars ?? 0;
|
|
144
144
|
const maxChars = input.max_chars ?? DEEP_RESEARCH_ARTIFACT_READ_DEFAULT_CHARS;
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
const
|
|
145
|
+
const selected = [];
|
|
146
|
+
let total = 0;
|
|
147
|
+
for (const character of read.text) {
|
|
148
|
+
if (total >= offset && total < offset + maxChars)
|
|
149
|
+
selected.push(character);
|
|
150
|
+
total += 1;
|
|
151
|
+
}
|
|
152
|
+
const end = Math.min(total, offset + maxChars);
|
|
153
|
+
const chunk = safeResearchArtifactContent(selected.join(''));
|
|
148
154
|
return [
|
|
149
|
-
`<deep-research-artifact id="${ref.artifactId}" role="${ref.role}" offset="${offset}" end="${end}" total="${
|
|
155
|
+
`<deep-research-artifact id="${ref.artifactId}" role="${ref.role}" offset="${offset}" end="${end}" total="${total}">`,
|
|
150
156
|
`Name: ${normalizeInlineText(ref.name)}`,
|
|
151
157
|
...(ref.locator ? [`Locator: ${normalizeInlineText(ref.locator)}`] : []),
|
|
152
|
-
`Truncated: ${end <
|
|
158
|
+
`Truncated: ${end < total}`,
|
|
153
159
|
'',
|
|
154
160
|
chunk,
|
|
155
161
|
'</deep-research-artifact>',
|
|
@@ -139,10 +139,10 @@ export function computeEditedSource(source, oldString, newString, where) {
|
|
|
139
139
|
function finish(content, span, replacement, matchedVia) {
|
|
140
140
|
const index = content.indexOf(span);
|
|
141
141
|
const before = content.slice(0, index);
|
|
142
|
-
const startLine = before
|
|
142
|
+
const startLine = countOccurrences(before, '\n') + 1;
|
|
143
143
|
// A trailing newline in the span is the last line's terminator, not an
|
|
144
144
|
// extra line, so it must not bump endLine.
|
|
145
|
-
const spanLineCount = span
|
|
145
|
+
const spanLineCount = countOccurrences(span, '\n') + 1 - (span.endsWith('\n') ? 1 : 0);
|
|
146
146
|
const endLine = startLine + Math.max(spanLineCount, 1) - 1;
|
|
147
147
|
// slice-join (not String.replace) so `$&`/`$1` in newString are literal.
|
|
148
148
|
const next = before + replacement + content.slice(index + span.length);
|
|
@@ -25,6 +25,7 @@ import { sandboxPathApi } from './sandbox-paths.js';
|
|
|
25
25
|
import { sandboxBoundaryExpansionAllowsPath } from '@maka/core/sandbox-boundary';
|
|
26
26
|
import { ApplyPatchRejectedError, applyUpdateToContent, createPatchedFile, } from '../apply-patch-file.js';
|
|
27
27
|
import { computeEditedSource } from '../edit-replace.js';
|
|
28
|
+
import { readTextLineWindow } from '../text-line-window.js';
|
|
28
29
|
import { createEditUnifiedDiff, createUnifiedDiff } from '../unified-diff.js';
|
|
29
30
|
import { compareAndDeleteEntry, hostVisibilityAfterWrite, openStableTarget, readModifyWriteThroughHandle, StableWriteFailure, writeThroughHandle, } from '../file-stable-write.js';
|
|
30
31
|
import { isSupportedImagePath, readWorkspaceImage } from '../image-file.js';
|
|
@@ -75,12 +76,10 @@ export async function executeFilesystemOperation(operation, operationBoundary, d
|
|
|
75
76
|
}
|
|
76
77
|
}
|
|
77
78
|
const content = await fs.readFile(path, 'utf8');
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const end = operation.limit ? start + operation.limit : lines.length;
|
|
83
|
-
return { kind: 'read', content: lines.slice(start, end).join('\n') };
|
|
79
|
+
return {
|
|
80
|
+
kind: 'read',
|
|
81
|
+
content: readTextLineWindow(content, operation.offset, operation.limit),
|
|
82
|
+
};
|
|
84
83
|
}
|
|
85
84
|
case 'write': {
|
|
86
85
|
const path = await resolveWritableAllowed(operation.cwd, operation.path, 'Write', operationBoundary);
|
|
@@ -273,7 +273,13 @@ function historyRole(event) {
|
|
|
273
273
|
return event.role === 'model' ? 'assistant' : 'user';
|
|
274
274
|
}
|
|
275
275
|
function sliceCodePoints(value, maximum) {
|
|
276
|
-
|
|
276
|
+
const prefix = [];
|
|
277
|
+
for (const point of value) {
|
|
278
|
+
if (prefix.length >= maximum)
|
|
279
|
+
break;
|
|
280
|
+
prefix.push(point);
|
|
281
|
+
}
|
|
282
|
+
return prefix.join('');
|
|
277
283
|
}
|
|
278
284
|
function uniqueSorted(values) {
|
|
279
285
|
return [...new Set(values)].sort((left, right) => left - right);
|
|
@@ -369,7 +369,7 @@ export class MemoryExtractionEngine {
|
|
|
369
369
|
return undefined;
|
|
370
370
|
maximumSplitIndex = requestedTurnStart;
|
|
371
371
|
}
|
|
372
|
-
const split =
|
|
372
|
+
const split = findMemoryRangeSplit(pendingEntries, maximumSplitIndex, ({ first, second }) => {
|
|
373
373
|
const firstThroughOrdinal = first.at(-1).ordinal;
|
|
374
374
|
const firstTrigger = 'extract';
|
|
375
375
|
const firstPrepared = this.prepareRange({
|
|
@@ -924,9 +924,9 @@ function memorySegmentOperationId(operationId, afterOrdinal, throughOrdinal, por
|
|
|
924
924
|
.update(JSON.stringify({ operationId, afterOrdinal, throughOrdinal }))
|
|
925
925
|
.digest('hex')}`;
|
|
926
926
|
}
|
|
927
|
-
function
|
|
927
|
+
function findMemoryRangeSplit(entries, maximumSplitIndex = entries.length - 1, accepts) {
|
|
928
928
|
if (entries.length < 2)
|
|
929
|
-
return
|
|
929
|
+
return undefined;
|
|
930
930
|
const weights = entries.map(memoryRangeEventWeight);
|
|
931
931
|
const total = weights.reduce((sum, weight) => sum + weight, 0);
|
|
932
932
|
let prefix = 0;
|
|
@@ -942,11 +942,16 @@ function memoryRangeSplitCandidates(entries, maximumSplitIndex = entries.length
|
|
|
942
942
|
};
|
|
943
943
|
})
|
|
944
944
|
.filter(({ index }) => index <= maximumSplitIndex);
|
|
945
|
-
|
|
946
|
-
.sort((left, right) => Number(right.turnBoundary) - Number(left.turnBoundary) ||
|
|
945
|
+
candidates.sort((left, right) => Number(right.turnBoundary) - Number(left.turnBoundary) ||
|
|
947
946
|
left.distance - right.distance ||
|
|
948
|
-
left.index - right.index)
|
|
949
|
-
|
|
947
|
+
left.index - right.index);
|
|
948
|
+
// Keep only the candidate being checked; each pair copies the entire range.
|
|
949
|
+
for (const { index } of candidates) {
|
|
950
|
+
const split = { first: entries.slice(0, index), second: entries.slice(index) };
|
|
951
|
+
if (accepts(split))
|
|
952
|
+
return split;
|
|
953
|
+
}
|
|
954
|
+
return undefined;
|
|
950
955
|
}
|
|
951
956
|
function preparedMemoryRangeFits(prepared, trigger) {
|
|
952
957
|
if (!prepared)
|
|
@@ -221,11 +221,8 @@ function prepareWireRequest(body, baseline) {
|
|
|
221
221
|
const { previous_response_id: _previousResponseId, ...currentProperties } = body;
|
|
222
222
|
const fullBody = {
|
|
223
223
|
...currentProperties,
|
|
224
|
-
input
|
|
225
|
-
|
|
226
|
-
...structuredClone(baseline.responseOutput),
|
|
227
|
-
...structuredClone(body.input),
|
|
228
|
-
],
|
|
224
|
+
// These JSON values are privately owned; only the combined input array needs to be new.
|
|
225
|
+
input: [...baseline.fullBody.input, ...baseline.responseOutput, ...body.input],
|
|
229
226
|
};
|
|
230
227
|
const sameProperties = isDeepStrictEqual(requestProperties(baseline.fullBody), requestProperties(fullBody));
|
|
231
228
|
return {
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Licensed to the Apache Software Foundation (ASF) under one
|
|
3
|
+
* or more contributor license agreements. See the NOTICE file
|
|
4
|
+
* distributed with this work for additional information
|
|
5
|
+
* regarding copyright ownership. The ASF licenses this file
|
|
6
|
+
* to you under the Apache License, Version 2.0 (the
|
|
7
|
+
* "License"); you may not use this file except in compliance
|
|
8
|
+
* with the License. You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing,
|
|
13
|
+
* software distributed under the License is distributed on an
|
|
14
|
+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
15
|
+
* KIND, either express or implied. See the License for the
|
|
16
|
+
* specific language governing permissions and limitations
|
|
17
|
+
* under the License.
|
|
18
|
+
*/
|
|
19
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
20
|
+
import { Service } from './plugin-kernel.js';
|
|
21
|
+
import { pluginInvocationSignal } from './plugin-invocation-signal.js';
|
|
22
|
+
/** Agent registry and invocation carrier exposed to trusted Host plugins. */
|
|
23
|
+
export class PluginAgentService extends Service {
|
|
24
|
+
invocations = new AsyncLocalStorage();
|
|
25
|
+
agentRuntime;
|
|
26
|
+
constructor(ctx) {
|
|
27
|
+
super(ctx, 'agents');
|
|
28
|
+
ctx.accessor('agent', {
|
|
29
|
+
get: () => this.current(),
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
bindRuntime(runtime) {
|
|
33
|
+
if (this.ctx.maka)
|
|
34
|
+
throw new Error('Only the Host may bind the Agent Runtime');
|
|
35
|
+
if (this.agentRuntime)
|
|
36
|
+
throw new Error('Plugin Agent Runtime is already bound');
|
|
37
|
+
this.agentRuntime = runtime;
|
|
38
|
+
return this.ctx.effect(() => () => {
|
|
39
|
+
if (this.agentRuntime === runtime)
|
|
40
|
+
this.agentRuntime = undefined;
|
|
41
|
+
}, 'agents.bindRuntime()');
|
|
42
|
+
}
|
|
43
|
+
currentInvocation() {
|
|
44
|
+
return this.invocations.getStore();
|
|
45
|
+
}
|
|
46
|
+
requireInvocation() {
|
|
47
|
+
const invocation = this.currentInvocation();
|
|
48
|
+
if (!invocation)
|
|
49
|
+
throw new Error('This capability requires an active Agent invocation');
|
|
50
|
+
return invocation;
|
|
51
|
+
}
|
|
52
|
+
withInvocation(toolContext, operation) {
|
|
53
|
+
const invocation = Object.freeze({
|
|
54
|
+
sessionId: toolContext.sessionId,
|
|
55
|
+
...(toolContext.runId ? { runId: toolContext.runId } : {}),
|
|
56
|
+
turnId: toolContext.turnId,
|
|
57
|
+
cwd: toolContext.cwd,
|
|
58
|
+
...(toolContext.permissionMode ? { permissionMode: toolContext.permissionMode } : {}),
|
|
59
|
+
...(toolContext.executionBoundary
|
|
60
|
+
? { executionBoundary: toolContext.executionBoundary }
|
|
61
|
+
: {}),
|
|
62
|
+
toolCallId: toolContext.toolCallId,
|
|
63
|
+
abortSignal: toolContext.abortSignal,
|
|
64
|
+
toolContext,
|
|
65
|
+
});
|
|
66
|
+
return this.invocations.run(invocation, operation);
|
|
67
|
+
}
|
|
68
|
+
current() {
|
|
69
|
+
const invocation = this.currentInvocation();
|
|
70
|
+
if (!invocation)
|
|
71
|
+
return undefined;
|
|
72
|
+
return this.handle({
|
|
73
|
+
id: invocation.sessionId,
|
|
74
|
+
sessionId: invocation.sessionId,
|
|
75
|
+
root: true,
|
|
76
|
+
status: 'running',
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
async create(options = {}) {
|
|
80
|
+
const invocation = this.requireInvocation();
|
|
81
|
+
return this.handle(await this.runtime().create({ ...options, signal: pluginInvocationSignal(invocation.abortSignal, options.signal) }, invocation), invocation);
|
|
82
|
+
}
|
|
83
|
+
async resume(options) {
|
|
84
|
+
const invocation = this.requireInvocation();
|
|
85
|
+
return this.handle(await this.runtime().resume({ ...options, signal: pluginInvocationSignal(invocation.abortSignal, options.signal) }, invocation), invocation);
|
|
86
|
+
}
|
|
87
|
+
async get(id) {
|
|
88
|
+
const invocation = this.requireInvocation();
|
|
89
|
+
const descriptor = await this.runtime().get(assertId(id), invocation);
|
|
90
|
+
return descriptor ? this.handle(descriptor, invocation) : undefined;
|
|
91
|
+
}
|
|
92
|
+
async list() {
|
|
93
|
+
const invocation = this.requireInvocation();
|
|
94
|
+
return Object.freeze((await this.runtime().list(invocation)).map((descriptor) => this.handle(descriptor, invocation)));
|
|
95
|
+
}
|
|
96
|
+
async roots() {
|
|
97
|
+
const invocation = this.requireInvocation();
|
|
98
|
+
return Object.freeze((await this.runtime().roots(invocation)).map((descriptor) => this.handle(descriptor, invocation)));
|
|
99
|
+
}
|
|
100
|
+
runtime() {
|
|
101
|
+
if (!this.agentRuntime)
|
|
102
|
+
throw new Error('Plugin Agent Runtime is unavailable');
|
|
103
|
+
return this.agentRuntime;
|
|
104
|
+
}
|
|
105
|
+
handle(descriptor, invocation = this.requireInvocation()) {
|
|
106
|
+
const service = this;
|
|
107
|
+
const id = assertId(descriptor.id);
|
|
108
|
+
return Object.freeze({
|
|
109
|
+
...descriptor,
|
|
110
|
+
id,
|
|
111
|
+
followup: (message) => service.runtime().followup(id, message, invocation),
|
|
112
|
+
steer: (message) => service.runtime().steer(id, message, invocation),
|
|
113
|
+
inject: (message) => service.runtime().inject(id, message, invocation),
|
|
114
|
+
cancel: () => service.runtime().cancel(id, invocation),
|
|
115
|
+
whenIdle: (signal) => service
|
|
116
|
+
.runtime()
|
|
117
|
+
.whenIdle(id, pluginInvocationSignal(invocation.abortSignal, signal), invocation),
|
|
118
|
+
snapshot: () => service.runtime().snapshot(id, invocation),
|
|
119
|
+
inbox: () => service.runtime().inbox(id, invocation),
|
|
120
|
+
result: () => service.runtime().result(id, invocation),
|
|
121
|
+
artifacts: () => service.runtime().artifacts(id, invocation),
|
|
122
|
+
transcript: () => service.runtime().transcript(id, invocation),
|
|
123
|
+
dispose: () => service.runtime().dispose(id, invocation),
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function assertId(id) {
|
|
128
|
+
if (!id || /[\0\r\n]/u.test(id))
|
|
129
|
+
throw new TypeError('Agent id is invalid');
|
|
130
|
+
return id;
|
|
131
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Licensed to the Apache Software Foundation (ASF) under one
|
|
3
|
+
* or more contributor license agreements. See the NOTICE file
|
|
4
|
+
* distributed with this work for additional information
|
|
5
|
+
* regarding copyright ownership. The ASF licenses this file
|
|
6
|
+
* to you under the Apache License, Version 2.0 (the
|
|
7
|
+
* "License"); you may not use this file except in compliance
|
|
8
|
+
* with the License. You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing,
|
|
13
|
+
* software distributed under the License is distributed on an
|
|
14
|
+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
15
|
+
* KIND, either express or implied. See the License for the
|
|
16
|
+
* specific language governing permissions and limitations
|
|
17
|
+
* under the License.
|
|
18
|
+
*/
|
|
19
|
+
import { Service } from './plugin-kernel.js';
|
|
20
|
+
/** Permission request surface backed by Maka's durable Sandbox Boundary authority. */
|
|
21
|
+
export class PluginApprovalService extends Service {
|
|
22
|
+
agents;
|
|
23
|
+
constructor(ctx, agents) {
|
|
24
|
+
super(ctx, 'approval');
|
|
25
|
+
this.agents = agents;
|
|
26
|
+
}
|
|
27
|
+
request(request) {
|
|
28
|
+
const ask = this.agents.requireInvocation().toolContext?.requestSandboxBoundary;
|
|
29
|
+
if (!ask)
|
|
30
|
+
throw new Error('Approval is unavailable on this Agent surface');
|
|
31
|
+
return ask(request.expansion, request.justification);
|
|
32
|
+
}
|
|
33
|
+
}
|