maka-agent 0.2.0-dev.30.20260912 → 0.2.0-dev.31.20260913
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/THIRD_PARTY_NOTICES.txt +392 -0
- package/dist/acp/maka-acp-agent.js +8 -2
- package/dist/acp/prompt-content.js +225 -0
- package/dist/acp/session-event-mapper.js +103 -0
- package/dist/acp/session-registry.js +654 -17
- package/dist/acp/stdio-server.js +10 -1
- package/dist/cli-core.js +1 -1
- package/dist/pi-transcript-tools.js +3 -2
- package/dist/pi-transcript.js +12 -2
- package/dist/runtime-host-session-channel.js +63 -9
- package/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
- package/node_modules/@maka/core/dist/artifacts.js +6 -0
- package/node_modules/@maka/core/dist/attachments.js +7 -2
- package/node_modules/@maka/core/dist/durable-tool-result-projection.js +3 -1
- package/node_modules/@maka/core/dist/events.js +21 -0
- package/node_modules/@maka/core/dist/goal.js +44 -2
- package/node_modules/@maka/core/dist/permission.js +0 -1
- package/node_modules/@maka/core/dist/runtime-boundary.js +73 -29
- package/node_modules/@maka/core/dist/runtime-event.js +6 -3
- package/node_modules/@maka/core/dist/runtime-handoff.js +10 -2
- package/node_modules/@maka/core/dist/runtime-logical-execution.js +39 -14
- package/node_modules/@maka/core/dist/tool-result-archive-evidence.js +3 -1
- package/node_modules/@maka/core/dist/tool-result-record-schema.js +2 -1
- package/node_modules/@maka/core/dist/unified-diff.js +33 -26
- package/node_modules/@maka/runtime/dist/ai-sdk-compaction.js +49 -178
- package/node_modules/@maka/runtime/dist/ai-sdk-message-projection.js +7 -2
- package/node_modules/@maka/runtime/dist/ai-sdk-turn.js +15 -53
- package/node_modules/@maka/runtime/dist/bash-model-output.js +7 -1
- package/node_modules/@maka/runtime/dist/bash-tail-buffer.js +13 -52
- package/node_modules/@maka/runtime/dist/builtin-tools.js +59 -111
- package/node_modules/@maka/runtime/dist/child-fd-input.js +3 -2
- package/node_modules/@maka/runtime/dist/context-budget-policy.js +1 -11
- package/node_modules/@maka/runtime/dist/context-budget.js +12 -1
- package/node_modules/@maka/runtime/dist/conversation-copy.js +104 -9
- package/node_modules/@maka/runtime/dist/filesystem-executor.js +10 -6
- package/node_modules/@maka/runtime/dist/filesystem-worker/client.js +77 -19
- package/node_modules/@maka/runtime/dist/filesystem-worker/launch-spec.js +66 -55
- package/node_modules/@maka/runtime/dist/filesystem-worker/operations.js +34 -97
- package/node_modules/@maka/runtime/dist/filesystem-worker/protocol.js +25 -10
- package/node_modules/@maka/runtime/dist/filesystem-worker/worker-entry.js +2 -0
- package/node_modules/@maka/runtime/dist/glob-search.js +74 -0
- package/node_modules/@maka/runtime/dist/goal-continuation.js +78 -8
- package/node_modules/@maka/runtime/dist/goal-state.js +7 -0
- package/node_modules/@maka/runtime/dist/grep-search.js +155 -0
- package/node_modules/@maka/runtime/dist/ledger-tool-result-archive-reader.js +84 -94
- package/node_modules/@maka/runtime/dist/model-history.js +25 -3
- package/node_modules/@maka/runtime/dist/pipe-tail-collector.js +6 -9
- package/node_modules/@maka/runtime/dist/read-page.js +231 -0
- package/node_modules/@maka/runtime/dist/request-projection.js +2 -15
- package/node_modules/@maka/runtime/dist/ripgrep-executable.js +62 -0
- package/node_modules/@maka/runtime/dist/ripgrep-guidance.js +81 -0
- package/node_modules/@maka/runtime/dist/runtime-event-read-model.js +187 -20
- package/node_modules/@maka/runtime/dist/runtime-read-model.js +2 -1
- package/node_modules/@maka/runtime/dist/sandbox/linux-profile-path.js +7 -1
- package/node_modules/@maka/runtime/dist/sandbox/linux-sandbox.js +20 -5
- package/node_modules/@maka/runtime/dist/session-manager.js +6 -6
- package/node_modules/@maka/runtime/dist/session-recap.js +9 -5
- package/node_modules/@maka/runtime/dist/shell-exec.js +7 -25
- package/node_modules/@maka/runtime/dist/shell-run-manager.js +1 -1
- package/node_modules/@maka/runtime/dist/shell-run-tool-result.js +1 -1
- package/node_modules/@maka/runtime/dist/shell-tools.js +6 -12
- package/node_modules/@maka/runtime/dist/tool-availability.js +0 -1
- package/node_modules/@maka/runtime/dist/tool-output.js +1 -1
- package/node_modules/@maka/runtime/dist/tool-result-archive-capability.js +24 -36
- package/node_modules/@maka/runtime/dist/tool-result-archive-resource.js +32 -527
- package/node_modules/@maka/runtime/dist/tool-result-archive-transition.js +17 -119
- package/node_modules/@maka/runtime/dist/tool-result-archive.js +7 -25
- package/node_modules/@maka/runtime/dist/tool-runtime.js +7 -5
- package/node_modules/@maka/runtime/dist/workers/filesystem-worker.js +6933 -3681
- package/node_modules/@maka/runtime/dist/workspace-executor.js +20 -24
- package/node_modules/@maka/runtime/package.json +2 -0
- package/node_modules/@maka/runtime-host/dist/client/host-handoff-copy.js +185 -191
- package/node_modules/@maka/runtime-host/dist/client/reconnecting-connection.js +3 -0
- package/node_modules/@maka/runtime-host/dist/protocol/index.js +5 -1
- package/node_modules/@maka/runtime-host/dist/protocol/message.js +2 -2
- package/node_modules/@maka/runtime-host/dist/protocol/operations.js +1 -0
- package/node_modules/@maka/runtime-host/dist/protocol/session-continuity.js +2 -2
- package/node_modules/@maka/runtime-host/dist/protocol/turn.js +10 -2
- package/node_modules/@maka/runtime-host/dist/protocol/workhub-coordination.js +38 -0
- package/node_modules/@maka/runtime-host/dist/server/execution-artifacts.js +2 -8
- package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +2 -0
- package/node_modules/@maka/runtime-host/dist/server/goal-coordinator.js +81 -7
- package/node_modules/@maka/runtime-host/dist/server/hosted-execution-tool-profile.js +13 -13
- package/node_modules/@maka/runtime-host/dist/server/interaction-coordinator.js +65 -0
- package/node_modules/@maka/runtime-host/dist/server/root-turn-coordinator.js +1 -0
- package/node_modules/@maka/runtime-host/dist/server/session-continuity-coordinator.js +5 -2
- package/node_modules/@maka/runtime-host/dist/server/session-transcript-reader.js +88 -72
- package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-action-gate.js +21 -4
- package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-coordinator.js +145 -1
- package/node_modules/@maka/storage/dist/agent-run-store.js +5 -2
- package/node_modules/@maka/storage/dist/execution-stores.js +2 -1
- package/node_modules/@maka/storage/dist/runtime-transcript-query.js +27 -14
- package/node_modules/@maka/storage/dist/sqlite-runtime-store.js +69 -3
- package/node_modules/balanced-match/LICENSE.md +23 -0
- package/node_modules/balanced-match/README.md +57 -0
- package/node_modules/balanced-match/dist/commonjs/index.js +59 -0
- package/node_modules/balanced-match/dist/commonjs/package.json +3 -0
- package/node_modules/balanced-match/dist/esm/index.js +54 -0
- package/node_modules/balanced-match/dist/esm/package.json +3 -0
- package/node_modules/balanced-match/package.json +68 -0
- package/node_modules/brace-expansion/LICENSE +23 -0
- package/node_modules/brace-expansion/README.md +105 -0
- package/node_modules/brace-expansion/dist/commonjs/index.js +289 -0
- package/node_modules/brace-expansion/dist/commonjs/package.json +3 -0
- package/node_modules/brace-expansion/dist/esm/index.js +285 -0
- package/node_modules/brace-expansion/dist/esm/package.json +3 -0
- package/node_modules/brace-expansion/package.json +64 -0
- package/node_modules/glob/LICENSE.md +63 -0
- package/node_modules/glob/README.md +1203 -0
- package/node_modules/glob/dist/commonjs/glob.js +248 -0
- package/node_modules/glob/dist/commonjs/has-magic.js +27 -0
- package/node_modules/glob/dist/commonjs/ignore.js +119 -0
- package/node_modules/glob/dist/commonjs/index.js +68 -0
- package/node_modules/glob/dist/commonjs/index.min.js +4 -0
- package/node_modules/glob/dist/commonjs/package.json +3 -0
- package/node_modules/glob/dist/commonjs/pattern.js +223 -0
- package/node_modules/glob/dist/commonjs/processor.js +301 -0
- package/node_modules/glob/dist/commonjs/walker.js +387 -0
- package/node_modules/glob/dist/esm/glob.js +244 -0
- package/node_modules/glob/dist/esm/has-magic.js +23 -0
- package/node_modules/glob/dist/esm/ignore.js +115 -0
- package/node_modules/glob/dist/esm/index.js +55 -0
- package/node_modules/glob/dist/esm/index.min.js +4 -0
- package/node_modules/glob/dist/esm/package.json +3 -0
- package/node_modules/glob/dist/esm/pattern.js +219 -0
- package/node_modules/glob/dist/esm/processor.js +294 -0
- package/node_modules/glob/dist/esm/walker.js +381 -0
- package/node_modules/glob/package.json +98 -0
- package/node_modules/minimatch/LICENSE.md +55 -0
- package/node_modules/minimatch/README.md +528 -0
- package/node_modules/minimatch/dist/commonjs/assert-valid-pattern.js +14 -0
- package/node_modules/minimatch/dist/commonjs/ast.js +845 -0
- package/node_modules/minimatch/dist/commonjs/brace-expressions.js +150 -0
- package/node_modules/minimatch/dist/commonjs/escape.js +30 -0
- package/node_modules/minimatch/dist/commonjs/index.js +1127 -0
- package/node_modules/minimatch/dist/commonjs/package.json +3 -0
- package/node_modules/minimatch/dist/commonjs/unescape.js +38 -0
- package/node_modules/minimatch/dist/esm/assert-valid-pattern.js +10 -0
- package/node_modules/minimatch/dist/esm/ast.js +841 -0
- package/node_modules/minimatch/dist/esm/brace-expressions.js +146 -0
- package/node_modules/minimatch/dist/esm/escape.js +26 -0
- package/node_modules/minimatch/dist/esm/index.js +1114 -0
- package/node_modules/minimatch/dist/esm/package.json +3 -0
- package/node_modules/minimatch/dist/esm/unescape.js +34 -0
- package/node_modules/minimatch/package.json +73 -0
- package/node_modules/minipass/LICENSE.md +55 -0
- package/node_modules/minipass/README.md +825 -0
- package/node_modules/minipass/dist/commonjs/index.js +1038 -0
- package/node_modules/minipass/dist/commonjs/package.json +3 -0
- package/node_modules/minipass/dist/esm/index.js +1020 -0
- package/node_modules/minipass/dist/esm/package.json +3 -0
- package/node_modules/minipass/package.json +77 -0
- package/node_modules/path-scurry/LICENSE.md +55 -0
- package/node_modules/path-scurry/README.md +636 -0
- package/node_modules/path-scurry/dist/commonjs/index.js +2018 -0
- package/node_modules/path-scurry/dist/commonjs/package.json +3 -0
- package/node_modules/path-scurry/dist/esm/index.js +1983 -0
- package/node_modules/path-scurry/dist/esm/package.json +3 -0
- package/node_modules/path-scurry/node_modules/lru-cache/LICENSE.md +55 -0
- package/node_modules/path-scurry/node_modules/lru-cache/README.md +469 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/diagnostics-channel.js +7 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/index.js +1726 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/index.min.js +2 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/browser/perf.js +10 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/diagnostics-channel-cjs.d.cts.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/diagnostics-channel.js +7 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.js +1726 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/index.min.js +2 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/diagnostics-channel.js +9 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/index.js +1726 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/index.min.js +2 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/node/perf.js +10 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/package.json +3 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/commonjs/perf.js +10 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/diagnostics-channel.js +4 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/index.js +1722 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/index.min.js +2 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/browser/perf.js +7 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/diagnostics-channel-esm.d.mts.map +1 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/diagnostics-channel.js +19 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.js +1722 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.min.js +2 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/diagnostics-channel.js +6 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/index.js +1722 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/index.min.js +2 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/node/perf.js +7 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/package.json +3 -0
- package/node_modules/path-scurry/node_modules/lru-cache/dist/esm/perf.js +7 -0
- package/node_modules/path-scurry/node_modules/lru-cache/package.json +154 -0
- package/node_modules/path-scurry/package.json +72 -0
- package/package.json +1 -1
- package/node_modules/@maka/runtime/dist/active-tool-result-prune.js +0 -248
- package/node_modules/@maka/runtime/dist/active-tool-result-working-set.js +0 -218
- package/node_modules/@maka/runtime/dist/archive-read-tool.js +0 -115
|
@@ -0,0 +1,81 @@
|
|
|
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
|
+
* Grep's only engine is ripgrep, and nothing ships it (#5167). These builders
|
|
21
|
+
* keep the missing-ripgrep copy identical on the local executor and the
|
|
22
|
+
* filesystem worker, so the model and the user learn the same fix whichever
|
|
23
|
+
* path ran the search. Both paths look ripgrep up again on the next attempt —
|
|
24
|
+
* the local executor on every call, the worker whenever the copy it knew is
|
|
25
|
+
* missing, gone or replaced — so the recovery is always "install it where the
|
|
26
|
+
* Host runs, then retry", never a restart. The Windows sandbox refusal
|
|
27
|
+
* deliberately stays in the worker: that is a capability limit of the
|
|
28
|
+
* AppContainer, not a missing dependency.
|
|
29
|
+
*
|
|
30
|
+
* The copy reaches the model as tool output, so it names a place without
|
|
31
|
+
* naming the machine. A WSL distribution is an identifier Maka already keeps
|
|
32
|
+
* for its Hosts; a hostname is personal (a default macOS name carries its
|
|
33
|
+
* owner's name) and Maka otherwise shows it only as a device name in Desktop,
|
|
34
|
+
* which already says which Host is active.
|
|
35
|
+
*/
|
|
36
|
+
const RIPGREP_INSTALL_URL = 'https://github.com/BurntSushi/ripgrep#installation';
|
|
37
|
+
export function currentRipgrepEnvironment(env = process.env) {
|
|
38
|
+
const distribution = env.WSL_DISTRO_NAME?.trim();
|
|
39
|
+
return distribution ? { kind: 'wsl', name: distribution } : undefined;
|
|
40
|
+
}
|
|
41
|
+
/** The worker receives its environment as a launch argument: its own environment block is scrubbed. */
|
|
42
|
+
export function formatRipgrepEnvironmentArg(environment) {
|
|
43
|
+
return `${environment.kind}:${environment.name}`;
|
|
44
|
+
}
|
|
45
|
+
export function parseRipgrepEnvironmentArg(value) {
|
|
46
|
+
const match = value ? /^wsl:(.+)$/u.exec(value) : null;
|
|
47
|
+
return match ? { kind: 'wsl', name: match[1] } : undefined;
|
|
48
|
+
}
|
|
49
|
+
function installLocation(environment) {
|
|
50
|
+
return environment
|
|
51
|
+
? `the WSL distribution "${environment.name}"`
|
|
52
|
+
: 'the machine this Maka Host runs on (for a remote Host, that server rather than this computer)';
|
|
53
|
+
}
|
|
54
|
+
function installInstructions(environment, platform) {
|
|
55
|
+
const command = platform === 'darwin'
|
|
56
|
+
? '`brew install ripgrep`'
|
|
57
|
+
: platform === 'win32'
|
|
58
|
+
? '`winget install BurntSushi.ripgrep.MSVC`'
|
|
59
|
+
: 'your package manager (for example `apt install ripgrep`)';
|
|
60
|
+
return `Install it on ${installLocation(environment)} with ${command}, or see ${RIPGREP_INSTALL_URL}, then retry.`;
|
|
61
|
+
}
|
|
62
|
+
/** The local executor looks `rg` up on PATH at every call. */
|
|
63
|
+
export function ripgrepMissingOnPathMessage(environment, platform = process.platform) {
|
|
64
|
+
return `Grep requires ripgrep (\`rg\`), and it was not found on PATH. ${installInstructions(environment, platform)}`;
|
|
65
|
+
}
|
|
66
|
+
/** The worker was launched without a usable ripgrep; its next launch looks again. */
|
|
67
|
+
export function ripgrepMissingMessage(environment, platform = process.platform) {
|
|
68
|
+
return `Grep requires ripgrep (\`rg\`), and no usable copy was found. ${installInstructions(environment, platform)}`;
|
|
69
|
+
}
|
|
70
|
+
/** The executable the worker was launched with is gone (e.g. a package upgrade removed it). */
|
|
71
|
+
export function ripgrepVanishedMessage(executable, environment) {
|
|
72
|
+
return `Grep could not start ripgrep at ${executable}; it was moved or removed, for example by a package upgrade. Reinstall it on ${installLocation(environment)} if needed, then retry.`;
|
|
73
|
+
}
|
|
74
|
+
/** Local-executor twin of the worker protocol's `grep_unavailable` error. */
|
|
75
|
+
export class RipgrepUnavailableError extends Error {
|
|
76
|
+
code = 'grep_unavailable';
|
|
77
|
+
constructor(message, options) {
|
|
78
|
+
super(message, options);
|
|
79
|
+
this.name = 'RipgrepUnavailableError';
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -25,6 +25,7 @@ import { isPartialRuntimeEvent, isTerminalRuntimeEvent, isTerminalRuntimeEventSt
|
|
|
25
25
|
import { decodePersistedToolResultContent } from '@maka/core/tool-result-record-schema';
|
|
26
26
|
const SETTLED_SANDBOX_BOUNDARY_STATUSES = SANDBOX_BOUNDARY_REQUEST_STATUSES.filter((status) => status !== 'pending');
|
|
27
27
|
import { isArchivedToolResultPlaceholder } from './tool-result-archive.js';
|
|
28
|
+
import { truncateToolOutput } from './tool-output.js';
|
|
28
29
|
/**
|
|
29
30
|
* Whether a diagnostic means the projection may have lost user-visible content.
|
|
30
31
|
*
|
|
@@ -94,7 +95,54 @@ const UNCLAIMED_RUNTIME_EVENT_DIAGNOSTIC_CODES = [
|
|
|
94
95
|
export function isUnclaimedRuntimeEventDiagnostic(diagnostic) {
|
|
95
96
|
return UNCLAIMED_RUNTIME_EVENT_DIAGNOSTIC_CODES.includes(diagnostic.code);
|
|
96
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* Keep a completed local terminal result useful but bounded in transcript views.
|
|
100
|
+
* The durable RuntimeEvent remains untouched and the marker names its retained
|
|
101
|
+
* result, so readers can fetch the full output without repeating the command.
|
|
102
|
+
*/
|
|
103
|
+
export function projectTranscriptToolResult(event, content) {
|
|
104
|
+
if (content.kind !== 'terminal' ||
|
|
105
|
+
content.output.mode !== 'pipes' ||
|
|
106
|
+
!hasLocalTerminalModelProjection(event)) {
|
|
107
|
+
return content;
|
|
108
|
+
}
|
|
109
|
+
const recoveryHint = `Read ${JSON.stringify({
|
|
110
|
+
path: `maka://runtime/tool-results/${encodeURIComponent(event.id)}`,
|
|
111
|
+
})} for the retained output; follow next to continue.`;
|
|
112
|
+
const options = { maxBytes: 1024, maxLines: 20, direction: 'tail', recoveryHint };
|
|
113
|
+
const stdout = truncateToolOutput(content.output.stdout, options);
|
|
114
|
+
const stderr = truncateToolOutput(content.output.stderr, options);
|
|
115
|
+
if (!stdout.truncated && !stderr.truncated)
|
|
116
|
+
return content;
|
|
117
|
+
return {
|
|
118
|
+
...content,
|
|
119
|
+
output: {
|
|
120
|
+
...content.output,
|
|
121
|
+
stdout: stdout.content,
|
|
122
|
+
stderr: stderr.content,
|
|
123
|
+
stdoutTruncated: content.output.stdoutTruncated || stdout.truncated,
|
|
124
|
+
stderrTruncated: content.output.stderrTruncated || stderr.truncated,
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
function hasLocalTerminalModelProjection(event) {
|
|
129
|
+
const content = event.content;
|
|
130
|
+
if (content?.kind !== 'function_response' || content.providerExecuted)
|
|
131
|
+
return false;
|
|
132
|
+
const projection = content.modelProjection;
|
|
133
|
+
return (projection?.kind === 'json' &&
|
|
134
|
+
projection.value !== null &&
|
|
135
|
+
typeof projection.value === 'object' &&
|
|
136
|
+
'kind' in projection.value &&
|
|
137
|
+
projection.value.kind === 'terminal');
|
|
138
|
+
}
|
|
97
139
|
export function projectRuntimeEventsToStoredMessages(events, options) {
|
|
140
|
+
const projector = createRuntimeEventStoredMessageProjector(options);
|
|
141
|
+
for (const event of events)
|
|
142
|
+
projector.push(event);
|
|
143
|
+
return projector.finish();
|
|
144
|
+
}
|
|
145
|
+
export function createRuntimeEventStoredMessageProjector(options) {
|
|
98
146
|
const state = {
|
|
99
147
|
invocations: normalizeInvocations(options.invocations),
|
|
100
148
|
diagnostics: [],
|
|
@@ -102,6 +150,8 @@ export function projectRuntimeEventsToStoredMessages(events, options) {
|
|
|
102
150
|
permissionRequestById: new Map(),
|
|
103
151
|
thinkingByMessageId: new Map(),
|
|
104
152
|
contentOrderByMessageId: new Map(),
|
|
153
|
+
...(options.projectToolResult ? { projectToolResult: options.projectToolResult } : {}),
|
|
154
|
+
sourceOrder: -1,
|
|
105
155
|
};
|
|
106
156
|
const messages = [];
|
|
107
157
|
/**
|
|
@@ -112,19 +162,48 @@ export function projectRuntimeEventsToStoredMessages(events, options) {
|
|
|
112
162
|
* handled are exactly that event's rows. A durable reader numbers its pages
|
|
113
163
|
* from this, which is why it is recorded here rather than rediscovered.
|
|
114
164
|
*/
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
165
|
+
const messageSources = [];
|
|
166
|
+
const diagnosticSources = [];
|
|
167
|
+
const deferredPermissionAcceptances = [];
|
|
168
|
+
const permissionRequestIds = new Set();
|
|
169
|
+
let nextSourceOrder = 0;
|
|
170
|
+
let finished;
|
|
171
|
+
const attributeEmitted = (event, sourceOrder, firstSourcePosition) => {
|
|
172
|
+
let sourcePosition = firstSourcePosition;
|
|
173
|
+
while (messageSources.length < messages.length) {
|
|
174
|
+
const message = messages[messageSources.length];
|
|
175
|
+
messageSources.push({
|
|
176
|
+
eventId: event.id,
|
|
177
|
+
sourceOrder,
|
|
178
|
+
sourcePosition,
|
|
179
|
+
emittedOrder: messageSources.length,
|
|
180
|
+
});
|
|
181
|
+
sourcePosition += 1;
|
|
182
|
+
options.onMessage?.(message, event.id);
|
|
183
|
+
}
|
|
184
|
+
return sourcePosition;
|
|
120
185
|
};
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
186
|
+
const attributeDiagnostics = (sourceOrder, firstSourcePosition) => {
|
|
187
|
+
let sourcePosition = firstSourcePosition;
|
|
188
|
+
while (diagnosticSources.length < state.diagnostics.length) {
|
|
189
|
+
diagnosticSources.push({
|
|
190
|
+
sourceOrder,
|
|
191
|
+
sourcePosition,
|
|
192
|
+
emittedOrder: diagnosticSources.length,
|
|
193
|
+
});
|
|
194
|
+
sourcePosition += 1;
|
|
195
|
+
}
|
|
196
|
+
return sourcePosition;
|
|
197
|
+
};
|
|
198
|
+
const projectEvent = (event, sourceOrder) => {
|
|
199
|
+
let nextMessagePosition = 0;
|
|
200
|
+
let nextDiagnosticPosition = 0;
|
|
201
|
+
state.sourceOrder = sourceOrder;
|
|
124
202
|
recordStepContentOrder(event, state);
|
|
125
203
|
if (isPartialRuntimeEvent(event)) {
|
|
126
204
|
diagnostic(state, event, 'partial_skipped', 'partial RuntimeEvent skipped');
|
|
127
|
-
|
|
205
|
+
attributeDiagnostics(sourceOrder, nextDiagnosticPosition);
|
|
206
|
+
return;
|
|
128
207
|
}
|
|
129
208
|
let projected = false;
|
|
130
209
|
const content = event.content;
|
|
@@ -197,7 +276,17 @@ export function projectRuntimeEventsToStoredMessages(events, options) {
|
|
|
197
276
|
projected = true;
|
|
198
277
|
}
|
|
199
278
|
if (event.actions?.permissionAnswerAccepted) {
|
|
200
|
-
|
|
279
|
+
nextMessagePosition = attributeEmitted(event, sourceOrder, nextMessagePosition);
|
|
280
|
+
nextDiagnosticPosition = attributeDiagnostics(sourceOrder, nextDiagnosticPosition);
|
|
281
|
+
const requestId = event.actions.permissionAnswerAccepted.requestId;
|
|
282
|
+
permissionRequestIds.add(requestId);
|
|
283
|
+
deferredPermissionAcceptances.push({
|
|
284
|
+
event: permissionAcceptanceProjectionEvent(event),
|
|
285
|
+
ledgerRequest: state.permissionRequestById.get(requestId),
|
|
286
|
+
sourceOrder,
|
|
287
|
+
messagePosition: nextMessagePosition++,
|
|
288
|
+
diagnosticPosition: nextDiagnosticPosition++,
|
|
289
|
+
});
|
|
201
290
|
projected = true;
|
|
202
291
|
}
|
|
203
292
|
if (event.actions?.permissionClosureAccepted) {
|
|
@@ -284,14 +373,74 @@ export function projectRuntimeEventsToStoredMessages(events, options) {
|
|
|
284
373
|
diagnostic(state, event, 'unsupported_event', 'RuntimeEvent shape is not supported by the legacy read-model projection');
|
|
285
374
|
}
|
|
286
375
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
376
|
+
attributeEmitted(event, sourceOrder, nextMessagePosition);
|
|
377
|
+
attributeDiagnostics(sourceOrder, nextDiagnosticPosition);
|
|
378
|
+
};
|
|
379
|
+
const push = (event) => {
|
|
380
|
+
if (finished)
|
|
381
|
+
throw new Error('RuntimeEvent StoredMessage projector is already finished');
|
|
382
|
+
const sourceOrder = nextSourceOrder++;
|
|
383
|
+
projectEvent(options.active ? settledPresentationEvent(event) : event, sourceOrder);
|
|
384
|
+
};
|
|
385
|
+
const finish = () => {
|
|
386
|
+
if (finished)
|
|
387
|
+
return finished;
|
|
388
|
+
for (const acceptance of deferredPermissionAcceptances) {
|
|
389
|
+
const before = messages.length;
|
|
390
|
+
projectCanonicalPermissionOutcome(acceptance.event, state, messages, options.canonicalPermissionOutcomes, acceptance.ledgerRequest);
|
|
391
|
+
if (messages.length > before) {
|
|
392
|
+
attributeEmitted(acceptance.event, acceptance.sourceOrder, acceptance.messagePosition);
|
|
393
|
+
}
|
|
394
|
+
attributeDiagnostics(acceptance.sourceOrder, acceptance.diagnosticPosition);
|
|
291
395
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
396
|
+
if (options.active) {
|
|
397
|
+
for (const pendingItems of [...state.thinkingByMessageId.values()]) {
|
|
398
|
+
const pending = pendingItems.at(-1);
|
|
399
|
+
if (pending)
|
|
400
|
+
projectEvent(emptyAssistantText(pending.event), pending.sourceOrder);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
const orderedDiagnostics = state.diagnostics
|
|
404
|
+
.map((diagnostic, index) => ({ diagnostic, source: diagnosticSources[index] }))
|
|
405
|
+
.sort((left, right) => left.source.sourceOrder - right.source.sourceOrder ||
|
|
406
|
+
left.source.sourcePosition - right.source.sourcePosition ||
|
|
407
|
+
left.source.emittedOrder - right.source.emittedOrder);
|
|
408
|
+
state.diagnostics.splice(0, state.diagnostics.length, ...orderedDiagnostics.map(({ diagnostic }) => diagnostic));
|
|
409
|
+
if (!options.active) {
|
|
410
|
+
for (const pendingItems of state.thinkingByMessageId.values()) {
|
|
411
|
+
for (const pending of pendingItems) {
|
|
412
|
+
diagnostic(state, pending.event, 'unsupported_event', 'thinking content has no assistant text row with a matching message id');
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
const ordered = messages
|
|
417
|
+
.map((message, index) => ({ message, source: messageSources[index] }))
|
|
418
|
+
.sort((left, right) => left.source.sourceOrder - right.source.sourceOrder ||
|
|
419
|
+
left.source.sourcePosition - right.source.sourcePosition ||
|
|
420
|
+
left.source.emittedOrder - right.source.emittedOrder);
|
|
421
|
+
finished = {
|
|
422
|
+
messages: ordered.map(({ message }) => message),
|
|
423
|
+
diagnostics: state.diagnostics,
|
|
424
|
+
sourceEventIds: ordered.map(({ source }) => source.eventId),
|
|
425
|
+
};
|
|
426
|
+
deferredPermissionAcceptances.length = 0;
|
|
427
|
+
messageSources.length = 0;
|
|
428
|
+
diagnosticSources.length = 0;
|
|
429
|
+
state.invocations.clear();
|
|
430
|
+
state.toolNameByUseId.clear();
|
|
431
|
+
state.permissionRequestById.clear();
|
|
432
|
+
state.thinkingByMessageId.clear();
|
|
433
|
+
state.contentOrderByMessageId.clear();
|
|
434
|
+
state.projectToolResult = undefined;
|
|
435
|
+
return finished;
|
|
436
|
+
};
|
|
437
|
+
return {
|
|
438
|
+
push,
|
|
439
|
+
finish,
|
|
440
|
+
get permissionRequestIds() {
|
|
441
|
+
return [...permissionRequestIds];
|
|
442
|
+
},
|
|
443
|
+
};
|
|
295
444
|
}
|
|
296
445
|
/**
|
|
297
446
|
* A running invocation's events as the transcript should show them right now.
|
|
@@ -564,6 +713,7 @@ function projectThinking(event, state, messages) {
|
|
|
564
713
|
event,
|
|
565
714
|
messageId,
|
|
566
715
|
text: event.content.text,
|
|
716
|
+
sourceOrder: state.sourceOrder,
|
|
567
717
|
...(event.content.signature !== undefined ? { signature: event.content.signature } : {}),
|
|
568
718
|
...(event.content.providerOptions !== undefined
|
|
569
719
|
? { providerOptions: structuredClone(event.content.providerOptions) }
|
|
@@ -669,7 +819,7 @@ function projectFunctionResponse(event, state, messages) {
|
|
|
669
819
|
}
|
|
670
820
|
if (event.content.name)
|
|
671
821
|
state.toolNameByUseId.set(toolUseId, event.content.name);
|
|
672
|
-
const
|
|
822
|
+
const decodedResult = archivedPlaceholder
|
|
673
823
|
? {
|
|
674
824
|
kind: 'archived_tool_result',
|
|
675
825
|
status: 'not_loaded',
|
|
@@ -687,6 +837,9 @@ function projectFunctionResponse(event, state, messages) {
|
|
|
687
837
|
reason: archivedPlaceholder.reason,
|
|
688
838
|
}
|
|
689
839
|
: normalizedResult;
|
|
840
|
+
const resultContent = state.projectToolResult
|
|
841
|
+
? state.projectToolResult(event, decodedResult)
|
|
842
|
+
: decodedResult;
|
|
690
843
|
messages.push({
|
|
691
844
|
type: 'tool_result',
|
|
692
845
|
id: stableMessageId(event, state, 'tool_result'),
|
|
@@ -766,11 +919,10 @@ function projectPermissionDecision(event, state, messages) {
|
|
|
766
919
|
});
|
|
767
920
|
return true;
|
|
768
921
|
}
|
|
769
|
-
function projectCanonicalPermissionOutcome(event, state, messages, outcomes) {
|
|
922
|
+
function projectCanonicalPermissionOutcome(event, state, messages, outcomes, ledgerRequest) {
|
|
770
923
|
const accepted = event.actions?.permissionAnswerAccepted;
|
|
771
924
|
if (!accepted)
|
|
772
925
|
return;
|
|
773
|
-
const ledgerRequest = state.permissionRequestById.get(accepted.requestId);
|
|
774
926
|
const canonical = outcomes?.get(accepted.requestId);
|
|
775
927
|
const toolUseId = event.refs?.toolCallId;
|
|
776
928
|
if (!canonical || !toolUseId) {
|
|
@@ -807,6 +959,21 @@ function projectCanonicalPermissionOutcome(event, state, messages, outcomes) {
|
|
|
807
959
|
...(ledgerRequest?.hint !== undefined ? { hint: ledgerRequest.hint } : {}),
|
|
808
960
|
});
|
|
809
961
|
}
|
|
962
|
+
function permissionAcceptanceProjectionEvent(event) {
|
|
963
|
+
return {
|
|
964
|
+
id: event.id,
|
|
965
|
+
sessionId: event.sessionId,
|
|
966
|
+
invocationId: event.invocationId,
|
|
967
|
+
runId: event.runId,
|
|
968
|
+
turnId: event.turnId,
|
|
969
|
+
ts: event.ts,
|
|
970
|
+
partial: event.partial,
|
|
971
|
+
role: event.role,
|
|
972
|
+
author: event.author,
|
|
973
|
+
actions: { permissionAnswerAccepted: event.actions.permissionAnswerAccepted },
|
|
974
|
+
...(event.refs?.toolCallId ? { refs: { toolCallId: event.refs.toolCallId } } : {}),
|
|
975
|
+
};
|
|
976
|
+
}
|
|
810
977
|
function projectTokenUsage(event, state, messages) {
|
|
811
978
|
const usage = event.actions?.tokenUsage;
|
|
812
979
|
if (!usage)
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import { deriveTurnRecords } from '@maka/core/session';
|
|
20
20
|
import { isSessionInlineInvocation } from '@maka/core/runtime-invocation';
|
|
21
|
-
import { activePresentationRuntimeEvents, classifyRuntimeEventTerminalFact, isHardRuntimeEventReadModelDiagnostic, projectRuntimeEventsToStoredMessages, } from './runtime-event-read-model.js';
|
|
21
|
+
import { activePresentationRuntimeEvents, classifyRuntimeEventTerminalFact, isHardRuntimeEventReadModelDiagnostic, projectRuntimeEventsToStoredMessages, projectTranscriptToolResult, } from './runtime-event-read-model.js';
|
|
22
22
|
import { buildRuntimeEventModelReplayPlan, } from './model-history.js';
|
|
23
23
|
const CANONICAL_PERMISSION_READ_CONCURRENCY = 8;
|
|
24
24
|
export class RuntimeReadModelError extends Error {
|
|
@@ -116,6 +116,7 @@ export class RuntimeReadModel {
|
|
|
116
116
|
const projected = projectRuntimeEventsToStoredMessages(input.events, {
|
|
117
117
|
invocations: input.invocations,
|
|
118
118
|
canonicalPermissionOutcomes: canonicalPermissionRead.outcomes,
|
|
119
|
+
projectToolResult: projectTranscriptToolResult,
|
|
119
120
|
});
|
|
120
121
|
const diagnostics = [
|
|
121
122
|
...input.diagnostics,
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* specific language governing permissions and limitations
|
|
17
17
|
* under the License.
|
|
18
18
|
*/
|
|
19
|
-
import { closeSync, constants, fstatSync, lstatSync, openSync } from 'node:fs';
|
|
19
|
+
import { closeSync, constants, fstatSync, lstatSync, openSync, readlinkSync } from 'node:fs';
|
|
20
20
|
export function pinExistingLinuxProfilePath(input) {
|
|
21
21
|
const existing = (() => {
|
|
22
22
|
try {
|
|
@@ -43,6 +43,12 @@ export function pinExistingLinuxProfilePath(input) {
|
|
|
43
43
|
closeSync(sourceFd);
|
|
44
44
|
};
|
|
45
45
|
try {
|
|
46
|
+
// O_NOFOLLOW only protects the last component. Check the kernel's path for
|
|
47
|
+
// the opened object too, so a replaced ancestor cannot redirect an approved
|
|
48
|
+
// canonical path. Checking the original pathname again would race anew.
|
|
49
|
+
if (process.platform === 'linux' && readlinkSync(`/proc/self/fd/${sourceFd}`) !== input.path) {
|
|
50
|
+
throw new Error(`Approved sandbox path changed before pinning: ${input.path}`);
|
|
51
|
+
}
|
|
46
52
|
const metadata = fstatSync(sourceFd, { bigint: true });
|
|
47
53
|
if (metadata.dev !== BigInt(existing.dev) ||
|
|
48
54
|
metadata.ino !== BigInt(existing.ino) ||
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* under the License.
|
|
18
18
|
*/
|
|
19
19
|
import { posix } from 'node:path';
|
|
20
|
-
import { readdirSync } from 'node:fs';
|
|
20
|
+
import { fstatSync, readdirSync } from 'node:fs';
|
|
21
21
|
import { detectLinuxSandboxCapability, LINUX_BWRAP_REQUIRED_NAMESPACE_ARGS, } from './linux-capability.js';
|
|
22
22
|
const DEFAULT_READ_ONLY_HOST_PATHS = ['/usr', '/bin', '/sbin', '/lib', '/lib64', '/etc'];
|
|
23
23
|
export class LinuxBubblewrapBackend {
|
|
@@ -59,7 +59,12 @@ export class LinuxBubblewrapBackend {
|
|
|
59
59
|
catch (error) {
|
|
60
60
|
return failure('backend_not_available', `Unable to enumerate protected metadata: ${error instanceof Error ? error.message : String(error)}`, plan.platform, plan.preference);
|
|
61
61
|
}
|
|
62
|
-
const
|
|
62
|
+
const exactReadableRoots = exactProfileRoots(command.profile, 'read');
|
|
63
|
+
const pinnedFdInputs = command.pathContext.pinnedProfilePaths
|
|
64
|
+
?.filter((entry) => !(entry.access === 'read' &&
|
|
65
|
+
exactReadableRoots.has(entry.path) &&
|
|
66
|
+
fstatSync(entry.sourceFd).isDirectory()))
|
|
67
|
+
.map(({ fd, sourceFd, releaseSource }) => ({
|
|
63
68
|
fd,
|
|
64
69
|
sourceFd,
|
|
65
70
|
...(releaseSource ? { releaseSource } : {}),
|
|
@@ -159,9 +164,6 @@ function buildBubblewrapArgvWithRoots(input, roots) {
|
|
|
159
164
|
if (networkRestricted(command.profile)) {
|
|
160
165
|
argv.push('--unshare-net', '--seccomp', '3');
|
|
161
166
|
}
|
|
162
|
-
for (const path of DEFAULT_READ_ONLY_HOST_PATHS) {
|
|
163
|
-
argv.push('--ro-bind-try', path, path);
|
|
164
|
-
}
|
|
165
167
|
const runtimeWritableRoots = removeNestedRoots((command.pathContext.runtimeWritableRoots ?? []).filter(isUsableRuntimeRoot));
|
|
166
168
|
const unavailableProfilePaths = new Set(command.pathContext.unavailableProfilePaths ?? []);
|
|
167
169
|
const pinnedRuntimeWritableRoots = new Map((command.pathContext.pinnedRuntimeWritableRoots ?? []).map((entry) => [entry.path, entry]));
|
|
@@ -219,6 +221,17 @@ function buildBubblewrapArgvWithRoots(input, roots) {
|
|
|
219
221
|
for (const directory of requiredParentDirectories(mountRoots)) {
|
|
220
222
|
argv.push('--dir', directory);
|
|
221
223
|
}
|
|
224
|
+
// Materialize exact directory markers before any host bind. Creating them
|
|
225
|
+
// inside an already-mounted tree could follow concurrently replaced symlinks.
|
|
226
|
+
const exactReadableDirectories = new Set(profileReadableRoots.filter((root) => {
|
|
227
|
+
const pinned = pinnedProfilePaths.get(root);
|
|
228
|
+
return exactReadableRoots.has(root) && pinned && fstatSync(pinned.sourceFd).isDirectory();
|
|
229
|
+
}));
|
|
230
|
+
for (const directory of exactReadableDirectories)
|
|
231
|
+
argv.push('--dir', directory);
|
|
232
|
+
for (const path of DEFAULT_READ_ONLY_HOST_PATHS) {
|
|
233
|
+
argv.push('--ro-bind-try', path, path);
|
|
234
|
+
}
|
|
222
235
|
for (const directory of extraProgramDirectories) {
|
|
223
236
|
argv.push('--ro-bind', directory, directory);
|
|
224
237
|
}
|
|
@@ -243,6 +256,8 @@ function buildBubblewrapArgvWithRoots(input, roots) {
|
|
|
243
256
|
const pinned = pinnedProfilePaths.get(root);
|
|
244
257
|
if (exactReadableRoots.has(root) && !pinned)
|
|
245
258
|
continue;
|
|
259
|
+
if (exactReadableDirectories.has(root))
|
|
260
|
+
continue;
|
|
246
261
|
argv.push('--ro-bind', pinned ? `/proc/self/fd/${pinned.fd}` : root, root);
|
|
247
262
|
}
|
|
248
263
|
for (const root of profileWritableRoots) {
|
|
@@ -720,10 +720,10 @@ export class SessionManager {
|
|
|
720
720
|
: header.permissionMode;
|
|
721
721
|
const narrows = narrowsExecutionAuthority(current, permissionMode);
|
|
722
722
|
if (narrows && this.runtimeKernel.hasActiveRuns(sessionId)) {
|
|
723
|
-
throw new
|
|
723
|
+
throw new SessionConfigurationTransitionError('session_busy', 'Execution boundary cannot change while a Turn is running');
|
|
724
724
|
}
|
|
725
725
|
if (header.status === 'waiting_for_user') {
|
|
726
|
-
throw new
|
|
726
|
+
throw new SessionConfigurationTransitionError('session_busy', 'Execution boundary cannot change while an Interaction is pending');
|
|
727
727
|
}
|
|
728
728
|
const boundary = await this.commitExecutionBoundaryTransition(sessionId, current, permissionMode, async () => () => this.deps.store.setExecutionBoundaryKind(sessionId, kind, { permissionMode }));
|
|
729
729
|
return boundary;
|
|
@@ -904,18 +904,18 @@ export class SessionManager {
|
|
|
904
904
|
throw new PlanConflictError('Linked child Sessions cannot enter Plan mode');
|
|
905
905
|
}
|
|
906
906
|
if (this.runtimeKernel.hasActiveRuns(sessionId)) {
|
|
907
|
-
throw new
|
|
907
|
+
throw new SessionConfigurationTransitionError('session_busy', 'Collaboration mode cannot change while a Turn is running');
|
|
908
908
|
}
|
|
909
909
|
if (previous.status === 'waiting_for_user') {
|
|
910
|
-
throw new
|
|
910
|
+
throw new SessionConfigurationTransitionError('session_busy', 'Collaboration mode cannot change while an Interaction is pending');
|
|
911
911
|
}
|
|
912
912
|
const planState = await this.requirePlanStore().readState(sessionId);
|
|
913
913
|
if (mode === 'plan' && planState.activeExecutionId) {
|
|
914
|
-
throw new
|
|
914
|
+
throw new SessionConfigurationTransitionError('session_busy', 'An active Plan execution prevents entering Plan mode');
|
|
915
915
|
}
|
|
916
916
|
const latestProposal = planState.proposals.find((proposal) => proposal.proposalId === planState.latestProposalId);
|
|
917
917
|
if (mode === 'agent' && latestProposal?.status === 'pending_approval') {
|
|
918
|
-
throw new
|
|
918
|
+
throw new SessionConfigurationTransitionError('operation_conflict', 'A pending Plan proposal must be resolved before leaving Plan mode');
|
|
919
919
|
}
|
|
920
920
|
const next = await this.deps.store.updateHeader(sessionId, {
|
|
921
921
|
collaborationMode: mode,
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
import { runtimeEventHasModelVisibleContent } from '@maka/core/runtime-event';
|
|
20
20
|
import { resolveSelectedModelContextWindow } from './context-budget-policy.js';
|
|
21
21
|
import { stableJsonLength } from './context-budget-helpers.js';
|
|
22
|
-
import { groupEventsByTurn } from './model-history.js';
|
|
22
|
+
import { groupEventsByTurn, formatTextWithInlineRefs } from './model-history.js';
|
|
23
23
|
import { HistoryCompactSummarizerError } from './history-compact-error.js';
|
|
24
24
|
import { fitHistoryCompactMessages } from './history-compact-input-fit.js';
|
|
25
25
|
const SESSION_RECAP_TOOL_OUTCOME_MAX_CHARS = 600;
|
|
@@ -99,10 +99,14 @@ function projectSessionRecapMessages(events) {
|
|
|
99
99
|
continue;
|
|
100
100
|
const content = event.content;
|
|
101
101
|
if (content?.kind === 'text' && (event.role === 'user' || event.role === 'model')) {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
102
|
+
// The gate above already decided visibility through the shared
|
|
103
|
+
// predicate, which is satisfied by non-empty text or by the structured
|
|
104
|
+
// carriers — so every event reaching here projects, with its trimmed
|
|
105
|
+
// text and staged refs rendered by the shared inline-ref formatter.
|
|
106
|
+
messages.push({
|
|
107
|
+
role: event.role === 'user' ? 'user' : 'assistant',
|
|
108
|
+
content: formatTextWithInlineRefs({ ...content, text: content.text.trim() }),
|
|
109
|
+
});
|
|
106
110
|
continue;
|
|
107
111
|
}
|
|
108
112
|
if (content?.kind !== 'function_response')
|
|
@@ -30,11 +30,11 @@ import { buildShellSpawnPlan, defaultShellPlan } from './shell-detect.js';
|
|
|
30
30
|
import { BashTailBuffer } from './bash-tail-buffer.js';
|
|
31
31
|
import { DEFAULT_PROCESS_TERMINATION_GRACE_MS } from './process-tree-terminator.js';
|
|
32
32
|
import { DEFAULT_PROCESS_IO_DRAIN_TIMEOUT_MS, manageChildProcessLifecycle, } from './child-process-lifecycle.js';
|
|
33
|
-
import { OUTPUT_RECOVERY_HINT } from './tool-output.js';
|
|
34
33
|
import { buildSpawnStdio, closeChildFdSources, writeChildFdInputs, } from './child-fd-input.js';
|
|
35
34
|
// Per-stream cap on the output RETAINED for the result (~1MB). This only bounds
|
|
36
|
-
// what is kept to return. The tool layer
|
|
37
|
-
//
|
|
35
|
+
// what is kept to return. The tool layer preserves this result for durable
|
|
36
|
+
// storage; unified result pruning bounds its model projection.
|
|
37
|
+
// Shared so both Bash paths retain identically.
|
|
38
38
|
export const BASH_MAX_RETAINED_CHARS = 1024 * 1024;
|
|
39
39
|
// Per-stream cap on output forwarded LIVE via emitOutput (~1MB). The command is
|
|
40
40
|
// never killed for size and the full recoverable tail is still RETAINED (above),
|
|
@@ -47,20 +47,6 @@ export const BASH_MAX_LIVE_EMIT_CHARS = 1024 * 1024;
|
|
|
47
47
|
// not lost — it still feeds the retained tail and the returned result.
|
|
48
48
|
export const LIVE_OUTPUT_SUPPRESSED_MARKER = '[live output suppressed: too much output to stream live; the command keeps ' +
|
|
49
49
|
'running and its result still contains the most recent output]';
|
|
50
|
-
// Appended to a stream when BashTailBuffer dropped an oversized line that had no
|
|
51
|
-
// newline to truncate at (dropped whole for redaction safety). Without it, a
|
|
52
|
-
// command whose only output was one giant line would look like it produced
|
|
53
|
-
// nothing. Carries no dropped content — just a recoverable notice.
|
|
54
|
-
const UNSAFE_DROP_MARKER = '[a single line larger than the output limit was omitted for safety. ' +
|
|
55
|
-
OUTPUT_RECOVERY_HINT +
|
|
56
|
-
']';
|
|
57
|
-
export function shellTailValueWithUnsafeDropMarker(buf) {
|
|
58
|
-
const text = buf.value(); // value() trims first, so the drop flag is current after it
|
|
59
|
-
if (!buf.hasDroppedUnsafe())
|
|
60
|
-
return text;
|
|
61
|
-
// Append (not prepend) so a later tail-keeping truncateToolOutput retains it.
|
|
62
|
-
return text ? `${text}\n${UNSAFE_DROP_MARKER}` : UNSAFE_DROP_MARKER;
|
|
63
|
-
}
|
|
64
50
|
/**
|
|
65
51
|
* Run `command` in a shell, streaming output into a memory-bounded tail. Never
|
|
66
52
|
* kills the command for producing too much output — it keeps only the last
|
|
@@ -213,8 +199,8 @@ function runSpawnedProcessWithBoundedTail(program, args, useShellOption, options
|
|
|
213
199
|
return;
|
|
214
200
|
settled = true;
|
|
215
201
|
cleanup();
|
|
216
|
-
const stdout =
|
|
217
|
-
const stderr =
|
|
202
|
+
const stdout = stdoutBuf.value();
|
|
203
|
+
const stderr = stderrBuf.value();
|
|
218
204
|
resolvePromise({
|
|
219
205
|
exitCode: termination
|
|
220
206
|
? termination.timedOut
|
|
@@ -223,12 +209,8 @@ function runSpawnedProcessWithBoundedTail(program, args, useShellOption, options
|
|
|
223
209
|
: (outcome.exitCode ?? (outcome.signal ? 128 : 1)),
|
|
224
210
|
stdout,
|
|
225
211
|
stderr,
|
|
226
|
-
stdoutTruncated: outcome.incompleteOutputs.has('stdout') ||
|
|
227
|
-
|
|
228
|
-
stdoutBuf.hasDroppedUnsafe(),
|
|
229
|
-
stderrTruncated: outcome.incompleteOutputs.has('stderr') ||
|
|
230
|
-
stderrChars > stderr.length ||
|
|
231
|
-
stderrBuf.hasDroppedUnsafe(),
|
|
212
|
+
stdoutTruncated: outcome.incompleteOutputs.has('stdout') || stdoutChars > stdout.length,
|
|
213
|
+
stderrTruncated: outcome.incompleteOutputs.has('stderr') || stderrChars > stderr.length,
|
|
232
214
|
timedOut: !!termination?.timedOut,
|
|
233
215
|
aborted: !!termination?.aborted,
|
|
234
216
|
});
|
|
@@ -715,7 +715,7 @@ export class ShellRunProcessManager {
|
|
|
715
715
|
sourceToolCallId: input.sourceToolCallId,
|
|
716
716
|
...(input.visibility === undefined ? {} : { visibility: input.visibility }),
|
|
717
717
|
cwd: input.cwd,
|
|
718
|
-
command:
|
|
718
|
+
command: input.command,
|
|
719
719
|
status: 'starting',
|
|
720
720
|
startedAt,
|
|
721
721
|
updatedAt: startedAt,
|
|
@@ -43,7 +43,7 @@ export function terminalContent(record) {
|
|
|
43
43
|
status: terminalResultStatus(record.status),
|
|
44
44
|
...(record.exitCode !== undefined ? { exitCode: record.exitCode } : {}),
|
|
45
45
|
...(record.failureMessage !== undefined ? { failureMessage: record.failureMessage } : {}),
|
|
46
|
-
output:
|
|
46
|
+
output: record.output,
|
|
47
47
|
...(sandboxDenialForRecord(record) ? { sandboxDenial: sandboxDenialForRecord(record) } : {}),
|
|
48
48
|
};
|
|
49
49
|
}
|