zcode-acp-server 0.23.0 → 0.25.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/assets/martty-plugins/quota-dock/plugin.json +14 -0
- package/dist/config/options.d.ts +5 -2
- package/dist/config/options.d.ts.map +1 -1
- package/dist/config/options.js +39 -7
- package/dist/config/options.js.map +1 -1
- package/dist/handlers/dispatch.js +2 -2
- package/dist/handlers/dispatch.js.map +1 -1
- package/dist/handlers/extensions.js +2 -2
- package/dist/handlers/extensions.js.map +1 -1
- package/dist/handlers/server-requests.js +2 -2
- package/dist/handlers/server-requests.js.map +1 -1
- package/dist/handlers/session.d.ts.map +1 -1
- package/dist/handlers/session.js +66 -6
- package/dist/handlers/session.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/quota/format.d.ts +11 -0
- package/dist/quota/format.d.ts.map +1 -1
- package/dist/quota/format.js +43 -0
- package/dist/quota/format.js.map +1 -1
- package/dist/quota/live.d.ts +30 -0
- package/dist/quota/live.d.ts.map +1 -0
- package/dist/quota/live.js +144 -0
- package/dist/quota/live.js.map +1 -0
- package/dist/remote/hub-server.d.ts +22 -0
- package/dist/remote/hub-server.d.ts.map +1 -1
- package/dist/remote/hub-server.js +155 -8
- package/dist/remote/hub-server.js.map +1 -1
- package/dist/server.d.ts +21 -2
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +27 -4
- package/dist/server.js.map +1 -1
- package/dist/tui.d.ts +26 -0
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +80 -1
- package/dist/tui.js.map +1 -1
- package/docs/REMOTE-CLIENTS.md +6 -1
- package/package.json +2 -1
package/dist/quota/format.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/quota/format.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/quota/format.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quota dock refresher (ADR-0021) — keeps the Martty TUI's resident quota line
|
|
3
|
+
* up to date.
|
|
4
|
+
*
|
|
5
|
+
* A lazy process-wide singleton: started on first martty session activity, it
|
|
6
|
+
* refreshes every 60s and on every forceRefresh() (wired at turn end). Each
|
|
7
|
+
* successful refresh stores the formatted string on `server.quotaDock` and
|
|
8
|
+
* pushes a `config_option_update` (full options array — martty's subscribe is
|
|
9
|
+
* full-replace semantics) to the martty connections only.
|
|
10
|
+
*
|
|
11
|
+
* Cross-process sharing is hub-first: when the remote hub is reachable, its
|
|
12
|
+
* cached /api/quota/dock endpoint serves the string (~500ms budget); any
|
|
13
|
+
* failure falls back silently to a direct queryQuota() — the fallback is the
|
|
14
|
+
* normal path for local-only users (the hub is opt-in and idle-exits).
|
|
15
|
+
*/
|
|
16
|
+
import type { ZcodeAcpServer } from "../server.js";
|
|
17
|
+
/** Interval between background refreshes. */
|
|
18
|
+
export declare const QUOTA_REFRESH_INTERVAL_MS = 60000;
|
|
19
|
+
/**
|
|
20
|
+
* Start the refresher (idempotent). No-op unless a martty client has been
|
|
21
|
+
* seen — editor-only setups never poll the quota API in the background.
|
|
22
|
+
*/
|
|
23
|
+
export declare function startQuotaRefresher(server: ZcodeAcpServer): void;
|
|
24
|
+
/** Best-effort immediate refresh (called at every turn end). Never rejects. */
|
|
25
|
+
export declare function forceRefreshQuota(): Promise<void>;
|
|
26
|
+
/** Stop and forget the singleton (test helper). */
|
|
27
|
+
export declare function resetQuotaRefresherForTest(): void;
|
|
28
|
+
/** Hub-first dock string, falling back to a direct query. */
|
|
29
|
+
export declare function fetchDockText(env?: NodeJS.ProcessEnv): Promise<string | null>;
|
|
30
|
+
//# sourceMappingURL=live.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../src/quota/live.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAOH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAKnD,6CAA6C;AAC7C,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAahD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAUhE;AAED,+EAA+E;AAC/E,wBAAgB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAGjD;AAED,mDAAmD;AACnD,wBAAgB,0BAA0B,IAAI,IAAI,CAGjD;AAuBD,6DAA6D;AAC7D,wBAAsB,aAAa,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAkBhG"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quota dock refresher (ADR-0021) — keeps the Martty TUI's resident quota line
|
|
3
|
+
* up to date.
|
|
4
|
+
*
|
|
5
|
+
* A lazy process-wide singleton: started on first martty session activity, it
|
|
6
|
+
* refreshes every 60s and on every forceRefresh() (wired at turn end). Each
|
|
7
|
+
* successful refresh stores the formatted string on `server.quotaDock` and
|
|
8
|
+
* pushes a `config_option_update` (full options array — martty's subscribe is
|
|
9
|
+
* full-replace semantics) to the martty connections only.
|
|
10
|
+
*
|
|
11
|
+
* Cross-process sharing is hub-first: when the remote hub is reachable, its
|
|
12
|
+
* cached /api/quota/dock endpoint serves the string (~500ms budget); any
|
|
13
|
+
* failure falls back silently to a direct queryQuota() — the fallback is the
|
|
14
|
+
* normal path for local-only users (the hub is opt-in and idle-exits).
|
|
15
|
+
*/
|
|
16
|
+
import { buildConfigOptions } from "../config/options.js";
|
|
17
|
+
import { parseRemoteConfig } from "../remote/config.js";
|
|
18
|
+
import { log, warn } from "../utils.js";
|
|
19
|
+
import { enqueueSessionSend } from "../handlers/io.js";
|
|
20
|
+
import { formatQuotaDock } from "./format.js";
|
|
21
|
+
import { queryQuota } from "./index.js";
|
|
22
|
+
/** Interval between background refreshes. */
|
|
23
|
+
export const QUOTA_REFRESH_INTERVAL_MS = 60_000;
|
|
24
|
+
/** Budget for the hub-first lookup before falling back to a direct query. */
|
|
25
|
+
const HUB_TIMEOUT_MS = 500;
|
|
26
|
+
let state = null;
|
|
27
|
+
/**
|
|
28
|
+
* Start the refresher (idempotent). No-op unless a martty client has been
|
|
29
|
+
* seen — editor-only setups never poll the quota API in the background.
|
|
30
|
+
*/
|
|
31
|
+
export function startQuotaRefresher(server) {
|
|
32
|
+
if (state || !server.marttyClientSeen)
|
|
33
|
+
return;
|
|
34
|
+
const entry = {
|
|
35
|
+
server,
|
|
36
|
+
timer: setInterval(() => void refresh(entry), QUOTA_REFRESH_INTERVAL_MS),
|
|
37
|
+
inFlight: null,
|
|
38
|
+
};
|
|
39
|
+
entry.timer.unref?.();
|
|
40
|
+
state = entry;
|
|
41
|
+
void refresh(entry);
|
|
42
|
+
}
|
|
43
|
+
/** Best-effort immediate refresh (called at every turn end). Never rejects. */
|
|
44
|
+
export function forceRefreshQuota() {
|
|
45
|
+
if (!state)
|
|
46
|
+
return Promise.resolve();
|
|
47
|
+
return refresh(state);
|
|
48
|
+
}
|
|
49
|
+
/** Stop and forget the singleton (test helper). */
|
|
50
|
+
export function resetQuotaRefresherForTest() {
|
|
51
|
+
if (state)
|
|
52
|
+
clearInterval(state.timer);
|
|
53
|
+
state = null;
|
|
54
|
+
}
|
|
55
|
+
async function refresh(entry) {
|
|
56
|
+
if (entry.inFlight)
|
|
57
|
+
return entry.inFlight;
|
|
58
|
+
entry.inFlight = runRefresh(entry.server)
|
|
59
|
+
.catch((e) => {
|
|
60
|
+
log(`quota-dock: refresh failed (${e instanceof Error ? e.message : String(e)})`);
|
|
61
|
+
})
|
|
62
|
+
.finally(() => {
|
|
63
|
+
entry.inFlight = null;
|
|
64
|
+
});
|
|
65
|
+
return entry.inFlight;
|
|
66
|
+
}
|
|
67
|
+
async function runRefresh(server) {
|
|
68
|
+
const text = await fetchDockText();
|
|
69
|
+
const prev = server.quotaDock;
|
|
70
|
+
server.quotaDock = text;
|
|
71
|
+
// ADR-0021: on failure/no-data the dock hides — no update is emitted.
|
|
72
|
+
if (text === null || text === prev)
|
|
73
|
+
return;
|
|
74
|
+
await emitQuotaOptions(server);
|
|
75
|
+
}
|
|
76
|
+
/** Hub-first dock string, falling back to a direct query. */
|
|
77
|
+
export async function fetchDockText(env = process.env) {
|
|
78
|
+
const remote = parseRemoteConfig(env);
|
|
79
|
+
if (remote) {
|
|
80
|
+
try {
|
|
81
|
+
const resp = await fetch(`http://${remote.hubHost}:${remote.hubPort}/api/quota/dock`, {
|
|
82
|
+
headers: { Authorization: `Bearer ${remote.token}` },
|
|
83
|
+
signal: AbortSignal.timeout(HUB_TIMEOUT_MS),
|
|
84
|
+
});
|
|
85
|
+
if (resp.ok) {
|
|
86
|
+
const body = (await resp.json());
|
|
87
|
+
if (body.formatted === null)
|
|
88
|
+
return null;
|
|
89
|
+
if (typeof body.formatted === "string")
|
|
90
|
+
return body.formatted;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// hub absent/restarting — silent fallback below
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return formatQuotaDock(await queryQuota());
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Push a `config_option_update` carrying the full options array (quota
|
|
101
|
+
* included) to every martty connection, for every live session alias. Other
|
|
102
|
+
* clients are untouched — the quota option is martty-only by contract.
|
|
103
|
+
*/
|
|
104
|
+
async function emitQuotaOptions(server) {
|
|
105
|
+
if (server.marttyConnectionRoots.size === 0)
|
|
106
|
+
return;
|
|
107
|
+
const targets = server.clients
|
|
108
|
+
.snapshot()
|
|
109
|
+
.filter((cx) => server.marttyConnectionRoots.has(connectionRootOf(cx)));
|
|
110
|
+
if (targets.length === 0)
|
|
111
|
+
return;
|
|
112
|
+
// Build the options once per zcode session (aliases share the same list).
|
|
113
|
+
const byZcodeSid = new Map();
|
|
114
|
+
const emitFor = async (acpSid) => {
|
|
115
|
+
const zcodeSid = server.resolveSid(acpSid) ?? null;
|
|
116
|
+
let options = byZcodeSid.get(zcodeSid);
|
|
117
|
+
if (!options) {
|
|
118
|
+
// All targets are martty connections by construction — any target's
|
|
119
|
+
// root unlocks the quota pseudo-option for the shared options array.
|
|
120
|
+
options = await buildConfigOptions(server, zcodeSid, connectionRootOf(targets[0]));
|
|
121
|
+
byZcodeSid.set(zcodeSid, options);
|
|
122
|
+
}
|
|
123
|
+
await enqueueSessionSend(acpSid, async () => {
|
|
124
|
+
const results = await Promise.allSettled(targets.map((cx) => cx.notify("session/update", {
|
|
125
|
+
sessionId: acpSid,
|
|
126
|
+
update: { sessionUpdate: "config_option_update", configOptions: options },
|
|
127
|
+
})));
|
|
128
|
+
for (const r of results) {
|
|
129
|
+
if (r.status === "rejected") {
|
|
130
|
+
warn(`quota-dock: config_option_update failed on one client: ` +
|
|
131
|
+
`${r.reason instanceof Error ? r.reason.message : String(r.reason)}`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
};
|
|
136
|
+
const acpSids = [...server.sessionMap.keys(), ...server.pendingSessions.keys()];
|
|
137
|
+
for (const acpSid of acpSids)
|
|
138
|
+
await emitFor(acpSid);
|
|
139
|
+
}
|
|
140
|
+
/** clientConnectionRoot equivalent for a raw ClientLike (see utils.ts). */
|
|
141
|
+
function connectionRootOf(cx) {
|
|
142
|
+
return cx.connectionContext;
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=live.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"live.js","sourceRoot":"","sources":["../../src/quota/live.ts"],"names":[],"mappings":"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"}
|
|
@@ -127,8 +127,30 @@ export declare function resolveTerminalLaunch(env: NodeJS.ProcessEnv, prefs?: Te
|
|
|
127
127
|
* values are single-quoted.
|
|
128
128
|
*/
|
|
129
129
|
export declare function terminalTuiScript(cwd: string, cliJs: string, env: NodeJS.ProcessEnv): string;
|
|
130
|
+
/**
|
|
131
|
+
* Write the throwaway .command script for a terminal TUI incubation.
|
|
132
|
+
*
|
|
133
|
+
* Preferred location: `<workspace>/.zcode/tmp/tui-XXXX.command`. Terminal apps
|
|
134
|
+
* bind the new tab's project root to the script's PARENT directory (Warp's
|
|
135
|
+
* open_file opens a session in the file's dir before executing it), so a
|
|
136
|
+
* tmpdir script leaves the tab bound to a throwaway directory — the in-script
|
|
137
|
+
* `cd` only moves the shell cwd and never re-binds the terminal project, which
|
|
138
|
+
* blinds diff/git panels. Any failure writing there (read-only workspace,
|
|
139
|
+
* permissions, …) falls back to the historical mkdtemp(tmpdir()) path.
|
|
140
|
+
*/
|
|
141
|
+
export declare function writeTuiScript(workspace: string, cliJs: string, env: NodeJS.ProcessEnv): string;
|
|
130
142
|
/** Reset the quota cache (test helper). */
|
|
131
143
|
export declare function resetQuotaCacheForTest(): void;
|
|
144
|
+
/** Reset the dock cache (test helper). */
|
|
145
|
+
export declare function resetDockCacheForTest(): void;
|
|
146
|
+
/**
|
|
147
|
+
* Tab-title sanitizer: the value is printf'd into the terminal as an OSC
|
|
148
|
+
* payload, so control characters (an ESC inside a model-generated summary
|
|
149
|
+
* would inject terminal sequences) become spaces, whitespace collapses, and
|
|
150
|
+
* the length caps at what a tab can usefully show. Empty/non-string →
|
|
151
|
+
* undefined (the caller falls back to the project name).
|
|
152
|
+
*/
|
|
153
|
+
export declare function sanitizeTabTitle(v: unknown): string | undefined;
|
|
132
154
|
/**
|
|
133
155
|
* Start the hub. Resolves once listening; rejects on bind failure (including
|
|
134
156
|
* EADDRINUSE when another hub already owns the port).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hub-server.d.ts","sourceRoot":"","sources":["../../src/remote/hub-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"hub-server.d.ts","sourceRoot":"","sources":["../../src/remote/hub-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAiC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAQ9D,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,kFAAkF;IAClF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gFAAgF;IAChF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB;;;;OAIG;IACH,SAAS,CAAC,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACrD;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE;QAClB,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;QACvB,sFAAsF;QACtF,IAAI,EAAE,KAAK,GAAG,OAAO,CAAC;KACvB,KAAK,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CAC5C;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAsID,sEAAsE;AACtE,MAAM,MAAM,cAAc;AACxB;uEACuE;AACrE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE;AACpC,6EAA6E;GAC3E;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE;AAClC;kEACkE;GAChE;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE;AACtD;;;;kEAIkE;GAChE;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AA2BrD;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,KAAK,GAAE,aAAwC,GAC9C;IACD,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAUA;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAqB5F;AAKD;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CA+B/F;AA2JD,2CAA2C;AAC3C,wBAAgB,sBAAsB,IAAI,IAAI,CAG7C;AAsBD,0CAA0C;AAC1C,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAmCD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAQ/D;AAyID;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG;IAAE,UAAU,CAAC,EAAE,MAAM,IAAI,CAAA;CAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CA83B9F"}
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
*/
|
|
25
25
|
import { spawn } from "node:child_process";
|
|
26
26
|
import { createHash, randomUUID, timingSafeEqual } from "node:crypto";
|
|
27
|
-
import { chmodSync, mkdtempSync, realpathSync, writeFileSync } from "node:fs";
|
|
27
|
+
import { chmodSync, mkdirSync, mkdtempSync, readdirSync, realpathSync, statSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
28
28
|
import { readdir, readFile, stat } from "node:fs/promises";
|
|
29
29
|
import { createServer, get as httpGet, request as httpRequest, } from "node:http";
|
|
30
30
|
import { EventEmitter } from "node:events";
|
|
@@ -38,6 +38,8 @@ import { AGENT_INFO, compareVersions, log, warn } from "../utils.js";
|
|
|
38
38
|
import { remoteTerminalPrefs } from "./config.js";
|
|
39
39
|
import { accountUsageStats } from "../handlers/account.js";
|
|
40
40
|
import { BOOT_RESUME_TRIGGER } from "../handlers/session.js";
|
|
41
|
+
import { formatQuotaDock } from "../quota/format.js";
|
|
42
|
+
import { queryQuota } from "../quota/index.js";
|
|
41
43
|
import { listKnownWorkspaces } from "../tasks-index.js";
|
|
42
44
|
const HEARTBEAT_TIMEOUT_MS = 30_000;
|
|
43
45
|
const IDLE_EXIT_MS = 10 * 60_000;
|
|
@@ -199,10 +201,64 @@ export function terminalTuiScript(cwd, cliJs, env) {
|
|
|
199
201
|
`# Hub-incubated TUI session (ADR-0016): closing this window ends the bridge.`,
|
|
200
202
|
`cd ${shQuote(cwd)} || exit 1`,
|
|
201
203
|
...exports,
|
|
204
|
+
// OSC 0 names the tab after the conversation — without it terminals show
|
|
205
|
+
// the running process ("node"). printf reads the \033/\007 escapes from
|
|
206
|
+
// the format string; %s keeps the value itself shell-safe. martty never
|
|
207
|
+
// sets a terminal title, so this survives until the window closes.
|
|
208
|
+
...(env.ZCODE_ACP_TAB_TITLE !== undefined
|
|
209
|
+
? [`printf '\\033]0;%s\\007' "$ZCODE_ACP_TAB_TITLE"`]
|
|
210
|
+
: []),
|
|
202
211
|
`exec ${shQuote(process.execPath)} ${shQuote(cliJs)}`,
|
|
203
212
|
"",
|
|
204
213
|
].join("\n");
|
|
205
214
|
}
|
|
215
|
+
/** Stale TUI scripts older than this are swept on the next incubation. */
|
|
216
|
+
const TUI_SCRIPT_MAX_AGE_MS = 60 * 60 * 1000;
|
|
217
|
+
/**
|
|
218
|
+
* Write the throwaway .command script for a terminal TUI incubation.
|
|
219
|
+
*
|
|
220
|
+
* Preferred location: `<workspace>/.zcode/tmp/tui-XXXX.command`. Terminal apps
|
|
221
|
+
* bind the new tab's project root to the script's PARENT directory (Warp's
|
|
222
|
+
* open_file opens a session in the file's dir before executing it), so a
|
|
223
|
+
* tmpdir script leaves the tab bound to a throwaway directory — the in-script
|
|
224
|
+
* `cd` only moves the shell cwd and never re-binds the terminal project, which
|
|
225
|
+
* blinds diff/git panels. Any failure writing there (read-only workspace,
|
|
226
|
+
* permissions, …) falls back to the historical mkdtemp(tmpdir()) path.
|
|
227
|
+
*/
|
|
228
|
+
export function writeTuiScript(workspace, cliJs, env) {
|
|
229
|
+
const contents = terminalTuiScript(workspace, cliJs, env);
|
|
230
|
+
const dir = path.join(workspace, ".zcode", "tmp");
|
|
231
|
+
try {
|
|
232
|
+
mkdirSync(dir, { recursive: true });
|
|
233
|
+
// Best-effort sweep of stale scripts (>1h old): an unlinked-but-running
|
|
234
|
+
// script keeps executing on unix, and a fresh one may back a live
|
|
235
|
+
// incubation, so only clearly-stale files go.
|
|
236
|
+
const cutoff = Date.now() - TUI_SCRIPT_MAX_AGE_MS;
|
|
237
|
+
for (const entry of readdirSync(dir)) {
|
|
238
|
+
if (!entry.startsWith("tui-") || !entry.endsWith(".command"))
|
|
239
|
+
continue;
|
|
240
|
+
const stale = path.join(dir, entry);
|
|
241
|
+
try {
|
|
242
|
+
if (statSync(stale).mtimeMs < cutoff)
|
|
243
|
+
unlinkSync(stale);
|
|
244
|
+
}
|
|
245
|
+
catch {
|
|
246
|
+
// best-effort — a racing removal must not abort the incubation
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
const script = path.join(dir, `tui-${randomUUID().slice(0, 8)}.command`);
|
|
250
|
+
writeFileSync(script, contents, { mode: 0o700 });
|
|
251
|
+
chmodSync(script, 0o700);
|
|
252
|
+
return script;
|
|
253
|
+
}
|
|
254
|
+
catch (e) {
|
|
255
|
+
warn(`hub: cannot place the TUI script in ${dir} (${e instanceof Error ? e.message : String(e)}) — using the system tmpdir`);
|
|
256
|
+
}
|
|
257
|
+
const fallback = path.join(mkdtempSync(path.join(tmpdir(), "zcode-acp-term-")), "tui.command");
|
|
258
|
+
writeFileSync(fallback, contents, { mode: 0o700 });
|
|
259
|
+
chmodSync(fallback, 0o700);
|
|
260
|
+
return fallback;
|
|
261
|
+
}
|
|
206
262
|
/**
|
|
207
263
|
* Spawn session-create as a VISIBLE interactive TUI (ADR-0016): write a
|
|
208
264
|
* throwaway .command script (`cd <project> && exec node cli.js`) and hand it
|
|
@@ -226,9 +282,7 @@ async function spawnTerminalTui(opts) {
|
|
|
226
282
|
if (!remoteTerminalPrefs(process.env).enabled)
|
|
227
283
|
return null;
|
|
228
284
|
const cliJs = fileURLToPath(new URL("../cli.js", import.meta.url));
|
|
229
|
-
const script =
|
|
230
|
-
writeFileSync(script, terminalTuiScript(opts.cwd, cliJs, opts.env), { mode: 0o700 });
|
|
231
|
-
chmodSync(script, 0o700);
|
|
285
|
+
const script = writeTuiScript(opts.cwd, cliJs, opts.env);
|
|
232
286
|
const { launch, warning } = resolveTerminalLaunch(process.env);
|
|
233
287
|
if (warning)
|
|
234
288
|
warn(`hub: ${warning}`);
|
|
@@ -354,6 +408,28 @@ export function resetQuotaCacheForTest() {
|
|
|
354
408
|
quotaCache = null;
|
|
355
409
|
quotaInflight = null;
|
|
356
410
|
}
|
|
411
|
+
/**
|
|
412
|
+
* Cached dock string for GET /api/quota/dock (ADR-0021) — the compact one-line
|
|
413
|
+
* quota format consumed by the Martty TUI refresher. Shorter TTL than
|
|
414
|
+
* /api/quota (15s): the dock is resident UI, freshness beats upstream load.
|
|
415
|
+
* `formatted: null` (no data) is cached too, so a credentials-less machine
|
|
416
|
+
* does not hammer the API on every 60s refresh.
|
|
417
|
+
*/
|
|
418
|
+
const DOCK_TTL_MS = 15_000;
|
|
419
|
+
let dockCache = null;
|
|
420
|
+
function getQuotaDock() {
|
|
421
|
+
if (dockCache && Date.now() - dockCache.at < DOCK_TTL_MS) {
|
|
422
|
+
return Promise.resolve({ formatted: dockCache.formatted, fetchedAt: dockCache.at });
|
|
423
|
+
}
|
|
424
|
+
return queryQuota().then((result) => {
|
|
425
|
+
dockCache = { formatted: formatQuotaDock(result), at: Date.now() };
|
|
426
|
+
return { formatted: dockCache.formatted, fetchedAt: dockCache.at };
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
/** Reset the dock cache (test helper). */
|
|
430
|
+
export function resetDockCacheForTest() {
|
|
431
|
+
dockCache = null;
|
|
432
|
+
}
|
|
357
433
|
/**
|
|
358
434
|
* TCP-probe a bridge's loopback endpoint. Loopback refusals are instant, so
|
|
359
435
|
* the timeout only guards pathological cases; a bare connect+destroy is
|
|
@@ -381,6 +457,36 @@ const MAX_SESSION_LIST_BYTES = 4 * 1024 * 1024;
|
|
|
381
457
|
* gives its own query 15s).
|
|
382
458
|
*/
|
|
383
459
|
const SESSION_LIST_TIMEOUT_MS = 12_000;
|
|
460
|
+
/** Best-effort budget for the resume tab-title lookup — the window must
|
|
461
|
+
* never wait on a slow bridge (the 12s list budget is for listings, not
|
|
462
|
+
* for cosmetics). */
|
|
463
|
+
const TITLE_LOOKUP_BUDGET_MS = 2_000;
|
|
464
|
+
/**
|
|
465
|
+
* Tab-title sanitizer: the value is printf'd into the terminal as an OSC
|
|
466
|
+
* payload, so control characters (an ESC inside a model-generated summary
|
|
467
|
+
* would inject terminal sequences) become spaces, whitespace collapses, and
|
|
468
|
+
* the length caps at what a tab can usefully show. Empty/non-string →
|
|
469
|
+
* undefined (the caller falls back to the project name).
|
|
470
|
+
*/
|
|
471
|
+
export function sanitizeTabTitle(v) {
|
|
472
|
+
if (typeof v !== "string")
|
|
473
|
+
return undefined;
|
|
474
|
+
const clean = v
|
|
475
|
+
.replace(/[\p{Cc}]/gu, " ")
|
|
476
|
+
.replace(/\s+/g, " ")
|
|
477
|
+
.trim()
|
|
478
|
+
.slice(0, 80);
|
|
479
|
+
return clean.length > 0 ? clean : undefined;
|
|
480
|
+
}
|
|
481
|
+
/** Resolve with undefined after `ms` — for best-effort lookups that must not
|
|
482
|
+
* stall their caller; the losing promise settles into the void (its own
|
|
483
|
+
* rejection is the caller's `.catch`, never unhandled). */
|
|
484
|
+
function withTimeout(p, ms) {
|
|
485
|
+
const timeout = new Promise((resolve) => {
|
|
486
|
+
setTimeout(() => resolve(undefined), ms).unref?.();
|
|
487
|
+
});
|
|
488
|
+
return Promise.race([p, timeout]);
|
|
489
|
+
}
|
|
384
490
|
/**
|
|
385
491
|
* Fetch a bridge's GET /sessions payload (ADR-0015), forwarding the
|
|
386
492
|
* pagination query ("?limit=..&before=.."). Resolves with the parsed JSON;
|
|
@@ -537,7 +643,7 @@ export function startHub(options) {
|
|
|
537
643
|
* requested session (ADR-0017), "serve" the detached headless bridge
|
|
538
644
|
* (background listing, ADR-0015).
|
|
539
645
|
*/
|
|
540
|
-
const incubateServe = async (workspacePath, kind, sessionId) => {
|
|
646
|
+
const incubateServe = async (workspacePath, kind, sessionId, tabTitle) => {
|
|
541
647
|
// Async spawn failures (ENOENT — the dir vanished between the whitelist
|
|
542
648
|
// check and the spawn) arrive as an 'error' event with exitCode still
|
|
543
649
|
// null; without this flag the poll burns the full budget.
|
|
@@ -578,6 +684,14 @@ export function startHub(options) {
|
|
|
578
684
|
// Must ride the env verbatim — martty reads it once at process start.
|
|
579
685
|
env.DSH_TUI_AUTOPROMPT = BOOT_RESUME_TRIGGER;
|
|
580
686
|
}
|
|
687
|
+
if (kind !== "serve") {
|
|
688
|
+
// Tab title (both visible-terminal kinds): a resume carries the
|
|
689
|
+
// conversation's title when the hub resolved it; session-create and a
|
|
690
|
+
// failed lookup fall back to the project name. Rides the env —
|
|
691
|
+
// terminalTuiScript turns it into an OSC 0 before exec'ing the CLI
|
|
692
|
+
// (terminals otherwise name the tab after the process, "node").
|
|
693
|
+
env.ZCODE_ACP_TAB_TITLE = tabTitle ?? path.basename(workspacePath);
|
|
694
|
+
}
|
|
581
695
|
try {
|
|
582
696
|
// Resume shares session-create's visible-terminal surface (and its
|
|
583
697
|
// detached-serve fallback for headless machines); only a background
|
|
@@ -639,14 +753,14 @@ export function startHub(options) {
|
|
|
639
753
|
* key carries the session id, so resumes of different sessions each get
|
|
640
754
|
* their own window.
|
|
641
755
|
*/
|
|
642
|
-
const joinIncubation = (workspacePath, kind, sessionId) => {
|
|
756
|
+
const joinIncubation = (workspacePath, kind, sessionId, tabTitle) => {
|
|
643
757
|
const mapKey = kind === "resume" ? `${workspacePath}\u0000resume\u0000${sessionId ?? ""}` : workspacePath;
|
|
644
758
|
const inflight = serveIncubations.get(mapKey);
|
|
645
759
|
if (inflight && (inflight.kind === kind || kind === "serve")) {
|
|
646
760
|
log(`hub: joining the incubating serve bridge for ${workspacePath}`);
|
|
647
761
|
return inflight.promise;
|
|
648
762
|
}
|
|
649
|
-
const promise = incubateServe(workspacePath, kind, sessionId);
|
|
763
|
+
const promise = incubateServe(workspacePath, kind, sessionId, tabTitle);
|
|
650
764
|
serveIncubations.set(mapKey, { kind, promise });
|
|
651
765
|
// Drop the entry once settled (identity-checked — a newer incubation may
|
|
652
766
|
// already have replaced it). The catch keeps the DERIVED promise handled;
|
|
@@ -829,6 +943,26 @@ export function startHub(options) {
|
|
|
829
943
|
}
|
|
830
944
|
return;
|
|
831
945
|
}
|
|
946
|
+
// GET /api/quota/dock — the compact quota-dock string for the TUI
|
|
947
|
+
// refresher (ADR-0021). Account-level like /api/quota; hub-side cache is
|
|
948
|
+
// the only caching layer, so clients must not store stale copies.
|
|
949
|
+
if (url.pathname === "/api/quota/dock" && req.method === "GET") {
|
|
950
|
+
if (!authorized(req, url, token)) {
|
|
951
|
+
res.writeHead(401, { "Content-Type": "text/plain" });
|
|
952
|
+
res.end("unauthorized");
|
|
953
|
+
return;
|
|
954
|
+
}
|
|
955
|
+
try {
|
|
956
|
+
const { formatted, fetchedAt } = await getQuotaDock();
|
|
957
|
+
res.writeHead(200, { "Content-Type": "application/json", "Cache-Control": "no-store" });
|
|
958
|
+
res.end(JSON.stringify({ formatted, fetchedAt }));
|
|
959
|
+
}
|
|
960
|
+
catch {
|
|
961
|
+
res.writeHead(502, { "Content-Type": "text/plain" });
|
|
962
|
+
res.end("quota query failed");
|
|
963
|
+
}
|
|
964
|
+
return;
|
|
965
|
+
}
|
|
832
966
|
// GET /api/projects — the machine's known-project list (remote
|
|
833
967
|
// session-create, ADR-0014). Sourced from the App's tasks index: every
|
|
834
968
|
// workspace that ever ran a session. The list gates POST /api/instances
|
|
@@ -984,13 +1118,26 @@ export function startHub(options) {
|
|
|
984
1118
|
return;
|
|
985
1119
|
}
|
|
986
1120
|
if (resumeSid) {
|
|
1121
|
+
// Tab title, best-effort: the App browsed this conversation through
|
|
1122
|
+
// the serve bridge's /sessions history, which is normally still live
|
|
1123
|
+
// and still holds the title. Every miss (no live instance, id beyond
|
|
1124
|
+
// the page, slow fetch) falls back to the project name inside
|
|
1125
|
+
// incubateServe — the window must never wait on this lookup.
|
|
1126
|
+
let tabTitle;
|
|
1127
|
+
const titleSource = findServeInstance(workspacePath);
|
|
1128
|
+
if (titleSource) {
|
|
1129
|
+
const row = await withTimeout(fetchBridgeSessions(titleSource.port, "?limit=200")
|
|
1130
|
+
.then((payload) => (payload.sessions ?? []).find((s) => s.sessionId === resumeSid))
|
|
1131
|
+
.catch(() => undefined), TITLE_LOOKUP_BUDGET_MS);
|
|
1132
|
+
tabTitle = sanitizeTabTitle(row?.title);
|
|
1133
|
+
}
|
|
987
1134
|
// Resume never reuses the live serve bridge: the window IS the
|
|
988
1135
|
// feature, and the answer must be the NEW instance so the attaching
|
|
989
1136
|
// client and the terminal share one bridge (and one backend process)
|
|
990
1137
|
// for the session. A bogus id still opens the window — the TUI
|
|
991
1138
|
// shows the load failure and falls back to a fresh session, the same
|
|
992
1139
|
// honesty as a window that dies early (ADR-0016 §4).
|
|
993
|
-
const incubation = joinIncubation(workspacePath, "resume", resumeSid);
|
|
1140
|
+
const incubation = joinIncubation(workspacePath, "resume", resumeSid, tabTitle);
|
|
994
1141
|
try {
|
|
995
1142
|
const out = await incubation;
|
|
996
1143
|
res.writeHead(200, { "Content-Type": "application/json" });
|