@undefineds.co/linx 0.3.5 → 0.3.7
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 +58 -23
- package/dist/generated/version.js +1 -1
- package/dist/generated/version.js.map +1 -1
- package/dist/index.js +334 -162
- package/dist/index.js.map +1 -1
- package/dist/lib/account-session.js +4 -8
- package/dist/lib/account-session.js.map +1 -1
- package/dist/lib/ai-command.js +228 -178
- package/dist/lib/ai-command.js.map +1 -1
- package/dist/lib/auto-mode/archive.js +38 -7
- package/dist/lib/auto-mode/archive.js.map +1 -1
- package/dist/lib/auto-mode/auth.js.map +1 -1
- package/dist/lib/auto-mode/display.js +71 -45
- package/dist/lib/auto-mode/display.js.map +1 -1
- package/dist/lib/auto-mode/format.js +9 -7
- package/dist/lib/auto-mode/format.js.map +1 -1
- package/dist/lib/auto-mode/hooks/claude.js +12 -2
- package/dist/lib/auto-mode/hooks/claude.js.map +1 -1
- package/dist/lib/auto-mode/hooks/codex.js +17 -7
- package/dist/lib/auto-mode/hooks/codex.js.map +1 -1
- package/dist/lib/auto-mode/hooks/index.js +28 -8
- package/dist/lib/auto-mode/hooks/index.js.map +1 -1
- package/dist/lib/auto-mode/pod-ai.js +20 -37
- package/dist/lib/auto-mode/pod-ai.js.map +1 -1
- package/dist/lib/auto-mode/pod-approval.js +124 -195
- package/dist/lib/auto-mode/pod-approval.js.map +1 -1
- package/dist/lib/auto-mode/pod-persistence.js +169 -90
- package/dist/lib/auto-mode/pod-persistence.js.map +1 -1
- package/dist/lib/auto-mode/runner.js +683 -81
- package/dist/lib/auto-mode/runner.js.map +1 -1
- package/dist/lib/auto-mode/secretary.js +186 -41
- package/dist/lib/auto-mode/secretary.js.map +1 -1
- package/dist/lib/auto-mode-command.js +32 -32
- package/dist/lib/auto-mode-command.js.map +1 -1
- package/dist/lib/chat-api.js +242 -50
- package/dist/lib/chat-api.js.map +1 -1
- package/dist/lib/codex-plugin/bridge.js +164 -17
- package/dist/lib/codex-plugin/bridge.js.map +1 -1
- package/dist/lib/codex-plugin/codex-native-proxy.js +370 -34
- package/dist/lib/codex-plugin/codex-native-proxy.js.map +1 -1
- package/dist/lib/credentials-store.js +33 -42
- package/dist/lib/credentials-store.js.map +1 -1
- package/dist/lib/linx-cloud-errors.js +61 -0
- package/dist/lib/linx-cloud-errors.js.map +1 -0
- package/dist/lib/linx-tui-contract.js +8 -5
- package/dist/lib/linx-tui-contract.js.map +1 -1
- package/dist/lib/login-command.js +9 -2
- package/dist/lib/login-command.js.map +1 -1
- package/dist/lib/models.js +3 -20
- package/dist/lib/models.js.map +1 -1
- package/dist/lib/oidc-auth.js +143 -17
- package/dist/lib/oidc-auth.js.map +1 -1
- package/dist/lib/oidc-session-storage.js +2 -6
- package/dist/lib/oidc-session-storage.js.map +1 -1
- package/dist/lib/pi-adapter/auto-input-controller.js +988 -0
- package/dist/lib/pi-adapter/auto-input-controller.js.map +1 -0
- package/dist/lib/pi-adapter/backend-command.js +2 -0
- package/dist/lib/pi-adapter/backend-command.js.map +1 -0
- package/dist/lib/pi-adapter/backend-credentials.js +80 -0
- package/dist/lib/pi-adapter/backend-credentials.js.map +1 -0
- package/dist/lib/pi-adapter/branding.js +246 -108
- package/dist/lib/pi-adapter/branding.js.map +1 -1
- package/dist/lib/pi-adapter/control-state.js +72 -0
- package/dist/lib/pi-adapter/control-state.js.map +1 -0
- package/dist/lib/pi-adapter/interactive.js +2634 -30
- package/dist/lib/pi-adapter/interactive.js.map +1 -1
- package/dist/lib/pi-adapter/pod-approval.js +382 -210
- package/dist/lib/pi-adapter/pod-approval.js.map +1 -1
- package/dist/lib/pi-adapter/pod-mirror-mapping.js +71 -17
- package/dist/lib/pi-adapter/pod-mirror-mapping.js.map +1 -1
- package/dist/lib/pi-adapter/pod-mirror.js +531 -64
- package/dist/lib/pi-adapter/pod-mirror.js.map +1 -1
- package/dist/lib/pi-adapter/pod-native.js +81 -85
- package/dist/lib/pi-adapter/pod-native.js.map +1 -1
- package/dist/lib/pi-adapter/pod-status-output.js +54 -0
- package/dist/lib/pi-adapter/pod-status-output.js.map +1 -0
- package/dist/lib/pi-adapter/runtime.js +458 -228
- package/dist/lib/pi-adapter/runtime.js.map +1 -1
- package/dist/lib/pi-adapter/session-control.js +509 -0
- package/dist/lib/pi-adapter/session-control.js.map +1 -0
- package/dist/lib/pi-adapter/session.js +35 -22
- package/dist/lib/pi-adapter/session.js.map +1 -1
- package/dist/lib/pi-adapter/stream.js +89 -32
- package/dist/lib/pi-adapter/stream.js.map +1 -1
- package/dist/lib/pi-adapter/sync-recovery.js +89 -0
- package/dist/lib/pi-adapter/sync-recovery.js.map +1 -0
- package/dist/lib/pi-adapter/web-fetch.js +13 -14
- package/dist/lib/pi-adapter/web-fetch.js.map +1 -1
- package/dist/lib/pod-chat-store.js +254 -78
- package/dist/lib/pod-chat-store.js.map +1 -1
- package/dist/lib/pod-data-session.js +156 -35
- package/dist/lib/pod-data-session.js.map +1 -1
- package/dist/lib/solid-auth-store.js +27 -0
- package/dist/lib/solid-auth-store.js.map +1 -0
- package/dist/lib/solid-auth.js +2 -4
- package/dist/lib/solid-auth.js.map +1 -1
- package/dist/lib/solid-client-credentials-login.js +100 -0
- package/dist/lib/solid-client-credentials-login.js.map +1 -0
- package/dist/lib/solid-local-store.js +31 -0
- package/dist/lib/solid-local-store.js.map +1 -0
- package/dist/lib/symphony/archive.js +328 -18
- package/dist/lib/symphony/archive.js.map +1 -1
- package/dist/lib/symphony/pod-projection.js +2222 -0
- package/dist/lib/symphony/pod-projection.js.map +1 -0
- package/dist/lib/symphony-command.js +602 -178
- package/dist/lib/symphony-command.js.map +1 -1
- package/dist/lib/sync-checkpoint-store.js +74 -0
- package/dist/lib/sync-checkpoint-store.js.map +1 -0
- package/dist/skills/symphony/SKILL.md +665 -0
- package/package.json +15 -9
- package/vendor/agent-runtime/dist/agent-runtime.d.ts +137 -0
- package/vendor/agent-runtime/dist/agent-runtime.js +211 -0
- package/vendor/agent-runtime/dist/auto-mode.d.ts +78 -13
- package/vendor/agent-runtime/dist/auto-mode.js +288 -31
- package/vendor/agent-runtime/dist/control-plane.d.ts +28 -0
- package/vendor/agent-runtime/dist/control-plane.js +79 -0
- package/vendor/agent-runtime/dist/file-sync.d.ts +157 -0
- package/vendor/agent-runtime/dist/file-sync.js +314 -0
- package/vendor/agent-runtime/dist/index.d.ts +7 -0
- package/vendor/agent-runtime/dist/index.js +7 -0
- package/vendor/agent-runtime/dist/reconciler.d.ts +117 -0
- package/vendor/agent-runtime/dist/reconciler.js +361 -0
- package/vendor/agent-runtime/dist/symphony.d.ts +128 -8
- package/vendor/agent-runtime/dist/symphony.js +362 -57
- package/vendor/agent-runtime/dist/sync.d.ts +271 -0
- package/vendor/agent-runtime/dist/sync.js +550 -0
- package/vendor/agent-runtime/dist/thread-reconciler-controller.d.ts +58 -0
- package/vendor/agent-runtime/dist/thread-reconciler-controller.js +137 -0
- package/vendor/agent-runtime/dist/turn-controller.js +2 -2
- package/vendor/agent-runtime/dist/wake-scheduler.d.ts +67 -0
- package/vendor/agent-runtime/dist/wake-scheduler.js +194 -0
- package/vendor/agent-runtime/package.json +8 -1
- package/vendor/pi-web-access/CHANGELOG.md +387 -0
- package/vendor/pi-web-access/LICENSE +21 -0
- package/vendor/pi-web-access/README.md +352 -0
- package/vendor/pi-web-access/activity.ts +101 -0
- package/vendor/pi-web-access/banner.png +0 -0
- package/vendor/pi-web-access/chrome-cookies.ts +322 -0
- package/vendor/pi-web-access/code-search.ts +107 -0
- package/vendor/pi-web-access/curator-page.ts +3359 -0
- package/vendor/pi-web-access/curator-server.ts +605 -0
- package/vendor/pi-web-access/exa.ts +520 -0
- package/vendor/pi-web-access/extract.ts +641 -0
- package/vendor/pi-web-access/gemini-api.ts +112 -0
- package/vendor/pi-web-access/gemini-search.ts +361 -0
- package/vendor/pi-web-access/gemini-url-context.ts +126 -0
- package/vendor/pi-web-access/gemini-web-config.ts +52 -0
- package/vendor/pi-web-access/gemini-web.ts +396 -0
- package/vendor/pi-web-access/github-api.ts +196 -0
- package/vendor/pi-web-access/github-extract.ts +634 -0
- package/vendor/pi-web-access/index.ts +2346 -0
- package/vendor/pi-web-access/package.json +45 -0
- package/vendor/pi-web-access/pdf-extract.ts +192 -0
- package/vendor/pi-web-access/perplexity.ts +195 -0
- package/vendor/pi-web-access/pi-web-fetch-demo.mp4 +0 -0
- package/vendor/pi-web-access/rsc-extract.ts +338 -0
- package/vendor/pi-web-access/skills/librarian/SKILL.md +195 -0
- package/vendor/pi-web-access/storage.ts +72 -0
- package/vendor/pi-web-access/summary-review.ts +276 -0
- package/vendor/pi-web-access/test/gemini-web-cookie-opt-in.test.mjs +41 -0
- package/vendor/pi-web-access/test/pdf-extract.test.mjs +95 -0
- package/vendor/pi-web-access/utils.ts +44 -0
- package/vendor/pi-web-access/video-extract.ts +378 -0
- package/vendor/pi-web-access/youtube-extract.ts +310 -0
- package/dist/lib/pi-adapter/auth.js +0 -68
- package/dist/lib/pi-adapter/auth.js.map +0 -1
- package/dist/lib/pi-adapter/pod-tools.js +0 -140
- package/dist/lib/pi-adapter/pod-tools.js.map +0 -1
- package/dist/skills/drizzle-solid/SKILL.md +0 -340
- package/dist/skills/pod-storage/SKILL.md +0 -100
- package/dist/skills/solid-modeling/SKILL.md +0 -274
- package/dist/skills/xpod-componentsjs/SKILL.md +0 -284
package/dist/index.js
CHANGED
|
@@ -1,26 +1,30 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import './lib/node-warning-filter.js';
|
|
3
3
|
import { readFileSync } from 'node:fs';
|
|
4
|
+
import { join } from 'node:path';
|
|
4
5
|
import yargs from 'yargs';
|
|
5
6
|
import { hideBin } from 'yargs/helpers';
|
|
6
7
|
import { aiCommand } from './lib/ai-command.js';
|
|
7
8
|
import { resolveAccountBaseUrl } from './lib/account-api.js';
|
|
8
9
|
import { loadCredentials } from './lib/credentials-store.js';
|
|
9
10
|
import { loginCommand, logoutCommand, whoamiCommand } from './lib/login-command.js';
|
|
10
|
-
import { DefaultPackageManager, SettingsManager, runPrintMode } from '@
|
|
11
|
+
import { DefaultPackageManager, SettingsManager, SessionSelectorComponent, runPrintMode } from '@earendil-works/pi-coding-agent';
|
|
12
|
+
import { ProcessTerminal, TUI } from '@earendil-works/pi-tui';
|
|
11
13
|
import { promptText } from './lib/prompt.js';
|
|
12
14
|
import { buildAutoModeOptions, isAutoModeRequest, runAutoModeCommand, } from './lib/auto-mode-command.js';
|
|
13
|
-
import { formatAutoModeSessionSummary, listArchivedAutoModeSessions, loadArchivedAutoModeSession, resumeAutoModeSession, } from './lib/auto-mode/index.js';
|
|
14
|
-
import { symphonyCommand } from './lib/symphony-command.js';
|
|
15
15
|
import { resolveRuntimeTarget } from './lib/runtime-target.js';
|
|
16
16
|
import { createCodexNativeProxy } from './lib/codex-plugin/index.js';
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import { createPodDataSession } from './lib/pod-data-session.js';
|
|
17
|
+
import { bootstrapLinxInteractiveMode, createLinxRuntimeAdapter, resolveLinxInteractiveLoginReason, resolveLinxStartupLoginPromptDecision, } from './lib/pi-adapter/index.js';
|
|
18
|
+
import { clearDefaultPodDataSession, createPodDataSession, getDefaultPodDataSession } from './lib/pod-data-session.js';
|
|
20
19
|
import { DEFAULT_LINX_CLOUD_MODEL_ID, FALLBACK_LINX_CLOUD_MODEL_IDS } from './lib/default-model.js';
|
|
21
|
-
import { createLinxPiSessionManager,
|
|
20
|
+
import { createLinxPiSessionManager, listLinxPiSessions, } from './lib/pi-adapter/session.js';
|
|
22
21
|
import { LinxPiPodMirror } from './lib/pi-adapter/pod-mirror.js';
|
|
22
|
+
import { listPendingPiPodMirrorSync, retryPendingPiPodMirrorSync } from './lib/pi-adapter/sync-recovery.js';
|
|
23
23
|
import { LINX_AGENT_DIR } from './lib/pi-adapter/branding.js';
|
|
24
|
+
import { createFileSyncCheckpointStore } from './lib/sync-checkpoint-store.js';
|
|
25
|
+
import { deriveLinxPiStartupControlState, hydrateLinxPiControlState } from './lib/pi-adapter/control-state.js';
|
|
26
|
+
import { drizzle, solidResources } from './lib/models.js';
|
|
27
|
+
import { formatLinxCliErrorMessage } from './lib/linx-cloud-errors.js';
|
|
24
28
|
function readPackageVersion() {
|
|
25
29
|
try {
|
|
26
30
|
const raw = readFileSync(new URL('../package.json', import.meta.url), 'utf-8');
|
|
@@ -77,11 +81,10 @@ async function resolveContext(urlOverride) {
|
|
|
77
81
|
issuerUrl: podSession.credentials.url,
|
|
78
82
|
runtimeUrlOverride: urlOverride,
|
|
79
83
|
});
|
|
80
|
-
const apiKey = await resolvePodRuntimeAuthToken(podSession);
|
|
81
84
|
const session = podSession.solidSession;
|
|
82
85
|
await runtime.initPodData(session);
|
|
83
86
|
const chatId = await runtime.getOrCreateDefaultChat(session);
|
|
84
|
-
return { runtimeUrl: target.runtimeUrl,
|
|
87
|
+
return { runtimeUrl: target.runtimeUrl, authFetch: podSession.runtimeFetch, session, podSession, chatId, runtime };
|
|
85
88
|
}
|
|
86
89
|
async function resolveRuntimeAuthContext(urlOverride) {
|
|
87
90
|
const runtime = await loadChatRuntime();
|
|
@@ -90,10 +93,9 @@ async function resolveRuntimeAuthContext(urlOverride) {
|
|
|
90
93
|
issuerUrl: podSession.credentials.url,
|
|
91
94
|
runtimeUrlOverride: urlOverride,
|
|
92
95
|
});
|
|
93
|
-
const apiKey = await resolvePodRuntimeAuthToken(podSession);
|
|
94
96
|
return {
|
|
95
97
|
runtimeUrl: target.runtimeUrl,
|
|
96
|
-
|
|
98
|
+
authFetch: podSession.runtimeFetch,
|
|
97
99
|
session: podSession.solidSession,
|
|
98
100
|
podSession,
|
|
99
101
|
runtime,
|
|
@@ -109,43 +111,76 @@ async function createLinxPodDataSession() {
|
|
|
109
111
|
}
|
|
110
112
|
return podSession;
|
|
111
113
|
}
|
|
112
|
-
async function
|
|
113
|
-
|
|
114
|
-
return
|
|
115
|
-
}
|
|
116
|
-
catch (error) {
|
|
117
|
-
if (isOidcLoginExpiredError(error)) {
|
|
118
|
-
throw new Error('LinX Cloud login expired. Run `linx login` to re-authorize.');
|
|
119
|
-
}
|
|
120
|
-
throw error;
|
|
114
|
+
async function resolveStartupLinxPodDataSession() {
|
|
115
|
+
if (!loadCredentials()) {
|
|
116
|
+
return null;
|
|
121
117
|
}
|
|
118
|
+
return createLinxPodDataSession();
|
|
122
119
|
}
|
|
123
120
|
async function runSingleTurn(options) {
|
|
124
121
|
const { ctx, threadId, model, prompt } = options;
|
|
125
|
-
const history = await
|
|
126
|
-
await ctx.runtime.saveUserMessage(ctx.session, ctx.chatId, threadId, prompt);
|
|
122
|
+
const history = await tryLoadMessages(ctx, threadId);
|
|
127
123
|
const reply = await ctx.runtime.createRemoteCompletion({
|
|
128
124
|
runtimeUrl: ctx.runtimeUrl,
|
|
129
|
-
|
|
125
|
+
authFetch: ctx.authFetch,
|
|
130
126
|
model,
|
|
131
127
|
messages: [...ctx.runtime.toOpenAiMessages(history), { role: 'user', content: prompt }],
|
|
132
128
|
});
|
|
133
129
|
const replyText = typeof reply === 'string' ? reply : reply.content ?? '';
|
|
134
|
-
await ctx.runtime.saveAssistantMessage(ctx.session, ctx.chatId, threadId, replyText);
|
|
135
130
|
process.stdout.write(`\n${replyText}\n\n`);
|
|
131
|
+
await persistSingleTurnBestEffort(ctx, threadId, prompt, replyText);
|
|
132
|
+
}
|
|
133
|
+
async function tryLoadMessages(ctx, threadId) {
|
|
134
|
+
try {
|
|
135
|
+
return await ctx.runtime.loadMessages(ctx.session, threadId);
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
process.stderr.write(`Warning: failed to load Pod chat history; continuing without history: ${formatLinxCliErrorMessage(error)}\n`);
|
|
139
|
+
return [];
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
async function persistSingleTurnBestEffort(ctx, threadId, prompt, replyText) {
|
|
143
|
+
try {
|
|
144
|
+
await ctx.runtime.saveUserMessage(ctx.session, ctx.chatId, threadId, prompt);
|
|
145
|
+
await ctx.runtime.saveAssistantMessage(ctx.session, ctx.chatId, threadId, replyText);
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
process.stderr.write(`Warning: failed to persist Pod chat turn: ${formatLinxCliErrorMessage(error)}\n`);
|
|
149
|
+
}
|
|
136
150
|
}
|
|
137
151
|
async function resolveThreadId(options) {
|
|
138
|
-
const { ctx, continueMode, explicitThreadId, workspace } = options;
|
|
152
|
+
const { ctx, continueMode, explicitThreadId, workspace, bestEffort } = options;
|
|
139
153
|
if (explicitThreadId) {
|
|
140
154
|
return explicitThreadId;
|
|
141
155
|
}
|
|
142
156
|
if (continueMode) {
|
|
143
|
-
const latest =
|
|
157
|
+
const latest = bestEffort
|
|
158
|
+
? await tryGetLatestThreadId(ctx)
|
|
159
|
+
: await ctx.runtime.getLatestThreadId(ctx.session, ctx.chatId);
|
|
144
160
|
if (latest) {
|
|
145
161
|
return latest;
|
|
146
162
|
}
|
|
147
163
|
}
|
|
148
|
-
|
|
164
|
+
if (!bestEffort) {
|
|
165
|
+
return ctx.runtime.createThread(ctx.session, ctx.chatId, workspace || process.cwd(), 'CLI Session');
|
|
166
|
+
}
|
|
167
|
+
try {
|
|
168
|
+
return await ctx.runtime.createThread(ctx.session, ctx.chatId, workspace || process.cwd(), 'CLI Session');
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
const fallbackThreadId = `local-${Date.now().toString(36)}`;
|
|
172
|
+
process.stderr.write(`Warning: failed to create Pod chat thread; using temporary thread ${fallbackThreadId}: ${formatLinxCliErrorMessage(error)}\n`);
|
|
173
|
+
return fallbackThreadId;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
async function tryGetLatestThreadId(ctx) {
|
|
177
|
+
try {
|
|
178
|
+
return await ctx.runtime.getLatestThreadId(ctx.session, ctx.chatId);
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
process.stderr.write(`Warning: failed to load latest Pod chat thread: ${formatLinxCliErrorMessage(error)}\n`);
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
149
184
|
}
|
|
150
185
|
async function runInteractive(options) {
|
|
151
186
|
const { ctx, initialThreadId, initialModel, initialPrompt } = options;
|
|
@@ -262,39 +297,82 @@ function printConfiguredLinxPackages(packageManager) {
|
|
|
262
297
|
async function runPiCommand(argv) {
|
|
263
298
|
const firstPromptToken = Array.isArray(argv.prompt) ? argv.prompt[0] : undefined;
|
|
264
299
|
// Reject old command aliases explicitly; auto-mode is only selected through flags.
|
|
265
|
-
if (firstPromptToken === 'automode' || firstPromptToken === 'watch') {
|
|
300
|
+
if (firstPromptToken === 'automode' || firstPromptToken === 'watch' || firstPromptToken === 'resume') {
|
|
266
301
|
throw new Error(`Unknown command: ${firstPromptToken}`);
|
|
267
302
|
}
|
|
303
|
+
if (argv.resume) {
|
|
304
|
+
const selectedSession = await selectLinxSession(cwdFromArg(argv.cwd));
|
|
305
|
+
if (!selectedSession) {
|
|
306
|
+
process.stdout.write('No session selected\n');
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
await runPiCommand({
|
|
310
|
+
...argv,
|
|
311
|
+
resume: false,
|
|
312
|
+
session: selectedSession,
|
|
313
|
+
});
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
268
316
|
if (isAutoModeRequest(argv)) {
|
|
269
317
|
await runAutoModeCommand(argv);
|
|
270
318
|
return;
|
|
271
319
|
}
|
|
272
|
-
|
|
320
|
+
if (argv['pi-sync-status']) {
|
|
321
|
+
await runPiSyncStatusCommand();
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
if (argv['pi-sync-retry']) {
|
|
325
|
+
await runPiSyncRetryCommand({
|
|
326
|
+
cwd: argv.cwd || process.cwd(),
|
|
327
|
+
sessionId: argv['pi-sync-retry'],
|
|
328
|
+
});
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
if (argv.backend) {
|
|
332
|
+
await runAutoModeCommand({
|
|
333
|
+
...argv,
|
|
334
|
+
plain: Boolean(argv.plain || argv.print),
|
|
335
|
+
});
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
const cwd = argv.cwd || process.cwd();
|
|
273
339
|
const startupLoginPrompt = await resolveLinxStartupLoginPromptDecision({
|
|
274
|
-
backend,
|
|
340
|
+
backend: 'cloud',
|
|
275
341
|
print: argv.print,
|
|
276
342
|
issuerUrl: resolveAccountBaseUrl(),
|
|
343
|
+
resolveSession: resolveStartupLinxPodDataSession,
|
|
277
344
|
});
|
|
278
|
-
const
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
345
|
+
const sessionManager = await createLinxPiSessionManager({
|
|
346
|
+
cwd,
|
|
347
|
+
agentDir: LINX_AGENT_DIR,
|
|
348
|
+
session: argv.session,
|
|
349
|
+
last: Boolean(argv.continue || argv.last),
|
|
350
|
+
});
|
|
351
|
+
const restoreAutoFromHydration = Boolean(argv.session || argv.continue || argv.last);
|
|
352
|
+
const controlState = await resolvePiStartupControlState({
|
|
353
|
+
requestedAuto: typeof argv.auto === 'boolean' ? argv.auto : undefined,
|
|
354
|
+
hydrateFromPod: !argv.print && !startupLoginPrompt.shouldPrompt,
|
|
355
|
+
restoreAutoFromHydration,
|
|
356
|
+
sessionManager,
|
|
357
|
+
});
|
|
358
|
+
const autoEnabled = controlState.autoEnabled;
|
|
359
|
+
const symphonyEnabled = controlState.symphonyEnabled;
|
|
360
|
+
const adapter = createLinxRuntimeAdapter({
|
|
286
361
|
async createRemoteCompletion(options) {
|
|
287
362
|
const chatApi = await import('./lib/chat-api.js');
|
|
288
363
|
return chatApi.createRemoteCompletionResult(options);
|
|
289
364
|
},
|
|
290
|
-
async listRemoteModels(
|
|
365
|
+
async listRemoteModels(authFetch, runtimeUrl, options) {
|
|
291
366
|
const chatApi = await import('./lib/chat-api.js');
|
|
292
|
-
return chatApi.listRemoteModels(
|
|
367
|
+
return chatApi.listRemoteModels(authFetch, runtimeUrl, options ?? { fallback: false, timeoutMs: 5000 });
|
|
293
368
|
},
|
|
294
369
|
}, {
|
|
295
|
-
cwd
|
|
370
|
+
cwd,
|
|
296
371
|
model: argv.model,
|
|
297
|
-
backend,
|
|
372
|
+
backend: 'cloud',
|
|
373
|
+
autoEnabled,
|
|
374
|
+
symphonyEnabled,
|
|
375
|
+
getPodDataSession: getDefaultPodDataSession,
|
|
298
376
|
port: argv.port,
|
|
299
377
|
providerConfig: {
|
|
300
378
|
baseUrl: String(argv['runtime-url'] ?? 'https://api.undefineds.co/v1'),
|
|
@@ -302,42 +380,14 @@ async function runPiCommand(argv) {
|
|
|
302
380
|
},
|
|
303
381
|
});
|
|
304
382
|
await adapter.start();
|
|
305
|
-
const sessionManager = await createLinxPiSessionManager({
|
|
306
|
-
cwd: adapter.cwd,
|
|
307
|
-
agentDir: LINX_AGENT_DIR,
|
|
308
|
-
session: argv.session,
|
|
309
|
-
last: argv.last,
|
|
310
|
-
});
|
|
311
383
|
const runtime = await adapter.createRuntime({
|
|
312
384
|
cwd: adapter.cwd,
|
|
313
385
|
agentDir: LINX_AGENT_DIR,
|
|
314
386
|
sessionManager,
|
|
315
387
|
});
|
|
316
|
-
const
|
|
317
|
-
cwd: adapter.cwd,
|
|
318
|
-
sessionManager,
|
|
319
|
-
onError(error) {
|
|
320
|
-
if (process.env.LINX_DEBUG === '1') {
|
|
321
|
-
const message = error instanceof Error ? error.stack || error.message : String(error);
|
|
322
|
-
process.stderr.write(`[linx pod mirror] ${message}\n`);
|
|
323
|
-
}
|
|
324
|
-
},
|
|
325
|
-
});
|
|
326
|
-
const unsubscribePodMirror = runtime.session.subscribe((event) => {
|
|
327
|
-
podMirror.handleEvent(event);
|
|
328
|
-
});
|
|
329
|
-
const interactive = bootstrapPiInteractiveMode(runtime);
|
|
330
|
-
const bridge = runtime;
|
|
331
|
-
const loginPromptReason = resolveLinxInteractiveLoginReason({
|
|
332
|
-
startupDecision: startupLoginPrompt,
|
|
333
|
-
runtimePromptOnStart: bridge.linxAuthBridge?.shouldPromptLoginOnStart,
|
|
334
|
-
});
|
|
335
|
-
if (loginPromptReason) {
|
|
336
|
-
interactive.requestLogin?.(loginPromptReason);
|
|
337
|
-
}
|
|
388
|
+
const prompt = (argv.prompt ?? []).join(' ').trim();
|
|
338
389
|
try {
|
|
339
390
|
if (argv.print) {
|
|
340
|
-
const prompt = (argv.prompt ?? []).join(' ').trim();
|
|
341
391
|
const exitCode = await runPrintMode(runtime, {
|
|
342
392
|
mode: 'text',
|
|
343
393
|
initialMessage: prompt || undefined,
|
|
@@ -347,94 +397,192 @@ async function runPiCommand(argv) {
|
|
|
347
397
|
}
|
|
348
398
|
return;
|
|
349
399
|
}
|
|
350
|
-
|
|
400
|
+
const podMirror = new LinxPiPodMirror({
|
|
401
|
+
cwd: adapter.cwd,
|
|
402
|
+
sessionManager,
|
|
403
|
+
autoEnabled,
|
|
404
|
+
symphonyEnabled,
|
|
405
|
+
checkpointStore: createFileSyncCheckpointStore({
|
|
406
|
+
dir: join(LINX_AGENT_DIR, 'sync', 'pi-pod-mirror', sessionManager.getSessionId()),
|
|
407
|
+
}),
|
|
408
|
+
onError(error) {
|
|
409
|
+
if (process.env.LINX_DEBUG === '1') {
|
|
410
|
+
const message = error instanceof Error ? error.stack || error.message : String(error);
|
|
411
|
+
process.stderr.write(`[linx pod mirror] ${message}\n`);
|
|
412
|
+
}
|
|
413
|
+
},
|
|
414
|
+
});
|
|
415
|
+
runtime.__linxPodMirror = podMirror;
|
|
416
|
+
const unsubscribePodMirror = runtime.session.subscribe((event) => {
|
|
417
|
+
podMirror.handleEvent(event);
|
|
418
|
+
});
|
|
419
|
+
const interactive = bootstrapLinxInteractiveMode(runtime, {
|
|
420
|
+
initialMessage: prompt || undefined,
|
|
421
|
+
restoredAuto: autoEnabled && restoreAutoFromHydration,
|
|
422
|
+
onAutoControlChange(enabled) {
|
|
423
|
+
void podMirror.syncAutoControlState(enabled);
|
|
424
|
+
},
|
|
425
|
+
onSymphonyControlChange(enabled) {
|
|
426
|
+
void podMirror.syncSymphonyControlState(enabled);
|
|
427
|
+
},
|
|
428
|
+
});
|
|
429
|
+
const bridge = runtime;
|
|
430
|
+
const loginPromptReason = resolveLinxInteractiveLoginReason({
|
|
431
|
+
startupDecision: startupLoginPrompt,
|
|
432
|
+
runtimePromptOnStart: bridge.linxAuthBridge?.shouldPromptLoginOnStart,
|
|
433
|
+
});
|
|
434
|
+
if (loginPromptReason) {
|
|
435
|
+
interactive.requestLogin?.(loginPromptReason);
|
|
436
|
+
}
|
|
437
|
+
try {
|
|
438
|
+
await interactive.run();
|
|
439
|
+
}
|
|
440
|
+
finally {
|
|
441
|
+
unsubscribePodMirror();
|
|
442
|
+
await podMirror.close().catch(() => undefined);
|
|
443
|
+
interactive.stop();
|
|
444
|
+
}
|
|
351
445
|
}
|
|
352
446
|
finally {
|
|
353
|
-
unsubscribePodMirror();
|
|
354
|
-
await podMirror.close().catch(() => undefined);
|
|
355
|
-
interactive.stop();
|
|
356
447
|
await adapter.close();
|
|
448
|
+
clearDefaultPodDataSession();
|
|
357
449
|
}
|
|
358
450
|
}
|
|
359
|
-
async function
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
if (piSessions.length === 0 && autoModeSessions.length === 0) {
|
|
366
|
-
process.stdout.write('No LinX sessions found.\n');
|
|
367
|
-
return;
|
|
368
|
-
}
|
|
369
|
-
if (piSessions.length > 0) {
|
|
370
|
-
process.stdout.write('LinX sessions:\n');
|
|
371
|
-
process.stdout.write(`${piSessions.map((item) => ` ${formatLinxPiSessionSummary(item)}`).join('\n')}\n`);
|
|
372
|
-
}
|
|
373
|
-
if (autoModeSessions.length > 0) {
|
|
374
|
-
process.stdout.write('Auto-mode sessions:\n');
|
|
375
|
-
process.stdout.write(`${autoModeSessions.map((item) => ` ${formatAutoModeSessionSummary(item)}`).join('\n')}\n`);
|
|
376
|
-
}
|
|
377
|
-
return;
|
|
451
|
+
async function resolvePiStartupControlState(options) {
|
|
452
|
+
if (!options.hydrateFromPod) {
|
|
453
|
+
return {
|
|
454
|
+
autoEnabled: options.requestedAuto === true,
|
|
455
|
+
symphonyEnabled: false,
|
|
456
|
+
};
|
|
378
457
|
}
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
const exitCode = await resumeAutoModeSession(latestAutoMode, {
|
|
386
|
-
cwd,
|
|
387
|
-
model: argv.model,
|
|
388
|
-
});
|
|
389
|
-
if (exitCode !== 0) {
|
|
390
|
-
process.exitCode = exitCode;
|
|
391
|
-
}
|
|
392
|
-
return;
|
|
393
|
-
}
|
|
458
|
+
const session = await createLinxPodDataSession().catch(() => null);
|
|
459
|
+
if (!session) {
|
|
460
|
+
return {
|
|
461
|
+
autoEnabled: options.requestedAuto === true,
|
|
462
|
+
symphonyEnabled: false,
|
|
463
|
+
};
|
|
394
464
|
}
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
cwd,
|
|
412
|
-
model: argv.model,
|
|
413
|
-
});
|
|
414
|
-
if (exitCode !== 0) {
|
|
415
|
-
process.exitCode = exitCode;
|
|
465
|
+
try {
|
|
466
|
+
const db = drizzle(session.solidSession, {
|
|
467
|
+
logger: false,
|
|
468
|
+
disableInteropDiscovery: true,
|
|
469
|
+
podUrl: session.podUrl,
|
|
470
|
+
resourcePreparation: 'off',
|
|
471
|
+
schema: solidResources,
|
|
472
|
+
});
|
|
473
|
+
const hydration = await hydrateLinxPiControlState({
|
|
474
|
+
db,
|
|
475
|
+
sessionId: options.sessionManager.getSessionId(),
|
|
476
|
+
createdAt: getPiSessionCreatedAt(options.sessionManager),
|
|
477
|
+
onError(error) {
|
|
478
|
+
if (process.env.LINX_DEBUG === '1') {
|
|
479
|
+
const message = error instanceof Error ? error.stack || error.message : String(error);
|
|
480
|
+
process.stderr.write(`[linx control state] ${message}\n`);
|
|
416
481
|
}
|
|
482
|
+
},
|
|
483
|
+
});
|
|
484
|
+
return {
|
|
485
|
+
...deriveLinxPiStartupControlState({
|
|
486
|
+
requestedAuto: options.requestedAuto,
|
|
487
|
+
hydration,
|
|
488
|
+
restoreAutoFromHydration: options.restoreAutoFromHydration,
|
|
489
|
+
}),
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
finally {
|
|
493
|
+
await session.close().catch(() => undefined);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
function getPiSessionCreatedAt(sessionManager) {
|
|
497
|
+
const entryDate = sessionManager.getEntries()
|
|
498
|
+
.map((entry) => toDate(entry.timestamp))
|
|
499
|
+
.find((date) => date instanceof Date);
|
|
500
|
+
return entryDate ?? parseTimestampFromUuidLikeId(sessionManager.getSessionId()) ?? new Date();
|
|
501
|
+
}
|
|
502
|
+
function parseTimestampFromUuidLikeId(id) {
|
|
503
|
+
const prefix = id.replace(/-/g, '').slice(0, 12);
|
|
504
|
+
if (!/^[\da-f]{12}$/i.test(prefix)) {
|
|
505
|
+
return null;
|
|
506
|
+
}
|
|
507
|
+
const millis = Number.parseInt(prefix, 16);
|
|
508
|
+
if (!Number.isFinite(millis) || millis <= 0) {
|
|
509
|
+
return null;
|
|
510
|
+
}
|
|
511
|
+
const date = new Date(millis);
|
|
512
|
+
return Number.isNaN(date.getTime()) ? null : date;
|
|
513
|
+
}
|
|
514
|
+
function toDate(value) {
|
|
515
|
+
if (value instanceof Date && !Number.isNaN(value.getTime())) {
|
|
516
|
+
return value;
|
|
517
|
+
}
|
|
518
|
+
if (typeof value === 'number' || typeof value === 'string') {
|
|
519
|
+
const date = new Date(value);
|
|
520
|
+
return Number.isNaN(date.getTime()) ? null : date;
|
|
521
|
+
}
|
|
522
|
+
return null;
|
|
523
|
+
}
|
|
524
|
+
function cwdFromArg(cwd) {
|
|
525
|
+
return typeof cwd === 'string' && cwd.trim() ? cwd : process.cwd();
|
|
526
|
+
}
|
|
527
|
+
async function selectLinxSession(cwd) {
|
|
528
|
+
return new Promise((resolve) => {
|
|
529
|
+
const ui = new TUI(new ProcessTerminal());
|
|
530
|
+
let resolved = false;
|
|
531
|
+
const finish = (sessionPath) => {
|
|
532
|
+
if (resolved) {
|
|
417
533
|
return;
|
|
418
534
|
}
|
|
419
|
-
|
|
535
|
+
resolved = true;
|
|
536
|
+
ui.stop();
|
|
537
|
+
resolve(sessionPath);
|
|
538
|
+
};
|
|
539
|
+
const loadSessions = () => listLinxPiSessions(cwd, LINX_AGENT_DIR, { podSessionSource: null });
|
|
540
|
+
const selector = new SessionSelectorComponent(loadSessions, loadSessions, (sessionPath) => finish(sessionPath), () => finish(null), () => {
|
|
541
|
+
ui.stop();
|
|
542
|
+
process.exit(0);
|
|
543
|
+
}, () => ui.requestRender(), { showRenameHint: false });
|
|
544
|
+
ui.addChild(selector);
|
|
545
|
+
ui.setFocus(selector.getSessionList());
|
|
546
|
+
ui.start();
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
async function runPiSyncStatusCommand() {
|
|
550
|
+
const sessions = await listPendingPiPodMirrorSync(LINX_AGENT_DIR);
|
|
551
|
+
if (sessions.length === 0) {
|
|
552
|
+
process.stdout.write('No pending LinX Pod sync sessions.\n');
|
|
553
|
+
return;
|
|
420
554
|
}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
session
|
|
426
|
-
|
|
555
|
+
process.stdout.write(`${sessions.map((session) => {
|
|
556
|
+
const failed = session.checkpoints.filter((checkpoint) => checkpoint.status === 'failed').length;
|
|
557
|
+
const partial = session.checkpoints.filter((checkpoint) => checkpoint.status === 'partial').length;
|
|
558
|
+
const latest = session.checkpoints.at(-1)?.completedAt ?? 'unknown';
|
|
559
|
+
return `${session.sessionId} · failed=${failed} partial=${partial} latest=${latest}`;
|
|
560
|
+
}).join('\n')}\n`);
|
|
561
|
+
}
|
|
562
|
+
async function runPiSyncRetryCommand(options) {
|
|
563
|
+
const result = await retryPendingPiPodMirrorSync({
|
|
564
|
+
cwd: options.cwd,
|
|
565
|
+
agentDir: LINX_AGENT_DIR,
|
|
566
|
+
sessionId: options.sessionId,
|
|
427
567
|
});
|
|
568
|
+
if (!result.attempted) {
|
|
569
|
+
process.stdout.write(`LinX Pod sync skipped: ${options.sessionId}\n`);
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
const status = result.results.map((item) => item.status).join(', ') || 'none';
|
|
573
|
+
process.stdout.write(status === 'none'
|
|
574
|
+
? `LinX Pod sync has no replayable local projections: ${options.sessionId}\n`
|
|
575
|
+
: `Retried LinX Pod sync: ${options.sessionId} (${status})\n`);
|
|
428
576
|
}
|
|
429
577
|
function buildPiCommand(command) {
|
|
430
578
|
const configured = buildAutoModeOptions(command)
|
|
431
579
|
.option('cwd', {
|
|
432
580
|
type: 'string',
|
|
433
|
-
describe: 'Workspace path for the
|
|
581
|
+
describe: 'Workspace path for the LinX session',
|
|
434
582
|
})
|
|
435
583
|
.option('model', {
|
|
436
584
|
type: 'string',
|
|
437
|
-
describe: 'Model id to expose through the
|
|
585
|
+
describe: 'Model id to expose through the LinX runtime adapter; defaults to the last LinX selection',
|
|
438
586
|
})
|
|
439
587
|
.option('runtime-url', {
|
|
440
588
|
type: 'string',
|
|
@@ -448,12 +596,32 @@ function buildPiCommand(command) {
|
|
|
448
596
|
})
|
|
449
597
|
.option('session', {
|
|
450
598
|
type: 'string',
|
|
451
|
-
describe: 'Resume a specific LinX
|
|
599
|
+
describe: 'Resume a specific LinX session id or JSONL file',
|
|
600
|
+
})
|
|
601
|
+
.option('continue', {
|
|
602
|
+
alias: 'c',
|
|
603
|
+
type: 'boolean',
|
|
604
|
+
default: false,
|
|
605
|
+
describe: 'Continue previous LinX session',
|
|
606
|
+
})
|
|
607
|
+
.option('resume', {
|
|
608
|
+
alias: 'r',
|
|
609
|
+
type: 'boolean',
|
|
610
|
+
default: false,
|
|
611
|
+
describe: 'Select a LinX session to resume',
|
|
452
612
|
})
|
|
453
613
|
.option('last', {
|
|
454
614
|
type: 'boolean',
|
|
455
615
|
default: false,
|
|
456
|
-
|
|
616
|
+
hidden: true,
|
|
617
|
+
})
|
|
618
|
+
.option('pi-sync-status', {
|
|
619
|
+
type: 'boolean',
|
|
620
|
+
hidden: true,
|
|
621
|
+
})
|
|
622
|
+
.option('pi-sync-retry', {
|
|
623
|
+
type: 'string',
|
|
624
|
+
hidden: true,
|
|
457
625
|
})
|
|
458
626
|
.positional('prompt', {
|
|
459
627
|
array: true,
|
|
@@ -464,7 +632,7 @@ function buildPiCommand(command) {
|
|
|
464
632
|
}
|
|
465
633
|
const defaultPiCommand = {
|
|
466
634
|
command: '$0 [prompt..]',
|
|
467
|
-
describe: 'Run LinX
|
|
635
|
+
describe: 'Run LinX with the selected runtime backend',
|
|
468
636
|
builder: buildPiCommand,
|
|
469
637
|
handler: runPiCommand,
|
|
470
638
|
};
|
|
@@ -489,6 +657,23 @@ const execCommand = {
|
|
|
489
657
|
await runPiCommand({ ...argv, print: true });
|
|
490
658
|
},
|
|
491
659
|
};
|
|
660
|
+
const retiredSymphonyCommand = {
|
|
661
|
+
command: 'symphony [args..]',
|
|
662
|
+
describe: false,
|
|
663
|
+
builder(command) {
|
|
664
|
+
return command
|
|
665
|
+
.help(false)
|
|
666
|
+
.version(false)
|
|
667
|
+
.positional('args', {
|
|
668
|
+
array: true,
|
|
669
|
+
type: 'string',
|
|
670
|
+
describe: 'Retired Symphony CLI arguments',
|
|
671
|
+
});
|
|
672
|
+
},
|
|
673
|
+
handler() {
|
|
674
|
+
throw new Error('`linx symphony` is not a product command. Enter the TUI, run `/symphony on`, then send the objective as normal chat to Secretary.');
|
|
675
|
+
},
|
|
676
|
+
};
|
|
492
677
|
const cli = yargs(hideBin(process.argv))
|
|
493
678
|
.scriptName('linx')
|
|
494
679
|
.version(readPackageVersion())
|
|
@@ -499,7 +684,7 @@ const cli = yargs(hideBin(process.argv))
|
|
|
499
684
|
.command(logoutCommand)
|
|
500
685
|
.command(whoamiCommand)
|
|
501
686
|
.command(aiCommand)
|
|
502
|
-
.command(
|
|
687
|
+
.command(retiredSymphonyCommand)
|
|
503
688
|
.command('install [source]', 'Install a LinX package or extension', (command) => command
|
|
504
689
|
.positional('source', { type: 'string', describe: 'Package source to install' })
|
|
505
690
|
.option('local', { alias: 'l', type: 'boolean', default: false, describe: 'Install project-locally (.pi/settings.json)' }), async (argv) => {
|
|
@@ -538,6 +723,7 @@ const cli = yargs(hideBin(process.argv))
|
|
|
538
723
|
continueMode: argv.continue,
|
|
539
724
|
explicitThreadId: argv.thread,
|
|
540
725
|
workspace: argv.workspace,
|
|
726
|
+
bestEffort: Boolean(argv.prompt?.join(' ').trim()),
|
|
541
727
|
});
|
|
542
728
|
const prompt = argv.prompt?.join(' ').trim() || undefined;
|
|
543
729
|
if (prompt) {
|
|
@@ -552,7 +738,7 @@ const cli = yargs(hideBin(process.argv))
|
|
|
552
738
|
const ctx = await resolveRuntimeAuthContext(argv.url);
|
|
553
739
|
let models;
|
|
554
740
|
try {
|
|
555
|
-
models = await ctx.runtime.listRemoteModels(ctx.
|
|
741
|
+
models = await ctx.runtime.listRemoteModels(ctx.authFetch, ctx.runtimeUrl, { fallback: false });
|
|
556
742
|
}
|
|
557
743
|
catch (error) {
|
|
558
744
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -568,25 +754,11 @@ const cli = yargs(hideBin(process.argv))
|
|
|
568
754
|
}
|
|
569
755
|
}
|
|
570
756
|
await ctx.podSession.close();
|
|
571
|
-
})
|
|
572
|
-
.command('resume [session]', 'Resume a previous LinX or auto-mode session', (command) => command
|
|
573
|
-
.positional('session', { type: 'string', describe: 'Session id/prefix or JSONL file to resume' })
|
|
574
|
-
.option('last', { type: 'boolean', default: false, describe: 'Resume the most recent LinX or auto-mode session' })
|
|
575
|
-
.option('cwd', { type: 'string', describe: 'Workspace path for the resumed session' })
|
|
576
|
-
.option('model', { type: 'string', describe: 'Model id to expose through the Pi runtime adapter' })
|
|
577
|
-
.option('runtime-url', { type: 'string', default: 'https://api.undefineds.co/v1', describe: 'Cloud runtime API base URL' }), async (argv) => {
|
|
578
|
-
await runResumeCommand({
|
|
579
|
-
cwd: typeof argv.cwd === 'string' ? argv.cwd : undefined,
|
|
580
|
-
model: typeof argv.model === 'string' ? argv.model : undefined,
|
|
581
|
-
'runtime-url': typeof argv['runtime-url'] === 'string' ? argv['runtime-url'] : undefined,
|
|
582
|
-
session: typeof argv.session === 'string' ? argv.session : undefined,
|
|
583
|
-
last: Boolean(argv.last),
|
|
584
|
-
});
|
|
585
757
|
})
|
|
586
758
|
.command('fork [thread]', 'Fork a previous interactive session', (command) => command
|
|
587
759
|
.positional('thread', { type: 'string', describe: 'Thread ID to fork' })
|
|
588
760
|
.option('last', { type: 'boolean', default: false, describe: 'Fork the most recent thread' }), () => {
|
|
589
|
-
throw new Error('Fork is not implemented yet for LinX Pod-backed
|
|
761
|
+
throw new Error('Fork is not implemented yet for LinX Pod-backed sessions.');
|
|
590
762
|
})
|
|
591
763
|
.command(hiddenPiAliasCommand)
|
|
592
764
|
.command(hiddenPiFrontendAliasCommand)
|
|
@@ -628,18 +800,18 @@ const cli = yargs(hideBin(process.argv))
|
|
|
628
800
|
.help()
|
|
629
801
|
.fail((message, error, yargsInstance) => {
|
|
630
802
|
if (error) {
|
|
631
|
-
console.error(
|
|
803
|
+
console.error(formatLinxCliErrorMessage(error));
|
|
632
804
|
process.exit(1);
|
|
633
805
|
}
|
|
634
806
|
if (message) {
|
|
635
|
-
console.error(message);
|
|
807
|
+
console.error(formatLinxCliErrorMessage(message));
|
|
636
808
|
process.exit(1);
|
|
637
809
|
}
|
|
638
810
|
yargsInstance.showHelp();
|
|
639
811
|
process.exit(1);
|
|
640
812
|
});
|
|
641
813
|
process.on('unhandledRejection', (error) => {
|
|
642
|
-
console.error(
|
|
814
|
+
console.error(formatLinxCliErrorMessage(error));
|
|
643
815
|
process.exit(1);
|
|
644
816
|
});
|
|
645
817
|
cli.parse();
|