tmux-ide 2.9.15 → 2.9.17
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 +1 -1
- package/bin/cli.js +740 -185
- package/package.json +2 -1
- package/packages/contracts/src/tmux-server-scope.ts +54 -0
- package/packages/core/src/terminal-fnv64-wasm.ts +8 -1
- package/packages/core/src/terminal-replica-hash-cache.ts +108 -1
- package/packages/core/src/terminal-replica.ts +46 -10
- package/packages/daemon/dist/command-center/daemon-fleet-facts-observer.js +8 -1
- package/packages/daemon/dist/command-center/discovery.js +39 -6
- package/packages/daemon/dist/command-center/tmux-servers.js +46 -10
- package/packages/daemon/dist/lib/catalog-fleet-read.js +10 -0
- package/packages/daemon/dist/lib/daemon-embed.js +14 -3
- package/packages/daemon/dist/lib/daemon-service.js +13 -5
- package/packages/daemon/dist/lib/session-favicon.js +152 -0
- package/packages/daemon/dist/lib/skill-sync.js +3 -3
- package/packages/daemon/dist/lib/tmux-server-owner.js +16 -3
- package/packages/daemon/dist/lib/tmux-server-owners.js +20 -1
- package/packages/daemon/dist/lib/tui-binary.js +83 -17
- package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/Info.plist +2 -2
- package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/MacOS/tmux-ide-notifier +0 -0
- package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/Resources/AppIcon.icns +0 -0
- package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/Resources/Assets.car +0 -0
- package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/_CodeSignature/CodeResources +4 -4
- package/packages/daemon/dist/open-browser.js +47 -3
- package/packages/daemon/dist/terminal/pane-stream/pane-stream-websocket.js +12 -0
- package/packages/daemon/dist/terminal/session-runtime/terminal-delivery-hub.js +16 -0
- package/packages/daemon/src/command-center/daemon-fleet-facts-observer.ts +9 -1
- package/packages/daemon/src/command-center/discovery.ts +72 -7
- package/packages/daemon/src/command-center/tmux-servers.ts +55 -11
- package/packages/daemon/src/lib/catalog-fleet-read.ts +40 -0
- package/packages/daemon/src/lib/daemon-embed.ts +27 -12
- package/packages/daemon/src/lib/daemon-service.ts +17 -4
- package/packages/daemon/src/lib/session-favicon.ts +185 -0
- package/packages/daemon/src/lib/skill-sync.ts +3 -3
- package/packages/daemon/src/lib/tmux-server-owner.ts +35 -6
- package/packages/daemon/src/lib/tmux-server-owners.ts +17 -1
- package/packages/daemon/src/lib/tui-binary.ts +114 -22
- package/packages/daemon/src/open-browser.ts +88 -3
- package/packages/daemon/src/terminal/pane-stream/pane-stream-websocket.ts +12 -0
- package/packages/daemon/src/terminal/session-runtime/terminal-delivery-hub.ts +25 -0
- package/skill/SKILL.md +6 -1
package/bin/cli.js
CHANGED
|
@@ -7432,14 +7432,18 @@ var init_terminal_projection = __esm({
|
|
|
7432
7432
|
var tmux_server_scope_exports = {};
|
|
7433
7433
|
__export(tmux_server_scope_exports, {
|
|
7434
7434
|
TMUX_SERVERS_API_PATH: () => TMUX_SERVERS_API_PATH,
|
|
7435
|
+
TMUX_SERVER_SESSION_FAVICON_MAX_BYTES: () => TMUX_SERVER_SESSION_FAVICON_MAX_BYTES,
|
|
7435
7436
|
TmuxServerDescriptorSchemaZ: () => TmuxServerDescriptorSchemaZ,
|
|
7436
7437
|
TmuxServerGenerationSchemaZ: () => TmuxServerGenerationSchemaZ,
|
|
7437
7438
|
TmuxServerIdSchemaZ: () => TmuxServerIdSchemaZ,
|
|
7438
7439
|
TmuxServerPaneTargetSchemaZ: () => TmuxServerPaneTargetSchemaZ,
|
|
7439
7440
|
TmuxServerRegistrationRequestSchemaZ: () => TmuxServerRegistrationRequestSchemaZ,
|
|
7440
7441
|
TmuxServerScopeSchemaZ: () => TmuxServerScopeSchemaZ,
|
|
7442
|
+
TmuxServerSessionFaviconMimeSchemaZ: () => TmuxServerSessionFaviconMimeSchemaZ,
|
|
7443
|
+
TmuxServerSessionFaviconSchemaZ: () => TmuxServerSessionFaviconSchemaZ,
|
|
7441
7444
|
TmuxServerSessionTargetSchemaZ: () => TmuxServerSessionTargetSchemaZ,
|
|
7442
7445
|
TmuxServerSessionsResourceSchemaZ: () => TmuxServerSessionsResourceSchemaZ,
|
|
7446
|
+
TmuxServerSessionsResourceV2SchemaZ: () => TmuxServerSessionsResourceV2SchemaZ,
|
|
7443
7447
|
TmuxServerWindowTargetSchemaZ: () => TmuxServerWindowTargetSchemaZ,
|
|
7444
7448
|
TmuxServersResourceSchemaZ: () => TmuxServersResourceSchemaZ,
|
|
7445
7449
|
isTmuxServerPaneStreamPath: () => isTmuxServerPaneStreamPath,
|
|
@@ -7474,7 +7478,11 @@ function isTmuxServerPaneStreamPath(path2) {
|
|
|
7474
7478
|
if (!match) return false;
|
|
7475
7479
|
return TmuxServerScopeSchemaZ.safeParse({ serverId: match[1], generation: match[2] }).success;
|
|
7476
7480
|
}
|
|
7477
|
-
|
|
7481
|
+
function base64DecodedLength(data) {
|
|
7482
|
+
const padding = data.endsWith("==") ? 2 : data.endsWith("=") ? 1 : 0;
|
|
7483
|
+
return data.length / 4 * 3 - padding;
|
|
7484
|
+
}
|
|
7485
|
+
var descriptorShape, TmuxServerDescriptorSchemaZ, TMUX_SERVERS_API_PATH, TmuxServersResourceSchemaZ, TmuxServerSessionTargetSchemaZ, TmuxServerWindowTargetSchemaZ, TmuxServerPaneTargetSchemaZ, TmuxServerSessionsResourceSchemaZ, TMUX_SERVER_SESSION_FAVICON_MAX_BYTES, TmuxServerSessionFaviconMimeSchemaZ, TmuxServerSessionFaviconSchemaZ, TmuxServerSessionsResourceV2SchemaZ, TmuxServerRegistrationRequestSchemaZ;
|
|
7478
7486
|
var init_tmux_server_scope = __esm({
|
|
7479
7487
|
"packages/contracts/src/tmux-server-scope.ts"() {
|
|
7480
7488
|
"use strict";
|
|
@@ -7537,6 +7545,37 @@ var init_tmux_server_scope = __esm({
|
|
|
7537
7545
|
}).strict()
|
|
7538
7546
|
)
|
|
7539
7547
|
}).strict())();
|
|
7548
|
+
TMUX_SERVER_SESSION_FAVICON_MAX_BYTES = /* @__PURE__ */ (() => 32768)();
|
|
7549
|
+
TmuxServerSessionFaviconMimeSchemaZ = /* @__PURE__ */ (() => z47.enum([
|
|
7550
|
+
"image/png",
|
|
7551
|
+
"image/svg+xml",
|
|
7552
|
+
"image/x-icon",
|
|
7553
|
+
"image/jpeg",
|
|
7554
|
+
"image/webp",
|
|
7555
|
+
"image/gif"
|
|
7556
|
+
]))();
|
|
7557
|
+
TmuxServerSessionFaviconSchemaZ = /* @__PURE__ */ (() => z47.object({
|
|
7558
|
+
mime: TmuxServerSessionFaviconMimeSchemaZ,
|
|
7559
|
+
data: z47.string().regex(/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/u).refine(
|
|
7560
|
+
(data) => base64DecodedLength(data) <= TMUX_SERVER_SESSION_FAVICON_MAX_BYTES,
|
|
7561
|
+
"favicon exceeds 32 KiB"
|
|
7562
|
+
)
|
|
7563
|
+
}).strict())();
|
|
7564
|
+
TmuxServerSessionsResourceV2SchemaZ = /* @__PURE__ */ (() => z47.object({
|
|
7565
|
+
version: z47.literal(2),
|
|
7566
|
+
server: TmuxServerScopeSchemaZ,
|
|
7567
|
+
sessions: z47.array(
|
|
7568
|
+
z47.object({
|
|
7569
|
+
liveSessionId: WorkspaceCatalogLiveSessionIdSchemaZ,
|
|
7570
|
+
sessionName: z47.string().min(1).max(160),
|
|
7571
|
+
workspaceName: z47.string().min(1).max(160).nullable(),
|
|
7572
|
+
paneCount: z47.number().int().nonnegative(),
|
|
7573
|
+
windowCount: z47.number().int().min(1),
|
|
7574
|
+
lastActivity: z47.number().int().nonnegative().nullable(),
|
|
7575
|
+
favicon: TmuxServerSessionFaviconSchemaZ.nullable()
|
|
7576
|
+
}).strict()
|
|
7577
|
+
)
|
|
7578
|
+
}).strict())();
|
|
7540
7579
|
TmuxServerRegistrationRequestSchemaZ = /* @__PURE__ */ (() => z47.object({
|
|
7541
7580
|
label: descriptorShape.label.max(128),
|
|
7542
7581
|
selector: z47.discriminatedUnion("kind", [
|
|
@@ -12364,7 +12403,10 @@ __export(tui_binary_exports, {
|
|
|
12364
12403
|
MAX_TUI_COMPRESSED_BYTES: () => MAX_TUI_COMPRESSED_BYTES,
|
|
12365
12404
|
MIN_TUI_BINARY_BYTES: () => MIN_TUI_BINARY_BYTES,
|
|
12366
12405
|
RELEASE_REPO: () => RELEASE_REPO,
|
|
12367
|
-
|
|
12406
|
+
TUI_DOWNLOAD_MAX_ATTEMPTS: () => TUI_DOWNLOAD_MAX_ATTEMPTS,
|
|
12407
|
+
TUI_DOWNLOAD_RETRY_DELAY_MS: () => TUI_DOWNLOAD_RETRY_DELAY_MS,
|
|
12408
|
+
TUI_DOWNLOAD_STALL_TIMEOUT_MS: () => TUI_DOWNLOAD_STALL_TIMEOUT_MS,
|
|
12409
|
+
TUI_DOWNLOAD_TOTAL_TIMEOUT_MS: () => TUI_DOWNLOAD_TOTAL_TIMEOUT_MS,
|
|
12368
12410
|
bunTargetForTag: () => bunTargetForTag,
|
|
12369
12411
|
downloadTuiBinary: () => downloadTuiBinary,
|
|
12370
12412
|
downloadedTuiPath: () => downloadedTuiPath,
|
|
@@ -12509,30 +12551,54 @@ function purgeCachedBinary(path2) {
|
|
|
12509
12551
|
}
|
|
12510
12552
|
}
|
|
12511
12553
|
}
|
|
12512
|
-
|
|
12554
|
+
function isTransientHttpStatus(status2) {
|
|
12555
|
+
return status2 === 408 || status2 === 429 || status2 >= 500;
|
|
12556
|
+
}
|
|
12557
|
+
async function readBoundedResponse(fetchImpl, url, maxBytes, policy) {
|
|
12513
12558
|
const controller = new AbortController();
|
|
12514
|
-
|
|
12559
|
+
let total = 0;
|
|
12560
|
+
let timeoutMessage = null;
|
|
12561
|
+
const abortWith = (message) => () => {
|
|
12562
|
+
timeoutMessage = message();
|
|
12563
|
+
controller.abort();
|
|
12564
|
+
};
|
|
12565
|
+
const overallTimer = setTimeout(
|
|
12566
|
+
abortWith(() => `download did not finish within ${policy.totalTimeoutMs}ms`),
|
|
12567
|
+
Math.max(0, policy.deadline - Date.now())
|
|
12568
|
+
);
|
|
12569
|
+
const onStall = abortWith(
|
|
12570
|
+
() => `download stalled: no data for ${policy.stallTimeoutMs}ms after ${total} bytes`
|
|
12571
|
+
);
|
|
12572
|
+
let stallTimer = setTimeout(onStall, policy.stallTimeoutMs);
|
|
12573
|
+
const markProgress = () => {
|
|
12574
|
+
clearTimeout(stallTimer);
|
|
12575
|
+
stallTimer = setTimeout(onStall, policy.stallTimeoutMs);
|
|
12576
|
+
};
|
|
12515
12577
|
try {
|
|
12516
12578
|
const response3 = await fetchImpl(url, { signal: controller.signal });
|
|
12517
12579
|
if (!response3.ok) {
|
|
12518
|
-
|
|
12580
|
+
const message = `HTTP ${response3.status} ${response3.statusText}`;
|
|
12581
|
+
if (isTransientHttpStatus(response3.status)) throw new Error(message);
|
|
12582
|
+
throw new PermanentDownloadError(message);
|
|
12519
12583
|
}
|
|
12584
|
+
markProgress();
|
|
12520
12585
|
const declaredLength = Number(response3.headers.get("content-length"));
|
|
12521
12586
|
if (Number.isFinite(declaredLength) && declaredLength > maxBytes) {
|
|
12522
|
-
throw new
|
|
12587
|
+
throw new PermanentDownloadError(`declared size ${declaredLength} exceeds ${maxBytes} bytes`);
|
|
12523
12588
|
}
|
|
12524
12589
|
if (!response3.body) throw new Error("response has no body");
|
|
12525
12590
|
const chunks = [];
|
|
12526
|
-
let total = 0;
|
|
12527
12591
|
const reader = response3.body.getReader();
|
|
12528
12592
|
try {
|
|
12529
12593
|
while (true) {
|
|
12530
12594
|
const { done, value } = await reader.read();
|
|
12531
12595
|
if (done) break;
|
|
12596
|
+
if (value.byteLength === 0) continue;
|
|
12597
|
+
markProgress();
|
|
12532
12598
|
total += value.byteLength;
|
|
12533
12599
|
if (total > maxBytes) {
|
|
12534
12600
|
await reader.cancel();
|
|
12535
|
-
throw new
|
|
12601
|
+
throw new PermanentDownloadError(`download exceeds ${maxBytes} bytes`);
|
|
12536
12602
|
}
|
|
12537
12603
|
chunks.push(Buffer.from(value));
|
|
12538
12604
|
}
|
|
@@ -12541,12 +12607,27 @@ async function readBoundedResponse(fetchImpl, url, maxBytes, timeoutMs) {
|
|
|
12541
12607
|
}
|
|
12542
12608
|
return Buffer.concat(chunks, total);
|
|
12543
12609
|
} catch (error) {
|
|
12544
|
-
if (
|
|
12545
|
-
throw new Error(`download timed out after ${timeoutMs}ms`, { cause: error });
|
|
12546
|
-
}
|
|
12610
|
+
if (timeoutMessage) throw new Error(timeoutMessage, { cause: error });
|
|
12547
12611
|
throw error;
|
|
12548
12612
|
} finally {
|
|
12549
|
-
clearTimeout(
|
|
12613
|
+
clearTimeout(overallTimer);
|
|
12614
|
+
clearTimeout(stallTimer);
|
|
12615
|
+
controller.abort();
|
|
12616
|
+
}
|
|
12617
|
+
}
|
|
12618
|
+
async function readWithRetries(fetchImpl, url, maxBytes, policy, log) {
|
|
12619
|
+
for (let attempt = 1; ; attempt++) {
|
|
12620
|
+
try {
|
|
12621
|
+
return await readBoundedResponse(fetchImpl, url, maxBytes, policy);
|
|
12622
|
+
} catch (error) {
|
|
12623
|
+
const delayMs = policy.retryDelayMs * attempt;
|
|
12624
|
+
if (error instanceof PermanentDownloadError || attempt >= policy.maxAttempts || Date.now() + delayMs >= policy.deadline) {
|
|
12625
|
+
throw error;
|
|
12626
|
+
}
|
|
12627
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
12628
|
+
log(`download attempt ${attempt}/${policy.maxAttempts} failed (${message}); retrying`);
|
|
12629
|
+
await new Promise((resolve45) => setTimeout(resolve45, delayMs));
|
|
12630
|
+
}
|
|
12550
12631
|
}
|
|
12551
12632
|
}
|
|
12552
12633
|
async function downloadTuiBinary(opts = {}) {
|
|
@@ -12567,14 +12648,18 @@ async function downloadTuiBinary(opts = {}) {
|
|
|
12567
12648
|
const limits = {
|
|
12568
12649
|
minBinaryBytes: opts.limits?.minBinaryBytes ?? MIN_TUI_BINARY_BYTES,
|
|
12569
12650
|
maxCompressedBytes: opts.limits?.maxCompressedBytes ?? MAX_TUI_COMPRESSED_BYTES,
|
|
12570
|
-
maxBinaryBytes: opts.limits?.maxBinaryBytes ?? MAX_TUI_BINARY_BYTES
|
|
12571
|
-
timeoutMs: opts.timeoutMs ?? TUI_DOWNLOAD_TIMEOUT_MS
|
|
12651
|
+
maxBinaryBytes: opts.limits?.maxBinaryBytes ?? MAX_TUI_BINARY_BYTES
|
|
12572
12652
|
};
|
|
12653
|
+
const totalTimeoutMs = opts.totalTimeoutMs ?? TUI_DOWNLOAD_TOTAL_TIMEOUT_MS;
|
|
12573
12654
|
mkdirSync5(dirname9(dest), { recursive: true });
|
|
12655
|
+
const lockNotice = setTimeout(
|
|
12656
|
+
() => log("waiting for another tmux-ide download of this version to finish"),
|
|
12657
|
+
TUI_DOWNLOAD_LOCK_NOTICE_MS
|
|
12658
|
+
);
|
|
12574
12659
|
const releaseLock = await acquirePrivateOperationLock(
|
|
12575
12660
|
downloadLockPath(dest),
|
|
12576
|
-
|
|
12577
|
-
);
|
|
12661
|
+
totalTimeoutMs + TUI_DOWNLOAD_LOCK_MARGIN_MS
|
|
12662
|
+
).finally(() => clearTimeout(lockNotice));
|
|
12578
12663
|
const suffix = `${process.pid}.${randomUUID2()}.tmp`;
|
|
12579
12664
|
const binaryTmp = `${dest}.${suffix}`;
|
|
12580
12665
|
const checksumTmp = `${checksumPath(dest)}.${suffix}`;
|
|
@@ -12583,21 +12668,31 @@ async function downloadTuiBinary(opts = {}) {
|
|
|
12583
12668
|
if (cached2) return { path: dest, bytes: cached2.bytes };
|
|
12584
12669
|
purgeCachedBinary(dest);
|
|
12585
12670
|
const fetchImpl = opts.fetch ?? globalThis.fetch;
|
|
12671
|
+
const policy = {
|
|
12672
|
+
stallTimeoutMs: opts.stallTimeoutMs ?? TUI_DOWNLOAD_STALL_TIMEOUT_MS,
|
|
12673
|
+
deadline: Date.now() + totalTimeoutMs,
|
|
12674
|
+
totalTimeoutMs,
|
|
12675
|
+
maxAttempts: opts.maxAttempts ?? TUI_DOWNLOAD_MAX_ATTEMPTS,
|
|
12676
|
+
retryDelayMs: opts.retryDelayMs ?? TUI_DOWNLOAD_RETRY_DELAY_MS
|
|
12677
|
+
};
|
|
12586
12678
|
log(`downloading checksum manifest ${checksumUrl}`);
|
|
12587
12679
|
let manifestBytes;
|
|
12588
12680
|
let gz;
|
|
12589
12681
|
try {
|
|
12590
|
-
manifestBytes = await
|
|
12682
|
+
manifestBytes = await readWithRetries(
|
|
12591
12683
|
fetchImpl,
|
|
12592
12684
|
checksumUrl,
|
|
12593
12685
|
MAX_CHECKSUM_MANIFEST_BYTES,
|
|
12594
|
-
|
|
12686
|
+
policy,
|
|
12687
|
+
log
|
|
12595
12688
|
);
|
|
12596
|
-
|
|
12689
|
+
log(`downloading ${url}`);
|
|
12690
|
+
gz = await readWithRetries(fetchImpl, url, limits.maxCompressedBytes, policy, log);
|
|
12597
12691
|
} catch (error) {
|
|
12598
12692
|
const message = error instanceof Error ? error.message : String(error);
|
|
12693
|
+
const hint = error instanceof PermanentDownloadError ? "Check that the release published both exact-version assets." : "Check your network connection, then retry with `tmux-ide update --tui-binary`, or run the installer again if tmux-ide is not installed yet.";
|
|
12599
12694
|
throw new Error(
|
|
12600
|
-
`could not download the TUI binary and checksum for v${version} (${message}).
|
|
12695
|
+
`could not download the TUI binary and checksum for v${version} (${message}). ${hint}`,
|
|
12601
12696
|
{ cause: error }
|
|
12602
12697
|
);
|
|
12603
12698
|
}
|
|
@@ -12642,7 +12737,7 @@ async function downloadTuiBinary(opts = {}) {
|
|
|
12642
12737
|
releaseLock();
|
|
12643
12738
|
}
|
|
12644
12739
|
}
|
|
12645
|
-
var RELEASE_REPO, MIN_TUI_BINARY_BYTES, MAX_TUI_COMPRESSED_BYTES, MAX_TUI_BINARY_BYTES,
|
|
12740
|
+
var RELEASE_REPO, MIN_TUI_BINARY_BYTES, MAX_TUI_COMPRESSED_BYTES, MAX_TUI_BINARY_BYTES, TUI_DOWNLOAD_STALL_TIMEOUT_MS, TUI_DOWNLOAD_TOTAL_TIMEOUT_MS, TUI_DOWNLOAD_MAX_ATTEMPTS, TUI_DOWNLOAD_RETRY_DELAY_MS, MAX_CHECKSUM_MANIFEST_BYTES, TUI_DOWNLOAD_LOCK_NOTICE_MS, TUI_DOWNLOAD_LOCK_MARGIN_MS, SUPPORTED, PermanentDownloadError;
|
|
12646
12741
|
var init_tui_binary = __esm({
|
|
12647
12742
|
"packages/daemon/src/lib/tui-binary.ts"() {
|
|
12648
12743
|
"use strict";
|
|
@@ -12653,13 +12748,20 @@ var init_tui_binary = __esm({
|
|
|
12653
12748
|
MIN_TUI_BINARY_BYTES = 10 * 1024 * 1024;
|
|
12654
12749
|
MAX_TUI_COMPRESSED_BYTES = 128 * 1024 * 1024;
|
|
12655
12750
|
MAX_TUI_BINARY_BYTES = 256 * 1024 * 1024;
|
|
12656
|
-
|
|
12751
|
+
TUI_DOWNLOAD_STALL_TIMEOUT_MS = 3e4;
|
|
12752
|
+
TUI_DOWNLOAD_TOTAL_TIMEOUT_MS = 15 * 6e4;
|
|
12753
|
+
TUI_DOWNLOAD_MAX_ATTEMPTS = 3;
|
|
12754
|
+
TUI_DOWNLOAD_RETRY_DELAY_MS = 1e3;
|
|
12657
12755
|
MAX_CHECKSUM_MANIFEST_BYTES = 4 * 1024;
|
|
12756
|
+
TUI_DOWNLOAD_LOCK_NOTICE_MS = 2e3;
|
|
12757
|
+
TUI_DOWNLOAD_LOCK_MARGIN_MS = 5e3;
|
|
12658
12758
|
SUPPORTED = {
|
|
12659
12759
|
"darwin-arm64": "darwin-arm64",
|
|
12660
12760
|
"linux-x64": "linux-x64",
|
|
12661
12761
|
"linux-arm64": "linux-arm64"
|
|
12662
12762
|
};
|
|
12763
|
+
PermanentDownloadError = class extends Error {
|
|
12764
|
+
};
|
|
12663
12765
|
}
|
|
12664
12766
|
});
|
|
12665
12767
|
|
|
@@ -13043,7 +13145,7 @@ var require_package = __commonJS({
|
|
|
13043
13145
|
"package.json"(exports, module) {
|
|
13044
13146
|
module.exports = {
|
|
13045
13147
|
name: "tmux-ide",
|
|
13046
|
-
version: "2.9.
|
|
13148
|
+
version: "2.9.17",
|
|
13047
13149
|
description: "The open-source workspace for coding agents: run Claude Code, Codex and other agents in tmux with live status",
|
|
13048
13150
|
type: "module",
|
|
13049
13151
|
bin: {
|
|
@@ -13113,6 +13215,7 @@ var require_package = __commonJS({
|
|
|
13113
13215
|
postinstall: "node scripts/postinstall.js",
|
|
13114
13216
|
docs: "turbo run dev --filter=@tmux-ide/docs",
|
|
13115
13217
|
"demo:tui": "bun --preload @opentui/solid/preload docs/scripts/render-tui-demo.tsx",
|
|
13218
|
+
"demo:themes": "bun --preload @opentui/solid/preload docs/scripts/render-theme-gallery.tsx && node docs/scripts/rasterize-theme-gallery.mjs",
|
|
13116
13219
|
"demo:font": "node docs/scripts/tui-demo-font/build.mjs",
|
|
13117
13220
|
"readme:media": "node docs/scripts/readme-media.mjs",
|
|
13118
13221
|
"test:tui-renderer": "bun test --preload @opentui/solid/preload --preload ./packages/daemon/test-support/opentui-renderer-preload.ts ./packages/daemon/src/tui/mirror/automatic-contrast-renderer.test.tsx ./packages/daemon/src/tui/mirror/pane-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/native-grid-projection-renderer.test.tsx ./packages/daemon/src/tui/mirror/widget-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/missions-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/recipes-gallery-renderer.test.tsx ./packages/daemon/src/tui/mirror/shell-chrome-renderer.test.tsx ./packages/daemon/src/tui/mirror/sidebar-renderer.test.tsx ./packages/daemon/src/tui/mirror/home-files-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/changes-terminal-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/activity-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/features/files/session-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-terminal-workspace-renderer.test.tsx ./packages/daemon/src/tui/mirror/testing/styled-frame-oracle.test.tsx ./packages/daemon/src/tui/mirror/runtime/terminal-transient-frame-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/terminal-draw-failure-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-shell-view-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-root-error-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-backpressure-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-demand-cadence-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/files-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/changes-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/missions-activity-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/dialogs-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/optional-feature-registry-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/palette-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/pane-scoped-terminal-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/features/rich-preview/feature.test.ts ./packages/daemon/src/tui/mirror/runtime/rich-preview-optional-feature-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/application-shell-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/pane-frame-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/terminal-pane-chrome-view.test.tsx ./packages/daemon/src/tui/mirror/workspace/terminal-window-strip-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/workbench-shell-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/workbench-dock-dual-host-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/agent-terminal-canvas-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/command-palette-surface-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/opentui-insertion-stability-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-shell-home-renderer.test.tsx ./packages/daemon/src/tui/mirror/workspace/terminal-pane-header-polish-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-home-agent-roster-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-home-agent-flow-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/guided-tour-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-shell-sidebar-catalog-renderer.test.tsx ./packages/daemon/src/tui/mirror/ui/ui-renderer.test.tsx ./packages/daemon/src/tui/mirror/ui/pane-interaction-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-machine-sidebar-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-add-machine-dialog-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-new-agent-dialog-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-fleet-switcher-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-palette-preview-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-fleet-palette-renderer.test.tsx ./packages/daemon/src/tui/mirror/runtime/application-fleet-session-actions-renderer.test.tsx ./packages/daemon/src/tui/mirror/ui/agent-team-renderer.test.tsx ./scripts/solid-conditional-props.test.tsx",
|
|
@@ -27034,10 +27137,13 @@ function isVisibleFleetSession(name) {
|
|
|
27034
27137
|
function readAdoptedSessionNames(runTmux2 = _tmuxRunner) {
|
|
27035
27138
|
let raw;
|
|
27036
27139
|
try {
|
|
27037
|
-
raw = runTmux2(
|
|
27140
|
+
raw = runTmux2(ADOPTED_SESSIONS_ARGS);
|
|
27038
27141
|
} catch {
|
|
27039
27142
|
return null;
|
|
27040
27143
|
}
|
|
27144
|
+
return parseAdoptedSessionNames(raw);
|
|
27145
|
+
}
|
|
27146
|
+
function parseAdoptedSessionNames(raw) {
|
|
27041
27147
|
const names = [];
|
|
27042
27148
|
for (const line of raw.split("\n")) {
|
|
27043
27149
|
if (!line) continue;
|
|
@@ -27056,16 +27162,51 @@ function readAdoptedFleet(registry = getDefaultWorkspaceRegistry(), runTmux2 = _
|
|
|
27056
27162
|
const nativeEpoch = nativeServerEpoch?.() ?? null;
|
|
27057
27163
|
const adopted = readAdoptedSessionNames(runTmux2);
|
|
27058
27164
|
if (adopted === null) return null;
|
|
27059
|
-
|
|
27060
|
-
if (adoptedSet.size === 0) return [];
|
|
27061
|
-
const appCreatedSessions = new Set(registry.list().map((workspace) => workspace.sessionName));
|
|
27062
|
-
const panesBySession = /* @__PURE__ */ new Map();
|
|
27165
|
+
if (adopted.length === 0) return [];
|
|
27063
27166
|
let panesRaw;
|
|
27064
27167
|
try {
|
|
27065
|
-
panesRaw = runTmux2(
|
|
27168
|
+
panesRaw = runTmux2(FLEET_PANES_ARGS);
|
|
27066
27169
|
} catch {
|
|
27067
27170
|
panesRaw = "";
|
|
27068
27171
|
}
|
|
27172
|
+
return assembleAdoptedFleet(
|
|
27173
|
+
adopted,
|
|
27174
|
+
panesRaw,
|
|
27175
|
+
registry,
|
|
27176
|
+
nativeEpoch,
|
|
27177
|
+
resolveInteractionEndpoint,
|
|
27178
|
+
nativeServerEpoch
|
|
27179
|
+
);
|
|
27180
|
+
}
|
|
27181
|
+
async function readAdoptedFleetAsync(registry, runTmux2, resolveInteractionEndpoint, nativeServerEpoch) {
|
|
27182
|
+
const nativeEpoch = nativeServerEpoch?.() ?? null;
|
|
27183
|
+
let sessionsRaw;
|
|
27184
|
+
try {
|
|
27185
|
+
sessionsRaw = await runTmux2(ADOPTED_SESSIONS_ARGS);
|
|
27186
|
+
} catch {
|
|
27187
|
+
return null;
|
|
27188
|
+
}
|
|
27189
|
+
const adopted = parseAdoptedSessionNames(sessionsRaw);
|
|
27190
|
+
if (adopted.length === 0) return [];
|
|
27191
|
+
let panesRaw;
|
|
27192
|
+
try {
|
|
27193
|
+
panesRaw = await runTmux2(FLEET_PANES_ARGS);
|
|
27194
|
+
} catch {
|
|
27195
|
+
panesRaw = "";
|
|
27196
|
+
}
|
|
27197
|
+
return assembleAdoptedFleet(
|
|
27198
|
+
adopted,
|
|
27199
|
+
panesRaw,
|
|
27200
|
+
registry,
|
|
27201
|
+
nativeEpoch,
|
|
27202
|
+
resolveInteractionEndpoint,
|
|
27203
|
+
nativeServerEpoch
|
|
27204
|
+
);
|
|
27205
|
+
}
|
|
27206
|
+
function assembleAdoptedFleet(adopted, panesRaw, registry, nativeEpoch, resolveInteractionEndpoint, nativeServerEpoch) {
|
|
27207
|
+
const adoptedSet = new Set(adopted);
|
|
27208
|
+
const appCreatedSessions = new Set(registry.list().map((workspace) => workspace.sessionName));
|
|
27209
|
+
const panesBySession = /* @__PURE__ */ new Map();
|
|
27069
27210
|
for (const line of panesRaw.split("\n")) {
|
|
27070
27211
|
if (!line) continue;
|
|
27071
27212
|
const fields = line.split(FLEET_FIELD_SEPARATOR);
|
|
@@ -27153,7 +27294,7 @@ function buildProjectDetail(info) {
|
|
|
27153
27294
|
panes: info.panes.map(({ semanticPaneId: _semanticPaneId, ...pane }) => pane)
|
|
27154
27295
|
};
|
|
27155
27296
|
}
|
|
27156
|
-
var _tmuxRunner, FLEET_FIELD_SEPARATOR, FLEET_LINE_SENTINEL, FLEET_PANE_FORMAT;
|
|
27297
|
+
var _tmuxRunner, ADOPTED_SESSIONS_ARGS, FLEET_FIELD_SEPARATOR, FLEET_LINE_SENTINEL, FLEET_PANE_FORMAT, FLEET_PANES_ARGS;
|
|
27157
27298
|
var init_discovery = __esm({
|
|
27158
27299
|
"packages/daemon/src/command-center/discovery.ts"() {
|
|
27159
27300
|
"use strict";
|
|
@@ -27170,6 +27311,7 @@ var init_discovery = __esm({
|
|
|
27170
27311
|
maxBuffer: 1024 * 1024,
|
|
27171
27312
|
stdio: ["ignore", "pipe", "ignore"]
|
|
27172
27313
|
}).trim();
|
|
27314
|
+
ADOPTED_SESSIONS_ARGS = ["list-sessions", "-F", `#{session_name} #{${ADOPTED_OPTION}}`];
|
|
27173
27315
|
FLEET_FIELD_SEPARATOR = "|tmux-ide-fleet-field-v1|";
|
|
27174
27316
|
FLEET_LINE_SENTINEL = "tmux-ide-fleet-v1";
|
|
27175
27317
|
FLEET_PANE_FORMAT = [
|
|
@@ -27191,6 +27333,7 @@ var init_discovery = __esm({
|
|
|
27191
27333
|
"#{@tmux_ide_team}",
|
|
27192
27334
|
FLEET_LINE_SENTINEL
|
|
27193
27335
|
].join(FLEET_FIELD_SEPARATOR);
|
|
27336
|
+
FLEET_PANES_ARGS = ["list-panes", "-a", "-F", FLEET_PANE_FORMAT];
|
|
27194
27337
|
}
|
|
27195
27338
|
});
|
|
27196
27339
|
|
|
@@ -39850,7 +39993,7 @@ function createNativeTmuxSessionOpener(options) {
|
|
|
39850
39993
|
options.assertOpen();
|
|
39851
39994
|
if (disposed) throw new Error("Session admission is retired");
|
|
39852
39995
|
};
|
|
39853
|
-
const
|
|
39996
|
+
const open5 = async (liveSessionId, observed) => {
|
|
39854
39997
|
assertOpen();
|
|
39855
39998
|
const records = await options.run([
|
|
39856
39999
|
"list-sessions",
|
|
@@ -39912,7 +40055,7 @@ function createNativeTmuxSessionOpener(options) {
|
|
|
39912
40055
|
const previous = pending.get(liveSessionId);
|
|
39913
40056
|
if (previous) return previous;
|
|
39914
40057
|
if (pending.size >= 16) throw new Error("Session admission capacity reached");
|
|
39915
|
-
const operation = tail.then(() =>
|
|
40058
|
+
const operation = tail.then(() => open5(liveSessionId)).finally(() => pending.delete(liveSessionId));
|
|
39916
40059
|
pending.set(liveSessionId, operation);
|
|
39917
40060
|
tail = operation.catch(() => {
|
|
39918
40061
|
});
|
|
@@ -39925,7 +40068,7 @@ function createNativeTmuxSessionOpener(options) {
|
|
|
39925
40068
|
if (pending.size >= 16) throw new Error("Session admission capacity reached");
|
|
39926
40069
|
const key2 = randomUUID23();
|
|
39927
40070
|
const operation = tail.then(async () => {
|
|
39928
|
-
const result2 = await
|
|
40071
|
+
const result2 = await open5(liveSessionId, observed);
|
|
39929
40072
|
if (!result2.semanticPaneId) throw new Error("Agent admission returned no target");
|
|
39930
40073
|
return { ...result2, semanticPaneId: result2.semanticPaneId };
|
|
39931
40074
|
}).finally(() => pending.delete(key2));
|
|
@@ -43764,11 +43907,14 @@ function initialize() {
|
|
|
43764
43907
|
}
|
|
43765
43908
|
return native;
|
|
43766
43909
|
}
|
|
43910
|
+
function nativeFnv64() {
|
|
43911
|
+
return initialize();
|
|
43912
|
+
}
|
|
43767
43913
|
function createBufferedFnv64(initialState = OFFSET_BASIS) {
|
|
43768
43914
|
const hasher = initialize();
|
|
43769
43915
|
return hasher ? new BufferedHasher(hasher, initialState) : null;
|
|
43770
43916
|
}
|
|
43771
|
-
var SCRATCH_BYTES, OFFSET_BASIS, initialized, native, BufferedHasher;
|
|
43917
|
+
var SCRATCH_BYTES, OFFSET_BASIS, initialized, native, FNV64_OFFSET_BASIS, BufferedHasher;
|
|
43772
43918
|
var init_terminal_fnv64_wasm = __esm({
|
|
43773
43919
|
"packages/core/src/terminal-fnv64-wasm.ts"() {
|
|
43774
43920
|
"use strict";
|
|
@@ -43777,6 +43923,7 @@ var init_terminal_fnv64_wasm = __esm({
|
|
|
43777
43923
|
OFFSET_BASIS = 0xcbf29ce484222325n;
|
|
43778
43924
|
initialized = false;
|
|
43779
43925
|
native = null;
|
|
43926
|
+
FNV64_OFFSET_BASIS = OFFSET_BASIS;
|
|
43780
43927
|
BufferedHasher = class {
|
|
43781
43928
|
#native;
|
|
43782
43929
|
#buffer = new Uint8Array(SCRATCH_BYTES);
|
|
@@ -43914,6 +44061,12 @@ function hashTerminalReplicaRowCached(row, onMiss, encodingCache) {
|
|
|
43914
44061
|
const cached2 = ROW_HASH_CACHE.get(row);
|
|
43915
44062
|
if (cached2) return cached2;
|
|
43916
44063
|
onMiss?.();
|
|
44064
|
+
const native2 = nativeFnv64();
|
|
44065
|
+
if (native2) {
|
|
44066
|
+
const digest4 = hashRowBytes(row, native2);
|
|
44067
|
+
if (isTerminalReplicaRowDeeplyFrozen(row)) ROW_HASH_CACHE.set(row, digest4);
|
|
44068
|
+
return digest4;
|
|
44069
|
+
}
|
|
43917
44070
|
const hash = encodingCache?.createHash() ?? new CanonicalFnv64();
|
|
43918
44071
|
let canonicalBytes = 10 + String(row.cells.length).length;
|
|
43919
44072
|
hash.ascii("a2:");
|
|
@@ -43977,6 +44130,10 @@ async function hashTerminalReplicaRowCooperatively(row, yieldControl, bytesPerSl
|
|
|
43977
44130
|
}
|
|
43978
44131
|
function isTerminalReplicaRowDeeplyFrozen(row) {
|
|
43979
44132
|
if (DEEPLY_FROZEN_ROWS.has(row)) return true;
|
|
44133
|
+
if (isOwnedTerminalReplicaRow(row)) {
|
|
44134
|
+
DEEPLY_FROZEN_ROWS.add(row);
|
|
44135
|
+
return true;
|
|
44136
|
+
}
|
|
43980
44137
|
if (!Object.isFrozen(row) || !Object.isFrozen(row.cells)) return false;
|
|
43981
44138
|
for (const cell of row.cells) {
|
|
43982
44139
|
if (!Object.isFrozen(cell) || !Object.isFrozen(cell.foreground) || !Object.isFrozen(cell.background))
|
|
@@ -43985,7 +44142,74 @@ function isTerminalReplicaRowDeeplyFrozen(row) {
|
|
|
43985
44142
|
DEEPLY_FROZEN_ROWS.add(row);
|
|
43986
44143
|
return true;
|
|
43987
44144
|
}
|
|
43988
|
-
|
|
44145
|
+
function canonicalNumber(value) {
|
|
44146
|
+
const text2 = String(value);
|
|
44147
|
+
return `d${text2.length}:${text2};`;
|
|
44148
|
+
}
|
|
44149
|
+
function canonicalColor(color3) {
|
|
44150
|
+
if (color3.kind === "default") return "o1:s4:kind;s7:default;;";
|
|
44151
|
+
if (color3.kind === "indexed")
|
|
44152
|
+
return `o2:s5:index;${canonicalNumber(color3.index)}s4:kind;s7:indexed;;`;
|
|
44153
|
+
return `o2:s4:kind;s3:rgb;s5:value;${canonicalNumber(color3.value)};`;
|
|
44154
|
+
}
|
|
44155
|
+
function encodeCell(cell) {
|
|
44156
|
+
const grapheme = cell.grapheme;
|
|
44157
|
+
let length = grapheme.length;
|
|
44158
|
+
for (let index = 0; index < grapheme.length; index += 1)
|
|
44159
|
+
if (grapheme.charCodeAt(index) > 127) {
|
|
44160
|
+
length = UTF8_ENCODER.encode(grapheme).byteLength;
|
|
44161
|
+
break;
|
|
44162
|
+
}
|
|
44163
|
+
return UTF8_ENCODER.encode(
|
|
44164
|
+
`a5:s${length}:${grapheme};${canonicalNumber(cell.width)}${canonicalColor(
|
|
44165
|
+
cell.foreground
|
|
44166
|
+
)}${canonicalColor(cell.background)}${canonicalNumber(cell.attributes)};`
|
|
44167
|
+
);
|
|
44168
|
+
}
|
|
44169
|
+
function remember(cache3, key2, bytes) {
|
|
44170
|
+
if (cache3.size >= CELL_BYTES_LIMIT) cache3.clear();
|
|
44171
|
+
cache3.set(key2, bytes);
|
|
44172
|
+
return bytes;
|
|
44173
|
+
}
|
|
44174
|
+
function cellBytes(cell) {
|
|
44175
|
+
const { grapheme, width, attributes, foreground, background } = cell;
|
|
44176
|
+
if (width === 1 && attributes === 0 && foreground.kind === "default" && background.kind === "default")
|
|
44177
|
+
return PLAIN_CELL_BYTES.get(grapheme) ?? remember(PLAIN_CELL_BYTES, grapheme, encodeCell(cell));
|
|
44178
|
+
const key2 = `${width}\0${attributes}\0${canonicalColor(foreground)}\0${canonicalColor(
|
|
44179
|
+
background
|
|
44180
|
+
)}\0${grapheme}`;
|
|
44181
|
+
return STYLED_CELL_BYTES.get(key2) ?? remember(STYLED_CELL_BYTES, key2, encodeCell(cell));
|
|
44182
|
+
}
|
|
44183
|
+
function hashRowBytes(row, native2) {
|
|
44184
|
+
const scratch = native2.scratch;
|
|
44185
|
+
const capacity = scratch.byteLength;
|
|
44186
|
+
let state = FNV64_OFFSET_BASIS;
|
|
44187
|
+
let length = 0;
|
|
44188
|
+
const write2 = (bytes) => {
|
|
44189
|
+
if (bytes.byteLength <= capacity - length) {
|
|
44190
|
+
scratch.set(bytes, length);
|
|
44191
|
+
length += bytes.byteLength;
|
|
44192
|
+
return;
|
|
44193
|
+
}
|
|
44194
|
+
let offset = 0;
|
|
44195
|
+
while (offset < bytes.byteLength) {
|
|
44196
|
+
const count = Math.min(capacity - length, bytes.byteLength - offset);
|
|
44197
|
+
scratch.set(bytes.subarray(offset, offset + count), length);
|
|
44198
|
+
length += count;
|
|
44199
|
+
offset += count;
|
|
44200
|
+
if (length === capacity) {
|
|
44201
|
+
state = BigInt.asUintN(64, native2.update(state, length));
|
|
44202
|
+
length = 0;
|
|
44203
|
+
}
|
|
44204
|
+
}
|
|
44205
|
+
};
|
|
44206
|
+
write2(ASCII_ENCODER.encode(`a2:${row.wrapped ? "b1;" : "b0;"}a${row.cells.length}:`));
|
|
44207
|
+
for (const cell of row.cells) write2(cellBytes(cell));
|
|
44208
|
+
write2(ROW_TRAILER);
|
|
44209
|
+
state = BigInt.asUintN(64, native2.update(state, length));
|
|
44210
|
+
return state.toString(16).padStart(16, "0");
|
|
44211
|
+
}
|
|
44212
|
+
var ROW_HASH_CACHE, DEEPLY_FROZEN_ROWS, UTF8_ENCODER, SHORT_ASCII_HEADERS, DEFAULT_COLOR_KEYS, DEFAULT_COLOR_KEY_ORDER, CanonicalFnv64, compactColorKey, TerminalReplicaRunEncodingCache, DECODED_DEFAULT_COLOR, ASCII_ENCODER, CELL_BYTES_LIMIT, PLAIN_CELL_BYTES, STYLED_CELL_BYTES, ROW_TRAILER;
|
|
43989
44213
|
var init_terminal_replica_hash_cache = __esm({
|
|
43990
44214
|
"packages/core/src/terminal-replica-hash-cache.ts"() {
|
|
43991
44215
|
"use strict";
|
|
@@ -44232,6 +44456,11 @@ var init_terminal_replica_hash_cache = __esm({
|
|
|
44232
44456
|
}
|
|
44233
44457
|
};
|
|
44234
44458
|
DECODED_DEFAULT_COLOR = Object.freeze({ kind: "default" });
|
|
44459
|
+
ASCII_ENCODER = new TextEncoder();
|
|
44460
|
+
CELL_BYTES_LIMIT = 4096;
|
|
44461
|
+
PLAIN_CELL_BYTES = /* @__PURE__ */ new Map();
|
|
44462
|
+
STYLED_CELL_BYTES = /* @__PURE__ */ new Map();
|
|
44463
|
+
ROW_TRAILER = ASCII_ENCODER.encode(";;");
|
|
44235
44464
|
}
|
|
44236
44465
|
});
|
|
44237
44466
|
|
|
@@ -44563,8 +44792,13 @@ async function applyTerminalReplicaUpdateCooperatively(current, update, options)
|
|
|
44563
44792
|
}
|
|
44564
44793
|
const authenticated = options.authenticatedFrameHash;
|
|
44565
44794
|
const frameStart = readProfileClock(options.instrumentation);
|
|
44566
|
-
const
|
|
44567
|
-
|
|
44795
|
+
const reuseAuthenticated = Boolean(authenticated && /^[0-9a-f]{16}$/u.test(authenticated));
|
|
44796
|
+
if (!reuseAuthenticated) {
|
|
44797
|
+
await primeTerminalReplicaRowsHashCooperatively(snapshot3.grid, yieldControl);
|
|
44798
|
+
await primeTerminalReplicaRowsHashCooperatively(snapshot3.history, yieldControl);
|
|
44799
|
+
}
|
|
44800
|
+
const frameHash = reuseAuthenticated ? authenticated : await hashCanonicalTerminalValueCooperatively(
|
|
44801
|
+
terminalReplicaFrameIdentity({ ...admitted, snapshot: snapshot3 }),
|
|
44568
44802
|
yieldControl,
|
|
44569
44803
|
// Bound frame hashing without scheduling a task per few cells.
|
|
44570
44804
|
32 * 1024
|
|
@@ -44841,10 +45075,30 @@ function resolveFrameHash(update, options, profile) {
|
|
|
44841
45075
|
return authenticated;
|
|
44842
45076
|
}
|
|
44843
45077
|
const started = readProfileClock(options.instrumentation);
|
|
44844
|
-
const hash = hashStable(update);
|
|
45078
|
+
const hash = hashStable(terminalReplicaFrameIdentity(update));
|
|
44845
45079
|
addProfileDuration(profile, "updateHash", started, options.instrumentation);
|
|
44846
45080
|
return hash;
|
|
44847
45081
|
}
|
|
45082
|
+
function terminalReplicaFrameIdentity(update) {
|
|
45083
|
+
if (update.type === "terminal.patch") {
|
|
45084
|
+
const { rows, history: history2, historyDelta, ...rest2 } = update.patch;
|
|
45085
|
+
return [
|
|
45086
|
+
"terminal-replica-patch-frame-v2",
|
|
45087
|
+
{ ...update, patch: rest2 },
|
|
45088
|
+
rows.map(({ index, row }) => [index, hashTerminalReplicaRow(row)]),
|
|
45089
|
+
history2 === void 0 ? null : hashTerminalReplicaRows(history2),
|
|
45090
|
+
historyDelta === void 0 ? null : [historyDelta.trim, hashTerminalReplicaRows(historyDelta.append)]
|
|
45091
|
+
];
|
|
45092
|
+
}
|
|
45093
|
+
if (update.type !== "terminal.seed") return update;
|
|
45094
|
+
const { grid, history, ...rest } = update.snapshot;
|
|
45095
|
+
return [
|
|
45096
|
+
"terminal-replica-frame-v2",
|
|
45097
|
+
{ ...update, snapshot: rest },
|
|
45098
|
+
hashTerminalReplicaRows(grid),
|
|
45099
|
+
hashTerminalReplicaRows(history)
|
|
45100
|
+
];
|
|
45101
|
+
}
|
|
44848
45102
|
function readProfileClock(instrumentation) {
|
|
44849
45103
|
if (!instrumentation) return void 0;
|
|
44850
45104
|
try {
|
|
@@ -62237,6 +62491,14 @@ function joinBytes(chunks) {
|
|
|
62237
62491
|
}
|
|
62238
62492
|
return joined;
|
|
62239
62493
|
}
|
|
62494
|
+
function logDeliveryFault(client, reason, cause) {
|
|
62495
|
+
logger.info("terminal-delivery", "fault sent to client", {
|
|
62496
|
+
reason,
|
|
62497
|
+
...cause ? { cause } : {},
|
|
62498
|
+
pane: client.paneId,
|
|
62499
|
+
workspace: client.deliveryWorkspaceName
|
|
62500
|
+
});
|
|
62501
|
+
}
|
|
62240
62502
|
var MAX_CANONICAL_REVISIONS, MAX_RAW_JOURNAL_BYTES, MAX_REPRESENTATION_CACHE_ENTRIES, MAX_REPRESENTATION_CACHE_BYTES, MAX_CLIENTS, MAX_PANES, MAX_PENDING_CANONICAL_CELLS, MAX_CONNECTIONS, BACKGROUND_CADENCE_MS, DeferredProjectionEncoding, DeferredSeedEncoding, ExactSemanticRepresentationSelectionError, TerminalDeliveryRepresentationSelectionError, TerminalDeliveryPreaccountLimitError, SessionRuntimeTerminalDeliveryHub;
|
|
62241
62503
|
var init_terminal_delivery_hub = __esm({
|
|
62242
62504
|
"packages/daemon/src/terminal/session-runtime/terminal-delivery-hub.ts"() {
|
|
@@ -62245,6 +62507,7 @@ var init_terminal_delivery_hub = __esm({
|
|
|
62245
62507
|
init_src2();
|
|
62246
62508
|
init_src3();
|
|
62247
62509
|
init_stock_capture_fidelity();
|
|
62510
|
+
init_log();
|
|
62248
62511
|
init_native_seed_backing();
|
|
62249
62512
|
init_src2();
|
|
62250
62513
|
init_src3();
|
|
@@ -62426,6 +62689,11 @@ var init_terminal_delivery_hub = __esm({
|
|
|
62426
62689
|
};
|
|
62427
62690
|
} catch (error) {
|
|
62428
62691
|
if (!(error instanceof StockCaptureTabUnavailableError)) throw error;
|
|
62692
|
+
logDeliveryFault(
|
|
62693
|
+
{ paneId: semanticPaneId3, deliveryWorkspaceName: address },
|
|
62694
|
+
"source-closed",
|
|
62695
|
+
"capture-unavailable"
|
|
62696
|
+
);
|
|
62429
62697
|
await accept({
|
|
62430
62698
|
type: "terminal.delivery.fault",
|
|
62431
62699
|
reason: "source-closed",
|
|
@@ -62584,6 +62852,7 @@ var init_terminal_delivery_hub = __esm({
|
|
|
62584
62852
|
this.#cancelEncoding(client);
|
|
62585
62853
|
client.outgoing.length = 0;
|
|
62586
62854
|
client.inFlight = null;
|
|
62855
|
+
logDeliveryFault(client, "source-closed", "source-restarted");
|
|
62587
62856
|
this.#enqueue(client, {
|
|
62588
62857
|
type: "terminal.delivery.fault",
|
|
62589
62858
|
reason: "source-closed",
|
|
@@ -63571,6 +63840,7 @@ var init_terminal_delivery_hub = __esm({
|
|
|
63571
63840
|
this.#recordDeliveryStatus(client, this.#panes.get(client.paneId));
|
|
63572
63841
|
}
|
|
63573
63842
|
#fault(client, reason, message, selectionObservation = null) {
|
|
63843
|
+
logDeliveryFault(client, reason);
|
|
63574
63844
|
if (this.#observability.enabled)
|
|
63575
63845
|
try {
|
|
63576
63846
|
const atMicros = this.#observability.nowMicros();
|
|
@@ -72667,6 +72937,7 @@ var init_pane_stream_websocket = __esm({
|
|
|
72667
72937
|
init_src2();
|
|
72668
72938
|
init_src2();
|
|
72669
72939
|
init_src2();
|
|
72940
|
+
init_log();
|
|
72670
72941
|
init_src2();
|
|
72671
72942
|
init_admission_util();
|
|
72672
72943
|
init_registry2();
|
|
@@ -73175,6 +73446,11 @@ var init_pane_stream_websocket = __esm({
|
|
|
73175
73446
|
this.#open = false;
|
|
73176
73447
|
this.#cancelDeadline();
|
|
73177
73448
|
const socket = this.#socket;
|
|
73449
|
+
logger.info("pane-stream", "admission closed", {
|
|
73450
|
+
code: code2,
|
|
73451
|
+
reason,
|
|
73452
|
+
hostClientId: this.hostClientId
|
|
73453
|
+
});
|
|
73178
73454
|
this.#detach();
|
|
73179
73455
|
this.#onRelease(this);
|
|
73180
73456
|
if (socket) safeCloseSocket(socket, code2, reason);
|
|
@@ -73426,6 +73702,12 @@ var init_pane_stream_websocket = __esm({
|
|
|
73426
73702
|
close(code2 = 1e3, reason = "stream-closed") {
|
|
73427
73703
|
if (this.#closed) return;
|
|
73428
73704
|
this.#recordDiagnosticLifecycle("pane-stream-terminal", code2, reason);
|
|
73705
|
+
logger.info("pane-stream", "stream closed", {
|
|
73706
|
+
code: code2,
|
|
73707
|
+
reason,
|
|
73708
|
+
session: this.#descriptor.sessionName,
|
|
73709
|
+
clientId: this.#clientId
|
|
73710
|
+
});
|
|
73429
73711
|
this.#closed = true;
|
|
73430
73712
|
for (const demand of this.#surfaceDemands.values()) demand.close();
|
|
73431
73713
|
this.#surfaceDemands.clear();
|
|
@@ -75719,7 +76001,8 @@ function createNativeTmuxServerCatalog(workspaceRegistry, run, assertOpen = () =
|
|
|
75719
76001
|
"list-panes",
|
|
75720
76002
|
"-a",
|
|
75721
76003
|
"-F",
|
|
75722
|
-
|
|
76004
|
+
// session_path stays last: tmux rejects tabs in session names but not in paths.
|
|
76005
|
+
"#{pid} #{session_id} #{session_created} #{session_name} #{pane_id} #{window_id} #{session_activity} #{session_path}"
|
|
75723
76006
|
].map(shellEscape).join(" ")
|
|
75724
76007
|
],
|
|
75725
76008
|
AbortSignal.timeout(2e3)
|
|
@@ -75728,17 +76011,21 @@ function createNativeTmuxServerCatalog(workspaceRegistry, run, assertOpen = () =
|
|
|
75728
76011
|
const rows = /* @__PURE__ */ new Map();
|
|
75729
76012
|
const lines = raw.trim() === "tmux-ide-empty-catalog-v1" ? [] : raw.trim().split("\n");
|
|
75730
76013
|
for (const line of lines) {
|
|
75731
|
-
const [pid, id2, created, name, pane,
|
|
75732
|
-
|
|
76014
|
+
const [pid, id2, created, name, pane, window2, activity, ...pathParts] = line.split(" ");
|
|
76015
|
+
const dir = pathParts.join(" ");
|
|
76016
|
+
if (!pid || !/^\d+$/.test(pid) || !id2 || !/^\$\d+$/.test(id2) || !created || !/^\d+$/.test(created) || !name || !pane || !/^%\d+$/.test(pane) || !window2 || !/^@\d+$/.test(window2) || !dir)
|
|
75733
76017
|
throw new Error("Invalid native server catalog");
|
|
75734
76018
|
if (!isVisibleFleetSession(name)) continue;
|
|
75735
76019
|
const liveSessionId = liveSessionIdForNativeIdentity(pid, id2, created);
|
|
75736
76020
|
const row = rows.get(liveSessionId) ?? {
|
|
75737
76021
|
summary: { liveSessionId, sessionName: name, paneCount: 0 },
|
|
75738
76022
|
panes: /* @__PURE__ */ new Set(),
|
|
75739
|
-
|
|
76023
|
+
windows: /* @__PURE__ */ new Set(),
|
|
76024
|
+
dir,
|
|
76025
|
+
activity: activity && /^\d+$/.test(activity) ? Number(activity) : null
|
|
75740
76026
|
};
|
|
75741
76027
|
row.panes.add(pane);
|
|
76028
|
+
row.windows.add(window2);
|
|
75742
76029
|
rows.set(liveSessionId, row);
|
|
75743
76030
|
}
|
|
75744
76031
|
const names = new Set([...rows.values()].map(({ summary }) => summary.sessionName));
|
|
@@ -75753,7 +76040,13 @@ function createNativeTmuxServerCatalog(workspaceRegistry, run, assertOpen = () =
|
|
|
75753
76040
|
projectDir: dir,
|
|
75754
76041
|
persistence: "volatile"
|
|
75755
76042
|
});
|
|
75756
|
-
return [...rows.values()].map(({ summary, panes }) => ({
|
|
76043
|
+
return [...rows.values()].map(({ summary, panes, windows, dir, activity }) => ({
|
|
76044
|
+
...summary,
|
|
76045
|
+
paneCount: panes.size,
|
|
76046
|
+
windowCount: windows.size,
|
|
76047
|
+
lastActivity: activity,
|
|
76048
|
+
sessionPath: dir
|
|
76049
|
+
}));
|
|
75757
76050
|
};
|
|
75758
76051
|
}
|
|
75759
76052
|
async function createNativeTmuxServerOwner(options) {
|
|
@@ -76334,6 +76627,8 @@ var init_tmux_server_owners = __esm({
|
|
|
76334
76627
|
#tail = Promise.resolve();
|
|
76335
76628
|
#disposed = false;
|
|
76336
76629
|
#disposePromise = null;
|
|
76630
|
+
#queuedRefresh = null;
|
|
76631
|
+
#queuedRefreshTail = null;
|
|
76337
76632
|
#serial(work) {
|
|
76338
76633
|
const run = this.#tail.then(() => {
|
|
76339
76634
|
if (this.#disposed) throw new TmuxServerScopeError("disposed");
|
|
@@ -76434,10 +76729,19 @@ var init_tmux_server_owners = __esm({
|
|
|
76434
76729
|
this.#entries.set(scope2.serverId, { registration, scope: scope2, observation: observation2, owner });
|
|
76435
76730
|
}
|
|
76436
76731
|
refresh() {
|
|
76437
|
-
|
|
76732
|
+
if (this.#queuedRefresh && this.#tail === this.#queuedRefreshTail) return this.#queuedRefresh;
|
|
76733
|
+
const queued = this.#serial(async () => {
|
|
76734
|
+
if (this.#queuedRefresh === queued) this.#queuedRefresh = null;
|
|
76438
76735
|
for (const entry of this.#entries.values()) await this.#refresh(entry);
|
|
76439
76736
|
return this.list();
|
|
76440
76737
|
});
|
|
76738
|
+
this.#queuedRefresh = queued;
|
|
76739
|
+
this.#queuedRefreshTail = this.#tail;
|
|
76740
|
+
const settle = () => {
|
|
76741
|
+
if (this.#queuedRefresh === queued) this.#queuedRefresh = null;
|
|
76742
|
+
};
|
|
76743
|
+
queued.then(settle, settle);
|
|
76744
|
+
return queued;
|
|
76441
76745
|
}
|
|
76442
76746
|
current(scopeInput) {
|
|
76443
76747
|
const scope2 = TmuxServerScopeSchemaZ.parse(scopeInput);
|
|
@@ -78728,7 +79032,7 @@ function createSharedFleetFactsReaders(run, isAbsentServer = () => false) {
|
|
|
78728
79032
|
}
|
|
78729
79033
|
};
|
|
78730
79034
|
}
|
|
78731
|
-
var DaemonFleetFactsObserver, SESSION_COMPOSITION_TMUX_ARGS, FLEET_FACTS_TMUX_ARGS;
|
|
79035
|
+
var DaemonFleetFactsObserver, FLEET_FACTS_POLL_MS, SESSION_COMPOSITION_TMUX_ARGS, FLEET_FACTS_TMUX_ARGS;
|
|
78732
79036
|
var init_daemon_fleet_facts_observer = __esm({
|
|
78733
79037
|
"packages/daemon/src/command-center/daemon-fleet-facts-observer.ts"() {
|
|
78734
79038
|
"use strict";
|
|
@@ -78763,7 +79067,7 @@ var init_daemon_fleet_facts_observer = __esm({
|
|
|
78763
79067
|
#diagnosticActiveOperations = 0;
|
|
78764
79068
|
constructor(options) {
|
|
78765
79069
|
this.#options = options;
|
|
78766
|
-
this.#intervalMs = options.intervalMs ??
|
|
79070
|
+
this.#intervalMs = options.intervalMs ?? FLEET_FACTS_POLL_MS;
|
|
78767
79071
|
this.#setTimer = options.setTimer ?? ((callback, delayMs) => {
|
|
78768
79072
|
const timer = setTimeout(callback, delayMs);
|
|
78769
79073
|
timer.unref?.();
|
|
@@ -79101,6 +79405,7 @@ var init_daemon_fleet_facts_observer = __esm({
|
|
|
79101
79405
|
return this.#refs.has(demand) && (captured.get(demand) ?? 0) === (this.#demandEpochs.get(demand) ?? 0);
|
|
79102
79406
|
}
|
|
79103
79407
|
};
|
|
79408
|
+
FLEET_FACTS_POLL_MS = 500;
|
|
79104
79409
|
SESSION_COMPOSITION_TMUX_ARGS = [
|
|
79105
79410
|
"list-panes",
|
|
79106
79411
|
"-a",
|
|
@@ -80592,6 +80897,22 @@ var init_daemon_shutdown = __esm({
|
|
|
80592
80897
|
}
|
|
80593
80898
|
});
|
|
80594
80899
|
|
|
80900
|
+
// packages/daemon/src/lib/catalog-fleet-read.ts
|
|
80901
|
+
async function readCatalogFleet(registry, runners, resolveInteractionEndpoint, nativeServerEpoch) {
|
|
80902
|
+
return runners.fence.active ? readAdoptedFleet(registry, runners.fencedSync, resolveInteractionEndpoint, nativeServerEpoch) : readAdoptedFleetAsync(
|
|
80903
|
+
registry,
|
|
80904
|
+
runners.generationFencedAsync,
|
|
80905
|
+
resolveInteractionEndpoint,
|
|
80906
|
+
nativeServerEpoch
|
|
80907
|
+
);
|
|
80908
|
+
}
|
|
80909
|
+
var init_catalog_fleet_read = __esm({
|
|
80910
|
+
"packages/daemon/src/lib/catalog-fleet-read.ts"() {
|
|
80911
|
+
"use strict";
|
|
80912
|
+
init_discovery();
|
|
80913
|
+
}
|
|
80914
|
+
});
|
|
80915
|
+
|
|
80595
80916
|
// packages/daemon/src/lib/workspace-open.ts
|
|
80596
80917
|
import { createHash as createHash25 } from "node:crypto";
|
|
80597
80918
|
import { realpathSync as realpathSync19, statSync as statSync17 } from "node:fs";
|
|
@@ -84761,6 +85082,145 @@ var init_tmux_server_editor_context = __esm({
|
|
|
84761
85082
|
}
|
|
84762
85083
|
});
|
|
84763
85084
|
|
|
85085
|
+
// packages/daemon/src/lib/session-favicon.ts
|
|
85086
|
+
import { constants as constants16 } from "node:fs";
|
|
85087
|
+
import { lstat as lstat4, open as open4 } from "node:fs/promises";
|
|
85088
|
+
import { extname, isAbsolute as isAbsolute24, join as join41 } from "node:path";
|
|
85089
|
+
async function lstatOrNull(io, path2) {
|
|
85090
|
+
try {
|
|
85091
|
+
return await io.lstat(path2);
|
|
85092
|
+
} catch {
|
|
85093
|
+
return null;
|
|
85094
|
+
}
|
|
85095
|
+
}
|
|
85096
|
+
function createSessionFaviconResolver(options = {}) {
|
|
85097
|
+
const io = options.io ?? defaultSessionFaviconIo;
|
|
85098
|
+
const now = options.now ?? Date.now;
|
|
85099
|
+
const missTtlMs = options.missTtlMs ?? 3e4;
|
|
85100
|
+
const maxEntries = options.maxEntries ?? 256;
|
|
85101
|
+
const cache3 = /* @__PURE__ */ new Map();
|
|
85102
|
+
const remember2 = (sessionPath, entry) => {
|
|
85103
|
+
cache3.delete(sessionPath);
|
|
85104
|
+
cache3.set(sessionPath, entry);
|
|
85105
|
+
while (cache3.size > maxEntries) cache3.delete(cache3.keys().next().value);
|
|
85106
|
+
};
|
|
85107
|
+
const scan = async (sessionPath) => {
|
|
85108
|
+
const directories = /* @__PURE__ */ new Map();
|
|
85109
|
+
for (const candidate of SESSION_FAVICON_CANDIDATES) {
|
|
85110
|
+
const mime = MIME_BY_EXTENSION[extname(candidate)];
|
|
85111
|
+
if (!mime) continue;
|
|
85112
|
+
const slash = candidate.lastIndexOf("/");
|
|
85113
|
+
if (slash >= 0) {
|
|
85114
|
+
const parts = candidate.slice(0, slash).split("/");
|
|
85115
|
+
let real = true;
|
|
85116
|
+
for (let index = 1; index <= parts.length && real; index += 1) {
|
|
85117
|
+
const directory2 = parts.slice(0, index).join("/");
|
|
85118
|
+
let known = directories.get(directory2);
|
|
85119
|
+
if (known === void 0) {
|
|
85120
|
+
const stats2 = await lstatOrNull(io, join41(sessionPath, directory2));
|
|
85121
|
+
known = stats2 !== null && stats2.isDirectory() && !stats2.isSymbolicLink();
|
|
85122
|
+
directories.set(directory2, known);
|
|
85123
|
+
}
|
|
85124
|
+
real = known;
|
|
85125
|
+
}
|
|
85126
|
+
if (!real) continue;
|
|
85127
|
+
}
|
|
85128
|
+
const file = join41(sessionPath, candidate);
|
|
85129
|
+
const stats = await lstatOrNull(io, file);
|
|
85130
|
+
if (!stats || !stats.isFile() || stats.size > TMUX_SERVER_SESSION_FAVICON_MAX_BYTES) continue;
|
|
85131
|
+
const bytes = await io.readNoFollow(file, TMUX_SERVER_SESSION_FAVICON_MAX_BYTES);
|
|
85132
|
+
if (!bytes) continue;
|
|
85133
|
+
return {
|
|
85134
|
+
kind: "hit",
|
|
85135
|
+
file,
|
|
85136
|
+
mtimeMs: stats.mtimeMs,
|
|
85137
|
+
size: stats.size,
|
|
85138
|
+
favicon: { mime, data: bytes.toString("base64"), size: bytes.byteLength }
|
|
85139
|
+
};
|
|
85140
|
+
}
|
|
85141
|
+
return { kind: "miss", at: now() };
|
|
85142
|
+
};
|
|
85143
|
+
return async (sessionPath) => {
|
|
85144
|
+
if (!sessionPath || !isAbsolute24(sessionPath) || sessionPath.includes("\0")) return null;
|
|
85145
|
+
const cached2 = cache3.get(sessionPath);
|
|
85146
|
+
if (cached2?.kind === "miss" && now() - cached2.at < missTtlMs) {
|
|
85147
|
+
remember2(sessionPath, cached2);
|
|
85148
|
+
return null;
|
|
85149
|
+
}
|
|
85150
|
+
if (cached2?.kind === "hit") {
|
|
85151
|
+
const stats = await lstatOrNull(io, cached2.file);
|
|
85152
|
+
if (stats && stats.isFile() && stats.mtimeMs === cached2.mtimeMs && stats.size === cached2.size) {
|
|
85153
|
+
remember2(sessionPath, cached2);
|
|
85154
|
+
return cached2.favicon;
|
|
85155
|
+
}
|
|
85156
|
+
}
|
|
85157
|
+
const entry = await scan(sessionPath);
|
|
85158
|
+
remember2(sessionPath, entry);
|
|
85159
|
+
return entry.kind === "hit" ? entry.favicon : null;
|
|
85160
|
+
};
|
|
85161
|
+
}
|
|
85162
|
+
var SESSION_FAVICON_CANDIDATES, MIME_BY_EXTENSION, defaultSessionFaviconIo;
|
|
85163
|
+
var init_session_favicon = __esm({
|
|
85164
|
+
"packages/daemon/src/lib/session-favicon.ts"() {
|
|
85165
|
+
"use strict";
|
|
85166
|
+
init_src2();
|
|
85167
|
+
SESSION_FAVICON_CANDIDATES = [
|
|
85168
|
+
"favicon.svg",
|
|
85169
|
+
"favicon.png",
|
|
85170
|
+
"favicon.ico",
|
|
85171
|
+
"public/favicon.svg",
|
|
85172
|
+
"public/favicon.png",
|
|
85173
|
+
"public/favicon.ico",
|
|
85174
|
+
"app/icon.svg",
|
|
85175
|
+
"app/icon.png",
|
|
85176
|
+
"app/favicon.ico",
|
|
85177
|
+
"src/app/icon.svg",
|
|
85178
|
+
"src/app/icon.png",
|
|
85179
|
+
"src/app/favicon.ico",
|
|
85180
|
+
"static/favicon.svg",
|
|
85181
|
+
"static/favicon.png",
|
|
85182
|
+
"static/favicon.ico",
|
|
85183
|
+
"assets/favicon.svg",
|
|
85184
|
+
"assets/favicon.png",
|
|
85185
|
+
"assets/favicon.ico",
|
|
85186
|
+
"apple-touch-icon.png",
|
|
85187
|
+
"public/apple-touch-icon.png",
|
|
85188
|
+
"icon.svg",
|
|
85189
|
+
"icon.png"
|
|
85190
|
+
];
|
|
85191
|
+
MIME_BY_EXTENSION = {
|
|
85192
|
+
".png": "image/png",
|
|
85193
|
+
".svg": "image/svg+xml",
|
|
85194
|
+
".ico": "image/x-icon",
|
|
85195
|
+
".jpg": "image/jpeg",
|
|
85196
|
+
".jpeg": "image/jpeg",
|
|
85197
|
+
".webp": "image/webp",
|
|
85198
|
+
".gif": "image/gif"
|
|
85199
|
+
};
|
|
85200
|
+
defaultSessionFaviconIo = {
|
|
85201
|
+
lstat: (path2) => lstat4(path2),
|
|
85202
|
+
readNoFollow: async (path2, maxBytes) => {
|
|
85203
|
+
let handle;
|
|
85204
|
+
try {
|
|
85205
|
+
handle = await open4(path2, constants16.O_RDONLY | constants16.O_NOFOLLOW | constants16.O_NONBLOCK);
|
|
85206
|
+
} catch {
|
|
85207
|
+
return null;
|
|
85208
|
+
}
|
|
85209
|
+
try {
|
|
85210
|
+
const stats = await handle.stat();
|
|
85211
|
+
if (!stats.isFile() || stats.size > maxBytes) return null;
|
|
85212
|
+
const bytes = await handle.readFile();
|
|
85213
|
+
return bytes.byteLength > maxBytes ? null : bytes;
|
|
85214
|
+
} catch {
|
|
85215
|
+
return null;
|
|
85216
|
+
} finally {
|
|
85217
|
+
await handle.close().catch(() => void 0);
|
|
85218
|
+
}
|
|
85219
|
+
}
|
|
85220
|
+
};
|
|
85221
|
+
}
|
|
85222
|
+
});
|
|
85223
|
+
|
|
84764
85224
|
// packages/daemon/src/command-center/pane-stream-issue.ts
|
|
84765
85225
|
function issueError(code2, reason, retryable = false) {
|
|
84766
85226
|
return PaneStreamIssueResultSchemaZ.parse({
|
|
@@ -85019,6 +85479,7 @@ function failure(c, error) {
|
|
|
85019
85479
|
}
|
|
85020
85480
|
function mountTmuxServerRoutes(app, options) {
|
|
85021
85481
|
const base2 = TMUX_SERVERS_API_PATH;
|
|
85482
|
+
const resolveSessionFavicon = options.resolveSessionFavicon ?? createSessionFaviconResolver();
|
|
85022
85483
|
const authorize = async (c, next) => {
|
|
85023
85484
|
c.header("Cache-Control", "no-store");
|
|
85024
85485
|
if (!ownerBearerMatches(c.req.header("Authorization"), options.ownerToken))
|
|
@@ -85191,19 +85652,54 @@ function mountTmuxServerRoutes(app, options) {
|
|
|
85191
85652
|
`${scoped}/sessions`,
|
|
85192
85653
|
route(async (c) => {
|
|
85193
85654
|
const server = scope2(c);
|
|
85655
|
+
const v2 = c.req.query("version") === "2";
|
|
85656
|
+
const { rows, favicons } = await options.owners.withOwner(server, async (owner) => {
|
|
85657
|
+
const sessions = await owner.catalog();
|
|
85658
|
+
const workspaces = owner.workspaceRegistry.list();
|
|
85659
|
+
const rows2 = sessions.map((session) => {
|
|
85660
|
+
const aliases = workspaces.filter(
|
|
85661
|
+
(workspace) => workspace.sessionName === session.sessionName
|
|
85662
|
+
);
|
|
85663
|
+
return { session, workspaceName: aliases.length === 1 ? aliases[0].name : null };
|
|
85664
|
+
});
|
|
85665
|
+
const favicons2 = v2 ? await Promise.all(
|
|
85666
|
+
sessions.map(
|
|
85667
|
+
(session) => resolveSessionFavicon(session.sessionPath).catch(() => null)
|
|
85668
|
+
)
|
|
85669
|
+
) : [];
|
|
85670
|
+
return { rows: rows2, favicons: favicons2 };
|
|
85671
|
+
});
|
|
85672
|
+
if (!v2)
|
|
85673
|
+
return c.json(
|
|
85674
|
+
TmuxServerSessionsResourceSchemaZ.parse({
|
|
85675
|
+
version: 1,
|
|
85676
|
+
server,
|
|
85677
|
+
sessions: rows.map(({ session, workspaceName }) => ({
|
|
85678
|
+
liveSessionId: session.liveSessionId,
|
|
85679
|
+
sessionName: session.sessionName,
|
|
85680
|
+
paneCount: session.paneCount,
|
|
85681
|
+
workspaceName
|
|
85682
|
+
}))
|
|
85683
|
+
})
|
|
85684
|
+
);
|
|
85685
|
+
let budget2 = SESSIONS_RESOURCE_FAVICON_BUDGET_BYTES;
|
|
85194
85686
|
return c.json(
|
|
85195
|
-
|
|
85196
|
-
version:
|
|
85687
|
+
TmuxServerSessionsResourceV2SchemaZ.parse({
|
|
85688
|
+
version: 2,
|
|
85197
85689
|
server,
|
|
85198
|
-
sessions:
|
|
85199
|
-
const
|
|
85200
|
-
const
|
|
85201
|
-
|
|
85202
|
-
|
|
85203
|
-
|
|
85204
|
-
|
|
85205
|
-
|
|
85206
|
-
|
|
85690
|
+
sessions: rows.map(({ session, workspaceName }, index) => {
|
|
85691
|
+
const found = favicons[index] ?? null;
|
|
85692
|
+
const favicon = found && found.size <= budget2 ? found : null;
|
|
85693
|
+
if (favicon) budget2 -= favicon.size;
|
|
85694
|
+
return {
|
|
85695
|
+
liveSessionId: session.liveSessionId,
|
|
85696
|
+
sessionName: session.sessionName,
|
|
85697
|
+
workspaceName,
|
|
85698
|
+
paneCount: session.paneCount,
|
|
85699
|
+
windowCount: session.windowCount,
|
|
85700
|
+
lastActivity: session.lastActivity,
|
|
85701
|
+
favicon: favicon ? { mime: favicon.mime, data: favicon.data } : null
|
|
85702
|
+
};
|
|
85207
85703
|
})
|
|
85208
85704
|
})
|
|
85209
85705
|
);
|
|
@@ -85469,7 +85965,7 @@ function mountTmuxServerRoutes(app, options) {
|
|
|
85469
85965
|
})
|
|
85470
85966
|
);
|
|
85471
85967
|
}
|
|
85472
|
-
var registrationSchema, workspaceSchema;
|
|
85968
|
+
var SESSIONS_RESOURCE_FAVICON_BUDGET_BYTES, registrationSchema, workspaceSchema;
|
|
85473
85969
|
var init_tmux_servers = __esm({
|
|
85474
85970
|
"packages/daemon/src/command-center/tmux-servers.ts"() {
|
|
85475
85971
|
"use strict";
|
|
@@ -85484,11 +85980,13 @@ var init_tmux_servers = __esm({
|
|
|
85484
85980
|
init_fleet_catalog2();
|
|
85485
85981
|
init_src2();
|
|
85486
85982
|
init_tmux_server_owners();
|
|
85983
|
+
init_session_favicon();
|
|
85487
85984
|
init_workspace_multiplexer_verbs();
|
|
85488
85985
|
init_workspace_pane_creation2();
|
|
85489
85986
|
init_owner_authority();
|
|
85490
85987
|
init_pane_stream_issue();
|
|
85491
85988
|
init_terminal_runtime_inventory2();
|
|
85989
|
+
SESSIONS_RESOURCE_FAVICON_BUDGET_BYTES = 512 * 1024;
|
|
85492
85990
|
registrationSchema = TmuxServerRegistrationSchemaZ.omit({ serverId: true }).strict();
|
|
85493
85991
|
workspaceSchema = z125.string().min(1).max(160).refine((value) => !/[\0\r\n]/u.test(value));
|
|
85494
85992
|
}
|
|
@@ -85665,9 +86163,9 @@ import {
|
|
|
85665
86163
|
writeFileSync as writeFileSync22,
|
|
85666
86164
|
watch
|
|
85667
86165
|
} from "node:fs";
|
|
85668
|
-
import { basename as basename15, dirname as dirname33, join as
|
|
86166
|
+
import { basename as basename15, dirname as dirname33, join as join42 } from "node:path";
|
|
85669
86167
|
function savedMachinesPath() {
|
|
85670
|
-
return runtimeOwnedPath(
|
|
86168
|
+
return runtimeOwnedPath(join42(resolveRuntimeNamespace().registryDir, "machines.json"));
|
|
85671
86169
|
}
|
|
85672
86170
|
function loadSavedMachines(path2 = savedMachinesPath()) {
|
|
85673
86171
|
let fd;
|
|
@@ -85986,9 +86484,9 @@ import {
|
|
|
85986
86484
|
writeFileSync as writeFileSync23
|
|
85987
86485
|
} from "node:fs";
|
|
85988
86486
|
import { randomUUID as randomUUID43 } from "node:crypto";
|
|
85989
|
-
import { dirname as dirname34, join as
|
|
86487
|
+
import { dirname as dirname34, join as join43 } from "node:path";
|
|
85990
86488
|
function fleetClientStatePath() {
|
|
85991
|
-
return runtimeOwnedPath(
|
|
86489
|
+
return runtimeOwnedPath(join43(resolveRuntimeNamespace().registryDir, "fleet-view.json"));
|
|
85992
86490
|
}
|
|
85993
86491
|
function loadFleetClientState(path2 = fleetClientStatePath()) {
|
|
85994
86492
|
let fd;
|
|
@@ -86221,14 +86719,14 @@ var init_schemas = __esm({
|
|
|
86221
86719
|
import { createHash as createHash28 } from "node:crypto";
|
|
86222
86720
|
import { realpathSync as realpathSync21 } from "node:fs";
|
|
86223
86721
|
import { existsSync as existsSync28, mkdirSync as mkdirSync27, readFileSync as readFileSync29, renameSync as renameSync17, writeFileSync as writeFileSync24 } from "node:fs";
|
|
86224
|
-
import { dirname as dirname35, join as
|
|
86722
|
+
import { dirname as dirname35, join as join44 } from "node:path";
|
|
86225
86723
|
function path(dir) {
|
|
86226
86724
|
const namespace = resolveRuntimeNamespace();
|
|
86227
86725
|
if (namespace.development) {
|
|
86228
86726
|
const identity4 = createHash28("sha256").update(realpathSync21(dir)).digest("hex");
|
|
86229
|
-
return runtimeOwnedPath(
|
|
86727
|
+
return runtimeOwnedPath(join44(namespace.stateHome, "projects", identity4, "terminals.json"));
|
|
86230
86728
|
}
|
|
86231
|
-
return
|
|
86729
|
+
return join44(dir, TERMINALS_FILE);
|
|
86232
86730
|
}
|
|
86233
86731
|
function ensureDir(dir) {
|
|
86234
86732
|
mkdirSync27(dirname35(path(dir)), { recursive: true });
|
|
@@ -86319,7 +86817,7 @@ __export(auth_service_exports, {
|
|
|
86319
86817
|
});
|
|
86320
86818
|
import * as crypto2 from "node:crypto";
|
|
86321
86819
|
import { readFileSync as readFileSync30, existsSync as existsSync29 } from "node:fs";
|
|
86322
|
-
import { join as
|
|
86820
|
+
import { join as join45 } from "node:path";
|
|
86323
86821
|
import { homedir as homedir5 } from "node:os";
|
|
86324
86822
|
function base64url(buf) {
|
|
86325
86823
|
const b = typeof buf === "string" ? Buffer.from(buf) : buf;
|
|
@@ -86465,7 +86963,7 @@ var init_auth_service = __esm({
|
|
|
86465
86963
|
if (resolveRuntimeNamespace().development) return false;
|
|
86466
86964
|
try {
|
|
86467
86965
|
const home = userId === process.env.USER ? homedir5() : `/home/${userId}`;
|
|
86468
|
-
const authKeysPath =
|
|
86966
|
+
const authKeysPath = join45(home, ".ssh", "authorized_keys");
|
|
86469
86967
|
if (!existsSync29(authKeysPath)) return false;
|
|
86470
86968
|
const authorizedKeys = readFileSync30(authKeysPath, "utf-8");
|
|
86471
86969
|
const parts = publicKey.trim().split(" ");
|
|
@@ -89491,7 +89989,7 @@ var init_inspect = __esm({
|
|
|
89491
89989
|
// packages/daemon/src/lib/filesystem-browser.ts
|
|
89492
89990
|
import { realpathSync as realpathSync22, readdirSync as readdirSync6, statSync as statSync19 } from "node:fs";
|
|
89493
89991
|
import { homedir as homedir6 } from "node:os";
|
|
89494
|
-
import { isAbsolute as
|
|
89992
|
+
import { isAbsolute as isAbsolute25, join as join46, resolve as resolve32, sep as sep11 } from "node:path";
|
|
89495
89993
|
function isUnderRoot(canonical, root) {
|
|
89496
89994
|
if (canonical === root) return true;
|
|
89497
89995
|
const prefix = root.endsWith(sep11) ? root : root + sep11;
|
|
@@ -89735,7 +90233,7 @@ var init_detect = __esm({
|
|
|
89735
90233
|
|
|
89736
90234
|
// packages/daemon/src/lib/project-inspect.ts
|
|
89737
90235
|
import { existsSync as existsSync32 } from "node:fs";
|
|
89738
|
-
import { isAbsolute as
|
|
90236
|
+
import { isAbsolute as isAbsolute26, resolve as resolve34 } from "node:path";
|
|
89739
90237
|
function narrowPackageManager(raw) {
|
|
89740
90238
|
if (!raw) return null;
|
|
89741
90239
|
return KNOWN_PACKAGE_MANAGERS.has(raw) ? raw : null;
|
|
@@ -89746,7 +90244,7 @@ function inferTestCommand(packageManager) {
|
|
|
89746
90244
|
}
|
|
89747
90245
|
async function inspectProject(dir, io = {}) {
|
|
89748
90246
|
const exists = io.exists ?? existsSync32;
|
|
89749
|
-
const absoluteDir =
|
|
90247
|
+
const absoluteDir = isAbsolute26(dir) ? dir : resolve34(dir);
|
|
89750
90248
|
if (!exists(absoluteDir)) {
|
|
89751
90249
|
throw new InspectDirNotFoundError(absoluteDir);
|
|
89752
90250
|
}
|
|
@@ -90606,7 +91104,7 @@ var init_workspace_changes_git = __esm({
|
|
|
90606
91104
|
// packages/daemon/src/command-center/resources/workspace-changes-authority.ts
|
|
90607
91105
|
import { spawnSync } from "node:child_process";
|
|
90608
91106
|
import { readFileSync as readFileSync33, realpathSync as realpathSync24, statSync as statSync20 } from "node:fs";
|
|
90609
|
-
import { basename as basename18, isAbsolute as
|
|
91107
|
+
import { basename as basename18, isAbsolute as isAbsolute27, relative as relative8, resolve as resolvePath2 } from "node:path";
|
|
90610
91108
|
function runGit(args, cwd) {
|
|
90611
91109
|
const result2 = spawnSync("git", args, {
|
|
90612
91110
|
cwd,
|
|
@@ -90650,7 +91148,7 @@ function confineToWorkspace(realRoot, repoRoot, gitPath) {
|
|
|
90650
91148
|
if (gitPath.length === 0 || gitPath.includes("\0")) return null;
|
|
90651
91149
|
const abs = resolvePath2(repoRoot, gitPath);
|
|
90652
91150
|
const rel = relative8(realRoot, abs);
|
|
90653
|
-
if (rel.length === 0 || rel.startsWith("..") ||
|
|
91151
|
+
if (rel.length === 0 || rel.startsWith("..") || isAbsolute27(rel)) return null;
|
|
90654
91152
|
const display = rel.split(/[\\/]+/u).join("/");
|
|
90655
91153
|
return WorkspaceRelativeDisplayPathSchemaZ.safeParse(display).success ? display : null;
|
|
90656
91154
|
}
|
|
@@ -92878,9 +93376,9 @@ import {
|
|
|
92878
93376
|
rmSync as rmSync5,
|
|
92879
93377
|
writeFileSync as writeFileSync25
|
|
92880
93378
|
} from "node:fs";
|
|
92881
|
-
import { join as
|
|
93379
|
+
import { join as join47 } from "node:path";
|
|
92882
93380
|
function assetRoot() {
|
|
92883
|
-
return runtimeOwnedPath(
|
|
93381
|
+
return runtimeOwnedPath(join47(stateHome(), ASSET_DIRECTORY));
|
|
92884
93382
|
}
|
|
92885
93383
|
function ensureAssetRoot() {
|
|
92886
93384
|
const root = assetRoot();
|
|
@@ -92900,8 +93398,8 @@ function safeName2(name) {
|
|
|
92900
93398
|
}
|
|
92901
93399
|
function assetPaths(root, assetId) {
|
|
92902
93400
|
return {
|
|
92903
|
-
data:
|
|
92904
|
-
metadata:
|
|
93401
|
+
data: join47(root, `${assetId}.bin`),
|
|
93402
|
+
metadata: join47(root, `${assetId}.json`)
|
|
92905
93403
|
};
|
|
92906
93404
|
}
|
|
92907
93405
|
function parseMetadata(raw) {
|
|
@@ -92926,7 +93424,7 @@ function parseMetadata(raw) {
|
|
|
92926
93424
|
}
|
|
92927
93425
|
function pruneAssets(root, now = Date.now()) {
|
|
92928
93426
|
const metadataFiles = readdirSync8(root).filter((name) => /^[0-9a-f]{64}\.json$/u.test(name)).map((name) => {
|
|
92929
|
-
const path2 =
|
|
93427
|
+
const path2 = join47(root, name);
|
|
92930
93428
|
try {
|
|
92931
93429
|
const stat3 = lstatSync14(path2);
|
|
92932
93430
|
return stat3.isFile() && !stat3.isSymbolicLink() ? { name, mtimeMs: stat3.mtimeMs } : null;
|
|
@@ -92937,8 +93435,8 @@ function pruneAssets(root, now = Date.now()) {
|
|
|
92937
93435
|
for (const [index, entry] of metadataFiles.entries()) {
|
|
92938
93436
|
if (index < MAX_ASSET_FILES && now - entry.mtimeMs <= WIDGET_ASSET_RETENTION_MS) continue;
|
|
92939
93437
|
const assetId = entry.name.slice(0, -".json".length);
|
|
92940
|
-
rmSync5(
|
|
92941
|
-
rmSync5(
|
|
93438
|
+
rmSync5(join47(root, `${assetId}.json`), { force: true });
|
|
93439
|
+
rmSync5(join47(root, `${assetId}.bin`), { force: true });
|
|
92942
93440
|
}
|
|
92943
93441
|
}
|
|
92944
93442
|
function publishWidgetAsset(bytes, options) {
|
|
@@ -92967,11 +93465,11 @@ function publishWidgetAsset(bytes, options) {
|
|
|
92967
93465
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
92968
93466
|
};
|
|
92969
93467
|
if (!existsSync33(paths.data)) {
|
|
92970
|
-
const temporary =
|
|
93468
|
+
const temporary = join47(root, `.${assetId}.${randomUUID45()}.bin`);
|
|
92971
93469
|
writeFileSync25(temporary, bytes, { mode: 384, flag: "wx" });
|
|
92972
93470
|
renameSync18(temporary, paths.data);
|
|
92973
93471
|
}
|
|
92974
|
-
const metadataTemporary =
|
|
93472
|
+
const metadataTemporary = join47(root, `.${assetId}.${randomUUID45()}.json`);
|
|
92975
93473
|
writeFileSync25(metadataTemporary, `${JSON.stringify(metadata)}
|
|
92976
93474
|
`, { mode: 384, flag: "wx" });
|
|
92977
93475
|
renameSync18(metadataTemporary, paths.metadata);
|
|
@@ -93033,7 +93531,7 @@ __export(server_exports2, {
|
|
|
93033
93531
|
import { execFile as execFile14 } from "node:child_process";
|
|
93034
93532
|
import { promisify as promisify4 } from "node:util";
|
|
93035
93533
|
import { existsSync as existsSync34, readdirSync as readdirSync9 } from "node:fs";
|
|
93036
|
-
import { join as
|
|
93534
|
+
import { join as join48, dirname as dirname38, basename as basename19 } from "node:path";
|
|
93037
93535
|
import { fileURLToPath as fileURLToPath10 } from "node:url";
|
|
93038
93536
|
import { Hono as Hono3 } from "hono";
|
|
93039
93537
|
import { streamSSE as streamSSE3 } from "hono/streaming";
|
|
@@ -93042,7 +93540,7 @@ import { zValidator } from "@hono/zod-validator";
|
|
|
93042
93540
|
import { z as z130 } from "zod";
|
|
93043
93541
|
import { realpathSync as realpathSync25 } from "node:fs";
|
|
93044
93542
|
import { homedir as homedir7 } from "node:os";
|
|
93045
|
-
import { isAbsolute as
|
|
93543
|
+
import { isAbsolute as isAbsolute28, resolve as pathResolve } from "node:path";
|
|
93046
93544
|
import { randomUUID as randomUUID46 } from "node:crypto";
|
|
93047
93545
|
import { WebSocketServer as WebSocketServer4 } from "ws";
|
|
93048
93546
|
function bearerToken(authHeader) {
|
|
@@ -93148,7 +93646,7 @@ function sandboxResolveDir(rawDir) {
|
|
|
93148
93646
|
} else if (candidate.startsWith("~/")) {
|
|
93149
93647
|
candidate = `${home.replace(/\/+$/, "")}/${candidate.slice(2)}`;
|
|
93150
93648
|
}
|
|
93151
|
-
if (!
|
|
93649
|
+
if (!isAbsolute28(candidate)) {
|
|
93152
93650
|
return { error: "invalid-path", message: "Path must be absolute", status: 400 };
|
|
93153
93651
|
}
|
|
93154
93652
|
const resolved2 = pathResolve(candidate);
|
|
@@ -94285,7 +94783,7 @@ function listAvailableTemplates() {
|
|
|
94285
94783
|
const __filename = fileURLToPath10(import.meta.url);
|
|
94286
94784
|
const __dir = dirname38(__filename);
|
|
94287
94785
|
const configuredTemplatesDir = process.env.TMUX_IDE_TEMPLATES_DIR;
|
|
94288
|
-
const templatesDir = configuredTemplatesDir &&
|
|
94786
|
+
const templatesDir = configuredTemplatesDir && isAbsolute28(configuredTemplatesDir) ? configuredTemplatesDir : join48(__dir, "..", "..", "..", "..", "templates");
|
|
94289
94787
|
if (!existsSync34(templatesDir)) return [];
|
|
94290
94788
|
const labels = {
|
|
94291
94789
|
default: { label: "Default", description: "Single Claude pane + dev/shell row" },
|
|
@@ -94482,7 +94980,7 @@ var init_types = __esm({
|
|
|
94482
94980
|
});
|
|
94483
94981
|
|
|
94484
94982
|
// packages/daemon/src/lib/daemon-embed.ts
|
|
94485
|
-
import { dirname as dirname39, join as
|
|
94983
|
+
import { dirname as dirname39, join as join49 } from "node:path";
|
|
94486
94984
|
import { execFileSync as execFileSync21 } from "node:child_process";
|
|
94487
94985
|
import { randomBytes as randomBytes9, randomUUID as randomUUID47 } from "node:crypto";
|
|
94488
94986
|
import { createWriteStream } from "node:fs";
|
|
@@ -95158,7 +95656,7 @@ async function startEmbeddedDaemonGeneration(opts) {
|
|
|
95158
95656
|
execFileSync21(tmuxAuthority.executablePath, ["-V"], { encoding: "utf8", timeout: 3e3 })
|
|
95159
95657
|
);
|
|
95160
95658
|
const readTeamMemberships = createClaudeTeamMembershipReader(
|
|
95161
|
-
|
|
95659
|
+
join49(resolveRuntimeNamespace().claudeDir, "teams")
|
|
95162
95660
|
);
|
|
95163
95661
|
const catalogTmuxRunner = createPinnedWorkspaceTmuxRunner(tmuxAuthority);
|
|
95164
95662
|
const initialTmuxProof = captureTmuxServerProof(catalogTmuxRunner);
|
|
@@ -95958,15 +96456,21 @@ async function startEmbeddedDaemonGeneration(opts) {
|
|
|
95958
96456
|
paneStreamRuntime,
|
|
95959
96457
|
catalogLiveSessions: () => discoverLiveSessionSummaries(catalogTmuxRunner),
|
|
95960
96458
|
catalogFleet: async () => {
|
|
95961
|
-
const
|
|
96459
|
+
const endpoint = (sessionName2, pane) => pane.semanticPaneId ? interactionEvidence?.captureInventoryEndpoint(
|
|
96460
|
+
sessionName2,
|
|
96461
|
+
pane.runtimePaneId,
|
|
96462
|
+
pane.semanticPaneId
|
|
96463
|
+
) ?? null : null;
|
|
96464
|
+
const epoch = () => observationSelector?.nativeServerEpoch ?? null;
|
|
96465
|
+
const fleet = await readCatalogFleet(
|
|
95962
96466
|
workspaceRegistry,
|
|
95963
|
-
|
|
95964
|
-
|
|
95965
|
-
|
|
95966
|
-
|
|
95967
|
-
|
|
95968
|
-
|
|
95969
|
-
|
|
96467
|
+
{
|
|
96468
|
+
fence: sessionMutationFence,
|
|
96469
|
+
fencedSync: nativeGenerationTmuxRunner,
|
|
96470
|
+
generationFencedAsync: (args) => fleetFactsTmuxRunner(args)
|
|
96471
|
+
},
|
|
96472
|
+
endpoint,
|
|
96473
|
+
epoch
|
|
95970
96474
|
);
|
|
95971
96475
|
if (!fleet) return null;
|
|
95972
96476
|
const names = await readTeamMemberships(
|
|
@@ -96418,6 +96922,7 @@ var init_daemon_embed = __esm({
|
|
|
96418
96922
|
init_workspace_registry();
|
|
96419
96923
|
init_workspace_pane_creation2();
|
|
96420
96924
|
init_discovery();
|
|
96925
|
+
init_catalog_fleet_read();
|
|
96421
96926
|
init_workspace_open2();
|
|
96422
96927
|
init_workspace_promotion2();
|
|
96423
96928
|
init_workspace_open_handoff2();
|
|
@@ -96825,7 +97330,7 @@ __export(development_owner_exports, {
|
|
|
96825
97330
|
verifyManagedDevelopmentAdmission: () => verifyManagedDevelopmentAdmission
|
|
96826
97331
|
});
|
|
96827
97332
|
import { realpathSync as realpathSync26, writeFileSync as writeFileSync26 } from "node:fs";
|
|
96828
|
-
import { join as
|
|
97333
|
+
import { join as join50 } from "node:path";
|
|
96829
97334
|
async function claimManagedDevelopmentLaunch(instance, attempt) {
|
|
96830
97335
|
if (!/^[a-f0-9-]{36}$/u.test(attempt)) throw new Error("Invalid development launch attempt");
|
|
96831
97336
|
const owner = readDevelopmentOwner(instance);
|
|
@@ -96833,7 +97338,7 @@ async function claimManagedDevelopmentLaunch(instance, attempt) {
|
|
|
96833
97338
|
throw new Error("A live or unknown managed owner is protected");
|
|
96834
97339
|
requireDevelopmentNotSuspended(instance);
|
|
96835
97340
|
writeFileSync26(
|
|
96836
|
-
|
|
97341
|
+
join50(instance.root, `launch-${attempt}.json`),
|
|
96837
97342
|
JSON.stringify({ version: 1, attempt, pid: process.pid }),
|
|
96838
97343
|
{ flag: "wx", mode: 384 }
|
|
96839
97344
|
);
|
|
@@ -96842,7 +97347,7 @@ async function claimManagedDevelopmentLaunch(instance, attempt) {
|
|
|
96842
97347
|
function verifyManagedDevelopmentAdmission(instance, attempt, expected) {
|
|
96843
97348
|
requireDevelopmentNotSuspended(instance);
|
|
96844
97349
|
const current = readPrivateDevelopmentRecord(
|
|
96845
|
-
|
|
97350
|
+
join50(instance.root, "startup.json")
|
|
96846
97351
|
);
|
|
96847
97352
|
if (!current || current.attempt !== attempt || current.attempt !== expected.attempt || current.generation !== expected.generation || current.manifestHash !== expected.manifestHash)
|
|
96848
97353
|
throw new Error("Managed owner admission changed before startup");
|
|
@@ -96853,7 +97358,7 @@ async function runManagedDevelopmentOwner() {
|
|
|
96853
97358
|
if (!instance) throw new Error("Managed development owner requires a development namespace");
|
|
96854
97359
|
const identity4 = await readDevelopmentIdentity(instance);
|
|
96855
97360
|
const attempt = process.env.TMUX_IDE_DEVELOPMENT_ATTEMPT;
|
|
96856
|
-
const pending = readPrivateDevelopmentRecord(
|
|
97361
|
+
const pending = readPrivateDevelopmentRecord(join50(instance.root, "startup.json"));
|
|
96857
97362
|
const build = readDevelopmentBuild(instance);
|
|
96858
97363
|
if (!identity4 || identity4.capability !== namespace.cleanupToken || !attempt || pending?.attempt !== attempt || pending.generation !== build.generation || pending.manifestHash !== process.env.TMUX_IDE_DEVELOPMENT_BUILD_HASH)
|
|
96859
97364
|
throw new Error("Development launch admission does not match owner");
|
|
@@ -96863,7 +97368,7 @@ async function runManagedDevelopmentOwner() {
|
|
|
96863
97368
|
if (!incarnation) throw new Error("Cannot establish managed owner incarnation");
|
|
96864
97369
|
await claimManagedDevelopmentLaunch(instance, attempt);
|
|
96865
97370
|
verifyManagedDevelopmentAdmission(instance, attempt, pending);
|
|
96866
|
-
const log = createBoundedDevelopmentLog(
|
|
97371
|
+
const log = createBoundedDevelopmentLog(join50(instance.root, "logs/owner.log"));
|
|
96867
97372
|
const originalOut = process.stdout.write;
|
|
96868
97373
|
const originalErr = process.stderr.write;
|
|
96869
97374
|
const writer = ((chunk, encodingOrCallback, callback) => {
|
|
@@ -96880,7 +97385,7 @@ async function runManagedDevelopmentOwner() {
|
|
|
96880
97385
|
json: true,
|
|
96881
97386
|
expectedVersion: build.packageVersion,
|
|
96882
97387
|
onOwnedReady: () => {
|
|
96883
|
-
writeDevelopmentRecord(
|
|
97388
|
+
writeDevelopmentRecord(join50(instance.root, "owner.json"), {
|
|
96884
97389
|
version: 1,
|
|
96885
97390
|
attempt,
|
|
96886
97391
|
pid: process.pid,
|
|
@@ -96927,7 +97432,7 @@ import {
|
|
|
96927
97432
|
readdirSync as readdirSync10,
|
|
96928
97433
|
copyFileSync as copyFileSync2
|
|
96929
97434
|
} from "node:fs";
|
|
96930
|
-
import { resolve as resolve35, join as
|
|
97435
|
+
import { resolve as resolve35, join as join51, basename as basename20, dirname as dirname40 } from "node:path";
|
|
96931
97436
|
import { fileURLToPath as fileURLToPath11 } from "node:url";
|
|
96932
97437
|
function copyTemplateSkills(targetDir) {
|
|
96933
97438
|
const created = [];
|
|
@@ -96936,20 +97441,20 @@ function copyTemplateSkills(targetDir) {
|
|
|
96936
97441
|
mkdirSync29(targetDir, { recursive: true });
|
|
96937
97442
|
for (const file of readdirSync10(templateSkillsDir)) {
|
|
96938
97443
|
if (!file.endsWith(".md")) continue;
|
|
96939
|
-
const destination =
|
|
96940
|
-
copyFileSync2(
|
|
97444
|
+
const destination = join51(targetDir, file);
|
|
97445
|
+
copyFileSync2(join51(templateSkillsDir, file), destination);
|
|
96941
97446
|
created.push(destination);
|
|
96942
97447
|
}
|
|
96943
97448
|
return created;
|
|
96944
97449
|
}
|
|
96945
97450
|
function scaffoldLibraryStubs(dir) {
|
|
96946
97451
|
const created = [];
|
|
96947
|
-
const libraryDir =
|
|
97452
|
+
const libraryDir = join51(dir, ".tmux-ide", "library");
|
|
96948
97453
|
if (!existsSync35(libraryDir)) {
|
|
96949
97454
|
mkdirSync29(libraryDir, { recursive: true });
|
|
96950
97455
|
created.push(libraryDir);
|
|
96951
97456
|
}
|
|
96952
|
-
const archPath =
|
|
97457
|
+
const archPath = join51(libraryDir, "architecture.md");
|
|
96953
97458
|
if (!existsSync35(archPath)) {
|
|
96954
97459
|
writeFileSync27(
|
|
96955
97460
|
archPath,
|
|
@@ -96957,7 +97462,7 @@ function scaffoldLibraryStubs(dir) {
|
|
|
96957
97462
|
);
|
|
96958
97463
|
created.push(archPath);
|
|
96959
97464
|
}
|
|
96960
|
-
const learningsPath =
|
|
97465
|
+
const learningsPath = join51(libraryDir, "learnings.md");
|
|
96961
97466
|
if (!existsSync35(learningsPath)) {
|
|
96962
97467
|
writeFileSync27(
|
|
96963
97468
|
learningsPath,
|
|
@@ -96969,11 +97474,11 @@ function scaffoldLibraryStubs(dir) {
|
|
|
96969
97474
|
}
|
|
96970
97475
|
function scaffoldValidationContract(dir) {
|
|
96971
97476
|
const created = [];
|
|
96972
|
-
const tasksDir =
|
|
97477
|
+
const tasksDir = join51(dir, ".tasks");
|
|
96973
97478
|
if (!existsSync35(tasksDir)) {
|
|
96974
97479
|
mkdirSync29(tasksDir, { recursive: true });
|
|
96975
97480
|
}
|
|
96976
|
-
const contractPath =
|
|
97481
|
+
const contractPath = join51(tasksDir, "validation-contract.md");
|
|
96977
97482
|
if (!existsSync35(contractPath)) {
|
|
96978
97483
|
writeFileSync27(
|
|
96979
97484
|
contractPath,
|
|
@@ -96987,7 +97492,7 @@ function scaffoldAgentsMd(dir, name) {
|
|
|
96987
97492
|
const created = [];
|
|
96988
97493
|
const agentsTemplatePath = resolve35(__dirname4, "..", "..", "..", "templates", "AGENTS.md");
|
|
96989
97494
|
if (existsSync35(agentsTemplatePath)) {
|
|
96990
|
-
const agentsPath =
|
|
97495
|
+
const agentsPath = join51(dir, "AGENTS.md");
|
|
96991
97496
|
if (!existsSync35(agentsPath)) {
|
|
96992
97497
|
const content = readFileSync35(agentsTemplatePath, "utf-8").replace(/{{name}}/g, name);
|
|
96993
97498
|
writeFileSync27(agentsPath, content);
|
|
@@ -97008,7 +97513,7 @@ function scaffoldTeamWorkspace(dir, name) {
|
|
|
97008
97513
|
}
|
|
97009
97514
|
function scaffoldMissionsWorkspace(dir, name) {
|
|
97010
97515
|
const created = [];
|
|
97011
|
-
const skillsDir =
|
|
97516
|
+
const skillsDir = join51(dir, ".tmux-ide", "skills");
|
|
97012
97517
|
created.push(...copyTemplateSkills(skillsDir));
|
|
97013
97518
|
created.push(...scaffoldTeamWorkspace(dir, name));
|
|
97014
97519
|
return created;
|
|
@@ -97040,11 +97545,11 @@ async function init({
|
|
|
97040
97545
|
created = scaffoldMissionsWorkspace(dir, name2);
|
|
97041
97546
|
} else if (isTeamTemplate(template)) {
|
|
97042
97547
|
created = [
|
|
97043
|
-
...copyTemplateSkills(
|
|
97548
|
+
...copyTemplateSkills(join51(dir, ".tmux-ide", "skills")),
|
|
97044
97549
|
...scaffoldTeamWorkspace(dir, name2)
|
|
97045
97550
|
];
|
|
97046
97551
|
} else {
|
|
97047
|
-
created = copyTemplateSkills(
|
|
97552
|
+
created = copyTemplateSkills(join51(dir, ".tmux-ide", "skills"));
|
|
97048
97553
|
}
|
|
97049
97554
|
if (json3) {
|
|
97050
97555
|
console.log(JSON.stringify({ created: true, template, name: name2, paths: created }));
|
|
@@ -97086,7 +97591,7 @@ async function init({
|
|
|
97086
97591
|
console.log("Edit it to configure your workspace, then run: tmux-ide");
|
|
97087
97592
|
}
|
|
97088
97593
|
}
|
|
97089
|
-
const skillsDir =
|
|
97594
|
+
const skillsDir = join51(dir, ".tmux-ide", "skills");
|
|
97090
97595
|
if (!existsSync35(skillsDir)) {
|
|
97091
97596
|
const created = copyTemplateSkills(skillsDir);
|
|
97092
97597
|
if (created.length > 0 && !json3) {
|
|
@@ -97141,19 +97646,21 @@ var init_stop = __esm({
|
|
|
97141
97646
|
// packages/daemon/src/open-browser.ts
|
|
97142
97647
|
var open_browser_exports = {};
|
|
97143
97648
|
__export(open_browser_exports, {
|
|
97649
|
+
NO_NATIVE_CONTROLS_NOTICE: () => NO_NATIVE_CONTROLS_NOTICE,
|
|
97144
97650
|
createBrowserPane: () => createBrowserPane,
|
|
97651
|
+
nativeControlsNotice: () => nativeControlsNotice,
|
|
97145
97652
|
openBrowser: () => openBrowser,
|
|
97146
97653
|
resolveTerminalBrowser: () => resolveTerminalBrowser,
|
|
97147
97654
|
validateBrowserOpen: () => validateBrowserOpen
|
|
97148
97655
|
});
|
|
97149
|
-
import { accessSync as accessSync10, constants as
|
|
97150
|
-
import { delimiter as delimiter4, isAbsolute as
|
|
97656
|
+
import { accessSync as accessSync10, constants as constants17, realpathSync as realpathSync27, statSync as statSync21 } from "node:fs";
|
|
97657
|
+
import { delimiter as delimiter4, isAbsolute as isAbsolute29, join as join52, resolve as resolve37 } from "node:path";
|
|
97151
97658
|
import { homedir as homedir8 } from "node:os";
|
|
97152
97659
|
function resolveTerminalBrowser(environment = process.env, platform2 = process.platform) {
|
|
97153
97660
|
const configured = environment.TMUX_IDE_TERMINAL_BROWSER_BIN;
|
|
97154
97661
|
const home = environment.HOME ?? homedir8();
|
|
97155
|
-
const bundled = platform2 === "darwin" &&
|
|
97156
|
-
|
|
97662
|
+
const bundled = platform2 === "darwin" && isAbsolute29(home) ? [
|
|
97663
|
+
join52(
|
|
97157
97664
|
home,
|
|
97158
97665
|
"Library",
|
|
97159
97666
|
"Application Support",
|
|
@@ -97168,12 +97675,12 @@ function resolveTerminalBrowser(environment = process.env, platform2 = process.p
|
|
|
97168
97675
|
] : [];
|
|
97169
97676
|
const candidates = configured ? [configured] : [
|
|
97170
97677
|
...bundled,
|
|
97171
|
-
...(environment.PATH ?? "").split(delimiter4).filter(
|
|
97678
|
+
...(environment.PATH ?? "").split(delimiter4).filter(isAbsolute29).map((dir) => join52(dir, "terminal-browser"))
|
|
97172
97679
|
];
|
|
97173
97680
|
for (const candidate of candidates) {
|
|
97174
97681
|
try {
|
|
97175
|
-
if (!
|
|
97176
|
-
accessSync10(candidate,
|
|
97682
|
+
if (!isAbsolute29(candidate)) continue;
|
|
97683
|
+
accessSync10(candidate, constants17.X_OK);
|
|
97177
97684
|
const path2 = realpathSync27(candidate);
|
|
97178
97685
|
if (statSync21(path2).isFile()) return path2;
|
|
97179
97686
|
} catch {
|
|
@@ -97218,6 +97725,26 @@ function validateBrowserOpen(url, options) {
|
|
|
97218
97725
|
exitCode: 2
|
|
97219
97726
|
});
|
|
97220
97727
|
}
|
|
97728
|
+
function isBundledBrowser(executable) {
|
|
97729
|
+
return /\/[^/]+\.app\/Contents\/Resources\/browser\//u.test(executable);
|
|
97730
|
+
}
|
|
97731
|
+
async function nativeControlsNotice(run, pane, executable, wait = {}) {
|
|
97732
|
+
if (isBundledBrowser(executable)) return null;
|
|
97733
|
+
const sleep3 = wait.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
97734
|
+
const now = wait.now ?? Date.now;
|
|
97735
|
+
const deadline = now() + STANDALONE_WAIT_MS;
|
|
97736
|
+
for (; ; ) {
|
|
97737
|
+
let control;
|
|
97738
|
+
try {
|
|
97739
|
+
control = run(["display-message", "-p", "-t", pane, "#{@tmux_ide_browser_control}"]).trim();
|
|
97740
|
+
} catch {
|
|
97741
|
+
return null;
|
|
97742
|
+
}
|
|
97743
|
+
if (control) return null;
|
|
97744
|
+
if (now() >= deadline) return NO_NATIVE_CONTROLS_NOTICE;
|
|
97745
|
+
await sleep3(250);
|
|
97746
|
+
}
|
|
97747
|
+
}
|
|
97221
97748
|
function createBrowserPane(run, executable, url, options, environment, cwd, namespace) {
|
|
97222
97749
|
validateBrowserOpen(url, options);
|
|
97223
97750
|
const inheritedPane = /^%\d+$/u.test(environment.TMUX_PANE ?? "") ? environment.TMUX_PANE : void 0;
|
|
@@ -97289,9 +97816,21 @@ function createBrowserPane(run, executable, url, options, environment, cwd, name
|
|
|
97289
97816
|
});
|
|
97290
97817
|
return { pane, session: createdSession, window: createdWindow, status: "created" };
|
|
97291
97818
|
}
|
|
97292
|
-
function openBrowser(url, options = {}) {
|
|
97819
|
+
async function openBrowser(url, options = {}, dependencies = {}) {
|
|
97293
97820
|
validateBrowserOpen(url, options);
|
|
97294
|
-
const executable = resolveTerminalBrowser();
|
|
97821
|
+
const executable = (dependencies.executable ?? resolveTerminalBrowser)();
|
|
97822
|
+
const { result: result2, run } = (dependencies.create ?? createPinnedBrowserPane)(
|
|
97823
|
+
executable,
|
|
97824
|
+
url,
|
|
97825
|
+
options
|
|
97826
|
+
);
|
|
97827
|
+
const message = await nativeControlsNotice(run, result2.pane, executable, dependencies.wait);
|
|
97828
|
+
if (message)
|
|
97829
|
+
(dependencies.notice ?? ((line) => process.stderr.write(`${line}
|
|
97830
|
+
`)))(message);
|
|
97831
|
+
return result2;
|
|
97832
|
+
}
|
|
97833
|
+
function createPinnedBrowserPane(executable, url, options) {
|
|
97295
97834
|
try {
|
|
97296
97835
|
const namespace = { ...runtimeNamespaceEnvironment(resolveRuntimeNamespace()) };
|
|
97297
97836
|
const authority2 = resolveWorkspacePaneTmuxAuthority();
|
|
@@ -97299,7 +97838,16 @@ function openBrowser(url, options = {}) {
|
|
|
97299
97838
|
const run = createPinnedWorkspaceTmuxRunner(authority2, {
|
|
97300
97839
|
timeoutMs: 1e4
|
|
97301
97840
|
});
|
|
97302
|
-
|
|
97841
|
+
const result2 = createBrowserPane(
|
|
97842
|
+
run,
|
|
97843
|
+
executable,
|
|
97844
|
+
url,
|
|
97845
|
+
options,
|
|
97846
|
+
process.env,
|
|
97847
|
+
process.cwd(),
|
|
97848
|
+
namespace
|
|
97849
|
+
);
|
|
97850
|
+
return { result: result2, run };
|
|
97303
97851
|
} catch (error) {
|
|
97304
97852
|
if (error instanceof IdeError) throw error;
|
|
97305
97853
|
throw new IdeError(
|
|
@@ -97311,12 +97859,15 @@ function openBrowser(url, options = {}) {
|
|
|
97311
97859
|
);
|
|
97312
97860
|
}
|
|
97313
97861
|
}
|
|
97862
|
+
var NO_NATIVE_CONTROLS_NOTICE, STANDALONE_WAIT_MS;
|
|
97314
97863
|
var init_open_browser = __esm({
|
|
97315
97864
|
"packages/daemon/src/open-browser.ts"() {
|
|
97316
97865
|
"use strict";
|
|
97317
97866
|
init_errors2();
|
|
97318
97867
|
init_runtime_namespace();
|
|
97319
97868
|
init_workspace_pane_creation2();
|
|
97869
|
+
NO_NATIVE_CONTROLS_NOTICE = "This browser has no tmux-ide controls; install the native app for back/forward/reload.";
|
|
97870
|
+
STANDALONE_WAIT_MS = 2e3;
|
|
97320
97871
|
}
|
|
97321
97872
|
});
|
|
97322
97873
|
|
|
@@ -97475,7 +98026,7 @@ var init_daemon_service_manager = __esm({
|
|
|
97475
98026
|
|
|
97476
98027
|
// packages/daemon/src/lib/daemon-service-plan.ts
|
|
97477
98028
|
import { createHash as createHash34 } from "node:crypto";
|
|
97478
|
-
import { isAbsolute as
|
|
98029
|
+
import { isAbsolute as isAbsolute30, join as join53 } from "node:path";
|
|
97479
98030
|
function safeValue(value, name) {
|
|
97480
98031
|
if (!value || [...value].some((char) => char.charCodeAt(0) < 32 || char.charCodeAt(0) === 127))
|
|
97481
98032
|
throw new TypeError(`${name} must be nonempty and contain no control characters`);
|
|
@@ -97483,7 +98034,7 @@ function safeValue(value, name) {
|
|
|
97483
98034
|
}
|
|
97484
98035
|
function absolute(value, name) {
|
|
97485
98036
|
safeValue(value, name);
|
|
97486
|
-
if (!
|
|
98037
|
+
if (!isAbsolute30(value)) throw new TypeError(`${name} must be an absolute path`);
|
|
97487
98038
|
return value;
|
|
97488
98039
|
}
|
|
97489
98040
|
function xml(value) {
|
|
@@ -97507,8 +98058,8 @@ function planDaemonService(options) {
|
|
|
97507
98058
|
const executable = absolute(options.executable, "Stable CLI executable");
|
|
97508
98059
|
const identity4 = createHash34("sha256").update(absolute(namespace.daemonInfoDir, "Daemon state directory")).digest("hex").slice(0, 24);
|
|
97509
98060
|
const supervisionId = `tmux-ide.${identity4}`;
|
|
97510
|
-
const stdoutPath =
|
|
97511
|
-
const stderrPath =
|
|
98061
|
+
const stdoutPath = join53(namespace.daemonInfoDir, "service.stdout.log");
|
|
98062
|
+
const stderrPath = join53(namespace.daemonInfoDir, "service.stderr.log");
|
|
97512
98063
|
const environment = {
|
|
97513
98064
|
HOME: home,
|
|
97514
98065
|
PATH: safeValue(options.path, "Service PATH"),
|
|
@@ -97525,7 +98076,7 @@ function planDaemonService(options) {
|
|
|
97525
98076
|
const shared = {
|
|
97526
98077
|
supervisionId,
|
|
97527
98078
|
executable,
|
|
97528
|
-
recordPath:
|
|
98079
|
+
recordPath: join53(namespace.daemonInfoDir, "service.json"),
|
|
97529
98080
|
stdoutPath,
|
|
97530
98081
|
stderrPath
|
|
97531
98082
|
};
|
|
@@ -97536,7 +98087,7 @@ function planDaemonService(options) {
|
|
|
97536
98087
|
...shared,
|
|
97537
98088
|
manager: "launchd",
|
|
97538
98089
|
target: `gui/${options.uid}/${label4}`,
|
|
97539
|
-
unitPath:
|
|
98090
|
+
unitPath: join53(home, "Library", "LaunchAgents", `${label4}.plist`),
|
|
97540
98091
|
contents: `<?xml version="1.0" encoding="UTF-8"?>
|
|
97541
98092
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
97542
98093
|
<plist version="1.0"><dict>
|
|
@@ -97555,14 +98106,14 @@ function planDaemonService(options) {
|
|
|
97555
98106
|
`
|
|
97556
98107
|
});
|
|
97557
98108
|
}
|
|
97558
|
-
const configHome = absolute(options.configHome ??
|
|
98109
|
+
const configHome = absolute(options.configHome ?? join53(home, ".config"), "Config directory");
|
|
97559
98110
|
const target = `${supervisionId}.service`;
|
|
97560
98111
|
const workingDirectory = `${home.replace(/%/gu, "%%")}/.`;
|
|
97561
98112
|
return Object.freeze({
|
|
97562
98113
|
...shared,
|
|
97563
98114
|
manager: "systemd",
|
|
97564
98115
|
target,
|
|
97565
|
-
unitPath:
|
|
98116
|
+
unitPath: join53(configHome, "systemd", "user", target),
|
|
97566
98117
|
contents: `[Unit]
|
|
97567
98118
|
Description=tmux-ide canonical user daemon
|
|
97568
98119
|
StartLimitIntervalSec=60
|
|
@@ -97600,7 +98151,7 @@ __export(daemon_service_exports, {
|
|
|
97600
98151
|
});
|
|
97601
98152
|
import {
|
|
97602
98153
|
accessSync as accessSync11,
|
|
97603
|
-
constants as
|
|
98154
|
+
constants as constants18,
|
|
97604
98155
|
openSync as openSync11,
|
|
97605
98156
|
closeSync as closeSync11,
|
|
97606
98157
|
fstatSync as fstatSync9,
|
|
@@ -97614,7 +98165,7 @@ import {
|
|
|
97614
98165
|
linkSync as linkSync4
|
|
97615
98166
|
} from "node:fs";
|
|
97616
98167
|
import { randomUUID as randomUUID48 } from "node:crypto";
|
|
97617
|
-
import { dirname as dirname41, join as
|
|
98168
|
+
import { dirname as dirname41, join as join54 } from "node:path";
|
|
97618
98169
|
import { homedir as homedir9 } from "node:os";
|
|
97619
98170
|
import { z as z131 } from "zod";
|
|
97620
98171
|
function defaults() {
|
|
@@ -97634,7 +98185,7 @@ function defaults() {
|
|
|
97634
98185
|
reserve: reserveCanonicalDaemonSupervision,
|
|
97635
98186
|
release: releaseCanonicalDaemonSupervision,
|
|
97636
98187
|
probe: probeCanonicalDaemonIdentity,
|
|
97637
|
-
recordPath:
|
|
98188
|
+
recordPath: join54(dirname41(getCanonicalDaemonInfoPath()), "service.json"),
|
|
97638
98189
|
waitMs: 3e4
|
|
97639
98190
|
};
|
|
97640
98191
|
}
|
|
@@ -97644,7 +98195,7 @@ function refused(message) {
|
|
|
97644
98195
|
function ownedFile(path2) {
|
|
97645
98196
|
let descriptor;
|
|
97646
98197
|
try {
|
|
97647
|
-
descriptor = openSync11(path2,
|
|
98198
|
+
descriptor = openSync11(path2, constants18.O_RDONLY | constants18.O_NOFOLLOW | constants18.O_NONBLOCK);
|
|
97648
98199
|
const stat3 = fstatSync9(descriptor);
|
|
97649
98200
|
if (!stat3.isFile() || stat3.uid !== process.getuid?.() || (stat3.mode & 18) !== 0 || stat3.size > 128 * 1024)
|
|
97650
98201
|
refused(`Service file is not a bounded, user-owned regular file: ${path2}`);
|
|
@@ -97691,13 +98242,13 @@ async function manageDaemonService(action, executable, deps2 = defaults()) {
|
|
|
97691
98242
|
refused("The service manager loaded a different definition; refusing to control it");
|
|
97692
98243
|
return state;
|
|
97693
98244
|
};
|
|
97694
|
-
const ready = async (previousInstance) => {
|
|
98245
|
+
const ready = async (previousInstance, retiredPid) => {
|
|
97695
98246
|
const deadline = Date.now() + deps2.waitMs;
|
|
97696
98247
|
do {
|
|
97697
98248
|
const state = deps2.inspect();
|
|
97698
98249
|
if (!boundTo(state, plan.supervisionId))
|
|
97699
98250
|
refused("Service reservation changed during startup");
|
|
97700
|
-
if (state.status === "valid" && state.info.instanceId !== previousInstance) {
|
|
98251
|
+
if (state.status === "valid" && state.info.instanceId !== previousInstance && state.info.pid !== retiredPid) {
|
|
97701
98252
|
const identity4 = await deps2.probe(state.info);
|
|
97702
98253
|
const service2 = await inspectManager();
|
|
97703
98254
|
if (identity4 && service2.active && service2.pid === state.info.pid && identity4.pid === state.info.pid && identity4.instanceId === state.info.instanceId && identity4.startedAt === state.info.startedAt && identity4.protocolVersion === state.info.protocolVersion)
|
|
@@ -97737,7 +98288,7 @@ async function manageDaemonService(action, executable, deps2 = defaults()) {
|
|
|
97737
98288
|
if (record2 && !boundTo(deps2.inspect(), plan.supervisionId) && !(record2.removing && action === "remove" && deps2.inspect().status === "missing"))
|
|
97738
98289
|
refused("Service reservation is missing or belongs to another owner");
|
|
97739
98290
|
if (!record2) {
|
|
97740
|
-
accessSync11(plan.executable,
|
|
98291
|
+
accessSync11(plan.executable, constants18.X_OK);
|
|
97741
98292
|
deps2.reserve(plan.supervisionId);
|
|
97742
98293
|
}
|
|
97743
98294
|
const lock = `${plan.recordPath}.lock`;
|
|
@@ -97798,9 +98349,13 @@ async function manageDaemonService(action, executable, deps2 = defaults()) {
|
|
|
97798
98349
|
}
|
|
97799
98350
|
const before = deps2.inspect();
|
|
97800
98351
|
if (action === "install" && service.active) return await ready();
|
|
97801
|
-
|
|
98352
|
+
const current = service.loaded ? await inspectManager() : service;
|
|
98353
|
+
if (current.loaded) await manager.restart(current.pid !== null);
|
|
97802
98354
|
else await manager.install();
|
|
97803
|
-
return await ready(
|
|
98355
|
+
return await ready(
|
|
98356
|
+
before.status === "valid" ? before.info.instanceId : void 0,
|
|
98357
|
+
current.loaded ? current.pid : null
|
|
98358
|
+
);
|
|
97804
98359
|
} catch (error) {
|
|
97805
98360
|
if (!activationAttempted && wroteRecord) {
|
|
97806
98361
|
if (wroteUnit && ownedFile(plan.unitPath) === contents) unlinkSync9(plan.unitPath);
|
|
@@ -98353,23 +98908,23 @@ __export(skill_sync_exports, {
|
|
|
98353
98908
|
versionMarker: () => versionMarker
|
|
98354
98909
|
});
|
|
98355
98910
|
import { existsSync as existsSync36, mkdirSync as mkdirSync31, readFileSync as readFileSync37, writeFileSync as writeFileSync29 } from "node:fs";
|
|
98356
|
-
import { dirname as dirname42, join as
|
|
98911
|
+
import { dirname as dirname42, join as join55 } from "node:path";
|
|
98357
98912
|
import { fileURLToPath as fileURLToPath12 } from "node:url";
|
|
98358
98913
|
function claudeDir() {
|
|
98359
98914
|
return resolveRuntimeNamespace().claudeDir;
|
|
98360
98915
|
}
|
|
98361
98916
|
function skillTargetDir() {
|
|
98362
|
-
return runtimeOwnedPath(
|
|
98917
|
+
return runtimeOwnedPath(join55(claudeDir(), "skills", "tmux-ide"));
|
|
98363
98918
|
}
|
|
98364
98919
|
function skillTargetFile() {
|
|
98365
|
-
return
|
|
98920
|
+
return join55(skillTargetDir(), "SKILL.md");
|
|
98366
98921
|
}
|
|
98367
98922
|
function defaultSkillSource() {
|
|
98368
98923
|
const here = dirname42(fileURLToPath12(import.meta.url));
|
|
98369
98924
|
const candidates = [
|
|
98370
|
-
|
|
98925
|
+
join55(here, "../skill/SKILL.md"),
|
|
98371
98926
|
// bundled bin/cli.js → repo root
|
|
98372
|
-
|
|
98927
|
+
join55(here, "../../../../skill/SKILL.md")
|
|
98373
98928
|
// dev src/lib → repo root
|
|
98374
98929
|
];
|
|
98375
98930
|
return candidates.find((c) => existsSync36(c)) ?? candidates[0];
|
|
@@ -98386,7 +98941,7 @@ function rewriteVersionMarker(content, version) {
|
|
|
98386
98941
|
return content.replace(VERSION_MARKER_RE, versionMarker(version));
|
|
98387
98942
|
}
|
|
98388
98943
|
function installedSkillVersion(dir = skillTargetDir()) {
|
|
98389
|
-
const file =
|
|
98944
|
+
const file = join55(dir, "SKILL.md");
|
|
98390
98945
|
if (!existsSync36(file)) return null;
|
|
98391
98946
|
try {
|
|
98392
98947
|
return parseSkillVersion(readFileSync37(file, "utf-8"));
|
|
@@ -98402,7 +98957,7 @@ function syncSkill({
|
|
|
98402
98957
|
throw new Error("Automatic skill sync is disabled in development instances");
|
|
98403
98958
|
const rendered = rewriteVersionMarker(readFileSync37(source, "utf-8"), version);
|
|
98404
98959
|
const dir = skillTargetDir();
|
|
98405
|
-
const target =
|
|
98960
|
+
const target = join55(dir, "SKILL.md");
|
|
98406
98961
|
const existing = existsSync36(target) ? readFileSync37(target, "utf-8") : null;
|
|
98407
98962
|
if (existing === rendered) {
|
|
98408
98963
|
return { action: "unchanged", path: target, to: version };
|
|
@@ -98435,7 +98990,7 @@ __export(doctor_exports, {
|
|
|
98435
98990
|
workspaceConfigRow: () => workspaceConfigRow
|
|
98436
98991
|
});
|
|
98437
98992
|
import { execSync as execSync3, execFileSync as execFileSync22 } from "node:child_process";
|
|
98438
|
-
import { accessSync as accessSync12, constants as
|
|
98993
|
+
import { accessSync as accessSync12, constants as constants19, existsSync as existsSync37 } from "node:fs";
|
|
98439
98994
|
import { resolve as resolve39, dirname as dirname43 } from "node:path";
|
|
98440
98995
|
import { fileURLToPath as fileURLToPath13 } from "node:url";
|
|
98441
98996
|
function agentIntegrationRows(agents) {
|
|
@@ -98650,7 +99205,7 @@ async function doctor({
|
|
|
98650
99205
|
}
|
|
98651
99206
|
let writable = false;
|
|
98652
99207
|
try {
|
|
98653
|
-
accessSync12(probe,
|
|
99208
|
+
accessSync12(probe, constants19.W_OK);
|
|
98654
99209
|
writable = true;
|
|
98655
99210
|
} catch {
|
|
98656
99211
|
}
|
|
@@ -101212,11 +101767,11 @@ __export(pane_team_exports, {
|
|
|
101212
101767
|
assignPaneTeam: () => assignPaneTeam
|
|
101213
101768
|
});
|
|
101214
101769
|
import { execFileSync as execFileSync25 } from "node:child_process";
|
|
101215
|
-
import { isAbsolute as
|
|
101770
|
+
import { isAbsolute as isAbsolute31 } from "node:path";
|
|
101216
101771
|
function assignPaneTeam(options, run = (args) => execFileSync25("tmux", args, { encoding: "utf8", timeout: 5e3 })) {
|
|
101217
101772
|
if (!/^%\d+$/u.test(options.paneId)) throw new Error("Use an exact pane ID such as %3");
|
|
101218
101773
|
if (options.socketPath && options.socketName) throw new Error("Choose one tmux socket selector");
|
|
101219
|
-
if (options.socketPath && !
|
|
101774
|
+
if (options.socketPath && !isAbsolute31(options.socketPath))
|
|
101220
101775
|
throw new Error("Socket path must be absolute");
|
|
101221
101776
|
if (options.socketName && !/^[a-zA-Z0-9_.-]+$/u.test(options.socketName))
|
|
101222
101777
|
throw new Error("Invalid socket name");
|
|
@@ -101453,9 +102008,9 @@ import {
|
|
|
101453
102008
|
unlinkSync as unlinkSync10,
|
|
101454
102009
|
writeFileSync as writeFileSync30,
|
|
101455
102010
|
accessSync as accessSync13,
|
|
101456
|
-
constants as
|
|
102011
|
+
constants as constants20
|
|
101457
102012
|
} from "node:fs";
|
|
101458
|
-
import { basename as basename21, delimiter as delimiter5, dirname as dirname45, join as
|
|
102013
|
+
import { basename as basename21, delimiter as delimiter5, dirname as dirname45, join as join56 } from "node:path";
|
|
101459
102014
|
function isOptOut(value) {
|
|
101460
102015
|
if (value === false || value === 0) return true;
|
|
101461
102016
|
return typeof value === "string" && /^\s*(0|false|off|no)\s*$/iu.test(value);
|
|
@@ -101503,8 +102058,8 @@ function agentTeamsPaths() {
|
|
|
101503
102058
|
function claudeOnPath2(path2 = process.env.PATH ?? "") {
|
|
101504
102059
|
return path2.split(delimiter5).filter(Boolean).some((dir) => {
|
|
101505
102060
|
try {
|
|
101506
|
-
accessSync13(
|
|
101507
|
-
return statSync23(
|
|
102061
|
+
accessSync13(join56(dir, "claude"), constants20.X_OK);
|
|
102062
|
+
return statSync23(join56(dir, "claude")).isFile();
|
|
101508
102063
|
} catch {
|
|
101509
102064
|
return false;
|
|
101510
102065
|
}
|
|
@@ -101529,7 +102084,7 @@ function existingBackup(settingsPath) {
|
|
|
101529
102084
|
const prefix = `${basename21(settingsPath)}${BACKUP_INFIX}`;
|
|
101530
102085
|
try {
|
|
101531
102086
|
const found = readdirSync11(dir).find((name) => name.startsWith(prefix));
|
|
101532
|
-
return found ?
|
|
102087
|
+
return found ? join56(dir, found) : null;
|
|
101533
102088
|
} catch {
|
|
101534
102089
|
return null;
|
|
101535
102090
|
}
|
|
@@ -101545,7 +102100,7 @@ function writeSettings(path2, settings, exists) {
|
|
|
101545
102100
|
copyFileSync3(path2, backup);
|
|
101546
102101
|
}
|
|
101547
102102
|
}
|
|
101548
|
-
const temporary =
|
|
102103
|
+
const temporary = join56(dirname45(path2), `.${basename21(path2)}.tmux-ide-${process.pid}.tmp`);
|
|
101549
102104
|
try {
|
|
101550
102105
|
writeFileSync30(temporary, `${JSON.stringify(settings, null, 2)}
|
|
101551
102106
|
`, { mode: 384 });
|
|
@@ -101686,7 +102241,7 @@ __export(worktree_exports, {
|
|
|
101686
102241
|
worktreeSessionName: () => worktreeSessionName
|
|
101687
102242
|
});
|
|
101688
102243
|
import { execFileSync as execFileSync26 } from "node:child_process";
|
|
101689
|
-
import { basename as basename22, dirname as dirname46, isAbsolute as
|
|
102244
|
+
import { basename as basename22, dirname as dirname46, isAbsolute as isAbsolute32, join as join57, resolve as resolve43 } from "node:path";
|
|
101690
102245
|
function sanitizeForTmux(part) {
|
|
101691
102246
|
return part.replace(/[.:/\s]+/g, "-");
|
|
101692
102247
|
}
|
|
@@ -101695,11 +102250,11 @@ function worktreeSessionName(project, branch) {
|
|
|
101695
102250
|
}
|
|
101696
102251
|
function defaultWorktreeBaseDir(repoDir) {
|
|
101697
102252
|
const abs = resolve43(repoDir);
|
|
101698
|
-
return
|
|
102253
|
+
return join57(dirname46(abs), `${basename22(abs)}-worktrees`);
|
|
101699
102254
|
}
|
|
101700
102255
|
function worktreePath(repoDir, branch, configuredDir) {
|
|
101701
|
-
const base2 = configuredDir && configuredDir.length > 0 ?
|
|
101702
|
-
return
|
|
102256
|
+
const base2 = configuredDir && configuredDir.length > 0 ? isAbsolute32(configuredDir) ? configuredDir : resolve43(repoDir, configuredDir) : defaultWorktreeBaseDir(repoDir);
|
|
102257
|
+
return join57(base2, branch);
|
|
101703
102258
|
}
|
|
101704
102259
|
function parseWorktreeList(porcelain) {
|
|
101705
102260
|
const entries = [];
|
|
@@ -101834,7 +102389,7 @@ var init_worktree = __esm({
|
|
|
101834
102389
|
|
|
101835
102390
|
// packages/daemon/src/lib/managed-installer-update.ts
|
|
101836
102391
|
import { mkdtempSync, readFileSync as readFileSync40, realpathSync as realpathSync29, rmSync as rmSync7 } from "node:fs";
|
|
101837
|
-
import { dirname as dirname47, join as
|
|
102392
|
+
import { dirname as dirname47, join as join58 } from "node:path";
|
|
101838
102393
|
import { tmpdir } from "node:os";
|
|
101839
102394
|
import { execFileSync as execFileSync27 } from "node:child_process";
|
|
101840
102395
|
function managedInstallerPrefix(cliPath) {
|
|
@@ -101843,16 +102398,16 @@ function managedInstallerPrefix(cliPath) {
|
|
|
101843
102398
|
);
|
|
101844
102399
|
if (!match) return null;
|
|
101845
102400
|
const prefix = match[1] || "/";
|
|
101846
|
-
const root =
|
|
101847
|
-
const release =
|
|
102401
|
+
const root = join58(prefix, "share/tmux-ide");
|
|
102402
|
+
const release = join58(root, "releases", match[2]);
|
|
101848
102403
|
try {
|
|
101849
|
-
if (realpathSync29(
|
|
102404
|
+
if (realpathSync29(join58(root, "current")) !== release) return null;
|
|
101850
102405
|
if (realpathSync29(release) !== release) return null;
|
|
101851
|
-
if (readFileSync40(
|
|
101852
|
-
if (readFileSync40(
|
|
101853
|
-
if (!readFileSync40(
|
|
102406
|
+
if (readFileSync40(join58(root, "installer-v1"), "utf8") !== "1\n") return null;
|
|
102407
|
+
if (readFileSync40(join58(release, ".installer-release-v1"), "utf8") !== "1\n") return null;
|
|
102408
|
+
if (!readFileSync40(join58(prefix, "bin/tmux-ide"), "utf8").split("\n").includes("# tmux-ide universal installer v1"))
|
|
101854
102409
|
return null;
|
|
101855
|
-
if (JSON.parse(readFileSync40(
|
|
102410
|
+
if (JSON.parse(readFileSync40(join58(dirname47(cliPath), "package.json"), "utf8")).name !== "tmux-ide")
|
|
101856
102411
|
return null;
|
|
101857
102412
|
return prefix;
|
|
101858
102413
|
} catch {
|
|
@@ -101860,8 +102415,8 @@ function managedInstallerPrefix(cliPath) {
|
|
|
101860
102415
|
}
|
|
101861
102416
|
}
|
|
101862
102417
|
function runManagedInstallerUpdate(prefix, channel, json3, execute2 = execFileSync27) {
|
|
101863
|
-
const temporary = mkdtempSync(
|
|
101864
|
-
const script =
|
|
102418
|
+
const temporary = mkdtempSync(join58(tmpdir(), "tmux-ide-update-"));
|
|
102419
|
+
const script = join58(temporary, "install.sh");
|
|
101865
102420
|
try {
|
|
101866
102421
|
execute2(
|
|
101867
102422
|
"curl",
|
|
@@ -101904,7 +102459,7 @@ var init_managed_installer_update = __esm({
|
|
|
101904
102459
|
|
|
101905
102460
|
// packages/daemon/src/lib/install-origin.ts
|
|
101906
102461
|
import { existsSync as existsSync39, readFileSync as readFileSync41, realpathSync as realpathSync30 } from "node:fs";
|
|
101907
|
-
import { dirname as dirname48, join as
|
|
102462
|
+
import { dirname as dirname48, join as join59 } from "node:path";
|
|
101908
102463
|
import { fileURLToPath as fileURLToPath14 } from "node:url";
|
|
101909
102464
|
function detectPackageManager(path2) {
|
|
101910
102465
|
if (/\/share\/tmux-ide\/releases\/install-[^/]+\/npm\/lib\/node_modules\/tmux-ide\/bin$/.test(path2))
|
|
@@ -101921,9 +102476,9 @@ function findGitCheckoutRoot(startDir) {
|
|
|
101921
102476
|
let dir = startDir;
|
|
101922
102477
|
for (; ; ) {
|
|
101923
102478
|
if (dir.endsWith("/node_modules")) return null;
|
|
101924
|
-
if (existsSync39(
|
|
102479
|
+
if (existsSync39(join59(dir, ".git"))) {
|
|
101925
102480
|
try {
|
|
101926
|
-
if (JSON.parse(readFileSync41(
|
|
102481
|
+
if (JSON.parse(readFileSync41(join59(dir, "package.json"), "utf8")).name === "tmux-ide")
|
|
101927
102482
|
return dir;
|
|
101928
102483
|
} catch {
|
|
101929
102484
|
}
|
|
@@ -101944,7 +102499,7 @@ function installOrigin(cliDir = dirname48(fileURLToPath14(import.meta.url))) {
|
|
|
101944
102499
|
let detected2 = detectPackageManager(path2);
|
|
101945
102500
|
if (detected2 === "npm" || detected2 === "pnpm" || detected2 === "bun") {
|
|
101946
102501
|
try {
|
|
101947
|
-
if (JSON.parse(readFileSync41(
|
|
102502
|
+
if (JSON.parse(readFileSync41(join59(path2, "../package.json"), "utf8")).name !== "tmux-ide")
|
|
101948
102503
|
detected2 = "unknown";
|
|
101949
102504
|
} catch {
|
|
101950
102505
|
detected2 = "unknown";
|
|
@@ -101970,7 +102525,7 @@ __export(update_exports, {
|
|
|
101970
102525
|
runUpdate: () => runUpdate
|
|
101971
102526
|
});
|
|
101972
102527
|
import { realpathSync as realpathSync31 } from "node:fs";
|
|
101973
|
-
import { dirname as dirname49, join as
|
|
102528
|
+
import { dirname as dirname49, join as join60 } from "node:path";
|
|
101974
102529
|
import { execFileSync as execFileSync28 } from "node:child_process";
|
|
101975
102530
|
function planUpdate(input) {
|
|
101976
102531
|
const current = input.currentVersion ?? getCurrentVersion();
|
|
@@ -102060,7 +102615,7 @@ function runUpdate({ cliDir, dryRun, json: json3 = false }, dependencies = {}) {
|
|
|
102060
102615
|
plan.executable === "bun" ? ["pm", "bin", "-g"] : ["root", "-g"]
|
|
102061
102616
|
).trim();
|
|
102062
102617
|
if (!root.startsWith("/")) throw new Error("invalid manager path");
|
|
102063
|
-
const target = plan.executable === "bun" ? dirname49(realpathSync31(
|
|
102618
|
+
const target = plan.executable === "bun" ? dirname49(realpathSync31(join60(root, "tmux-ide"))) : realpathSync31(join60(root, "tmux-ide", "bin"));
|
|
102064
102619
|
if (target !== source.path) throw new Error("different installation");
|
|
102065
102620
|
} catch {
|
|
102066
102621
|
plan = {
|
|
@@ -102122,9 +102677,9 @@ __export(pane_widget_exports, {
|
|
|
102122
102677
|
paneWidgetId: () => paneWidgetId,
|
|
102123
102678
|
paneWidgetIdForFile: () => paneWidgetIdForFile
|
|
102124
102679
|
});
|
|
102125
|
-
import { basename as basename23, extname } from "node:path";
|
|
102680
|
+
import { basename as basename23, extname as extname2 } from "node:path";
|
|
102126
102681
|
function imageMediaTypeFor(fileName) {
|
|
102127
|
-
return IMAGE_MEDIA_BY_EXTENSION.get(
|
|
102682
|
+
return IMAGE_MEDIA_BY_EXTENSION.get(extname2(fileName).toLowerCase()) ?? null;
|
|
102128
102683
|
}
|
|
102129
102684
|
function buildMarkdownAnnouncement(text2, title) {
|
|
102130
102685
|
if (text2.trim().length === 0) {
|
|
@@ -102190,7 +102745,7 @@ function paneWidgetId(value) {
|
|
|
102190
102745
|
);
|
|
102191
102746
|
}
|
|
102192
102747
|
function paneWidgetIdForFile(fileName) {
|
|
102193
|
-
const extension =
|
|
102748
|
+
const extension = extname2(fileName).toLowerCase();
|
|
102194
102749
|
if ([".md", ".markdown"].includes(extension)) return "markdown";
|
|
102195
102750
|
if (IMAGE_MEDIA_BY_EXTENSION.has(extension)) return "image";
|
|
102196
102751
|
if (extension === ".json") return "card";
|
|
@@ -102337,7 +102892,7 @@ var init_server3 = __esm({
|
|
|
102337
102892
|
init_src();
|
|
102338
102893
|
init_tmux_client_execution();
|
|
102339
102894
|
import { parseArgs as parseArgs2 } from "node:util";
|
|
102340
|
-
import { resolve as resolve44, dirname as dirname50, join as
|
|
102895
|
+
import { resolve as resolve44, dirname as dirname50, join as join61 } from "node:path";
|
|
102341
102896
|
import { execFileSync as execFileSync29 } from "node:child_process";
|
|
102342
102897
|
import { appendFileSync as appendFileSync2, existsSync as existsSync40, mkdirSync as mkdirSync33, writeFileSync as writeFileSync31 } from "node:fs";
|
|
102343
102898
|
import { fileURLToPath as fileURLToPath15 } from "node:url";
|
|
@@ -102678,9 +103233,9 @@ Install bun (https://bun.sh) \u2014 the TUI surfaces run on it. Sources ship wit
|
|
|
102678
103233
|
let automaticDiagnosticLog;
|
|
102679
103234
|
if (surface === "app" && !process.env.TMUX_IDE_TUI_PERF_LOG && !process.env.TMUX_IDE_TUI_LOG) {
|
|
102680
103235
|
try {
|
|
102681
|
-
const logDirectory =
|
|
103236
|
+
const logDirectory = join61(stateHome(), "logs");
|
|
102682
103237
|
mkdirSync33(logDirectory, { recursive: true, mode: 448 });
|
|
102683
|
-
automaticDiagnosticLog =
|
|
103238
|
+
automaticDiagnosticLog = join61(logDirectory, "tui-latest.jsonl");
|
|
102684
103239
|
writeFileSync31(
|
|
102685
103240
|
automaticDiagnosticLog,
|
|
102686
103241
|
`${JSON.stringify({
|
|
@@ -103052,7 +103607,7 @@ try {
|
|
|
103052
103607
|
exitCode: 2
|
|
103053
103608
|
});
|
|
103054
103609
|
const { openBrowser: openBrowser2 } = await Promise.resolve().then(() => (init_open_browser(), open_browser_exports));
|
|
103055
|
-
const result2 = openBrowser2(positionals[1], {
|
|
103610
|
+
const result2 = await openBrowser2(positionals[1], {
|
|
103056
103611
|
session: values.session,
|
|
103057
103612
|
pane: values.pane,
|
|
103058
103613
|
split: values.split,
|