maka-agent 0.2.0-dev.24.20260907 → 0.2.0-dev.25.20260908
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/README.md +38 -19
- package/README.zh-CN.md +34 -19
- package/dist/pi-transcript-tools.js +6 -0
- package/dist/pi-tui-layout.js +56 -10
- package/dist/pi-tui-pickers.js +102 -1
- package/dist/pi-tui-runner.js +156 -42
- package/dist/pi-tui-todo.js +221 -0
- package/dist/pi-tui-transcript-viewer.js +134 -7
- package/dist/runtime-host-cli-context.js +70 -13
- package/dist/runtime-host-handoff-surface.js +51 -26
- package/dist/runtime-host-local-handoff.js +11 -1
- package/dist/runtime-host-service-manager.js +0 -3
- package/dist/runtime-host-session-channel.js +13 -0
- package/dist/runtime-host-session-driver.js +42 -1
- package/dist/tui-copy-catalog.js +79 -3
- package/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
- package/node_modules/@maka/core/dist/agent-run.js +1 -0
- package/node_modules/@maka/core/dist/attachments.js +3 -0
- package/node_modules/@maka/core/dist/canonical-json.js +27 -0
- package/node_modules/@maka/core/dist/capabilities.js +35 -0
- package/node_modules/@maka/core/dist/computer-use.js +0 -1
- package/node_modules/@maka/core/dist/display-redaction.js +18 -0
- package/node_modules/@maka/core/dist/llm-connections.js +13 -0
- package/node_modules/@maka/core/dist/model-call-attempt.js +2 -0
- package/node_modules/@maka/core/dist/model-metadata.js +4 -0
- package/node_modules/@maka/core/dist/redaction.js +35 -0
- package/node_modules/@maka/core/dist/run-composition.js +77 -2
- package/node_modules/@maka/core/dist/session.js +30 -4
- package/node_modules/@maka/core/dist/slash-command-catalog.js +1 -0
- package/node_modules/@maka/core/dist/tool-result-record-schema.js +2 -1
- package/node_modules/@maka/core/package.json +1 -0
- package/node_modules/@maka/eval/dist/experiment-directory.js +4 -13
- package/node_modules/@maka/runtime/dist/agent-run-inspect.js +0 -13
- package/node_modules/@maka/runtime/dist/agent-run.js +80 -1
- package/node_modules/@maka/runtime/dist/ai-sdk-backend.js +16 -8
- package/node_modules/@maka/runtime/dist/ai-sdk-turn.js +57 -50
- package/node_modules/@maka/runtime/dist/archive-read-tool.js +2 -2
- package/node_modules/@maka/runtime/dist/context-budget-helpers.js +0 -16
- package/node_modules/@maka/runtime/dist/conversation-copy.js +153 -11
- package/node_modules/@maka/runtime/dist/github-copilot-oauth-enrollment.js +3 -3
- package/node_modules/@maka/runtime/dist/ledger-tool-result-archive-reader.js +69 -1
- package/node_modules/@maka/runtime/dist/mcp-tools.js +7 -2
- package/node_modules/@maka/runtime/dist/model-fetcher.js +42 -2
- package/node_modules/@maka/runtime/dist/model-history.js +0 -112
- package/node_modules/@maka/runtime/dist/plugin-runtime.js +20 -10
- package/node_modules/@maka/runtime/dist/plugin-tool-service.js +205 -0
- package/node_modules/@maka/runtime/dist/provider-request-telemetry.js +8 -1
- package/node_modules/@maka/runtime/dist/request-shape.js +23 -0
- package/node_modules/@maka/runtime/dist/runtime-event-backfill.js +1 -1
- package/node_modules/@maka/runtime/dist/runtime-event-read-model.js +4 -0
- package/node_modules/@maka/runtime/dist/runtime-kernel.js +7 -0
- package/node_modules/@maka/runtime/dist/stream-graph-coordinator.js +21 -0
- package/node_modules/@maka/runtime/dist/stream-graph-supervisor-tools.js +0 -5
- package/node_modules/@maka/runtime/dist/test-connection.js +0 -1
- package/node_modules/@maka/runtime/dist/tool-activation-identity.js +41 -0
- package/node_modules/@maka/runtime/dist/tool-availability.js +11 -1
- package/node_modules/@maka/runtime/dist/tool-result-archive-resource.js +63 -1
- package/node_modules/@maka/runtime/dist/tool-result-archive-transition.js +42 -12
- package/node_modules/@maka/runtime/dist/tool-result-archive.js +27 -4
- package/node_modules/@maka/runtime/package.json +1 -0
- package/node_modules/@maka/runtime-host/dist/client/host-handoff-copy.js +35 -12
- package/node_modules/@maka/runtime-host/dist/client/host-handoff.js +2 -0
- package/node_modules/@maka/runtime-host/dist/client/session-subscription.js +19 -0
- package/node_modules/@maka/runtime-host/dist/control/endpoint.js +1 -3
- package/node_modules/@maka/runtime-host/dist/node-error.js +22 -0
- package/node_modules/@maka/runtime-host/dist/operator/managed-deployment.js +1 -3
- package/node_modules/@maka/runtime-host/dist/peer-mesh/limits.js +0 -1
- package/node_modules/@maka/runtime-host/dist/peer-mesh/model.js +1 -1
- package/node_modules/@maka/runtime-host/dist/peer-reachability/publisher.js +1 -3
- package/node_modules/@maka/runtime-host/dist/protocol/index.js +5 -1
- package/node_modules/@maka/runtime-host/dist/protocol/plan.js +1 -0
- package/node_modules/@maka/runtime-host/dist/protocol/plugin-platform.js +27 -5
- package/node_modules/@maka/runtime-host/dist/protocol/project-catalog.js +2 -2
- package/node_modules/@maka/runtime-host/dist/protocol/workhub-coordination.js +31 -2
- package/node_modules/@maka/runtime-host/dist/server/agent-graph-coordinator.js +0 -3
- package/node_modules/@maka/runtime-host/dist/server/execution-artifacts.js +32 -32
- package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +44 -9
- package/node_modules/@maka/runtime-host/dist/server/execution-model-composition.js +42 -14
- package/node_modules/@maka/runtime-host/dist/server/interactive-run-composer.js +47 -22
- 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 +6 -0
- package/node_modules/@maka/runtime-host/dist/server/session-retirement-coordinator.js +5 -2
- package/node_modules/@maka/runtime-host/dist/server/session-revision-coordinator.js +4 -0
- package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-action-gate.js +20 -2
- package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-coordinator.js +13 -3
- package/node_modules/@maka/runtime-host/dist/server/workhub-message-attachments.js +46 -0
- package/node_modules/@maka/storage/dist/claude-code-session-adapter.js +0 -1
- package/node_modules/@maka/storage/dist/codex-session-adapter.js +284 -196
- package/node_modules/@maka/storage/dist/git-exec.js +61 -0
- package/node_modules/@maka/storage/dist/git-worktree-child-executor.js +8 -35
- package/node_modules/@maka/storage/dist/goal-authority.js +2 -2
- package/node_modules/@maka/storage/dist/interaction-store.js +2 -2
- package/node_modules/@maka/storage/dist/project-catalog.js +2 -23
- package/node_modules/@maka/storage/dist/runtime-event-invariants.js +2 -2
- package/node_modules/@maka/storage/dist/runtime-policy/connection-catalog-document.js +8 -3
- package/node_modules/@maka/storage/dist/scheduled-task-store.js +249 -283
- package/node_modules/@maka/storage/dist/session-bundle-manifest.js +5 -17
- package/node_modules/@maka/storage/dist/session-bundle-policy.js +2 -1
- package/node_modules/@maka/storage/dist/session-copy-cleanup.js +2 -1
- package/node_modules/@maka/storage/dist/sqlite-runtime-store.js +1 -2
- package/node_modules/@maka/storage/dist/storage-id.js +28 -0
- package/node_modules/@maka/storage/dist/tool-result-archive-evidence.js +31 -4
- package/node_modules/@maka/storage/dist/workspace-identity.js +2 -15
- package/node_modules/@maka/storage/dist/workspace-version-authority-internal.js +1 -8
- package/package.json +1 -1
|
@@ -269,10 +269,9 @@ function registerPluginEffect(ctx, label, register) {
|
|
|
269
269
|
}
|
|
270
270
|
export function registerPluginContribution(ctx, label, register) {
|
|
271
271
|
if (ctx.makaTransaction) {
|
|
272
|
-
ctx.makaTransaction.stage(label, register, ctx);
|
|
273
|
-
return;
|
|
272
|
+
return ctx.makaTransaction.stage(label, register, ctx);
|
|
274
273
|
}
|
|
275
|
-
registerPluginEffect(ctx, label, register);
|
|
274
|
+
return registerPluginEffect(ctx, label, register);
|
|
276
275
|
}
|
|
277
276
|
export class MakaPluginTransactionBuffer {
|
|
278
277
|
context;
|
|
@@ -283,13 +282,22 @@ export class MakaPluginTransactionBuffer {
|
|
|
283
282
|
}
|
|
284
283
|
stage(label, register, owner = this.context) {
|
|
285
284
|
if (this.#state === 'committed') {
|
|
286
|
-
registerPluginEffect(owner, label, register);
|
|
287
|
-
return;
|
|
285
|
+
return registerPluginEffect(owner, label, register);
|
|
288
286
|
}
|
|
289
287
|
if (this.#state === 'rolled_back') {
|
|
290
288
|
throw new MakaPluginRuntimeError('activation_failed', `Cannot stage contribution after transaction is ${this.#state}`);
|
|
291
289
|
}
|
|
292
|
-
|
|
290
|
+
const item = {
|
|
291
|
+
label,
|
|
292
|
+
register,
|
|
293
|
+
owner,
|
|
294
|
+
cancelled: false,
|
|
295
|
+
};
|
|
296
|
+
this.#registrations.push(item);
|
|
297
|
+
return async () => {
|
|
298
|
+
item.cancelled = true;
|
|
299
|
+
await item.release?.();
|
|
300
|
+
};
|
|
293
301
|
}
|
|
294
302
|
async commit() {
|
|
295
303
|
if (this.#state === 'committed')
|
|
@@ -300,7 +308,10 @@ export class MakaPluginTransactionBuffer {
|
|
|
300
308
|
const registered = [];
|
|
301
309
|
try {
|
|
302
310
|
for (const item of this.#registrations) {
|
|
303
|
-
|
|
311
|
+
if (item.cancelled)
|
|
312
|
+
continue;
|
|
313
|
+
item.release = registerPluginEffect(item.owner, item.label, item.register);
|
|
314
|
+
registered.push(item.release);
|
|
304
315
|
}
|
|
305
316
|
this.#state = 'committed';
|
|
306
317
|
this.#registrations.length = 0;
|
|
@@ -333,10 +344,9 @@ export class MakaPluginTransactionBuffer {
|
|
|
333
344
|
export function fiberStateName(state) {
|
|
334
345
|
return ['pending', 'loading', 'active', 'failed', 'disposed', 'unloading'][state];
|
|
335
346
|
}
|
|
336
|
-
export function
|
|
347
|
+
export function isCanonicalExtensionId(value) {
|
|
337
348
|
return typeof value === 'string' && value.length <= 128 && ID_PATTERN.test(value);
|
|
338
349
|
}
|
|
339
|
-
export const isCanonicalExtensionId = isCanonicalPluginId;
|
|
340
350
|
function cloneCompositionEntry(entry) {
|
|
341
351
|
return {
|
|
342
352
|
...entry,
|
|
@@ -384,7 +394,7 @@ export function isCanonicalExtensionScopeId(value) {
|
|
|
384
394
|
return (typeof value === 'string' && value.length <= 128 && /^[A-Za-z0-9][A-Za-z0-9._:-]*$/u.test(value));
|
|
385
395
|
}
|
|
386
396
|
function validatePluginId(value, label) {
|
|
387
|
-
if (!
|
|
397
|
+
if (!isCanonicalExtensionId(value)) {
|
|
388
398
|
throw new MakaPluginRuntimeError('invalid_entry', `Invalid ${label}`);
|
|
389
399
|
}
|
|
390
400
|
}
|
|
@@ -0,0 +1,205 @@
|
|
|
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 { REQUEST_COMPOSITION_MAX_TOOL_DESCRIPTION_LENGTH } from '@maka/core/run-composition';
|
|
20
|
+
import { Service } from './plugin-kernel.js';
|
|
21
|
+
import { MakaPluginRuntimeError, pluginIdentity, registerPluginContribution, } from './plugin-runtime.js';
|
|
22
|
+
import { bindToolActivationIdentity } from './tool-activation-identity.js';
|
|
23
|
+
import { TOOL_SEARCH_NAME, TOOL_SEARCH_PROVIDER_NAME } from './tool-availability.js';
|
|
24
|
+
/**
|
|
25
|
+
* Context-scoped Tool contribution registry for trusted Host plugins.
|
|
26
|
+
*
|
|
27
|
+
* Registration is staged by the Plugin Platform transaction and owned by the
|
|
28
|
+
* registering Fiber. Profile registrations are inherited by Session roots;
|
|
29
|
+
* an exact Session registration shadows the Profile registration. Core tools
|
|
30
|
+
* remain Host-owned and cannot be shadowed.
|
|
31
|
+
*/
|
|
32
|
+
export class PluginToolService extends Service {
|
|
33
|
+
layers = new Map();
|
|
34
|
+
onChanged;
|
|
35
|
+
constructor(ctx, options = {}) {
|
|
36
|
+
super(ctx, 'tools');
|
|
37
|
+
this.onChanged = options.onChanged;
|
|
38
|
+
}
|
|
39
|
+
register(definition) {
|
|
40
|
+
const identity = pluginIdentity(this.ctx);
|
|
41
|
+
if (identity.scopeId === 'desktop-ui') {
|
|
42
|
+
throw new MakaPluginRuntimeError('activation_failed', 'desktop-ui plugins cannot register Host tools');
|
|
43
|
+
}
|
|
44
|
+
validateTool(definition);
|
|
45
|
+
return registerPluginContribution(this.ctx, `tools.register(${JSON.stringify(definition.name)})`, () => this.publish(identity, definition));
|
|
46
|
+
}
|
|
47
|
+
resolve(sessionId, coreTools) {
|
|
48
|
+
const contributions = this.resolveContributions(sessionId, coreTools);
|
|
49
|
+
return Object.freeze({
|
|
50
|
+
tools: Object.freeze([...coreTools, ...contributions.tools]),
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/** Resolve only Plugin-owned additions after validating them against the Host binding. */
|
|
54
|
+
resolveContributions(sessionId, coreTools) {
|
|
55
|
+
if (!sessionId || /[\r\n\0]/u.test(sessionId))
|
|
56
|
+
throw new Error('Invalid Tool Session scope');
|
|
57
|
+
const visible = new Map();
|
|
58
|
+
for (const entry of this.layers.get('profile')?.values() ?? []) {
|
|
59
|
+
visible.set(entry.definition.name, entry);
|
|
60
|
+
}
|
|
61
|
+
const sessionRoot = `session:${sessionId}`;
|
|
62
|
+
for (const entry of this.layers.get(sessionRoot)?.values() ?? []) {
|
|
63
|
+
visible.set(entry.definition.name, entry);
|
|
64
|
+
}
|
|
65
|
+
const coreNames = new Set(coreTools.map(({ name }) => name));
|
|
66
|
+
for (const name of visible.keys()) {
|
|
67
|
+
if (coreNames.has(name)) {
|
|
68
|
+
throw new MakaPluginRuntimeError('activation_failed', `Plugin Tool ${JSON.stringify(name)} conflicts with a Host-owned Tool`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const entries = [...visible.values()].sort(compareRegistration);
|
|
72
|
+
return Object.freeze({
|
|
73
|
+
tools: Object.freeze(entries.map(({ exposed }) => exposed)),
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
inspect(rootId) {
|
|
77
|
+
const layers = rootId
|
|
78
|
+
? [[rootId, this.layers.get(rootId)]]
|
|
79
|
+
: [...this.layers.entries()];
|
|
80
|
+
return Object.freeze(layers
|
|
81
|
+
.flatMap(([, layer]) => [...(layer?.values() ?? [])])
|
|
82
|
+
.sort(compareRegistration)
|
|
83
|
+
.map((entry) => Object.freeze({
|
|
84
|
+
entryId: entry.entryId,
|
|
85
|
+
scopeId: entry.scopeId,
|
|
86
|
+
extensionId: entry.extensionId,
|
|
87
|
+
generation: entry.generation,
|
|
88
|
+
toolName: entry.definition.name,
|
|
89
|
+
activeCalls: entry.activeCalls,
|
|
90
|
+
retired: entry.retired,
|
|
91
|
+
})));
|
|
92
|
+
}
|
|
93
|
+
publish(identity, definition) {
|
|
94
|
+
const rootId = identity.scopeId;
|
|
95
|
+
let layer = this.layers.get(rootId);
|
|
96
|
+
if (!layer) {
|
|
97
|
+
layer = new Map();
|
|
98
|
+
this.layers.set(rootId, layer);
|
|
99
|
+
}
|
|
100
|
+
const existing = layer.get(definition.name);
|
|
101
|
+
if (existing && existing.entryId !== identity.entryId) {
|
|
102
|
+
throw new MakaPluginRuntimeError('activation_failed', `Plugin Tool ${JSON.stringify(definition.name)} is already registered by ${existing.entryId}`);
|
|
103
|
+
}
|
|
104
|
+
let entry;
|
|
105
|
+
const exposed = bindToolActivationIdentity({
|
|
106
|
+
...definition,
|
|
107
|
+
impl: async (args, context) => {
|
|
108
|
+
if (entry.retired) {
|
|
109
|
+
throw new Error(`Plugin Tool ${JSON.stringify(definition.name)} is no longer active`);
|
|
110
|
+
}
|
|
111
|
+
entry.activeCalls += 1;
|
|
112
|
+
try {
|
|
113
|
+
return await definition.impl(args, context);
|
|
114
|
+
}
|
|
115
|
+
finally {
|
|
116
|
+
entry.activeCalls -= 1;
|
|
117
|
+
if (entry.activeCalls === 0) {
|
|
118
|
+
for (const resolve of entry.drainWaiters)
|
|
119
|
+
resolve();
|
|
120
|
+
entry.drainWaiters.clear();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
}, {
|
|
125
|
+
kind: 'plugin',
|
|
126
|
+
scopeId: identity.scopeId,
|
|
127
|
+
entryId: identity.entryId,
|
|
128
|
+
extensionId: identity.extensionId,
|
|
129
|
+
generation: identity.generation,
|
|
130
|
+
toolName: definition.name,
|
|
131
|
+
});
|
|
132
|
+
entry = {
|
|
133
|
+
...identity,
|
|
134
|
+
definition,
|
|
135
|
+
exposed,
|
|
136
|
+
token: Symbol(definition.name),
|
|
137
|
+
activeCalls: 0,
|
|
138
|
+
retired: false,
|
|
139
|
+
drainWaiters: new Set(),
|
|
140
|
+
};
|
|
141
|
+
layer.set(definition.name, entry);
|
|
142
|
+
try {
|
|
143
|
+
this.notifyChanged(rootId);
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
if (existing)
|
|
147
|
+
layer.set(definition.name, existing);
|
|
148
|
+
else
|
|
149
|
+
layer.delete(definition.name);
|
|
150
|
+
if (layer.size === 0)
|
|
151
|
+
this.layers.delete(rootId);
|
|
152
|
+
throw error;
|
|
153
|
+
}
|
|
154
|
+
return async () => {
|
|
155
|
+
entry.retired = true;
|
|
156
|
+
const currentLayer = this.layers.get(rootId);
|
|
157
|
+
if (currentLayer?.get(definition.name)?.token === entry.token) {
|
|
158
|
+
if (existing && !existing.retired)
|
|
159
|
+
currentLayer.set(definition.name, existing);
|
|
160
|
+
else
|
|
161
|
+
currentLayer.delete(definition.name);
|
|
162
|
+
if (currentLayer.size === 0)
|
|
163
|
+
this.layers.delete(rootId);
|
|
164
|
+
this.notifyChanged(rootId);
|
|
165
|
+
}
|
|
166
|
+
if (entry.activeCalls > 0) {
|
|
167
|
+
await new Promise((resolve) => entry.drainWaiters.add(resolve));
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
notifyChanged(rootId) {
|
|
172
|
+
this.ctx.emit('tools/change');
|
|
173
|
+
this.onChanged?.(rootId);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
function validateTool(tool) {
|
|
177
|
+
if (!tool || typeof tool !== 'object')
|
|
178
|
+
throw new TypeError('Tool definition is required');
|
|
179
|
+
if (typeof tool.name !== 'string' ||
|
|
180
|
+
tool.name.length === 0 ||
|
|
181
|
+
tool.name.length > 128 ||
|
|
182
|
+
/[\r\n\0]/u.test(tool.name)) {
|
|
183
|
+
throw new TypeError('Tool requires a valid name');
|
|
184
|
+
}
|
|
185
|
+
if (typeof tool.description !== 'string' ||
|
|
186
|
+
tool.description.length === 0 ||
|
|
187
|
+
tool.description.length > REQUEST_COMPOSITION_MAX_TOOL_DESCRIPTION_LENGTH ||
|
|
188
|
+
typeof tool.impl !== 'function') {
|
|
189
|
+
throw new TypeError(`Tool ${JSON.stringify(tool.name)} requires a description of at most ${REQUEST_COMPOSITION_MAX_TOOL_DESCRIPTION_LENGTH} characters and an implementation`);
|
|
190
|
+
}
|
|
191
|
+
if (tool.parameters === undefined) {
|
|
192
|
+
throw new TypeError(`Tool ${JSON.stringify(tool.name)} requires an input schema`);
|
|
193
|
+
}
|
|
194
|
+
if (tool.providerTool) {
|
|
195
|
+
throw new TypeError(`Plugin Tool ${JSON.stringify(tool.name)} cannot claim a provider protocol`);
|
|
196
|
+
}
|
|
197
|
+
if (tool.name === TOOL_SEARCH_NAME || tool.name === TOOL_SEARCH_PROVIDER_NAME) {
|
|
198
|
+
throw new TypeError(`Plugin Tool name ${JSON.stringify(tool.name)} is reserved by Runtime`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
function compareRegistration(left, right) {
|
|
202
|
+
return (left.definition.name.localeCompare(right.definition.name) ||
|
|
203
|
+
left.scopeId.localeCompare(right.scopeId) ||
|
|
204
|
+
left.entryId.localeCompare(right.entryId));
|
|
205
|
+
}
|
|
@@ -199,14 +199,18 @@ export class ProviderRequestTracker {
|
|
|
199
199
|
* that call, not new calls, so they share this id.
|
|
200
200
|
*/
|
|
201
201
|
logicalCallIdByStep = new Map();
|
|
202
|
+
requestCompositionIdByStep = new Map();
|
|
202
203
|
constructor(input) {
|
|
203
204
|
this.input = input;
|
|
204
205
|
}
|
|
205
206
|
get traceId() {
|
|
206
207
|
return this.input.traceId;
|
|
207
208
|
}
|
|
208
|
-
setStep(step) {
|
|
209
|
+
setStep(step, requestCompositionId) {
|
|
209
210
|
this.step = step;
|
|
211
|
+
if (requestCompositionId !== undefined) {
|
|
212
|
+
this.requestCompositionIdByStep.set(step, requestCompositionId);
|
|
213
|
+
}
|
|
210
214
|
}
|
|
211
215
|
async trackStream(input) {
|
|
212
216
|
throwIfAbortedBeforeDispatch(input.abortSignal);
|
|
@@ -356,6 +360,9 @@ export class ProviderRequestTracker {
|
|
|
356
360
|
? { connectionSlug: accounting.connectionSlug }
|
|
357
361
|
: {}),
|
|
358
362
|
step: Math.max(0, step),
|
|
363
|
+
...(this.requestCompositionIdByStep.get(step)
|
|
364
|
+
? { requestCompositionId: this.requestCompositionIdByStep.get(step) }
|
|
365
|
+
: {}),
|
|
359
366
|
attempt: Math.max(0, attempt - 1),
|
|
360
367
|
callKind: accounting.callKind,
|
|
361
368
|
...((input.historyCompactRoute ?? accounting.historyCompactRoute) !== undefined
|
|
@@ -152,6 +152,29 @@ export function toolCatalogHash(tools) {
|
|
|
152
152
|
.sort((left, right) => (left.name < right.name ? -1 : left.name > right.name ? 1 : 0))
|
|
153
153
|
.map(toolShapeForDiagnostics));
|
|
154
154
|
}
|
|
155
|
+
/** Canonical, JSON-safe schemas for the exact provider-visible tool subset. */
|
|
156
|
+
export function requestCompositionToolSchemas(tools, activeToolNames) {
|
|
157
|
+
const active = new Set(activeToolNames);
|
|
158
|
+
return tools
|
|
159
|
+
.filter((tool) => active.has(tool.name))
|
|
160
|
+
.map((tool) => {
|
|
161
|
+
const inputSchema = JSON.parse(stableStringify(schemaShapeForHash(tool.parameters)));
|
|
162
|
+
if (!isPlainObject(inputSchema)) {
|
|
163
|
+
throw new Error(`Tool ${JSON.stringify(tool.name)} produced a non-object input schema`);
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
name: tool.name,
|
|
167
|
+
description: tool.description,
|
|
168
|
+
inputSchema,
|
|
169
|
+
...(tool.providerTool
|
|
170
|
+
? {
|
|
171
|
+
providerTool: JSON.parse(stableStringify(tool.providerTool)),
|
|
172
|
+
}
|
|
173
|
+
: {}),
|
|
174
|
+
};
|
|
175
|
+
})
|
|
176
|
+
.sort((left, right) => (left.name < right.name ? -1 : left.name > right.name ? 1 : 0));
|
|
177
|
+
}
|
|
155
178
|
export function stableStringify(value) {
|
|
156
179
|
return JSON.stringify(canonicalize(value));
|
|
157
180
|
}
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import { isRuntimeSystemNoteKind } from '@maka/core/session';
|
|
20
20
|
import { createRuntimeEventId } from '@maka/core/runtime-event';
|
|
21
|
-
|
|
21
|
+
const RUNTIME_EVENT_BACKFILL_STATE_KEY = 'makaRuntimeRecovery';
|
|
22
22
|
export function backfillRuntimeEventsFromStoredMessages(input) {
|
|
23
23
|
const newId = input.newId ?? (() => createRuntimeEventId('rt-backfill'));
|
|
24
24
|
const now = input.now ?? (() => Date.now());
|
|
@@ -357,6 +357,7 @@ export function applyArchivedToolResultReadModelStatuses(events, archiveStatuses
|
|
|
357
357
|
toolCallId: placeholder.toolCallId,
|
|
358
358
|
toolName: placeholder.toolName,
|
|
359
359
|
artifactId: placeholder.artifactId,
|
|
360
|
+
...(placeholder.rewriteVersion === 2 ? { resourceRef: placeholder.resourceRef } : {}),
|
|
360
361
|
bodySha256: placeholder.bodySha256,
|
|
361
362
|
originalEstimatedTokens: placeholder.originalEstimatedTokens,
|
|
362
363
|
originalBytes: placeholder.originalBytes,
|
|
@@ -658,6 +659,9 @@ function projectFunctionResponse(event, state, messages) {
|
|
|
658
659
|
toolName: archivedPlaceholder.toolName,
|
|
659
660
|
artifactId: archivedPlaceholder.artifactId,
|
|
660
661
|
bodySha256: archivedPlaceholder.bodySha256,
|
|
662
|
+
...(archivedPlaceholder.rewriteVersion === 2
|
|
663
|
+
? { resourceRef: archivedPlaceholder.resourceRef }
|
|
664
|
+
: {}),
|
|
661
665
|
originalEstimatedTokens: archivedPlaceholder.originalEstimatedTokens,
|
|
662
666
|
originalBytes: archivedPlaceholder.originalBytes,
|
|
663
667
|
rewriteVersion: archivedPlaceholder.rewriteVersion,
|
|
@@ -1694,6 +1694,13 @@ export class RuntimeKernel {
|
|
|
1694
1694
|
}
|
|
1695
1695
|
return run.recordRunComposition(snapshot);
|
|
1696
1696
|
},
|
|
1697
|
+
recordRequestComposition: (runId, snapshot) => {
|
|
1698
|
+
const run = this.active.get(sessionId)?.activeRuns.get(runId);
|
|
1699
|
+
if (!run) {
|
|
1700
|
+
return Promise.reject(new Error('No active AgentRun for Request Composition'));
|
|
1701
|
+
}
|
|
1702
|
+
return run.recordRequestComposition(snapshot);
|
|
1703
|
+
},
|
|
1697
1704
|
loadHistoryCompactCheckpoint: () => this.historyCompactCoordinator.load(sessionId),
|
|
1698
1705
|
recordHistoryCompactCheckpoint: (checkpoint, turnId) => this.historyCompactCoordinator.record(sessionId, checkpoint, runFor(turnId)),
|
|
1699
1706
|
loadModelProjectionTransitions: async () => loadModelProjectionTransitionsFromRunLedger(this.deps.runStore, sessionId, await this.sessionRunIds(sessionId)),
|
|
@@ -184,6 +184,27 @@ export class AgentGraphCoordinator {
|
|
|
184
184
|
async hasLiveSessionState(rootSessionId) {
|
|
185
185
|
return (await this.readSessionState(rootSessionId)) === 'live';
|
|
186
186
|
}
|
|
187
|
+
/**
|
|
188
|
+
* Classify durable graph state for Session retirement without changing the
|
|
189
|
+
* broader live-state semantics used by recovery and graph epoch selection.
|
|
190
|
+
*/
|
|
191
|
+
async readRetirementDisposition(rootSessionId) {
|
|
192
|
+
const snapshot = buildAgentGraphClientSnapshot(await this.#readClientModelInputForGraph(rootSessionId, await this.currentGraphId(rootSessionId)));
|
|
193
|
+
if (snapshot.scheduleRevision === 0)
|
|
194
|
+
return { kind: 'clear' };
|
|
195
|
+
switch (snapshot.status) {
|
|
196
|
+
case 'empty':
|
|
197
|
+
case 'completed':
|
|
198
|
+
return { kind: 'clear' };
|
|
199
|
+
case 'stopped':
|
|
200
|
+
case 'failed':
|
|
201
|
+
return { kind: 'quiescent_open' };
|
|
202
|
+
case 'active':
|
|
203
|
+
case 'waiting':
|
|
204
|
+
case 'closing':
|
|
205
|
+
return { kind: 'busy', status: snapshot.status };
|
|
206
|
+
}
|
|
207
|
+
}
|
|
187
208
|
/**
|
|
188
209
|
* Reconstruct one stable, reference-only control/data-plane timeline page.
|
|
189
210
|
*
|
|
@@ -22,11 +22,6 @@ import { stableHash } from './request-shape.js';
|
|
|
22
22
|
export const VIEW_AGENT_GRAPH_TOOL_NAME = 'view_agent_graph';
|
|
23
23
|
export const UPDATE_AGENT_GRAPH_TOOL_NAME = 'update_agent_graph';
|
|
24
24
|
export const YIELD_AGENT_GRAPH_TOOL_NAME = 'yield_agent_graph';
|
|
25
|
-
export const AGENT_GRAPH_SUPERVISOR_TOOL_NAMES = [
|
|
26
|
-
VIEW_AGENT_GRAPH_TOOL_NAME,
|
|
27
|
-
UPDATE_AGENT_GRAPH_TOOL_NAME,
|
|
28
|
-
YIELD_AGENT_GRAPH_TOOL_NAME,
|
|
29
|
-
];
|
|
30
25
|
const TOOL_VIEW_MAX_TERMINAL_WORK = 64;
|
|
31
26
|
const TOOL_VIEW_MAX_STOPPED_TARGETS = 64;
|
|
32
27
|
const TOOL_VIEW_MAX_INSTRUCTION_CHARS = 2_000;
|
|
@@ -0,0 +1,41 @@
|
|
|
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 { stableHash, toolCatalogHash } from './request-shape.js';
|
|
20
|
+
const TOOL_ACTIVATION_IDENTITY = Symbol('maka.toolActivationIdentity');
|
|
21
|
+
/** Bind a Runtime-owned contribution identity to a Tool without exposing it to providers. */
|
|
22
|
+
export function bindToolActivationIdentity(tool, identity) {
|
|
23
|
+
return Object.freeze({
|
|
24
|
+
...tool,
|
|
25
|
+
[TOOL_ACTIVATION_IDENTITY]: stableHash({
|
|
26
|
+
identity,
|
|
27
|
+
schemaHash: toolCatalogHash([tool]),
|
|
28
|
+
}),
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Stable logical identity used by deferred-tool activation.
|
|
33
|
+
*
|
|
34
|
+
* Host wrappers without explicit contribution metadata fall back to their
|
|
35
|
+
* canonical provider-visible shape, so rebuilding an equivalent wrapper does
|
|
36
|
+
* not revoke activation. Dynamic contributors bind generation-aware metadata.
|
|
37
|
+
*/
|
|
38
|
+
export function toolActivationKey(tool) {
|
|
39
|
+
const explicit = tool[TOOL_ACTIVATION_IDENTITY];
|
|
40
|
+
return explicit ?? stableHash({ kind: 'host', schemaHash: toolCatalogHash([tool]) });
|
|
41
|
+
}
|
|
@@ -20,6 +20,7 @@ import MiniSearch from 'minisearch';
|
|
|
20
20
|
import { z } from 'zod';
|
|
21
21
|
import { estimateTokens } from './context-budget-helpers.js';
|
|
22
22
|
import { canonicalizeToolSet, stableHash, toolSchemaCharsForDiagnostics } from './request-shape.js';
|
|
23
|
+
import { toolActivationKey } from './tool-activation-identity.js';
|
|
23
24
|
/** Canonical name of Maka's provider-independent deferred-tool search connector. */
|
|
24
25
|
export const TOOL_SEARCH_NAME = 'tool_search';
|
|
25
26
|
/** Provider-safe alias used because OpenAI Responses reserves `tool_search`. */
|
|
@@ -101,6 +102,7 @@ export class ToolAvailabilityRuntime {
|
|
|
101
102
|
invalidTool;
|
|
102
103
|
tools;
|
|
103
104
|
toolsByName;
|
|
105
|
+
activationKeysByName;
|
|
104
106
|
groups;
|
|
105
107
|
searchableNames;
|
|
106
108
|
directNames;
|
|
@@ -115,6 +117,7 @@ export class ToolAvailabilityRuntime {
|
|
|
115
117
|
}
|
|
116
118
|
this.tools = [...tools];
|
|
117
119
|
this.toolsByName = new Map(tools.map((tool) => [tool.name, tool]));
|
|
120
|
+
this.activationKeysByName = new Map(tools.map((tool) => [tool.name, toolActivationKey(tool)]));
|
|
118
121
|
const known = new Set(this.toolsByName.keys());
|
|
119
122
|
const searchable = config === undefined
|
|
120
123
|
? new Set()
|
|
@@ -240,6 +243,13 @@ export class ToolAvailabilityRuntime {
|
|
|
240
243
|
const allTools = [...this.tools, connector];
|
|
241
244
|
const canonical = canonicalizeToolSet(allTools, this.invalidTool);
|
|
242
245
|
const knownNames = new Set(canonical.providerTools.map((tool) => tool.name));
|
|
246
|
+
// Activation belongs to a stable logical contribution, not a temporary
|
|
247
|
+
// wrapper object or merely its name. Equivalent Host wrappers survive
|
|
248
|
+
// per-step rebuilding; a replaced Plugin generation does not.
|
|
249
|
+
for (const [name, activatedKey] of activeTools) {
|
|
250
|
+
if (this.activationKeysByName.get(name) !== activatedKey)
|
|
251
|
+
activeTools.delete(name);
|
|
252
|
+
}
|
|
243
253
|
const requiredNames = [...requiredToolNames].filter((name) => knownNames.has(name));
|
|
244
254
|
const step = { active: new Set() };
|
|
245
255
|
const computeActive = () => {
|
|
@@ -308,7 +318,7 @@ export class ToolAvailabilityRuntime {
|
|
|
308
318
|
schemaChars += chars;
|
|
309
319
|
}
|
|
310
320
|
for (const name of activated)
|
|
311
|
-
activeTools.set(name, this.
|
|
321
|
+
activeTools.set(name, this.activationKeysByName.get(name));
|
|
312
322
|
const result = {
|
|
313
323
|
activated,
|
|
314
324
|
...(blocked ? { blocked } : {}),
|
|
@@ -35,12 +35,72 @@ const MAX_SEARCH_SNIPPET_CHARS = 240;
|
|
|
35
35
|
const MAX_SEARCH_PATTERN_CHARS = 256;
|
|
36
36
|
/** Preview length surfaced by inspect for text/object payloads. */
|
|
37
37
|
const INSPECT_PREVIEW_CHARS = 600;
|
|
38
|
+
export function isLedgerArchiveIdentity(value) {
|
|
39
|
+
if (!isRecord(value))
|
|
40
|
+
return false;
|
|
41
|
+
return (value.storage === 'ledger' &&
|
|
42
|
+
value.artifactId === undefined &&
|
|
43
|
+
['runtimeEventId', 'toolCallId', 'toolName'].every((key) => typeof value[key] === 'string' &&
|
|
44
|
+
value[key].length > 0 &&
|
|
45
|
+
value[key].length <= 512) &&
|
|
46
|
+
typeof value.sourceProjectionDigest === 'string' &&
|
|
47
|
+
/^sha256:[a-f0-9]{64}$/.test(value.sourceProjectionDigest) &&
|
|
48
|
+
(value.previousTransitionId === undefined ||
|
|
49
|
+
(typeof value.previousTransitionId === 'string' &&
|
|
50
|
+
/^mptransition-[a-f0-9]{32}$/.test(value.previousTransitionId))) &&
|
|
51
|
+
typeof value.bodySha256 === 'string' &&
|
|
52
|
+
/^[a-f0-9]{64}$/.test(value.bodySha256) &&
|
|
53
|
+
Number.isSafeInteger(value.originalBytes) &&
|
|
54
|
+
Number(value.originalBytes) > 0);
|
|
55
|
+
}
|
|
38
56
|
export function buildToolResultArchiveResourceRef(input) {
|
|
57
|
+
if (input.storage === 'ledger') {
|
|
58
|
+
if (!isLedgerArchiveIdentity(input))
|
|
59
|
+
throw new Error('Invalid ledger archive identity');
|
|
60
|
+
const value = [
|
|
61
|
+
input.runtimeEventId,
|
|
62
|
+
input.toolCallId,
|
|
63
|
+
input.toolName,
|
|
64
|
+
input.sourceProjectionDigest,
|
|
65
|
+
input.previousTransitionId ?? null,
|
|
66
|
+
input.bodySha256,
|
|
67
|
+
input.originalBytes,
|
|
68
|
+
];
|
|
69
|
+
return `maka://archive-ledger/v1/${encodeURIComponent(JSON.stringify(value))}`;
|
|
70
|
+
}
|
|
39
71
|
const artifactId = encodeURIComponent(input.artifactId);
|
|
40
72
|
const sha256 = encodeURIComponent(input.bodySha256);
|
|
41
73
|
return `maka://archive/${artifactId}/${sha256}/${input.originalBytes}`;
|
|
42
74
|
}
|
|
43
75
|
export function parseToolResultArchiveResourceRef(ref) {
|
|
76
|
+
if (ref.startsWith('maka://archive-ledger/')) {
|
|
77
|
+
try {
|
|
78
|
+
const prefix = 'maka://archive-ledger/v1/';
|
|
79
|
+
if (!ref.startsWith(prefix) || ref.length > 16384)
|
|
80
|
+
return null;
|
|
81
|
+
const values = JSON.parse(decodeURIComponent(ref.slice(prefix.length)));
|
|
82
|
+
if (!Array.isArray(values) || values.length !== 7)
|
|
83
|
+
return null;
|
|
84
|
+
const [runtimeEventId, toolCallId, toolName, sourceProjectionDigest, previous, bodySha256, originalBytes,] = values;
|
|
85
|
+
const identity = {
|
|
86
|
+
storage: 'ledger',
|
|
87
|
+
runtimeEventId,
|
|
88
|
+
toolCallId,
|
|
89
|
+
toolName,
|
|
90
|
+
sourceProjectionDigest,
|
|
91
|
+
...(previous === null ? {} : { previousTransitionId: previous }),
|
|
92
|
+
bodySha256,
|
|
93
|
+
originalBytes,
|
|
94
|
+
};
|
|
95
|
+
return isLedgerArchiveIdentity(identity) &&
|
|
96
|
+
buildToolResultArchiveResourceRef(identity) === ref
|
|
97
|
+
? identity
|
|
98
|
+
: null;
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
44
104
|
let url;
|
|
45
105
|
try {
|
|
46
106
|
url = new URL(ref);
|
|
@@ -162,7 +222,9 @@ function inspectArchive(ref, identity, value, serializedResult) {
|
|
|
162
222
|
kind: 'tool_result_archive',
|
|
163
223
|
operation: 'inspect',
|
|
164
224
|
ref,
|
|
165
|
-
|
|
225
|
+
...(identity.storage === 'ledger'
|
|
226
|
+
? { storage: 'ledger', runtimeEventId: identity.runtimeEventId }
|
|
227
|
+
: { artifactId: identity.artifactId }),
|
|
166
228
|
originalBytes: identity.originalBytes,
|
|
167
229
|
};
|
|
168
230
|
const readHint = 'Call ArchiveRead with operation "read" (unit "char" or "line"), offset, and limit for bounded pages, or operation "search" with a pattern to locate text.';
|