skydive-cli 0.5.0-beta.12 → 0.5.0-beta.14
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/dist/js/bin.mjs +22 -22
- package/dist/js/{boot-DNe3CikP.mjs → boot-CJKq8rvL.mjs} +32 -12
- package/dist/js/{client-DabRpc_T.mjs → client-DbqRBquD.mjs} +61 -21
- package/dist/js/client-hH2PJL8y.mjs +5 -0
- package/dist/js/{daemon-DLY2NmVU.mjs → daemon-CL25CwjW.mjs} +30 -4
- package/dist/js/{daemon-BuAxg1_H.mjs → daemon-DjsUMczp.mjs} +2 -2
- package/dist/js/daemon-client-DEyOdfdA.mjs +7 -0
- package/dist/js/{daemon-client-CG6KWbdI.mjs → daemon-client-k8ICifN2.mjs} +1 -1
- package/dist/js/{print-Bo06tvfV.mjs → print-DTx2HyDY.mjs} +2 -2
- package/dist/js/{print-ClPkgR9z.mjs → print-riiY5Gly.mjs} +1 -1
- package/dist/js/{print-share-CKLPmsg0.mjs → print-share-BH9gvCls.mjs} +3 -1
- package/dist/js/{profiler-CZIaF_t9.mjs → profiler-COGO4LN8.mjs} +2 -2
- package/dist/js/{rest-I3imNduB.mjs → rest-CLrHVkxh.mjs} +4 -0
- package/dist/js/{rest-D29qNkto.mjs → rest-DsdPAE8K.mjs} +1 -1
- package/package.json +1 -1
- package/dist/js/client-BuU34IVE.mjs +0 -5
- package/dist/js/daemon-client-DnhKkk1Y.mjs +0 -7
package/dist/js/bin.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { C as ensureActiveOrganization, D as setActiveWorkspace, E as listWorkspaces, O as name, T as getSessionIdentity, a as installCrashHandler, k as version, t as maybeStartProfiling, u as brandHelpArt, w as getActiveWorkspaceId, x as themes } from "./profiler-
|
|
3
|
-
import { A as getStoredApiKeyId, B as saveConfig, C as getDefaultAgent, E as getPromptHistoryPath, F as resolveChatAuth, I as resolveConfig, L as resolveManagementAuth, M as getUpdateCheckDisabled, P as resolveAppUrl, R as resolveSession, S as getConfigPath, T as getPreference, U as setLastSeenVersion, V as saveSession, _ as API_KEY_PREFIX, b as PREFERENCES, g as API_KEY_FAMILY_PREFIX, h as API_KEYS_URL, i as resolveAgent, j as getStoredApiKeyWorkspaceName, k as getShareMachineDefault, v as DEFAULT_API_URL, w as getLastSeenVersion, x as deleteConfig } from "./print-
|
|
2
|
+
import { C as ensureActiveOrganization, D as setActiveWorkspace, E as listWorkspaces, O as name, T as getSessionIdentity, a as installCrashHandler, k as version, t as maybeStartProfiling, u as brandHelpArt, w as getActiveWorkspaceId, x as themes } from "./profiler-COGO4LN8.mjs";
|
|
3
|
+
import { A as getStoredApiKeyId, B as saveConfig, C as getDefaultAgent, E as getPromptHistoryPath, F as resolveChatAuth, I as resolveConfig, L as resolveManagementAuth, M as getUpdateCheckDisabled, P as resolveAppUrl, R as resolveSession, S as getConfigPath, T as getPreference, U as setLastSeenVersion, V as saveSession, _ as API_KEY_PREFIX, b as PREFERENCES, g as API_KEY_FAMILY_PREFIX, h as API_KEYS_URL, i as resolveAgent, j as getStoredApiKeyWorkspaceName, k as getShareMachineDefault, v as DEFAULT_API_URL, w as getLastSeenVersion, x as deleteConfig } from "./print-riiY5Gly.mjs";
|
|
4
4
|
import { n as printError, r as printTable, t as output } from "./output-DYzzdXYV.mjs";
|
|
5
5
|
import { t as HttpError } from "./http-error-DzyrsLAZ.mjs";
|
|
6
|
-
import { t as createRestClient } from "./rest-
|
|
6
|
+
import { t as createRestClient } from "./rest-CLrHVkxh.mjs";
|
|
7
7
|
import "./billing-blocked-2wju4gC_.mjs";
|
|
8
|
-
import { r as resolveMachineIdentity } from "./client-
|
|
9
|
-
import { i as queryDaemonStatus, l as PORTAL_DAEMON_FLAG, n as ensureDaemonRunning, s as stopDaemon, u as daemonPaths } from "./daemon-
|
|
8
|
+
import { r as resolveMachineIdentity } from "./client-DbqRBquD.mjs";
|
|
9
|
+
import { i as queryDaemonStatus, l as PORTAL_DAEMON_FLAG, n as ensureDaemonRunning, s as stopDaemon, u as daemonPaths } from "./daemon-CL25CwjW.mjs";
|
|
10
10
|
import { i as grantPortalAccess, n as fetchPortalDevices, o as registerPortalDevice, r as findThisDevice, s as revokePortalAccess } from "./api-DG5W6iwx.mjs";
|
|
11
11
|
import { t as SandboxStream } from "./client-c4c5MmgN.mjs";
|
|
12
12
|
import { hideBin } from "yargs/helpers";
|
|
@@ -1517,7 +1517,7 @@ const importCommand = {
|
|
|
1517
1517
|
process.exit(1);
|
|
1518
1518
|
}
|
|
1519
1519
|
}
|
|
1520
|
-
const { runChat } = await import("./boot-
|
|
1520
|
+
const { runChat } = await import("./boot-CJKq8rvL.mjs");
|
|
1521
1521
|
await runChat({
|
|
1522
1522
|
appUrl,
|
|
1523
1523
|
sessionToken: session.value.sessionToken,
|
|
@@ -1545,7 +1545,7 @@ async function runImportPrintMode({ argv, appUrl }) {
|
|
|
1545
1545
|
printError(`${session.error.message} For non-interactive use, run \`skydive auth login --web\` first, or set SKYDIVE_SESSION_TOKEN.`);
|
|
1546
1546
|
process.exit(1);
|
|
1547
1547
|
}
|
|
1548
|
-
const { connectMachineShare } = await import("./print-share-
|
|
1548
|
+
const { connectMachineShare } = await import("./print-share-BH9gvCls.mjs");
|
|
1549
1549
|
const machineShare = await connectMachineShare({
|
|
1550
1550
|
appUrl,
|
|
1551
1551
|
sessionToken: session.value.sessionToken,
|
|
@@ -1553,7 +1553,7 @@ async function runImportPrintMode({ argv, appUrl }) {
|
|
|
1553
1553
|
});
|
|
1554
1554
|
const extra = (argv.print ?? "").trim();
|
|
1555
1555
|
const prompt = buildImportSeedPrompt(process.cwd()) + (extra ? `\n\nAdditional instructions: ${extra}` : "");
|
|
1556
|
-
const { runPrint } = await import("./print-
|
|
1556
|
+
const { runPrint } = await import("./print-DTx2HyDY.mjs");
|
|
1557
1557
|
try {
|
|
1558
1558
|
const result = await runPrint({
|
|
1559
1559
|
appUrl,
|
|
@@ -1930,7 +1930,7 @@ const chatCommand = {
|
|
|
1930
1930
|
sessionToken: auth.value.token,
|
|
1931
1931
|
agentSelector: argv.agent ?? null
|
|
1932
1932
|
});
|
|
1933
|
-
const { runChat } = await import("./boot-
|
|
1933
|
+
const { runChat } = await import("./boot-CJKq8rvL.mjs");
|
|
1934
1934
|
await runChat({
|
|
1935
1935
|
appUrl: auth.value.appUrl,
|
|
1936
1936
|
sessionToken: auth.value.token,
|
|
@@ -1998,7 +1998,7 @@ async function runPrintMode({ argv, appUrl }) {
|
|
|
1998
1998
|
printError(`${auth.error.message} For non-interactive use, run \`skydive auth login\` first, or set SKYDIVE_API_KEY / SKYDIVE_SESSION_TOKEN.`);
|
|
1999
1999
|
process.exit(1);
|
|
2000
2000
|
}
|
|
2001
|
-
const { runPrint, readStdin } = await import("./print-
|
|
2001
|
+
const { runPrint, readStdin } = await import("./print-DTx2HyDY.mjs");
|
|
2002
2002
|
await ensureAgentWorkspace({
|
|
2003
2003
|
appUrl,
|
|
2004
2004
|
sessionToken: auth.value.token,
|
|
@@ -2023,7 +2023,7 @@ async function runPrintMode({ argv, appUrl }) {
|
|
|
2023
2023
|
process.exit(1);
|
|
2024
2024
|
}
|
|
2025
2025
|
} else {
|
|
2026
|
-
const { connectMachineShare } = await import("./print-share-
|
|
2026
|
+
const { connectMachineShare } = await import("./print-share-BH9gvCls.mjs");
|
|
2027
2027
|
machineShare = await connectMachineShare({
|
|
2028
2028
|
appUrl: auth.value.appUrl,
|
|
2029
2029
|
sessionToken: auth.value.token,
|
|
@@ -2087,7 +2087,7 @@ const getCommand$1 = {
|
|
|
2087
2087
|
printError(`${auth.error.message} Run \`skydive auth login\` first, or set SKYDIVE_API_KEY / SKYDIVE_SESSION_TOKEN.`);
|
|
2088
2088
|
process.exit(1);
|
|
2089
2089
|
}
|
|
2090
|
-
const { messageGet } = await import("./print-
|
|
2090
|
+
const { messageGet } = await import("./print-DTx2HyDY.mjs");
|
|
2091
2091
|
try {
|
|
2092
2092
|
const result = await messageGet({
|
|
2093
2093
|
appUrl: auth.value.appUrl,
|
|
@@ -2290,7 +2290,7 @@ const switchCommand = {
|
|
|
2290
2290
|
printError("The workspace picker needs the Bun runtime and it could not be set up automatically. Pass a workspace slug instead, or install Bun and retry.");
|
|
2291
2291
|
process.exit(1);
|
|
2292
2292
|
}
|
|
2293
|
-
const { runWorkspacePicker } = await import("./boot-
|
|
2293
|
+
const { runWorkspacePicker } = await import("./boot-CJKq8rvL.mjs");
|
|
2294
2294
|
await runWorkspacePicker(session);
|
|
2295
2295
|
return;
|
|
2296
2296
|
}
|
|
@@ -2339,7 +2339,7 @@ const workspaceCommand = {
|
|
|
2339
2339
|
*/
|
|
2340
2340
|
async function resolveGrantTarget(argv) {
|
|
2341
2341
|
const session = requireSession(argv);
|
|
2342
|
-
const [{ devices, agents }, identity] = await Promise.all([fetchPortalDevices(session), resolveMachineIdentity()]);
|
|
2342
|
+
const [{ devices, agents }, identity] = await Promise.all([fetchPortalDevices(session), resolveMachineIdentity(null)]);
|
|
2343
2343
|
return {
|
|
2344
2344
|
session,
|
|
2345
2345
|
agent: resolveAgent(agents, argv.agent),
|
|
@@ -2368,8 +2368,8 @@ const openCommand = {
|
|
|
2368
2368
|
const session = requireSession(argv);
|
|
2369
2369
|
const agent = argv.agent ? resolveAgent((await fetchPortalDevices(session)).agents, argv.agent) : null;
|
|
2370
2370
|
const cwd = argv.cwd ? path.resolve(argv.cwd) : process.cwd();
|
|
2371
|
-
const { machineName } = await resolveMachineIdentity();
|
|
2372
|
-
const { PortalDaemonClient } = await import("./daemon-client-
|
|
2371
|
+
const { machineName } = await resolveMachineIdentity(null);
|
|
2372
|
+
const { PortalDaemonClient } = await import("./daemon-client-DEyOdfdA.mjs");
|
|
2373
2373
|
let lastLine = "";
|
|
2374
2374
|
let signalConnected;
|
|
2375
2375
|
const connected = new Promise((resolve) => {
|
|
@@ -2468,7 +2468,7 @@ const statusCommand = {
|
|
|
2468
2468
|
console.log("No machines registered. Run `skydive portal open` to register this one.");
|
|
2469
2469
|
return;
|
|
2470
2470
|
}
|
|
2471
|
-
const { headers, rows } = buildDeviceTable(devices, agents, (await resolveMachineIdentity()).machineName);
|
|
2471
|
+
const { headers, rows } = buildDeviceTable(devices, agents, (await resolveMachineIdentity(null)).machineName);
|
|
2472
2472
|
printTable(headers, rows);
|
|
2473
2473
|
}
|
|
2474
2474
|
};
|
|
@@ -2679,8 +2679,8 @@ const sandboxCommand = {
|
|
|
2679
2679
|
}).example("skydive sandbox --agent grace", "Live terminal (Ctrl-] detaches)").example("skydive sandbox --agent grace -- tail -n 50 /tmp/harness.log", "One-shot command (use `--` so its flags reach the sandbox)").example("skydive sandbox --agent grace -- sh -c 'ls /tmp | wc -l'", "Shell features go through an explicit `sh -c`"),
|
|
2680
2680
|
handler: async (argv) => {
|
|
2681
2681
|
const session = requireSession(argv);
|
|
2682
|
-
const { createRestClient } = await import("./rest-
|
|
2683
|
-
const { resolveAgent } = await import("./print-
|
|
2682
|
+
const { createRestClient } = await import("./rest-DsdPAE8K.mjs");
|
|
2683
|
+
const { resolveAgent } = await import("./print-DTx2HyDY.mjs");
|
|
2684
2684
|
const client = createRestClient({
|
|
2685
2685
|
appUrl: session.appUrl,
|
|
2686
2686
|
sessionToken: session.sessionToken
|
|
@@ -2837,8 +2837,8 @@ const fsEditCommand = {
|
|
|
2837
2837
|
handler: async (argv) => {
|
|
2838
2838
|
const session = requireSession(argv);
|
|
2839
2839
|
const remotePath = argv.path;
|
|
2840
|
-
const { createRestClient } = await import("./rest-
|
|
2841
|
-
const { resolveAgent } = await import("./print-
|
|
2840
|
+
const { createRestClient } = await import("./rest-DsdPAE8K.mjs");
|
|
2841
|
+
const { resolveAgent } = await import("./print-DTx2HyDY.mjs");
|
|
2842
2842
|
const client = createRestClient({
|
|
2843
2843
|
appUrl: session.appUrl,
|
|
2844
2844
|
sessionToken: session.sessionToken
|
|
@@ -4215,7 +4215,7 @@ if (process.argv.includes(UPDATE_WORKER_FLAG)) {
|
|
|
4215
4215
|
process.exit(0);
|
|
4216
4216
|
}
|
|
4217
4217
|
if (process.argv.includes(PORTAL_DAEMON_FLAG)) {
|
|
4218
|
-
const { runPortalDaemon } = await import("./daemon-
|
|
4218
|
+
const { runPortalDaemon } = await import("./daemon-DjsUMczp.mjs");
|
|
4219
4219
|
runPortalDaemon(process.argv);
|
|
4220
4220
|
} else runCli();
|
|
4221
4221
|
function runCli() {
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { D as setActiveWorkspace, E as listWorkspaces, S as themesForMode, _ as themeForMode, a as installCrashHandler, b as themeVersion, c as MARK_CELLS, d as DEFAULT_THEME_ID, f as applyTheme, g as theme, h as noColorRequested, i as writeArtifact, l as WORDMARK, m as monoTheme, n as profilingEnabled, o as buildCrashReport, p as findTheme, r as record, s as writeCrashReport, v as themeMode, w as getActiveWorkspaceId, y as themeModeFromColorFgBg } from "./profiler-
|
|
3
|
-
import { D as getReviewStateDir, H as saveTheme, N as recordDefaultAgent, O as getSavedTheme, S as getConfigPath, c as cardActionErrorMessage, d as reconcileMaskedInput, f as resolveConnectUrl, i as resolveAgent, l as parseExternalOauthConnectParams, m as specKeyFor, p as parseConnectCard, s as MASK_CHAR, u as parseOauthConnectParams, v as DEFAULT_API_URL, y as DEFAULT_APP_URL, z as resolveWebUrl } from "./print-
|
|
2
|
+
import { D as setActiveWorkspace, E as listWorkspaces, S as themesForMode, _ as themeForMode, a as installCrashHandler, b as themeVersion, c as MARK_CELLS, d as DEFAULT_THEME_ID, f as applyTheme, g as theme, h as noColorRequested, i as writeArtifact, l as WORDMARK, m as monoTheme, n as profilingEnabled, o as buildCrashReport, p as findTheme, r as record, s as writeCrashReport, v as themeMode, w as getActiveWorkspaceId, y as themeModeFromColorFgBg } from "./profiler-COGO4LN8.mjs";
|
|
3
|
+
import { D as getReviewStateDir, H as saveTheme, N as recordDefaultAgent, O as getSavedTheme, S as getConfigPath, c as cardActionErrorMessage, d as reconcileMaskedInput, f as resolveConnectUrl, i as resolveAgent, l as parseExternalOauthConnectParams, m as specKeyFor, p as parseConnectCard, s as MASK_CHAR, u as parseOauthConnectParams, v as DEFAULT_API_URL, y as DEFAULT_APP_URL, z as resolveWebUrl } from "./print-riiY5Gly.mjs";
|
|
4
4
|
import { t as HttpError } from "./http-error-DzyrsLAZ.mjs";
|
|
5
|
-
import { a as isRecord, i as errorMessage, n as errorDetail, r as sendErrorMessage, t as createRestClient } from "./rest-
|
|
5
|
+
import { a as isRecord, i as errorMessage, n as errorDetail, r as sendErrorMessage, t as createRestClient } from "./rest-CLrHVkxh.mjs";
|
|
6
6
|
import { i as billingBlockedOutcomeFromSendResponse } from "./billing-blocked-2wju4gC_.mjs";
|
|
7
|
-
import { t as PortalClient } from "./client-
|
|
8
|
-
import "./daemon-
|
|
7
|
+
import { t as PortalClient } from "./client-DbqRBquD.mjs";
|
|
8
|
+
import "./daemon-CL25CwjW.mjs";
|
|
9
9
|
import "./api-DG5W6iwx.mjs";
|
|
10
10
|
import { t as SandboxStream } from "./client-c4c5MmgN.mjs";
|
|
11
|
-
import { t as PortalDaemonClient } from "./daemon-client-
|
|
11
|
+
import { t as PortalDaemonClient } from "./daemon-client-k8ICifN2.mjs";
|
|
12
12
|
import { t as runRawPtyPassthrough } from "./raw-pty-DY4KelZW.mjs";
|
|
13
13
|
import * as os$1 from "node:os";
|
|
14
14
|
import { homedir, platform, release, tmpdir } from "node:os";
|
|
@@ -386,6 +386,8 @@ function createPortalClient(opts) {
|
|
|
386
386
|
deviceToken: null
|
|
387
387
|
}),
|
|
388
388
|
resolveCwd: () => process.cwd(),
|
|
389
|
+
persistedMachineName: null,
|
|
390
|
+
onMachineName: () => {},
|
|
389
391
|
onState: (state) => opts.onState({
|
|
390
392
|
status: state.status,
|
|
391
393
|
machineName: state.machineName,
|
|
@@ -2841,15 +2843,20 @@ function ConversationList({ agent, conversations, complete, showAutomated, onTog
|
|
|
2841
2843
|
children: [marker, truncate("+ new conversation", rowWidth)]
|
|
2842
2844
|
}, "new");
|
|
2843
2845
|
const archived = isArchived(row.hit.item);
|
|
2846
|
+
const unread = row.hit.item.unread === true;
|
|
2844
2847
|
const { title, detail, tag } = fitRowText(singleLine(row.hit.item.title ?? "(untitled)"), `${archived ? "archived · " : ""}${previewLine(row.hit.item)}`, rowWidth, coAgentsTag(row.hit.item, agent.id));
|
|
2848
|
+
const titleText = /* @__PURE__ */ jsx(FuzzyText, {
|
|
2849
|
+
text: title,
|
|
2850
|
+
indexes: row.hit.item.title ? row.hit.highlights[0] : null
|
|
2851
|
+
});
|
|
2845
2852
|
return /* @__PURE__ */ jsxs("text", {
|
|
2846
2853
|
fg: archived && !selected ? theme.dim : fg,
|
|
2847
2854
|
children: [
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
}),
|
|
2855
|
+
!selected && unread ? /* @__PURE__ */ jsx("span", {
|
|
2856
|
+
fg: theme.accent,
|
|
2857
|
+
children: "● "
|
|
2858
|
+
}) : marker,
|
|
2859
|
+
unread ? /* @__PURE__ */ jsx("b", { children: titleText }) : titleText,
|
|
2853
2860
|
tag ? /* @__PURE__ */ jsxs("span", {
|
|
2854
2861
|
fg: theme.muted,
|
|
2855
2862
|
children: [" ", tag]
|
|
@@ -10738,6 +10745,8 @@ function ChatScreen({ agent, conversation }) {
|
|
|
10738
10745
|
const menuHighlightClamped = Math.min(menuHighlight, Math.max(0, menuCommands.length - 1));
|
|
10739
10746
|
const runRef = useRef(run);
|
|
10740
10747
|
runRef.current = run;
|
|
10748
|
+
const conversationIdRef = useRef(conversationId);
|
|
10749
|
+
conversationIdRef.current = conversationId;
|
|
10741
10750
|
const itemsRef = useRef(items);
|
|
10742
10751
|
itemsRef.current = items;
|
|
10743
10752
|
const attachmentsRef = useRef(attachments);
|
|
@@ -10907,6 +10916,15 @@ function ChatScreen({ agent, conversation }) {
|
|
|
10907
10916
|
initialConversationId,
|
|
10908
10917
|
agentHost
|
|
10909
10918
|
]);
|
|
10919
|
+
const markRead = useCallback(() => {
|
|
10920
|
+
const id = conversationIdRef.current;
|
|
10921
|
+
if (!rest || !id) return;
|
|
10922
|
+
rest.markConversationRead({ conversationId: id }).catch(() => {});
|
|
10923
|
+
}, [rest]);
|
|
10924
|
+
useEffect(() => {
|
|
10925
|
+
if (!conversationId) return;
|
|
10926
|
+
markRead();
|
|
10927
|
+
}, [conversationId, markRead]);
|
|
10910
10928
|
const attachToRun = useCallback((runId, runAgentName, runStartedAtMs) => {
|
|
10911
10929
|
if (!rest) return;
|
|
10912
10930
|
seenRunsRef.current.add(runId);
|
|
@@ -10959,6 +10977,7 @@ function ChatScreen({ agent, conversation }) {
|
|
|
10959
10977
|
attachments: m.attachments
|
|
10960
10978
|
} : m));
|
|
10961
10979
|
setRun({ kind: "idle" });
|
|
10980
|
+
markRead();
|
|
10962
10981
|
agentHost.transition({
|
|
10963
10982
|
state: "idle",
|
|
10964
10983
|
notification: {
|
|
@@ -10980,7 +10999,8 @@ function ChatScreen({ agent, conversation }) {
|
|
|
10980
10999
|
}, [
|
|
10981
11000
|
rest,
|
|
10982
11001
|
agent.name,
|
|
10983
|
-
agentHost
|
|
11002
|
+
agentHost,
|
|
11003
|
+
markRead
|
|
10984
11004
|
]);
|
|
10985
11005
|
const multiAgent = useMemo(() => conversationAgentNames(items, agent.name), [items, agent.name]).size > 1;
|
|
10986
11006
|
const transcriptWindow = useMemo(() => windowItems(items), [items]);
|
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
import { a as mintPortalDeviceToken, c as unifyLegacyCliGrants, i as grantPortalAccess, n as fetchPortalDevices, r as findThisDevice } from "./api-DG5W6iwx.mjs";
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import { z } from "zod";
|
|
5
|
-
import
|
|
5
|
+
import * as childProcess from "node:child_process";
|
|
6
|
+
import { spawn } from "node:child_process";
|
|
6
7
|
import net from "node:net";
|
|
7
8
|
import { WebSocket, createWebSocketStream } from "ws";
|
|
8
9
|
|
|
9
10
|
//#region ../portal-daemon/src/machine.ts
|
|
11
|
+
const SCUTIL_TIMEOUT_MS = 2e3;
|
|
12
|
+
const SCUTIL_ATTEMPTS = 3;
|
|
10
13
|
/**
|
|
11
14
|
* Identity this machine registers under on the portal.
|
|
12
15
|
*
|
|
@@ -15,38 +18,74 @@ import { WebSocket, createWebSocketStream } from "ws";
|
|
|
15
18
|
* row, so a grant applies to the machine no matter which surface the user
|
|
16
19
|
* shared from. The name must therefore match what the desktop app registers —
|
|
17
20
|
* on macOS that is `scutil --get LocalHostName` (the Rust client's own
|
|
18
|
-
* derivation, stabler than the network-assigned hostname)
|
|
19
|
-
*
|
|
21
|
+
* derivation, stabler than the network-assigned hostname).
|
|
22
|
+
*
|
|
23
|
+
* The machine name is a durable IDENTITY, not a fresh network reading: every
|
|
24
|
+
* grant hangs off the device row keyed by this name, so if it changes the
|
|
25
|
+
* device flips to a brand-new row with ZERO grants and every agent re-prompts
|
|
26
|
+
* across every open CLI. `os.hostname()` is NOT durable — macOS rewrites it
|
|
27
|
+
* from DHCP/DNS per network — so it must never be allowed to silently replace
|
|
28
|
+
* a name we already registered under. Resolution order:
|
|
29
|
+
*
|
|
30
|
+
* 1. `scutil --get LocalHostName` (retried) — the stable, correct source.
|
|
31
|
+
* 2. `previous` — the name we last successfully registered under, persisted
|
|
32
|
+
* by the daemon. Preferred over the volatile hostname so a transient
|
|
33
|
+
* `scutil` failure keeps our existing identity (and grants) intact.
|
|
34
|
+
* 3. `os.hostname()` — last resort for a machine that has NEVER resolved a
|
|
35
|
+
* name (first run, non-macOS, scutil permanently unavailable).
|
|
20
36
|
*
|
|
21
37
|
* Historically the CLI suffixed `-cli` to keep a device distinct from the
|
|
22
38
|
* desktop's; `unifyLegacyCliGrants` migrates grants off those rows.
|
|
23
39
|
*/
|
|
24
|
-
async function resolveMachineIdentity() {
|
|
25
|
-
const
|
|
26
|
-
if (process.platform !== "darwin")
|
|
27
|
-
machineName
|
|
28
|
-
|
|
40
|
+
async function resolveMachineIdentity(previous) {
|
|
41
|
+
const persisted = previous?.trim() || null;
|
|
42
|
+
if (process.platform !== "darwin") {
|
|
43
|
+
const machineName = persisted ?? fallbackHost();
|
|
44
|
+
return {
|
|
45
|
+
machineName,
|
|
46
|
+
friendlyName: machineName,
|
|
47
|
+
machineNameSource: persisted ? "persisted" : "hostname-fallback"
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
const local = await scutilRead("LocalHostName");
|
|
51
|
+
if (local) return {
|
|
52
|
+
machineName: local,
|
|
53
|
+
friendlyName: await scutilRead("ComputerName") ?? local,
|
|
54
|
+
machineNameSource: "scutil"
|
|
55
|
+
};
|
|
56
|
+
if (persisted) return {
|
|
57
|
+
machineName: persisted,
|
|
58
|
+
friendlyName: persisted,
|
|
59
|
+
machineNameSource: "persisted"
|
|
29
60
|
};
|
|
30
|
-
const
|
|
61
|
+
const fallback = fallbackHost();
|
|
31
62
|
return {
|
|
32
|
-
machineName:
|
|
33
|
-
friendlyName:
|
|
63
|
+
machineName: fallback,
|
|
64
|
+
friendlyName: fallback,
|
|
65
|
+
machineNameSource: "hostname-fallback"
|
|
34
66
|
};
|
|
35
67
|
}
|
|
36
68
|
function fallbackHost() {
|
|
37
69
|
return (os.hostname() || "machine").trim().replace(/\.local$/i, "") || "machine";
|
|
38
70
|
}
|
|
39
71
|
function scutilRead(key) {
|
|
40
|
-
return
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
72
|
+
return attempt(0);
|
|
73
|
+
function attempt(n) {
|
|
74
|
+
return new Promise((resolve) => {
|
|
75
|
+
childProcess.execFile("/usr/sbin/scutil", ["--get", key], { timeout: SCUTIL_TIMEOUT_MS }, (error, stdout) => {
|
|
76
|
+
if (error) {
|
|
77
|
+
if (n + 1 < SCUTIL_ATTEMPTS) {
|
|
78
|
+
resolve(attempt(n + 1));
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
resolve(null);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const value = stdout.trim();
|
|
85
|
+
resolve(value.length > 0 ? value : null);
|
|
86
|
+
});
|
|
48
87
|
});
|
|
49
|
-
}
|
|
88
|
+
}
|
|
50
89
|
}
|
|
51
90
|
const INHERITED_ENV = [
|
|
52
91
|
"HOME",
|
|
@@ -550,9 +589,10 @@ var PortalClient = class {
|
|
|
550
589
|
}
|
|
551
590
|
async connectLoop() {
|
|
552
591
|
if (!this.machineName) {
|
|
553
|
-
const identity = await resolveMachineIdentity();
|
|
592
|
+
const identity = await resolveMachineIdentity(this.opts.persistedMachineName);
|
|
554
593
|
this.machineName = identity.machineName;
|
|
555
594
|
this.friendlyName = identity.friendlyName;
|
|
595
|
+
this.opts.onMachineName(identity.machineName, identity.machineNameSource);
|
|
556
596
|
}
|
|
557
597
|
let backoff = INITIAL_BACKOFF_MS;
|
|
558
598
|
while (this.enabled && !this.disposed) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { n as isRecord, t as PortalClient } from "./client-
|
|
2
|
+
import { n as isRecord, t as PortalClient } from "./client-DbqRBquD.mjs";
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { z } from "zod";
|
|
@@ -20,7 +20,7 @@ import { access, appendFile, mkdir, readFile, unlink, writeFile } from "node:fs/
|
|
|
20
20
|
* the commit time of the built tree is one monotonic clock they share.
|
|
21
21
|
*/
|
|
22
22
|
function portalDaemonBuild() {
|
|
23
|
-
return "
|
|
23
|
+
return "1786604432";
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
26
|
* Whether a client carrying `mine` should replace a running daemon carrying
|
|
@@ -365,6 +365,7 @@ var PortalDaemon = class {
|
|
|
365
365
|
conns = /* @__PURE__ */ new Set();
|
|
366
366
|
cwds = /* @__PURE__ */ new Map();
|
|
367
367
|
declined = /* @__PURE__ */ new Set();
|
|
368
|
+
persistedMachineName = null;
|
|
368
369
|
fallbackCwd;
|
|
369
370
|
idleTimer = null;
|
|
370
371
|
sessionToken = null;
|
|
@@ -499,12 +500,28 @@ var PortalDaemon = class {
|
|
|
499
500
|
deviceToken: this.deviceToken
|
|
500
501
|
}),
|
|
501
502
|
resolveCwd: (conversationId) => this.resolveCwd(conversationId),
|
|
503
|
+
persistedMachineName: this.persistedMachineName,
|
|
504
|
+
onMachineName: (name, source) => this.onMachineName(name, source),
|
|
502
505
|
onState: (state) => {
|
|
503
506
|
this.lastState = state;
|
|
504
507
|
this.broadcastState();
|
|
505
508
|
}
|
|
506
509
|
});
|
|
507
510
|
}
|
|
511
|
+
/**
|
|
512
|
+
* The identity resolved on connect. Persist the name so a later scutil
|
|
513
|
+
* failure reuses it instead of adopting the volatile hostname, and log the
|
|
514
|
+
* source — a `hostname-fallback` after we'd previously registered under
|
|
515
|
+
* scutil is the tell that a flap just orphaned this machine's grants.
|
|
516
|
+
*/
|
|
517
|
+
onMachineName(name, source) {
|
|
518
|
+
if (source === "hostname-fallback" && this.persistedMachineName) this.logInfo(`portal identity WARNING: fell back to hostname "${name}" but had previously registered as "${this.persistedMachineName}" — grants may be orphaned`);
|
|
519
|
+
else this.logInfo(`portal identity: "${name}" (source=${source})`);
|
|
520
|
+
if (name && name !== this.persistedMachineName) {
|
|
521
|
+
this.persistedMachineName = name;
|
|
522
|
+
this.persistState();
|
|
523
|
+
}
|
|
524
|
+
}
|
|
508
525
|
/** The cwd an exec for `conversationId` runs in. */
|
|
509
526
|
resolveCwd(conversationId) {
|
|
510
527
|
if (conversationId) {
|
|
@@ -538,7 +555,14 @@ var PortalDaemon = class {
|
|
|
538
555
|
/** Append a line to the daemon log file (best-effort, for post-hoc debugging). */
|
|
539
556
|
logError(context, error) {
|
|
540
557
|
const message = error instanceof Error ? error.message : String(error);
|
|
541
|
-
|
|
558
|
+
this.logLine(`${context}: ${message}`);
|
|
559
|
+
}
|
|
560
|
+
/** Append an informational line to the daemon log file (best-effort). */
|
|
561
|
+
logInfo(message) {
|
|
562
|
+
this.logLine(message);
|
|
563
|
+
}
|
|
564
|
+
logLine(message) {
|
|
565
|
+
const line = `${(/* @__PURE__ */ new Date()).toISOString()} ${message}\n`;
|
|
542
566
|
appendFile(this.paths.logPath, line).catch((_error) => {});
|
|
543
567
|
}
|
|
544
568
|
/** Close the listener without exiting the process (tests own the process). */
|
|
@@ -598,6 +622,7 @@ var PortalDaemon = class {
|
|
|
598
622
|
if (Array.isArray(parsed.declined)) {
|
|
599
623
|
for (const id of parsed.declined) if (typeof id === "string") this.declined.add(id);
|
|
600
624
|
}
|
|
625
|
+
if (typeof parsed.machineName === "string" && parsed.machineName) this.persistedMachineName = parsed.machineName;
|
|
601
626
|
}
|
|
602
627
|
} catch (_error) {}
|
|
603
628
|
}
|
|
@@ -605,7 +630,8 @@ var PortalDaemon = class {
|
|
|
605
630
|
const state = {
|
|
606
631
|
version: LOCAL_PROTOCOL_VERSION,
|
|
607
632
|
cwds: Object.fromEntries(this.cwds),
|
|
608
|
-
declined: [...this.declined]
|
|
633
|
+
declined: [...this.declined],
|
|
634
|
+
machineName: this.persistedMachineName ?? void 0
|
|
609
635
|
};
|
|
610
636
|
writeFile(this.paths.statePath, JSON.stringify(state)).catch((error) => {
|
|
611
637
|
this.logError("persistState failed", error);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import "./client-
|
|
3
|
-
import { a as runPortalDaemon, i as queryDaemonStatus, n as ensureDaemonRunning, o as startPortalDaemon, r as isDaemonListening, s as stopDaemon, t as PortalDaemon } from "./daemon-
|
|
2
|
+
import "./client-DbqRBquD.mjs";
|
|
3
|
+
import { a as runPortalDaemon, i as queryDaemonStatus, n as ensureDaemonRunning, o as startPortalDaemon, r as isDaemonListening, s as stopDaemon, t as PortalDaemon } from "./daemon-CL25CwjW.mjs";
|
|
4
4
|
import "./api-DG5W6iwx.mjs";
|
|
5
5
|
|
|
6
6
|
export { runPortalDaemon };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { c as LOCAL_PROTOCOL_VERSION, d as encodeLine, f as makeLineParser, n as ensureDaemonRunning, p as parseDaemonMessage, u as daemonPaths } from "./daemon-
|
|
2
|
+
import { c as LOCAL_PROTOCOL_VERSION, d as encodeLine, f as makeLineParser, n as ensureDaemonRunning, p as parseDaemonMessage, u as daemonPaths } from "./daemon-CL25CwjW.mjs";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
4
|
import { connect } from "node:net";
|
|
5
5
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as runPrint, i as resolveAgent, n as messageGet, o as toPrintError, r as readStdin, t as collectRunText } from "./print-
|
|
3
|
-
import "./rest-
|
|
2
|
+
import { a as runPrint, i as resolveAgent, n as messageGet, o as toPrintError, r as readStdin, t as collectRunText } from "./print-riiY5Gly.mjs";
|
|
3
|
+
import "./rest-CLrHVkxh.mjs";
|
|
4
4
|
import "./billing-blocked-2wju4gC_.mjs";
|
|
5
5
|
|
|
6
6
|
export { messageGet, readStdin, resolveAgent, runPrint };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { t as HttpError } from "./http-error-DzyrsLAZ.mjs";
|
|
3
|
-
import { a as isRecord, i as errorMessage, r as sendErrorMessage, t as createRestClient } from "./rest-
|
|
3
|
+
import { a as isRecord, i as errorMessage, r as sendErrorMessage, t as createRestClient } from "./rest-CLrHVkxh.mjs";
|
|
4
4
|
import { i as billingBlockedOutcomeFromSendResponse, n as BillingBlockedError } from "./billing-blocked-2wju4gC_.mjs";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import Conf from "conf";
|
|
@@ -14,7 +14,7 @@ import { n as printError } from "./output-DYzzdXYV.mjs";
|
|
|
14
14
|
* the reply (and to --json).
|
|
15
15
|
*/
|
|
16
16
|
async function connectMachineShare({ appUrl, sessionToken, timeoutHint }) {
|
|
17
|
-
const { PortalClient } = await import("./client-
|
|
17
|
+
const { PortalClient } = await import("./client-hH2PJL8y.mjs");
|
|
18
18
|
let signalConnected;
|
|
19
19
|
const connected = new Promise((resolve) => {
|
|
20
20
|
signalConnected = resolve;
|
|
@@ -26,6 +26,8 @@ async function connectMachineShare({ appUrl, sessionToken, timeoutHint }) {
|
|
|
26
26
|
deviceToken: null
|
|
27
27
|
}),
|
|
28
28
|
resolveCwd: () => process.cwd(),
|
|
29
|
+
persistedMachineName: null,
|
|
30
|
+
onMachineName: () => {},
|
|
29
31
|
onState: (state) => {
|
|
30
32
|
if (state.status === "connected") signalConnected();
|
|
31
33
|
if (state.status === "error") console.error(`portal: connection error: ${state.error ?? "unknown"}; retrying`);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { S as getConfigPath } from "./print-
|
|
2
|
+
import { S as getConfigPath } from "./print-riiY5Gly.mjs";
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { err, ok } from "neverthrow";
|
|
@@ -8,7 +8,7 @@ import fs from "node:fs";
|
|
|
8
8
|
|
|
9
9
|
//#region package.json
|
|
10
10
|
var name = "skydive-cli";
|
|
11
|
-
var version$1 = "0.5.0-beta.
|
|
11
|
+
var version$1 = "0.5.0-beta.14";
|
|
12
12
|
|
|
13
13
|
//#endregion
|
|
14
14
|
//#region src/auth/organization.ts
|
|
@@ -329,6 +329,9 @@ function createRestClient({ appUrl, sessionToken, workspaceId }) {
|
|
|
329
329
|
setConversationArchived: async ({ conversationId, archived }) => {
|
|
330
330
|
await post(`/api/v1/conversations/${encodeURIComponent(conversationId)}/archive`, { archived }, z.object({ archived: z.boolean() }));
|
|
331
331
|
},
|
|
332
|
+
markConversationRead: async ({ conversationId }) => {
|
|
333
|
+
await post(`/api/v1/conversations/${encodeURIComponent(conversationId)}/read`, {}, z.object({ read: z.boolean() }));
|
|
334
|
+
},
|
|
332
335
|
renameConversation: async ({ conversationId, title }) => {
|
|
333
336
|
await post(`/api/v1/conversations/${encodeURIComponent(conversationId)}`, { title }, z.object({ conversation: z.object({ id: z.string() }) }), "PATCH");
|
|
334
337
|
},
|
|
@@ -469,6 +472,7 @@ const conversationSummarySchema = z.object({
|
|
|
469
472
|
channel: z.string().nullable(),
|
|
470
473
|
channelLabel: z.string().nullable(),
|
|
471
474
|
viewerArchivedAt: z.string().nullable().optional(),
|
|
475
|
+
unread: z.boolean().optional(),
|
|
472
476
|
agent: conversationAgentSchema,
|
|
473
477
|
agents: z.array(conversationAgentSchema).optional()
|
|
474
478
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { t as HttpError } from "./http-error-DzyrsLAZ.mjs";
|
|
3
|
-
import { n as errorDetail, r as sendErrorMessage, t as createRestClient } from "./rest-
|
|
3
|
+
import { n as errorDetail, r as sendErrorMessage, t as createRestClient } from "./rest-CLrHVkxh.mjs";
|
|
4
4
|
import "./billing-blocked-2wju4gC_.mjs";
|
|
5
5
|
|
|
6
6
|
export { createRestClient };
|
package/package.json
CHANGED