@undefineds.co/linx 0.3.5 → 0.3.8
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 +336 -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, initTheme, 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,194 @@ 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
|
+
const settingsManager = SettingsManager.create(cwd, LINX_AGENT_DIR);
|
|
529
|
+
initTheme(settingsManager.getTheme());
|
|
530
|
+
return new Promise((resolve) => {
|
|
531
|
+
const ui = new TUI(new ProcessTerminal());
|
|
532
|
+
let resolved = false;
|
|
533
|
+
const finish = (sessionPath) => {
|
|
534
|
+
if (resolved) {
|
|
417
535
|
return;
|
|
418
536
|
}
|
|
419
|
-
|
|
537
|
+
resolved = true;
|
|
538
|
+
ui.stop();
|
|
539
|
+
resolve(sessionPath);
|
|
540
|
+
};
|
|
541
|
+
const loadSessions = () => listLinxPiSessions(cwd, LINX_AGENT_DIR, { podSessionSource: null });
|
|
542
|
+
const selector = new SessionSelectorComponent(loadSessions, loadSessions, (sessionPath) => finish(sessionPath), () => finish(null), () => {
|
|
543
|
+
ui.stop();
|
|
544
|
+
process.exit(0);
|
|
545
|
+
}, () => ui.requestRender(), { showRenameHint: false });
|
|
546
|
+
ui.addChild(selector);
|
|
547
|
+
ui.setFocus(selector.getSessionList());
|
|
548
|
+
ui.start();
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
async function runPiSyncStatusCommand() {
|
|
552
|
+
const sessions = await listPendingPiPodMirrorSync(LINX_AGENT_DIR);
|
|
553
|
+
if (sessions.length === 0) {
|
|
554
|
+
process.stdout.write('No pending LinX Pod sync sessions.\n');
|
|
555
|
+
return;
|
|
420
556
|
}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
session
|
|
426
|
-
|
|
557
|
+
process.stdout.write(`${sessions.map((session) => {
|
|
558
|
+
const failed = session.checkpoints.filter((checkpoint) => checkpoint.status === 'failed').length;
|
|
559
|
+
const partial = session.checkpoints.filter((checkpoint) => checkpoint.status === 'partial').length;
|
|
560
|
+
const latest = session.checkpoints.at(-1)?.completedAt ?? 'unknown';
|
|
561
|
+
return `${session.sessionId} · failed=${failed} partial=${partial} latest=${latest}`;
|
|
562
|
+
}).join('\n')}\n`);
|
|
563
|
+
}
|
|
564
|
+
async function runPiSyncRetryCommand(options) {
|
|
565
|
+
const result = await retryPendingPiPodMirrorSync({
|
|
566
|
+
cwd: options.cwd,
|
|
567
|
+
agentDir: LINX_AGENT_DIR,
|
|
568
|
+
sessionId: options.sessionId,
|
|
427
569
|
});
|
|
570
|
+
if (!result.attempted) {
|
|
571
|
+
process.stdout.write(`LinX Pod sync skipped: ${options.sessionId}\n`);
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
574
|
+
const status = result.results.map((item) => item.status).join(', ') || 'none';
|
|
575
|
+
process.stdout.write(status === 'none'
|
|
576
|
+
? `LinX Pod sync has no replayable local projections: ${options.sessionId}\n`
|
|
577
|
+
: `Retried LinX Pod sync: ${options.sessionId} (${status})\n`);
|
|
428
578
|
}
|
|
429
579
|
function buildPiCommand(command) {
|
|
430
580
|
const configured = buildAutoModeOptions(command)
|
|
431
581
|
.option('cwd', {
|
|
432
582
|
type: 'string',
|
|
433
|
-
describe: 'Workspace path for the
|
|
583
|
+
describe: 'Workspace path for the LinX session',
|
|
434
584
|
})
|
|
435
585
|
.option('model', {
|
|
436
586
|
type: 'string',
|
|
437
|
-
describe: 'Model id to expose through the
|
|
587
|
+
describe: 'Model id to expose through the LinX runtime adapter; defaults to the last LinX selection',
|
|
438
588
|
})
|
|
439
589
|
.option('runtime-url', {
|
|
440
590
|
type: 'string',
|
|
@@ -448,12 +598,32 @@ function buildPiCommand(command) {
|
|
|
448
598
|
})
|
|
449
599
|
.option('session', {
|
|
450
600
|
type: 'string',
|
|
451
|
-
describe: 'Resume a specific LinX
|
|
601
|
+
describe: 'Resume a specific LinX session id or JSONL file',
|
|
602
|
+
})
|
|
603
|
+
.option('continue', {
|
|
604
|
+
alias: 'c',
|
|
605
|
+
type: 'boolean',
|
|
606
|
+
default: false,
|
|
607
|
+
describe: 'Continue previous LinX session',
|
|
608
|
+
})
|
|
609
|
+
.option('resume', {
|
|
610
|
+
alias: 'r',
|
|
611
|
+
type: 'boolean',
|
|
612
|
+
default: false,
|
|
613
|
+
describe: 'Select a LinX session to resume',
|
|
452
614
|
})
|
|
453
615
|
.option('last', {
|
|
454
616
|
type: 'boolean',
|
|
455
617
|
default: false,
|
|
456
|
-
|
|
618
|
+
hidden: true,
|
|
619
|
+
})
|
|
620
|
+
.option('pi-sync-status', {
|
|
621
|
+
type: 'boolean',
|
|
622
|
+
hidden: true,
|
|
623
|
+
})
|
|
624
|
+
.option('pi-sync-retry', {
|
|
625
|
+
type: 'string',
|
|
626
|
+
hidden: true,
|
|
457
627
|
})
|
|
458
628
|
.positional('prompt', {
|
|
459
629
|
array: true,
|
|
@@ -464,7 +634,7 @@ function buildPiCommand(command) {
|
|
|
464
634
|
}
|
|
465
635
|
const defaultPiCommand = {
|
|
466
636
|
command: '$0 [prompt..]',
|
|
467
|
-
describe: 'Run LinX
|
|
637
|
+
describe: 'Run LinX with the selected runtime backend',
|
|
468
638
|
builder: buildPiCommand,
|
|
469
639
|
handler: runPiCommand,
|
|
470
640
|
};
|
|
@@ -489,6 +659,23 @@ const execCommand = {
|
|
|
489
659
|
await runPiCommand({ ...argv, print: true });
|
|
490
660
|
},
|
|
491
661
|
};
|
|
662
|
+
const retiredSymphonyCommand = {
|
|
663
|
+
command: 'symphony [args..]',
|
|
664
|
+
describe: false,
|
|
665
|
+
builder(command) {
|
|
666
|
+
return command
|
|
667
|
+
.help(false)
|
|
668
|
+
.version(false)
|
|
669
|
+
.positional('args', {
|
|
670
|
+
array: true,
|
|
671
|
+
type: 'string',
|
|
672
|
+
describe: 'Retired Symphony CLI arguments',
|
|
673
|
+
});
|
|
674
|
+
},
|
|
675
|
+
handler() {
|
|
676
|
+
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.');
|
|
677
|
+
},
|
|
678
|
+
};
|
|
492
679
|
const cli = yargs(hideBin(process.argv))
|
|
493
680
|
.scriptName('linx')
|
|
494
681
|
.version(readPackageVersion())
|
|
@@ -499,7 +686,7 @@ const cli = yargs(hideBin(process.argv))
|
|
|
499
686
|
.command(logoutCommand)
|
|
500
687
|
.command(whoamiCommand)
|
|
501
688
|
.command(aiCommand)
|
|
502
|
-
.command(
|
|
689
|
+
.command(retiredSymphonyCommand)
|
|
503
690
|
.command('install [source]', 'Install a LinX package or extension', (command) => command
|
|
504
691
|
.positional('source', { type: 'string', describe: 'Package source to install' })
|
|
505
692
|
.option('local', { alias: 'l', type: 'boolean', default: false, describe: 'Install project-locally (.pi/settings.json)' }), async (argv) => {
|
|
@@ -538,6 +725,7 @@ const cli = yargs(hideBin(process.argv))
|
|
|
538
725
|
continueMode: argv.continue,
|
|
539
726
|
explicitThreadId: argv.thread,
|
|
540
727
|
workspace: argv.workspace,
|
|
728
|
+
bestEffort: Boolean(argv.prompt?.join(' ').trim()),
|
|
541
729
|
});
|
|
542
730
|
const prompt = argv.prompt?.join(' ').trim() || undefined;
|
|
543
731
|
if (prompt) {
|
|
@@ -552,7 +740,7 @@ const cli = yargs(hideBin(process.argv))
|
|
|
552
740
|
const ctx = await resolveRuntimeAuthContext(argv.url);
|
|
553
741
|
let models;
|
|
554
742
|
try {
|
|
555
|
-
models = await ctx.runtime.listRemoteModels(ctx.
|
|
743
|
+
models = await ctx.runtime.listRemoteModels(ctx.authFetch, ctx.runtimeUrl, { fallback: false });
|
|
556
744
|
}
|
|
557
745
|
catch (error) {
|
|
558
746
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -568,25 +756,11 @@ const cli = yargs(hideBin(process.argv))
|
|
|
568
756
|
}
|
|
569
757
|
}
|
|
570
758
|
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
759
|
})
|
|
586
760
|
.command('fork [thread]', 'Fork a previous interactive session', (command) => command
|
|
587
761
|
.positional('thread', { type: 'string', describe: 'Thread ID to fork' })
|
|
588
762
|
.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
|
|
763
|
+
throw new Error('Fork is not implemented yet for LinX Pod-backed sessions.');
|
|
590
764
|
})
|
|
591
765
|
.command(hiddenPiAliasCommand)
|
|
592
766
|
.command(hiddenPiFrontendAliasCommand)
|
|
@@ -628,18 +802,18 @@ const cli = yargs(hideBin(process.argv))
|
|
|
628
802
|
.help()
|
|
629
803
|
.fail((message, error, yargsInstance) => {
|
|
630
804
|
if (error) {
|
|
631
|
-
console.error(
|
|
805
|
+
console.error(formatLinxCliErrorMessage(error));
|
|
632
806
|
process.exit(1);
|
|
633
807
|
}
|
|
634
808
|
if (message) {
|
|
635
|
-
console.error(message);
|
|
809
|
+
console.error(formatLinxCliErrorMessage(message));
|
|
636
810
|
process.exit(1);
|
|
637
811
|
}
|
|
638
812
|
yargsInstance.showHelp();
|
|
639
813
|
process.exit(1);
|
|
640
814
|
});
|
|
641
815
|
process.on('unhandledRejection', (error) => {
|
|
642
|
-
console.error(
|
|
816
|
+
console.error(formatLinxCliErrorMessage(error));
|
|
643
817
|
process.exit(1);
|
|
644
818
|
});
|
|
645
819
|
cli.parse();
|