@modootoday/pmcp 0.15.0 → 0.16.0
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/.agents/plugins/marketplace.json +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +22 -11
- package/dist/cli.js +471 -89
- package/dist/harness-launch-gate.js +0 -3
- package/dist/harness-worker.js +0 -4
- package/dist/http.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/mailbox/index.js +0 -3
- package/dist/stdio.js +1 -3
- package/dist/tui-worker.js +271 -24
- package/docs/terminal-workspace.md +102 -5
- package/gemini-extension.json +1 -1
- package/package.json +1 -1
- package/plugin.json +1 -1
- package/plugins/pmcp/.claude-plugin/plugin.json +1 -1
- package/plugins/pmcp/gemini-extension.json +1 -1
- package/plugins/pmcp/plugin.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -471,8 +471,6 @@ var init_types = __esm({
|
|
|
471
471
|
this.retryable = retryable;
|
|
472
472
|
this.name = "MailboxError";
|
|
473
473
|
}
|
|
474
|
-
code;
|
|
475
|
-
retryable;
|
|
476
474
|
};
|
|
477
475
|
}
|
|
478
476
|
});
|
|
@@ -1837,11 +1835,11 @@ function dockerPolicy(value) {
|
|
|
1837
1835
|
for (const [runtime2, value2] of entries) {
|
|
1838
1836
|
if (!Object.hasOwn(runtimeExecutables, runtime2))
|
|
1839
1837
|
throw new Error("unsupported_docker_runtime");
|
|
1840
|
-
const
|
|
1841
|
-
const executable =
|
|
1842
|
-
if (!isAbsolute10(executable) || posix5.normalize(executable) !== executable ||
|
|
1838
|
+
const command3 = strings2(value2, "docker_runtime_command");
|
|
1839
|
+
const executable = command3[0];
|
|
1840
|
+
if (!isAbsolute10(executable) || posix5.normalize(executable) !== executable || command3.some((argument) => /[\r\n\x1b]/.test(argument)))
|
|
1843
1841
|
throw new Error("invalid_docker_runtime_command");
|
|
1844
|
-
parsed[runtime2] =
|
|
1842
|
+
parsed[runtime2] = command3;
|
|
1845
1843
|
}
|
|
1846
1844
|
return {
|
|
1847
1845
|
schemaVersion: 1,
|
|
@@ -2303,7 +2301,6 @@ var init_connection = __esm({
|
|
|
2303
2301
|
constructor(records2) {
|
|
2304
2302
|
this.records = records2;
|
|
2305
2303
|
}
|
|
2306
|
-
records;
|
|
2307
2304
|
tmux(args, options2 = {}) {
|
|
2308
2305
|
return command(
|
|
2309
2306
|
"tmux",
|
|
@@ -2581,8 +2578,6 @@ var init_journal = __esm({
|
|
|
2581
2578
|
this.id = id2;
|
|
2582
2579
|
runtimeUnit(id2);
|
|
2583
2580
|
}
|
|
2584
|
-
records;
|
|
2585
|
-
id;
|
|
2586
2581
|
path(kind2) {
|
|
2587
2582
|
if (!["intent", "proof", "grant", "committed", "aborted"].includes(kind2))
|
|
2588
2583
|
throw new Error("invalid_launch_artifact");
|
|
@@ -2962,14 +2957,14 @@ function bridgeName(nonce) {
|
|
|
2962
2957
|
function containerEntrypoint(policy, runtime2, nonce, privateProfile) {
|
|
2963
2958
|
const native2 = policy.commands[runtime2];
|
|
2964
2959
|
if (!native2) throw new Error("docker_runtime_command_not_granted");
|
|
2965
|
-
const
|
|
2960
|
+
const command3 = policy.egress?.bridgeExecutable ? [
|
|
2966
2961
|
policy.egress.bridgeExecutable,
|
|
2967
2962
|
`/state/${bridgeName(nonce)}`,
|
|
2968
2963
|
"--",
|
|
2969
2964
|
...native2
|
|
2970
2965
|
] : native2;
|
|
2971
2966
|
const profile = selectedProfile(policy, privateProfile, runtime2);
|
|
2972
|
-
if (!profile) return
|
|
2967
|
+
if (!profile) return command3;
|
|
2973
2968
|
return [
|
|
2974
2969
|
profile.lockExecutable,
|
|
2975
2970
|
"--exclusive",
|
|
@@ -2978,7 +2973,7 @@ function containerEntrypoint(policy, runtime2, nonce, privateProfile) {
|
|
|
2978
2973
|
"--conflict-exit-code",
|
|
2979
2974
|
"73",
|
|
2980
2975
|
`/state/${privateProfileLock}`,
|
|
2981
|
-
...
|
|
2976
|
+
...command3
|
|
2982
2977
|
];
|
|
2983
2978
|
}
|
|
2984
2979
|
var init_entrypoint = __esm({
|
|
@@ -3867,7 +3862,6 @@ var init_backend = __esm({
|
|
|
3867
3862
|
this.runDirectory = recordStore.directory;
|
|
3868
3863
|
this.metadataPath = recordStore.metadataPath;
|
|
3869
3864
|
}
|
|
3870
|
-
recordStore;
|
|
3871
3865
|
connection;
|
|
3872
3866
|
owner;
|
|
3873
3867
|
socket;
|
|
@@ -5254,6 +5248,79 @@ var init_runtime2 = __esm({
|
|
|
5254
5248
|
}
|
|
5255
5249
|
});
|
|
5256
5250
|
|
|
5251
|
+
// src/tui/startup/diagnostics.ts
|
|
5252
|
+
function remediation(tools, userManagerAvailable) {
|
|
5253
|
+
const steps = [];
|
|
5254
|
+
if (tools.platform !== "linux")
|
|
5255
|
+
steps.push(
|
|
5256
|
+
"Use a qualified Linux host for the terminal workspace. Other PMCP CLI features do not require this host profile."
|
|
5257
|
+
);
|
|
5258
|
+
const missing = ["tmux", "flock", "systemctl", "systemdRun"].filter(
|
|
5259
|
+
(name) => !tools[name]
|
|
5260
|
+
);
|
|
5261
|
+
if (missing.length)
|
|
5262
|
+
steps.push(
|
|
5263
|
+
`Install the missing tmux, util-linux or systemd tools for your distribution and add them to PATH: ${missing.join(", ")}.`
|
|
5264
|
+
);
|
|
5265
|
+
if (!tools.nodeSupported)
|
|
5266
|
+
steps.push(
|
|
5267
|
+
"Select Node.js 22 or later through your existing version manager and check node --version in this terminal."
|
|
5268
|
+
);
|
|
5269
|
+
if (tools.supported && !userManagerAvailable)
|
|
5270
|
+
steps.push(
|
|
5271
|
+
"Check systemctl --user status in your login session and restore access to its user manager before launching. Doctor does not start or repair services."
|
|
5272
|
+
);
|
|
5273
|
+
return steps;
|
|
5274
|
+
}
|
|
5275
|
+
function inspectTerminalHost() {
|
|
5276
|
+
const tools = dependencies();
|
|
5277
|
+
let userManagerAvailable = false;
|
|
5278
|
+
let reason;
|
|
5279
|
+
try {
|
|
5280
|
+
if (!tools.supported) throw new Error("tui_dependencies_unavailable");
|
|
5281
|
+
assertNativeHost();
|
|
5282
|
+
userManagerAvailable = true;
|
|
5283
|
+
} catch (error) {
|
|
5284
|
+
reason = error instanceof Error ? error.message : "native_host_unavailable";
|
|
5285
|
+
}
|
|
5286
|
+
const runtimes = Object.entries(runtimeExecutables).map(
|
|
5287
|
+
([id2, executable]) => {
|
|
5288
|
+
const path = locateExecutable(executable);
|
|
5289
|
+
return {
|
|
5290
|
+
id: id2,
|
|
5291
|
+
executable,
|
|
5292
|
+
installed: Boolean(path),
|
|
5293
|
+
...path ? { path } : {},
|
|
5294
|
+
nativeAcceptance: "not-assessed",
|
|
5295
|
+
authentication: "not-inspected"
|
|
5296
|
+
};
|
|
5297
|
+
}
|
|
5298
|
+
);
|
|
5299
|
+
return {
|
|
5300
|
+
schemaVersion: 1,
|
|
5301
|
+
ok: true,
|
|
5302
|
+
...tools,
|
|
5303
|
+
supported: tools.supported && userManagerAvailable,
|
|
5304
|
+
userManagerAvailable,
|
|
5305
|
+
...reason ? { reason } : {},
|
|
5306
|
+
runtimes,
|
|
5307
|
+
qualification: "Prerequisite availability only; native behavior and cgroup delegation require separate qualification.",
|
|
5308
|
+
remediation: remediation(tools, userManagerAvailable),
|
|
5309
|
+
nextCommands: ["pmcp tui plan", "pmcp tui recovery"],
|
|
5310
|
+
providerInvoked: false,
|
|
5311
|
+
authenticationInspected: false
|
|
5312
|
+
};
|
|
5313
|
+
}
|
|
5314
|
+
var init_diagnostics = __esm({
|
|
5315
|
+
"src/tui/startup/diagnostics.ts"() {
|
|
5316
|
+
"use strict";
|
|
5317
|
+
init_runtime2();
|
|
5318
|
+
init_admission2();
|
|
5319
|
+
init_registry();
|
|
5320
|
+
init_executable();
|
|
5321
|
+
}
|
|
5322
|
+
});
|
|
5323
|
+
|
|
5257
5324
|
// src/tui/state/store.ts
|
|
5258
5325
|
import { randomUUID as randomUUID13 } from "crypto";
|
|
5259
5326
|
import {
|
|
@@ -5473,9 +5540,6 @@ var init_connection2 = __esm({
|
|
|
5473
5540
|
this.identity = identity;
|
|
5474
5541
|
this.socket = join49(directory, "s");
|
|
5475
5542
|
}
|
|
5476
|
-
directory;
|
|
5477
|
-
owner;
|
|
5478
|
-
identity;
|
|
5479
5543
|
socket;
|
|
5480
5544
|
raw(args) {
|
|
5481
5545
|
const env = { ...process.env };
|
|
@@ -5592,13 +5656,19 @@ var init_feedback = __esm({
|
|
|
5592
5656
|
init_store3();
|
|
5593
5657
|
init_store2();
|
|
5594
5658
|
hints = {
|
|
5595
|
-
startup_requires_recovery: "
|
|
5659
|
+
startup_requires_recovery: "Run pmcp tui recovery for saved ownership and exact inspection commands. No runtime was restarted.",
|
|
5596
5660
|
startup_group_paused: "The saved group is paused. Resume it explicitly through the harness CLI before reopening.",
|
|
5597
5661
|
startup_main_unavailable: "Inspect the saved main and recovery state. Stop the old group explicitly before using pmcp tui --new.",
|
|
5598
5662
|
startup_busy: "Another workspace launch is running. Wait and retry.",
|
|
5599
5663
|
startup_runtime_conflict: "The saved main uses another runtime. Stop the old group before creating a new workspace.",
|
|
5600
5664
|
workspace_already_running: "Reopen the existing workspace, or stop its exact owned group before using --new.",
|
|
5601
5665
|
runtime_executable_unavailable: "Install the selected native CLI on PATH, or choose an installed runtime with --runtime.",
|
|
5666
|
+
view_client_unavailable: "Open the view before using the worker menu, or run pmcp tui start-worker with --view and --runtime.",
|
|
5667
|
+
runtime_not_granted: "Choose a runtime granted by this owned group. Inspect the group before creating another workspace.",
|
|
5668
|
+
runtime_capacity_exceeded: "Stop an exact owned worker before adding another, or use the main session alone.",
|
|
5669
|
+
aggregate_memory_budget_exceeded: "Use fewer sessions or start a worker with an explicit smaller --memory-mb reservation.",
|
|
5670
|
+
group_not_ready: "Inspect the group and resume a paused group explicitly before adding a worker.",
|
|
5671
|
+
startup_group_not_ready: "Inspect the group and resume a paused group explicitly before adding a worker.",
|
|
5602
5672
|
control_connection_lost: "The native writer or lease disappeared. Inspect and release control before reconnecting.",
|
|
5603
5673
|
control_busy: "Another controller holds the lease. Release it explicitly before retrying.",
|
|
5604
5674
|
native_writer_active: "A native writer is still attached. Detach that writer before retrying.",
|
|
@@ -5619,6 +5689,20 @@ var init_feedback = __esm({
|
|
|
5619
5689
|
}
|
|
5620
5690
|
});
|
|
5621
5691
|
|
|
5692
|
+
// src/tui/presentation/target.ts
|
|
5693
|
+
function targetStatus(view) {
|
|
5694
|
+
const role = view.target === view.mainId ? "MAIN" : "WORKER";
|
|
5695
|
+
const phase2 = view.phase === "read-only" ? "OBSERVE" : phaseLabel(view.phase);
|
|
5696
|
+
const input = view.phase === "controlled" ? "INPUT ON" : "INPUT OFF";
|
|
5697
|
+
return `${role} ${view.target.slice(0, 8)} | ${phase2} | ${input}`;
|
|
5698
|
+
}
|
|
5699
|
+
var init_target = __esm({
|
|
5700
|
+
"src/tui/presentation/target.ts"() {
|
|
5701
|
+
"use strict";
|
|
5702
|
+
init_feedback();
|
|
5703
|
+
}
|
|
5704
|
+
});
|
|
5705
|
+
|
|
5622
5706
|
// src/tui/adapters/tmux/bindings.ts
|
|
5623
5707
|
function callback(view, file2, action, args = []) {
|
|
5624
5708
|
return [
|
|
@@ -5645,7 +5729,8 @@ function bindKeys(connection, view, file2) {
|
|
|
5645
5729
|
["b", "mailbox"],
|
|
5646
5730
|
["d", "detach"],
|
|
5647
5731
|
["!", "dismiss"],
|
|
5648
|
-
["g", "management"]
|
|
5732
|
+
["g", "management"],
|
|
5733
|
+
["n", "worker-menu"]
|
|
5649
5734
|
])
|
|
5650
5735
|
connection.command([
|
|
5651
5736
|
"bind-key",
|
|
@@ -5666,7 +5751,7 @@ function bindKeys(connection, view, file2) {
|
|
|
5666
5751
|
"bind-key",
|
|
5667
5752
|
"?",
|
|
5668
5753
|
"display-message",
|
|
5669
|
-
"m main; w/1-4 worker; c control; r release; h history; b mailbox; d detach; ! dismiss error; double Ctrl-g forwards native Ctrl-g"
|
|
5754
|
+
"m main; n add worker; w/1-4 worker; c control; r release; h history; b mailbox; d detach; ! dismiss error; double Ctrl-g forwards native Ctrl-g"
|
|
5670
5755
|
]);
|
|
5671
5756
|
connection.command([
|
|
5672
5757
|
"set-hook",
|
|
@@ -5694,7 +5779,7 @@ var init_view = __esm({
|
|
|
5694
5779
|
"src/tui/adapters/tmux/view.ts"() {
|
|
5695
5780
|
"use strict";
|
|
5696
5781
|
init_command();
|
|
5697
|
-
|
|
5782
|
+
init_target();
|
|
5698
5783
|
init_connection2();
|
|
5699
5784
|
init_bindings();
|
|
5700
5785
|
TmuxView = class {
|
|
@@ -5707,8 +5792,6 @@ var init_view = __esm({
|
|
|
5707
5792
|
view.serverIdentity
|
|
5708
5793
|
);
|
|
5709
5794
|
}
|
|
5710
|
-
view;
|
|
5711
|
-
stateFile;
|
|
5712
5795
|
connection;
|
|
5713
5796
|
shell(argv) {
|
|
5714
5797
|
return `exec ${argv.map(quote2).join(" ")}`;
|
|
@@ -5880,7 +5963,7 @@ var init_view = __esm({
|
|
|
5880
5963
|
"set-option",
|
|
5881
5964
|
"-g",
|
|
5882
5965
|
"status-right",
|
|
5883
|
-
`${
|
|
5966
|
+
`${targetStatus(view)}${failure2} | Ctrl-g ?`
|
|
5884
5967
|
]);
|
|
5885
5968
|
}
|
|
5886
5969
|
input(pane, enabled) {
|
|
@@ -5903,6 +5986,32 @@ var init_view = __esm({
|
|
|
5903
5986
|
clients() {
|
|
5904
5987
|
return this.connection.command(["list-clients", "-F", "#{client_pid}"]);
|
|
5905
5988
|
}
|
|
5989
|
+
workerMenu(view) {
|
|
5990
|
+
const pane = view.workerPane ?? view.mainPane;
|
|
5991
|
+
this.connection.assertOwned(pane);
|
|
5992
|
+
const popup = [
|
|
5993
|
+
"tmux",
|
|
5994
|
+
"-S",
|
|
5995
|
+
this.connection.socket,
|
|
5996
|
+
"display-popup",
|
|
5997
|
+
"-E",
|
|
5998
|
+
"-t",
|
|
5999
|
+
pane,
|
|
6000
|
+
"-w",
|
|
6001
|
+
"90%",
|
|
6002
|
+
"-h",
|
|
6003
|
+
"80%",
|
|
6004
|
+
this.shell([
|
|
6005
|
+
view.node,
|
|
6006
|
+
view.worker,
|
|
6007
|
+
"worker-menu",
|
|
6008
|
+
"--view",
|
|
6009
|
+
this.stateFile,
|
|
6010
|
+
"--callback"
|
|
6011
|
+
])
|
|
6012
|
+
];
|
|
6013
|
+
this.connection.command(["run-shell", "-b", popup.map(quote2).join(" ")]);
|
|
6014
|
+
}
|
|
5906
6015
|
copy(pane) {
|
|
5907
6016
|
this.connection.assertOwned(pane);
|
|
5908
6017
|
this.connection.command(["copy-mode", "-t", pane]);
|
|
@@ -5926,7 +6035,6 @@ var init_common = __esm({
|
|
|
5926
6035
|
constructor(view) {
|
|
5927
6036
|
this.view = view;
|
|
5928
6037
|
}
|
|
5929
|
-
view;
|
|
5930
6038
|
async call(family, action, input = {}) {
|
|
5931
6039
|
const group = new GroupStore(this.view.groupFile).state.group;
|
|
5932
6040
|
if (group.owner !== this.view.groupOwner) throw new Error("foreign_group");
|
|
@@ -6465,6 +6573,11 @@ var init_operations = __esm({
|
|
|
6465
6573
|
close: closeView,
|
|
6466
6574
|
check: checkControl,
|
|
6467
6575
|
dismiss: ({ view, file: file2 }) => dismissFailure(file2, view),
|
|
6576
|
+
"worker-menu": async (context) => {
|
|
6577
|
+
if (!context.renderer.clients()) throw new Error("view_client_unavailable");
|
|
6578
|
+
await releaseControl(context);
|
|
6579
|
+
context.renderer.workerMenu(context.view);
|
|
6580
|
+
},
|
|
6468
6581
|
management: async (context) => {
|
|
6469
6582
|
await releaseControl(context);
|
|
6470
6583
|
if (context.view.managementWindow) {
|
|
@@ -6488,10 +6601,9 @@ __export(invoke_exports2, {
|
|
|
6488
6601
|
invokeTui: () => invokeTui
|
|
6489
6602
|
});
|
|
6490
6603
|
async function invokeTui(invocation2) {
|
|
6491
|
-
if (
|
|
6604
|
+
if (["launch", "plan", "recovery", "start-worker"].includes(invocation2.action))
|
|
6492
6605
|
throw new Error("startup_requires_cli_context");
|
|
6493
|
-
if (invocation2.action === "doctor")
|
|
6494
|
-
return { schemaVersion: 1, ok: true, ...dependencies() };
|
|
6606
|
+
if (invocation2.action === "doctor") return inspectTerminalHost();
|
|
6495
6607
|
if (invocation2.action === "create") return createView(invocation2.create);
|
|
6496
6608
|
if (invocation2.action === "inspect")
|
|
6497
6609
|
return operate("inspect", invocation2.viewFile);
|
|
@@ -6529,7 +6641,7 @@ function failedInvocation(action, error) {
|
|
|
6529
6641
|
var init_invoke2 = __esm({
|
|
6530
6642
|
"src/tui/application/invoke.ts"() {
|
|
6531
6643
|
"use strict";
|
|
6532
|
-
|
|
6644
|
+
init_diagnostics();
|
|
6533
6645
|
init_lock();
|
|
6534
6646
|
init_create();
|
|
6535
6647
|
init_operations();
|
|
@@ -6538,6 +6650,31 @@ var init_invoke2 = __esm({
|
|
|
6538
6650
|
}
|
|
6539
6651
|
});
|
|
6540
6652
|
|
|
6653
|
+
// src/tui/application/worker-start.ts
|
|
6654
|
+
var worker_start_exports = {};
|
|
6655
|
+
__export(worker_start_exports, {
|
|
6656
|
+
startViewWorker: () => startViewWorker
|
|
6657
|
+
});
|
|
6658
|
+
async function startViewWorker(file2, runtime2, memoryMb) {
|
|
6659
|
+
const { view, common: common2 } = openView(file2);
|
|
6660
|
+
if (view.state !== "open") throw new Error("view_closed");
|
|
6661
|
+
const observed = await common2.snapshot();
|
|
6662
|
+
if (observed.group.state !== "ready") throw new Error("group_not_ready");
|
|
6663
|
+
const main2 = observed.sessions.find(
|
|
6664
|
+
(session) => session.id === view.mainId && session.role === "main"
|
|
6665
|
+
);
|
|
6666
|
+
if (!main2?.alive) throw new Error("startup_main_unavailable");
|
|
6667
|
+
return common2.call("session", "start", {
|
|
6668
|
+
input: { role: "worker", runtime: runtime2, memoryMb: memoryMb ?? main2.memoryMb }
|
|
6669
|
+
});
|
|
6670
|
+
}
|
|
6671
|
+
var init_worker_start = __esm({
|
|
6672
|
+
"src/tui/application/worker-start.ts"() {
|
|
6673
|
+
"use strict";
|
|
6674
|
+
init_context2();
|
|
6675
|
+
}
|
|
6676
|
+
});
|
|
6677
|
+
|
|
6541
6678
|
// src/tui/startup/config.ts
|
|
6542
6679
|
import { realpathSync as realpathSync17 } from "fs";
|
|
6543
6680
|
import { resolve as resolve19 } from "path";
|
|
@@ -6664,6 +6801,160 @@ var init_state = __esm({
|
|
|
6664
6801
|
}
|
|
6665
6802
|
});
|
|
6666
6803
|
|
|
6804
|
+
// src/tui/startup/worker.ts
|
|
6805
|
+
var worker_exports = {};
|
|
6806
|
+
__export(worker_exports, {
|
|
6807
|
+
startWorkspaceWorker: () => startWorkspaceWorker
|
|
6808
|
+
});
|
|
6809
|
+
async function startWorkspaceWorker(request3, runtime2, memoryMb) {
|
|
6810
|
+
if (!Object.hasOwn(runtimeExecutables, runtime2))
|
|
6811
|
+
throw new Error("unsupported_runtime");
|
|
6812
|
+
const settings2 = startupSettings({
|
|
6813
|
+
cwd: request3.cwd,
|
|
6814
|
+
config: request3.config
|
|
6815
|
+
});
|
|
6816
|
+
const state = readStartup(
|
|
6817
|
+
startupFile(settings2.projectRoot),
|
|
6818
|
+
settings2.projectRoot
|
|
6819
|
+
);
|
|
6820
|
+
if (!state || state.phase !== "ready" || !state.groupFile || !state.generation)
|
|
6821
|
+
throw new Error("startup_requires_recovery");
|
|
6822
|
+
const store = new GroupStore(state.groupFile);
|
|
6823
|
+
const group = store.state.group;
|
|
6824
|
+
if (group.projectRoot !== settings2.projectRoot)
|
|
6825
|
+
throw new Error("startup_project_mismatch");
|
|
6826
|
+
if (group.generation !== state.generation)
|
|
6827
|
+
throw new Error("stale_group_generation");
|
|
6828
|
+
if (group.state === "paused") throw new Error("startup_group_paused");
|
|
6829
|
+
if (group.state !== "ready") throw new Error("startup_group_not_ready");
|
|
6830
|
+
if (group.profile === "native" && !locateExecutable(runtimeExecutables[runtime2], request3.cwd))
|
|
6831
|
+
throw new Error("runtime_executable_unavailable");
|
|
6832
|
+
const observed = await invoke({
|
|
6833
|
+
family: "session",
|
|
6834
|
+
action: "list",
|
|
6835
|
+
groupFile: store.path
|
|
6836
|
+
});
|
|
6837
|
+
if (observed.ok !== true) return observed;
|
|
6838
|
+
const sessions = observed.sessions;
|
|
6839
|
+
if (!sessions.some((session) => session.role === "main" && session.alive))
|
|
6840
|
+
throw new Error("startup_main_unavailable");
|
|
6841
|
+
return invoke({
|
|
6842
|
+
family: "session",
|
|
6843
|
+
action: "start",
|
|
6844
|
+
groupFile: store.path,
|
|
6845
|
+
generation: group.generation,
|
|
6846
|
+
input: {
|
|
6847
|
+
runtime: runtime2,
|
|
6848
|
+
role: "worker",
|
|
6849
|
+
memoryMb: memoryMb ?? settings2.sessionMemoryMb
|
|
6850
|
+
}
|
|
6851
|
+
});
|
|
6852
|
+
}
|
|
6853
|
+
var init_worker = __esm({
|
|
6854
|
+
"src/tui/startup/worker.ts"() {
|
|
6855
|
+
"use strict";
|
|
6856
|
+
init_invoke();
|
|
6857
|
+
init_store2();
|
|
6858
|
+
init_registry();
|
|
6859
|
+
init_executable();
|
|
6860
|
+
init_config3();
|
|
6861
|
+
init_state();
|
|
6862
|
+
}
|
|
6863
|
+
});
|
|
6864
|
+
|
|
6865
|
+
// src/tui/startup/recovery.ts
|
|
6866
|
+
var recovery_exports = {};
|
|
6867
|
+
__export(recovery_exports, {
|
|
6868
|
+
inspectStartupRecovery: () => inspectStartupRecovery
|
|
6869
|
+
});
|
|
6870
|
+
function command2(args) {
|
|
6871
|
+
return ["pmcp", ...args].map(quote2).join(" ");
|
|
6872
|
+
}
|
|
6873
|
+
function inspectStartupRecovery(request3) {
|
|
6874
|
+
const settings2 = startupSettings(request3);
|
|
6875
|
+
const checkpoint = startupFile(settings2.projectRoot);
|
|
6876
|
+
const state = readStartup(checkpoint, settings2.projectRoot);
|
|
6877
|
+
const config = settings2.configFile ? ["--config", settings2.configFile] : [];
|
|
6878
|
+
const common2 = {
|
|
6879
|
+
schemaVersion: 1,
|
|
6880
|
+
ok: true,
|
|
6881
|
+
checkpoint,
|
|
6882
|
+
projectRoot: settings2.projectRoot,
|
|
6883
|
+
providerInvoked: false,
|
|
6884
|
+
runtimeRestarted: false,
|
|
6885
|
+
inputReplayed: false,
|
|
6886
|
+
observedNativeProcesses: false
|
|
6887
|
+
};
|
|
6888
|
+
if (!state)
|
|
6889
|
+
return {
|
|
6890
|
+
...common2,
|
|
6891
|
+
status: "not-started",
|
|
6892
|
+
hint: "No saved workspace exists. Start explicitly from an interactive terminal.",
|
|
6893
|
+
commands: [command2(["tui", ...config])]
|
|
6894
|
+
};
|
|
6895
|
+
if (!state.groupFile || !state.generation)
|
|
6896
|
+
return {
|
|
6897
|
+
...common2,
|
|
6898
|
+
status: "manual-inspection",
|
|
6899
|
+
phase: state.phase,
|
|
6900
|
+
hint: "Creation stopped before a group reference was saved. Preserve this checkpoint and inspect owned launch evidence before changing it. No group ownership can be inferred from a matching project path.",
|
|
6901
|
+
commands: []
|
|
6902
|
+
};
|
|
6903
|
+
const store = new GroupStore(state.groupFile);
|
|
6904
|
+
const group = store.state.group;
|
|
6905
|
+
if (group.projectRoot !== settings2.projectRoot)
|
|
6906
|
+
throw new Error("startup_project_mismatch");
|
|
6907
|
+
if (group.generation !== state.generation)
|
|
6908
|
+
throw new Error("stale_group_generation");
|
|
6909
|
+
const target2 = ["--group-file", store.path];
|
|
6910
|
+
const generation = ["--generation", group.generation];
|
|
6911
|
+
const inspect = command2([
|
|
6912
|
+
"harness",
|
|
6913
|
+
"recovery",
|
|
6914
|
+
"inspect",
|
|
6915
|
+
...target2,
|
|
6916
|
+
"--include-starts"
|
|
6917
|
+
]);
|
|
6918
|
+
const status = group.state === "ready" ? state.phase : group.state;
|
|
6919
|
+
const commands = [inspect];
|
|
6920
|
+
let hint = "Inspect actual processes and outstanding starts before any recovery action.";
|
|
6921
|
+
if (group.state === "paused") {
|
|
6922
|
+
hint = "The group is paused. Keep it paused until you explicitly decide to resume it.";
|
|
6923
|
+
commands.push(
|
|
6924
|
+
command2(["harness", "group", "resume", ...target2, ...generation])
|
|
6925
|
+
);
|
|
6926
|
+
}
|
|
6927
|
+
if (group.state === "stopped") {
|
|
6928
|
+
hint = "The saved group is stopped. An explicitly confirmed fresh launch can create a replacement.";
|
|
6929
|
+
commands.push(command2(["tui", "--new", ...config]));
|
|
6930
|
+
}
|
|
6931
|
+
if (group.state === "ready" && !["ready", "view-pending"].includes(state.phase)) {
|
|
6932
|
+
hint = "Startup is incomplete. Inspect pending starts; stop the exact owned group before an explicit fresh launch.";
|
|
6933
|
+
commands.push(
|
|
6934
|
+
command2(["harness", "group", "stop", ...target2, ...generation])
|
|
6935
|
+
);
|
|
6936
|
+
}
|
|
6937
|
+
return {
|
|
6938
|
+
...common2,
|
|
6939
|
+
status,
|
|
6940
|
+
phase: state.phase,
|
|
6941
|
+
groupFile: store.path,
|
|
6942
|
+
generation: group.generation,
|
|
6943
|
+
hint,
|
|
6944
|
+
commands,
|
|
6945
|
+
commandsRequireExplicitAction: true
|
|
6946
|
+
};
|
|
6947
|
+
}
|
|
6948
|
+
var init_recovery2 = __esm({
|
|
6949
|
+
"src/tui/startup/recovery.ts"() {
|
|
6950
|
+
"use strict";
|
|
6951
|
+
init_store2();
|
|
6952
|
+
init_command();
|
|
6953
|
+
init_config3();
|
|
6954
|
+
init_state();
|
|
6955
|
+
}
|
|
6956
|
+
});
|
|
6957
|
+
|
|
6667
6958
|
// src/tui/startup/host.ts
|
|
6668
6959
|
var host_exports = {};
|
|
6669
6960
|
__export(host_exports, {
|
|
@@ -6767,13 +7058,48 @@ var init_lock2 = __esm({
|
|
|
6767
7058
|
}
|
|
6768
7059
|
});
|
|
6769
7060
|
|
|
7061
|
+
// src/tui/presentation/runtime-choice.ts
|
|
7062
|
+
import { createInterface as createInterface2 } from "readline/promises";
|
|
7063
|
+
async function chooseRuntime(prompt, choices, preferred) {
|
|
7064
|
+
if (!choices.length) throw new Error("runtime_executable_unavailable");
|
|
7065
|
+
const fallback = Math.max(choices.indexOf(preferred), 0);
|
|
7066
|
+
process.stderr.write(
|
|
7067
|
+
`${choices.map((runtime2, index) => `${index + 1}. ${runtime2}`).join("\n")}
|
|
7068
|
+
`
|
|
7069
|
+
);
|
|
7070
|
+
while (true) {
|
|
7071
|
+
const answer = (await prompt.question(
|
|
7072
|
+
`Runtime [1-${choices.length}, Enter=${fallback + 1}, q=cancel] `
|
|
7073
|
+
)).trim();
|
|
7074
|
+
if (answer === "q") return void 0;
|
|
7075
|
+
if (answer === "") return choices[fallback];
|
|
7076
|
+
if (!/^\d+$/.test(answer)) continue;
|
|
7077
|
+
const index = Number(answer) - 1;
|
|
7078
|
+
if (Number.isSafeInteger(index) && index >= 0 && index < choices.length)
|
|
7079
|
+
return choices[index];
|
|
7080
|
+
}
|
|
7081
|
+
}
|
|
7082
|
+
async function confirmRuntimeStart(prompt, runtime2) {
|
|
7083
|
+
const answer = await prompt.question(
|
|
7084
|
+
`Start ${runtime2}? [Enter=start, q=cancel] `
|
|
7085
|
+
);
|
|
7086
|
+
return answer.trim() === "";
|
|
7087
|
+
}
|
|
7088
|
+
function terminalPrompt() {
|
|
7089
|
+
return createInterface2({ input: process.stdin, output: process.stderr });
|
|
7090
|
+
}
|
|
7091
|
+
var init_runtime_choice = __esm({
|
|
7092
|
+
"src/tui/presentation/runtime-choice.ts"() {
|
|
7093
|
+
"use strict";
|
|
7094
|
+
}
|
|
7095
|
+
});
|
|
7096
|
+
|
|
6770
7097
|
// src/tui/startup/entry.ts
|
|
6771
7098
|
var entry_exports = {};
|
|
6772
7099
|
__export(entry_exports, {
|
|
6773
7100
|
launchStartup: () => launchStartup,
|
|
6774
7101
|
planStartup: () => planStartup
|
|
6775
7102
|
});
|
|
6776
|
-
import { createInterface as createInterface2 } from "readline/promises";
|
|
6777
7103
|
function planStartup(request3) {
|
|
6778
7104
|
const settings2 = startupSettings(request3);
|
|
6779
7105
|
const state = readStartup(
|
|
@@ -6795,26 +7121,41 @@ function planStartup(request3) {
|
|
|
6795
7121
|
}
|
|
6796
7122
|
async function launchStartup(request3, confirmed) {
|
|
6797
7123
|
requireTerminal();
|
|
6798
|
-
|
|
7124
|
+
let settings2 = startupSettings(request3);
|
|
6799
7125
|
const state = readStartup(
|
|
6800
7126
|
startupFile(settings2.projectRoot),
|
|
6801
7127
|
settings2.projectRoot
|
|
6802
7128
|
);
|
|
6803
7129
|
const starting = (!state || request3.fresh) && !settings2.groupFile;
|
|
6804
7130
|
if (starting) {
|
|
7131
|
+
if (!confirmed) {
|
|
7132
|
+
const prompt = terminalPrompt();
|
|
7133
|
+
try {
|
|
7134
|
+
let runtime2 = settings2.runtime;
|
|
7135
|
+
process.stderr.write(`PMCP MAIN | ${settings2.projectRoot}
|
|
7136
|
+
`);
|
|
7137
|
+
if (!request3.runtime) {
|
|
7138
|
+
const installed = settings2.allowedRuntimes.filter(
|
|
7139
|
+
(id2) => locateExecutable(runtimeExecutables[id2], request3.cwd)
|
|
7140
|
+
);
|
|
7141
|
+
const selected = await chooseRuntime(prompt, installed, runtime2);
|
|
7142
|
+
if (!selected) return cancelledStart();
|
|
7143
|
+
runtime2 = selected;
|
|
7144
|
+
}
|
|
7145
|
+
if (!await confirmRuntimeStart(prompt, runtime2))
|
|
7146
|
+
return cancelledStart();
|
|
7147
|
+
request3 = { ...request3, runtime: runtime2 };
|
|
7148
|
+
settings2 = startupSettings(request3);
|
|
7149
|
+
} finally {
|
|
7150
|
+
prompt.close();
|
|
7151
|
+
}
|
|
7152
|
+
}
|
|
6805
7153
|
if (!locateExecutable(runtimeExecutables[settings2.runtime], request3.cwd))
|
|
6806
7154
|
throw new Error("runtime_executable_unavailable");
|
|
6807
7155
|
process.stderr.write(
|
|
6808
7156
|
`PMCP main: ${settings2.runtime} | ${settings2.projectRoot}
|
|
6809
7157
|
`
|
|
6810
7158
|
);
|
|
6811
|
-
if (!confirmed && !await confirmStart(settings2.runtime))
|
|
6812
|
-
return {
|
|
6813
|
-
schemaVersion: 1,
|
|
6814
|
-
ok: true,
|
|
6815
|
-
cancelled: true,
|
|
6816
|
-
providerInvoked: false
|
|
6817
|
-
};
|
|
6818
7159
|
}
|
|
6819
7160
|
const prepared = serializedStartup(request3);
|
|
6820
7161
|
if (prepared.ok !== true) return prepared;
|
|
@@ -6824,19 +7165,13 @@ async function launchStartup(request3, confirmed) {
|
|
|
6824
7165
|
input: {}
|
|
6825
7166
|
});
|
|
6826
7167
|
}
|
|
6827
|
-
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
|
|
6832
|
-
|
|
6833
|
-
|
|
6834
|
-
`Start ${runtime2}? [Enter=start, q=cancel] `
|
|
6835
|
-
);
|
|
6836
|
-
return answer.trim() === "";
|
|
6837
|
-
} finally {
|
|
6838
|
-
prompt.close();
|
|
6839
|
-
}
|
|
7168
|
+
function cancelledStart() {
|
|
7169
|
+
return {
|
|
7170
|
+
schemaVersion: 1,
|
|
7171
|
+
ok: true,
|
|
7172
|
+
cancelled: true,
|
|
7173
|
+
providerInvoked: false
|
|
7174
|
+
};
|
|
6840
7175
|
}
|
|
6841
7176
|
var init_entry2 = __esm({
|
|
6842
7177
|
"src/tui/startup/entry.ts"() {
|
|
@@ -6848,6 +7183,7 @@ var init_entry2 = __esm({
|
|
|
6848
7183
|
init_state();
|
|
6849
7184
|
init_host();
|
|
6850
7185
|
init_lock2();
|
|
7186
|
+
init_runtime_choice();
|
|
6851
7187
|
}
|
|
6852
7188
|
});
|
|
6853
7189
|
|
|
@@ -6904,15 +7240,15 @@ function one(args, name) {
|
|
|
6904
7240
|
function many(args, name) {
|
|
6905
7241
|
return args.options.get(name) ?? [];
|
|
6906
7242
|
}
|
|
6907
|
-
function printCommandHelp(ui,
|
|
6908
|
-
ui.heading(`pmcp ${
|
|
6909
|
-
ui.line(` ${
|
|
7243
|
+
function printCommandHelp(ui, command3) {
|
|
7244
|
+
ui.heading(`pmcp ${command3.name}`);
|
|
7245
|
+
ui.line(` ${command3.describe}`);
|
|
6910
7246
|
ui.line();
|
|
6911
|
-
ui.line(` ${ui.paint(
|
|
6912
|
-
if (
|
|
7247
|
+
ui.line(` ${ui.paint(command3.usage, "dim")}`);
|
|
7248
|
+
if (command3.options && command3.options.length > 0) {
|
|
6913
7249
|
ui.line();
|
|
6914
7250
|
ui.table(
|
|
6915
|
-
|
|
7251
|
+
command3.options.map((option) => [
|
|
6916
7252
|
`--${option.name}${option.placeholder ? ` ${option.placeholder}` : ""}`,
|
|
6917
7253
|
option.describe
|
|
6918
7254
|
])
|
|
@@ -6923,7 +7259,7 @@ function printCommandHelp(ui, command2) {
|
|
|
6923
7259
|
function printHelp(ui, commands, notImplemented) {
|
|
6924
7260
|
ui.heading("pmcp \u2014 the skills your installed packages ship");
|
|
6925
7261
|
ui.line();
|
|
6926
|
-
ui.table(commands.map((
|
|
7262
|
+
ui.table(commands.map((command3) => [command3.name, command3.describe]));
|
|
6927
7263
|
ui.line();
|
|
6928
7264
|
ui.line(
|
|
6929
7265
|
" With no command, pmcp opens a terminal workspace on a supported TTY."
|
|
@@ -9511,7 +9847,7 @@ function registerMailboxTools(server, service) {
|
|
|
9511
9847
|
|
|
9512
9848
|
// src/mcp.ts
|
|
9513
9849
|
var SERVER_NAME = "pmcp";
|
|
9514
|
-
var SERVER_VERSION = "0.
|
|
9850
|
+
var SERVER_VERSION = "0.16.0";
|
|
9515
9851
|
function registerSkillTools(server, tools) {
|
|
9516
9852
|
registerCatalogTool(server, tools);
|
|
9517
9853
|
registerFindTool(server, tools);
|
|
@@ -12131,8 +12467,8 @@ var denied = () => ({
|
|
|
12131
12467
|
decision: "deny",
|
|
12132
12468
|
reason: "Shell guard failed validation or execution"
|
|
12133
12469
|
});
|
|
12134
|
-
function guardPath(root,
|
|
12135
|
-
const script =
|
|
12470
|
+
function guardPath(root, command3) {
|
|
12471
|
+
const script = command3[0]?.startsWith(".agents/guards/") ? command3[0] : command3[1];
|
|
12136
12472
|
if (!script?.startsWith(".agents/guards/")) {
|
|
12137
12473
|
throw new Error("Hook command must execute a script under .agents/guards/");
|
|
12138
12474
|
}
|
|
@@ -12190,10 +12526,10 @@ function evaluateShellHook(root, policy, tool, payload) {
|
|
|
12190
12526
|
if (!shellNames[tool].includes(name)) {
|
|
12191
12527
|
return { decision: "allow" };
|
|
12192
12528
|
}
|
|
12193
|
-
const
|
|
12529
|
+
const command3 = scalar(
|
|
12194
12530
|
input[tool === "antigravity" ? "CommandLine" : "command"]
|
|
12195
12531
|
);
|
|
12196
|
-
if (
|
|
12532
|
+
if (command3 === void 0 || command3.length > 65536) {
|
|
12197
12533
|
return denied();
|
|
12198
12534
|
}
|
|
12199
12535
|
const cwd = scalar(input["Cwd"]) ?? scalar(value["cwd"]) ?? root;
|
|
@@ -12214,7 +12550,7 @@ function evaluateShellHook(root, policy, tool, payload) {
|
|
|
12214
12550
|
input: JSON.stringify({
|
|
12215
12551
|
runtime: tool,
|
|
12216
12552
|
event: "before_shell",
|
|
12217
|
-
command:
|
|
12553
|
+
command: command3,
|
|
12218
12554
|
cwd
|
|
12219
12555
|
}),
|
|
12220
12556
|
encoding: "utf8",
|
|
@@ -12402,11 +12738,11 @@ function hookOutputs(spec) {
|
|
|
12402
12738
|
continue;
|
|
12403
12739
|
}
|
|
12404
12740
|
const target2 = native[tool];
|
|
12405
|
-
const
|
|
12741
|
+
const command3 = `d="$PWD"; while [ ! -f "$d/pmcp.toml" ]; do [ "$d" = / ] && exit 1; d=$(dirname "$d"); done; exec node "$d/${ADAPTER}" --pmcp-shell-hook ${tool} "$d/${policyFile}" ${integrity2}`;
|
|
12406
12742
|
const timeout = tool === "gemini" ? hook.timeoutMs + 2e3 : Math.ceil(hook.timeoutMs / 1e3) + 2;
|
|
12407
12743
|
const value = {
|
|
12408
12744
|
matcher: target2.matcher,
|
|
12409
|
-
hooks: [{ type: "command", command:
|
|
12745
|
+
hooks: [{ type: "command", command: command3, timeout }]
|
|
12410
12746
|
};
|
|
12411
12747
|
const path = `${target2.file}#${target2.key.join(".")}`;
|
|
12412
12748
|
const entry2 = desired.get(path) ?? {
|
|
@@ -13120,13 +13456,13 @@ function readHooks(path, root, raw) {
|
|
|
13120
13456
|
return fail2("unknown shell entry field");
|
|
13121
13457
|
}
|
|
13122
13458
|
const name = entry2["name"];
|
|
13123
|
-
const
|
|
13459
|
+
const command3 = entry2["command"];
|
|
13124
13460
|
const targets = entry2["targets"];
|
|
13125
13461
|
const timeoutMs = entry2["timeout_ms"] ?? 15e3;
|
|
13126
13462
|
if (typeof name !== "string" || !/^[a-z0-9][a-z0-9-]*$/u.test(name) || names.has(name)) {
|
|
13127
13463
|
return fail2("shell names must be unique lowercase names");
|
|
13128
13464
|
}
|
|
13129
|
-
if (!Array.isArray(
|
|
13465
|
+
if (!Array.isArray(command3) || command3.length === 0 || !command3.every(
|
|
13130
13466
|
(part) => typeof part === "string" && part.length > 0 && !part.includes("\0")
|
|
13131
13467
|
)) {
|
|
13132
13468
|
return fail2("command must be a nonempty argument list");
|
|
@@ -13140,7 +13476,7 @@ function readHooks(path, root, raw) {
|
|
|
13140
13476
|
return fail2("timeout_ms must be an integer from 100 to 60000");
|
|
13141
13477
|
}
|
|
13142
13478
|
try {
|
|
13143
|
-
guardPath(root,
|
|
13479
|
+
guardPath(root, command3);
|
|
13144
13480
|
} catch (error) {
|
|
13145
13481
|
return fail2(
|
|
13146
13482
|
error instanceof Error ? error.message : "invalid guard path"
|
|
@@ -13149,7 +13485,7 @@ function readHooks(path, root, raw) {
|
|
|
13149
13485
|
names.add(name);
|
|
13150
13486
|
return {
|
|
13151
13487
|
name,
|
|
13152
|
-
command:
|
|
13488
|
+
command: command3,
|
|
13153
13489
|
targets,
|
|
13154
13490
|
timeoutMs
|
|
13155
13491
|
};
|
|
@@ -13372,13 +13708,13 @@ function readMcp(path, value) {
|
|
|
13372
13708
|
fail(path, where, `unknown field ${key}`);
|
|
13373
13709
|
}
|
|
13374
13710
|
}
|
|
13375
|
-
const
|
|
13711
|
+
const command3 = entry2["command"];
|
|
13376
13712
|
const url = entry2["url"];
|
|
13377
|
-
if (
|
|
13713
|
+
if (command3 === void 0 === (url === void 0)) {
|
|
13378
13714
|
fail(path, where, "provide exactly one of command or url");
|
|
13379
13715
|
}
|
|
13380
13716
|
for (const [key, item] of [
|
|
13381
|
-
["command",
|
|
13717
|
+
["command", command3],
|
|
13382
13718
|
["url", url],
|
|
13383
13719
|
["cwd", entry2["cwd"]]
|
|
13384
13720
|
]) {
|
|
@@ -13476,7 +13812,7 @@ function readMcp(path, value) {
|
|
|
13476
13812
|
fail(path, where, "mailbox must be a boolean");
|
|
13477
13813
|
}
|
|
13478
13814
|
servers[alias] = {
|
|
13479
|
-
...typeof
|
|
13815
|
+
...typeof command3 === "string" ? { command: command3 } : { url },
|
|
13480
13816
|
args: list(path, `${where} args`, entry2["args"], false),
|
|
13481
13817
|
env,
|
|
13482
13818
|
...envVars.length > 0 ? { envVars } : {},
|
|
@@ -13879,8 +14215,8 @@ import { spawnSync as spawnSync3 } from "child_process";
|
|
|
13879
14215
|
import { existsSync as existsSync21, readFileSync as readFileSync28 } from "fs";
|
|
13880
14216
|
import { join as join25 } from "path";
|
|
13881
14217
|
import { parse as parse8 } from "smol-toml";
|
|
13882
|
-
var spawnRunner = (
|
|
13883
|
-
const result = spawnSync3(
|
|
14218
|
+
var spawnRunner = (command3, args, cwd, env) => {
|
|
14219
|
+
const result = spawnSync3(command3, [...args], {
|
|
13884
14220
|
cwd,
|
|
13885
14221
|
...env ? { env: { ...process.env, ...env } } : {},
|
|
13886
14222
|
encoding: "utf8",
|
|
@@ -15137,6 +15473,11 @@ var tuiOptions = [
|
|
|
15137
15473
|
},
|
|
15138
15474
|
{ name: "rows", describe: "Terminal rows (12\u20131000)", placeholder: "<count>" },
|
|
15139
15475
|
{ name: "index", describe: "Worker dock index", placeholder: "<count>" },
|
|
15476
|
+
{
|
|
15477
|
+
name: "memory-mb",
|
|
15478
|
+
describe: "Worker memory reservation",
|
|
15479
|
+
placeholder: "<count>"
|
|
15480
|
+
},
|
|
15140
15481
|
{
|
|
15141
15482
|
name: "confirm-session",
|
|
15142
15483
|
describe: "Exact target ID for stop",
|
|
@@ -15149,7 +15490,7 @@ var tuiOptions = [
|
|
|
15149
15490
|
},
|
|
15150
15491
|
{
|
|
15151
15492
|
name: "runtime",
|
|
15152
|
-
describe: "
|
|
15493
|
+
describe: "Native runtime ID for main launch or worker start",
|
|
15153
15494
|
placeholder: "<runtime>"
|
|
15154
15495
|
},
|
|
15155
15496
|
{
|
|
@@ -15171,6 +15512,8 @@ var tuiOptions = [
|
|
|
15171
15512
|
var allowed2 = {
|
|
15172
15513
|
launch: ["config", "runtime", "yes", "new"],
|
|
15173
15514
|
plan: ["config", "runtime"],
|
|
15515
|
+
recovery: ["config"],
|
|
15516
|
+
"start-worker": ["config", "view", "runtime", "memory-mb"],
|
|
15174
15517
|
doctor: [],
|
|
15175
15518
|
create: ["group-file", "columns", "rows", "config", "actor-file"],
|
|
15176
15519
|
inspect: ["view"],
|
|
@@ -15188,6 +15531,7 @@ var allowed2 = {
|
|
|
15188
15531
|
close: ["view"],
|
|
15189
15532
|
dismiss: ["view"],
|
|
15190
15533
|
management: ["view"],
|
|
15534
|
+
"worker-menu": ["view"],
|
|
15191
15535
|
check: ["view"]
|
|
15192
15536
|
};
|
|
15193
15537
|
function parseTui(args) {
|
|
@@ -15212,7 +15556,23 @@ function parseTui(args) {
|
|
|
15212
15556
|
return Number(value);
|
|
15213
15557
|
};
|
|
15214
15558
|
if (action === "doctor") return { action, input: {} };
|
|
15215
|
-
if (action === "
|
|
15559
|
+
if (action === "start-worker") {
|
|
15560
|
+
const config = one(args, "config");
|
|
15561
|
+
const viewFile = one(args, "view");
|
|
15562
|
+
if (config && viewFile)
|
|
15563
|
+
throw new ArgumentError("Choose --config or --view for worker start");
|
|
15564
|
+
return {
|
|
15565
|
+
action,
|
|
15566
|
+
viewFile,
|
|
15567
|
+
input: {},
|
|
15568
|
+
startup: {
|
|
15569
|
+
config,
|
|
15570
|
+
runtime: required2("runtime"),
|
|
15571
|
+
memoryMb: number("memory-mb")
|
|
15572
|
+
}
|
|
15573
|
+
};
|
|
15574
|
+
}
|
|
15575
|
+
if (action === "launch" || action === "plan" || action === "recovery")
|
|
15216
15576
|
return {
|
|
15217
15577
|
action,
|
|
15218
15578
|
input: {},
|
|
@@ -15263,14 +15623,36 @@ function parseTui(args) {
|
|
|
15263
15623
|
var tuiCommand = {
|
|
15264
15624
|
name: "tui",
|
|
15265
15625
|
describe: "Open a native terminal workspace with optional configuration",
|
|
15266
|
-
usage: "pmcp tui [--config <file>] [--runtime <id>] | plan | doctor | operation --view <file>",
|
|
15626
|
+
usage: "pmcp tui [--config <file>] [--runtime <id>] | plan | recovery | doctor | start-worker --runtime <id> | operation --view <file>",
|
|
15267
15627
|
options: tuiOptions,
|
|
15268
15628
|
async run(context) {
|
|
15269
15629
|
const invocation2 = parseTui(context.args);
|
|
15270
15630
|
const { invokeTui: invokeTui2, failedInvocation: failedInvocation2 } = await Promise.resolve().then(() => (init_invoke2(), invoke_exports2));
|
|
15271
15631
|
try {
|
|
15272
15632
|
let receipt;
|
|
15273
|
-
if (invocation2.action === "
|
|
15633
|
+
if (invocation2.action === "start-worker") {
|
|
15634
|
+
if (invocation2.viewFile) {
|
|
15635
|
+
const { startViewWorker: startViewWorker2 } = await Promise.resolve().then(() => (init_worker_start(), worker_start_exports));
|
|
15636
|
+
receipt = await startViewWorker2(
|
|
15637
|
+
invocation2.viewFile,
|
|
15638
|
+
invocation2.startup.runtime,
|
|
15639
|
+
invocation2.startup?.memoryMb
|
|
15640
|
+
);
|
|
15641
|
+
} else {
|
|
15642
|
+
const { startWorkspaceWorker: startWorkspaceWorker2 } = await Promise.resolve().then(() => (init_worker(), worker_exports));
|
|
15643
|
+
receipt = await startWorkspaceWorker2(
|
|
15644
|
+
{ config: invocation2.startup?.config, cwd: context.cwd },
|
|
15645
|
+
invocation2.startup.runtime,
|
|
15646
|
+
invocation2.startup?.memoryMb
|
|
15647
|
+
);
|
|
15648
|
+
}
|
|
15649
|
+
} else if (invocation2.action === "recovery") {
|
|
15650
|
+
const { inspectStartupRecovery: inspectStartupRecovery2 } = await Promise.resolve().then(() => (init_recovery2(), recovery_exports));
|
|
15651
|
+
receipt = inspectStartupRecovery2({
|
|
15652
|
+
...invocation2.startup,
|
|
15653
|
+
cwd: context.cwd
|
|
15654
|
+
});
|
|
15655
|
+
} else if (invocation2.action === "launch" || invocation2.action === "plan") {
|
|
15274
15656
|
const { launchStartup: launchStartup2, planStartup: planStartup2 } = await Promise.resolve().then(() => (init_entry2(), entry_exports));
|
|
15275
15657
|
const request3 = { ...invocation2.startup, cwd: context.cwd };
|
|
15276
15658
|
receipt = invocation2.action === "plan" ? planStartup2(request3) : await launchStartup2(
|
|
@@ -15525,7 +15907,7 @@ function dispatch(argv, options2 = {}) {
|
|
|
15525
15907
|
return defaultEntry(options2, { ui, env, cwd });
|
|
15526
15908
|
}
|
|
15527
15909
|
if (verb === "--help" || verb === "-h" || verb === "help") {
|
|
15528
|
-
const named2 = COMMANDS.find((
|
|
15910
|
+
const named2 = COMMANDS.find((command4) => command4.name === rest[0]);
|
|
15529
15911
|
if (named2) printCommandHelp(ui, named2);
|
|
15530
15912
|
else printHelp(ui, COMMANDS, PLANNED);
|
|
15531
15913
|
return 0;
|
|
@@ -15538,8 +15920,8 @@ function dispatch(argv, options2 = {}) {
|
|
|
15538
15920
|
if (verb.startsWith("-")) {
|
|
15539
15921
|
return run(serveCommand, rest0, { ui, env, cwd });
|
|
15540
15922
|
}
|
|
15541
|
-
const
|
|
15542
|
-
if (
|
|
15923
|
+
const command3 = COMMANDS.find((candidate2) => candidate2.name === verb);
|
|
15924
|
+
if (command3 === void 0) {
|
|
15543
15925
|
if (PLANNED.includes(verb))
|
|
15544
15926
|
ui.error(`"${verb}" is designed but not implemented yet`);
|
|
15545
15927
|
else ui.error(`unknown command "${verb}"`);
|
|
@@ -15547,12 +15929,12 @@ function dispatch(argv, options2 = {}) {
|
|
|
15547
15929
|
return 2;
|
|
15548
15930
|
}
|
|
15549
15931
|
if (rest.includes("--help") || rest.includes("-h")) {
|
|
15550
|
-
printCommandHelp(ui,
|
|
15932
|
+
printCommandHelp(ui, command3);
|
|
15551
15933
|
return 0;
|
|
15552
15934
|
}
|
|
15553
|
-
return run(
|
|
15935
|
+
return run(command3, rest, { ui, env, cwd });
|
|
15554
15936
|
}
|
|
15555
|
-
var VERSION = "0.
|
|
15937
|
+
var VERSION = "0.16.0";
|
|
15556
15938
|
async function defaultEntry(options2, context) {
|
|
15557
15939
|
const terminal = options2.terminal ?? {
|
|
15558
15940
|
stdin: process.stdin.isTTY === true,
|
|
@@ -15576,16 +15958,16 @@ async function defaultEntry(options2, context) {
|
|
|
15576
15958
|
printHelp(context.ui, COMMANDS, PLANNED);
|
|
15577
15959
|
return 0;
|
|
15578
15960
|
}
|
|
15579
|
-
async function run(
|
|
15961
|
+
async function run(command3, argv, context) {
|
|
15580
15962
|
try {
|
|
15581
|
-
return await
|
|
15963
|
+
return await command3.run({
|
|
15582
15964
|
...context,
|
|
15583
|
-
args: parseArgs(argv,
|
|
15965
|
+
args: parseArgs(argv, command3.options)
|
|
15584
15966
|
});
|
|
15585
15967
|
} catch (error) {
|
|
15586
15968
|
if (error instanceof ArgumentError) {
|
|
15587
15969
|
context.ui.error(error.message);
|
|
15588
|
-
printCommandHelp(context.ui,
|
|
15970
|
+
printCommandHelp(context.ui, command3);
|
|
15589
15971
|
return 2;
|
|
15590
15972
|
}
|
|
15591
15973
|
context.ui.error(error instanceof Error ? error.message : "command failed");
|