litmus-cli 1.4.92 → 1.4.94
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 +48 -0
- package/dist/commands/connect.d.ts +6 -2
- package/dist/commands/connect.d.ts.map +1 -1
- package/dist/commands/connect.js +222 -35
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/forward.d.ts +7 -1
- package/dist/commands/forward.d.ts.map +1 -1
- package/dist/commands/forward.js +8 -7
- package/dist/commands/forward.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +12 -2
- package/dist/commands/init.js.map +1 -1
- package/dist/lib/ai-tracking.d.ts +8 -0
- package/dist/lib/ai-tracking.d.ts.map +1 -1
- package/dist/lib/ai-tracking.js +96 -1
- package/dist/lib/ai-tracking.js.map +1 -1
- package/dist/lib/connect-skills.d.ts +1 -0
- package/dist/lib/connect-skills.d.ts.map +1 -1
- package/dist/lib/connect-skills.js +1 -1
- package/dist/lib/connect-skills.js.map +1 -1
- package/dist/lib/desktop-readiness.d.ts +9 -0
- package/dist/lib/desktop-readiness.d.ts.map +1 -0
- package/dist/lib/desktop-readiness.js +131 -0
- package/dist/lib/desktop-readiness.js.map +1 -0
- package/dist/lib/editor-foreground.d.ts +6 -0
- package/dist/lib/editor-foreground.d.ts.map +1 -0
- package/dist/lib/editor-foreground.js +38 -0
- package/dist/lib/editor-foreground.js.map +1 -0
- package/dist/lib/environment-checks.d.ts +2 -0
- package/dist/lib/environment-checks.d.ts.map +1 -1
- package/dist/lib/environment-checks.js +4 -2
- package/dist/lib/environment-checks.js.map +1 -1
- package/dist/lib/file-monitor.d.ts +18 -0
- package/dist/lib/file-monitor.d.ts.map +1 -0
- package/dist/lib/file-monitor.js +87 -0
- package/dist/lib/file-monitor.js.map +1 -0
- package/dist/lib/hosted-capture.d.ts +1 -1
- package/dist/lib/hosted-capture.d.ts.map +1 -1
- package/dist/lib/hosted-capture.js +22 -12
- package/dist/lib/hosted-capture.js.map +1 -1
- package/dist/lib/init-location.d.ts +4 -0
- package/dist/lib/init-location.d.ts.map +1 -0
- package/dist/lib/init-location.js +36 -0
- package/dist/lib/init-location.js.map +1 -0
- package/dist/lib/installed-tools.d.ts +29 -0
- package/dist/lib/installed-tools.d.ts.map +1 -0
- package/dist/lib/installed-tools.js +159 -0
- package/dist/lib/installed-tools.js.map +1 -0
- package/dist/lib/portal-launcher-background.d.ts +13 -0
- package/dist/lib/portal-launcher-background.d.ts.map +1 -0
- package/dist/lib/portal-launcher-background.js +51 -0
- package/dist/lib/portal-launcher-background.js.map +1 -0
- package/dist/lib/portal-launcher-worker.d.ts +2 -0
- package/dist/lib/portal-launcher-worker.d.ts.map +1 -0
- package/dist/lib/portal-launcher-worker.js +43 -0
- package/dist/lib/portal-launcher-worker.js.map +1 -0
- package/dist/lib/portal-launcher.d.ts +43 -0
- package/dist/lib/portal-launcher.d.ts.map +1 -0
- package/dist/lib/portal-launcher.js +408 -0
- package/dist/lib/portal-launcher.js.map +1 -0
- package/dist/lib/prepared-desktop.d.ts +7 -0
- package/dist/lib/prepared-desktop.d.ts.map +1 -0
- package/dist/lib/prepared-desktop.js +35 -0
- package/dist/lib/prepared-desktop.js.map +1 -0
- package/dist/lib/prepared-editor.d.ts +26 -0
- package/dist/lib/prepared-editor.d.ts.map +1 -0
- package/dist/lib/prepared-editor.js +150 -0
- package/dist/lib/prepared-editor.js.map +1 -0
- package/dist/lib/schemas.d.ts +1 -0
- package/dist/lib/schemas.d.ts.map +1 -1
- package/dist/lib/schemas.js +2 -0
- package/dist/lib/schemas.js.map +1 -1
- package/dist/lib/ssh-client.d.ts +12 -0
- package/dist/lib/ssh-client.d.ts.map +1 -1
- package/dist/lib/ssh-client.js +1 -1
- package/dist/lib/ssh-client.js.map +1 -1
- package/dist/lib/ssh-config-file.d.ts +3 -0
- package/dist/lib/ssh-config-file.d.ts.map +1 -1
- package/dist/lib/ssh-config-file.js +42 -0
- package/dist/lib/ssh-config-file.js.map +1 -1
- package/dist/lib/tracker.d.ts +1 -0
- package/dist/lib/tracker.d.ts.map +1 -1
- package/dist/lib/tracker.js +4 -2
- package/dist/lib/tracker.js.map +1 -1
- package/dist/lib/vscode-server-preparation.d.ts +7 -0
- package/dist/lib/vscode-server-preparation.d.ts.map +1 -0
- package/dist/lib/vscode-server-preparation.js +78 -0
- package/dist/lib/vscode-server-preparation.js.map +1 -0
- package/dist/lib/watcher.js +98 -77
- package/dist/lib/watcher.js.map +1 -1
- package/dist/lib/workspace-start-wait.d.ts +23 -0
- package/dist/lib/workspace-start-wait.d.ts.map +1 -0
- package/dist/lib/workspace-start-wait.js +50 -0
- package/dist/lib/workspace-start-wait.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { fileURLToPath } from "url";
|
|
2
|
+
import { spawn } from "child_process";
|
|
3
|
+
/** Pass credentials over IPC, never argv or a persistent settings/log file.
|
|
4
|
+
* Wait for registration and discovery before releasing the terminal.
|
|
5
|
+
*/
|
|
6
|
+
export function startBackgroundLauncher(context, timeoutMs = 240000, worker = new URL("./portal-launcher-worker.js", import.meta.url)) {
|
|
7
|
+
return new Promise((resolve, reject) => {
|
|
8
|
+
const env = { ...process.env };
|
|
9
|
+
delete env.LITMUS_ASSESSMENT_TOKEN;
|
|
10
|
+
const child = spawn(process.execPath, [fileURLToPath(worker)], {
|
|
11
|
+
detached: true, stdio: ["ignore", "ignore", "ignore", "ipc"], env,
|
|
12
|
+
windowsHide: true,
|
|
13
|
+
});
|
|
14
|
+
let status = "starting";
|
|
15
|
+
let settled = false;
|
|
16
|
+
const finish = (error) => {
|
|
17
|
+
if (settled)
|
|
18
|
+
return;
|
|
19
|
+
settled = true;
|
|
20
|
+
clearTimeout(timer);
|
|
21
|
+
if (error) {
|
|
22
|
+
child.kill();
|
|
23
|
+
reject(error);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
child.unref();
|
|
27
|
+
resolve(status === "ready");
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
const failure = () => finish(new Error("Could not start the laptop connection. Run litmus connect again."));
|
|
31
|
+
const timer = setTimeout(failure, timeoutMs);
|
|
32
|
+
child.once("error", failure);
|
|
33
|
+
child.once("exit", failure);
|
|
34
|
+
child.once("disconnect", () => status !== "starting" ? finish() : failure());
|
|
35
|
+
child.on("message", message => {
|
|
36
|
+
const type = message?.type;
|
|
37
|
+
if (type === "unavailable") {
|
|
38
|
+
status = "unavailable";
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (type !== "ready" || status !== "starting")
|
|
42
|
+
return;
|
|
43
|
+
status = "ready";
|
|
44
|
+
child.send({ type: "detach" }, error => { if (error)
|
|
45
|
+
failure(); });
|
|
46
|
+
});
|
|
47
|
+
child.send(context, error => { if (error)
|
|
48
|
+
failure(); });
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=portal-launcher-background.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portal-launcher-background.js","sourceRoot":"","sources":["../../src/lib/portal-launcher-background.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAA;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAWrC;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,OAAyB,EAAE,SAAS,GAAG,MAAO,EAAE,MAAM,GAAG,IAAI,GAAG,CAAC,6BAA6B,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC;IACtJ,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,GAAG,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAA;QAC9B,OAAO,GAAG,CAAC,uBAAuB,CAAA;QAClC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,EAAE;YAC7D,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,GAAG;YACjE,WAAW,EAAE,IAAI;SAClB,CAAC,CAAA;QACF,IAAI,MAAM,GAAyC,UAAU,CAAA;QAC7D,IAAI,OAAO,GAAG,KAAK,CAAA;QACnB,MAAM,MAAM,GAAG,CAAC,KAAa,EAAE,EAAE;YAC/B,IAAI,OAAO;gBAAE,OAAM;YACnB,OAAO,GAAG,IAAI,CAAA;YACd,YAAY,CAAC,KAAK,CAAC,CAAA;YACnB,IAAI,KAAK,EAAE,CAAC;gBAAC,KAAK,CAAC,IAAI,EAAE,CAAC;gBAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YAAC,CAAC;iBACrC,CAAC;gBAAC,KAAK,CAAC,KAAK,EAAE,CAAC;gBAAC,OAAO,CAAC,MAAM,KAAK,OAAO,CAAC,CAAA;YAAC,CAAC;QACrD,CAAC,CAAA;QACD,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC,CAAA;QAC3G,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;QAC5C,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QAC5B,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAC3B,KAAK,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAA;QAC5E,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE;YAC5B,MAAM,IAAI,GAAI,OAAoC,EAAE,IAAI,CAAA;YACxD,IAAI,IAAI,KAAK,aAAa,EAAE,CAAC;gBAAC,MAAM,GAAG,aAAa,CAAC;gBAAC,OAAM;YAAC,CAAC;YAC9D,IAAI,IAAI,KAAK,OAAO,IAAI,MAAM,KAAK,UAAU;gBAAE,OAAM;YACrD,MAAM,GAAG,OAAO,CAAA;YAChB,KAAK,CAAC,IAAK,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,KAAK,CAAC,EAAE,GAAG,IAAI,KAAK;gBAAE,OAAO,EAAE,CAAA,CAAC,CAAC,CAAC,CAAA;QACpE,CAAC,CAAC,CAAA;QACF,KAAK,CAAC,IAAK,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,GAAG,IAAI,KAAK;YAAE,OAAO,EAAE,CAAA,CAAC,CAAC,CAAC,CAAA;IACzD,CAAC,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portal-launcher-worker.d.ts","sourceRoot":"","sources":["../../src/lib/portal-launcher-worker.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { runPreparedPortalLauncher } from "../commands/connect.js";
|
|
2
|
+
const abort = new AbortController();
|
|
3
|
+
let handedOff = false;
|
|
4
|
+
if (!process.connected)
|
|
5
|
+
process.exit(1);
|
|
6
|
+
// A terminal closed during setup must not leave an unacknowledged worker behind.
|
|
7
|
+
process.once("disconnect", () => { clearTimeout(startup); if (!handedOff)
|
|
8
|
+
abort.abort(); });
|
|
9
|
+
const startup = setTimeout(() => {
|
|
10
|
+
abort.abort();
|
|
11
|
+
process.exitCode = 1;
|
|
12
|
+
if (process.connected)
|
|
13
|
+
process.disconnect?.();
|
|
14
|
+
}, 240000);
|
|
15
|
+
process.once("message", async (message) => {
|
|
16
|
+
clearTimeout(startup);
|
|
17
|
+
const context = message;
|
|
18
|
+
// No OS service or restart-at-login registration. The server revokes this
|
|
19
|
+
// session on replacement/submission/expiry; also bound unattended lifetime.
|
|
20
|
+
const lifetime = setTimeout(() => abort.abort(), 24 * 60 * 60 * 1000);
|
|
21
|
+
process.once("message", value => {
|
|
22
|
+
if (value?.type === "detach") {
|
|
23
|
+
handedOff = true;
|
|
24
|
+
process.disconnect?.();
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
let ready = false;
|
|
28
|
+
try {
|
|
29
|
+
await runPreparedPortalLauncher(context, () => { ready = true; process.send?.({ type: "ready" }); }, abort.signal);
|
|
30
|
+
if (!ready && !abort.signal.aborted) {
|
|
31
|
+
await new Promise(resolve => process.send?.({ type: "unavailable" }, () => resolve()));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
process.exitCode = 1;
|
|
36
|
+
}
|
|
37
|
+
finally {
|
|
38
|
+
clearTimeout(lifetime);
|
|
39
|
+
if (process.connected)
|
|
40
|
+
process.disconnect?.();
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
//# sourceMappingURL=portal-launcher-worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portal-launcher-worker.js","sourceRoot":"","sources":["../../src/lib/portal-launcher-worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAA;AAGlE,MAAM,KAAK,GAAG,IAAI,eAAe,EAAE,CAAA;AACnC,IAAI,SAAS,GAAG,KAAK,CAAA;AACrB,IAAI,CAAC,OAAO,CAAC,SAAS;IAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACvC,iFAAiF;AACjF,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,EAAE,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS;IAAE,KAAK,CAAC,KAAK,EAAE,CAAA,CAAC,CAAC,CAAC,CAAA;AAC1F,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;IAC9B,KAAK,CAAC,KAAK,EAAE,CAAA;IACb,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;IACpB,IAAI,OAAO,CAAC,SAAS;QAAE,OAAO,CAAC,UAAU,EAAE,EAAE,CAAA;AAC/C,CAAC,EAAE,MAAO,CAAC,CAAA;AACX,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,EAAC,OAAO,EAAC,EAAE;IACtC,YAAY,CAAC,OAAO,CAAC,CAAA;IACrB,MAAM,OAAO,GAAG,OAA2B,CAAA;IAC3C,0EAA0E;IAC1E,4EAA4E;IAC5E,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAA;IACrE,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE;QAC9B,IAAK,KAAkC,EAAE,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC3D,SAAS,GAAG,IAAI,CAAA;YAChB,OAAO,CAAC,UAAU,EAAE,EAAE,CAAA;QACxB,CAAC;IACH,CAAC,CAAC,CAAA;IACF,IAAI,KAAK,GAAG,KAAK,CAAA;IACjB,IAAI,CAAC;QACH,MAAM,yBAAyB,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAA,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;QACjH,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpC,MAAM,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;QAC9F,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;IAAC,CAAC;YACxB,CAAC;QACP,YAAY,CAAC,QAAQ,CAAC,CAAA;QACtB,IAAI,OAAO,CAAC,SAAS;YAAE,OAAO,CAAC,UAAU,EAAE,EAAE,CAAA;IAC/C,CAAC;AACH,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { spawn, fork } from "child_process";
|
|
2
|
+
import { type InstalledTool, type LaunchTool } from "./installed-tools.js";
|
|
3
|
+
import { type WorkspaceGeneration, type PreparedEditor } from "./prepared-editor.js";
|
|
4
|
+
export declare function permanentLauncherFailure(error: unknown): boolean;
|
|
5
|
+
export type LaunchResult = "dispatched" | "action_required" | "failed";
|
|
6
|
+
export declare function desktopUrl(tool: "codex" | "claude", alias: string): string;
|
|
7
|
+
export declare function spawnDetached(command: string, args: string[]): Promise<boolean>;
|
|
8
|
+
export declare function terminalRemoteCommand(requestId?: string): string;
|
|
9
|
+
export declare function openTerminal(alias: string, terminal: string, requestId?: string): Promise<boolean>;
|
|
10
|
+
/** Isolate existing fatal/exit paths and synchronous probes from the heartbeat process. */
|
|
11
|
+
export declare function openNativeEditor(tool: "vscode" | "cursor", token: string, signal?: AbortSignal, forkFn?: typeof fork, onPrepared?: (editor: PreparedEditor) => void, generation?: WorkspaceGeneration): Promise<LaunchResult>;
|
|
12
|
+
/** Announce preparation before skills, key creation and workspace startup.
|
|
13
|
+
* Older/unavailable launcher APIs must not prevent the assessment connection.
|
|
14
|
+
* A killed process expires server-side; normal exits remove only this session.
|
|
15
|
+
*/
|
|
16
|
+
export type PreparationStage = "waiting_input" | "waiting_capacity" | "starting_workspace" | "checking_connection" | "checking_tools";
|
|
17
|
+
export type PortalPreparation = (() => Promise<void>) & {
|
|
18
|
+
update: (stage: PreparationStage) => void;
|
|
19
|
+
fail: (reason: "capacity_timeout" | "connection_failed") => void;
|
|
20
|
+
};
|
|
21
|
+
export declare function startPortalPreparation(backendUrl: string, token: string): Promise<PortalPreparation>;
|
|
22
|
+
export interface LauncherOptions {
|
|
23
|
+
backendUrl: string;
|
|
24
|
+
token: string;
|
|
25
|
+
alias: string;
|
|
26
|
+
pageUrl: string;
|
|
27
|
+
browserAvailable: boolean;
|
|
28
|
+
openUrl: (url: string) => Promise<boolean>;
|
|
29
|
+
launch: (tool: LaunchTool, installed: InstalledTool[], signal: AbortSignal, context?: {
|
|
30
|
+
requestId: string;
|
|
31
|
+
generation?: WorkspaceGeneration;
|
|
32
|
+
}) => Promise<LaunchResult>;
|
|
33
|
+
prepareTools?: (installed: InstalledTool[], signal: AbortSignal) => Promise<InstalledTool[]>;
|
|
34
|
+
onReady?: () => void;
|
|
35
|
+
onSubmitted?: () => void | Promise<void>;
|
|
36
|
+
signal?: AbortSignal;
|
|
37
|
+
/** Injectable scheduling for deterministic retry tests. Production defaults to 5s. */
|
|
38
|
+
wait?: (ms: number, signal: AbortSignal) => Promise<void>;
|
|
39
|
+
}
|
|
40
|
+
export declare function runPortalLauncher(options: LauncherOptions): Promise<void>;
|
|
41
|
+
/** Observe the OS opener's exit status; spawning it alone does not prove dispatch. */
|
|
42
|
+
export declare function openDesktop(app: InstalledTool, alias: string, signal: AbortSignal, platform?: NodeJS.Platform, spawnFn?: typeof spawn): Promise<boolean>;
|
|
43
|
+
//# sourceMappingURL=portal-launcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portal-launcher.d.ts","sourceRoot":"","sources":["../../src/lib/portal-launcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
/** Candidate-scoped, outbound-only launcher. No localhost listener or arbitrary commands. */
|
|
2
|
+
import { fetchSubmissionSaved } from "./api.js";
|
|
3
|
+
import { spawn, fork } from "child_process";
|
|
4
|
+
import { mkdirSync, writeFileSync } from "fs";
|
|
5
|
+
import os from "os";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import { discoverInstalledTools } from "./installed-tools.js";
|
|
8
|
+
import { configSetsRemoteCommand } from "./ssh-client.js";
|
|
9
|
+
import { parsePreparedEditor, parseWorkspaceGeneration } from "./prepared-editor.js";
|
|
10
|
+
class LauncherRefusal extends Error {
|
|
11
|
+
constructor(status, readinessPending = false, code) {
|
|
12
|
+
super(`Launcher request refused (${status}). Re-run litmus connect to reconnect.`);
|
|
13
|
+
this.status = status;
|
|
14
|
+
this.readinessPending = readinessPending;
|
|
15
|
+
this.code = code;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function permanentLauncherFailure(error) {
|
|
19
|
+
return error instanceof LauncherRefusal && !error.readinessPending && error.status >= 400 && error.status < 500 && ![408, 429].includes(error.status);
|
|
20
|
+
}
|
|
21
|
+
export function desktopUrl(tool, alias) {
|
|
22
|
+
if (!/^litmus-[a-zA-Z0-9-]+$/.test(alias))
|
|
23
|
+
throw new Error("Invalid assessment SSH alias");
|
|
24
|
+
// `name` is the documented SSH-config alias parameter. Recent ChatGPT apps
|
|
25
|
+
// also accept projectPath/enabled; older ones may stop at SSH settings.
|
|
26
|
+
// Dispatch never proves that sign-in or remote project selection completed.
|
|
27
|
+
return tool === "codex"
|
|
28
|
+
? `codex://settings/connections/ssh/add?name=${encodeURIComponent(alias)}&projectPath=${encodeURIComponent("/home/candidate/workspace")}&enabled=true`
|
|
29
|
+
: `claude://code/new?ssh_host=${encodeURIComponent(alias)}&ssh_folder=${encodeURIComponent("/home/candidate/workspace")}`;
|
|
30
|
+
}
|
|
31
|
+
export function spawnDetached(command, args) {
|
|
32
|
+
return new Promise(resolve => {
|
|
33
|
+
const child = spawn(command, args, { detached: true, stdio: "ignore" });
|
|
34
|
+
child.once("error", () => resolve(false));
|
|
35
|
+
child.once("spawn", () => { child.unref(); resolve(true); });
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
export function terminalRemoteCommand(requestId) {
|
|
39
|
+
if (requestId && !/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(requestId))
|
|
40
|
+
throw new Error("Invalid launch request");
|
|
41
|
+
const wrapper = "/opt/litmus/bin/litmus-launcher-shell";
|
|
42
|
+
// Fixed remote adapter; old images keep their ordinary interactive shell.
|
|
43
|
+
return `if test -x ${wrapper}; then exec ${wrapper}${requestId ? ` ${requestId}` : ""}; else cd /home/candidate/workspace && exec bash -l; fi`;
|
|
44
|
+
}
|
|
45
|
+
export async function openTerminal(alias, terminal, requestId) {
|
|
46
|
+
if (!/^litmus-[a-zA-Z0-9-]+$/.test(alias))
|
|
47
|
+
return false;
|
|
48
|
+
const remote = terminalRemoteCommand(requestId);
|
|
49
|
+
const options = ["-t", "-o", "PermitLocalCommand=no"];
|
|
50
|
+
if (configSetsRemoteCommand(alias))
|
|
51
|
+
options.push("-o", "RemoteCommand=none");
|
|
52
|
+
if (process.platform === "darwin") {
|
|
53
|
+
const dir = path.join(os.homedir(), ".litmus", "launchers");
|
|
54
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
55
|
+
const file = path.join(dir, `${alias}.command`);
|
|
56
|
+
writeFileSync(file, `#!/bin/sh\nexec ssh ${options.join(" ")} ${alias} '${remote}'\n`, { mode: 0o700 });
|
|
57
|
+
return spawnDetached("/usr/bin/open", ["-a", terminal, file]);
|
|
58
|
+
}
|
|
59
|
+
if (process.platform === "win32")
|
|
60
|
+
return spawnDetached(terminal, ["new-tab", "ssh", ...options, alias, remote]);
|
|
61
|
+
const flag = terminal.endsWith("gnome-terminal") ? "--" : "-e";
|
|
62
|
+
return spawnDetached(terminal, [flag, "ssh", ...options, alias, remote]);
|
|
63
|
+
}
|
|
64
|
+
/** Isolate existing fatal/exit paths and synchronous probes from the heartbeat process. */
|
|
65
|
+
export function openNativeEditor(tool, token, signal, forkFn = fork, onPrepared, generation) {
|
|
66
|
+
return new Promise(resolve => {
|
|
67
|
+
let result = "action_required";
|
|
68
|
+
let prepared = null;
|
|
69
|
+
let announced = false;
|
|
70
|
+
const env = { ...process.env, LITMUS_ASSESSMENT_TOKEN: token, LITMUS_PORTAL_LAUNCHER_CHILD: "1" };
|
|
71
|
+
delete env.LITMUS_LAUNCH_GENERATION;
|
|
72
|
+
const currentGeneration = parseWorkspaceGeneration(generation);
|
|
73
|
+
if (currentGeneration)
|
|
74
|
+
env.LITMUS_LAUNCH_GENERATION = JSON.stringify(currentGeneration);
|
|
75
|
+
const child = forkFn(new URL("../index.js", import.meta.url), ["connect", "--ide", tool, "--no-skills"], {
|
|
76
|
+
execArgv: [], env,
|
|
77
|
+
stdio: ["ignore", "inherit", "inherit", "ipc"],
|
|
78
|
+
});
|
|
79
|
+
child.on("message", message => {
|
|
80
|
+
if (!message || typeof message !== "object")
|
|
81
|
+
return;
|
|
82
|
+
const value = message;
|
|
83
|
+
if (value.type === "litmus-connect-result" && value.result === "server_detected") {
|
|
84
|
+
result = "dispatched";
|
|
85
|
+
prepared = parsePreparedEditor(value.preparedEditor);
|
|
86
|
+
// The child has verified attachment. Reporting/cleanup can finish after
|
|
87
|
+
// the UI stops saying Launching; neither is part of opening the editor.
|
|
88
|
+
if (!announced) {
|
|
89
|
+
announced = true;
|
|
90
|
+
if (prepared?.tool === tool)
|
|
91
|
+
onPrepared?.(prepared);
|
|
92
|
+
resolve("dispatched");
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
const stop = () => child.kill();
|
|
97
|
+
signal?.addEventListener("abort", stop, { once: true });
|
|
98
|
+
if (signal?.aborted)
|
|
99
|
+
stop();
|
|
100
|
+
const cleanup = () => { clearTimeout(timer); signal?.removeEventListener("abort", stop); };
|
|
101
|
+
const timer = setTimeout(() => { child.kill(); resolve("action_required"); }, 240000);
|
|
102
|
+
child.once("error", () => { cleanup(); resolve("action_required"); });
|
|
103
|
+
child.once("exit", code => {
|
|
104
|
+
cleanup();
|
|
105
|
+
if (!announced && code === 0 && result === "dispatched" && prepared?.tool === tool)
|
|
106
|
+
onPrepared?.(prepared);
|
|
107
|
+
resolve(code === 0 ? result : "action_required");
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
export async function startPortalPreparation(backendUrl, token) {
|
|
112
|
+
const noop = () => Object.assign(async () => { }, { update: (_stage) => { }, fail: (_reason) => { } });
|
|
113
|
+
const report = { tools: [], phase: "connecting" };
|
|
114
|
+
const request = async (route, key, method = "POST") => {
|
|
115
|
+
const response = await fetch(`${backendUrl}/workspace/launcher${route}`, {
|
|
116
|
+
method, redirect: "error", signal: AbortSignal.timeout(10000),
|
|
117
|
+
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json",
|
|
118
|
+
...(key ? { "X-Litmus-Launcher-Key": key } : {}) },
|
|
119
|
+
...(method === "DELETE" ? {} : { body: JSON.stringify(report) }),
|
|
120
|
+
});
|
|
121
|
+
if (!response.ok)
|
|
122
|
+
throw new LauncherRefusal(response.status);
|
|
123
|
+
return response;
|
|
124
|
+
};
|
|
125
|
+
let session;
|
|
126
|
+
try {
|
|
127
|
+
const value = await (await request("/sessions")).json();
|
|
128
|
+
if (!value || typeof value.session_id !== "string" || typeof value.key !== "string")
|
|
129
|
+
return noop();
|
|
130
|
+
session = { session_id: value.session_id, key: value.key, progress_updates: value.progress_updates === true };
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
return noop();
|
|
134
|
+
}
|
|
135
|
+
let stopped = false;
|
|
136
|
+
let pending = Promise.resolve();
|
|
137
|
+
const beat = () => {
|
|
138
|
+
pending = request(`/sessions/${session.session_id}/poll`, session.key)
|
|
139
|
+
.then(() => { }, () => { })
|
|
140
|
+
.finally(() => { if (!stopped)
|
|
141
|
+
timer = setTimeout(beat, 5000); });
|
|
142
|
+
};
|
|
143
|
+
let timer = setTimeout(beat, 5000);
|
|
144
|
+
return Object.assign(async () => {
|
|
145
|
+
stopped = true;
|
|
146
|
+
clearTimeout(timer);
|
|
147
|
+
await pending;
|
|
148
|
+
if (report.stage === "failed") {
|
|
149
|
+
// Leave the fixed failure visible for the remaining short session lease.
|
|
150
|
+
await request(`/sessions/${session.session_id}/poll`, session.key).catch(() => { });
|
|
151
|
+
}
|
|
152
|
+
else
|
|
153
|
+
await request(`/sessions/${session.session_id}`, session.key, "DELETE").catch(() => { });
|
|
154
|
+
}, {
|
|
155
|
+
update: (stage) => { if (session.progress_updates && report.stage !== "failed")
|
|
156
|
+
report.stage = stage; },
|
|
157
|
+
fail: (reason) => {
|
|
158
|
+
if (session.progress_updates && report.stage !== "failed") {
|
|
159
|
+
report.stage = "failed";
|
|
160
|
+
report.failure = reason;
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
export async function runPortalLauncher(options) {
|
|
166
|
+
const abort = new AbortController();
|
|
167
|
+
const stop = () => abort.abort();
|
|
168
|
+
options.signal?.addEventListener("abort", stop, { once: true });
|
|
169
|
+
if (options.signal?.aborted)
|
|
170
|
+
stop();
|
|
171
|
+
process.once("SIGINT", stop);
|
|
172
|
+
process.once("SIGTERM", stop);
|
|
173
|
+
let session = null;
|
|
174
|
+
let installed = discoverInstalledTools();
|
|
175
|
+
let lastDiscovery = Date.now();
|
|
176
|
+
let inventory = JSON.stringify(installed);
|
|
177
|
+
let changedInventory;
|
|
178
|
+
let inventoryPoll;
|
|
179
|
+
// Local discovery stays independent of the idle server long poll.
|
|
180
|
+
const discoveryTimer = setInterval(() => {
|
|
181
|
+
const next = discoverInstalledTools();
|
|
182
|
+
const signature = JSON.stringify(next);
|
|
183
|
+
if (signature !== inventory) {
|
|
184
|
+
inventory = signature;
|
|
185
|
+
changedInventory = next;
|
|
186
|
+
inventoryPoll?.abort();
|
|
187
|
+
}
|
|
188
|
+
}, 5000);
|
|
189
|
+
let seenCommandId = null;
|
|
190
|
+
let longPoll = false;
|
|
191
|
+
let readinessSupported = false;
|
|
192
|
+
let desktopConnectionSetupSupported = false;
|
|
193
|
+
const toolIds = () => [...installed.filter(i => !i.unavailable).map(i => i.tool), ...(options.browserAvailable ? ["browser"] : [])];
|
|
194
|
+
const unavailableTools = () => Object.fromEntries(installed.filter(i => i.unavailable).map(i => [i.tool, i.unavailable === "desktop_setup_failed" && !desktopConnectionSetupSupported ? "workspace_not_ready" : i.unavailable]));
|
|
195
|
+
async function call(route, body, method = "POST", polling = false) {
|
|
196
|
+
const response = await fetch(`${options.backendUrl}/workspace/launcher${route}`, {
|
|
197
|
+
method, headers: { Authorization: `Bearer ${options.token}`, "Content-Type": "application/json",
|
|
198
|
+
...(session ? { "X-Litmus-Launcher-Key": session.key } : {}) },
|
|
199
|
+
...(body === undefined ? {} : { body: JSON.stringify(body) }), signal: polling ? AbortSignal.any([abort.signal, inventoryPoll.signal, AbortSignal.timeout(35000)]) : AbortSignal.timeout(10000),
|
|
200
|
+
redirect: "error",
|
|
201
|
+
});
|
|
202
|
+
if (!response.ok) {
|
|
203
|
+
// Only the server's fixed health-pending refusal is recoverable. A
|
|
204
|
+
// replaced/revoked session can also be 409 and must still stop here.
|
|
205
|
+
const detail = [403, 409].includes(response.status) ? await response.json().catch(() => null) : null;
|
|
206
|
+
throw new LauncherRefusal(response.status, detail?.detail?.code === "workspace_not_ready", detail?.detail?.code);
|
|
207
|
+
}
|
|
208
|
+
return await response.json();
|
|
209
|
+
}
|
|
210
|
+
const wait = options.wait ?? ((ms, signal) => new Promise(resolve => {
|
|
211
|
+
const done = () => { clearTimeout(timer); signal.removeEventListener("abort", done); resolve(); };
|
|
212
|
+
const timer = setTimeout(done, ms);
|
|
213
|
+
signal.addEventListener("abort", done, { once: true });
|
|
214
|
+
if (signal.aborted)
|
|
215
|
+
done();
|
|
216
|
+
}));
|
|
217
|
+
try {
|
|
218
|
+
let registered;
|
|
219
|
+
try {
|
|
220
|
+
registered = await call("/sessions", { tools: [], phase: "connecting" });
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
if (!(error instanceof LauncherRefusal) || !([404, 405].includes(error.status) || (error.status === 403 && error.code === "launcher_beta_unavailable")))
|
|
224
|
+
throw error;
|
|
225
|
+
// CLI and backend releases are independent. The prepared SSH alias is
|
|
226
|
+
// usable even when the backend predates the portal launcher.
|
|
227
|
+
console.log("Tool launching is unavailable on this deployment. Open your assessment page or connect directly:");
|
|
228
|
+
console.log(` ${options.pageUrl}\n ssh ${options.alias}`);
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
session = registered;
|
|
232
|
+
readinessSupported = registered.tool_readiness === true;
|
|
233
|
+
desktopConnectionSetupSupported = registered.desktop_connection_setup === true;
|
|
234
|
+
if (options.prepareTools && registered.progress_updates) {
|
|
235
|
+
await call(`/sessions/${session.session_id}/poll`, { tools: [], phase: "connecting", stage: "checking_tools" }).catch(() => { });
|
|
236
|
+
}
|
|
237
|
+
if (options.prepareTools) {
|
|
238
|
+
// Preparing a matching editor server may outlast the initial mailbox
|
|
239
|
+
// lease. Renew as connecting, without claiming readiness or starting time.
|
|
240
|
+
// Drain any in-flight renewal before the first ready poll, so a delayed
|
|
241
|
+
// response cannot put a connected laptop back into preparation.
|
|
242
|
+
let preparationEnded = false;
|
|
243
|
+
let pendingRenewal;
|
|
244
|
+
let renewalTimer;
|
|
245
|
+
const renewPreparation = () => {
|
|
246
|
+
if (preparationEnded || abort.signal.aborted)
|
|
247
|
+
return;
|
|
248
|
+
pendingRenewal = call(`/sessions/${session.session_id}/poll`, {
|
|
249
|
+
tools: [], phase: "connecting", ...(registered.progress_updates ? { stage: "checking_tools" } : {}),
|
|
250
|
+
}).then(() => { }, () => { }).finally(() => {
|
|
251
|
+
if (!preparationEnded && !abort.signal.aborted)
|
|
252
|
+
renewalTimer = setTimeout(renewPreparation, 15000);
|
|
253
|
+
});
|
|
254
|
+
};
|
|
255
|
+
renewalTimer = setTimeout(renewPreparation, 15000);
|
|
256
|
+
try {
|
|
257
|
+
installed = await options.prepareTools(installed, abort.signal);
|
|
258
|
+
}
|
|
259
|
+
finally {
|
|
260
|
+
preparationEnded = true;
|
|
261
|
+
clearTimeout(renewalTimer);
|
|
262
|
+
await pendingRenewal;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
lastDiscovery = Date.now();
|
|
266
|
+
if (abort.signal.aborted)
|
|
267
|
+
return;
|
|
268
|
+
let readyAcknowledged = false;
|
|
269
|
+
// The healthy host report can trail a working SSH connection by 60s.
|
|
270
|
+
let readinessDeadline = Date.now() + 120000;
|
|
271
|
+
let readinessFailures = 0;
|
|
272
|
+
let failures = 0;
|
|
273
|
+
const seenCommands = new Set();
|
|
274
|
+
while (!abort.signal.aborted) {
|
|
275
|
+
if (changedInventory || Date.now() - lastDiscovery >= 30000) {
|
|
276
|
+
installed = changedInventory ?? discoverInstalledTools();
|
|
277
|
+
changedInventory = undefined;
|
|
278
|
+
if (options.prepareTools)
|
|
279
|
+
installed = await options.prepareTools(installed, abort.signal);
|
|
280
|
+
lastDiscovery = Date.now();
|
|
281
|
+
}
|
|
282
|
+
let command;
|
|
283
|
+
try {
|
|
284
|
+
// End the wait in time for the next installation inventory refresh.
|
|
285
|
+
const waitSeconds = Math.min(25, Math.max(1, Math.ceil((30000 - (Date.now() - lastDiscovery)) / 1000)));
|
|
286
|
+
const query = new URLSearchParams({ wait_seconds: String(readyAcknowledged ? waitSeconds : 0) });
|
|
287
|
+
if (seenCommandId)
|
|
288
|
+
query.set("seen_command_id", seenCommandId);
|
|
289
|
+
inventoryPoll = new AbortController();
|
|
290
|
+
const reply = await call(`/sessions/${registered.session_id}/poll?${query}`, { tools: toolIds(), phase: "ready", ...(readinessSupported ? { unavailable: unavailableTools() } : {}) }, "POST", true);
|
|
291
|
+
longPoll = reply.long_poll === true;
|
|
292
|
+
command = reply.command;
|
|
293
|
+
failures = 0;
|
|
294
|
+
readinessFailures = 0;
|
|
295
|
+
readinessDeadline = 0;
|
|
296
|
+
}
|
|
297
|
+
catch (error) {
|
|
298
|
+
if (abort.signal.aborted)
|
|
299
|
+
break;
|
|
300
|
+
if (inventoryPoll?.signal.aborted && changedInventory)
|
|
301
|
+
continue;
|
|
302
|
+
if (error instanceof LauncherRefusal && error.readinessPending) {
|
|
303
|
+
// A later host-report gap gets its own bounded recovery window;
|
|
304
|
+
// it must not disconnect an already acknowledged laptop after five polls.
|
|
305
|
+
if (!readinessDeadline)
|
|
306
|
+
readinessDeadline = Date.now() + 120000;
|
|
307
|
+
const remaining = readinessDeadline - Date.now();
|
|
308
|
+
if (remaining <= 0)
|
|
309
|
+
throw error;
|
|
310
|
+
// Health-pending responses renew the authenticated session lease;
|
|
311
|
+
// they do not spend the separate transport failure allowance.
|
|
312
|
+
await wait(Math.min(++readinessFailures * 2000, 10000, remaining), abort.signal);
|
|
313
|
+
continue;
|
|
314
|
+
}
|
|
315
|
+
// Do not re-register: replacing a session could replay an uncertain launch.
|
|
316
|
+
if (permanentLauncherFailure(error) || ++failures > 5)
|
|
317
|
+
throw error;
|
|
318
|
+
await wait(Math.min(failures * 2000, 10000), abort.signal);
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
if (abort.signal.aborted)
|
|
322
|
+
break;
|
|
323
|
+
if (!readyAcknowledged) {
|
|
324
|
+
// Registration/preparation is not readiness. Publish success (including
|
|
325
|
+
// daemon handoff) only after the authenticated ready poll is accepted.
|
|
326
|
+
readyAcknowledged = true;
|
|
327
|
+
console.log("\nYour tool launcher is ready. Open tools from your assessment page.");
|
|
328
|
+
console.log(` ${options.pageUrl}`);
|
|
329
|
+
options.onReady?.();
|
|
330
|
+
await options.openUrl(options.pageUrl);
|
|
331
|
+
}
|
|
332
|
+
if (command && !seenCommands.has(command.id)) {
|
|
333
|
+
// A poll can redeliver an opening command after its response was lost.
|
|
334
|
+
// Record before launching, including while result delivery retries.
|
|
335
|
+
seenCommands.add(command.id);
|
|
336
|
+
seenCommandId = command.id;
|
|
337
|
+
void (async () => {
|
|
338
|
+
let status = "failed";
|
|
339
|
+
if (toolIds().includes(command.tool)) {
|
|
340
|
+
try {
|
|
341
|
+
status = await options.launch(command.tool, installed, abort.signal, { requestId: command.id, ...(command.generation ? { generation: command.generation } : {}) });
|
|
342
|
+
}
|
|
343
|
+
catch { /* fixed failure */ }
|
|
344
|
+
}
|
|
345
|
+
if (abort.signal.aborted)
|
|
346
|
+
return;
|
|
347
|
+
// Deliver the same result again after transport errors; never execute
|
|
348
|
+
// the tool again merely because its acknowledgement was lost.
|
|
349
|
+
// Polling owns the session's lifetime. Cap the delay, not attempts:
|
|
350
|
+
// retain the result until acknowledged, permanently refused or stopped.
|
|
351
|
+
for (let attempt = 0; !abort.signal.aborted; attempt++) {
|
|
352
|
+
try {
|
|
353
|
+
await call(`/sessions/${registered.session_id}/results/${command.id}`, { status });
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
catch (error) {
|
|
357
|
+
if (permanentLauncherFailure(error)) {
|
|
358
|
+
console.error("Launch result could not be delivered. Check the tool before opening it again.");
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
await wait(Math.min((attempt + 1) * 2000, 10000), abort.signal);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
})();
|
|
365
|
+
}
|
|
366
|
+
// Old backends ignore the query parameters. Preserve their polling rate.
|
|
367
|
+
if (!longPoll)
|
|
368
|
+
await wait(5000, abort.signal);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
finally {
|
|
372
|
+
clearInterval(discoveryTimer);
|
|
373
|
+
abort.abort();
|
|
374
|
+
if (session)
|
|
375
|
+
await call(`/sessions/${session.session_id}`, undefined, "DELETE").catch(() => { });
|
|
376
|
+
options.signal?.removeEventListener("abort", stop);
|
|
377
|
+
process.off("SIGINT", stop);
|
|
378
|
+
process.off("SIGTERM", stop);
|
|
379
|
+
// Session replacement, auth failures and offline time are not submission.
|
|
380
|
+
// Only a positive server acknowledgement permits local connection cleanup.
|
|
381
|
+
if (session && options.onSubmitted) {
|
|
382
|
+
try {
|
|
383
|
+
if (await fetchSubmissionSaved(options.backendUrl, options.token, 5000))
|
|
384
|
+
await options.onSubmitted();
|
|
385
|
+
}
|
|
386
|
+
catch { /* Leave settings intact when submission cannot be verified. */ }
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
/** Observe the OS opener's exit status; spawning it alone does not prove dispatch. */
|
|
391
|
+
export function openDesktop(app, alias, signal, platform = process.platform, spawnFn = spawn) {
|
|
392
|
+
if (app.tool !== "codex" && app.tool !== "claude")
|
|
393
|
+
return Promise.resolve(false);
|
|
394
|
+
const url = desktopUrl(app.tool, alias);
|
|
395
|
+
const command = platform === "darwin" ? "/usr/bin/open" : platform === "win32" ? "rundll32.exe" : "xdg-open";
|
|
396
|
+
const args = platform === "darwin" ? ["-a", app.command, url] : platform === "win32" ? ["url.dll,FileProtocolHandler", url] : [url];
|
|
397
|
+
return new Promise(resolve => {
|
|
398
|
+
try {
|
|
399
|
+
const child = spawnFn(command, args, { stdio: "ignore", windowsHide: true, signal, timeout: 10000 });
|
|
400
|
+
child.once("error", () => resolve(false));
|
|
401
|
+
child.once("exit", code => resolve(code === 0));
|
|
402
|
+
}
|
|
403
|
+
catch {
|
|
404
|
+
resolve(false);
|
|
405
|
+
}
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
//# sourceMappingURL=portal-launcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"portal-launcher.js","sourceRoot":"","sources":["../../src/lib/portal-launcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { desktopRuntimeReady, type DesktopApp } from "./desktop-readiness.js";
|
|
2
|
+
/** A short-lived capability result, never a replacement for mailbox authorization. */
|
|
3
|
+
export declare function createPreparedDesktopReadiness(alias: string, probe?: typeof desktopRuntimeReady, now?: () => number, maxAgeMs?: number): {
|
|
4
|
+
invalidate(): void;
|
|
5
|
+
check(app: DesktopApp, command: string, generationValue: unknown, signal: AbortSignal): Promise<boolean>;
|
|
6
|
+
};
|
|
7
|
+
//# sourceMappingURL=prepared-desktop.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prepared-desktop.d.ts","sourceRoot":"","sources":["../../src/lib/prepared-desktop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,KAAK,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAG7E,sFAAsF;AACtF,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,MAAM,EACb,KAAK,6BAAsB,EAC3B,GAAG,eAAW,EACd,QAAQ,SAAS;IAMf,UAAU;IACJ,KAAK,MAAM,UAAU,WAAW,MAAM,mBAAmB,OAAO,UAAU,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;EAgBjH"}
|