maka-agent 0.2.0-dev.44.20260920 → 0.2.0-dev.45.20260921
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/dist/runtime-host-service-manager.js +1 -6
- package/dist/runtime-host-update-command.js +39 -27
- package/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
- package/node_modules/@maka/core/dist/artifacts.js +1 -0
- package/node_modules/@maka/core/dist/model-metadata.js +1 -2
- package/node_modules/@maka/core/dist/provider-auth.js +1 -7
- package/node_modules/@maka/core/dist/provider-registry.js +13 -7
- package/node_modules/@maka/core/dist/recall.js +5 -1
- package/node_modules/@maka/core/dist/session-start-mode.js +2 -5
- package/node_modules/@maka/core/dist/session.js +0 -1
- package/node_modules/@maka/core/dist/settings.js +17 -0
- package/node_modules/@maka/core/dist/tool-quiet-preview.js +2 -16
- package/node_modules/@maka/core/dist/transcript-search.js +46 -0
- package/node_modules/@maka/core/package.json +1 -4
- package/node_modules/@maka/runtime/dist/model-factory.js +0 -16
- package/node_modules/@maka/runtime/dist/model-fetcher.js +1 -4
- package/node_modules/@maka/runtime/dist/model-runtime.js +0 -8
- package/node_modules/@maka/runtime/dist/recall-tools.js +4 -0
- package/node_modules/@maka/runtime/dist/session-manager.js +4 -13
- package/node_modules/@maka/runtime/dist/subagent-tools.js +69 -11
- package/node_modules/@maka/runtime/dist/test-connection.js +1 -48
- package/node_modules/@maka/runtime/package.json +0 -1
- package/node_modules/@maka/runtime-host/dist/client/host-handoff-copy.js +25 -18
- package/node_modules/@maka/runtime-host/dist/client/host-handoff.js +3 -1
- package/node_modules/@maka/runtime-host/dist/protocol/connection-effects.js +0 -108
- package/node_modules/@maka/runtime-host/dist/protocol/index.js +6 -1
- package/node_modules/@maka/runtime-host/dist/protocol/operations.js +4 -5
- package/node_modules/@maka/runtime-host/dist/protocol/recall.js +270 -0
- package/node_modules/@maka/runtime-host/dist/protocol/session-continuity.js +1 -7
- package/node_modules/@maka/runtime-host/dist/protocol/usage-screen.js +12 -4
- package/node_modules/@maka/runtime-host/dist/server/access-credential-store.js +4 -0
- package/node_modules/@maka/runtime-host/dist/server/connection-effect-coordinator.js +1 -57
- package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +11 -33
- package/node_modules/@maka/runtime-host/dist/server/interactive-run-composer.js +3 -20
- package/node_modules/@maka/runtime-host/dist/server/recall-coordinator.js +117 -0
- package/node_modules/@maka/runtime-host/dist/server/session-revision-coordinator.js +0 -4
- package/node_modules/@maka/storage/dist/artifact-metadata-codec.js +4 -3
- package/node_modules/@maka/storage/dist/artifact-store.js +1 -11
- package/node_modules/@maka/storage/dist/process-lifetime-file-update-lock.js +0 -41
- package/node_modules/@maka/storage/dist/runtime-policy/coordinator.js +0 -28
- package/node_modules/@maka/storage/dist/runtime-policy-stores.js +0 -2
- package/node_modules/@maka/storage/dist/sqlite-usage-schema.js +29 -5
- package/node_modules/@maka/storage/dist/sqlite-workflow-schema.js +2 -0
- package/node_modules/@maka/storage/dist/storage-writer-composition.js +0 -3
- package/node_modules/@maka/storage/dist/telemetry-file-schema.js +5 -3
- package/node_modules/@maka/storage/dist/usage-screen.js +5 -6
- package/node_modules/@maka/storage/dist/usage-stores.js +14 -4
- package/node_modules/@maka/storage/package.json +0 -2
- package/package.json +1 -1
- package/node_modules/@maka/core/dist/connection-usage.js +0 -27
- package/node_modules/@maka/core/dist/deep-research-client-progress.js +0 -132
- package/node_modules/@maka/core/dist/deep-research-run.js +0 -625
- package/node_modules/@maka/core/dist/deep-research.js +0 -208
- package/node_modules/@maka/core/dist/thread-search.js +0 -498
- package/node_modules/@maka/runtime/dist/commandcode-cli-language-model.js +0 -837
- package/node_modules/@maka/runtime/dist/connection-usage.js +0 -232
- package/node_modules/@maka/runtime/dist/deep-research-tools.js +0 -732
- package/node_modules/@maka/runtime-host/dist/protocol/deep-research.js +0 -233
- package/node_modules/@maka/runtime-host/dist/server/deep-research-coordinator.js +0 -116
- package/node_modules/@maka/storage/dist/deep-research-authority.js +0 -129
- package/node_modules/@maka/storage/dist/deep-research-store.js +0 -343
|
@@ -0,0 +1,270 @@
|
|
|
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
|
+
/**
|
|
20
|
+
* `recall.query` — the retrieval surface a Client can ask for directly.
|
|
21
|
+
*
|
|
22
|
+
* Recall runs inside the Host because that is where the corpus lives: the
|
|
23
|
+
* Session manager, the distilled-fact store, and the material fetch are all
|
|
24
|
+
* Host-owned. A Client cannot perform it itself without pulling every
|
|
25
|
+
* transcript across the boundary, which is exactly the arrangement this
|
|
26
|
+
* operation replaces.
|
|
27
|
+
*
|
|
28
|
+
* The wire shape mirrors what the model's `Recall` tool already returns
|
|
29
|
+
* (`@maka/runtime/recall-tools`), with this protocol's camelCase field naming.
|
|
30
|
+
* That is deliberate: one recall answer, two presentations. A UI renders
|
|
31
|
+
* passages as navigable results and a model reads them as context, and neither
|
|
32
|
+
* gets a second implementation to drift from.
|
|
33
|
+
*/
|
|
34
|
+
import { RECALL_MAX_LIMIT, RECALL_MAX_TERMS, RECALL_TOTAL_PAYLOAD_CAP_BYTES, } from '@maka/core/recall';
|
|
35
|
+
import { SEARCH_QUERY_MAX_CHARS } from '@maka/core/search';
|
|
36
|
+
import { requireCount, requireEncodedByteLimit, requireEntityId, requireShapedRecord, requireUtf8String, } from './codec.js';
|
|
37
|
+
import { invalidProtocolFrame } from './errors.js';
|
|
38
|
+
import { defineOperation } from './operation-spec.js';
|
|
39
|
+
export const RECALL_QUERY_TERM_MAX_CHARS = SEARCH_QUERY_MAX_CHARS;
|
|
40
|
+
/**
|
|
41
|
+
* Byte ceiling for one term. Core measures a term in code points
|
|
42
|
+
* (`Array.from(term).length`), so the wire bound is that count times the
|
|
43
|
+
* widest UTF-8 encoding of one code point. A term that passes here can still
|
|
44
|
+
* be rejected by core on the character count; this only stops a frame that
|
|
45
|
+
* could not represent a legal term at all.
|
|
46
|
+
*/
|
|
47
|
+
const RECALL_QUERY_TERM_MAX_BYTES = RECALL_QUERY_TERM_MAX_CHARS * 4;
|
|
48
|
+
export const RECALL_QUERY_QUESTION_MAX_BYTES = 2 * 1024;
|
|
49
|
+
export const RECALL_QUERY_TEXT_MAX_BYTES = 32 * 1024;
|
|
50
|
+
export const RECALL_QUERY_MATERIAL_NAME_MAX_BYTES = 1024;
|
|
51
|
+
export const RECALL_QUERY_RESOURCE_MAX_BYTES = 1024;
|
|
52
|
+
/**
|
|
53
|
+
* Encoded ceiling for one envelope. Recall caps its own payload at
|
|
54
|
+
* `RECALL_TOTAL_PAYLOAD_CAP_BYTES`, but that counts passage text only; the
|
|
55
|
+
* envelope adds field names, message ids, timestamps and materials on top.
|
|
56
|
+
* This bound is that cap plus generous structural headroom, so it rejects a
|
|
57
|
+
* frame that no honest Host could have produced without constraining one that
|
|
58
|
+
* did.
|
|
59
|
+
*/
|
|
60
|
+
export const RECALL_QUERY_RESULT_MAX_BYTES = RECALL_TOTAL_PAYLOAD_CAP_BYTES + 64 * 1024;
|
|
61
|
+
const RECALL_FAILURE_REASONS = [
|
|
62
|
+
'invalid_query',
|
|
63
|
+
'incognito_active',
|
|
64
|
+
'not_found',
|
|
65
|
+
'aborted',
|
|
66
|
+
];
|
|
67
|
+
const RECALL_ROLES = ['user', 'assistant', 'tool'];
|
|
68
|
+
const RECALL_MATERIAL_KINDS = ['image', 'pdf', 'doc', 'code', 'other'];
|
|
69
|
+
const ERROR_CODES = [
|
|
70
|
+
'host_not_ready',
|
|
71
|
+
'host_draining',
|
|
72
|
+
'operation_unavailable',
|
|
73
|
+
'invalid_request',
|
|
74
|
+
'internal_failure',
|
|
75
|
+
];
|
|
76
|
+
export const RECALL_OPERATION_SPECS = {
|
|
77
|
+
'recall.query': defineOperation({
|
|
78
|
+
mode: 'query',
|
|
79
|
+
availability: 'ready',
|
|
80
|
+
errors: ERROR_CODES,
|
|
81
|
+
decodeInput: decodeRecallQueryInput,
|
|
82
|
+
decodeOutput: decodeRecallQueryResult,
|
|
83
|
+
}),
|
|
84
|
+
};
|
|
85
|
+
function decodeRecallQueryInput(value) {
|
|
86
|
+
const record = requireShapedRecord(value, 'Recall query input', ['terms'], ['question', 'limit', 'sessionId', 'since', 'until']);
|
|
87
|
+
if (!Array.isArray(record.terms) || record.terms.length === 0) {
|
|
88
|
+
throw invalidProtocolFrame('Invalid Recall terms');
|
|
89
|
+
}
|
|
90
|
+
if (record.terms.length > RECALL_MAX_TERMS) {
|
|
91
|
+
throw invalidProtocolFrame('Too many Recall terms');
|
|
92
|
+
}
|
|
93
|
+
const terms = record.terms.map((term) => requireUtf8String(term, 'Recall term', RECALL_QUERY_TERM_MAX_BYTES));
|
|
94
|
+
const limit = record.limit === undefined ? undefined : requireCount(record.limit, 'Recall limit');
|
|
95
|
+
if (limit !== undefined && (limit < 1 || limit > RECALL_MAX_LIMIT)) {
|
|
96
|
+
throw invalidProtocolFrame('Invalid Recall limit');
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
terms,
|
|
100
|
+
...(record.question === undefined
|
|
101
|
+
? {}
|
|
102
|
+
: {
|
|
103
|
+
question: requireUtf8String(record.question, 'Recall question', RECALL_QUERY_QUESTION_MAX_BYTES),
|
|
104
|
+
}),
|
|
105
|
+
...(limit === undefined ? {} : { limit }),
|
|
106
|
+
...(record.sessionId === undefined
|
|
107
|
+
? {}
|
|
108
|
+
: { sessionId: requireEntityId(record.sessionId, 'Recall sessionId') }),
|
|
109
|
+
...(record.since === undefined ? {} : { since: requireCount(record.since, 'Recall since') }),
|
|
110
|
+
...(record.until === undefined ? {} : { until: requireCount(record.until, 'Recall until') }),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Bounded text that may be empty. Transcript text is legitimately empty when a
|
|
115
|
+
* message carried only files, and a Session title is empty for an unnamed
|
|
116
|
+
* Session; both are legal answers, so they must not be rejected as malformed.
|
|
117
|
+
*/
|
|
118
|
+
function requireBoundedText(value, label, maxBytes) {
|
|
119
|
+
if (typeof value !== 'string' || Buffer.byteLength(value, 'utf8') > maxBytes) {
|
|
120
|
+
throw invalidProtocolFrame(`Invalid ${label}`);
|
|
121
|
+
}
|
|
122
|
+
return value;
|
|
123
|
+
}
|
|
124
|
+
function decodeRecallQueryResult(value) {
|
|
125
|
+
requireEncodedByteLimit(value, 'Recall query result', RECALL_QUERY_RESULT_MAX_BYTES);
|
|
126
|
+
const record = requireShapedRecord(value, 'Recall query result', ['ok'], ['facts', 'passages', 'gaps', 'searchedEverySession', 'reason', 'message']);
|
|
127
|
+
if (record.ok === false) {
|
|
128
|
+
const exact = requireShapedRecord(record, 'Recall error result', ['ok', 'reason', 'message'], []);
|
|
129
|
+
if (typeof exact.reason !== 'string' ||
|
|
130
|
+
!RECALL_FAILURE_REASONS.includes(exact.reason)) {
|
|
131
|
+
throw invalidProtocolFrame('Invalid Recall failure reason');
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
ok: false,
|
|
135
|
+
reason: exact.reason,
|
|
136
|
+
message: requireUtf8String(exact.message, 'Recall failure message', RECALL_QUERY_TEXT_MAX_BYTES),
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
if (record.ok !== true)
|
|
140
|
+
throw invalidProtocolFrame('Invalid Recall query result kind');
|
|
141
|
+
const exact = requireShapedRecord(record, 'Recall success result', ['ok', 'facts', 'passages', 'gaps', 'searchedEverySession'], []);
|
|
142
|
+
if (!Array.isArray(exact.facts) || !Array.isArray(exact.passages)) {
|
|
143
|
+
throw invalidProtocolFrame('Invalid Recall success result');
|
|
144
|
+
}
|
|
145
|
+
if (typeof exact.searchedEverySession !== 'boolean') {
|
|
146
|
+
throw invalidProtocolFrame('Invalid Recall searchedEverySession');
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
ok: true,
|
|
150
|
+
facts: exact.facts.map((fact) => decodeFact(fact)),
|
|
151
|
+
passages: exact.passages.map((passage) => decodePassage(passage)),
|
|
152
|
+
gaps: requireUtf8String(exact.gaps, 'Recall gaps', RECALL_QUERY_TEXT_MAX_BYTES),
|
|
153
|
+
searchedEverySession: exact.searchedEverySession,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
function decodeFact(value) {
|
|
157
|
+
const record = requireShapedRecord(value, 'Recall fact', ['content', 'kind', 'observedAt'], []);
|
|
158
|
+
return {
|
|
159
|
+
content: requireUtf8String(record.content, 'Recall fact content', RECALL_QUERY_TEXT_MAX_BYTES),
|
|
160
|
+
kind: requireUtf8String(record.kind, 'Recall fact kind', RECALL_QUERY_MATERIAL_NAME_MAX_BYTES),
|
|
161
|
+
observedAt: requireCount(record.observedAt, 'Recall fact observedAt'),
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
function decodePassage(value) {
|
|
165
|
+
const record = requireShapedRecord(value, 'Recall passage', [
|
|
166
|
+
'sessionId',
|
|
167
|
+
'sessionTitle',
|
|
168
|
+
'anchorMessageId',
|
|
169
|
+
'sequence',
|
|
170
|
+
'messages',
|
|
171
|
+
'matchedTerms',
|
|
172
|
+
'score',
|
|
173
|
+
'hasMoreBefore',
|
|
174
|
+
'hasMoreAfter',
|
|
175
|
+
], ['turnId', 'lastMessageAt', 'truncated']);
|
|
176
|
+
if (!Array.isArray(record.messages) || !Array.isArray(record.matchedTerms)) {
|
|
177
|
+
throw invalidProtocolFrame('Invalid Recall passage messages');
|
|
178
|
+
}
|
|
179
|
+
if (typeof record.score !== 'number' || !Number.isFinite(record.score)) {
|
|
180
|
+
throw invalidProtocolFrame('Invalid Recall passage score');
|
|
181
|
+
}
|
|
182
|
+
if (typeof record.hasMoreBefore !== 'boolean' || typeof record.hasMoreAfter !== 'boolean') {
|
|
183
|
+
throw invalidProtocolFrame('Invalid Recall passage continuation flags');
|
|
184
|
+
}
|
|
185
|
+
return {
|
|
186
|
+
sessionId: requireEntityId(record.sessionId, 'Recall passage sessionId'),
|
|
187
|
+
sessionTitle: requireBoundedText(record.sessionTitle, 'Recall passage sessionTitle', RECALL_QUERY_TEXT_MAX_BYTES),
|
|
188
|
+
...(record.turnId === undefined
|
|
189
|
+
? {}
|
|
190
|
+
: { turnId: requireEntityId(record.turnId, 'Recall passage turnId') }),
|
|
191
|
+
anchorMessageId: requireEntityId(record.anchorMessageId, 'Recall passage anchorMessageId'),
|
|
192
|
+
sequence: requireCount(record.sequence, 'Recall passage sequence'),
|
|
193
|
+
messages: record.messages.map((message) => decodePassageMessage(message)),
|
|
194
|
+
matchedTerms: record.matchedTerms.map((term) => requireUtf8String(term, 'Recall matched term', RECALL_QUERY_TERM_MAX_BYTES)),
|
|
195
|
+
score: record.score,
|
|
196
|
+
...(record.lastMessageAt === undefined
|
|
197
|
+
? {}
|
|
198
|
+
: { lastMessageAt: requireCount(record.lastMessageAt, 'Recall passage lastMessageAt') }),
|
|
199
|
+
hasMoreBefore: record.hasMoreBefore,
|
|
200
|
+
hasMoreAfter: record.hasMoreAfter,
|
|
201
|
+
...(record.truncated === undefined
|
|
202
|
+
? {}
|
|
203
|
+
: record.truncated === true
|
|
204
|
+
? { truncated: true }
|
|
205
|
+
: (() => {
|
|
206
|
+
throw invalidProtocolFrame('Invalid Recall passage truncated flag');
|
|
207
|
+
})()),
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
function decodePassageMessage(value) {
|
|
211
|
+
const record = requireShapedRecord(value, 'Recall passage message', ['messageId', 'role', 'matchKind', 'text', 'timestamp', 'isAnchor'], ['materials']);
|
|
212
|
+
if (typeof record.role !== 'string' ||
|
|
213
|
+
!RECALL_ROLES.includes(record.role)) {
|
|
214
|
+
throw invalidProtocolFrame('Invalid Recall passage message role');
|
|
215
|
+
}
|
|
216
|
+
if (typeof record.isAnchor !== 'boolean') {
|
|
217
|
+
throw invalidProtocolFrame('Invalid Recall passage message anchor flag');
|
|
218
|
+
}
|
|
219
|
+
if (record.materials !== undefined && !Array.isArray(record.materials)) {
|
|
220
|
+
throw invalidProtocolFrame('Invalid Recall passage message materials');
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
messageId: requireEntityId(record.messageId, 'Recall passage messageId'),
|
|
224
|
+
role: record.role,
|
|
225
|
+
matchKind: requireUtf8String(record.matchKind, 'Recall passage message matchKind', RECALL_QUERY_MATERIAL_NAME_MAX_BYTES),
|
|
226
|
+
// A message whose whole content was a pasted file carries no text of its
|
|
227
|
+
// own; the material beside it is the point. Empty is legal here, unlike
|
|
228
|
+
// the identifiers around it.
|
|
229
|
+
text: requireBoundedText(record.text, 'Recall passage message text', RECALL_QUERY_TEXT_MAX_BYTES),
|
|
230
|
+
timestamp: requireCount(record.timestamp, 'Recall passage message timestamp'),
|
|
231
|
+
isAnchor: record.isAnchor,
|
|
232
|
+
...(record.materials === undefined
|
|
233
|
+
? {}
|
|
234
|
+
: { materials: record.materials.map((material) => decodeMaterial(material)) }),
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
function decodeMaterial(value) {
|
|
238
|
+
const record = requireShapedRecord(value, 'Recall material', ['name', 'kind', 'mimeType', 'bytes'], ['resource', 'sourceSessionId', 'materialId']);
|
|
239
|
+
if (typeof record.kind !== 'string' ||
|
|
240
|
+
!RECALL_MATERIAL_KINDS.includes(record.kind)) {
|
|
241
|
+
throw invalidProtocolFrame('Invalid Recall material kind');
|
|
242
|
+
}
|
|
243
|
+
const resource = record.resource === undefined
|
|
244
|
+
? undefined
|
|
245
|
+
: requireUtf8String(record.resource, 'Recall material resource', RECALL_QUERY_RESOURCE_MAX_BYTES);
|
|
246
|
+
const sourceSessionId = record.sourceSessionId === undefined
|
|
247
|
+
? undefined
|
|
248
|
+
: requireEntityId(record.sourceSessionId, 'Recall material sourceSessionId');
|
|
249
|
+
const materialId = record.materialId === undefined
|
|
250
|
+
? undefined
|
|
251
|
+
: requireEntityId(record.materialId, 'Recall material materialId');
|
|
252
|
+
// An address says "read this now"; a location says "ask for it". Carrying
|
|
253
|
+
// both would offer a caller two answers to one question, so recall never
|
|
254
|
+
// emits both and the decoder refuses the shape rather than picking a winner.
|
|
255
|
+
if (resource !== undefined && (sourceSessionId !== undefined || materialId !== undefined)) {
|
|
256
|
+
throw invalidProtocolFrame('Invalid Recall material location');
|
|
257
|
+
}
|
|
258
|
+
if ((sourceSessionId === undefined) !== (materialId === undefined)) {
|
|
259
|
+
throw invalidProtocolFrame('Incomplete Recall material location');
|
|
260
|
+
}
|
|
261
|
+
return {
|
|
262
|
+
name: requireUtf8String(record.name, 'Recall material name', RECALL_QUERY_MATERIAL_NAME_MAX_BYTES),
|
|
263
|
+
kind: record.kind,
|
|
264
|
+
mimeType: requireUtf8String(record.mimeType, 'Recall material mimeType', RECALL_QUERY_MATERIAL_NAME_MAX_BYTES),
|
|
265
|
+
bytes: requireCount(record.bytes, 'Recall material bytes'),
|
|
266
|
+
...(resource === undefined ? {} : { resource }),
|
|
267
|
+
...(sourceSessionId === undefined ? {} : { sourceSessionId }),
|
|
268
|
+
...(materialId === undefined ? {} : { materialId }),
|
|
269
|
+
};
|
|
270
|
+
}
|
|
@@ -47,13 +47,7 @@ export const SESSION_TOOL_INTENT_MAX_BYTES = 512;
|
|
|
47
47
|
export const SESSION_TOOL_ARGS_PREVIEW_MAX_BYTES = 8 * 1024;
|
|
48
48
|
export const SESSION_SUBSCRIPTION_FRAME_MAX_BYTES = 64 * 1024 - 1;
|
|
49
49
|
export const SESSION_RUNTIME_RESOURCE_PTY_DATA_MAX_BYTES = 48 * 1024;
|
|
50
|
-
export const SESSION_DOMAINS = [
|
|
51
|
-
'todo',
|
|
52
|
-
'plan',
|
|
53
|
-
'deep_research',
|
|
54
|
-
'usage',
|
|
55
|
-
'runtime_resource',
|
|
56
|
-
];
|
|
50
|
+
export const SESSION_DOMAINS = ['todo', 'plan', 'usage', 'runtime_resource'];
|
|
57
51
|
export const SESSION_RUNTIME_RESOURCE_CHANGES_MAX = 64;
|
|
58
52
|
const SUBSCRIPTION_OPEN_ERRORS = [
|
|
59
53
|
'transcript_preparing',
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* specific language governing permissions and limitations
|
|
17
17
|
* under the License.
|
|
18
18
|
*/
|
|
19
|
+
import { isUsageScreenSearch, isUsageTimestamp, } from '@maka/core/settings';
|
|
19
20
|
import { requireExactRecord, requireRecord, requireShapedRecord, requireCount } from './codec.js';
|
|
20
21
|
import { invalidProtocolFrame } from './errors.js';
|
|
21
22
|
import { decodeUsageProvenance } from './usage-pricing.js';
|
|
@@ -41,16 +42,23 @@ function amount(value) {
|
|
|
41
42
|
return fail();
|
|
42
43
|
return value;
|
|
43
44
|
}
|
|
45
|
+
function timestamp(value) {
|
|
46
|
+
if (!isUsageTimestamp(value))
|
|
47
|
+
return fail();
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
44
50
|
function query(value) {
|
|
45
51
|
const v = requireExactRecord(value, 'Usage screen query', ['range', 'search', 'status']);
|
|
46
52
|
const range = requireExactRecord(v.range, 'Usage range', ['from', 'to']);
|
|
47
|
-
const from =
|
|
48
|
-
const to =
|
|
53
|
+
const from = timestamp(range.from);
|
|
54
|
+
const to = timestamp(range.to);
|
|
49
55
|
if (from > to || !['all', 'success', 'error', 'aborted'].includes(String(v.status)))
|
|
50
56
|
return fail();
|
|
57
|
+
if (!isUsageScreenSearch(v.search))
|
|
58
|
+
return fail();
|
|
51
59
|
return {
|
|
52
60
|
range: { from, to },
|
|
53
|
-
search:
|
|
61
|
+
search: v.search,
|
|
54
62
|
status: v.status,
|
|
55
63
|
};
|
|
56
64
|
}
|
|
@@ -228,8 +236,8 @@ export function decodeUsageScreenResult(value) {
|
|
|
228
236
|
for (const key of ['id', 'provider', 'model', 'sessionId', 'sessionName', 'turnId', 'toolName'])
|
|
229
237
|
if (row[key] !== undefined)
|
|
230
238
|
text(row[key]);
|
|
239
|
+
timestamp(row.ts);
|
|
231
240
|
for (const key of [
|
|
232
|
-
'ts',
|
|
233
241
|
'inputTokens',
|
|
234
242
|
'outputTokens',
|
|
235
243
|
'cacheMiss',
|
|
@@ -48,8 +48,12 @@ const PERSISTED_GRANT_MIGRATIONS = new Map([
|
|
|
48
48
|
// Retired with the second execution-inspection contract; no shipped surface
|
|
49
49
|
// called execution.inspect.resolve.
|
|
50
50
|
['execution.inspect.resolve', { kind: 'release' }],
|
|
51
|
+
// Retired with the Command Code GO provider, whose private transport the
|
|
52
|
+
// usage read required.
|
|
53
|
+
['connection.usage.read', { kind: 'release' }],
|
|
51
54
|
// Retired in favor of editing and resending the original user message.
|
|
52
55
|
['turn.regenerate', { kind: 'release' }],
|
|
56
|
+
['deep-research.query', { kind: 'release' }],
|
|
53
57
|
// Direct WorkHub actions and record writes were retired. Their grants do not
|
|
54
58
|
// authorize actFromTurn, which requires the active coordination Turn.
|
|
55
59
|
['workhub.coordination.act', { kind: 'release' }],
|
|
@@ -17,13 +17,12 @@
|
|
|
17
17
|
* under the License.
|
|
18
18
|
*/
|
|
19
19
|
import { parseRequestHeaders } from '@maka/core/runtime-policy';
|
|
20
|
-
import { PROVIDER_REGISTRY,
|
|
20
|
+
import { PROVIDER_REGISTRY, providerFallbackModelIds, } from '@maka/core/llm-connections';
|
|
21
21
|
import { createConnectionEffectFetchTransport, } from '@maka/runtime/network/scoped-fetch-transport';
|
|
22
22
|
import { createRequestCustomizationFetch } from '@maka/runtime/request-customization-fetch';
|
|
23
23
|
import { isOAuthSubscriptionProvider, parseOAuthSubscriptionTokens, } from '@maka/runtime/subscription-credentials';
|
|
24
24
|
import { runConnectionModelDiscoveryEffect } from '@maka/runtime/model-fetcher';
|
|
25
25
|
import { runConnectionTestEffect } from '@maka/runtime/test-connection';
|
|
26
|
-
import { fetchConnectionUsage } from '@maka/runtime/connection-usage';
|
|
27
26
|
import { authenticateRuntimePolicyStoresWriter, RuntimePolicyStoreError, } from '@maka/storage/runtime-policy-stores';
|
|
28
27
|
import { toRuntimePolicyProxy } from './runtime-policy-proxy.js';
|
|
29
28
|
/** Runs provider I/O outside Storage lanes and conditionally commits canonical results. */
|
|
@@ -33,7 +32,6 @@ export class HostConnectionEffectCoordinator {
|
|
|
33
32
|
'connection.onboarding.verify': (input) => this.#verifyOnboarding(input),
|
|
34
33
|
'connection.models.fetch': (input) => this.#fetchModels(input),
|
|
35
34
|
'connection.test.run': (input) => this.#testConnection(input),
|
|
36
|
-
'connection.usage.read': (input) => this.#readConnectionUsage(input),
|
|
37
35
|
};
|
|
38
36
|
#stores;
|
|
39
37
|
#activation;
|
|
@@ -265,32 +263,6 @@ export class HostConnectionEffectCoordinator {
|
|
|
265
263
|
: projectSuperseded(completion);
|
|
266
264
|
});
|
|
267
265
|
}
|
|
268
|
-
/**
|
|
269
|
-
* Read-only: fetch the account's usage and project it. Nothing is committed,
|
|
270
|
-
* so no superseded branch exists — the ticket is spent and the report
|
|
271
|
-
* returned.
|
|
272
|
-
*/
|
|
273
|
-
#readConnectionUsage(input) {
|
|
274
|
-
return this.#admit(input.connectionId, 'connection.usage.read', async () => {
|
|
275
|
-
const prepared = await this.#stores.operations.beginConnectionUsage(input.connectionId);
|
|
276
|
-
if (prepared.kind !== 'ready')
|
|
277
|
-
return preparationResult(prepared);
|
|
278
|
-
try {
|
|
279
|
-
const result = await this.#withTransport(prepared, (fetch, secret) => fetchConnectionUsage({
|
|
280
|
-
providerType: prepared.connection.providerType,
|
|
281
|
-
apiKey: secret,
|
|
282
|
-
baseUrl: effectiveBaseUrl(prepared.connection),
|
|
283
|
-
fetch,
|
|
284
|
-
}));
|
|
285
|
-
return result.kind === 'report'
|
|
286
|
-
? { kind: 'report', report: projectUsageReport(result.report) }
|
|
287
|
-
: { kind: 'unavailable', reason: result.reason };
|
|
288
|
-
}
|
|
289
|
-
finally {
|
|
290
|
-
await this.#stores.operations.completeConnectionUsage(prepared.ticket);
|
|
291
|
-
}
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
266
|
#admit(connectionId, operation, run) {
|
|
295
267
|
if (!this.#accepting) {
|
|
296
268
|
return Promise.resolve({
|
|
@@ -379,34 +351,6 @@ function projectSuperseded(completion) {
|
|
|
379
351
|
changed: completion.changed.map((domain) => domain),
|
|
380
352
|
};
|
|
381
353
|
}
|
|
382
|
-
function projectUsageReport(report) {
|
|
383
|
-
return {
|
|
384
|
-
accountLabel: report.accountLabel ?? null,
|
|
385
|
-
planLabel: report.planLabel ?? null,
|
|
386
|
-
stats: report.stats
|
|
387
|
-
? {
|
|
388
|
-
requests: report.stats.requests ?? null,
|
|
389
|
-
failed: report.stats.failed ?? null,
|
|
390
|
-
successRate: report.stats.successRate ?? null,
|
|
391
|
-
cost: report.stats.cost ?? null,
|
|
392
|
-
tokensIn: report.stats.tokensIn ?? null,
|
|
393
|
-
tokensOut: report.stats.tokensOut ?? null,
|
|
394
|
-
}
|
|
395
|
-
: null,
|
|
396
|
-
windows: report.windows.map((window) => ({
|
|
397
|
-
id: window.id,
|
|
398
|
-
label: window.label ?? null,
|
|
399
|
-
used: window.used,
|
|
400
|
-
cap: window.cap,
|
|
401
|
-
unit: window.unit,
|
|
402
|
-
resetsAt: window.resetsAt ?? null,
|
|
403
|
-
unlimited: window.unlimited ?? null,
|
|
404
|
-
})),
|
|
405
|
-
periodEnd: report.periodEnd ?? null,
|
|
406
|
-
partiallyUnauthorized: report.partiallyUnauthorized === true,
|
|
407
|
-
fetchedAt: report.fetchedAt,
|
|
408
|
-
};
|
|
409
|
-
}
|
|
410
354
|
function projectConnectionTest(outcome, checkedAt) {
|
|
411
355
|
const checkedAtIso = new Date(checkedAt).toISOString();
|
|
412
356
|
if (outcome.ok) {
|
|
@@ -24,9 +24,9 @@ import { NO_REAL_CONNECTION_CODE } from '@maka/core/connection-error-copy';
|
|
|
24
24
|
import { generalizedErrorMessage } from '@maka/core/redaction';
|
|
25
25
|
import { emptyPlanSessionState } from '@maka/core/plan';
|
|
26
26
|
import { readLogicalRuntimeExecutionForRun } from '@maka/core/runtime-logical-execution';
|
|
27
|
-
import { foldForMatch } from '@maka/core/
|
|
27
|
+
import { foldForMatch } from '@maka/core/transcript-search';
|
|
28
28
|
import { runtimeInvocationOutcome, } from '@maka/core/runtime-invocation';
|
|
29
|
-
import {
|
|
29
|
+
import { WORKHUB_COORDINATION_SESSION_ID, WORKHUB_COORDINATION_REPLACEMENT_SCHEMA_VERSION, } from '@maka/core/session';
|
|
30
30
|
import { AgentGraphClientOperationError, AgentGraphCoordinator, } from '@maka/runtime/stream-graph-coordinator';
|
|
31
31
|
import { AgentGraphSupervisorWakeCoordinator } from '@maka/runtime/agent-graph-supervisor-wake';
|
|
32
32
|
import { BackendRegistry, SessionManager, workHubDirectStopAbortSource, } from '@maka/runtime/session-manager';
|
|
@@ -34,6 +34,7 @@ import { buildToolsForAgentDefinition } from '@maka/runtime/agent-catalog';
|
|
|
34
34
|
import { buildRecallTools } from '@maka/runtime/recall-tools';
|
|
35
35
|
import { RECALL_SYNTHETIC_TEXT_PATTERNS } from '@maka/runtime/recall-candidates';
|
|
36
36
|
import { createRecallMaterialFetch } from './recall-material-fetch.js';
|
|
37
|
+
import { HostRecallCoordinator } from './recall-coordinator.js';
|
|
37
38
|
import { buildBuiltinTools } from '@maka/runtime/builtin-tools';
|
|
38
39
|
import { createLocalContinuationSafetyInspector } from '@maka/runtime/continuation-safety';
|
|
39
40
|
import { createConfiguredSubagentCatalog } from '@maka/runtime/configured-subagent-catalog';
|
|
@@ -95,7 +96,6 @@ import { HostChangeFeed } from './host-change-feed.js';
|
|
|
95
96
|
import { HostConfigurationCoordinator } from './configuration-coordinator.js';
|
|
96
97
|
import { HostContextCoordinator } from './context-coordinator.js';
|
|
97
98
|
import { HostClientCapabilityCoordinator } from './client-capability-coordinator.js';
|
|
98
|
-
import { HostDeepResearchCoordinator } from './deep-research-coordinator.js';
|
|
99
99
|
import { HostDailyReviewCoordinator } from './daily-review-coordinator.js';
|
|
100
100
|
import { prepareHostAiSdkBackend } from './execution-model-composition.js';
|
|
101
101
|
import { createInteractiveRunComposer, createInteractiveRunComposerFactory, routeInteractiveRunToolSurface, } from './interactive-run-composer.js';
|
|
@@ -258,7 +258,6 @@ export async function createExecutionRuntimeHostComposition(context, options = {
|
|
|
258
258
|
const oauthCredentials = new HostOAuthExecutionAuthority(runtimePolicyStores);
|
|
259
259
|
const openedScheduledTaskStore = storage.scheduledTasks;
|
|
260
260
|
const openedPlanStore = storage.plan;
|
|
261
|
-
const openedDeepResearchStore = storage.deepResearch;
|
|
262
261
|
const openedDailyReviewStore = storage.dailyReview;
|
|
263
262
|
const openedGoalStore = storage.goal;
|
|
264
263
|
const memoryStore = storage.memoryBundle;
|
|
@@ -485,7 +484,10 @@ export async function createExecutionRuntimeHostComposition(context, options = {
|
|
|
485
484
|
search: ({ query, limit, abortSignal }) => webSearchService.search({ query, limit, ...(abortSignal ? { abortSignal } : {}) }),
|
|
486
485
|
fetch: (input) => webFetchService.fetch(input),
|
|
487
486
|
});
|
|
488
|
-
|
|
487
|
+
// The recall surface is built once and shared: the model's tools and the
|
|
488
|
+
// Host's `recall.query` operation answer from the same dependency graph, so
|
|
489
|
+
// a UI search and a model recall cannot diverge in what they can see.
|
|
490
|
+
const recallDeps = {
|
|
489
491
|
listSessions: () => requireSessionManager(manager).listSessions(),
|
|
490
492
|
readMessages: async (sessionId, abortSignal) => {
|
|
491
493
|
if (abortSignal?.aborted)
|
|
@@ -540,7 +542,9 @@ export async function createExecutionRuntimeHostComposition(context, options = {
|
|
|
540
542
|
incognitoActive: (await runtimePolicyStores.runtimePolicy.getSnapshot()).policy.privacy
|
|
541
543
|
.incognitoActive,
|
|
542
544
|
}),
|
|
543
|
-
}
|
|
545
|
+
};
|
|
546
|
+
const recallTools = buildRecallTools(recallDeps);
|
|
547
|
+
const recall = new HostRecallCoordinator(recallDeps);
|
|
544
548
|
const childHostTools = [
|
|
545
549
|
createHostWebSearchToolFromService(webSearchService),
|
|
546
550
|
createHostWebFetchToolFromService(webFetchService),
|
|
@@ -626,7 +630,6 @@ export async function createExecutionRuntimeHostComposition(context, options = {
|
|
|
626
630
|
let scheduledTasks;
|
|
627
631
|
let scheduledTaskTool;
|
|
628
632
|
let goal;
|
|
629
|
-
let deepResearch;
|
|
630
633
|
let dailyReview;
|
|
631
634
|
const rootPort = {
|
|
632
635
|
readLatestRootTurnLineage: (identity) => requireRootCoordinator(rootCoordinator).readLatestRootTurnLineage(identity),
|
|
@@ -675,13 +678,6 @@ export async function createExecutionRuntimeHostComposition(context, options = {
|
|
|
675
678
|
unsubscribeTranscriptChanges = stores.sessionStore.subscribeTranscriptChanges((sessionId) => continuityCoordinator.enqueueCanonicalRefresh(sessionId));
|
|
676
679
|
unsubscribeRuntimeEventCommits = stores.runtimeEventStore.subscribeRuntimeEventCommits((sessionId) => continuityCoordinator.enqueueTranscriptAdvanced(sessionId));
|
|
677
680
|
unsubscribeUsageChanges = openedUsageStores.subscribeSessionUsageChanges((sessionId) => continuityCoordinator.enqueueSessionDomainChanged(sessionId, 'usage'));
|
|
678
|
-
deepResearch = new HostDeepResearchCoordinator({
|
|
679
|
-
store: openedDeepResearchStore,
|
|
680
|
-
artifacts: openedArtifactStore,
|
|
681
|
-
sessions: stores.sessionStore,
|
|
682
|
-
sessionAdmission,
|
|
683
|
-
onProjectionChanged: (sessionId) => continuityCoordinator.enqueueSessionDomainChanged(sessionId, 'deep_research'),
|
|
684
|
-
});
|
|
685
681
|
dailyReview = new HostDailyReviewCoordinator({
|
|
686
682
|
store: openedDailyReviewStore,
|
|
687
683
|
usage: openedUsageStores,
|
|
@@ -784,7 +780,6 @@ export async function createExecutionRuntimeHostComposition(context, options = {
|
|
|
784
780
|
resolveTavilyWebSearchReadiness: () => resolveHostTavilyWebSearchReadiness(runtimePolicyStores.operations),
|
|
785
781
|
...(scheduledTaskTool ? { scheduledTaskTool } : {}),
|
|
786
782
|
planStore,
|
|
787
|
-
deepResearchTools: requireDeepResearch(deepResearch).toolsForSession(backendContext.sessionId),
|
|
788
783
|
goalTools: requireGoal(goal).tools,
|
|
789
784
|
builtinTools,
|
|
790
785
|
hostTools,
|
|
@@ -946,13 +941,6 @@ export async function createExecutionRuntimeHostComposition(context, options = {
|
|
|
946
941
|
mode: header.collaborationMode ?? 'agent',
|
|
947
942
|
permissionMode: header.permissionMode,
|
|
948
943
|
},
|
|
949
|
-
...(isDeepResearchSession(header.labels)
|
|
950
|
-
? {
|
|
951
|
-
deepResearch: {
|
|
952
|
-
tools: requireDeepResearch(deepResearch).toolsForSession(sessionId),
|
|
953
|
-
},
|
|
954
|
-
}
|
|
955
|
-
: {}),
|
|
956
944
|
}).tools.map((tool) => tool.name);
|
|
957
945
|
}
|
|
958
946
|
finally {
|
|
@@ -2031,7 +2019,6 @@ export async function createExecutionRuntimeHostComposition(context, options = {
|
|
|
2031
2019
|
// writer: publishing a per-Session `plan` invalidation for state that is
|
|
2032
2020
|
// being removed would only wake subscribers to read nothing.
|
|
2033
2021
|
await openedPlanStore.purgeSessionState(sessionId);
|
|
2034
|
-
await openedDeepResearchStore.purgeSessionState(sessionId);
|
|
2035
2022
|
},
|
|
2036
2023
|
purgeAgentGraphState: async (sessionId) => {
|
|
2037
2024
|
for (const graphId of await requireGraphCoordinator(graphCoordinator).listGraphIds(sessionId)) {
|
|
@@ -2150,6 +2137,7 @@ export async function createExecutionRuntimeHostComposition(context, options = {
|
|
|
2150
2137
|
oauth.handlers,
|
|
2151
2138
|
externalAgentSetup.handlers,
|
|
2152
2139
|
webSearch.handlers,
|
|
2140
|
+
recall.handlers,
|
|
2153
2141
|
networkProxy.handlers,
|
|
2154
2142
|
configuration.handlers,
|
|
2155
2143
|
],
|
|
@@ -2222,11 +2210,6 @@ export async function createExecutionRuntimeHostComposition(context, options = {
|
|
|
2222
2210
|
drain: [() => clientCapabilities.beginDrain()],
|
|
2223
2211
|
close: [() => clientCapabilities.close()],
|
|
2224
2212
|
}),
|
|
2225
|
-
createRuntimeHostDomainModule({
|
|
2226
|
-
id: 'deep-research',
|
|
2227
|
-
handlers: [requireDeepResearch(deepResearch).handlers],
|
|
2228
|
-
close: [() => deepResearch?.close()],
|
|
2229
|
-
}),
|
|
2230
2213
|
createRuntimeHostDomainModule({
|
|
2231
2214
|
id: 'daily-review',
|
|
2232
2215
|
handlers: [requireDailyReview(dailyReview).handlers],
|
|
@@ -2646,11 +2629,6 @@ function requireScheduledTasks(coordinator) {
|
|
|
2646
2629
|
throw new Error('Runtime Host ScheduledTask coordinator is not composed');
|
|
2647
2630
|
return coordinator;
|
|
2648
2631
|
}
|
|
2649
|
-
function requireDeepResearch(coordinator) {
|
|
2650
|
-
if (!coordinator)
|
|
2651
|
-
throw new Error('Runtime Host Deep Research coordinator is not composed');
|
|
2652
|
-
return coordinator;
|
|
2653
|
-
}
|
|
2654
2632
|
function requireDailyReview(coordinator) {
|
|
2655
2633
|
if (!coordinator)
|
|
2656
2634
|
throw new Error('Runtime Host Daily Review coordinator is not composed');
|
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import { isDeepStrictEqual } from 'node:util';
|
|
20
20
|
import { buildSideConversationSystemPromptFragment, isSideConversationSession, } from '@maka/core/side-conversation';
|
|
21
|
-
import { buildDeepResearchSystemPromptFragment, isDeepResearchSession, } from '@maka/core/deep-research';
|
|
22
21
|
import { activePlanExecution } from '@maka/core/plan';
|
|
23
22
|
import { createHash } from 'node:crypto';
|
|
24
23
|
import { assembleMainSessionSystemPrompt } from '@maka/runtime/system-prompt/main-session-prompt';
|
|
@@ -31,7 +30,6 @@ import { buildRequestSandboxBoundaryTool } from '@maka/runtime/sandbox-boundary-
|
|
|
31
30
|
import { buildHostCapabilitiesFromBinding, buildSkillAgentToolFromInventory, buildSkillSearchAgentToolFromInventory, buildSkillsPromptFragmentFromInventoryWithReport, SkillShadowSelectionTracker, } from '@maka/runtime/skills';
|
|
32
31
|
import { buildSessionTodoTools } from '@maka/runtime/session-todo-tools';
|
|
33
32
|
import { buildWorkspaceInstructionsPromptFragment } from '@maka/runtime/system-prompt/workspace-instructions';
|
|
34
|
-
import { isDeepResearchToolAllowed } from '@maka/runtime/deep-research-tools';
|
|
35
33
|
import { listRunnableBuiltinAgentDefinitions } from '@maka/runtime/agent-catalog';
|
|
36
34
|
import { renderPlanModePrompt, selectCollaborationTools } from '@maka/runtime/plan-mode';
|
|
37
35
|
import { routeWebFetchTools } from '@maka/runtime/web-fetch-tool';
|
|
@@ -60,7 +58,7 @@ export function createInteractiveRunComposer(input) {
|
|
|
60
58
|
// contributions are sampled at logical step boundaries.
|
|
61
59
|
const defaultTools = input.boundTools
|
|
62
60
|
? input.boundTools
|
|
63
|
-
: buildDefaultHostTools(input.sessionTodo, inventoryFor, builtinTools, input.hostTools ?? [], input.scheduledTaskTool, input.goalTools, input.parentAgentTools, input.plan
|
|
61
|
+
: buildDefaultHostTools(input.sessionTodo, inventoryFor, builtinTools, input.hostTools ?? [], input.scheduledTaskTool, input.goalTools, input.parentAgentTools, input.plan);
|
|
64
62
|
const clientCapabilityTools = input.boundTools !== undefined ||
|
|
65
63
|
(input.toolProfile !== undefined && input.toolProfile !== 'workhub-coordination-v2')
|
|
66
64
|
? []
|
|
@@ -70,11 +68,7 @@ export function createInteractiveRunComposer(input) {
|
|
|
70
68
|
const additionalTools = hasToolCeiling
|
|
71
69
|
? []
|
|
72
70
|
: (input.resolveAdditionalTools?.(stableHostTools) ?? []);
|
|
73
|
-
const
|
|
74
|
-
const routedCandidateTools = input.deepResearch
|
|
75
|
-
? unscopedCandidateTools.filter(isDeepResearchToolAllowed)
|
|
76
|
-
: unscopedCandidateTools;
|
|
77
|
-
const candidateTools = projectHostedExecutionTools(routedCandidateTools, input.toolProfile);
|
|
71
|
+
const candidateTools = projectHostedExecutionTools([...stableHostTools, ...additionalTools], input.toolProfile);
|
|
78
72
|
const selectedTools = input.plan
|
|
79
73
|
? selectCollaborationTools({
|
|
80
74
|
mode: input.plan.mode,
|
|
@@ -145,7 +139,6 @@ export function createInteractiveRunComposer(input) {
|
|
|
145
139
|
input.plan?.mode === 'plan'
|
|
146
140
|
? renderPlanModePrompt({ fullAccess: input.plan.permissionMode === 'bypass' })
|
|
147
141
|
: undefined,
|
|
148
|
-
input.deepResearch ? buildDeepResearchSystemPromptFragment() : undefined,
|
|
149
142
|
input.sideConversation ? buildSideConversationSystemPromptFragment() : undefined,
|
|
150
143
|
]);
|
|
151
144
|
// Keep each turn's source revisions independent while sharing identical
|
|
@@ -320,9 +313,6 @@ export function createInteractiveRunComposerFactory(input) {
|
|
|
320
313
|
},
|
|
321
314
|
}
|
|
322
315
|
: {}),
|
|
323
|
-
...(isDeepResearchSession(backendContext.header.labels) && !backendContext.tools
|
|
324
|
-
? { deepResearch: { tools: requireDeepResearchTools(input.deepResearchTools) } }
|
|
325
|
-
: {}),
|
|
326
316
|
skillBudget: contextWindow === null ? {} : { contextWindow },
|
|
327
317
|
shell,
|
|
328
318
|
...(input.resolveProfileSystemPrompt
|
|
@@ -354,7 +344,7 @@ function assertUniqueToolNames(tools) {
|
|
|
354
344
|
names.add(tool.name);
|
|
355
345
|
}
|
|
356
346
|
}
|
|
357
|
-
function buildDefaultHostTools(sessionTodo, inventoryFor, builtinOptions, hostTools = [], scheduledTaskTool, goalTools = [], parentAgentTools = [], plan
|
|
347
|
+
function buildDefaultHostTools(sessionTodo, inventoryFor, builtinOptions, hostTools = [], scheduledTaskTool, goalTools = [], parentAgentTools = [], plan) {
|
|
358
348
|
// Full access has no boundary to widen, so neither the Bash declaration nor
|
|
359
349
|
// the widening tool is offered. An unknown mode is not Full access.
|
|
360
350
|
const fullAccess = plan?.permissionMode === 'bypass';
|
|
@@ -390,7 +380,6 @@ function buildDefaultHostTools(sessionTodo, inventoryFor, builtinOptions, hostTo
|
|
|
390
380
|
...goalTools.map((tool) => tool.name),
|
|
391
381
|
...parentAgentTools.map((tool) => tool.name),
|
|
392
382
|
...planTools.map((tool) => tool.name),
|
|
393
|
-
...deepResearchTools.map((tool) => tool.name),
|
|
394
383
|
];
|
|
395
384
|
const skillHost = buildHostCapabilitiesFromBinding(toolNames);
|
|
396
385
|
const shadowTracker = new SkillShadowSelectionTracker();
|
|
@@ -406,14 +395,8 @@ function buildDefaultHostTools(sessionTodo, inventoryFor, builtinOptions, hostTo
|
|
|
406
395
|
...goalTools,
|
|
407
396
|
...parentAgentTools,
|
|
408
397
|
...planTools,
|
|
409
|
-
...deepResearchTools,
|
|
410
398
|
];
|
|
411
399
|
}
|
|
412
|
-
function requireDeepResearchTools(tools) {
|
|
413
|
-
if (!tools)
|
|
414
|
-
throw new Error('Runtime Host Deep Research tools are not composed');
|
|
415
|
-
return tools;
|
|
416
|
-
}
|
|
417
400
|
function filterToolGroups(groups, names) {
|
|
418
401
|
const seenIds = new Set();
|
|
419
402
|
return groups.flatMap((group) => {
|