maka-agent 0.2.0-dev.24.20260907 → 0.2.0-dev.26.20260909
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -19
- package/README.zh-CN.md +34 -19
- package/dist/mcp-capability-provider.js +4 -1
- package/dist/pi-transcript-tools.js +6 -0
- package/dist/pi-tui-layout.js +56 -10
- package/dist/pi-tui-mcp-status.js +2 -2
- package/dist/pi-tui-pickers.js +121 -30
- package/dist/pi-tui-runner.js +156 -42
- package/dist/pi-tui-todo.js +221 -0
- package/dist/pi-tui-transcript-viewer.js +134 -7
- package/dist/runtime-host-cli-context.js +70 -13
- package/dist/runtime-host-handoff-surface.js +51 -26
- package/dist/runtime-host-local-handoff.js +11 -1
- package/dist/runtime-host-service-manager.js +0 -3
- package/dist/runtime-host-session-channel.js +13 -0
- package/dist/runtime-host-session-driver.js +42 -1
- package/dist/tui-autocomplete-layout.js +3 -1
- package/dist/tui-copy-catalog.js +85 -6
- package/dist/tui-editor-render.js +36 -0
- package/dist/tui-mcp-control.js +41 -6
- package/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
- package/node_modules/@maka/core/dist/agent-run.js +1 -0
- package/node_modules/@maka/core/dist/attachments.js +3 -0
- package/node_modules/@maka/core/dist/canonical-json.js +27 -0
- package/node_modules/@maka/core/dist/capabilities.js +35 -0
- package/node_modules/@maka/core/dist/computer-use.js +0 -1
- package/node_modules/@maka/core/dist/display-redaction.js +18 -0
- package/node_modules/@maka/core/dist/llm-connections.js +13 -0
- package/node_modules/@maka/core/dist/model-call-attempt.js +2 -0
- package/node_modules/@maka/core/dist/model-metadata.js +4 -0
- package/node_modules/@maka/core/dist/redaction.js +35 -0
- package/node_modules/@maka/core/dist/run-composition.js +77 -2
- package/node_modules/@maka/core/dist/runtime-event.js +3 -0
- package/node_modules/@maka/core/dist/session.js +57 -6
- package/node_modules/@maka/core/dist/slash-command-catalog.js +1 -0
- package/node_modules/@maka/core/dist/tool-result-record-schema.js +2 -1
- package/node_modules/@maka/core/dist/workhub-action-result.js +68 -0
- package/node_modules/@maka/core/package.json +3 -3
- package/node_modules/@maka/eval/dist/experiment-directory.js +4 -13
- package/node_modules/@maka/eval/dist/toolchain-verification.js +1 -1
- package/node_modules/@maka/mcp/dist/form-elicitation.js +213 -0
- package/node_modules/@maka/mcp/dist/index.js +337 -71
- package/node_modules/@maka/runtime/dist/agent-run-inspect.js +0 -13
- package/node_modules/@maka/runtime/dist/agent-run.js +90 -2
- package/node_modules/@maka/runtime/dist/ai-sdk-backend.js +16 -8
- package/node_modules/@maka/runtime/dist/ai-sdk-turn.js +57 -50
- package/node_modules/@maka/runtime/dist/archive-read-tool.js +2 -2
- package/node_modules/@maka/runtime/dist/context-budget-helpers.js +0 -16
- package/node_modules/@maka/runtime/dist/conversation-copy.js +153 -11
- package/node_modules/@maka/runtime/dist/github-copilot-oauth-enrollment.js +3 -3
- package/node_modules/@maka/runtime/dist/goal-continuation.js +5 -1
- package/node_modules/@maka/runtime/dist/ledger-tool-result-archive-reader.js +69 -1
- package/node_modules/@maka/runtime/dist/mcp-tools.js +7 -2
- package/node_modules/@maka/runtime/dist/model-fetcher.js +42 -2
- package/node_modules/@maka/runtime/dist/model-history.js +0 -112
- package/node_modules/@maka/runtime/dist/plugin-runtime.js +20 -10
- package/node_modules/@maka/runtime/dist/plugin-tool-service.js +205 -0
- package/node_modules/@maka/runtime/dist/provider-request-telemetry.js +8 -1
- package/node_modules/@maka/runtime/dist/request-shape.js +23 -0
- package/node_modules/@maka/runtime/dist/runtime-event-backfill.js +1 -1
- package/node_modules/@maka/runtime/dist/runtime-event-read-model.js +24 -1
- package/node_modules/@maka/runtime/dist/runtime-kernel.js +127 -13
- package/node_modules/@maka/runtime/dist/session-manager.js +20 -36
- package/node_modules/@maka/runtime/dist/stream-graph-coordinator.js +21 -0
- package/node_modules/@maka/runtime/dist/stream-graph-supervisor-tools.js +0 -5
- package/node_modules/@maka/runtime/dist/test-connection.js +0 -1
- package/node_modules/@maka/runtime/dist/tool-activation-identity.js +41 -0
- package/node_modules/@maka/runtime/dist/tool-availability.js +11 -1
- package/node_modules/@maka/runtime/dist/tool-result-archive-resource.js +63 -1
- package/node_modules/@maka/runtime/dist/tool-result-archive-transition.js +42 -12
- package/node_modules/@maka/runtime/dist/tool-result-archive.js +27 -4
- package/node_modules/@maka/runtime/package.json +1 -0
- package/node_modules/@maka/runtime-host/dist/client/connection.js +30 -5
- package/node_modules/@maka/runtime-host/dist/client/host-handoff-copy.js +52 -13
- package/node_modules/@maka/runtime-host/dist/client/host-handoff.js +2 -0
- package/node_modules/@maka/runtime-host/dist/client/host-retirement.js +4 -2
- package/node_modules/@maka/runtime-host/dist/client/peer-client.js +18 -1
- package/node_modules/@maka/runtime-host/dist/client/session-subscription.js +19 -0
- package/node_modules/@maka/runtime-host/dist/control/endpoint.js +1 -3
- package/node_modules/@maka/runtime-host/dist/node-error.js +22 -0
- package/node_modules/@maka/runtime-host/dist/operator/managed-deployment.js +1 -3
- package/node_modules/@maka/runtime-host/dist/peer-mesh/limits.js +0 -1
- package/node_modules/@maka/runtime-host/dist/peer-mesh/model.js +1 -1
- package/node_modules/@maka/runtime-host/dist/peer-reachability/publisher.js +1 -3
- package/node_modules/@maka/runtime-host/dist/protocol/index.js +9 -1
- package/node_modules/@maka/runtime-host/dist/protocol/operations.js +3 -2
- package/node_modules/@maka/runtime-host/dist/protocol/plan.js +1 -0
- package/node_modules/@maka/runtime-host/dist/protocol/plugin-platform.js +27 -5
- package/node_modules/@maka/runtime-host/dist/protocol/project-catalog.js +2 -2
- package/node_modules/@maka/runtime-host/dist/protocol/session-continuity.js +1 -0
- package/node_modules/@maka/runtime-host/dist/protocol/workhub-coordination.js +86 -157
- package/node_modules/@maka/runtime-host/dist/server/access-credential-store.js +4 -0
- package/node_modules/@maka/runtime-host/dist/server/agent-graph-coordinator.js +0 -3
- package/node_modules/@maka/runtime-host/dist/server/canonical-session-projection.js +2 -1
- package/node_modules/@maka/runtime-host/dist/server/connection-session.js +28 -8
- package/node_modules/@maka/runtime-host/dist/server/daily-review-coordinator.js +112 -56
- package/node_modules/@maka/runtime-host/dist/server/execution-artifacts.js +32 -32
- package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +85 -25
- package/node_modules/@maka/runtime-host/dist/server/execution-model-composition.js +42 -14
- package/node_modules/@maka/runtime-host/dist/server/failure-diagnostic.js +24 -0
- package/node_modules/@maka/runtime-host/dist/server/goal-coordinator.js +7 -3
- package/node_modules/@maka/runtime-host/dist/server/host-kernel.js +3 -3
- package/node_modules/@maka/runtime-host/dist/server/host-session-availability.js +5 -2
- package/node_modules/@maka/runtime-host/dist/server/hosted-execution-recovery.js +3 -2
- package/node_modules/@maka/runtime-host/dist/server/hosted-execution-tool-profile.js +34 -4
- package/node_modules/@maka/runtime-host/dist/server/interactive-run-composer.js +51 -23
- package/node_modules/@maka/runtime-host/dist/server/operation-dispatcher.js +2 -7
- package/node_modules/@maka/runtime-host/dist/server/plugin-platform-coordinator.js +6 -0
- package/node_modules/@maka/runtime-host/dist/server/plugin-platform.js +6 -0
- package/node_modules/@maka/runtime-host/dist/server/root-turn-coordinator.js +110 -14
- package/node_modules/@maka/runtime-host/dist/server/runtime-resource-coordinator.js +11 -8
- package/node_modules/@maka/runtime-host/dist/server/scheduled-task-coordinator.js +31 -21
- package/node_modules/@maka/runtime-host/dist/server/serial-outbound-writer.js +1 -1
- package/node_modules/@maka/runtime-host/dist/server/session-catalog-coordinator.js +20 -8
- package/node_modules/@maka/runtime-host/dist/server/session-retirement-coordinator.js +5 -2
- package/node_modules/@maka/runtime-host/dist/server/session-revision-coordinator.js +4 -0
- package/node_modules/@maka/runtime-host/dist/server/session-transcript-reader.js +15 -104
- package/node_modules/@maka/runtime-host/dist/server/shared-session-transcript.js +3 -0
- package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-action-gate.js +59 -82
- package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-coordinator.js +132 -139
- package/node_modules/@maka/runtime-host/dist/server/workhub-message-attachments.js +46 -0
- package/node_modules/@maka/storage/dist/agent-run-store.js +14 -1
- package/node_modules/@maka/storage/dist/artifact-store.js +40 -3
- package/node_modules/@maka/storage/dist/atomic-file-write.js +74 -0
- package/node_modules/@maka/storage/dist/claude-code-session-adapter.js +0 -1
- package/node_modules/@maka/storage/dist/codex-session-adapter.js +284 -196
- package/node_modules/@maka/storage/dist/credential-store.js +12 -63
- package/node_modules/@maka/storage/dist/execution-stores.js +4 -1
- package/node_modules/@maka/storage/dist/git-exec.js +61 -0
- package/node_modules/@maka/storage/dist/git-worktree-child-executor.js +8 -35
- package/node_modules/@maka/storage/dist/goal-authority.js +2 -2
- package/node_modules/@maka/storage/dist/interaction-store.js +2 -2
- package/node_modules/@maka/storage/dist/mcp-config-store.js +10 -25
- package/node_modules/@maka/storage/dist/project-catalog.js +2 -23
- package/node_modules/@maka/storage/dist/runtime-event-invariants.js +2 -2
- package/node_modules/@maka/storage/dist/runtime-policy/connection-catalog-document.js +8 -3
- package/node_modules/@maka/storage/dist/scheduled-task-store.js +249 -283
- package/node_modules/@maka/storage/dist/session-bundle-manifest.js +5 -17
- package/node_modules/@maka/storage/dist/session-bundle-policy.js +2 -1
- package/node_modules/@maka/storage/dist/session-copy-cleanup.js +2 -1
- package/node_modules/@maka/storage/dist/session-store.js +14 -2
- package/node_modules/@maka/storage/dist/settings-store.js +8 -4
- package/node_modules/@maka/storage/dist/sqlite-artifact-metadata.js +11 -0
- package/node_modules/@maka/storage/dist/sqlite-runtime-store.js +1 -2
- package/node_modules/@maka/storage/dist/sqlite-session-metadata-schema.js +12 -1
- package/node_modules/@maka/storage/dist/sqlite-session-metadata-store.js +67 -3
- package/node_modules/@maka/storage/dist/stable-storage.js +14 -1
- package/node_modules/@maka/storage/dist/storage-id.js +28 -0
- package/node_modules/@maka/storage/dist/tool-result-archive-evidence.js +31 -4
- package/node_modules/@maka/storage/dist/workspace-identity.js +2 -15
- package/node_modules/@maka/storage/dist/workspace-version-authority-internal.js +1 -8
- package/package.json +1 -1
- package/node_modules/@maka/core/dist/workhub-creation-intent.js +0 -990
- package/node_modules/@maka/core/dist/workhub-session-resolver.js +0 -50
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
* under the License.
|
|
18
18
|
*/
|
|
19
19
|
import { isNonEmptyUnicodeString, isSha256Digest, SESSION_BUNDLE_ARCHIVE_FORMAT, SESSION_BUNDLE_CANONICALIZATION_VERSION, SESSION_BUNDLE_CODEC_NAME, SESSION_BUNDLE_CODEC_VERSION, SESSION_BUNDLE_COMPRESSION_FORMAT, SESSION_BUNDLE_COMPRESSION_LEVEL, SESSION_BUNDLE_SCHEMA_VERSION, SESSION_BUNDLE_STATE_IDENTITY_PATH, SESSION_BUNDLE_STATE_PATH, SESSION_BUNDLE_WORKSPACE_PATH, SessionBundleFileError, } from './session-bundle-contract.js';
|
|
20
|
+
import { stableJsonStringify } from '@maka/core/canonical-json';
|
|
20
21
|
const MANIFEST_KEYS = ['codec', 'envelope', 'payload', 'schemaVersion', 'stateIdentity'];
|
|
21
22
|
const CODEC_KEYS = [
|
|
22
23
|
'archive',
|
|
@@ -167,25 +168,12 @@ function decodePayload(value) {
|
|
|
167
168
|
};
|
|
168
169
|
}
|
|
169
170
|
function canonicalJson(value) {
|
|
170
|
-
|
|
171
|
-
return
|
|
172
|
-
if (typeof value === 'string')
|
|
173
|
-
return JSON.stringify(value);
|
|
174
|
-
if (typeof value === 'number') {
|
|
175
|
-
if (!Number.isFinite(value))
|
|
176
|
-
throw invalidManifest();
|
|
177
|
-
return JSON.stringify(value);
|
|
171
|
+
try {
|
|
172
|
+
return stableJsonStringify(value);
|
|
178
173
|
}
|
|
179
|
-
|
|
180
|
-
return value ? 'true' : 'false';
|
|
181
|
-
if (Array.isArray(value))
|
|
182
|
-
return `[${value.map((item) => canonicalJson(item)).join(',')}]`;
|
|
183
|
-
if (!isRecord(value))
|
|
174
|
+
catch {
|
|
184
175
|
throw invalidManifest();
|
|
185
|
-
|
|
186
|
-
.sort()
|
|
187
|
-
.map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`)
|
|
188
|
-
.join(',')}}`;
|
|
176
|
+
}
|
|
189
177
|
}
|
|
190
178
|
function hasExactKeys(value, expected) {
|
|
191
179
|
const actual = Object.keys(value);
|
|
@@ -25,6 +25,7 @@ import { withArtifactWriterLock } from './artifact-writer-lock.js';
|
|
|
25
25
|
import { withOfflineContextSnapshot, copyContextSnapshot, validateContextSnapshot, planContextSnapshotFiles, } from './context-offload-snapshot.js';
|
|
26
26
|
import { CONTEXT_OFFLOAD_DATABASE_NAME, CONTEXT_OFFLOAD_VALUES_DIRECTORY_NAME, } from './sqlite-context-offload-store.js';
|
|
27
27
|
import { acquireOperationalStateDatabase, OPERATIONAL_STATE_DATABASE_NAME, } from './operational-state-store.js';
|
|
28
|
+
import { isSafeStorageId } from './storage-id.js';
|
|
28
29
|
export const SESSION_BUNDLE_STATE_ENTRIES = [
|
|
29
30
|
'artifacts',
|
|
30
31
|
OPERATIONAL_STATE_DATABASE_NAME,
|
|
@@ -325,7 +326,7 @@ function assertRootsSeparate(left, right, allowSame) {
|
|
|
325
326
|
}
|
|
326
327
|
}
|
|
327
328
|
function assertSafeSessionId(sessionId) {
|
|
328
|
-
if (
|
|
329
|
+
if (!isSafeStorageId(sessionId)) {
|
|
329
330
|
throw new SessionBundleExportError('invalid_root', `Invalid session id: ${sessionId}`);
|
|
330
331
|
}
|
|
331
332
|
}
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
import { randomUUID } from 'node:crypto';
|
|
20
20
|
import { acquireOperationalStateDatabase, } from './operational-state-store.js';
|
|
21
21
|
import { isProcessLifetimeOwnerReference, } from './process-lifetime-owner.js';
|
|
22
|
+
import { isSafeStorageId } from './storage-id.js';
|
|
22
23
|
export function createSessionCopyCleanupAuthority(input) {
|
|
23
24
|
return new SessionCopyCleanupAuthorityImpl(new SqliteSessionCopyCleanupStore(input.workspaceRoot, input.databaseOptions), input.removeSession, input.resumeSessionCopy, input.processId ?? randomUUID(), input.isOwnerProcessActive, input.processLifetimeOwner);
|
|
24
25
|
}
|
|
@@ -392,7 +393,7 @@ function normalizeSessionId(value) {
|
|
|
392
393
|
if (typeof value !== 'string')
|
|
393
394
|
throw new Error('Invalid Session copy id');
|
|
394
395
|
const normalized = value.trim();
|
|
395
|
-
if (
|
|
396
|
+
if (!isSafeStorageId(normalized)) {
|
|
396
397
|
throw new Error('Invalid Session copy id');
|
|
397
398
|
}
|
|
398
399
|
return normalized;
|
|
@@ -351,9 +351,9 @@ class SqliteSessionStore {
|
|
|
351
351
|
// pre-cutover session sees its imported rows.
|
|
352
352
|
return projectHeaderSnapshot(await this.metadata.read(sessionId));
|
|
353
353
|
}
|
|
354
|
-
async readCatalogRecord(sessionId) {
|
|
354
|
+
async readCatalogRecord(sessionId, roleScope = 'ordinary') {
|
|
355
355
|
await this.ensureCatalogProjectionReadable();
|
|
356
|
-
const record = await this.metadata.readCatalogRecord(sessionId);
|
|
356
|
+
const record = await this.metadata.readCatalogRecord(sessionId, roleScope);
|
|
357
357
|
return {
|
|
358
358
|
...projectHeaderSnapshot(record),
|
|
359
359
|
activityAt: record.activityAt,
|
|
@@ -372,6 +372,18 @@ class SqliteSessionStore {
|
|
|
372
372
|
await this.ensureReady();
|
|
373
373
|
return this.metadata.readTranscriptHighWater(sessionId);
|
|
374
374
|
}
|
|
375
|
+
async readCoordinationTranscriptIndexState() {
|
|
376
|
+
await this.ensureReady();
|
|
377
|
+
return this.metadata.readCoordinationTranscriptIndexState();
|
|
378
|
+
}
|
|
379
|
+
async appendCoordinationTranscriptIndex(records) {
|
|
380
|
+
await this.ensureReady();
|
|
381
|
+
return this.metadata.appendCoordinationTranscriptIndex(records);
|
|
382
|
+
}
|
|
383
|
+
async readCoordinationTranscriptIndex(request) {
|
|
384
|
+
await this.ensureReady();
|
|
385
|
+
return this.metadata.readCoordinationTranscriptIndex(request);
|
|
386
|
+
}
|
|
375
387
|
async listTurnsSnapshot(sessionId) {
|
|
376
388
|
return deriveTurnRecords(await this.readMessagesSnapshot(sessionId));
|
|
377
389
|
}
|
|
@@ -16,10 +16,11 @@
|
|
|
16
16
|
* specific language governing permissions and limitations
|
|
17
17
|
* under the License.
|
|
18
18
|
*/
|
|
19
|
-
import { mkdir, readFile
|
|
19
|
+
import { mkdir, readFile } from 'node:fs/promises';
|
|
20
20
|
import { dirname, join } from 'node:path';
|
|
21
21
|
import { createDefaultSettings, mergeSettings, normalizeSettings } from '@maka/core/settings';
|
|
22
22
|
import { sanitizeOnboardingMilestones } from '@maka/core/onboarding';
|
|
23
|
+
import { writeAtomicFile } from './atomic-file-write.js';
|
|
23
24
|
export function createSettingsStore(workspaceRoot) {
|
|
24
25
|
return new FileSettingsStore(workspaceRoot);
|
|
25
26
|
}
|
|
@@ -133,10 +134,13 @@ class FileSettingsStore {
|
|
|
133
134
|
return result;
|
|
134
135
|
}
|
|
135
136
|
async write(settings) {
|
|
137
|
+
// SettingsStore does not own the workspace directory's permission policy:
|
|
138
|
+
// sibling stores such as MCP config may independently harden the same root.
|
|
139
|
+
// Keep both directory creation and the historical umask-derived file mode.
|
|
136
140
|
await mkdir(dirname(this.settingsPath), { recursive: true });
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
141
|
+
await writeAtomicFile(this.settingsPath, JSON.stringify(settings, null, 2) + '\n', {
|
|
142
|
+
fileMode: 0o666 & ~process.umask(),
|
|
143
|
+
});
|
|
140
144
|
}
|
|
141
145
|
withQueue(operation) {
|
|
142
146
|
const next = this.queue.then(operation, operation);
|
|
@@ -82,6 +82,17 @@ class SqliteArtifactMetadataRepository {
|
|
|
82
82
|
.prepare('SELECT 1 FROM artifact_records WHERE relative_path = ?')
|
|
83
83
|
.get(relativePath));
|
|
84
84
|
}
|
|
85
|
+
readRelativePathsByCaseFoldedArtifactIds(artifactIds) {
|
|
86
|
+
this.assertOpen();
|
|
87
|
+
if (artifactIds.length === 0)
|
|
88
|
+
return [];
|
|
89
|
+
const placeholders = artifactIds.map(() => '?').join(', ');
|
|
90
|
+
const rows = this.#lease.database
|
|
91
|
+
.prepare(`SELECT relative_path FROM artifact_records
|
|
92
|
+
WHERE artifact_id COLLATE NOCASE IN (${placeholders})`)
|
|
93
|
+
.all(...artifactIds);
|
|
94
|
+
return rows.map((row) => row.relative_path);
|
|
95
|
+
}
|
|
85
96
|
forgetUpgradeOrphanPaths(relativePaths) {
|
|
86
97
|
this.assertOpen();
|
|
87
98
|
this.#lease.transaction('write', () => {
|
|
@@ -1360,8 +1360,7 @@ export class SqliteRuntimeStore {
|
|
|
1360
1360
|
});
|
|
1361
1361
|
}
|
|
1362
1362
|
registerWorkspaceBaselineAuthorityWriter() {
|
|
1363
|
-
|
|
1364
|
-
registerWorkspaceBaselineAuthorityWriterInternal(this, (input, rootId) => this.#commitWorkspaceBaseline(input, rootId), (input, rootId) => this.#commitWorkspaceSuccessor(input, rootId), (input, rootId) => this.#commitManagedMutationTerminal(input, rootId), (rootId) => this.#bindWorkspaceStorageRoot(rootId), readWorkspaceHead, (workspaceInstanceId) => this.#readActiveManagedMutation(workspaceInstanceId));
|
|
1363
|
+
registerWorkspaceBaselineAuthorityWriterInternal(this, (input, rootId) => this.#commitWorkspaceBaseline(input, rootId), (input, rootId) => this.#commitWorkspaceSuccessor(input, rootId), (input, rootId) => this.#commitManagedMutationTerminal(input, rootId), (rootId) => this.#bindWorkspaceStorageRoot(rootId), (workspaceInstanceId) => this.#readActiveManagedMutation(workspaceInstanceId));
|
|
1365
1364
|
}
|
|
1366
1365
|
async #readActiveManagedMutation(workspaceInstanceId) {
|
|
1367
1366
|
return this.readTransaction(() => {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* specific language governing permissions and limitations
|
|
17
17
|
* under the License.
|
|
18
18
|
*/
|
|
19
|
-
export const SQLITE_SESSION_METADATA_SCHEMA_VERSION =
|
|
19
|
+
export const SQLITE_SESSION_METADATA_SCHEMA_VERSION = 39;
|
|
20
20
|
export const SQLITE_SESSION_MESSAGE_CHUNK_BYTES = 64 * 1024;
|
|
21
21
|
export const SQLITE_SESSION_MESSAGE_CHUNK_MARKER = '{"$maka":"session-message-chunks-v1"}';
|
|
22
22
|
export const SQLITE_AGENT_GRAPH_CONTROL_TABLES = [
|
|
@@ -32,6 +32,17 @@ export const SQLITE_AGENT_GRAPH_CONTROL_TABLES = [
|
|
|
32
32
|
'agent_graph_supervisor_wake_attempts',
|
|
33
33
|
];
|
|
34
34
|
const MIGRATIONS = new Map([
|
|
35
|
+
[
|
|
36
|
+
39,
|
|
37
|
+
`
|
|
38
|
+
CREATE TABLE IF NOT EXISTS coordination_transcript_index (
|
|
39
|
+
sequence INTEGER PRIMARY KEY,
|
|
40
|
+
source TEXT NOT NULL CHECK (source IN ('legacy', 'runtime')),
|
|
41
|
+
source_sequence INTEGER NOT NULL CHECK (source_sequence >= 0),
|
|
42
|
+
UNIQUE (source, source_sequence)
|
|
43
|
+
);
|
|
44
|
+
`,
|
|
45
|
+
],
|
|
35
46
|
[
|
|
36
47
|
1,
|
|
37
48
|
`
|
|
@@ -730,10 +730,12 @@ export class SqliteSessionMetadataStore {
|
|
|
730
730
|
throw new SessionNotFoundError(sessionId);
|
|
731
731
|
return record;
|
|
732
732
|
}
|
|
733
|
-
async readCatalogRecord(sessionId) {
|
|
733
|
+
async readCatalogRecord(sessionId, roleScope = 'ordinary') {
|
|
734
734
|
this.assertOpen();
|
|
735
735
|
assertSafeSessionId(sessionId);
|
|
736
|
-
const role =
|
|
736
|
+
const role = roleScope === 'recoverable'
|
|
737
|
+
? sqliteRecoverableSessionRolePredicate()
|
|
738
|
+
: sqliteOrdinarySessionRolePredicate();
|
|
737
739
|
const row = this.db
|
|
738
740
|
.prepare(`
|
|
739
741
|
SELECT
|
|
@@ -1206,7 +1208,11 @@ export class SqliteSessionMetadataStore {
|
|
|
1206
1208
|
assignment.id !== `wha_${suffix}` ||
|
|
1207
1209
|
assignment.targetMessageId !== `whm_${suffix}` ||
|
|
1208
1210
|
assignment.delegationId !== `whd_${suffix}` ||
|
|
1209
|
-
!
|
|
1211
|
+
!workHubAssignmentAttachmentsMatchTarget(assignment) ||
|
|
1212
|
+
!messageContentsEqual(admission.content, normalizeMessageContent({
|
|
1213
|
+
text: assignment.delegationText ?? assignment.userText,
|
|
1214
|
+
...(assignment.targetAttachments ? { attachments: assignment.targetAttachments } : {}),
|
|
1215
|
+
})) ||
|
|
1210
1216
|
admission.submittedContentDigest !== messageContentDigest(admission.content) ||
|
|
1211
1217
|
admission.submittedPlacement !== 'current_turn' ||
|
|
1212
1218
|
admission.placement !== 'current_turn' ||
|
|
@@ -1825,6 +1831,45 @@ export class SqliteSessionMetadataStore {
|
|
|
1825
1831
|
unique.forEach((messageId, index) => update.run(index, sessionId, messageId));
|
|
1826
1832
|
});
|
|
1827
1833
|
}
|
|
1834
|
+
async readCoordinationTranscriptIndexState() {
|
|
1835
|
+
this.assertOpen();
|
|
1836
|
+
return this.db
|
|
1837
|
+
.prepare(`SELECT (SELECT MAX(sequence) FROM coordination_transcript_index) AS highWater,
|
|
1838
|
+
(SELECT MAX(source_sequence) FROM coordination_transcript_index WHERE source = 'legacy') AS legacy,
|
|
1839
|
+
(SELECT MAX(source_sequence) FROM coordination_transcript_index WHERE source = 'runtime') AS runtime`)
|
|
1840
|
+
.get();
|
|
1841
|
+
}
|
|
1842
|
+
async appendCoordinationTranscriptIndex(records) {
|
|
1843
|
+
this.assertOpen();
|
|
1844
|
+
if (records.length > 64)
|
|
1845
|
+
throw new Error('Coordination transcript index batch exceeds limit');
|
|
1846
|
+
this.transaction(() => {
|
|
1847
|
+
let sequence = this.db
|
|
1848
|
+
.prepare('SELECT MAX(sequence) AS value FROM coordination_transcript_index')
|
|
1849
|
+
.get().value ?? -1;
|
|
1850
|
+
const insert = this.db.prepare(`INSERT INTO coordination_transcript_index
|
|
1851
|
+
(sequence, source, source_sequence) VALUES (?, ?, ?)
|
|
1852
|
+
ON CONFLICT(source, source_sequence) DO NOTHING`);
|
|
1853
|
+
for (const record of records) {
|
|
1854
|
+
if (!Number.isSafeInteger(record.sourceSequence) || record.sourceSequence < 0)
|
|
1855
|
+
throw new Error('Invalid Coordination source sequence');
|
|
1856
|
+
const result = insert.run(sequence + 1, record.source, record.sourceSequence);
|
|
1857
|
+
if (result.changes)
|
|
1858
|
+
sequence++;
|
|
1859
|
+
}
|
|
1860
|
+
});
|
|
1861
|
+
}
|
|
1862
|
+
async readCoordinationTranscriptIndex(request) {
|
|
1863
|
+
this.assertOpen();
|
|
1864
|
+
if (!Number.isSafeInteger(request.limit) || request.limit < 1 || request.limit > 64)
|
|
1865
|
+
throw new Error('Invalid Coordination transcript index limit');
|
|
1866
|
+
const older = request.direction === 'older';
|
|
1867
|
+
return this.db
|
|
1868
|
+
.prepare(`SELECT sequence, source, source_sequence AS sourceSequence
|
|
1869
|
+
FROM coordination_transcript_index WHERE sequence <= ? AND sequence ${older ? '<=' : '>='} ?
|
|
1870
|
+
ORDER BY sequence ${older ? 'DESC' : 'ASC'} LIMIT ?`)
|
|
1871
|
+
.all(request.throughSequence, request.position, request.limit);
|
|
1872
|
+
}
|
|
1828
1873
|
async readMessages(sessionId) {
|
|
1829
1874
|
return this.readMessagesWith(sessionId, decodeStoredMessage);
|
|
1830
1875
|
}
|
|
@@ -4566,6 +4611,21 @@ function isWorkHubActionOperation(value) {
|
|
|
4566
4611
|
value === 'replace' ||
|
|
4567
4612
|
value === 'stop');
|
|
4568
4613
|
}
|
|
4614
|
+
function workHubAssignmentAttachmentsMatchTarget(assignment) {
|
|
4615
|
+
const source = assignment.attachments ?? [];
|
|
4616
|
+
const target = assignment.targetAttachments ?? [];
|
|
4617
|
+
return (source.length === target.length &&
|
|
4618
|
+
source.every((attachment, index) => {
|
|
4619
|
+
const copied = target[index];
|
|
4620
|
+
const { ref: sourceRef, ...sourceMetadata } = attachment;
|
|
4621
|
+
const { ref: targetRef, ...targetMetadata } = copied;
|
|
4622
|
+
return (sourceRef.kind === 'session_file' &&
|
|
4623
|
+
sourceRef.sessionId === WORKHUB_COORDINATION_SESSION_ID &&
|
|
4624
|
+
targetRef.kind === 'session_file' &&
|
|
4625
|
+
targetRef.sessionId === assignment.targetSessionId &&
|
|
4626
|
+
isDeepStrictEqual(sourceMetadata, targetMetadata));
|
|
4627
|
+
}));
|
|
4628
|
+
}
|
|
4569
4629
|
function sameWorkHubAssignmentRequest(existing, requested) {
|
|
4570
4630
|
return isDeepStrictEqual({
|
|
4571
4631
|
actionId: existing.actionId,
|
|
@@ -4574,6 +4634,8 @@ function sameWorkHubAssignmentRequest(existing, requested) {
|
|
|
4574
4634
|
targetSessionId: existing.targetSessionId,
|
|
4575
4635
|
disposition: existing.disposition,
|
|
4576
4636
|
userText: existing.userText,
|
|
4637
|
+
delegationText: existing.delegationText,
|
|
4638
|
+
attachments: existing.attachments,
|
|
4577
4639
|
create: existing.create,
|
|
4578
4640
|
replacesActionId: existing.replacesActionId,
|
|
4579
4641
|
replacesDelegationId: existing.replacesDelegationId,
|
|
@@ -4584,6 +4646,8 @@ function sameWorkHubAssignmentRequest(existing, requested) {
|
|
|
4584
4646
|
targetSessionId: requested.targetSessionId,
|
|
4585
4647
|
disposition: requested.disposition,
|
|
4586
4648
|
userText: requested.userText,
|
|
4649
|
+
delegationText: requested.delegationText,
|
|
4650
|
+
attachments: requested.attachments,
|
|
4587
4651
|
create: requested.create,
|
|
4588
4652
|
replacesActionId: requested.replacesActionId,
|
|
4589
4653
|
replacesDelegationId: requested.replacesDelegationId,
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* under the License.
|
|
18
18
|
*/
|
|
19
19
|
import { constants } from 'node:fs';
|
|
20
|
-
import { lstat, open } from 'node:fs/promises';
|
|
20
|
+
import { chmod, lstat, mkdir, open } from 'node:fs/promises';
|
|
21
21
|
import { dirname, isAbsolute, relative, resolve, sep } from 'node:path';
|
|
22
22
|
const openStableFile = open;
|
|
23
23
|
const lstatStableFile = lstat;
|
|
@@ -74,6 +74,19 @@ export async function syncFile(path) {
|
|
|
74
74
|
await handle.close();
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Create (or harden) an owner-only directory: recursive mkdir plus a
|
|
79
|
+
* fail-closed chmod, since mkdir's mode only applies on creation. Callers that
|
|
80
|
+
* store secrets use this before creating their file or update lock.
|
|
81
|
+
*/
|
|
82
|
+
export async function hardenDirectory(dir, mode = 0o700) {
|
|
83
|
+
await mkdir(dir, { recursive: true, mode });
|
|
84
|
+
if (process.platform === 'win32') {
|
|
85
|
+
await chmod(dir, mode).catch(() => { });
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
await chmod(dir, mode);
|
|
89
|
+
}
|
|
77
90
|
export async function syncDirectoryChain(path, root, beforeSync) {
|
|
78
91
|
const boundary = resolve(root);
|
|
79
92
|
let current = resolve(path);
|
|
@@ -0,0 +1,28 @@
|
|
|
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
|
+
const SAFE_STORAGE_ID_PATTERN = /^[A-Za-z0-9_-]{1,128}$/;
|
|
20
|
+
/** Returns whether a value can safely be used as a persisted storage identity. */
|
|
21
|
+
export function isSafeStorageId(value) {
|
|
22
|
+
return typeof value === 'string' && SAFE_STORAGE_ID_PATTERN.test(value);
|
|
23
|
+
}
|
|
24
|
+
/** Throws a TypeError unless the value is a safe persisted storage identity. */
|
|
25
|
+
export function assertSafeStorageId(value, message = 'Storage identity is invalid') {
|
|
26
|
+
if (!isSafeStorageId(value))
|
|
27
|
+
throw new TypeError(message);
|
|
28
|
+
}
|
|
@@ -23,6 +23,12 @@ import { decodeAgentRunEvent } from '@maka/core/agent-run';
|
|
|
23
23
|
import { MODEL_PROJECTION_TARGET_SQL as TARGET } from './sqlite-core-execution-schema.js';
|
|
24
24
|
const TRANSITIONS = 'core_agent_run_events INDEXED BY core_model_projection_target';
|
|
25
25
|
const KIND = "event_type = 'model_projection_transition_recorded'";
|
|
26
|
+
// SQLite may parse the containing JSON, but only these reconstruction fields
|
|
27
|
+
// cross into JS or count toward the evidence budget. Raw tool bytes never do.
|
|
28
|
+
const EVENT_EVIDENCE = `CASE WHEN json_valid(payload_json) THEN json_extract(payload_json,
|
|
29
|
+
'$.id', '$.sessionId', '$.runId', '$.invocationId', '$.turnId', '$.ts', '$.partial',
|
|
30
|
+
'$.author', '$.role', '$.content.kind', '$.content.id', '$.content.name',
|
|
31
|
+
'$.content.modelProjection', '$.content.providerExecuted') END`;
|
|
26
32
|
/** Reader-first foundation; no archive writer or fallback is activated by opening it. */
|
|
27
33
|
export async function openToolResultArchiveEvidenceReader(lease) {
|
|
28
34
|
await assertStorageRootLease(lease, 'interactive', lease.access);
|
|
@@ -51,10 +57,12 @@ export async function openToolResultArchiveEvidenceReader(lease) {
|
|
|
51
57
|
const db = database.database;
|
|
52
58
|
const { sessionId, runtimeEventId } = accepted;
|
|
53
59
|
const eventSize = db
|
|
54
|
-
.prepare(
|
|
60
|
+
.prepare(`SELECT length(CAST(${EVENT_EVIDENCE} AS BLOB)) AS bytes FROM runtime_events WHERE event_id = ? AND session_id = ?`)
|
|
55
61
|
.get(runtimeEventId, sessionId);
|
|
56
62
|
if (!eventSize)
|
|
57
63
|
return { ok: false, reason: 'not_found' };
|
|
64
|
+
if (eventSize.bytes === null)
|
|
65
|
+
return { ok: false, reason: 'corrupt' };
|
|
58
66
|
// An unscoped unreadable transition prevents proving completeness.
|
|
59
67
|
if (db
|
|
60
68
|
.prepare(`SELECT 1 FROM ${TRANSITIONS} WHERE ${KIND} AND session_id = ? AND ${TARGET} IS NULL LIMIT 1`)
|
|
@@ -72,11 +80,30 @@ export async function openToolResultArchiveEvidenceReader(lease) {
|
|
|
72
80
|
if (!Number.isSafeInteger(bytes) || bytes < 0 || bytes > MAX_BYTES)
|
|
73
81
|
return { ok: false, reason: 'too_large' };
|
|
74
82
|
const raw = db
|
|
75
|
-
.prepare(
|
|
83
|
+
.prepare(`SELECT ${EVENT_EVIDENCE} AS evidence_json FROM runtime_events WHERE event_id = ? AND session_id = ?`)
|
|
76
84
|
.get(runtimeEventId, sessionId);
|
|
77
85
|
let event;
|
|
78
86
|
try {
|
|
79
|
-
|
|
87
|
+
const [id, sessionId, runId, invocationId, turnId, ts, partial, author, role, kind, callId, name, modelProjection, providerExecuted,] = JSON.parse(String(raw?.evidence_json));
|
|
88
|
+
event = decodeRuntimeEvent({
|
|
89
|
+
id,
|
|
90
|
+
sessionId,
|
|
91
|
+
runId,
|
|
92
|
+
invocationId,
|
|
93
|
+
turnId,
|
|
94
|
+
ts,
|
|
95
|
+
partial,
|
|
96
|
+
author,
|
|
97
|
+
role,
|
|
98
|
+
content: {
|
|
99
|
+
kind,
|
|
100
|
+
id: callId,
|
|
101
|
+
name,
|
|
102
|
+
result: null,
|
|
103
|
+
...(modelProjection === null ? {} : { modelProjection }),
|
|
104
|
+
...(providerExecuted === null ? {} : { providerExecuted }),
|
|
105
|
+
},
|
|
106
|
+
});
|
|
80
107
|
}
|
|
81
108
|
catch {
|
|
82
109
|
return { ok: false, reason: 'corrupt' };
|
|
@@ -98,7 +125,7 @@ export async function openToolResultArchiveEvidenceReader(lease) {
|
|
|
98
125
|
return { ok: false, reason: 'corrupt' };
|
|
99
126
|
transitions.push(transition);
|
|
100
127
|
}
|
|
101
|
-
return { ok: true, event, transitions };
|
|
128
|
+
return { ok: true, event, transitions, storedBytes: bytes };
|
|
102
129
|
});
|
|
103
130
|
});
|
|
104
131
|
}
|
|
@@ -16,12 +16,11 @@
|
|
|
16
16
|
* specific language governing permissions and limitations
|
|
17
17
|
* under the License.
|
|
18
18
|
*/
|
|
19
|
-
import { execFile } from 'node:child_process';
|
|
20
19
|
import { randomUUID } from 'node:crypto';
|
|
21
20
|
import { constants as fsConstants } from 'node:fs';
|
|
22
21
|
import { lstat, open, realpath, stat } from 'node:fs/promises';
|
|
23
22
|
import { isAbsolute, join, normalize, parse, resolve } from 'node:path';
|
|
24
|
-
import {
|
|
23
|
+
import { execGitText } from './git-exec.js';
|
|
25
24
|
import { hasEnclosingGitEntry } from './git-entry.js';
|
|
26
25
|
import { publishMarkerFile, readBoundedMarkerFile } from './marker-file.js';
|
|
27
26
|
export const WORKSPACE_MARKER_FILE = '.maka-workspace.json';
|
|
@@ -29,7 +28,6 @@ export const WORKSPACE_MARKER_SCHEMA_VERSION = 1;
|
|
|
29
28
|
export const WORKSPACE_IDENTITY_PREFIX = 'workspace:v1:';
|
|
30
29
|
const MAX_WORKSPACE_MARKER_BYTES = 4_096;
|
|
31
30
|
const MAX_GIT_EXCLUDE_BYTES = 1024 * 1024;
|
|
32
|
-
const execFileAsync = promisify(execFile);
|
|
33
31
|
export class WorkspaceIdentityError extends Error {
|
|
34
32
|
code;
|
|
35
33
|
constructor(code, message, options) {
|
|
@@ -101,18 +99,7 @@ async function createWorkspaceMarker(snapshot, workspaceId) {
|
|
|
101
99
|
async function ensureWorkspaceMarkerIgnored(workspacePath) {
|
|
102
100
|
if (!(await hasEnclosingGitEntry(workspacePath)))
|
|
103
101
|
return;
|
|
104
|
-
const
|
|
105
|
-
delete env.GIT_DIR;
|
|
106
|
-
delete env.GIT_WORK_TREE;
|
|
107
|
-
delete env.GIT_INDEX_FILE;
|
|
108
|
-
delete env.GIT_COMMON_DIR;
|
|
109
|
-
const { stdout } = await execFileAsync('git', ['-C', workspacePath, 'rev-parse', '--path-format=absolute', '--git-path', 'info/exclude'], {
|
|
110
|
-
env,
|
|
111
|
-
encoding: 'utf8',
|
|
112
|
-
maxBuffer: 64 * 1024,
|
|
113
|
-
timeout: 3_000,
|
|
114
|
-
windowsHide: true,
|
|
115
|
-
});
|
|
102
|
+
const stdout = await execGitText(workspacePath, ['rev-parse', '--path-format=absolute', '--git-path', 'info/exclude'], { maxBuffer: 64 * 1024, timeoutMs: 3_000 });
|
|
116
103
|
const excludePath = stdout.trim();
|
|
117
104
|
if (!isAbsolute(excludePath)) {
|
|
118
105
|
throw new Error(`Git returned a non-absolute exclude path: ${excludePath}`);
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* under the License.
|
|
18
18
|
*/
|
|
19
19
|
const workspaceBaselineAuthorityWriters = new WeakMap();
|
|
20
|
-
export function registerWorkspaceBaselineAuthorityWriterInternal(store, writer, successorWriter, terminalWriter, bindStorageRoot,
|
|
20
|
+
export function registerWorkspaceBaselineAuthorityWriterInternal(store, writer, successorWriter, terminalWriter, bindStorageRoot, readActiveManagedMutation) {
|
|
21
21
|
if (workspaceBaselineAuthorityWriters.has(store)) {
|
|
22
22
|
throw new Error('Workspace baseline authority writer is already registered');
|
|
23
23
|
}
|
|
@@ -25,7 +25,6 @@ export function registerWorkspaceBaselineAuthorityWriterInternal(store, writer,
|
|
|
25
25
|
writer,
|
|
26
26
|
successorWriter,
|
|
27
27
|
terminalWriter,
|
|
28
|
-
readHead,
|
|
29
28
|
readActiveManagedMutation,
|
|
30
29
|
bindStorageRoot,
|
|
31
30
|
});
|
|
@@ -36,12 +35,6 @@ export function readActiveManagedMutationInternal(store, workspaceInstanceId) {
|
|
|
36
35
|
throw new Error('Managed mutation reservation reader is unavailable');
|
|
37
36
|
return registration.readActiveManagedMutation(workspaceInstanceId);
|
|
38
37
|
}
|
|
39
|
-
export function readWorkspaceHeadInternal(store, workspaceId, workspaceEpochId) {
|
|
40
|
-
const registration = workspaceBaselineAuthorityWriters.get(store);
|
|
41
|
-
if (!registration)
|
|
42
|
-
throw new Error('Workspace baseline authority reader is unavailable');
|
|
43
|
-
return registration.readHead(workspaceId, workspaceEpochId);
|
|
44
|
-
}
|
|
45
38
|
/**
|
|
46
39
|
* Storage-internal authority seam. This module is deliberately absent from the
|
|
47
40
|
* @maka/storage package exports. The schema-9 reader, migration, and projection
|