larkin 0.4.29 → 0.5.1
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/CHANGELOG.md +15 -0
- package/README.md +5 -9
- package/artifacts/release/THIRD_PARTY_NOTICES.txt +751 -4425
- package/dist/app/agent-cli.mjs +14 -2
- package/dist/app/agent-config.mjs +26 -86
- package/dist/app/binary-entry.mjs +0 -20
- package/dist/app/cli.mjs +6 -22
- package/dist/app/internal-command.cjs +0 -2
- package/dist/app/internal-command.mjs +0 -2
- package/dist/app/runtime-model-directory.mjs +2 -16
- package/dist/app/runtime-process.mjs +0 -1
- package/dist/app/setup.mjs +52 -57
- package/dist/dashboard/dashboard-config-controller.mjs +43 -109
- package/dist/dashboard/dashboard-view-model.mjs +4 -7
- package/dist/dashboard/web/assets/dashboard.css +1 -1
- package/dist/dashboard/web/assets/dashboard.js +15 -15
- package/dist/feishu/host-shell.cjs +1 -2
- package/dist/feishu/host-shell.mjs +1 -2
- package/dist/platform/config.cjs +168 -133
- package/dist/platform/config.mjs +168 -133
- package/dist/runtime/pi-artifact-provenance.mjs +3 -3
- package/dist/runtime/pi-bash-timeout-extension.mjs +4 -5
- package/dist/runtime/pi-compaction-recovery.cjs +45 -15
- package/dist/runtime/pi-compaction-recovery.mjs +43 -14
- package/dist/runtime/pi-extension-api.mjs +1 -0
- package/dist/runtime/pi-model-catalog.cjs +7 -8
- package/dist/runtime/pi-model-catalog.mjs +7 -8
- package/dist/runtime/pi-subagent-injection.mjs +17 -4
- package/dist/runtime/runtime-adapters.mjs +26 -43
- package/dist/runtime/runtime-host.cjs +21 -43
- package/dist/runtime/runtime-host.mjs +22 -44
- package/dist/runtime/runtime-model-catalog.cjs +1 -1
- package/dist/runtime/runtime-model-catalog.mjs +1 -1
- package/dist/runtime/runtime-readiness.cjs +62 -98
- package/dist/runtime/runtime-readiness.mjs +60 -97
- package/dist/runtime/user-runtime.cjs +7 -24
- package/dist/runtime/user-runtime.mjs +7 -23
- package/dist/setup/bot-register.mjs +15 -123
- package/dist/setup/setup-agent-choice.mjs +48 -74
- package/dist/setup/setup-bind.mjs +51 -151
- package/dist/setup/setup-binding.mjs +6 -9
- package/package.json +3 -2
- package/dist/app/pi-auth-cli.mjs +0 -277
- package/dist/platform/process-boundary-trace.cjs +0 -108
- package/dist/runtime/builtin-pi-assets.cjs +0 -117
- package/dist/runtime/builtin-pi-assets.mjs +0 -105
- package/dist/runtime/pi-artifact-provenance.cjs +0 -147
- package/dist/runtime/pi-distribution-label.cjs +0 -6
- package/dist/runtime/pi-distribution-label.mjs +0 -3
- package/dist/runtime/pi-inline-extensions.mjs +0 -78
- package/dist/runtime/pi-official-auth.cjs +0 -594
- package/dist/runtime/pi-official-auth.mjs +0 -544
- package/dist/runtime/pi-profile-migration.cjs +0 -764
- package/dist/runtime/pi-profile-migration.mjs +0 -719
- package/dist/runtime/pi-provider-config.cjs +0 -354
- package/dist/runtime/pi-provider-config.mjs +0 -334
- package/dist/runtime/pi-provider-login.mjs +0 -240
|
@@ -6,8 +6,7 @@ import { auditReminderDelivery } from "../agent/reminder-delivery-audit.mjs";
|
|
|
6
6
|
import { isCanonicalInboxTarget, targetKeyOfInboxEnvelope } from "../agent/inbox-projection.mjs";
|
|
7
7
|
import { SpanKind } from "@opentelemetry/api";
|
|
8
8
|
import { buildStrictProviderErrorInput, classifyStrictProviderError } from "./provider-error-classifier.mjs";
|
|
9
|
-
import { authFailureAppliesTo, classifyPiMissingCredentialRejection, classifyRuntimePrerequisite, configuredProviderId,
|
|
10
|
-
import { officialPiHasStoredProvider } from "./pi-official-auth.mjs";
|
|
9
|
+
import { authFailureAppliesTo, classifyPiMissingCredentialRejection, classifyRuntimePrerequisite, configuredProviderId, missingProviderCredentialReadiness, parsePersistedAuthFailure, providerAuthenticationFailureReadiness, readinessForPersistedAuthFailure, safeProviderId, RuntimePrerequisiteError, } from "./runtime-readiness.mjs";
|
|
11
10
|
import { resolveOfficialLarkCli } from "../app/official-lark-cli.mjs";
|
|
12
11
|
import { assertAgentWorkspaceBound, managedLarkCliEnv } from "../app/agent-lark-cli-workspace.mjs";
|
|
13
12
|
import { isPiNativeCompactionRequired, PiCompactionBreaker, PiCompactionRecoveryMachine, } from "./pi-compaction-recovery.mjs";
|
|
@@ -94,37 +93,23 @@ function persistPreviousSession(agent, previous) {
|
|
|
94
93
|
// In-memory ref still holds for this process; restart will miss it only if this write failed.
|
|
95
94
|
}
|
|
96
95
|
}
|
|
97
|
-
function isBuiltinPiAgent(agent) {
|
|
98
|
-
return agent.adapter.id === "pi"
|
|
99
|
-
&& (isBuiltinPiDistribution(agent.config.piDistribution) || agent.config.runtime === "builtin-pi");
|
|
100
|
-
}
|
|
101
96
|
function authFailureScopeOf(agent) {
|
|
102
97
|
return {
|
|
103
98
|
runtime: agent.config.runtime,
|
|
104
99
|
model: agent.config.model,
|
|
105
|
-
piDistribution: agent.config.piDistribution,
|
|
106
100
|
adapterId: agent.adapter.id,
|
|
107
101
|
};
|
|
108
102
|
}
|
|
109
103
|
function currentAuthFailure(agent) {
|
|
110
104
|
if (!agent.authFailureActive)
|
|
111
105
|
return null;
|
|
112
|
-
const kind = agent.authFailureKind
|
|
113
|
-
?? (agent.authFailureProvider ? "missing-provider" : "generic");
|
|
114
|
-
if (kind === "missing-provider") {
|
|
115
|
-
if (!agent.authFailureProvider)
|
|
116
|
-
return null;
|
|
117
|
-
return { kind: "missing-provider", runtime: "pi", piDistribution: "builtin", provider: agent.authFailureProvider };
|
|
118
|
-
}
|
|
119
106
|
const runtime = agent.adapter.id === "codex" || agent.adapter.id === "claude" || agent.adapter.id === "pi"
|
|
120
107
|
? agent.adapter.id : null;
|
|
121
108
|
if (!runtime)
|
|
122
109
|
return null;
|
|
123
110
|
return {
|
|
124
|
-
kind: "generic",
|
|
111
|
+
kind: agent.authFailureKind === "missing-provider" ? "missing-provider" : "generic",
|
|
125
112
|
runtime,
|
|
126
|
-
...(runtime === "pi" && (agent.config.piDistribution === "builtin" || agent.config.piDistribution === "external")
|
|
127
|
-
? { piDistribution: agent.config.piDistribution } : {}),
|
|
128
113
|
provider: agent.authFailureProvider,
|
|
129
114
|
};
|
|
130
115
|
}
|
|
@@ -335,7 +320,6 @@ export function createRuntimeHost(options) {
|
|
|
335
320
|
} : {}),
|
|
336
321
|
LARKIN_CONFIG_DIR: process.env.LARKIN_CONFIG_DIR,
|
|
337
322
|
LARKIN_HOME: process.env.LARKIN_HOME,
|
|
338
|
-
...(config.piDistribution ? { LARKIN_PI_DISTRIBUTION: config.piDistribution } : {}),
|
|
339
323
|
LARKIN_STATE_DIR: effectivePiStateDir(config),
|
|
340
324
|
...(process.env.HOME ? { HOME: process.env.HOME } : {}),
|
|
341
325
|
...(process.env.SHELL ? { SHELL: process.env.SHELL } : {}),
|
|
@@ -597,10 +581,6 @@ export function createRuntimeHost(options) {
|
|
|
597
581
|
messageId: record.messageId, status: "consumed" });
|
|
598
582
|
}
|
|
599
583
|
};
|
|
600
|
-
const ownedConfigDir = () => {
|
|
601
|
-
const value = process.env.LARKIN_CONFIG_DIR?.trim();
|
|
602
|
-
return value || null;
|
|
603
|
-
};
|
|
604
584
|
const projectAuthFailure = (agent, readiness, failure) => {
|
|
605
585
|
agent.authFailureActive = true;
|
|
606
586
|
agent.authFailureKind = failure.kind;
|
|
@@ -618,12 +598,7 @@ export function createRuntimeHost(options) {
|
|
|
618
598
|
if (agent.authFailureKind !== "missing-provider" || !agent.authFailureProvider)
|
|
619
599
|
return true;
|
|
620
600
|
const failure = currentAuthFailure(agent);
|
|
621
|
-
|
|
622
|
-
return false;
|
|
623
|
-
const configDir = ownedConfigDir();
|
|
624
|
-
if (!configDir)
|
|
625
|
-
return false;
|
|
626
|
-
return officialPiHasStoredProvider(configDir, agent.config.agentId, agent.authFailureProvider);
|
|
601
|
+
return Boolean(failure && authFailureAppliesTo(authFailureScopeOf(agent), failure));
|
|
627
602
|
};
|
|
628
603
|
const resultFor = (agent, record, result) => {
|
|
629
604
|
if (result.status === "accepted") {
|
|
@@ -638,12 +613,12 @@ export function createRuntimeHost(options) {
|
|
|
638
613
|
deliveryId: record.deliveryId, messageId: record.messageId, status: "accepted" });
|
|
639
614
|
return { status: "accepted", deliveryId: record.deliveryId };
|
|
640
615
|
}
|
|
641
|
-
const missing = result.status === "rejected" &&
|
|
616
|
+
const missing = result.status === "rejected" && agent.adapter.id === "pi"
|
|
642
617
|
? classifyPiMissingCredentialRejection(result.reason)
|
|
643
618
|
: null;
|
|
644
619
|
if (missing) {
|
|
645
620
|
const readiness = missingProviderCredentialReadiness(agent.adapter.id, missing.provider);
|
|
646
|
-
const reason = readiness.reason ??
|
|
621
|
+
const reason = readiness.reason ?? result.reason;
|
|
647
622
|
if (record.status !== "error") {
|
|
648
623
|
record.reason = reason;
|
|
649
624
|
record.retryable = false;
|
|
@@ -1620,26 +1595,30 @@ export function createRuntimeHost(options) {
|
|
|
1620
1595
|
record.errorCategory = classifiedCategory;
|
|
1621
1596
|
else
|
|
1622
1597
|
delete record.errorCategory;
|
|
1623
|
-
const missing =
|
|
1598
|
+
const missing = agent.adapter.id === "pi"
|
|
1624
1599
|
? classifyPiMissingCredentialRejection(event.upstream?.message)
|
|
1625
1600
|
?? classifyPiMissingCredentialRejection(event.message)
|
|
1626
1601
|
: null;
|
|
1627
|
-
if (missing)
|
|
1602
|
+
if (missing) {
|
|
1603
|
+
record.retryable = false;
|
|
1604
|
+
record.errorCategory = "auth";
|
|
1628
1605
|
record.authProvider = missing.provider;
|
|
1629
|
-
|
|
1606
|
+
}
|
|
1607
|
+
const terminal = Boolean(missing) || !event.retryable;
|
|
1608
|
+
const finalRecord = setRecord(agent, record, terminal ? "error" : "pending");
|
|
1630
1609
|
if (finalRecord.status !== "consumed")
|
|
1631
1610
|
emit({ type: "delivery", agentId: agent.config.agentId,
|
|
1632
1611
|
deliveryId: record.deliveryId, messageId: record.messageId,
|
|
1633
|
-
status:
|
|
1634
|
-
if (
|
|
1635
|
-
const readiness = missing
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
}
|
|
1642
|
-
if (event.retryable && !agent.busy && !agent.turnInProgress)
|
|
1612
|
+
status: terminal ? "error" : "deferred", reason: event.message });
|
|
1613
|
+
if (missing) {
|
|
1614
|
+
const readiness = missingProviderCredentialReadiness(agent.adapter.id, missing.provider);
|
|
1615
|
+
projectAuthFailure(agent, readiness, { kind: "missing-provider", provider: missing.provider });
|
|
1616
|
+
}
|
|
1617
|
+
else if (event.errorCategory === "auth" && !event.retryable) {
|
|
1618
|
+
const readiness = providerAuthenticationFailureReadiness(agent.adapter.id, event.upstream?.provider);
|
|
1619
|
+
projectAuthFailure(agent, readiness, { kind: "generic", provider: genericAuthProvider(agent, event.upstream) });
|
|
1620
|
+
}
|
|
1621
|
+
if (!terminal && event.retryable && !agent.busy && !agent.turnInProgress)
|
|
1643
1622
|
void retryPending(agent);
|
|
1644
1623
|
}
|
|
1645
1624
|
else if (event.type === "configuration-error") {
|
|
@@ -1914,7 +1893,6 @@ export function createRuntimeHost(options) {
|
|
|
1914
1893
|
&& authFailureAppliesTo({
|
|
1915
1894
|
runtime: config.runtime,
|
|
1916
1895
|
model: config.model,
|
|
1917
|
-
piDistribution: config.piDistribution,
|
|
1918
1896
|
adapterId: adapter.id,
|
|
1919
1897
|
}, previousFailure));
|
|
1920
1898
|
const candidate = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CURRENT_RUNTIME_MODELS = void 0;
|
|
4
|
-
// Authored catalog keys are adapter ids only.
|
|
4
|
+
// Authored catalog keys are adapter ids only.
|
|
5
5
|
// Pi, Codex and Claude replace these placeholders/fallbacks at runtime with their machine-readable catalogs.
|
|
6
6
|
// Claude's supported stdin control-channel list is the live authority; its entries below
|
|
7
7
|
// remain explicit compatibility candidates for config loading and discovery failures.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Authored catalog keys are adapter ids only.
|
|
1
|
+
// Authored catalog keys are adapter ids only.
|
|
2
2
|
// Pi, Codex and Claude replace these placeholders/fallbacks at runtime with their machine-readable catalogs.
|
|
3
3
|
// Claude's supported stdin control-channel list is the live authority; its entries below
|
|
4
4
|
// remain explicit compatibility candidates for config loading and discovery failures.
|
|
@@ -38,25 +38,22 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
exports.RuntimePrerequisiteError = void 0;
|
|
40
40
|
exports.safeProviderId = safeProviderId;
|
|
41
|
-
exports.isBuiltinPiDistribution = isBuiltinPiDistribution;
|
|
42
41
|
exports.configuredProviderId = configuredProviderId;
|
|
43
42
|
exports.parsePersistedAuthFailure = parsePersistedAuthFailure;
|
|
44
43
|
exports.authFailureAppliesTo = authFailureAppliesTo;
|
|
45
44
|
exports.readinessForPersistedAuthFailure = readinessForPersistedAuthFailure;
|
|
46
45
|
exports.classifyPiMissingCredentialRejection = classifyPiMissingCredentialRejection;
|
|
46
|
+
exports.runtimeInstallNextAction = runtimeInstallNextAction;
|
|
47
|
+
exports.runtimeLoginNextAction = runtimeLoginNextAction;
|
|
47
48
|
exports.providerAuthenticationFailureReadiness = providerAuthenticationFailureReadiness;
|
|
48
49
|
exports.missingProviderCredentialReadiness = missingProviderCredentialReadiness;
|
|
49
50
|
exports.resolveRuntimeExecutable = resolveRuntimeExecutable;
|
|
50
51
|
exports.classifyRuntimePrerequisite = classifyRuntimePrerequisite;
|
|
51
52
|
exports.probeNativeRuntimeReadiness = probeNativeRuntimeReadiness;
|
|
52
53
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
53
|
-
const node_os_1 = __importDefault(require("node:os"));
|
|
54
54
|
const node_path_1 = __importDefault(require("node:path"));
|
|
55
55
|
const node_child_process_1 = require("node:child_process");
|
|
56
|
-
const
|
|
57
|
-
const builtin_pi_assets_js_1 = require("./builtin-pi-assets.cjs");
|
|
58
|
-
const pi_provider_config_js_1 = require("./pi-provider-config.cjs");
|
|
59
|
-
const process_boundary_trace_js_1 = require("../platform/process-boundary-trace.cjs");
|
|
56
|
+
const pi_compaction_recovery_js_1 = require("./pi-compaction-recovery.cjs");
|
|
60
57
|
function safeProviderId(value) {
|
|
61
58
|
const provider = typeof value === "string" ? value.trim() : "";
|
|
62
59
|
return /^[A-Za-z0-9][A-Za-z0-9._-]{0,79}$/.test(provider) ? provider : null;
|
|
@@ -64,9 +61,6 @@ function safeProviderId(value) {
|
|
|
64
61
|
function safeProviderLabel(value) {
|
|
65
62
|
return safeProviderId(value);
|
|
66
63
|
}
|
|
67
|
-
function isBuiltinPiDistribution(value) {
|
|
68
|
-
return value === "builtin";
|
|
69
|
-
}
|
|
70
64
|
/** Model ids are `provider/model`; only the provider prefix is used for scope. */
|
|
71
65
|
function configuredProviderId(model) {
|
|
72
66
|
const value = typeof model === "string" ? model.trim() : "";
|
|
@@ -89,53 +83,20 @@ function parsePersistedAuthFailure(state) {
|
|
|
89
83
|
const provider = safeProviderId(failure.provider);
|
|
90
84
|
if (kind === "missing-provider" && !provider)
|
|
91
85
|
return null;
|
|
92
|
-
|
|
93
|
-
? failure.piDistribution : undefined;
|
|
94
|
-
return {
|
|
95
|
-
kind,
|
|
96
|
-
runtime,
|
|
97
|
-
...(piDistribution ? { piDistribution } : {}),
|
|
98
|
-
provider,
|
|
99
|
-
};
|
|
86
|
+
return { kind, runtime, provider };
|
|
100
87
|
}
|
|
101
88
|
const legacy = safeProviderId(record.authFailureProvider);
|
|
102
|
-
return legacy
|
|
103
|
-
? { kind: "missing-provider", runtime: "pi", piDistribution: "builtin", provider: legacy }
|
|
104
|
-
: null;
|
|
89
|
+
return legacy ? { kind: "missing-provider", runtime: "pi", provider: legacy } : null;
|
|
105
90
|
}
|
|
106
91
|
function currentAdapterId(current) {
|
|
107
|
-
return current.adapterId ??
|
|
108
|
-
}
|
|
109
|
-
function currentIsBuiltinPi(current) {
|
|
110
|
-
return currentAdapterId(current) === "pi"
|
|
111
|
-
&& (isBuiltinPiDistribution(current.piDistribution) || current.runtime === "builtin-pi");
|
|
92
|
+
return current.adapterId ?? current.runtime;
|
|
112
93
|
}
|
|
113
|
-
/**
|
|
114
|
-
* Missing-provider and known-provider generic markers apply only to that provider.
|
|
115
|
-
* Generic without a provider is conservative fallback: it still binds runtime /
|
|
116
|
-
* builtin distribution, but cannot reject an A→B model switch because the
|
|
117
|
-
* upstream provider was genuinely unavailable.
|
|
118
|
-
*/
|
|
119
94
|
function authFailureAppliesTo(current, failure) {
|
|
120
|
-
if (failure.kind === "missing-provider") {
|
|
121
|
-
return currentIsBuiltinPi(current)
|
|
122
|
-
&& failure.runtime === "pi"
|
|
123
|
-
&& failure.piDistribution === "builtin"
|
|
124
|
-
&& Boolean(failure.provider)
|
|
125
|
-
&& configuredProviderId(current.model) === failure.provider;
|
|
126
|
-
}
|
|
127
95
|
if (failure.runtime !== currentAdapterId(current))
|
|
128
96
|
return false;
|
|
129
|
-
if (failure.runtime === "pi") {
|
|
130
|
-
const persistedBuiltin = failure.piDistribution === "builtin";
|
|
131
|
-
if (currentIsBuiltinPi(current) !== persistedBuiltin)
|
|
132
|
-
return false;
|
|
133
|
-
}
|
|
134
97
|
if (!failure.provider)
|
|
135
98
|
return true;
|
|
136
99
|
const currentProvider = configuredProviderId(current.model);
|
|
137
|
-
if (currentIsBuiltinPi(current))
|
|
138
|
-
return currentProvider === failure.provider;
|
|
139
100
|
return currentProvider ? currentProvider === failure.provider : true;
|
|
140
101
|
}
|
|
141
102
|
function readinessForPersistedAuthFailure(failure) {
|
|
@@ -154,6 +115,20 @@ function classifyPiMissingCredentialRejection(message) {
|
|
|
154
115
|
const provider = match ? safeProviderLabel(match[2]) : null;
|
|
155
116
|
return provider && match ? { provider, diagnostic: `${match[1]} ${provider}` } : null;
|
|
156
117
|
}
|
|
118
|
+
function runtimeInstallNextAction(runtime) {
|
|
119
|
+
if (runtime === "pi")
|
|
120
|
+
return "Install Pi and ensure `pi` is on PATH, or set LARKIN_PI_COMMAND.";
|
|
121
|
+
if (runtime === "codex")
|
|
122
|
+
return "Install Codex and ensure `codex` is on PATH, or set LARKIN_CODEX_COMMAND.";
|
|
123
|
+
return "Install Claude Code and ensure `claude` is on PATH, or set LARKIN_CLAUDE_COMMAND.";
|
|
124
|
+
}
|
|
125
|
+
function runtimeLoginNextAction(runtime) {
|
|
126
|
+
if (runtime === "pi")
|
|
127
|
+
return "Log in with the external `pi` CLI, then retry.";
|
|
128
|
+
if (runtime === "codex")
|
|
129
|
+
return "Run `codex login`, then retry.";
|
|
130
|
+
return "Run `claude login`, then retry.";
|
|
131
|
+
}
|
|
157
132
|
function providerAuthenticationFailureReadiness(runtime, provider) {
|
|
158
133
|
const label = safeProviderLabel(provider);
|
|
159
134
|
return {
|
|
@@ -162,23 +137,20 @@ function providerAuthenticationFailureReadiness(runtime, provider) {
|
|
|
162
137
|
reason: label
|
|
163
138
|
? `Provider ${label} API-key authentication failed during a Runtime turn.`
|
|
164
139
|
: "Configured provider API-key authentication failed during a Runtime turn.",
|
|
165
|
-
nextAction:
|
|
140
|
+
nextAction: runtimeLoginNextAction(runtime),
|
|
166
141
|
};
|
|
167
142
|
}
|
|
168
|
-
/** P0 分类;Pi nextAction 共用 UX preset 恢复文案,不写官方 provider ID。 */
|
|
169
143
|
function missingProviderCredentialReadiness(runtime, provider) {
|
|
170
144
|
const label = safeProviderLabel(provider);
|
|
171
145
|
return {
|
|
172
146
|
runtime,
|
|
173
147
|
state: "unauthenticated",
|
|
174
148
|
reason: label
|
|
175
|
-
? `Provider ${label} is
|
|
176
|
-
: "The configured provider is
|
|
177
|
-
nextAction: runtime === "pi"
|
|
178
|
-
?
|
|
179
|
-
:
|
|
180
|
-
? `Add the missing ${label} credential to this Agent's official store, then retry the Agent turn.`
|
|
181
|
-
: "Add the missing provider credential to this Agent's official store, then retry the Agent turn.",
|
|
149
|
+
? `Provider ${label} is not authenticated for this runtime.`
|
|
150
|
+
: "The configured provider is not authenticated for this runtime.",
|
|
151
|
+
nextAction: runtime === "pi" && label
|
|
152
|
+
? `Log in with the external \`pi\` CLI for provider ${label}, then retry.`
|
|
153
|
+
: runtimeLoginNextAction(runtime),
|
|
182
154
|
};
|
|
183
155
|
}
|
|
184
156
|
class RuntimePrerequisiteError extends Error {
|
|
@@ -211,27 +183,37 @@ function classifyRuntimePrerequisite(runtime, error, executable) {
|
|
|
211
183
|
const reason = (error instanceof Error ? error.message : String(error)).replace(/[\r\n]+/g, " ").slice(0, 500);
|
|
212
184
|
if (/ENOENT|not found|no such file|spawn .* failed/i.test(reason))
|
|
213
185
|
return {
|
|
214
|
-
runtime, state: "missing", ...(executable ? { executable } : {}),
|
|
215
|
-
|
|
186
|
+
runtime, state: "missing", ...(executable ? { executable } : {}),
|
|
187
|
+
reason: `${runtime} is not installed`,
|
|
188
|
+
nextAction: runtimeInstallNextAction(runtime),
|
|
216
189
|
};
|
|
217
190
|
if (/no authenticated available models|login|credential|unauthenticated|unauthorized|oauth/i.test(reason))
|
|
218
191
|
return {
|
|
219
192
|
runtime, state: "unauthenticated", ...(executable ? { executable } : {}), reason,
|
|
220
|
-
|
|
193
|
+
nextAction: runtimeLoginNextAction(runtime),
|
|
194
|
+
};
|
|
195
|
+
if (/older than the minimum|not a supported version(?: line)?|version output must contain exactly one/i.test(reason)) {
|
|
196
|
+
return {
|
|
197
|
+
runtime, state: "incompatible", ...(executable ? { executable } : {}), reason,
|
|
221
198
|
nextAction: runtime === "pi"
|
|
222
|
-
?
|
|
223
|
-
: `
|
|
199
|
+
? `Upgrade pi to ${pi_compaction_recovery_js_1.MINIMUM_PI_VERSION} or newer`
|
|
200
|
+
: `Upgrade ${runtime}, then retry.`,
|
|
224
201
|
};
|
|
225
|
-
|
|
202
|
+
}
|
|
203
|
+
if (/protocol (?:version )?(?:mismatch|unsupported|incompatible)|unsupported (?:rpc|protocol|schema)|schema (?:mismatch|incompatible)|requires (?:a )?newer version/i.test(reason)) {
|
|
226
204
|
return {
|
|
227
205
|
runtime, state: "incompatible", ...(executable ? { executable } : {}), reason,
|
|
228
|
-
nextAction: runtime === "pi"
|
|
206
|
+
nextAction: runtime === "pi"
|
|
207
|
+
? "Upgrade local Pi to a version that supports the documented RPC protocol."
|
|
208
|
+
: `Upgrade ${runtime}, then retry.`,
|
|
229
209
|
};
|
|
230
|
-
|
|
210
|
+
}
|
|
211
|
+
if (/timeout|timed out|unexpected EOF|\bEOF\b|TLS|ECONNRESET|socket hang up|network|temporar(?:y|ily)|unavailable/i.test(reason)) {
|
|
231
212
|
return {
|
|
232
213
|
runtime, state: "unavailable", ...(executable ? { executable } : {}), reason,
|
|
233
214
|
nextAction: `Retry ${runtime}; Larkin will use its bounded Runtime recreate/backoff policy.`,
|
|
234
215
|
};
|
|
216
|
+
}
|
|
235
217
|
return {
|
|
236
218
|
runtime, state: "unavailable", ...(executable ? { executable } : {}), reason,
|
|
237
219
|
nextAction: `Retry ${runtime}; the failure is not proven to be a protocol incompatibility.`,
|
|
@@ -254,47 +236,30 @@ function executableVersion(executable, env, commandArgs = []) {
|
|
|
254
236
|
}
|
|
255
237
|
/** Resolve and handshake through each runtime's structured native control protocol. */
|
|
256
238
|
async function probeNativeRuntimeReadiness(options) {
|
|
257
|
-
|
|
258
|
-
const
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
239
|
+
const env = { ...process.env, ...options.env };
|
|
240
|
+
const command = selectedCommand(options);
|
|
241
|
+
const executable = resolveRuntimeExecutable(command, env);
|
|
242
|
+
if (!executable) {
|
|
243
|
+
return {
|
|
244
|
+
runtime: options.runtime,
|
|
245
|
+
state: "missing",
|
|
246
|
+
reason: `${options.runtime} is not installed`,
|
|
247
|
+
nextAction: runtimeInstallNextAction(options.runtime),
|
|
248
|
+
};
|
|
263
249
|
}
|
|
264
|
-
|
|
250
|
+
let version = executableVersion(executable, env, options.commandArgs);
|
|
251
|
+
if (options.runtime === "pi") {
|
|
265
252
|
try {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
253
|
+
const probe = (0, node_child_process_1.spawnSync)(executable, [...options.commandArgs ?? [], "--version"], {
|
|
254
|
+
env, encoding: "utf8", timeout: 5_000, maxBuffer: 64 * 1024,
|
|
255
|
+
});
|
|
256
|
+
version = (0, pi_compaction_recovery_js_1.parsePiExecutableVersion)(String(probe.stdout || ""));
|
|
270
257
|
}
|
|
271
258
|
catch (error) {
|
|
272
|
-
|
|
273
|
-
return {
|
|
274
|
-
nextAction: (0, pi_provider_config_js_1.builtinPiProviderRecoveryNextAction)({ agentId: options.agentId }) };
|
|
259
|
+
const classified = classifyRuntimePrerequisite("pi", error, executable);
|
|
260
|
+
return { ...classified, executable, ...(version ? { version } : {}) };
|
|
275
261
|
}
|
|
276
262
|
}
|
|
277
|
-
const command = selectedCommand(options);
|
|
278
|
-
const executable = resolveRuntimeExecutable(command, env);
|
|
279
|
-
if (!executable)
|
|
280
|
-
return {
|
|
281
|
-
runtime: options.runtime, state: "missing",
|
|
282
|
-
reason: `${command} executable was not found`,
|
|
283
|
-
nextAction: options.runtime === "pi"
|
|
284
|
-
? "Install Pi and ensure `pi` is on PATH, or set LARKIN_PI_COMMAND."
|
|
285
|
-
: `Install ${options.runtime} and ensure it is on PATH.`,
|
|
286
|
-
};
|
|
287
|
-
const piAgentId = options.agentId;
|
|
288
|
-
if (options.runtime === "pi" && !piAgentId) {
|
|
289
|
-
return {
|
|
290
|
-
runtime: "pi",
|
|
291
|
-
state: "unavailable",
|
|
292
|
-
executable,
|
|
293
|
-
reason: "Pi catalog readiness requires Agent ID",
|
|
294
|
-
nextAction: "Retry setup or start so Larkin can probe the Agent-owned Pi provider directory.",
|
|
295
|
-
};
|
|
296
|
-
}
|
|
297
|
-
const version = executableVersion(executable, env, options.commandArgs);
|
|
298
263
|
try {
|
|
299
264
|
if (options.runtime === "pi") {
|
|
300
265
|
const { discoverPiModelCatalog } = await Promise.resolve().then(() => __importStar(require("./pi-model-catalog.cjs")));
|
|
@@ -303,7 +268,6 @@ async function probeNativeRuntimeReadiness(options) {
|
|
|
303
268
|
command: executable,
|
|
304
269
|
commandArgs: options.commandArgs,
|
|
305
270
|
env,
|
|
306
|
-
agentDir: (0, pi_provider_config_js_1.ownedPiCatalogAgentDir)((0, root_layout_js_1.resolveConfigDir)(env, node_os_1.default.homedir()), piAgentId),
|
|
307
271
|
});
|
|
308
272
|
}
|
|
309
273
|
else if (options.runtime === "codex") {
|