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
@@ -46,6 +46,7 @@ const AGENT_LIST_PAGE_SIZE = 8;
46
46
  const AGENT_LIST_MAX_RESPONSE_CHARS = 7_000;
47
47
  const AGENT_LIST_DESCRIPTION_MAX_CHARS = 240;
48
48
  const AGENT_LIST_MODEL_MAX_CHARS = 160;
49
+ const CHILD_EXECUTOR_SELECTION_GUIDANCE = 'Use executor_mode=inherit for the preset or inherited execution route; executor_id is then ignored. Use executor_mode=plugin only for an explicitly selected registered plugin executor. Without executor_mode, omit executor_id to inherit; "default" is not a default selector.';
49
50
  /**
50
51
  * Which schema fields each `agent_output` locator needs. A rejection that only
51
52
  * says "its matching identity fields" leaves the model guessing which of the
@@ -76,22 +77,34 @@ export function buildSubagentSpawnTool(deps = {}) {
76
77
  return {
77
78
  name: AGENT_SPAWN_TOOL_NAME,
78
79
  displayName: 'Agent',
79
- description: 'Run one bounded foreground child task. Prefer agent_list, then select the user-approved subagent_id whose description fits the task; profile is retained for legacy callers. If both selectors are present, subagent_id wins and profile is ignored.',
80
+ description: "Run one bounded foreground child task. Call agent_list and copy an available choice's spawn_args, then add task. target_kind=profile uses profile; target_kind=preset uses subagent_id. The unused selector is ignored. Empty presets does not disable built-in profiles. Without target_kind, subagent_id takes precedence for legacy callers. Independent child tasks may be called together in one parallel batch, including corrected retries after selector errors. " +
81
+ CHILD_EXECUTOR_SELECTION_GUIDANCE,
80
82
  parameters: z.preprocess(cleanSubagentSpawnInput, z
81
83
  .object({
82
- profile: z.enum(profiles).optional().describe('Legacy child capability profile.'),
84
+ target_kind: z
85
+ .enum(['profile', 'preset'])
86
+ .optional()
87
+ .describe('Choose profile for legacy_profiles or preset for presets. Only the selected identity field is used; the other is ignored even if populated.'),
88
+ profile: z
89
+ .enum(profiles)
90
+ .optional()
91
+ .describe('Built-in child capability: copy legacy_profiles[].profile from agent_list.'),
83
92
  subagent_id: z
84
93
  .string()
85
94
  .min(1)
86
95
  .max(128)
87
96
  .refine(isSafeSubagentPresetId)
88
97
  .optional()
89
- .describe('User-approved subagent preset id from agent_list.'),
98
+ .describe('For target_kind=preset, copy presets[].subagent_id from agent_list. Ignored for target_kind=profile.'),
99
+ executor_mode: z
100
+ .enum(['inherit', 'plugin'])
101
+ .optional()
102
+ .describe(CHILD_EXECUTOR_SELECTION_GUIDANCE),
90
103
  executor_id: z
91
104
  .string()
92
105
  .refine(isExecutorId)
93
106
  .optional()
94
- .describe('Plugin executor id for this child task.'),
107
+ .describe(CHILD_EXECUTOR_SELECTION_GUIDANCE),
95
108
  task: z
96
109
  .string()
97
110
  .min(1)
@@ -108,12 +121,30 @@ export function buildSubagentSpawnTool(deps = {}) {
108
121
  })
109
122
  .strip()
110
123
  .superRefine((input, ctx) => {
111
- if (!input.profile && !input.subagent_id) {
124
+ if (input.executor_mode === 'plugin' && !input.executor_id) {
112
125
  ctx.addIssue({
113
126
  code: z.ZodIssueCode.custom,
114
- message: 'No child selector was provided. Call agent_list and pass a returned subagent_id to agent_spawn, ' +
115
- `or pass one legacy profile: ${profiles.join(', ')}.`,
127
+ path: ['executor_id'],
128
+ message: 'executor_mode=plugin requires a registered executor_id. Use executor_mode=inherit for normal child execution.',
116
129
  });
130
+ }
131
+ if (!input.profile && !input.subagent_id) {
132
+ if (input.target_kind) {
133
+ const selector = input.target_kind === 'profile' ? 'profile' : 'subagent_id';
134
+ const catalogSection = input.target_kind === 'profile' ? 'legacy_profiles' : 'presets';
135
+ ctx.addIssue({
136
+ code: z.ZodIssueCode.custom,
137
+ path: [selector],
138
+ message: `target_kind=${input.target_kind} requires ${selector}. Call agent_list and copy an available ${catalogSection} choice's spawn_args, then add task.`,
139
+ });
140
+ }
141
+ else {
142
+ ctx.addIssue({
143
+ code: z.ZodIssueCode.custom,
144
+ message: 'No child selector was provided. Call agent_list and pass a returned subagent_id to agent_spawn, ' +
145
+ `or pass one legacy profile: ${profiles.join(', ')}.`,
146
+ });
147
+ }
117
148
  return;
118
149
  }
119
150
  if (input.subagent_id)
@@ -185,8 +216,12 @@ function cleanSubagentSpawnInput(input) {
185
216
  if (!input || typeof input !== 'object' || Array.isArray(input))
186
217
  return input;
187
218
  const cleaned = { ...input };
188
- if (cleaned.subagent_id !== undefined)
219
+ if (cleaned.target_kind === 'profile')
220
+ delete cleaned.subagent_id;
221
+ else if (cleaned.target_kind === 'preset' || cleaned.subagent_id !== undefined)
189
222
  delete cleaned.profile;
223
+ if (cleaned.executor_mode === 'inherit')
224
+ delete cleaned.executor_id;
190
225
  return cleaned;
191
226
  }
192
227
  async function resolvePresetDefinition(subagentId, ctx, definitions) {
@@ -205,8 +240,13 @@ async function resolvePresetDefinition(subagentId, ctx, definitions) {
205
240
  !Array.isArray(candidate) &&
206
241
  candidate.id === subagentId &&
207
242
  typeof candidate.profile === 'string');
208
- if (!preset)
209
- throw new Error(`Unknown subagent_id "${subagentId}". Call agent_list first.`);
243
+ if (!preset) {
244
+ const legacy = definitions.find((definition) => definition.profile === subagentId || definition.id === subagentId);
245
+ const recovery = legacy
246
+ ? `"${subagentId}" identifies a built-in agent, not a configured preset. Use ${JSON.stringify({ target_kind: 'profile', profile: legacy.profile, executor_mode: 'inherit' })}, keeping your task. The unused subagent_id and executor_id fields are ignored in these modes.`
247
+ : "Call agent_list and copy an available choice's spawn_args, then add task. presets use subagent_id; legacy_profiles use profile.";
248
+ throw new Error(`Unknown subagent_id "${subagentId}". No child was started. ${recovery} ${CHILD_EXECUTOR_SELECTION_GUIDANCE}`);
249
+ }
210
250
  if (preset.availability?.status !== 'available') {
211
251
  throw new Error(`Subagent preset "${subagentId}" is unavailable.`);
212
252
  }
@@ -249,7 +289,7 @@ export function buildSubagentListTool() {
249
289
  return {
250
290
  name: AGENT_LIST_TOOL_NAME,
251
291
  displayName: 'Agent List',
252
- description: 'List a compact page of subagents to select. The default selection view returns runnable user-approved subagent_id values first, followed by legacy choices with separate agent_id (Graph) and profile (agent_spawn) selectors. Use view=catalog only to diagnose unavailable routes. Child execution history is intentionally excluded; use refs returned by agent_spawn or asynchronous graph work with agent_output.',
292
+ description: "List a compact page of subagents to select. Copy an available choice's spawn_args into agent_spawn and add task. presets use subagent_id; legacy_profiles use profile, including when presets is empty. agent_id is for Graph only. Use view=catalog only to diagnose unavailable routes. Child execution history is intentionally excluded; use refs returned by agent_spawn or asynchronous graph work with agent_output.",
253
293
  parameters: z
254
294
  .object({
255
295
  view: z
@@ -309,6 +349,15 @@ function projectAgentList(catalog, input) {
309
349
  return [
310
350
  {
311
351
  subagent_id: preset.id,
352
+ ...(availability.status === 'available'
353
+ ? {
354
+ spawn_args: {
355
+ target_kind: 'preset',
356
+ subagent_id: preset.id,
357
+ executor_mode: 'inherit',
358
+ },
359
+ }
360
+ : {}),
312
361
  name: boundedCatalogText(preset.name, 128),
313
362
  description: boundedCatalogText(preset.description, AGENT_LIST_DESCRIPTION_MAX_CHARS),
314
363
  profile: preset.profile,
@@ -345,6 +394,15 @@ function projectAgentList(catalog, input) {
345
394
  {
346
395
  agent_id: definition.id,
347
396
  profile: definition.profile,
397
+ ...(availability.status === 'available'
398
+ ? {
399
+ spawn_args: {
400
+ target_kind: 'profile',
401
+ profile: definition.profile,
402
+ executor_mode: 'inherit',
403
+ },
404
+ }
405
+ : {}),
348
406
  name: boundedCatalogText(definition.name, 128),
349
407
  description: boundedCatalogText(definition.description, AGENT_LIST_DESCRIPTION_MAX_CHARS),
350
408
  ...(typeof contract?.workspace === 'string'
@@ -17,12 +17,11 @@
17
17
  * under the License.
18
18
  */
19
19
  import { randomUUID } from 'node:crypto';
20
- import { buildCommandCodeCliRequest, commandCodeCliGenerateUrl, commandCodeCliHeaders, summarizeCommandCodeCliStream, } from './commandcode-cli-language-model.js';
21
20
  import { PROVIDER_REGISTRY, effectiveBaseUrl, providerDefaultsOf, providerFallbackModelIds, connectionModelsEnumerateAccount, connectionEnabledModelIds, } from '@maka/core/llm-connections';
22
21
  import { openResponsesUrl } from './provider-urls.js';
23
22
  import { resolveModelRuntime } from './model-runtime.js';
24
23
  import { fetchGitHubCopilotModels } from './model-fetcher.js';
25
- import { CONNECTION_EFFECT_ERROR_BODY_MAX_BYTES, CONNECTION_EFFECT_JSON_BODY_MAX_BYTES, ConnectionEffectFetchError, fetchForConnectionEffect, } from './connection-effect-fetch.js';
24
+ import { CONNECTION_EFFECT_ERROR_BODY_MAX_BYTES, ConnectionEffectFetchError, fetchForConnectionEffect, } from './connection-effect-fetch.js';
26
25
  import { ConnectionEffectHttpError, ConnectionEffectInvalidResponseError, classifyConnectionEffectStatus, } from './connection-effect-outcome.js';
27
26
  import { withOpenCodeSessionHeader } from './opencode-session-header.js';
28
27
  const CONNECTION_TEST_TIMEOUT_MS = 15_000;
@@ -147,54 +146,8 @@ async function testConnectionModel(connection, secret, testModel, fetchFn, t0, t
147
146
  return await probeGoogle(baseUrl, secret, testModel, t0, adapter.normalizeBaseUrl !== false, fetchFn);
148
147
  case 'cohere':
149
148
  return await probeCohere(baseUrl, secret, testModel, t0, fetchFn);
150
- case 'commandcode-cli':
151
- return await probeCommandCodeCli(baseUrl, secret, testModel, t0, fetchFn, requestHeaders);
152
149
  }
153
150
  }
154
- async function probeCommandCodeCli(baseUrl, apiKey, model, t0, fetchFn, requestHeaders) {
155
- const { body } = buildCommandCodeCliRequest({ prompt: [{ role: 'user', content: [{ type: 'text', text: 'Hi' }] }], maxOutputTokens: 16 }, { modelId: model });
156
- const r = await fetchForConnectionEffect(fetchFn, commandCodeCliGenerateUrl(baseUrl), {
157
- method: 'POST',
158
- headers: { ...commandCodeCliHeaders(apiKey, 'maka'), ...(requestHeaders ?? {}) },
159
- body: JSON.stringify(body),
160
- timeoutMs: CONNECTION_TEST_TIMEOUT_MS,
161
- });
162
- if (!r.ok)
163
- return httpFailure(r, t0);
164
- // HTTP 200 is only the handshake on this wire. The generation adapter fails
165
- // the send on an in-band `error` event and on a stream that ends without a
166
- // `finish`, so a probe that stopped at the status would store a connection
167
- // as verified whose very next send is rejected.
168
- const outcome = summarizeCommandCodeCliStream(await r.readText(CONNECTION_EFFECT_JSON_BODY_MAX_BYTES));
169
- const latencyMs = Date.now() - t0;
170
- if (outcome.error) {
171
- const { message, statusCode } = outcome.error;
172
- return {
173
- ok: false,
174
- latencyMs,
175
- errorMessage: message.slice(0, 200),
176
- ...(statusCode === undefined ? {} : { statusCode }),
177
- errorClass: commandCodeCliStreamErrorClass(statusCode),
178
- };
179
- }
180
- if (!outcome.finished) {
181
- return {
182
- ok: false,
183
- latencyMs,
184
- errorMessage: 'The Command Code GO stream ended before the turn finished',
185
- errorClass: 'network',
186
- };
187
- }
188
- return { ok: true, latencyMs, modelTested: model };
189
- }
190
- function commandCodeCliStreamErrorClass(statusCode) {
191
- if (statusCode === 401 || statusCode === 403)
192
- return 'auth';
193
- if (statusCode === 429 || (statusCode !== undefined && statusCode >= 500)) {
194
- return 'provider_unavailable';
195
- }
196
- return 'unknown';
197
- }
198
151
  async function probeGitHubCopilot(baseUrl, apiKey, model, t0, fetchFn) {
199
152
  const models = await fetchGitHubCopilotModels(baseUrl, apiKey, fetchFn);
200
153
  if (!models.some(({ id }) => id === model)) {
@@ -13,7 +13,6 @@
13
13
  "./shell-tools": "./dist/shell-tools.js",
14
14
  "./shell-run-manager": "./dist/shell-run-manager.js",
15
15
  "./background-task-health-tool": "./dist/background-task-health-tool.js",
16
- "./deep-research-tools": "./dist/deep-research-tools.js",
17
16
  "./durable-tool-result-projection": "./dist/durable-tool-result-projection.js",
18
17
  "./tool-artifacts": "./dist/tool-artifacts.js",
19
18
  "./model-factory": "./dist/model-factory.js",
@@ -186,6 +186,25 @@ const COPY = {
186
186
  /** Shared consequence-oriented copy, not a second lifecycle policy. */
187
187
  export function formatHostHandoff(view, locale) {
188
188
  const copy = COPY[locale];
189
+ const labels = {
190
+ cancel: copy.labels.cancel,
191
+ retry: view.manualRecheck ? copy.labels.recheck : copy.labels.retry,
192
+ replace: copy.labels.replace,
193
+ interrupt: view.manualRecheck
194
+ ? copy.labels.interruptRecheck
195
+ : view.operation === 'repair'
196
+ ? copy.labels.interruptRepair
197
+ : copy.labels.interrupt,
198
+ };
199
+ const actions = view.actions.map((action) => ({ action, label: labels[action] }));
200
+ if (view.state === 'progress') {
201
+ return {
202
+ title: copy.progressTitle,
203
+ description: copy.phases[view.phase],
204
+ detail: copy.progressDetail,
205
+ actions,
206
+ };
207
+ }
189
208
  let title = copy.titles[view.reason];
190
209
  let description = copy.descriptions(view.target.name)[view.reason];
191
210
  if (view.recoveryBlocker && view.reason === 'operator_required') {
@@ -215,24 +234,12 @@ export function formatHostHandoff(view, locale) {
215
234
  ? copy.waiting.natural
216
235
  : copy.waiting.blocked;
217
236
  const repairNotice = view.operation === 'repair' ? copy.repairNotice : '';
218
- const labels = {
219
- cancel: copy.labels.cancel,
220
- retry: view.manualRecheck ? copy.labels.recheck : copy.labels.retry,
221
- replace: copy.labels.replace,
222
- interrupt: view.manualRecheck
223
- ? copy.labels.interruptRecheck
224
- : view.operation === 'repair'
225
- ? copy.labels.interruptRepair
226
- : copy.labels.interrupt,
227
- };
228
237
  return {
229
- title: view.state === 'progress' ? copy.progressTitle : title,
230
- description: view.state === 'progress' ? copy.phases[view.phase ?? 'checking'] : description,
231
- detail: view.state === 'progress'
232
- ? copy.progressDetail
233
- : [packageChange, facts, backgroundFacts, waiting, repairNotice, view.operatorStep]
234
- .filter(Boolean)
235
- .join('\n'),
236
- actions: view.actions.map((action) => ({ action, label: labels[action] })),
238
+ title,
239
+ description,
240
+ detail: [packageChange, facts, backgroundFacts, waiting, repairNotice, view.operatorStep]
241
+ .filter(Boolean)
242
+ .join('\n'),
243
+ actions,
237
244
  };
238
245
  }
@@ -172,11 +172,13 @@ export async function runHostHandoff(input) {
172
172
  ? AbortSignal.any([input.signal, attemptAbort.signal])
173
173
  : attemptAbort.signal;
174
174
  const progress = (phase) => publish({
175
- ...current,
176
175
  revision: randomUUID(),
176
+ target: current.target,
177
177
  state: 'progress',
178
178
  phase: cooperative && !interrupt && phase === 'retiring' ? 'pausing' : phase,
179
179
  actions: cancelled ? [] : ['cancel'],
180
+ defaultAction: 'cancel',
181
+ mayExitNaturally: false,
180
182
  });
181
183
  if (input.openSurface)
182
184
  surface ??= input.openSurface(submit);
@@ -29,13 +29,6 @@ const EFFECT_ERRORS = [
29
29
  'persistence_failed',
30
30
  'commit_outcome_unknown',
31
31
  ];
32
- /**
33
- * Upper bound on the quota windows one usage report may carry. The producer
34
- * emits three today (5-hour, weekly, monthly); the cap exists because a decoder
35
- * is the boundary that does not trust its producer, matching how every other
36
- * array in this package is bounded before mapping.
37
- */
38
- const CONNECTION_USAGE_MAX_WINDOWS = 16;
39
32
  export const CONNECTION_EFFECT_CHANGED_DOMAINS = [
40
33
  'connection',
41
34
  'credential',
@@ -84,13 +77,6 @@ export const CONNECTION_EFFECT_OPERATION_SPECS = {
84
77
  decodeInput: decodeConnectionTestRunInput,
85
78
  decodeOutput: decodeConnectionTestRunResult,
86
79
  }),
87
- 'connection.usage.read': defineOperation({
88
- mode: 'query',
89
- availability: 'ready',
90
- errors: EFFECT_ERRORS,
91
- decodeInput: decodeConnectionUsageReadInput,
92
- decodeOutput: decodeConnectionUsageReadResult,
93
- }),
94
80
  };
95
81
  export function decodeConnectionOnboardingSaveInput(value) {
96
82
  const input = requireExactRecord(value, 'connection onboarding save input', [
@@ -296,100 +282,6 @@ export function decodeConnectionTestRunResult(value) {
296
282
  }
297
283
  return decodeNonEffectResult(result, 'connection test result');
298
284
  }
299
- export function decodeConnectionUsageReadInput(value) {
300
- const input = requireExactRecord(value, 'connection usage input', ['connectionId']);
301
- return { connectionId: requireEntityId(input.connectionId, 'connectionId') };
302
- }
303
- export function decodeConnectionUsageReadResult(value) {
304
- const result = requireRecord(value, 'connection usage result');
305
- if (result.kind === 'report') {
306
- const report = requireExactRecord(result, 'connection usage report', ['kind', 'report']);
307
- return { kind: 'report', report: decodeUsageReport(report.report) };
308
- }
309
- if (result.kind === 'unavailable') {
310
- const unavailable = requireExactRecord(result, 'connection usage unavailable', [
311
- 'kind',
312
- 'reason',
313
- ]);
314
- if (unavailable.reason !== 'unsupported' &&
315
- unavailable.reason !== 'network' &&
316
- unavailable.reason !== 'no-credential' &&
317
- unavailable.reason !== 'unauthorized') {
318
- throw invalidProtocolFrame('Invalid connection usage unavailable reason');
319
- }
320
- return { kind: 'unavailable', reason: unavailable.reason };
321
- }
322
- if (result.kind === 'rejected') {
323
- const rejected = requireExactRecord(result, 'connection usage result', ['kind', 'reason']);
324
- return { kind: 'rejected', reason: rejectionReason(rejected.reason) };
325
- }
326
- throw invalidProtocolFrame('Invalid connection usage result');
327
- }
328
- function decodeUsageReport(value) {
329
- const report = requireExactRecord(value, 'connection usage report body', [
330
- 'accountLabel',
331
- 'planLabel',
332
- 'stats',
333
- 'windows',
334
- 'periodEnd',
335
- 'partiallyUnauthorized',
336
- 'fetchedAt',
337
- ]);
338
- if (!Array.isArray(report.windows) || report.windows.length > CONNECTION_USAGE_MAX_WINDOWS) {
339
- throw invalidProtocolFrame('Invalid connection usage windows');
340
- }
341
- return {
342
- accountLabel: optionalText(report.accountLabel, 'account label'),
343
- planLabel: optionalText(report.planLabel, 'plan label'),
344
- stats: report.stats === null ? null : decodeUsageStats(report.stats),
345
- windows: report.windows.map(decodeUsageWindow),
346
- periodEnd: optionalMillis(report.periodEnd, 'period end'),
347
- partiallyUnauthorized: requireBoolean(report.partiallyUnauthorized, 'partially unauthorized'),
348
- fetchedAt: requireCount(report.fetchedAt, 'usage fetchedAt'),
349
- };
350
- }
351
- function decodeUsageStats(value) {
352
- const stats = requireExactRecord(value, 'connection usage stats', [
353
- 'requests',
354
- 'failed',
355
- 'successRate',
356
- 'cost',
357
- 'tokensIn',
358
- 'tokensOut',
359
- ]);
360
- return {
361
- requests: optionalCount(stats.requests, 'requests'),
362
- failed: optionalCount(stats.failed, 'failed'),
363
- successRate: optionalAmount(stats.successRate, 'success rate'),
364
- cost: optionalAmount(stats.cost, 'cost'),
365
- tokensIn: optionalCount(stats.tokensIn, 'tokens in'),
366
- tokensOut: optionalCount(stats.tokensOut, 'tokens out'),
367
- };
368
- }
369
- function decodeUsageWindow(value) {
370
- const window = requireExactRecord(value, 'connection usage window', [
371
- 'id',
372
- 'label',
373
- 'used',
374
- 'cap',
375
- 'unit',
376
- 'resetsAt',
377
- 'unlimited',
378
- ]);
379
- const unit = window.unit;
380
- if (unit !== 'credits' && unit !== 'usd' && unit !== 'tokens') {
381
- throw invalidProtocolFrame('Invalid connection usage unit');
382
- }
383
- return {
384
- id: requireUtf8String(window.id, 'usage window id', 64),
385
- label: optionalText(window.label, 'usage window label'),
386
- used: requireAmount(window.used, 'usage window used'),
387
- cap: requireAmount(window.cap, 'usage window cap'),
388
- unit,
389
- resetsAt: optionalMillis(window.resetsAt, 'usage window reset'),
390
- unlimited: window.unlimited === null ? null : requireBoolean(window.unlimited, 'unlimited'),
391
- };
392
- }
393
285
  function optionalText(value, label) {
394
286
  return value === null ? null : requireUtf8String(value, label, 256);
395
287
  }
@@ -62,7 +62,12 @@ export const RUNTIME_HOST_REGISTRATION_SCHEMA_VERSION = 1;
62
62
  export const RUNTIME_HOST_PROTOCOL_VERSION = 0;
63
63
  // Increment when the same protocol version no longer guarantees safe Client-Host
64
64
  // interoperability. Mismatches are rejected before domain commands are admitted.
65
- export const RUNTIME_HOST_COMPATIBILITY_EPOCH = 169;
65
+ export const RUNTIME_HOST_COMPATIBILITY_EPOCH = 172;
66
+ // 172: Usage screen requests and results accept fractional timestamps in the
67
+ // persisted domain. Older peers reject these otherwise valid wire values.
68
+ // 171: Removed the `connection.usage.read` operation along with the Command
69
+ // Code GO provider it served. A peer older than this epoch may still advertise
70
+ // or submit that operation, which this Host no longer answers.
66
71
  // 169: The message execution query reports an identity the Host can prove was
67
72
  // never admitted as a positive `not_admitted` resolution instead of omitting
68
73
  // it, so silence stops meaning both "not admitted" and "cannot say yet".
@@ -22,7 +22,6 @@ import { AGENT_GRAPH_OPERATION_SPECS } from './agent-graph.js';
22
22
  import { requireExactRecord, requireId, requireRecord, requireString } from './codec.js';
23
23
  import { CONNECTION_EFFECT_OPERATION_SPECS } from './connection-effects.js';
24
24
  import { CONFIGURATION_OPERATION_SPECS } from './configuration.js';
25
- import { DEEP_RESEARCH_OPERATION_SPECS } from './deep-research.js';
26
25
  import { DAILY_REVIEW_OPERATION_SPECS } from './daily-review.js';
27
26
  import { CONTEXT_OPERATION_SPECS } from './context.js';
28
27
  import { EXECUTION_INSPECT_OPERATION_SPECS } from './execution-inspect.js';
@@ -61,6 +60,7 @@ import { SKILL_CATALOG_OPERATION_SPECS } from './skill-catalog.js';
61
60
  import { TURN_OPERATION_SPECS } from './turn.js';
62
61
  import { USAGE_PRICING_OPERATION_SPECS } from './usage-pricing.js';
63
62
  import { WEB_SEARCH_OPERATION_SPECS } from './web-search.js';
63
+ import { RECALL_OPERATION_SPECS } from './recall.js';
64
64
  import { WORKHUB_COORDINATION_OPERATION_SPECS } from './workhub-coordination.js';
65
65
  export { isHostActivityIdle } from './host-status.js';
66
66
  export { ARTIFACT_CURSOR_MAX_BYTES, ARTIFACT_INGEST_CHUNK_MAX_BYTES, ARTIFACT_INGEST_MIME_TYPE_MAX_BYTES, ARTIFACT_MIME_TYPE_MAX_BYTES, ARTIFACT_NAME_MAX_BYTES, ARTIFACT_PAGE_MAX_ITEMS, ARTIFACT_PREVIEW_MAX_BYTES, ARTIFACT_READ_CHUNK_MAX_BYTES, ARTIFACT_RESULT_MAX_BYTES, ARTIFACT_SUMMARY_MAX_BYTES, decodeArtifactDeleteInput, decodeArtifactDeleteResult, decodeArtifactIngestInput, decodeArtifactIngestResult, decodeArtifactQueryInput, decodeArtifactQueryResult, encodeArtifactDeleteResult, encodeArtifactQueryResult, } from './artifact.js';
@@ -68,7 +68,6 @@ export { TURN_FAILURE_MESSAGE_MAX_BYTES, TURN_MESSAGE_CONTENT_MAX_BYTES, TURN_ME
68
68
  export * from './connection-effects.js';
69
69
  export * from './access-authority.js';
70
70
  export * from './configuration.js';
71
- export * from './deep-research.js';
72
71
  export * from './daily-review.js';
73
72
  export * from './context.js';
74
73
  export * from './agent-graph.js';
@@ -97,8 +96,9 @@ export * from './session-effects.js';
97
96
  export * from './skill-catalog.js';
98
97
  export * from './usage-pricing.js';
99
98
  export * from './web-search.js';
99
+ export * from './recall.js';
100
100
  export * from './workspace.js';
101
- export const HOST_OPERATION_SPECS = composeOperationSpecMaps(HOST_BOOTSTRAP_OPERATION_SPECS, HOST_RESOURCE_OPERATION_SPECS, PEER_MESH_OPERATION_SPECS, HOSTED_EXECUTION_OPERATION_SPECS, ACCESS_AUTHORITY_OPERATION_SPECS, SESSION_COLLABORATION_OPERATION_SPECS, AGENT_GRAPH_OPERATION_SPECS, GOAL_OPERATION_SPECS, TURN_OPERATION_SPECS, CONTEXT_OPERATION_SPECS, CONNECTION_EFFECT_OPERATION_SPECS, DEEP_RESEARCH_OPERATION_SPECS, DAILY_REVIEW_OPERATION_SPECS, EXECUTION_INSPECT_OPERATION_SPECS, EXTERNAL_SESSION_OPERATION_SPECS, RUNTIME_POLICY_OPERATION_SPECS, RUNTIME_RESOURCE_OPERATION_SPECS, SCHEDULED_TASK_OPERATION_SPECS, PLAN_OPERATION_SPECS, PROJECT_CATALOG_OPERATION_SPECS, MESSAGE_OPERATION_SPECS, SESSION_TODO_OPERATION_SPECS, INTERACTION_OPERATION_SPECS, SESSION_CONTINUITY_OPERATION_SPECS, SESSION_TRANSCRIPT_OPERATION_SPECS, SESSION_TURNS_OPERATION_SPECS, SESSION_CATALOG_OPERATION_SPECS, SESSION_EFFECT_OPERATION_SPECS, SESSION_REVISION_OPERATION_SPECS, SESSION_BUNDLE_OPERATION_SPECS, SESSION_RETIREMENT_OPERATION_SPECS, ARTIFACT_OPERATION_SPECS, SKILL_CATALOG_OPERATION_SPECS, USAGE_PRICING_OPERATION_SPECS, MEMORY_OPERATION_SPECS, OAUTH_OPERATION_SPECS, EXTERNAL_AGENT_SETUP_OPERATION_SPECS, CLIENT_CAPABILITY_OPERATION_SPECS, WEB_SEARCH_OPERATION_SPECS, NETWORK_PROXY_OPERATION_SPECS, CONFIGURATION_OPERATION_SPECS, WORKHUB_COORDINATION_OPERATION_SPECS, PLUGIN_PLATFORM_OPERATION_SPECS);
101
+ export const HOST_OPERATION_SPECS = composeOperationSpecMaps(HOST_BOOTSTRAP_OPERATION_SPECS, HOST_RESOURCE_OPERATION_SPECS, PEER_MESH_OPERATION_SPECS, HOSTED_EXECUTION_OPERATION_SPECS, ACCESS_AUTHORITY_OPERATION_SPECS, SESSION_COLLABORATION_OPERATION_SPECS, AGENT_GRAPH_OPERATION_SPECS, GOAL_OPERATION_SPECS, TURN_OPERATION_SPECS, CONTEXT_OPERATION_SPECS, CONNECTION_EFFECT_OPERATION_SPECS, DAILY_REVIEW_OPERATION_SPECS, EXECUTION_INSPECT_OPERATION_SPECS, EXTERNAL_SESSION_OPERATION_SPECS, RUNTIME_POLICY_OPERATION_SPECS, RUNTIME_RESOURCE_OPERATION_SPECS, SCHEDULED_TASK_OPERATION_SPECS, PLAN_OPERATION_SPECS, PROJECT_CATALOG_OPERATION_SPECS, MESSAGE_OPERATION_SPECS, SESSION_TODO_OPERATION_SPECS, INTERACTION_OPERATION_SPECS, SESSION_CONTINUITY_OPERATION_SPECS, SESSION_TRANSCRIPT_OPERATION_SPECS, SESSION_TURNS_OPERATION_SPECS, SESSION_CATALOG_OPERATION_SPECS, SESSION_EFFECT_OPERATION_SPECS, SESSION_REVISION_OPERATION_SPECS, SESSION_BUNDLE_OPERATION_SPECS, SESSION_RETIREMENT_OPERATION_SPECS, ARTIFACT_OPERATION_SPECS, SKILL_CATALOG_OPERATION_SPECS, USAGE_PRICING_OPERATION_SPECS, MEMORY_OPERATION_SPECS, OAUTH_OPERATION_SPECS, EXTERNAL_AGENT_SETUP_OPERATION_SPECS, CLIENT_CAPABILITY_OPERATION_SPECS, WEB_SEARCH_OPERATION_SPECS, NETWORK_PROXY_OPERATION_SPECS, RECALL_OPERATION_SPECS, CONFIGURATION_OPERATION_SPECS, WORKHUB_COORDINATION_OPERATION_SPECS, PLUGIN_PLATFORM_OPERATION_SPECS);
102
102
  // Remote credentials are fail-closed: adding a protocol operation does not
103
103
  // grant it to remote owners until this policy is deliberately updated.
104
104
  export const REMOTE_OWNER_OPERATION_GRANTS = Object.freeze([
@@ -131,7 +131,6 @@ export const REMOTE_OWNER_OPERATION_GRANTS = Object.freeze([
131
131
  'connection.request-headers.query',
132
132
  'connection.request-headers.replace',
133
133
  'connection.test.run',
134
- 'connection.usage.read',
135
134
  'context.compact',
136
135
  'context.diagnostics.query',
137
136
  'credential.vault.delete',
@@ -139,7 +138,6 @@ export const REMOTE_OWNER_OPERATION_GRANTS = Object.freeze([
139
138
  'credential.vault.set',
140
139
  'daily-review.mutate',
141
140
  'daily-review.query',
142
- 'deep-research.query',
143
141
  'execution.inspect.query',
144
142
  'external-session.catalog.query',
145
143
  'external-session.import',
@@ -179,6 +177,7 @@ export const REMOTE_OWNER_OPERATION_GRANTS = Object.freeze([
179
177
  'runtime.policy.mutate',
180
178
  'runtime.policy.network-proxy.update',
181
179
  'runtime.policy.query',
180
+ 'recall.query',
182
181
  'runtime.resource.controller.acquire',
183
182
  'runtime.resource.controller.control',
184
183
  'runtime.resource.controller.release',