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.
Files changed (61) hide show
  1. package/dist/runtime-host-service-manager.js +1 -6
  2. package/dist/runtime-host-update-command.js +39 -27
  3. package/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
  4. package/node_modules/@maka/core/dist/artifacts.js +1 -0
  5. package/node_modules/@maka/core/dist/model-metadata.js +1 -2
  6. package/node_modules/@maka/core/dist/provider-auth.js +1 -7
  7. package/node_modules/@maka/core/dist/provider-registry.js +13 -7
  8. package/node_modules/@maka/core/dist/recall.js +5 -1
  9. package/node_modules/@maka/core/dist/session-start-mode.js +2 -5
  10. package/node_modules/@maka/core/dist/session.js +0 -1
  11. package/node_modules/@maka/core/dist/settings.js +17 -0
  12. package/node_modules/@maka/core/dist/tool-quiet-preview.js +2 -16
  13. package/node_modules/@maka/core/dist/transcript-search.js +46 -0
  14. package/node_modules/@maka/core/package.json +1 -4
  15. package/node_modules/@maka/runtime/dist/model-factory.js +0 -16
  16. package/node_modules/@maka/runtime/dist/model-fetcher.js +1 -4
  17. package/node_modules/@maka/runtime/dist/model-runtime.js +0 -8
  18. package/node_modules/@maka/runtime/dist/recall-tools.js +4 -0
  19. package/node_modules/@maka/runtime/dist/session-manager.js +4 -13
  20. package/node_modules/@maka/runtime/dist/subagent-tools.js +69 -11
  21. package/node_modules/@maka/runtime/dist/test-connection.js +1 -48
  22. package/node_modules/@maka/runtime/package.json +0 -1
  23. package/node_modules/@maka/runtime-host/dist/client/host-handoff-copy.js +25 -18
  24. package/node_modules/@maka/runtime-host/dist/client/host-handoff.js +3 -1
  25. package/node_modules/@maka/runtime-host/dist/protocol/connection-effects.js +0 -108
  26. package/node_modules/@maka/runtime-host/dist/protocol/index.js +6 -1
  27. package/node_modules/@maka/runtime-host/dist/protocol/operations.js +4 -5
  28. package/node_modules/@maka/runtime-host/dist/protocol/recall.js +270 -0
  29. package/node_modules/@maka/runtime-host/dist/protocol/session-continuity.js +1 -7
  30. package/node_modules/@maka/runtime-host/dist/protocol/usage-screen.js +12 -4
  31. package/node_modules/@maka/runtime-host/dist/server/access-credential-store.js +4 -0
  32. package/node_modules/@maka/runtime-host/dist/server/connection-effect-coordinator.js +1 -57
  33. package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +11 -33
  34. package/node_modules/@maka/runtime-host/dist/server/interactive-run-composer.js +3 -20
  35. package/node_modules/@maka/runtime-host/dist/server/recall-coordinator.js +117 -0
  36. package/node_modules/@maka/runtime-host/dist/server/session-revision-coordinator.js +0 -4
  37. package/node_modules/@maka/storage/dist/artifact-metadata-codec.js +4 -3
  38. package/node_modules/@maka/storage/dist/artifact-store.js +1 -11
  39. package/node_modules/@maka/storage/dist/process-lifetime-file-update-lock.js +0 -41
  40. package/node_modules/@maka/storage/dist/runtime-policy/coordinator.js +0 -28
  41. package/node_modules/@maka/storage/dist/runtime-policy-stores.js +0 -2
  42. package/node_modules/@maka/storage/dist/sqlite-usage-schema.js +29 -5
  43. package/node_modules/@maka/storage/dist/sqlite-workflow-schema.js +2 -0
  44. package/node_modules/@maka/storage/dist/storage-writer-composition.js +0 -3
  45. package/node_modules/@maka/storage/dist/telemetry-file-schema.js +5 -3
  46. package/node_modules/@maka/storage/dist/usage-screen.js +5 -6
  47. package/node_modules/@maka/storage/dist/usage-stores.js +14 -4
  48. package/node_modules/@maka/storage/package.json +0 -2
  49. package/package.json +1 -1
  50. package/node_modules/@maka/core/dist/connection-usage.js +0 -27
  51. package/node_modules/@maka/core/dist/deep-research-client-progress.js +0 -132
  52. package/node_modules/@maka/core/dist/deep-research-run.js +0 -625
  53. package/node_modules/@maka/core/dist/deep-research.js +0 -208
  54. package/node_modules/@maka/core/dist/thread-search.js +0 -498
  55. package/node_modules/@maka/runtime/dist/commandcode-cli-language-model.js +0 -837
  56. package/node_modules/@maka/runtime/dist/connection-usage.js +0 -232
  57. package/node_modules/@maka/runtime/dist/deep-research-tools.js +0 -732
  58. package/node_modules/@maka/runtime-host/dist/protocol/deep-research.js +0 -233
  59. package/node_modules/@maka/runtime-host/dist/server/deep-research-coordinator.js +0 -116
  60. package/node_modules/@maka/storage/dist/deep-research-authority.js +0 -129
  61. 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 = requireCount(range.from, 'Usage from');
48
- const to = requireCount(range.to, 'Usage 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: text(v.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, effectiveBaseUrl, providerFallbackModelIds, } from '@maka/core/llm-connections';
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/thread-search';
27
+ import { foldForMatch } from '@maka/core/transcript-search';
28
28
  import { runtimeInvocationOutcome, } from '@maka/core/runtime-invocation';
29
- import { isDeepResearchSession, WORKHUB_COORDINATION_SESSION_ID, WORKHUB_COORDINATION_REPLACEMENT_SCHEMA_VERSION, } from '@maka/core/session';
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
- const recallTools = buildRecallTools({
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, input.deepResearch?.tools);
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 unscopedCandidateTools = [...stableHostTools, ...additionalTools];
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, deepResearchTools = []) {
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) => {