maka-agent 0.2.0-dev.23.20260906 → 0.2.0-dev.25.20260908
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/acp/maka-acp-agent.js +2 -1
- package/dist/acp/session-configuration.js +143 -0
- package/dist/acp/session-registry.js +90 -4
- package/dist/cli-core.js +2 -0
- package/dist/pi-transcript-tools.js +6 -0
- package/dist/pi-transcript.js +5 -12
- package/dist/pi-tui-layout.js +56 -10
- package/dist/pi-tui-pickers.js +102 -1
- package/dist/pi-tui-runner.js +230 -46
- package/dist/pi-tui-todo.js +221 -0
- package/dist/pi-tui-transcript-viewer.js +134 -7
- package/dist/runtime-host-cli-context.js +224 -78
- package/dist/runtime-host-cli-installation.js +8 -2
- package/dist/runtime-host-cli.js +31 -1
- package/dist/runtime-host-handoff-surface.js +106 -0
- package/dist/runtime-host-installed-update-bootstrap.js +13 -0
- package/dist/runtime-host-installed-update-coordinator.js +33 -0
- package/dist/runtime-host-lifecycle-transaction.js +9 -1
- package/dist/runtime-host-local-handoff.js +48 -5
- package/dist/runtime-host-local-managed-activation.js +84 -0
- package/dist/runtime-host-local-source-retirement.js +18 -2
- package/dist/runtime-host-managed-lifecycle-manager.js +1 -0
- package/dist/runtime-host-operator-retirement.js +50 -0
- package/dist/runtime-host-service-manager.js +3 -3
- package/dist/runtime-host-session-channel.js +13 -0
- package/dist/runtime-host-session-driver.js +46 -26
- package/dist/runtime-host-session-update.js +62 -0
- package/dist/runtime-host-tui-command.js +38 -73
- package/dist/runtime-host-tui-context.js +1 -0
- package/dist/runtime-host-tui-owner.js +226 -0
- package/dist/tui-copy-catalog.js +219 -6
- package/dist/tui-host-owner-copy.js +24 -0
- 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/canonical-runtime-event.js +3 -1
- 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-failure.js +40 -0
- package/node_modules/@maka/core/dist/model-metadata.generated.js +4 -4
- package/node_modules/@maka/core/dist/model-metadata.js +7 -3
- package/node_modules/@maka/core/dist/model-web-search.js +5 -4
- package/node_modules/@maka/core/dist/provider-registry.js +45 -4
- package/node_modules/@maka/core/dist/record-schema.js +9 -2
- 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-boundary.js +31 -11
- package/node_modules/@maka/core/dist/runtime-event.js +37 -6
- package/node_modules/@maka/core/dist/runtime-handoff.js +98 -0
- package/node_modules/@maka/core/dist/runtime-invocation.js +1 -1
- package/node_modules/@maka/core/dist/runtime-logical-execution.js +112 -0
- package/node_modules/@maka/core/dist/session.js +84 -56
- package/node_modules/@maka/core/dist/slash-command-catalog.js +3 -0
- package/node_modules/@maka/core/dist/tool-result-archive-evidence.js +20 -0
- package/node_modules/@maka/core/dist/tool-result-record-schema.js +2 -1
- package/node_modules/@maka/core/dist/usage-record-schema.js +26 -35
- package/node_modules/@maka/core/package.json +5 -0
- package/node_modules/@maka/eval/dist/experiment-directory.js +4 -13
- package/node_modules/@maka/mcp/dist/index.js +131 -1
- package/node_modules/@maka/runtime/dist/agent-run-inspect.js +0 -13
- package/node_modules/@maka/runtime/dist/agent-run.js +351 -105
- package/node_modules/@maka/runtime/dist/ai-sdk-backend.js +29 -13
- package/node_modules/@maka/runtime/dist/ai-sdk-compaction.js +109 -34
- package/node_modules/@maka/runtime/dist/ai-sdk-turn.js +184 -183
- 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/context-budget.js +14 -9
- package/node_modules/@maka/runtime/dist/conversation-copy.js +158 -15
- package/node_modules/@maka/runtime/dist/github-copilot-oauth-enrollment.js +3 -3
- package/node_modules/@maka/runtime/dist/goal-continuation.js +36 -4
- package/node_modules/@maka/runtime/dist/history-compact-checkpoint.js +18 -9
- package/node_modules/@maka/runtime/dist/history-compact-summarizer.js +30 -22
- package/node_modules/@maka/runtime/dist/history-compaction.js +29 -4
- package/node_modules/@maka/runtime/dist/ledger-tool-result-archive-reader.js +174 -0
- package/node_modules/@maka/runtime/dist/mcp-tools.js +7 -2
- package/node_modules/@maka/runtime/dist/message-authority.js +9 -0
- package/node_modules/@maka/runtime/dist/model-adapter.js +19 -98
- package/node_modules/@maka/runtime/dist/model-factory.js +19 -81
- package/node_modules/@maka/runtime/dist/model-fetcher.js +49 -2
- package/node_modules/@maka/runtime/dist/model-history.js +0 -112
- package/node_modules/@maka/runtime/dist/model-runtime.js +85 -111
- package/node_modules/@maka/runtime/dist/native-web-search-tool.js +2 -1
- package/node_modules/@maka/runtime/dist/openai-codex-history-compactor.js +2 -2
- package/node_modules/@maka/runtime/dist/opencode-session-header.js +4 -2
- 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-error-classification.js +84 -123
- package/node_modules/@maka/runtime/dist/provider-request-telemetry.js +76 -109
- package/node_modules/@maka/runtime/dist/request-shape.js +23 -0
- package/node_modules/@maka/runtime/dist/run-handoff-gate.js +97 -0
- package/node_modules/@maka/runtime/dist/runtime-event-backfill.js +83 -55
- package/node_modules/@maka/runtime/dist/runtime-event-read-model.js +121 -159
- package/node_modules/@maka/runtime/dist/runtime-kernel.js +157 -112
- package/node_modules/@maka/runtime/dist/runtime-ledger-repair.js +160 -79
- package/node_modules/@maka/runtime/dist/runtime-read-model.js +30 -89
- package/node_modules/@maka/runtime/dist/runtime-resume.js +80 -4
- package/node_modules/@maka/runtime/dist/session-event-runtime-mapper.js +5 -0
- package/node_modules/@maka/runtime/dist/session-manager.js +171 -288
- package/node_modules/@maka/runtime/dist/session-projection-helpers.js +0 -27
- 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/subscription-model-fetch.js +3 -4
- package/node_modules/@maka/runtime/dist/test-connection.js +16 -17
- 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-encoding.js +38 -0
- 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/dist/tool-runtime.js +3 -61
- package/node_modules/@maka/runtime/package.json +2 -0
- package/node_modules/@maka/runtime-host/dist/adapter/session-projector.js +35 -0
- package/node_modules/@maka/runtime-host/dist/client/connect-or-spawn.js +9 -1
- package/node_modules/@maka/runtime-host/dist/client/connection.js +3 -0
- package/node_modules/@maka/runtime-host/dist/client/host-handoff-copy.js +179 -0
- package/node_modules/@maka/runtime-host/dist/client/host-handoff.js +275 -0
- package/node_modules/@maka/runtime-host/dist/client/host-retirement.js +26 -5
- package/node_modules/@maka/runtime-host/dist/client/index.js +2 -0
- package/node_modules/@maka/runtime-host/dist/client/launcher.js +3 -0
- package/node_modules/@maka/runtime-host/dist/client/remote-compatibility-error.js +2 -0
- package/node_modules/@maka/runtime-host/dist/client/session-subscription.js +46 -5
- 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/index.js +2 -1
- package/node_modules/@maka/runtime-host/dist/operator/managed-deployment.js +1 -3
- package/node_modules/@maka/runtime-host/dist/operator/retirement-cancellation.js +20 -0
- 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/host-status.js +21 -12
- package/node_modules/@maka/runtime-host/dist/protocol/index.js +29 -1
- package/node_modules/@maka/runtime-host/dist/protocol/operations.js +1 -0
- 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 +40 -20
- package/node_modules/@maka/runtime-host/dist/protocol/session-transcript.js +0 -5
- package/node_modules/@maka/runtime-host/dist/protocol/session-turns.js +29 -58
- package/node_modules/@maka/runtime-host/dist/protocol/turn.js +11 -1
- package/node_modules/@maka/runtime-host/dist/protocol/workhub-coordination.js +31 -2
- package/node_modules/@maka/runtime-host/dist/server/access-credential-store.js +1 -0
- package/node_modules/@maka/runtime-host/dist/server/agent-graph-coordinator.js +0 -3
- package/node_modules/@maka/runtime-host/dist/server/canonical-turn-snapshot.js +19 -4
- package/node_modules/@maka/runtime-host/dist/server/connection-session.js +7 -6
- package/node_modules/@maka/runtime-host/dist/server/execution-artifacts.js +32 -32
- package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +144 -33
- package/node_modules/@maka/runtime-host/dist/server/execution-model-authority.js +5 -5
- package/node_modules/@maka/runtime-host/dist/server/execution-model-composition.js +45 -16
- package/node_modules/@maka/runtime-host/dist/server/goal-coordinator.js +40 -1
- package/node_modules/@maka/runtime-host/dist/server/host-kernel.js +96 -17
- package/node_modules/@maka/runtime-host/dist/server/host-residency-registry.js +13 -7
- package/node_modules/@maka/runtime-host/dist/server/hosted-execution-admission-registry.js +3 -1
- package/node_modules/@maka/runtime-host/dist/server/hosted-execution-recovery.js +124 -62
- package/node_modules/@maka/runtime-host/dist/server/interactive-run-composer.js +47 -22
- package/node_modules/@maka/runtime-host/dist/server/message-coordinator.js +76 -6
- 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 +325 -73
- package/node_modules/@maka/runtime-host/dist/server/scheduled-task-coordinator.js +37 -2
- package/node_modules/@maka/runtime-host/dist/server/serial-outbound-writer.js +45 -3
- package/node_modules/@maka/runtime-host/dist/server/session-catalog-coordinator.js +50 -7
- package/node_modules/@maka/runtime-host/dist/server/session-continuity-coordinator.js +87 -25
- 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 +12 -55
- package/node_modules/@maka/runtime-host/dist/server/session-sidecar-purge.js +1 -16
- package/node_modules/@maka/runtime-host/dist/server/session-transcript-pager.js +0 -1
- package/node_modules/@maka/runtime-host/dist/server/session-transcript-reader.js +460 -70
- package/node_modules/@maka/runtime-host/dist/server/shared-session-transcript.js +1 -1
- package/node_modules/@maka/runtime-host/dist/server/storage-maintenance.js +109 -0
- package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-action-gate.js +20 -2
- package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-coordinator.js +13 -4
- package/node_modules/@maka/runtime-host/dist/server/workhub-message-attachments.js +46 -0
- package/node_modules/@maka/storage/dist/artifact-store.js +21 -10
- package/node_modules/@maka/storage/dist/artifact-stores.js +1 -1
- package/node_modules/@maka/storage/dist/claude-code-session-adapter.js +0 -5
- package/node_modules/@maka/storage/dist/codex-session-adapter.js +284 -198
- package/node_modules/@maka/storage/dist/context-offload-snapshot.js +325 -0
- package/node_modules/@maka/storage/dist/execution-stores.js +9 -7
- package/node_modules/@maka/storage/dist/file-session-repository.js +1012 -0
- 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/opencode-session-adapter.js +0 -4
- package/node_modules/@maka/storage/dist/operational-state-backup.js +9 -5
- 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-event-persistence.js +1 -0
- package/node_modules/@maka/storage/dist/runtime-policy/connection-catalog-document.js +8 -3
- package/node_modules/@maka/storage/dist/runtime-transcript-query.js +308 -0
- 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 +26 -5
- package/node_modules/@maka/storage/dist/session-copy-cleanup.js +2 -1
- package/node_modules/@maka/storage/dist/session-message-projection.js +15 -0
- package/node_modules/@maka/storage/dist/session-repository.js +767 -0
- package/node_modules/@maka/storage/dist/session-store.js +25 -99
- package/node_modules/@maka/storage/dist/sqlite-artifact-metadata.js +10 -3
- package/node_modules/@maka/storage/dist/sqlite-context-offload-store.js +24 -8
- package/node_modules/@maka/storage/dist/sqlite-core-execution-schema.js +7 -1
- package/node_modules/@maka/storage/dist/sqlite-runtime-schema.js +44 -1
- package/node_modules/@maka/storage/dist/sqlite-runtime-store.js +130 -27
- package/node_modules/@maka/storage/dist/sqlite-session-metadata-store.js +109 -892
- package/node_modules/@maka/storage/dist/storage-id.js +28 -0
- package/node_modules/@maka/storage/dist/tool-result-archive-evidence.js +138 -0
- 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/node_modules/@maka/storage/package.json +2 -0
- package/package.json +1 -1
|
@@ -16,8 +16,9 @@
|
|
|
16
16
|
* specific language governing permissions and limitations
|
|
17
17
|
* under the License.
|
|
18
18
|
*/
|
|
19
|
-
import { Key, matchesKey, truncateToWidth, visibleWidth, } from '@earendil-works/pi-tui';
|
|
20
|
-
import { ansi } from './tui-ansi.js';
|
|
19
|
+
import { Key, Input, isKeyRelease, isKeyRepeat, matchesKey, truncateToWidth, visibleWidth, } from '@earendil-works/pi-tui';
|
|
20
|
+
import { ansi, stripAnsi } from './tui-ansi.js';
|
|
21
|
+
import { TUI_COPY_RESOURCES } from './tui-copy-catalog.js';
|
|
21
22
|
const VIEWER_CHROME_ROWS = 2;
|
|
22
23
|
/**
|
|
23
24
|
* Full-screen, read-only navigation over the CLI transcript projection.
|
|
@@ -28,19 +29,100 @@ const VIEWER_CHROME_ROWS = 2;
|
|
|
28
29
|
*/
|
|
29
30
|
export class TranscriptViewerOverlay {
|
|
30
31
|
input;
|
|
32
|
+
focused = false;
|
|
31
33
|
top = 0;
|
|
32
34
|
documentRows = 0;
|
|
33
35
|
bodyRows = 0;
|
|
34
36
|
followsEnd = true;
|
|
37
|
+
document = { lines: [], anchors: [] };
|
|
38
|
+
expanded = true;
|
|
39
|
+
anchor;
|
|
40
|
+
search = new Input();
|
|
41
|
+
searching = false;
|
|
42
|
+
query = '';
|
|
43
|
+
matches = [];
|
|
44
|
+
searchOrigin;
|
|
45
|
+
matchedLine;
|
|
35
46
|
constructor(input) {
|
|
36
47
|
this.input = input;
|
|
37
48
|
}
|
|
38
49
|
invalidate() { }
|
|
39
50
|
handleInput(data) {
|
|
51
|
+
if (isKeyRelease(data))
|
|
52
|
+
return;
|
|
53
|
+
if (matchesKey(data, Key.ctrl('o'))) {
|
|
54
|
+
if (!isKeyRepeat(data))
|
|
55
|
+
this.input.onClose();
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (this.searching) {
|
|
59
|
+
if (matchesKey(data, Key.escape)) {
|
|
60
|
+
this.searching = false;
|
|
61
|
+
this.query = '';
|
|
62
|
+
this.matches = [];
|
|
63
|
+
if (this.searchOrigin)
|
|
64
|
+
Object.assign(this, this.searchOrigin);
|
|
65
|
+
this.input.onChange();
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (matchesKey(data, Key.enter)) {
|
|
69
|
+
this.searching = false;
|
|
70
|
+
this.input.onChange();
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (matchesKey(data, Key.up) || matchesKey(data, Key.down)) {
|
|
74
|
+
this.nextMatch(matchesKey(data, Key.up) ? -1 : 1);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
this.search.handleInput(data);
|
|
78
|
+
const query = this.search.getValue().trim().toLocaleLowerCase();
|
|
79
|
+
if (query !== this.query) {
|
|
80
|
+
this.query = query;
|
|
81
|
+
this.findMatches();
|
|
82
|
+
const target = this.matches.find((line) => line >= (this.searchOrigin?.top ?? 0)) ?? this.matches[0];
|
|
83
|
+
if (target !== undefined)
|
|
84
|
+
this.goToMatch(target);
|
|
85
|
+
}
|
|
86
|
+
this.input.onChange();
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
if (matchesKey(data, Key.escape) && this.query) {
|
|
90
|
+
this.query = '';
|
|
91
|
+
this.matches = [];
|
|
92
|
+
if (this.searchOrigin)
|
|
93
|
+
Object.assign(this, this.searchOrigin);
|
|
94
|
+
this.input.onChange();
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
40
97
|
if (matchesKey(data, Key.escape) || matchesKey(data, 'q')) {
|
|
41
98
|
this.input.onClose();
|
|
42
99
|
return;
|
|
43
100
|
}
|
|
101
|
+
if (matchesKey(data, '/')) {
|
|
102
|
+
this.searchOrigin = {
|
|
103
|
+
top: this.top,
|
|
104
|
+
followsEnd: this.followsEnd,
|
|
105
|
+
anchor: this.anchor ? { ...this.anchor } : undefined,
|
|
106
|
+
};
|
|
107
|
+
this.search.setValue(this.query);
|
|
108
|
+
this.searching = true;
|
|
109
|
+
this.input.onChange();
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (this.query && (matchesKey(data, 'n') || matchesKey(data, Key.shift('n')))) {
|
|
113
|
+
this.nextMatch(matchesKey(data, Key.shift('n')) ? -1 : 1);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (matchesKey(data, Key.ctrl('e'))) {
|
|
117
|
+
if (!isKeyRepeat(data)) {
|
|
118
|
+
this.expanded = !this.expanded;
|
|
119
|
+
// A detail that disappears on collapse returns to its own heading.
|
|
120
|
+
if (!this.expanded && this.anchor)
|
|
121
|
+
this.anchor.offset = 0;
|
|
122
|
+
this.input.onChange();
|
|
123
|
+
}
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
44
126
|
if (matchesKey(data, Key.up)) {
|
|
45
127
|
this.scrollBy(-1);
|
|
46
128
|
return;
|
|
@@ -60,12 +142,14 @@ export class TranscriptViewerOverlay {
|
|
|
60
142
|
if (matchesKey(data, Key.home)) {
|
|
61
143
|
this.followsEnd = false;
|
|
62
144
|
this.top = 0;
|
|
145
|
+
this.captureAnchor();
|
|
63
146
|
this.input.onChange();
|
|
64
147
|
return;
|
|
65
148
|
}
|
|
66
149
|
if (matchesKey(data, Key.end)) {
|
|
67
150
|
this.followsEnd = true;
|
|
68
151
|
this.top = this.maxTop();
|
|
152
|
+
this.captureAnchor();
|
|
69
153
|
this.input.onChange();
|
|
70
154
|
}
|
|
71
155
|
}
|
|
@@ -76,31 +160,74 @@ export class TranscriptViewerOverlay {
|
|
|
76
160
|
// navigation chrome only. The footer appears once header + body + footer fit.
|
|
77
161
|
const showFooter = viewportRows > 2;
|
|
78
162
|
this.bodyRows = Math.max(0, viewportRows - (showFooter ? VIEWER_CHROME_ROWS : 1));
|
|
79
|
-
|
|
163
|
+
this.document = this.input.renderTranscript(safeWidth, this.expanded);
|
|
164
|
+
const document = this.document.lines;
|
|
80
165
|
this.documentRows = document.length;
|
|
166
|
+
if (!this.followsEnd && this.anchor) {
|
|
167
|
+
const index = this.document.anchors.findIndex((entry) => entry.id === this.anchor.id);
|
|
168
|
+
if (index >= 0) {
|
|
169
|
+
const entry = this.document.anchors[index];
|
|
170
|
+
const end = this.document.anchors[index + 1]?.line ?? document.length;
|
|
171
|
+
this.top = entry.line + Math.min(this.anchor.offset, Math.max(0, end - entry.line - 1));
|
|
172
|
+
}
|
|
173
|
+
}
|
|
81
174
|
const maxTop = this.maxTop();
|
|
82
175
|
this.top = this.followsEnd ? maxTop : clamp(this.top, 0, maxTop);
|
|
83
|
-
this.
|
|
176
|
+
this.captureAnchor();
|
|
177
|
+
this.findMatches();
|
|
84
178
|
const visible = document.slice(this.top, this.top + this.bodyRows);
|
|
85
179
|
const start = visible.length === 0 ? 0 : this.top + 1;
|
|
86
180
|
const end = visible.length === 0 ? 0 : this.top + visible.length;
|
|
87
|
-
const
|
|
181
|
+
const copy = TUI_COPY_RESOURCES['transcript-reader'][this.input.locale ?? 'en'];
|
|
182
|
+
const header = padLine(`${ansi.bold(copy.title)} ${ansi.dim(`${start}-${end}/${document.length} · ${copy.scope}`)}`, safeWidth);
|
|
183
|
+
const matchingLines = new Set(this.matches);
|
|
88
184
|
const body = [
|
|
89
|
-
...visible.map((line) => padLine(line, safeWidth)),
|
|
185
|
+
...visible.map((line, index) => padLine(matchingLines.has(this.top + index) ? ansi.reverse(stripAnsi(line)) : line, safeWidth)),
|
|
90
186
|
...Array.from({ length: Math.max(0, this.bodyRows - visible.length) }, () => ' '.repeat(safeWidth)),
|
|
91
187
|
];
|
|
92
188
|
if (!showFooter)
|
|
93
189
|
return [header, ...body];
|
|
94
|
-
|
|
190
|
+
this.search.focused = this.focused && this.searching;
|
|
191
|
+
const footer = padLine(this.searching
|
|
192
|
+
? `/ ${this.search.render(Math.max(1, safeWidth - 3))[0] ?? ''}`
|
|
193
|
+
: ansi.dim(this.query
|
|
194
|
+
? `${this.matches.length} ${copy.matches} · n/N · Esc ${copy.back}`
|
|
195
|
+
: copy.hint), safeWidth);
|
|
95
196
|
return [header, ...body, footer];
|
|
96
197
|
}
|
|
97
198
|
scrollBy(delta) {
|
|
199
|
+
this.matchedLine = undefined;
|
|
98
200
|
const maxTop = this.maxTop();
|
|
99
201
|
this.top = clamp(this.top + delta, 0, maxTop);
|
|
100
202
|
// Follow the tail whenever the clamped position is the end, including the
|
|
101
203
|
// no-op case where a short transcript cannot move at all: a stray Up key
|
|
102
204
|
// must not pin the viewer at the head once the transcript grows.
|
|
103
205
|
this.followsEnd = this.top === maxTop;
|
|
206
|
+
this.captureAnchor();
|
|
207
|
+
this.input.onChange();
|
|
208
|
+
}
|
|
209
|
+
captureAnchor() {
|
|
210
|
+
const entry = [...this.document.anchors].reverse().find((entry) => entry.line <= this.top);
|
|
211
|
+
this.anchor = entry ? { id: entry.id, offset: this.top - entry.line } : undefined;
|
|
212
|
+
}
|
|
213
|
+
findMatches() {
|
|
214
|
+
this.matches = this.query
|
|
215
|
+
? this.document.lines.flatMap((line, index) => stripAnsi(line).toLocaleLowerCase().includes(this.query) ? [index] : [])
|
|
216
|
+
: [];
|
|
217
|
+
}
|
|
218
|
+
goToMatch(line) {
|
|
219
|
+
this.matchedLine = line;
|
|
220
|
+
this.top = clamp(line, 0, this.maxTop());
|
|
221
|
+
this.followsEnd = false;
|
|
222
|
+
this.captureAnchor();
|
|
223
|
+
}
|
|
224
|
+
nextMatch(direction) {
|
|
225
|
+
const current = this.matchedLine ?? this.top;
|
|
226
|
+
const line = direction > 0
|
|
227
|
+
? (this.matches.find((line) => line > current) ?? this.matches[0])
|
|
228
|
+
: ([...this.matches].reverse().find((line) => line < current) ?? this.matches.at(-1));
|
|
229
|
+
if (line !== undefined)
|
|
230
|
+
this.goToMatch(line);
|
|
104
231
|
this.input.onChange();
|
|
105
232
|
}
|
|
106
233
|
maxTop() {
|
|
@@ -16,13 +16,16 @@
|
|
|
16
16
|
* specific language governing permissions and limitations
|
|
17
17
|
* under the License.
|
|
18
18
|
*/
|
|
19
|
+
import { activateLocalManagedRuntimeHost } from './runtime-host-local-managed-activation.js';
|
|
19
20
|
import { randomUUID } from 'node:crypto';
|
|
20
21
|
import { join } from 'node:path';
|
|
21
22
|
import { NO_REAL_CONNECTION_CODE } from '@maka/core/connection-error-copy';
|
|
22
|
-
import { connectOrSpawnRuntimeHost, connectRuntimeHostProfile, createClientRuntimeHostProfileCatalog, createRuntimeHostPeerClientFromEnvironment, createRuntimeHostReconnectingConnection, loadOrCreateRuntimeHostClientInstanceId, LOCAL_RUNTIME_HOST_PROFILE, readRuntimeHostConnectionCatalog, RuntimeHostPermanentReconnectError, runtimeHostStartupError, } from '@maka/runtime-host/client';
|
|
23
|
-
import { INTERACTIVE_RUNTIME_HOST_COMPOSITION_ID,
|
|
24
|
-
import { readLocalHostDeploymentRecord } from '@maka/runtime-host/operator';
|
|
23
|
+
import { connectOrSpawnRuntimeHost, forceTerminateObservedRegisteredRuntimeHost, connectRuntimeHost, connectRuntimeHostProfile, createClientRuntimeHostProfileCatalog, createRuntimeHostPeerClientFromEnvironment, createRuntimeHostReconnectingConnection, loadOrCreateRuntimeHostClientInstanceId, LOCAL_RUNTIME_HOST_PROFILE, readRuntimeHostConnectionCatalog, RuntimeHostPermanentReconnectError, RuntimeHostRemoteCompatibilityError, runHostHandoff, runtimeHostStartupError, } from '@maka/runtime-host/client';
|
|
24
|
+
import { INTERACTIVE_RUNTIME_HOST_COMPOSITION_ID, RUNTIME_HOST_PROTOCOL_VERSION, RUNTIME_HOST_COMPATIBILITY_EPOCH, } from '@maka/runtime-host/protocol';
|
|
25
|
+
import { readLocalHostDeploymentRecord, resolveRuntimeHostManagedDeploymentAuthority, } from '@maka/runtime-host/operator';
|
|
25
26
|
import { resolveMakaClientDataRoot } from '@maka/storage/workspace-root';
|
|
27
|
+
import { isTemporaryNpxInstallation, resolveRuntimeHostNpmGlobalInstallation, } from './runtime-host-cli-installation.js';
|
|
28
|
+
import { restartRuntimeHostNpmGlobalDeployment, runtimeHostNpmGlobalSourceRetirementAvailable, } from './runtime-host-local-handoff.js';
|
|
26
29
|
/**
|
|
27
30
|
* The mode a new Session starts in belongs to the Host: `session.create`
|
|
28
31
|
* falls back to `chatDefaults.permissionMode` in the Runtime Policy whenever a
|
|
@@ -42,17 +45,6 @@ import { resolveMakaClientDataRoot } from '@maka/storage/workspace-root';
|
|
|
42
45
|
export async function readHostChatDefaultPermissionMode(connection) {
|
|
43
46
|
return (await connection.request('runtime.policy.query', {})).policy.chatDefaults.permissionMode;
|
|
44
47
|
}
|
|
45
|
-
export class RuntimeHostCliConflictError extends RuntimeHostPermanentReconnectError {
|
|
46
|
-
handshake;
|
|
47
|
-
registration;
|
|
48
|
-
code = 'RUNTIME_HOST_RESTART_REQUIRED';
|
|
49
|
-
constructor(handshake, registration) {
|
|
50
|
-
super(formatRuntimeHostCliConflict(handshake, registration));
|
|
51
|
-
this.handshake = handshake;
|
|
52
|
-
this.registration = registration;
|
|
53
|
-
this.name = 'RuntimeHostCliConflictError';
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
48
|
export async function connectRuntimeHostCli(input, overrides = {}) {
|
|
57
49
|
const context = await connectRuntimeHostCliConnection(input, overrides);
|
|
58
50
|
try {
|
|
@@ -67,12 +59,20 @@ export async function connectRuntimeHostCli(input, overrides = {}) {
|
|
|
67
59
|
export async function connectRuntimeHostCliConnection(input, overrides = {}) {
|
|
68
60
|
const deps = {
|
|
69
61
|
connectOrSpawn: connectOrSpawnRuntimeHost,
|
|
62
|
+
activateLocalManagedHost: activateLocalManagedRuntimeHost,
|
|
63
|
+
connectActivatedHost: connectRuntimeHost,
|
|
70
64
|
connectProfile: connectRuntimeHostProfile,
|
|
71
65
|
readConnectionCatalog: readRuntimeHostConnectionCatalog,
|
|
72
66
|
loadClientInstanceId: loadOrCreateRuntimeHostClientInstanceId,
|
|
73
67
|
executionCandidateEntrypoint: new URL(import.meta.resolve('@maka/runtime-host/execution-candidate-main')),
|
|
74
68
|
readDeploymentRecord: readLocalHostDeploymentRecord,
|
|
69
|
+
resolveManagedAuthority: resolveRuntimeHostManagedDeploymentAuthority,
|
|
75
70
|
createPeerClient: createRuntimeHostPeerClientFromEnvironment,
|
|
71
|
+
resolveInstallation: resolveRuntimeHostNpmGlobalInstallation,
|
|
72
|
+
isTemporaryNpxInstallation,
|
|
73
|
+
terminateObservedHost: forceTerminateObservedRegisteredRuntimeHost,
|
|
74
|
+
restartDeployment: restartRuntimeHostNpmGlobalDeployment,
|
|
75
|
+
sourceRetirementAvailable: runtimeHostNpmGlobalSourceRetirementAvailable,
|
|
76
76
|
...overrides,
|
|
77
77
|
};
|
|
78
78
|
const resolvedProfile = await resolveHostProfile(input, deps);
|
|
@@ -83,45 +83,227 @@ export async function connectRuntimeHostCliConnection(input, overrides = {}) {
|
|
|
83
83
|
const peerClient = profile.kind === 'remote' && profile.transport.kind === 'libp2p-direct'
|
|
84
84
|
? deps.createPeerClient()
|
|
85
85
|
: undefined;
|
|
86
|
+
// A temporary package is evidence for invocation lifetime, never deployment
|
|
87
|
+
// authority. This only guards candidates we create; using an existing Host
|
|
88
|
+
// leaves that Host's ownership and lifetime unchanged.
|
|
89
|
+
const invocationOwned = profile.kind === 'local' && (await deps.isTemporaryNpxInstallation());
|
|
86
90
|
const connectInput = {
|
|
87
91
|
rootPath: input.rootPath,
|
|
88
92
|
protocol: { min: RUNTIME_HOST_PROTOCOL_VERSION, max: RUNTIME_HOST_PROTOCOL_VERSION },
|
|
89
93
|
clientInstanceId,
|
|
90
94
|
compositionId: INTERACTIVE_RUNTIME_HOST_COMPOSITION_ID,
|
|
91
95
|
candidateEntrypoint: deps.executionCandidateEntrypoint,
|
|
96
|
+
...(invocationOwned ? { closeOnLauncherExit: true } : {}),
|
|
92
97
|
};
|
|
93
98
|
const connect = async (signal, sshInteraction = 'batch') => {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
99
|
+
const observe = async () => {
|
|
100
|
+
if (profile.kind !== 'local') {
|
|
101
|
+
try {
|
|
102
|
+
const connection = await deps.connectProfile({
|
|
103
|
+
profile,
|
|
104
|
+
...(resolvedProfile.credential ? { credential: resolvedProfile.credential } : {}),
|
|
105
|
+
clientInstanceId,
|
|
106
|
+
sshInteraction,
|
|
107
|
+
...(peerClient ? { peerClient } : {}),
|
|
108
|
+
...(signal ? { signal } : {}),
|
|
109
|
+
});
|
|
110
|
+
return { kind: 'ready', value: connection };
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
if (!(error instanceof RuntimeHostRemoteCompatibilityError))
|
|
114
|
+
throw error;
|
|
115
|
+
return {
|
|
116
|
+
kind: 'blocked',
|
|
117
|
+
blocker: {
|
|
118
|
+
identity: JSON.stringify([profile, error.hostEpoch, error.details]),
|
|
119
|
+
target: {
|
|
120
|
+
name: profile.name,
|
|
121
|
+
location: 'remote',
|
|
122
|
+
rootId: profile.rootId,
|
|
123
|
+
hostEpoch: error.hostEpoch,
|
|
124
|
+
},
|
|
125
|
+
reason: 'upgrade',
|
|
126
|
+
mayExitNaturally: false,
|
|
127
|
+
diagnostic: error.message,
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
let connected = await deps.connectOrSpawn({
|
|
133
|
+
...connectInput,
|
|
101
134
|
...(signal ? { signal } : {}),
|
|
102
135
|
});
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
await connected.connection.close().catch(() => undefined);
|
|
121
|
-
throw new RuntimeHostPermanentReconnectError('RUNTIME_HOST_RECOVERY_REQUIRED: The staged local Runtime Host is Ready, but its installation ownership was not durably committed.');
|
|
136
|
+
if (connected.kind === 'failed' && connected.reason === 'managed_root_requires_operator') {
|
|
137
|
+
await deps.activateLocalManagedHost({
|
|
138
|
+
rootPath: input.rootPath,
|
|
139
|
+
...(signal ? { signal } : {}),
|
|
140
|
+
});
|
|
141
|
+
signal?.throwIfAborted();
|
|
142
|
+
// The installed operator owns launch. Compatibility is still projected
|
|
143
|
+
// by the same handoff journey as an already-running managed Host.
|
|
144
|
+
const activated = await deps.connectActivatedHost(connectInput);
|
|
145
|
+
if (activated.kind === 'unavailable' || activated.kind === 'draining') {
|
|
146
|
+
throw new Error(`The installed Runtime Host was activated but the local CLI could not join it (${activated.kind === 'unavailable' ? activated.reason : activated.kind}). Use a compatible CLI or update the managed Host through its configured operator.`);
|
|
147
|
+
}
|
|
148
|
+
if (activated.kind === 'connected' && signal?.aborted) {
|
|
149
|
+
await activated.connection.close();
|
|
150
|
+
signal.throwIfAborted();
|
|
151
|
+
}
|
|
152
|
+
connected = activated;
|
|
122
153
|
}
|
|
123
|
-
|
|
124
|
-
|
|
154
|
+
if (connected.kind === 'incompatible' || connected.kind === 'upgrade_required') {
|
|
155
|
+
const managed = await deps.resolveManagedAuthority(connected.registration.rootId);
|
|
156
|
+
const record = managed
|
|
157
|
+
? undefined
|
|
158
|
+
: await deps.readDeploymentRecord(connected.registration.rootId);
|
|
159
|
+
let replacement;
|
|
160
|
+
let installation;
|
|
161
|
+
let installationFailure;
|
|
162
|
+
// On-demand managed Hosts are also ephemeral processes. Their durable
|
|
163
|
+
// operator authority, not the process lifetime label, decides who may
|
|
164
|
+
// replace them (including when the Host was already running).
|
|
165
|
+
if (!managed && connected.registration.lifecycleMode === 'ephemeral') {
|
|
166
|
+
try {
|
|
167
|
+
installation = await deps.resolveInstallation();
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
installationFailure = error instanceof Error ? error.message : String(error);
|
|
171
|
+
}
|
|
172
|
+
const owner = record?.state.kind === 'handoff' ? record.state.from : record?.state.owner;
|
|
173
|
+
if (installation &&
|
|
174
|
+
(!owner ||
|
|
175
|
+
(owner.kind === installation.owner.kind &&
|
|
176
|
+
owner.installationId === installation.owner.installationId))) {
|
|
177
|
+
const expectedInstallation = installation;
|
|
178
|
+
const canInterrupt = connected.processIdentity !== undefined ||
|
|
179
|
+
(record
|
|
180
|
+
? await deps
|
|
181
|
+
.sourceRetirementAvailable({
|
|
182
|
+
rootId: connected.registration.rootId,
|
|
183
|
+
owner: installation.owner,
|
|
184
|
+
source: record.state.selected,
|
|
185
|
+
})
|
|
186
|
+
.catch(() => false)
|
|
187
|
+
: false);
|
|
188
|
+
replacement = {
|
|
189
|
+
kind: record?.state.kind === 'handoff' ? 'repair' : 'replace',
|
|
190
|
+
canReplaceIdle: true,
|
|
191
|
+
canInterrupt,
|
|
192
|
+
execute: async (activeWorkPolicy, _progress, _consent, attemptSignal) => {
|
|
193
|
+
const result = await deps.restartDeployment({
|
|
194
|
+
rootPath: input.rootPath,
|
|
195
|
+
registration: connected.registration,
|
|
196
|
+
...(connected.processIdentity
|
|
197
|
+
? { processIdentity: connected.processIdentity }
|
|
198
|
+
: {}),
|
|
199
|
+
activeWorkPolicy,
|
|
200
|
+
expectedInstallation,
|
|
201
|
+
...(attemptSignal ? { signal: attemptSignal } : {}),
|
|
202
|
+
});
|
|
203
|
+
if (result.kind === 'completed')
|
|
204
|
+
return { kind: 'completed' };
|
|
205
|
+
if (result.kind === 'active_work')
|
|
206
|
+
return { kind: 'active_work' };
|
|
207
|
+
if (result.kind === 'changed' ||
|
|
208
|
+
result.kind === 'rejected' ||
|
|
209
|
+
result.kind === 'operator_required')
|
|
210
|
+
return { kind: 'changed' };
|
|
211
|
+
return {
|
|
212
|
+
kind: 'recovery_required',
|
|
213
|
+
diagnostic: `Local service recovery is required at ${result.phase}`,
|
|
214
|
+
};
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
// The same observed-process recovery used by Desktop is available to
|
|
220
|
+
// persistent local invocations without a deployment owner. This is an
|
|
221
|
+
// explicit interruption, never an idle inference or an installation claim.
|
|
222
|
+
const processIdentity = connected.processIdentity;
|
|
223
|
+
if (!replacement &&
|
|
224
|
+
!managed &&
|
|
225
|
+
!record &&
|
|
226
|
+
!invocationOwned &&
|
|
227
|
+
connected.registration.lifecycleMode === 'ephemeral' &&
|
|
228
|
+
processIdentity) {
|
|
229
|
+
const registration = connected.registration;
|
|
230
|
+
replacement = {
|
|
231
|
+
kind: 'replace',
|
|
232
|
+
canReplaceIdle: false,
|
|
233
|
+
canInterrupt: true,
|
|
234
|
+
execute: async (policy, progress, consent, attemptSignal) => {
|
|
235
|
+
if (policy !== 'interrupt_active_work' || consent !== 'explicit') {
|
|
236
|
+
return { kind: 'active_work' };
|
|
237
|
+
}
|
|
238
|
+
attemptSignal?.throwIfAborted();
|
|
239
|
+
if ((await deps.resolveManagedAuthority(registration.rootId)) ||
|
|
240
|
+
(await deps.readDeploymentRecord(registration.rootId)))
|
|
241
|
+
return { kind: 'changed' };
|
|
242
|
+
attemptSignal?.throwIfAborted();
|
|
243
|
+
progress('retiring');
|
|
244
|
+
const stopped = await deps.terminateObservedHost({ rootPath: input.rootPath, registration }, { processIdentity, isCurrent: () => !signal?.aborted && !attemptSignal?.aborted });
|
|
245
|
+
if (!stopped)
|
|
246
|
+
return { kind: 'changed' };
|
|
247
|
+
progress('verifying');
|
|
248
|
+
return { kind: 'completed' };
|
|
249
|
+
},
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
return {
|
|
253
|
+
kind: 'blocked',
|
|
254
|
+
blocker: {
|
|
255
|
+
identity: JSON.stringify([
|
|
256
|
+
connected.registration,
|
|
257
|
+
processIdentity,
|
|
258
|
+
managed?.record,
|
|
259
|
+
record,
|
|
260
|
+
installation,
|
|
261
|
+
]),
|
|
262
|
+
target: {
|
|
263
|
+
name: profile.name,
|
|
264
|
+
location: 'local',
|
|
265
|
+
rootId: connected.registration.rootId,
|
|
266
|
+
hostEpoch: connected.registration.hostEpoch,
|
|
267
|
+
},
|
|
268
|
+
reason: record?.state.kind === 'handoff' ? 'repair' : 'upgrade',
|
|
269
|
+
...(!replacement
|
|
270
|
+
? {
|
|
271
|
+
recoveryBlocker: managed || connected.registration.lifecycleMode === 'service'
|
|
272
|
+
? 'managed'
|
|
273
|
+
: record
|
|
274
|
+
? 'owner'
|
|
275
|
+
: invocationOwned
|
|
276
|
+
? 'installation'
|
|
277
|
+
: 'identity',
|
|
278
|
+
diagnostic: [
|
|
279
|
+
`Host compatibility: ${connected.registration.compatibilityEpoch}; client: ${RUNTIME_HOST_COMPATIBILITY_EPOCH}.`,
|
|
280
|
+
installationFailure,
|
|
281
|
+
]
|
|
282
|
+
.filter(Boolean)
|
|
283
|
+
.join('\n'),
|
|
284
|
+
}
|
|
285
|
+
: {}),
|
|
286
|
+
...(connected.handshake?.activity ? { activity: connected.handshake.activity } : {}),
|
|
287
|
+
mayExitNaturally: !managed &&
|
|
288
|
+
connected.registration.lifecycleMode === 'ephemeral' &&
|
|
289
|
+
connected.handshake?.replacement === 'wait_for_idle_exit',
|
|
290
|
+
...(replacement ? { replacement } : {}),
|
|
291
|
+
},
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
if (connected.kind === 'failed') {
|
|
295
|
+
throw runtimeHostStartupError(connected.reason, connected.diagnostic);
|
|
296
|
+
}
|
|
297
|
+
if (connected.registration.generation?.startsWith('npm-global-handoff:')) {
|
|
298
|
+
const record = await deps.readDeploymentRecord(connected.registration.rootId);
|
|
299
|
+
if (record?.state.kind !== 'owned' || record.state.owner.kind !== 'cli') {
|
|
300
|
+
await connected.connection.close().catch(() => undefined);
|
|
301
|
+
throw new RuntimeHostPermanentReconnectError('RUNTIME_HOST_RECOVERY_REQUIRED: The staged local Runtime Host is Ready, but its installation ownership was not durably committed.');
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
return { kind: 'ready', value: connected.connection };
|
|
305
|
+
};
|
|
306
|
+
return runHostHandoff({ observe, signal, openSurface: input.handoffSurface });
|
|
125
307
|
};
|
|
126
308
|
let initialConnection;
|
|
127
309
|
let connection;
|
|
@@ -222,42 +404,6 @@ async function resolveHostProfile(input, deps) {
|
|
|
222
404
|
const catalog = deps.profileCatalog ?? createClientRuntimeHostProfileCatalog(root);
|
|
223
405
|
return catalog.resolve(input.profileId);
|
|
224
406
|
}
|
|
225
|
-
function formatRuntimeHostCliConflict(handshake, registration) {
|
|
226
|
-
const lines = [
|
|
227
|
-
'RUNTIME_HOST_RESTART_REQUIRED: An older Runtime Host is still running and cannot accept this client.',
|
|
228
|
-
`Local Runtime Host: PID ${registration.pid}; lifecycle ${registration.lifecycleMode ?? 'unknown'}; compatibility epoch ${registration.compatibilityEpoch}.`,
|
|
229
|
-
];
|
|
230
|
-
if (registration.lifecycleMode === 'ephemeral') {
|
|
231
|
-
lines.push('The ephemeral Host is not currently idle and cannot be replaced by this Client.');
|
|
232
|
-
}
|
|
233
|
-
else if (registration.lifecycleMode === 'service') {
|
|
234
|
-
lines.push('This service Host is managed by its operator and cannot be replaced by this Client.');
|
|
235
|
-
}
|
|
236
|
-
else {
|
|
237
|
-
lines.push('This Host cannot be replaced by this Client.');
|
|
238
|
-
}
|
|
239
|
-
if (handshake.compatibilityEpoch < RUNTIME_HOST_COMPATIBILITY_EPOCH) {
|
|
240
|
-
lines.push(registration.lifecycleMode === 'service'
|
|
241
|
-
? 'Use the service operator to inspect or upgrade the Host.'
|
|
242
|
-
: 'Use a previous compatible Maka build to inspect the Host and finish or clear any retained work. Stop the Host only after deciding that interruption is safe.');
|
|
243
|
-
}
|
|
244
|
-
else {
|
|
245
|
-
lines.push(`Host protocol ${handshake.protocolMin}-${handshake.protocolMax}; CLI protocol ${RUNTIME_HOST_PROTOCOL_VERSION}.`);
|
|
246
|
-
}
|
|
247
|
-
return lines.join('\n');
|
|
248
|
-
}
|
|
249
|
-
export function shouldRetryRuntimeHostConflict(answer) {
|
|
250
|
-
const normalized = answer.trim().toLowerCase();
|
|
251
|
-
return normalized === 'w' || normalized === 'wait';
|
|
252
|
-
}
|
|
253
|
-
export function resolveRuntimeHostCliConflictDecision(answer, canRestart) {
|
|
254
|
-
const normalized = answer.trim().toLowerCase();
|
|
255
|
-
if (canRestart && (normalized === 'r' || normalized === 'restart'))
|
|
256
|
-
return 'restart';
|
|
257
|
-
if (normalized === 'w' || normalized === 'wait')
|
|
258
|
-
return 'wait';
|
|
259
|
-
return 'cancel';
|
|
260
|
-
}
|
|
261
407
|
export function resolveRuntimeHostCliTarget(catalog, input = {}) {
|
|
262
408
|
const defaultTarget = catalog.defaultTarget;
|
|
263
409
|
const connection = input.connectionSlug
|
|
@@ -76,9 +76,15 @@ export async function resolveRuntimeHostNpmGlobalInstallation(options = {}, over
|
|
|
76
76
|
observedRelease: { version: manifest.version, packageRoot, cliPath },
|
|
77
77
|
};
|
|
78
78
|
}
|
|
79
|
-
export async function isTemporaryNpxInstallation(path, input) {
|
|
79
|
+
export async function isTemporaryNpxInstallation(path = fileURLToPath(new URL('../', import.meta.url)), input = { environment: process.env, homeDir: homedir() }) {
|
|
80
80
|
const canonicalPath = await realpath(path).catch(() => resolve(path));
|
|
81
|
-
const
|
|
81
|
+
const defaultCache = (input.platform ?? process.platform) === 'win32'
|
|
82
|
+
? join(input.environment.LOCALAPPDATA || input.homeDir, 'npm-cache')
|
|
83
|
+
: join(input.homeDir, '.npm');
|
|
84
|
+
const cacheRoots = await Promise.all([
|
|
85
|
+
input.environment.npm_config_cache ?? input.environment.NPM_CONFIG_CACHE,
|
|
86
|
+
defaultCache,
|
|
87
|
+
].flatMap((root) => root ? [realpath(resolve(root, '_npx')).catch(() => resolve(root, '_npx'))] : []));
|
|
82
88
|
return cacheRoots.some((root) => isWithin(root, canonicalPath));
|
|
83
89
|
}
|
|
84
90
|
async function readPackageManifest(url) {
|
package/dist/runtime-host-cli.js
CHANGED
|
@@ -136,6 +136,10 @@ function parseLocalUpdateApply(argv) {
|
|
|
136
136
|
'--target-version',
|
|
137
137
|
'--target-integrity',
|
|
138
138
|
'--target-compatibility',
|
|
139
|
+
'--expected-root-id',
|
|
140
|
+
'--expected-deployment-revision',
|
|
141
|
+
'--expected-owner-installation-id',
|
|
142
|
+
'--expected-host-epoch',
|
|
139
143
|
]);
|
|
140
144
|
for (let index = 0; index < argv.length; index += 1) {
|
|
141
145
|
const argument = argv[index];
|
|
@@ -195,6 +199,28 @@ function parseLocalUpdateApply(argv) {
|
|
|
195
199
|
(!Number.isSafeInteger(targetCompatibility) || targetCompatibility <= 0)) {
|
|
196
200
|
return error('runtime-host local-update-apply compatibility is invalid');
|
|
197
201
|
}
|
|
202
|
+
const expectedValues = [
|
|
203
|
+
'--expected-root-id',
|
|
204
|
+
'--expected-deployment-revision',
|
|
205
|
+
'--expected-owner-installation-id',
|
|
206
|
+
'--expected-host-epoch',
|
|
207
|
+
].map((name) => values.get(name));
|
|
208
|
+
let expectedSource;
|
|
209
|
+
if (expectedValues.some((value) => value !== undefined)) {
|
|
210
|
+
if (!expectedValues.every((value) => value !== undefined && isSafeIdentity(value))) {
|
|
211
|
+
return error('runtime-host local-update-apply requires one complete expected source identity');
|
|
212
|
+
}
|
|
213
|
+
const [rootId, deploymentRevision, ownerInstallationId, hostEpoch] = expectedValues;
|
|
214
|
+
if (!/^[a-f0-9]{64}$/u.test(rootId)) {
|
|
215
|
+
return error('runtime-host local-update-apply expected Root identity is invalid');
|
|
216
|
+
}
|
|
217
|
+
expectedSource = {
|
|
218
|
+
rootId: rootId,
|
|
219
|
+
deploymentRevision: deploymentRevision,
|
|
220
|
+
ownerInstallationId: ownerInstallationId,
|
|
221
|
+
hostEpoch: hostEpoch,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
198
224
|
return {
|
|
199
225
|
kind: 'runtime-host-local-update-apply',
|
|
200
226
|
rootPath,
|
|
@@ -206,6 +232,7 @@ function parseLocalUpdateApply(argv) {
|
|
|
206
232
|
targetIntegrity,
|
|
207
233
|
...(targetCompatibility === undefined ? {} : { targetCompatibility }),
|
|
208
234
|
allowInterruptActiveTasks,
|
|
235
|
+
...(expectedSource ? { expectedSource } : {}),
|
|
209
236
|
};
|
|
210
237
|
}
|
|
211
238
|
function parseLocalUpdateActivate(argv) {
|
|
@@ -553,7 +580,7 @@ function parseServiceManagementCommand(argv) {
|
|
|
553
580
|
},
|
|
554
581
|
}
|
|
555
582
|
: {}),
|
|
556
|
-
...(action === 'update'
|
|
583
|
+
...(action === 'update' || action === 'restart'
|
|
557
584
|
? {
|
|
558
585
|
'--expected-host-json': (value) => {
|
|
559
586
|
if (expectedHost !== undefined)
|
|
@@ -675,10 +702,13 @@ function parseServiceManagementCommand(argv) {
|
|
|
675
702
|
...(allowInterruptActiveTasks ? { allowInterruptActiveTasks: true } : {}),
|
|
676
703
|
};
|
|
677
704
|
}
|
|
705
|
+
if (expectedHost && !options.managedRootId)
|
|
706
|
+
return error('--expected-host-json requires --managed-root-id');
|
|
678
707
|
return {
|
|
679
708
|
kind: 'runtime-host-service-manage',
|
|
680
709
|
action,
|
|
681
710
|
...options,
|
|
711
|
+
...(expectedHost ? { expectedHost } : {}),
|
|
682
712
|
...(clientDataRoot ? { clientDataRoot } : {}),
|
|
683
713
|
...(options.managedRootId ? { managedRootId: options.managedRootId } : {}),
|
|
684
714
|
...(retainManagedDeployment ? { retainManagedDeployment: true } : {}),
|