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,117 @@
1
+ /*
2
+ * Licensed to the Apache Software Foundation (ASF) under one
3
+ * or more contributor license agreements. See the NOTICE file
4
+ * distributed with this work for additional information
5
+ * regarding copyright ownership. The ASF licenses this file
6
+ * to you under the Apache License, Version 2.0 (the
7
+ * "License"); you may not use this file except in compliance
8
+ * with the License. You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing,
13
+ * software distributed under the License is distributed on an
14
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ * KIND, either express or implied. See the License for the
16
+ * specific language governing permissions and limitations
17
+ * under the License.
18
+ */
19
+ import { runRecall } from '@maka/core/recall';
20
+ /**
21
+ * Serves `recall.query` from the same dependency graph the model's `Recall`
22
+ * tool uses.
23
+ *
24
+ * The point of this coordinator is that it owns no retrieval logic: it hands
25
+ * the request to `runRecall` and projects the answer. Whatever recall can see —
26
+ * privacy gating, archived Sessions, the distilled-fact store — a Client
27
+ * asking over the wire sees the same thing, because there is one implementation
28
+ * and this is not a second one.
29
+ *
30
+ * Unlike the model's tool, no turn is excluded. A tool call runs inside a turn
31
+ * and must not surface that turn's own text back as corroboration; a Client
32
+ * search is not inside any turn, so there is nothing to exclude.
33
+ */
34
+ export class HostRecallCoordinator {
35
+ deps;
36
+ handlers = {
37
+ 'recall.query': (input) => this.#query(input),
38
+ };
39
+ constructor(deps) {
40
+ this.deps = deps;
41
+ }
42
+ async #query(input) {
43
+ try {
44
+ const result = await runRecall(input, this.deps, { includeArchived: true });
45
+ return { ok: true, result: projectRecallResult(result) };
46
+ }
47
+ catch {
48
+ return {
49
+ ok: false,
50
+ error: { code: 'internal_failure', message: 'Recall query failed' },
51
+ };
52
+ }
53
+ }
54
+ }
55
+ /**
56
+ * `RecallQueryResult` is the core result with the Host's field vocabulary.
57
+ *
58
+ * Recall already returns exactly these fields; the projection exists to drop
59
+ * core-internal detail and to make the boundary explicit, so a change to the
60
+ * core shape shows up here rather than silently widening the wire.
61
+ */
62
+ export function projectRecallResult(result) {
63
+ if (!result.ok) {
64
+ return { ok: false, reason: result.reason, message: result.message };
65
+ }
66
+ return {
67
+ ok: true,
68
+ facts: result.facts.map((fact) => ({
69
+ content: fact.content,
70
+ kind: fact.kind,
71
+ observedAt: fact.observedAt,
72
+ })),
73
+ passages: result.passages.map((passage) => projectPassage(passage)),
74
+ gaps: result.gaps,
75
+ searchedEverySession: result.scannedFully,
76
+ };
77
+ }
78
+ function projectPassage(passage) {
79
+ return {
80
+ sessionId: passage.sessionId,
81
+ sessionTitle: passage.sessionTitle,
82
+ ...(passage.turnId ? { turnId: passage.turnId } : {}),
83
+ anchorMessageId: passage.anchorMessageId,
84
+ sequence: passage.sequence,
85
+ messages: passage.messages.map((message) => ({
86
+ messageId: message.messageId,
87
+ role: message.role,
88
+ matchKind: message.matchKind,
89
+ text: message.text,
90
+ timestamp: message.timestamp,
91
+ isAnchor: message.isAnchor,
92
+ ...(message.materials
93
+ ? {
94
+ materials: message.materials.map((material) => ({
95
+ name: material.name,
96
+ kind: material.kind,
97
+ mimeType: material.mimeType,
98
+ bytes: material.bytes,
99
+ ...(material.resource ? { resource: material.resource } : {}),
100
+ ...(material.sourceSessionId && material.materialId
101
+ ? {
102
+ sourceSessionId: material.sourceSessionId,
103
+ materialId: material.materialId,
104
+ }
105
+ : {}),
106
+ })),
107
+ }
108
+ : {}),
109
+ })),
110
+ matchedTerms: passage.matchedTerms,
111
+ score: passage.score,
112
+ ...(passage.lastMessageAt !== undefined ? { lastMessageAt: passage.lastMessageAt } : {}),
113
+ hasMoreBefore: passage.hasMoreBefore,
114
+ hasMoreAfter: passage.hasMoreAfter,
115
+ ...(passage.truncated ? { truncated: true } : {}),
116
+ };
117
+ }
@@ -17,7 +17,6 @@
17
17
  * under the License.
18
18
  */
19
19
  import { createHash, randomUUID } from 'node:crypto';
20
- import { isDeepResearchSession } from '@maka/core/deep-research';
21
20
  import { SIDE_CONVERSATION_SESSION_LABEL } from '@maka/core/side-conversation';
22
21
  import { isWorkHubCoordinationSessionId, isWorkHubCoordinationSessionTarget, sessionRevisionFamilyId, } from '@maka/core/session';
23
22
  import { runtimeHostConversationCopyUnavailableReason } from './host-session-availability.js';
@@ -204,9 +203,6 @@ export class HostSessionRevisionCoordinator {
204
203
  if (sourceHeader.subagentParent) {
205
204
  return copyFailure('operation_conflict', 'Linked child Sessions cannot be copied as ordinary conversations');
206
205
  }
207
- if (isDeepResearchSession(sourceHeader.labels)) {
208
- return copyFailure('operation_unavailable', 'Deep Research Sessions cannot be copied without an exact research ledger boundary');
209
- }
210
206
  const copyUnavailableReason = runtimeHostConversationCopyUnavailableReason(sourceHeader);
211
207
  if (copyUnavailableReason)
212
208
  return copyFailure('operation_unavailable', copyUnavailableReason);
@@ -18,7 +18,6 @@
18
18
  */
19
19
  import { isAbsolute } from 'node:path';
20
20
  import { ARTIFACT_KINDS, ARTIFACT_SOURCES, isArtifactTurnKey, isCanonicalArtifactEntityId, } from '@maka/core/artifacts';
21
- import { isDeepResearchArtifactRole } from '@maka/core/deep-research-run';
22
21
  const ARTIFACT_KIND_SET = new Set(ARTIFACT_KINDS);
23
22
  const ARTIFACT_SOURCE_SET = new Set(ARTIFACT_SOURCES);
24
23
  const ARTIFACT_RECORD_KEYS = new Set([
@@ -104,7 +103,6 @@ function decodeArtifactRecord(value, index) {
104
103
  value.sizeBytes < 0 ||
105
104
  !isOptionalNonEmptyString(value.mimeType) ||
106
105
  !isOptionalNonEmptyString(value.summary) ||
107
- (value.deepResearchRole !== undefined && !isDeepResearchArtifactRole(value.deepResearchRole)) ||
108
106
  typeof value.source !== 'string') {
109
107
  throw invalidMetadataRecord(index);
110
108
  }
@@ -114,7 +112,10 @@ function decodeArtifactRecord(value, index) {
114
112
  if (value.relativePath !== `${value.sessionId}/${value.id}-${value.name}`) {
115
113
  throw invalidMetadataRecord(index);
116
114
  }
117
- return value;
115
+ // Old reports carry a workflow role that no longer has a consumer.
116
+ const record = { ...value };
117
+ delete record.deepResearchRole;
118
+ return record;
118
119
  }
119
120
  function isCompatibleArtifactName(name) {
120
121
  if (name.length === 0 || name.length > 120)
@@ -22,7 +22,6 @@ import { constants as fsConstants } from 'node:fs';
22
22
  import { access, copyFile, lstat, mkdir, open, readFile, realpath, rm, stat, unlink, writeFile, } from 'node:fs/promises';
23
23
  import { basename, dirname, join, relative, sep } from 'node:path';
24
24
  import { ARTIFACT_ENTITY_ID_MAX_CHARS, ARTIFACT_KINDS, ARTIFACT_SOURCES, canUserDeleteArtifact, isArtifactTurnKey, isCanonicalArtifactEntityId, } from '@maka/core/artifacts';
25
- import { isDeepResearchArtifactRole, } from '@maka/core/deep-research-run';
26
25
  import { sniffAttachmentMimeType } from '@maka/core/attachments';
27
26
  import { isSafeRelativeArtifactPath, validateRelativeArtifactPath, } from './artifact-metadata-codec.js';
28
27
  import { withArtifactWriterLock, withLeaseBoundArtifactWriterLock, } from './artifact-writer-lock.js';
@@ -68,10 +67,6 @@ class SqliteArtifactStore {
68
67
  if (!ARTIFACT_SOURCE_SET.has(acceptedInput.source)) {
69
68
  throw new Error('Invalid Artifact source');
70
69
  }
71
- if (acceptedInput.deepResearchRole !== undefined &&
72
- !isDeepResearchArtifactRole(acceptedInput.deepResearchRole)) {
73
- throw new Error('Invalid Artifact deep-research role');
74
- }
75
70
  if (acceptedInput.now !== undefined &&
76
71
  (!Number.isSafeInteger(acceptedInput.now) || acceptedInput.now < 0)) {
77
72
  throw new Error('Invalid Artifact creation time');
@@ -103,9 +98,6 @@ class SqliteArtifactStore {
103
98
  ...(acceptedInput.mimeType ? { mimeType: acceptedInput.mimeType } : {}),
104
99
  source: acceptedInput.source,
105
100
  ...(acceptedInput.summary ? { summary: acceptedInput.summary } : {}),
106
- ...(acceptedInput.deepResearchRole
107
- ? { deepResearchRole: acceptedInput.deepResearchRole }
108
- : {}),
109
101
  }, (targetPath) => writeFile(targetPath, acceptedInput.content, { flag: 'wx' }));
110
102
  });
111
103
  }
@@ -346,7 +338,6 @@ class SqliteArtifactStore {
346
338
  existing.mimeType !== optionalCanonicalText(input.mimeType) ||
347
339
  existing.source !== input.source ||
348
340
  existing.summary !== optionalCanonicalText(input.summary) ||
349
- existing.deepResearchRole !== input.deepResearchRole ||
350
341
  (input.now !== undefined && existing.createdAt !== input.now)) {
351
342
  throw artifactReplayConflict(canonical.id);
352
343
  }
@@ -798,8 +789,7 @@ function sameArtifactRecord(a, b) {
798
789
  a.sizeBytes === b.sizeBytes &&
799
790
  a.mimeType === b.mimeType &&
800
791
  a.source === b.source &&
801
- a.summary === b.summary &&
802
- a.deepResearchRole === b.deepResearchRole);
792
+ a.summary === b.summary);
803
793
  }
804
794
  function assertPageBound(value, allowZero, label) {
805
795
  if (!Number.isSafeInteger(value) || value < (allowZero ? 0 : 1)) {
@@ -22,43 +22,6 @@ import { openStableNativeLockFile, releaseNativeFileLock, tryAcquireNativeFileLo
22
22
  const LOCK_POLL_MS = 25;
23
23
  const LOCK_TIMEOUT_MS = 10_000;
24
24
  const lockGates = new Map();
25
- export async function withLegacyFileUpdateLockLease(targetPath, operation, timeoutMs = LOCK_TIMEOUT_MS) {
26
- const lockPath = `${targetPath}.lock`;
27
- const leasePath = `${targetPath}.lease`;
28
- const supervisionPath = `${targetPath}.supervised`;
29
- const deadline = Date.now() + timeoutMs;
30
- return runWithLockGate(leasePath, deadline, async () => {
31
- const lease = await openStableNativeLockFile(leasePath);
32
- let leased = false;
33
- let supervised = false;
34
- let completed = false;
35
- try {
36
- while (!(leased = tryAcquireNativeFileLock(lease))) {
37
- await waitForLockTurn(lockPath, deadline);
38
- }
39
- // The inherited advisory lease follows the legacy child process. A surviving
40
- // supervision marker therefore proves that its directory lock is ownerless
41
- // once a later process can acquire this lease.
42
- await recoverSupervisedLegacyLock(lockPath, supervisionPath);
43
- await createSupervisionMarker(supervisionPath);
44
- supervised = true;
45
- const result = await operation(lease.fd);
46
- completed = true;
47
- return result;
48
- }
49
- finally {
50
- try {
51
- if (supervised && completed)
52
- await unlink(supervisionPath).catch(ignoreMissing);
53
- }
54
- finally {
55
- if (leased)
56
- releaseNativeFileLock(lease);
57
- await lease.close();
58
- }
59
- }
60
- });
61
- }
62
25
  /**
63
26
  * The callback may pass the lease fd as an extra child stdio descriptor. The
64
27
  * advisory lock then survives a parent crash until that exact child exits.
@@ -93,10 +56,6 @@ export async function withProcessLifetimeFileUpdateLock(targetPath, operation, t
93
56
  }
94
57
  });
95
58
  }
96
- async function createSupervisionMarker(path) {
97
- const marker = await open(path, fsConstants.O_CREAT | fsConstants.O_EXCL | fsConstants.O_WRONLY | fsConstants.O_NOFOLLOW, 0o600);
98
- await marker.close();
99
- }
100
59
  async function recoverSupervisedLegacyLock(lockPath, supervisionPath) {
101
60
  const supervision = await lstat(supervisionPath).catch((error) => {
102
61
  if (isNodeError(error, 'ENOENT'))
@@ -1111,29 +1111,6 @@ export class RuntimePolicyCoordinator {
1111
1111
  });
1112
1112
  }));
1113
1113
  }
1114
- beginConnectionUsage(connectionId) {
1115
- return this.inLane(async (root) => {
1116
- const prepared = await this.prepareConnectionOperation(root, connectionId, 'read_usage');
1117
- if (prepared.kind !== 'ready')
1118
- return prepared;
1119
- const ticket = this.issueTicket('connection_usage', connectionUsageSemanticBasis(prepared));
1120
- return deepFreeze({
1121
- kind: 'ready',
1122
- ticket: ticket,
1123
- connection: structuredClone(prepared.connection),
1124
- secretMaterial: prepared.secretMaterial,
1125
- networkProxy: structuredClone(prepared.networkProxy),
1126
- });
1127
- });
1128
- }
1129
- /**
1130
- * Read-only counterpart of `completeConnectionTest`: nothing was written, so
1131
- * there is no catalog state to revalidate — the ticket is simply spent.
1132
- */
1133
- async completeConnectionUsage(ticket) {
1134
- const claimed = this.claimTicket(ticket, 'connection_usage');
1135
- await this.completeClaimedTicket(claimed, async () => undefined);
1136
- }
1137
1114
  async prepareConnectionOperation(root, connectionId, action) {
1138
1115
  const catalog = await this.catalog.read(root);
1139
1116
  const connection = findConnection(catalog, { connectionId });
@@ -1594,9 +1571,6 @@ function connectionTestSemanticBasis(prepared) {
1594
1571
  model: connectionTestModelBasis(prepared.connection),
1595
1572
  };
1596
1573
  }
1597
- function connectionUsageSemanticBasis(prepared) {
1598
- return { kind: 'connection_usage', ...commonSemanticConnectionBasis(prepared) };
1599
- }
1600
1574
  function isCanonicalConnectionTestModel(connection, modelId) {
1601
1575
  const basis = connectionTestModelBasis(connection);
1602
1576
  // Either source admits: testing a discovered model before enabling it is the
@@ -1709,8 +1683,6 @@ function ticketLabel(kind) {
1709
1683
  return 'model fetch';
1710
1684
  case 'connection_test':
1711
1685
  return 'connection test';
1712
- case 'connection_usage':
1713
- return 'connection usage';
1714
1686
  }
1715
1687
  }
1716
1688
  function networkProxyCredentialLocator() {
@@ -126,8 +126,6 @@ function createWriterFacade(coordinator) {
126
126
  completeConnectionOnboarding: (ticket, input) => coordinator.completeConnectionOnboarding(ticket, input),
127
127
  beginConnectionTest: (connectionId, modelId) => coordinator.beginConnectionTest(connectionId, modelId),
128
128
  completeConnectionTest: (ticket, result) => coordinator.completeConnectionTest(ticket, result),
129
- beginConnectionUsage: (connectionId) => coordinator.beginConnectionUsage(connectionId),
130
- completeConnectionUsage: (ticket) => coordinator.completeConnectionUsage(ticket),
131
129
  },
132
130
  };
133
131
  freezeFacade(stores);
@@ -203,6 +203,7 @@ export function migrateSqliteUsageDatabase(db) {
203
203
 
204
204
  CREATE INDEX IF NOT EXISTS usage_llm_calls_session_ts
205
205
  ON usage_llm_calls(session_id, ts DESC, id);
206
+ DROP INDEX IF EXISTS usage_llm_calls_session_id;
206
207
  `);
207
208
  // A ledger old enough to predate Session attribution has no column to carry
208
209
  // through, and the conversion below reads one.
@@ -224,6 +225,8 @@ export function migrateSqliteUsageDatabase(db) {
224
225
  INSERT OR IGNORE INTO usage_screen_revision VALUES (1, lower(hex(randomblob(16))), 0);
225
226
  CREATE INDEX IF NOT EXISTS usage_llm_calls_screen ON usage_llm_calls(ts DESC, storage_key DESC);
226
227
  CREATE INDEX IF NOT EXISTS usage_tool_invocations_screen ON usage_tool_invocations(ts DESC, storage_key DESC);
228
+ CREATE INDEX IF NOT EXISTS usage_tool_invocations_session_id
229
+ ON usage_tool_invocations(json_extract(record_json, '$.sessionId'));
227
230
  CREATE INDEX IF NOT EXISTS usage_model_call_attempts_screen ON usage_model_call_attempts(completed_at DESC, attempt_id DESC);
228
231
  `);
229
232
  // These are invalidation metadata, never an accounting or repair authority.
@@ -246,11 +249,26 @@ export function migrateSqliteUsageDatabase(db) {
246
249
  for (const event of ['INSERT', 'UPDATE', 'DELETE']) {
247
250
  let when = '';
248
251
  if (table === 'session_metadata') {
249
- // Only title/identity changes affect the Usage activity projection.
252
+ // Metadata only participates in Usage through activity titles. Avoid
253
+ // fencing an open screen for Sessions that have no retained activity.
254
+ const hasUsage = (row) => `(
255
+ EXISTS (SELECT 1 FROM usage_llm_calls WHERE session_id = ${row}.session_id LIMIT 1)
256
+ OR EXISTS (
257
+ SELECT 1 FROM usage_tool_invocations
258
+ WHERE json_extract(record_json, '$.sessionId') = ${row}.session_id LIMIT 1
259
+ )
260
+ OR EXISTS (
261
+ SELECT 1 FROM usage_model_call_attempts
262
+ WHERE session_id = ${row}.session_id LIMIT 1
263
+ )
264
+ )`;
250
265
  when =
251
- event === 'UPDATE'
252
- ? 'WHEN OLD.name IS NOT NEW.name OR OLD.session_id IS NOT NEW.session_id'
253
- : '';
266
+ event === 'INSERT'
267
+ ? `WHEN ${hasUsage('NEW')}`
268
+ : event === 'DELETE'
269
+ ? `WHEN ${hasUsage('OLD')}`
270
+ : `WHEN (OLD.name IS NOT NEW.name OR OLD.session_id IS NOT NEW.session_id)
271
+ AND (${hasUsage('OLD')} OR ${hasUsage('NEW')})`;
254
272
  }
255
273
  else if (table === 'core_agent_run_events') {
256
274
  const old = "OLD.event_type = 'model_call_attempt_recorded'";
@@ -265,7 +283,13 @@ export function migrateSqliteUsageDatabase(db) {
265
283
  ? 'WHEN OLD.latest_model_call_sequence IS NOT NULL'
266
284
  : 'WHEN OLD.latest_model_call_sequence IS NOT NEW.latest_model_call_sequence OR OLD.session_id IS NOT NEW.session_id OR OLD.run_id IS NOT NEW.run_id';
267
285
  }
268
- db.exec(`CREATE TRIGGER IF NOT EXISTS ${table}_screen_${event.toLowerCase()}
286
+ const trigger = `${table}_screen_${event.toLowerCase()}`;
287
+ // Schema v8 originally installed unconditional metadata INSERT/DELETE
288
+ // triggers. Recreate those named triggers so existing databases receive
289
+ // the narrowed predicate as well as fresh databases.
290
+ if (table === 'session_metadata')
291
+ db.exec(`DROP TRIGGER IF EXISTS ${trigger}`);
292
+ db.exec(`CREATE TRIGGER IF NOT EXISTS ${trigger}
269
293
  AFTER ${event} ON ${table} ${when} BEGIN
270
294
  UPDATE usage_screen_revision SET revision = revision + 1 WHERE singleton = 1;
271
295
  END`);
@@ -57,6 +57,8 @@ export function migrateSqliteWorkflowDatabase(db) {
57
57
  UNIQUE (session_id, store_version)
58
58
  );
59
59
 
60
+ -- Retained for existing State Roots: schema validation compares the complete DDL.
61
+ -- The research writer is retired, but its stored events must survive upgrades.
60
62
  CREATE TABLE IF NOT EXISTS workflow_deep_research_events (
61
63
  session_id TEXT NOT NULL,
62
64
  sequence INTEGER NOT NULL CHECK (sequence >= 0),
@@ -19,7 +19,6 @@
19
19
  import { openInteractiveArtifactStoreForWrite } from './artifact-stores.js';
20
20
  import { openInteractiveContextOffloadStoreForWrite } from './context-offload-store.js';
21
21
  import { openInteractiveDailyReviewAuthorityForWrite } from './daily-review-authority.js';
22
- import { openInteractiveDeepResearchStoreForWrite } from './deep-research-authority.js';
23
22
  import { openInteractiveExecutionStoresForWrite } from './execution-stores.js';
24
23
  import { openInteractiveLongTermMemoryStoreForWrite } from './long-term-memory-store.js';
25
24
  import { openInteractiveMemoryBundleStoreForWrite } from './memory-bundle-store.js';
@@ -87,7 +86,6 @@ async function createComposition(lease, options) {
87
86
  }
88
87
  const scheduledTasks = await openWriter(() => openInteractiveScheduledTaskStoreForWrite(lease), closeWriter);
89
88
  const plan = await openWriter(() => openInteractivePlanStoreForWrite(lease), closeWriter);
90
- const deepResearch = await openWriter(() => openInteractiveDeepResearchStoreForWrite(lease), closeWriter);
91
89
  const dailyReview = await openWriter(() => openInteractiveDailyReviewAuthorityForWrite(lease), closeWriter);
92
90
  const goal = execution.goalStore;
93
91
  const memoryBundle = await openWriter(() => openInteractiveMemoryBundleStoreForWrite(lease));
@@ -117,7 +115,6 @@ async function createComposition(lease, options) {
117
115
  runtimePolicy,
118
116
  scheduledTasks,
119
117
  plan,
120
- deepResearch,
121
118
  dailyReview,
122
119
  goal,
123
120
  memoryBundle,
@@ -17,6 +17,7 @@
17
17
  * under the License.
18
18
  */
19
19
  import { MODEL_CALL_KINDS, } from '@maka/core/usage-stats/types';
20
+ import { isUsageTimestamp } from '@maka/core/settings';
20
21
  import { isContextBudgetDiagnostic, isPromptSegmentEstimate } from '@maka/core/usage-record-schema';
21
22
  function exactKeys(shape) {
22
23
  return new Set(Object.keys(shape));
@@ -110,8 +111,8 @@ export function decodePersistedLlmCallRecord(input) {
110
111
  'latencyMs',
111
112
  'costUsd',
112
113
  'startedAt',
113
- 'ts',
114
- ])) {
114
+ ]) ||
115
+ !isUsageTimestamp(input.ts)) {
115
116
  throw invalid('invalid required LLM number');
116
117
  }
117
118
  if (input.cachedInputTokens !== input.cacheHitInputTokens) {
@@ -172,7 +173,8 @@ export function decodePersistedToolInvocationRecord(input) {
172
173
  if (!strings(input, ['id', 'toolName', 'date'])) {
173
174
  throw invalid('invalid required tool string');
174
175
  }
175
- if (!nonNegativeNumbers(input, ['durationMs', 'bytesIn', 'bytesOut', 'startedAt', 'ts'])) {
176
+ if (!nonNegativeNumbers(input, ['durationMs', 'bytesIn', 'bytesOut', 'startedAt']) ||
177
+ !isUsageTimestamp(input.ts)) {
176
178
  throw invalid('invalid required tool number');
177
179
  }
178
180
  if (!['success', 'error', 'aborted'].includes(input.status)) {
@@ -17,6 +17,7 @@
17
17
  * under the License.
18
18
  */
19
19
  import { createHash, randomUUID } from 'node:crypto';
20
+ import { isUsageScreenSearch, isUsageTimestamp, } from '@maka/core/settings';
20
21
  import { acquireOperationalStateDatabase } from './operational-state-store.js';
21
22
  import { CACHE_READ_TOKENS } from './model-call-usage-sql.js';
22
23
  import { TelemetryQueryValidationError } from './telemetry-repo.js';
@@ -201,12 +202,10 @@ export function createUsageScreenReader(root) {
201
202
  };
202
203
  }
203
204
  function validateQuery(query) {
204
- if (!Number.isSafeInteger(query.range.from) ||
205
- !Number.isSafeInteger(query.range.to) ||
206
- query.range.from < 0 ||
205
+ if (!isUsageTimestamp(query.range.from) ||
206
+ !isUsageTimestamp(query.range.to) ||
207
207
  query.range.to < query.range.from ||
208
- typeof query.search !== 'string' ||
209
- query.search.length > 1024 ||
208
+ !isUsageScreenSearch(query.search) ||
210
209
  !['all', 'success', 'error', 'aborted'].includes(query.status)) {
211
210
  throw new TelemetryQueryValidationError('Invalid Usage screen query');
212
211
  }
@@ -246,7 +245,7 @@ function activity(db, query, cursor) {
246
245
  if (!Array.isArray(value) ||
247
246
  value.length !== 4 ||
248
247
  value[0] !== hash(query) ||
249
- !Number.isSafeInteger(value[1]) ||
248
+ !isUsageTimestamp(value[1]) ||
250
249
  value[1] < query.range.from ||
251
250
  value[1] > query.range.to ||
252
251
  !['canonical', 'legacy', 'tool'].includes(value[2]) ||
@@ -110,11 +110,15 @@ export function authenticateInteractiveUsageStoresWriter(stores) {
110
110
  export async function openInteractiveUsageStoresForRead(lease) {
111
111
  const repos = await runWithStorageRootLease(lease, 'interactive', 'read', (root) => openRepos(root, false));
112
112
  let closed = false;
113
+ let barrier = Promise.resolve();
113
114
  let closePromise;
114
115
  const run = (operation) => {
115
116
  if (closed)
116
117
  return Promise.reject(new InteractiveUsageStoresClosedError());
117
- return runWithStorageRootLease(lease, 'interactive', 'read', async () => operation());
118
+ const admitted = runWithStorageRootLease(lease, 'interactive', 'read', async () => operation());
119
+ const settled = admitted.then(() => undefined, () => undefined);
120
+ barrier = Promise.all([barrier, settled]).then(() => undefined);
121
+ return admitted;
118
122
  };
119
123
  const stores = {
120
124
  readUsageScreen: (input) => run(() => repos.screen.read(input)),
@@ -128,8 +132,11 @@ export async function openInteractiveUsageStoresForRead(lease) {
128
132
  if (closePromise)
129
133
  return closePromise;
130
134
  closed = true;
131
- repos.screen.close();
132
- closePromise = closeRepos(repos.telemetry, repos.modelCalls, repos.pricing);
135
+ const accepted = barrier;
136
+ closePromise = accepted.then(async () => {
137
+ repos.screen.close();
138
+ await closeRepos(repos.telemetry, repos.modelCalls, repos.pricing);
139
+ });
133
140
  return closePromise;
134
141
  },
135
142
  };
@@ -230,7 +237,10 @@ function createWriterFacade(lease, telemetry, modelCalls, pricing, screen) {
230
237
  });
231
238
  const read = (operation) => {
232
239
  assertOpen();
233
- return run(operation);
240
+ const admitted = Promise.resolve().then(() => run(operation));
241
+ const settled = admitted.then(() => undefined, () => undefined);
242
+ barrier = Promise.all([barrier, settled]).then(() => undefined);
243
+ return admitted;
234
244
  };
235
245
  const beginDrain = () => {
236
246
  if (drainPromise)
@@ -13,8 +13,6 @@
13
13
  "./tool-result-archive-evidence": "./dist/tool-result-archive-evidence.js",
14
14
  "./credential-store": "./dist/credential-store.js",
15
15
  "./daily-review-authority": "./dist/daily-review-authority.js",
16
- "./deep-research-authority": "./dist/deep-research-authority.js",
17
- "./deep-research-store": "./dist/deep-research-store.js",
18
16
  "./encrypted-file-managed-secret-store": "./dist/encrypted-file-managed-secret-store.js",
19
17
  "./execution-stores": "./dist/execution-stores.js",
20
18
  "./execution-persistence-provider": "./dist/execution-persistence-provider.js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "maka-agent",
3
- "version": "0.2.0-dev.44.20260920",
3
+ "version": "0.2.0-dev.45.20260921",
4
4
  "description": "Apache Maka (Incubating) developer snapshot; not an Apache release.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -1,27 +0,0 @@
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
- * The providers Maka can read account usage from. The single source of truth
21
- * for both the settings section's visibility and the runtime dispatch, so a
22
- * provider that gains a mapper is offered the card in the same change.
23
- */
24
- const USAGE_PROVIDERS = new Set(['commandcode-go']);
25
- export function providerReportsUsage(providerType) {
26
- return USAGE_PROVIDERS.has(providerType);
27
- }