larkin 0.2.70
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/CONTRIBUTING.md +48 -0
- package/LICENSE +201 -0
- package/README.md +122 -0
- package/SECURITY.md +14 -0
- package/artifacts/release/THIRD_PARTY_NOTICES.txt +5488 -0
- package/dist/agent/agent-cli-capabilities.cjs +43 -0
- package/dist/agent/agent-cli-capabilities.mjs +35 -0
- package/dist/agent/agent-state-store.cjs +961 -0
- package/dist/agent/agent-state-store.mjs +923 -0
- package/dist/agent/agent-transport.cjs +201 -0
- package/dist/agent/agent-transport.mjs +194 -0
- package/dist/agent/config-cli-contract.cjs +19 -0
- package/dist/agent/config-cli-contract.mjs +16 -0
- package/dist/agent/context-prompt.cjs +159 -0
- package/dist/agent/context-prompt.mjs +155 -0
- package/dist/agent/freshness-gate.mjs +24 -0
- package/dist/agent/history-projection.cjs +72 -0
- package/dist/agent/history-projection.mjs +65 -0
- package/dist/agent/host-reminder-orchestrator.cjs +289 -0
- package/dist/agent/host-reminder-orchestrator.mjs +252 -0
- package/dist/agent/inbox-projection.cjs +92 -0
- package/dist/agent/inbox-projection.mjs +85 -0
- package/dist/agent/interaction-state-machine.cjs +710 -0
- package/dist/agent/interaction-state-machine.mjs +705 -0
- package/dist/agent/reminder-routes.cjs +192 -0
- package/dist/agent/reminder-routes.mjs +156 -0
- package/dist/agent/reminder-store.cjs +220 -0
- package/dist/agent/reminder-store.mjs +205 -0
- package/dist/agent/transport-business-context.cjs +486 -0
- package/dist/agent/transport-business-context.mjs +446 -0
- package/dist/agent/transport-shell.cjs +45 -0
- package/dist/agent/transport-shell.mjs +39 -0
- package/dist/app/agent-cli.mjs +596 -0
- package/dist/app/agent-config.mjs +633 -0
- package/dist/app/agent-lark-cli-workspace.cjs +95 -0
- package/dist/app/agent-lark-cli-workspace.mjs +85 -0
- package/dist/app/agent-readiness.cjs +42 -0
- package/dist/app/agent-readiness.mjs +38 -0
- package/dist/app/binary-entry.mjs +86 -0
- package/dist/app/cli.mjs +176 -0
- package/dist/app/dashboard.mjs +205 -0
- package/dist/app/internal-command.cjs +57 -0
- package/dist/app/internal-command.mjs +48 -0
- package/dist/app/lark-channel-secret.mjs +22 -0
- package/dist/app/lark-cli.mjs +887 -0
- package/dist/app/lark.mjs +45 -0
- package/dist/app/local-control.mjs +728 -0
- package/dist/app/official-lark-cli.cjs +138 -0
- package/dist/app/official-lark-cli.mjs +128 -0
- package/dist/app/pi-auth-cli.mjs +67 -0
- package/dist/app/run.mjs +364 -0
- package/dist/app/runtime-agent-config.mjs +416 -0
- package/dist/app/runtime-model-directory.mjs +78 -0
- package/dist/app/runtime-process.mjs +113 -0
- package/dist/app/session-cli.mjs +83 -0
- package/dist/app/setup-dashboard.mjs +26 -0
- package/dist/app/setup.mjs +166 -0
- package/dist/app/telemetry.mjs +83 -0
- package/dist/dashboard/dashboard-assets.mjs +21 -0
- package/dist/dashboard/dashboard-avatar.mjs +128 -0
- package/dist/dashboard/dashboard-config-controller.mjs +525 -0
- package/dist/dashboard/dashboard-lifecycle.cjs +97 -0
- package/dist/dashboard/dashboard-lifecycle.mjs +88 -0
- package/dist/dashboard/dashboard-template.mjs +29 -0
- package/dist/dashboard/dashboard-view-model.mjs +556 -0
- package/dist/dashboard/dashboard-workspace.mjs +104 -0
- package/dist/dashboard/web/assets/dashboard.css +3 -0
- package/dist/dashboard/web/assets/dashboard.js +49 -0
- package/dist/feishu/channel-transport.cjs +151 -0
- package/dist/feishu/channel-transport.mjs +148 -0
- package/dist/feishu/document-comment.cjs +120 -0
- package/dist/feishu/document-comment.mjs +109 -0
- package/dist/feishu/host-business-state.cjs +477 -0
- package/dist/feishu/host-business-state.mjs +462 -0
- package/dist/feishu/host-channel-business.cjs +161 -0
- package/dist/feishu/host-channel-business.mjs +157 -0
- package/dist/feishu/host-processing-eye.cjs +185 -0
- package/dist/feishu/host-processing-eye.mjs +181 -0
- package/dist/feishu/host-shell.cjs +1425 -0
- package/dist/feishu/host-shell.mjs +1385 -0
- package/dist/feishu/im-freshness-adapter.mjs +89 -0
- package/dist/feishu/interaction-orchestrator.cjs +279 -0
- package/dist/feishu/interaction-orchestrator.mjs +242 -0
- package/dist/feishu/lark-passthrough.mjs +70 -0
- package/dist/feishu/message-policy.cjs +111 -0
- package/dist/feishu/message-policy.mjs +98 -0
- package/dist/feishu/outbound-transport.cjs +221 -0
- package/dist/feishu/outbound-transport.mjs +215 -0
- package/dist/platform/build-info.cjs +25 -0
- package/dist/platform/build-info.mjs +18 -0
- package/dist/platform/callback-capability.cjs +301 -0
- package/dist/platform/callback-capability.mjs +252 -0
- package/dist/platform/check-bun-version.cjs +12 -0
- package/dist/platform/config.cjs +751 -0
- package/dist/platform/config.mjs +694 -0
- package/dist/platform/process-inspect.cjs +89 -0
- package/dist/platform/process-state.cjs +237 -0
- package/dist/platform/process-state.mjs +223 -0
- package/dist/platform/release-artifacts.mjs +61 -0
- package/dist/platform/root-layout.cjs +111 -0
- package/dist/platform/root-layout.mjs +72 -0
- package/dist/platform/telemetry-config.cjs +64 -0
- package/dist/platform/telemetry-config.mjs +56 -0
- package/dist/platform/telemetry-spool.cjs +661 -0
- package/dist/platform/telemetry-spool.mjs +653 -0
- package/dist/platform/telemetry-tracing.cjs +602 -0
- package/dist/platform/telemetry-tracing.mjs +596 -0
- package/dist/platform/telemetry-uploader.cjs +150 -0
- package/dist/platform/telemetry-uploader.mjs +146 -0
- package/dist/platform/workspace-service.cjs +469 -0
- package/dist/platform/workspace-service.mjs +430 -0
- package/dist/runtime/builtin-pi-assets.mjs +33 -0
- package/dist/runtime/claude-model-catalog.cjs +102 -0
- package/dist/runtime/claude-model-catalog.mjs +99 -0
- package/dist/runtime/codex-model-catalog.cjs +108 -0
- package/dist/runtime/codex-model-catalog.mjs +105 -0
- package/dist/runtime/pi-bash-timeout-extension.mjs +60 -0
- package/dist/runtime/pi-bash-timeout-injection.mjs +60 -0
- package/dist/runtime/pi-bash-timeout.bundle.js +43 -0
- package/dist/runtime/pi-model-catalog.cjs +116 -0
- package/dist/runtime/pi-model-catalog.mjs +75 -0
- package/dist/runtime/pi-official-auth.mjs +480 -0
- package/dist/runtime/pi-provider-config.cjs +252 -0
- package/dist/runtime/pi-provider-config.mjs +239 -0
- package/dist/runtime/pi-rpc-client.cjs +255 -0
- package/dist/runtime/pi-rpc-client.mjs +251 -0
- package/dist/runtime/pi-subagent-injection.mjs +129 -0
- package/dist/runtime/pi-subagents.bundle.js +8990 -0
- package/dist/runtime/runtime-adapters.mjs +1019 -0
- package/dist/runtime/runtime-contracts.cjs +2 -0
- package/dist/runtime/runtime-contracts.mjs +1 -0
- package/dist/runtime/runtime-host.cjs +930 -0
- package/dist/runtime/runtime-host.mjs +922 -0
- package/dist/runtime/runtime-model-catalog.cjs +43 -0
- package/dist/runtime/runtime-model-catalog.mjs +40 -0
- package/dist/runtime/runtime-readiness.cjs +177 -0
- package/dist/runtime/runtime-readiness.mjs +133 -0
- package/dist/setup/bot-register.mjs +655 -0
- package/dist/setup/grant-scopes.mjs +133 -0
- package/dist/setup/run-credential-preflight.mjs +89 -0
- package/dist/setup/setup-agent-choice.mjs +172 -0
- package/dist/setup/setup-bind.mjs +337 -0
- package/dist/setup/setup-binding.mjs +52 -0
- package/package.json +112 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CURRENT_RUNTIME_MODELS = void 0;
|
|
4
|
+
// Larkin supports exactly these three native Runtime adapters. Pi, Codex and Claude replace
|
|
5
|
+
// these placeholders/fallbacks at runtime with their machine-readable catalogs.
|
|
6
|
+
// Claude's supported stdin control-channel list is the live authority; its entries below
|
|
7
|
+
// remain explicit compatibility candidates for config loading and discovery failures.
|
|
8
|
+
exports.CURRENT_RUNTIME_MODELS = {
|
|
9
|
+
codex: [
|
|
10
|
+
{ id: "default", label: "default", verified: "dynamic" },
|
|
11
|
+
{ id: "gpt-5.6-sol", label: "GPT-5.6 Sol · 静态兼容目录", supportedReasoningEfforts: ["low", "medium", "high", "xhigh", "max", "ultra"], defaultReasoningEffort: "low", verified: "authored-compatibility" },
|
|
12
|
+
{ id: "gpt-5.6-terra", label: "GPT-5.6 Terra · 静态兼容目录", supportedReasoningEfforts: ["low", "medium", "high", "xhigh", "max", "ultra"], defaultReasoningEffort: "medium", verified: "authored-compatibility" },
|
|
13
|
+
{ id: "gpt-5.6-luna", label: "GPT-5.6 Luna · 静态兼容目录", supportedReasoningEfforts: ["low", "medium", "high", "xhigh", "max"], defaultReasoningEffort: "medium", verified: "authored-compatibility" },
|
|
14
|
+
{ id: "gpt-5.5", label: "GPT-5.5 · 静态兼容目录", verified: "authored-compatibility" },
|
|
15
|
+
{ id: "gpt-5.4", label: "GPT-5.4 · 静态兼容目录", verified: "authored-compatibility" },
|
|
16
|
+
{ id: "gpt-5.4-mini", label: "GPT-5.4 Mini · 静态兼容目录", verified: "authored-compatibility" },
|
|
17
|
+
{ id: "gpt-5.3-codex", label: "GPT-5.3 Codex · 静态兼容目录", verified: "authored-compatibility" },
|
|
18
|
+
{ id: "gpt-5.3-codex-spark", label: "GPT-5.3 Codex Spark · 静态兼容目录", verified: "authored-compatibility" },
|
|
19
|
+
{ id: "gpt-5.2-codex", label: "GPT-5.2 Codex · 静态兼容目录", verified: "authored-compatibility" },
|
|
20
|
+
{ id: "gpt-5.2", label: "GPT-5.2 · 静态兼容目录", verified: "authored-compatibility" },
|
|
21
|
+
{ id: "gpt-5.1-codex-max", label: "GPT-5.1 Codex Max · 静态兼容目录", verified: "authored-compatibility" },
|
|
22
|
+
{ id: "gpt-5.1-codex", label: "GPT-5.1 Codex · 静态兼容目录", verified: "authored-compatibility" },
|
|
23
|
+
{ id: "gpt-5-codex", label: "GPT-5 Codex · 静态兼容目录", verified: "authored-compatibility" },
|
|
24
|
+
{ id: "gpt-5", label: "GPT-5 · 静态兼容目录", verified: "authored-compatibility" },
|
|
25
|
+
],
|
|
26
|
+
claude: [
|
|
27
|
+
{ id: "default", label: "default", verified: "dynamic" },
|
|
28
|
+
{ id: "opus", label: "Claude Opus · 静态候选", verified: "authored-candidate" },
|
|
29
|
+
{ id: "opus[1m]", label: "Claude Opus 1M · 静态候选", verified: "authored-candidate" },
|
|
30
|
+
{ id: "fable", label: "Claude Fable · 静态候选", verified: "authored-candidate" },
|
|
31
|
+
{ id: "sonnet", label: "Claude Sonnet · 静态候选", verified: "authored-candidate" },
|
|
32
|
+
{ id: "haiku", label: "Claude Haiku · 静态候选", verified: "authored-candidate" },
|
|
33
|
+
{ id: "claude-opus-4-8", label: "Claude Opus 4.8 · 静态候选", verified: "authored-candidate" },
|
|
34
|
+
{ id: "claude-opus-4-7", label: "Claude Opus 4.7 · 静态候选", verified: "authored-candidate" },
|
|
35
|
+
{ id: "claude-opus-4-6", label: "Claude Opus 4.6 · 静态候选", verified: "authored-candidate" },
|
|
36
|
+
{ id: "claude-fable-5", label: "Claude Fable 5 · 静态候选", verified: "authored-candidate" },
|
|
37
|
+
{ id: "claude-fable-5[1m]", label: "Claude Fable 5 1M · 静态候选", verified: "authored-candidate" },
|
|
38
|
+
{ id: "claude-sonnet-5", label: "Claude Sonnet 5 · 静态候选", verified: "authored-candidate" },
|
|
39
|
+
{ id: "claude-sonnet-4-6", label: "Claude Sonnet 4.6 · 静态候选", verified: "authored-candidate" },
|
|
40
|
+
{ id: "claude-haiku-4-5", label: "Claude Haiku 4.5 · 静态候选", verified: "authored-candidate" },
|
|
41
|
+
],
|
|
42
|
+
pi: [{ id: "default", label: "default", verified: "dynamic" }],
|
|
43
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// Larkin supports exactly these three native Runtime adapters. Pi, Codex and Claude replace
|
|
2
|
+
// these placeholders/fallbacks at runtime with their machine-readable catalogs.
|
|
3
|
+
// Claude's supported stdin control-channel list is the live authority; its entries below
|
|
4
|
+
// remain explicit compatibility candidates for config loading and discovery failures.
|
|
5
|
+
export const CURRENT_RUNTIME_MODELS = {
|
|
6
|
+
codex: [
|
|
7
|
+
{ id: "default", label: "default", verified: "dynamic" },
|
|
8
|
+
{ id: "gpt-5.6-sol", label: "GPT-5.6 Sol · 静态兼容目录", supportedReasoningEfforts: ["low", "medium", "high", "xhigh", "max", "ultra"], defaultReasoningEffort: "low", verified: "authored-compatibility" },
|
|
9
|
+
{ id: "gpt-5.6-terra", label: "GPT-5.6 Terra · 静态兼容目录", supportedReasoningEfforts: ["low", "medium", "high", "xhigh", "max", "ultra"], defaultReasoningEffort: "medium", verified: "authored-compatibility" },
|
|
10
|
+
{ id: "gpt-5.6-luna", label: "GPT-5.6 Luna · 静态兼容目录", supportedReasoningEfforts: ["low", "medium", "high", "xhigh", "max"], defaultReasoningEffort: "medium", verified: "authored-compatibility" },
|
|
11
|
+
{ id: "gpt-5.5", label: "GPT-5.5 · 静态兼容目录", verified: "authored-compatibility" },
|
|
12
|
+
{ id: "gpt-5.4", label: "GPT-5.4 · 静态兼容目录", verified: "authored-compatibility" },
|
|
13
|
+
{ id: "gpt-5.4-mini", label: "GPT-5.4 Mini · 静态兼容目录", verified: "authored-compatibility" },
|
|
14
|
+
{ id: "gpt-5.3-codex", label: "GPT-5.3 Codex · 静态兼容目录", verified: "authored-compatibility" },
|
|
15
|
+
{ id: "gpt-5.3-codex-spark", label: "GPT-5.3 Codex Spark · 静态兼容目录", verified: "authored-compatibility" },
|
|
16
|
+
{ id: "gpt-5.2-codex", label: "GPT-5.2 Codex · 静态兼容目录", verified: "authored-compatibility" },
|
|
17
|
+
{ id: "gpt-5.2", label: "GPT-5.2 · 静态兼容目录", verified: "authored-compatibility" },
|
|
18
|
+
{ id: "gpt-5.1-codex-max", label: "GPT-5.1 Codex Max · 静态兼容目录", verified: "authored-compatibility" },
|
|
19
|
+
{ id: "gpt-5.1-codex", label: "GPT-5.1 Codex · 静态兼容目录", verified: "authored-compatibility" },
|
|
20
|
+
{ id: "gpt-5-codex", label: "GPT-5 Codex · 静态兼容目录", verified: "authored-compatibility" },
|
|
21
|
+
{ id: "gpt-5", label: "GPT-5 · 静态兼容目录", verified: "authored-compatibility" },
|
|
22
|
+
],
|
|
23
|
+
claude: [
|
|
24
|
+
{ id: "default", label: "default", verified: "dynamic" },
|
|
25
|
+
{ id: "opus", label: "Claude Opus · 静态候选", verified: "authored-candidate" },
|
|
26
|
+
{ id: "opus[1m]", label: "Claude Opus 1M · 静态候选", verified: "authored-candidate" },
|
|
27
|
+
{ id: "fable", label: "Claude Fable · 静态候选", verified: "authored-candidate" },
|
|
28
|
+
{ id: "sonnet", label: "Claude Sonnet · 静态候选", verified: "authored-candidate" },
|
|
29
|
+
{ id: "haiku", label: "Claude Haiku · 静态候选", verified: "authored-candidate" },
|
|
30
|
+
{ id: "claude-opus-4-8", label: "Claude Opus 4.8 · 静态候选", verified: "authored-candidate" },
|
|
31
|
+
{ id: "claude-opus-4-7", label: "Claude Opus 4.7 · 静态候选", verified: "authored-candidate" },
|
|
32
|
+
{ id: "claude-opus-4-6", label: "Claude Opus 4.6 · 静态候选", verified: "authored-candidate" },
|
|
33
|
+
{ id: "claude-fable-5", label: "Claude Fable 5 · 静态候选", verified: "authored-candidate" },
|
|
34
|
+
{ id: "claude-fable-5[1m]", label: "Claude Fable 5 1M · 静态候选", verified: "authored-candidate" },
|
|
35
|
+
{ id: "claude-sonnet-5", label: "Claude Sonnet 5 · 静态候选", verified: "authored-candidate" },
|
|
36
|
+
{ id: "claude-sonnet-4-6", label: "Claude Sonnet 4.6 · 静态候选", verified: "authored-candidate" },
|
|
37
|
+
{ id: "claude-haiku-4-5", label: "Claude Haiku 4.5 · 静态候选", verified: "authored-candidate" },
|
|
38
|
+
],
|
|
39
|
+
pi: [{ id: "default", label: "default", verified: "dynamic" }],
|
|
40
|
+
};
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.RuntimePrerequisiteError = void 0;
|
|
40
|
+
exports.providerAuthenticationFailureReadiness = providerAuthenticationFailureReadiness;
|
|
41
|
+
exports.resolveRuntimeExecutable = resolveRuntimeExecutable;
|
|
42
|
+
exports.classifyRuntimePrerequisite = classifyRuntimePrerequisite;
|
|
43
|
+
exports.probeNativeRuntimeReadiness = probeNativeRuntimeReadiness;
|
|
44
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
45
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
46
|
+
const node_child_process_1 = require("node:child_process");
|
|
47
|
+
const pi_provider_config_js_1 = require("./pi-provider-config.cjs");
|
|
48
|
+
function safeProviderLabel(value) {
|
|
49
|
+
const provider = typeof value === "string" ? value.trim() : "";
|
|
50
|
+
return /^[A-Za-z0-9][A-Za-z0-9._-]{0,79}$/.test(provider) ? provider : null;
|
|
51
|
+
}
|
|
52
|
+
function providerAuthenticationFailureReadiness(runtime, provider) {
|
|
53
|
+
const label = safeProviderLabel(provider);
|
|
54
|
+
return {
|
|
55
|
+
runtime,
|
|
56
|
+
state: "unauthenticated",
|
|
57
|
+
reason: label
|
|
58
|
+
? `Provider ${label} API-key authentication failed during a Runtime turn.`
|
|
59
|
+
: "Configured provider API-key authentication failed during a Runtime turn.",
|
|
60
|
+
nextAction: "Check the provider login or API-key resolver command, then retry the Agent turn.",
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
class RuntimePrerequisiteError extends Error {
|
|
64
|
+
readiness;
|
|
65
|
+
constructor(readiness) {
|
|
66
|
+
super(readiness.reason || `${readiness.runtime} runtime is ${readiness.state}`);
|
|
67
|
+
this.readiness = readiness;
|
|
68
|
+
this.name = "RuntimePrerequisiteError";
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
exports.RuntimePrerequisiteError = RuntimePrerequisiteError;
|
|
72
|
+
function resolveRuntimeExecutable(command, env = process.env) {
|
|
73
|
+
const value = command.trim();
|
|
74
|
+
if (!value || /[\r\n\0]/.test(value))
|
|
75
|
+
return null;
|
|
76
|
+
const candidates = value.includes(node_path_1.default.sep)
|
|
77
|
+
? [node_path_1.default.resolve(value)]
|
|
78
|
+
: String(env.PATH || "").split(node_path_1.default.delimiter).filter(Boolean).map((directory) => node_path_1.default.join(directory, value));
|
|
79
|
+
return candidates.find((candidate) => {
|
|
80
|
+
try {
|
|
81
|
+
node_fs_1.default.accessSync(candidate, node_fs_1.default.constants.X_OK);
|
|
82
|
+
return node_fs_1.default.statSync(candidate).isFile();
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
}) ?? null;
|
|
88
|
+
}
|
|
89
|
+
function classifyRuntimePrerequisite(runtime, error, executable) {
|
|
90
|
+
const reason = (error instanceof Error ? error.message : String(error)).replace(/[\r\n]+/g, " ").slice(0, 500);
|
|
91
|
+
if (/ENOENT|not found|no such file|spawn .* failed/i.test(reason))
|
|
92
|
+
return {
|
|
93
|
+
runtime, state: "missing", ...(executable ? { executable } : {}), reason,
|
|
94
|
+
nextAction: runtime === "pi" ? "Install Pi and ensure `pi` is on PATH, or set LARKIN_PI_COMMAND." : `Install ${runtime} and ensure it is on PATH.`,
|
|
95
|
+
};
|
|
96
|
+
if (/no authenticated available models|login|credential|unauthenticated|unauthorized|oauth/i.test(reason))
|
|
97
|
+
return {
|
|
98
|
+
runtime, state: "unauthenticated", ...(executable ? { executable } : {}), reason,
|
|
99
|
+
nextAction: runtime === "pi" ? "Run the official `pi` login flow, then retry." : `Authenticate ${runtime}, then retry.`,
|
|
100
|
+
};
|
|
101
|
+
if (/protocol (?:version )?(?:mismatch|unsupported|incompatible)|unsupported (?:rpc|protocol|schema)|schema (?:mismatch|incompatible)|requires (?:a )?newer version/i.test(reason))
|
|
102
|
+
return {
|
|
103
|
+
runtime, state: "incompatible", ...(executable ? { executable } : {}), reason,
|
|
104
|
+
nextAction: runtime === "pi" ? "Upgrade local Pi to a version that supports the documented RPC protocol." : `Upgrade ${runtime}, then retry.`,
|
|
105
|
+
};
|
|
106
|
+
if (/timeout|timed out|unexpected EOF|\bEOF\b|TLS|ECONNRESET|socket hang up|network|temporar(?:y|ily)|unavailable/i.test(reason))
|
|
107
|
+
return {
|
|
108
|
+
runtime, state: "unavailable", ...(executable ? { executable } : {}), reason,
|
|
109
|
+
nextAction: `Retry ${runtime}; Larkin will use its bounded Runtime recreate/backoff policy.`,
|
|
110
|
+
};
|
|
111
|
+
return {
|
|
112
|
+
runtime, state: "unavailable", ...(executable ? { executable } : {}), reason,
|
|
113
|
+
nextAction: `Retry ${runtime}; the failure is not proven to be a protocol incompatibility.`,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
function selectedCommand(options) {
|
|
117
|
+
if (options.command)
|
|
118
|
+
return options.command;
|
|
119
|
+
if (options.runtime === "pi")
|
|
120
|
+
return options.env?.LARKIN_PI_COMMAND || process.env.LARKIN_PI_COMMAND || "pi";
|
|
121
|
+
if (options.runtime === "codex")
|
|
122
|
+
return options.env?.LARKIN_CODEX_COMMAND || process.env.LARKIN_CODEX_COMMAND || "codex";
|
|
123
|
+
return options.env?.LARKIN_CLAUDE_COMMAND || process.env.LARKIN_CLAUDE_COMMAND || "claude";
|
|
124
|
+
}
|
|
125
|
+
function executableVersion(executable, env) {
|
|
126
|
+
const result = (0, node_child_process_1.spawnSync)(executable, ["--version"], { env, encoding: "utf8", timeout: 5_000, maxBuffer: 64 * 1024 });
|
|
127
|
+
if (result.status !== 0)
|
|
128
|
+
return undefined;
|
|
129
|
+
return String(result.stdout || result.stderr || "").replace(/[\r\n]+/g, " ").trim().slice(0, 120) || undefined;
|
|
130
|
+
}
|
|
131
|
+
/** Resolve and handshake through each runtime's structured native control protocol. */
|
|
132
|
+
async function probeNativeRuntimeReadiness(options) {
|
|
133
|
+
const env = { ...process.env, ...options.env };
|
|
134
|
+
if (options.runtime === "pi" && env.LARKIN_PI_DISTRIBUTION === "builtin") {
|
|
135
|
+
try {
|
|
136
|
+
if (!options.agentId || !env.LARKIN_CONFIG_DIR)
|
|
137
|
+
throw new Error("内置 Pi readiness 缺少 Agent/config identity");
|
|
138
|
+
(0, pi_provider_config_js_1.assertBuiltinPiAgentDirectory)((0, pi_provider_config_js_1.piAgentDirectory)(env.LARKIN_CONFIG_DIR, options.agentId));
|
|
139
|
+
return { runtime: "pi", state: "ready", executable: process.execPath, version: `official-pi ${pi_provider_config_js_1.BUNDLED_PI_VERSION} (bundled)` };
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
return { runtime: "pi", state: "unauthenticated", reason: error instanceof Error ? error.message : String(error),
|
|
143
|
+
nextAction: "重新运行 larkin setup,选择内置 Pi 并配置有效 API Key。" };
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const command = selectedCommand(options);
|
|
147
|
+
const executable = resolveRuntimeExecutable(command, env);
|
|
148
|
+
if (!executable)
|
|
149
|
+
return {
|
|
150
|
+
runtime: options.runtime, state: "missing",
|
|
151
|
+
reason: `${command} executable was not found`,
|
|
152
|
+
nextAction: options.runtime === "pi"
|
|
153
|
+
? "Install Pi and ensure `pi` is on PATH, or set LARKIN_PI_COMMAND."
|
|
154
|
+
: `Install ${options.runtime} and ensure it is on PATH.`,
|
|
155
|
+
};
|
|
156
|
+
const version = executableVersion(executable, env);
|
|
157
|
+
try {
|
|
158
|
+
if (options.runtime === "pi") {
|
|
159
|
+
const { discoverPiModelCatalog } = await Promise.resolve().then(() => __importStar(require("./pi-model-catalog.cjs")));
|
|
160
|
+
await discoverPiModelCatalog({ cwd: options.cwd, command: executable, env });
|
|
161
|
+
}
|
|
162
|
+
else if (options.runtime === "codex") {
|
|
163
|
+
const { discoverCodexModelCatalog } = await Promise.resolve().then(() => __importStar(require("./codex-model-catalog.cjs")));
|
|
164
|
+
await discoverCodexModelCatalog({ cwd: options.cwd, command: executable, env });
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
const { discoverClaudeModelCatalog } = await Promise.resolve().then(() => __importStar(require("./claude-model-catalog.cjs")));
|
|
168
|
+
await discoverClaudeModelCatalog({ cwd: options.cwd, command: executable, env });
|
|
169
|
+
}
|
|
170
|
+
return { runtime: options.runtime, state: "ready", executable, ...(version ? { version } : {}) };
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
const classified = error instanceof RuntimePrerequisiteError ? error.readiness
|
|
174
|
+
: classifyRuntimePrerequisite(options.runtime, error, executable);
|
|
175
|
+
return { ...classified, executable, ...(version ? { version } : {}) };
|
|
176
|
+
}
|
|
177
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { spawnSync } from "node:child_process";
|
|
4
|
+
import { assertBuiltinPiAgentDirectory, BUNDLED_PI_VERSION, piAgentDirectory } from "./pi-provider-config.mjs";
|
|
5
|
+
function safeProviderLabel(value) {
|
|
6
|
+
const provider = typeof value === "string" ? value.trim() : "";
|
|
7
|
+
return /^[A-Za-z0-9][A-Za-z0-9._-]{0,79}$/.test(provider) ? provider : null;
|
|
8
|
+
}
|
|
9
|
+
export function providerAuthenticationFailureReadiness(runtime, provider) {
|
|
10
|
+
const label = safeProviderLabel(provider);
|
|
11
|
+
return {
|
|
12
|
+
runtime,
|
|
13
|
+
state: "unauthenticated",
|
|
14
|
+
reason: label
|
|
15
|
+
? `Provider ${label} API-key authentication failed during a Runtime turn.`
|
|
16
|
+
: "Configured provider API-key authentication failed during a Runtime turn.",
|
|
17
|
+
nextAction: "Check the provider login or API-key resolver command, then retry the Agent turn.",
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export class RuntimePrerequisiteError extends Error {
|
|
21
|
+
readiness;
|
|
22
|
+
constructor(readiness) {
|
|
23
|
+
super(readiness.reason || `${readiness.runtime} runtime is ${readiness.state}`);
|
|
24
|
+
this.readiness = readiness;
|
|
25
|
+
this.name = "RuntimePrerequisiteError";
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export function resolveRuntimeExecutable(command, env = process.env) {
|
|
29
|
+
const value = command.trim();
|
|
30
|
+
if (!value || /[\r\n\0]/.test(value))
|
|
31
|
+
return null;
|
|
32
|
+
const candidates = value.includes(path.sep)
|
|
33
|
+
? [path.resolve(value)]
|
|
34
|
+
: String(env.PATH || "").split(path.delimiter).filter(Boolean).map((directory) => path.join(directory, value));
|
|
35
|
+
return candidates.find((candidate) => {
|
|
36
|
+
try {
|
|
37
|
+
fs.accessSync(candidate, fs.constants.X_OK);
|
|
38
|
+
return fs.statSync(candidate).isFile();
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}) ?? null;
|
|
44
|
+
}
|
|
45
|
+
export function classifyRuntimePrerequisite(runtime, error, executable) {
|
|
46
|
+
const reason = (error instanceof Error ? error.message : String(error)).replace(/[\r\n]+/g, " ").slice(0, 500);
|
|
47
|
+
if (/ENOENT|not found|no such file|spawn .* failed/i.test(reason))
|
|
48
|
+
return {
|
|
49
|
+
runtime, state: "missing", ...(executable ? { executable } : {}), reason,
|
|
50
|
+
nextAction: runtime === "pi" ? "Install Pi and ensure `pi` is on PATH, or set LARKIN_PI_COMMAND." : `Install ${runtime} and ensure it is on PATH.`,
|
|
51
|
+
};
|
|
52
|
+
if (/no authenticated available models|login|credential|unauthenticated|unauthorized|oauth/i.test(reason))
|
|
53
|
+
return {
|
|
54
|
+
runtime, state: "unauthenticated", ...(executable ? { executable } : {}), reason,
|
|
55
|
+
nextAction: runtime === "pi" ? "Run the official `pi` login flow, then retry." : `Authenticate ${runtime}, then retry.`,
|
|
56
|
+
};
|
|
57
|
+
if (/protocol (?:version )?(?:mismatch|unsupported|incompatible)|unsupported (?:rpc|protocol|schema)|schema (?:mismatch|incompatible)|requires (?:a )?newer version/i.test(reason))
|
|
58
|
+
return {
|
|
59
|
+
runtime, state: "incompatible", ...(executable ? { executable } : {}), reason,
|
|
60
|
+
nextAction: runtime === "pi" ? "Upgrade local Pi to a version that supports the documented RPC protocol." : `Upgrade ${runtime}, then retry.`,
|
|
61
|
+
};
|
|
62
|
+
if (/timeout|timed out|unexpected EOF|\bEOF\b|TLS|ECONNRESET|socket hang up|network|temporar(?:y|ily)|unavailable/i.test(reason))
|
|
63
|
+
return {
|
|
64
|
+
runtime, state: "unavailable", ...(executable ? { executable } : {}), reason,
|
|
65
|
+
nextAction: `Retry ${runtime}; Larkin will use its bounded Runtime recreate/backoff policy.`,
|
|
66
|
+
};
|
|
67
|
+
return {
|
|
68
|
+
runtime, state: "unavailable", ...(executable ? { executable } : {}), reason,
|
|
69
|
+
nextAction: `Retry ${runtime}; the failure is not proven to be a protocol incompatibility.`,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function selectedCommand(options) {
|
|
73
|
+
if (options.command)
|
|
74
|
+
return options.command;
|
|
75
|
+
if (options.runtime === "pi")
|
|
76
|
+
return options.env?.LARKIN_PI_COMMAND || process.env.LARKIN_PI_COMMAND || "pi";
|
|
77
|
+
if (options.runtime === "codex")
|
|
78
|
+
return options.env?.LARKIN_CODEX_COMMAND || process.env.LARKIN_CODEX_COMMAND || "codex";
|
|
79
|
+
return options.env?.LARKIN_CLAUDE_COMMAND || process.env.LARKIN_CLAUDE_COMMAND || "claude";
|
|
80
|
+
}
|
|
81
|
+
function executableVersion(executable, env) {
|
|
82
|
+
const result = spawnSync(executable, ["--version"], { env, encoding: "utf8", timeout: 5_000, maxBuffer: 64 * 1024 });
|
|
83
|
+
if (result.status !== 0)
|
|
84
|
+
return undefined;
|
|
85
|
+
return String(result.stdout || result.stderr || "").replace(/[\r\n]+/g, " ").trim().slice(0, 120) || undefined;
|
|
86
|
+
}
|
|
87
|
+
/** Resolve and handshake through each runtime's structured native control protocol. */
|
|
88
|
+
export async function probeNativeRuntimeReadiness(options) {
|
|
89
|
+
const env = { ...process.env, ...options.env };
|
|
90
|
+
if (options.runtime === "pi" && env.LARKIN_PI_DISTRIBUTION === "builtin") {
|
|
91
|
+
try {
|
|
92
|
+
if (!options.agentId || !env.LARKIN_CONFIG_DIR)
|
|
93
|
+
throw new Error("内置 Pi readiness 缺少 Agent/config identity");
|
|
94
|
+
assertBuiltinPiAgentDirectory(piAgentDirectory(env.LARKIN_CONFIG_DIR, options.agentId));
|
|
95
|
+
return { runtime: "pi", state: "ready", executable: process.execPath, version: `official-pi ${BUNDLED_PI_VERSION} (bundled)` };
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
return { runtime: "pi", state: "unauthenticated", reason: error instanceof Error ? error.message : String(error),
|
|
99
|
+
nextAction: "重新运行 larkin setup,选择内置 Pi 并配置有效 API Key。" };
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const command = selectedCommand(options);
|
|
103
|
+
const executable = resolveRuntimeExecutable(command, env);
|
|
104
|
+
if (!executable)
|
|
105
|
+
return {
|
|
106
|
+
runtime: options.runtime, state: "missing",
|
|
107
|
+
reason: `${command} executable was not found`,
|
|
108
|
+
nextAction: options.runtime === "pi"
|
|
109
|
+
? "Install Pi and ensure `pi` is on PATH, or set LARKIN_PI_COMMAND."
|
|
110
|
+
: `Install ${options.runtime} and ensure it is on PATH.`,
|
|
111
|
+
};
|
|
112
|
+
const version = executableVersion(executable, env);
|
|
113
|
+
try {
|
|
114
|
+
if (options.runtime === "pi") {
|
|
115
|
+
const { discoverPiModelCatalog } = await import("./pi-model-catalog.mjs");
|
|
116
|
+
await discoverPiModelCatalog({ cwd: options.cwd, command: executable, env });
|
|
117
|
+
}
|
|
118
|
+
else if (options.runtime === "codex") {
|
|
119
|
+
const { discoverCodexModelCatalog } = await import("./codex-model-catalog.mjs");
|
|
120
|
+
await discoverCodexModelCatalog({ cwd: options.cwd, command: executable, env });
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
const { discoverClaudeModelCatalog } = await import("./claude-model-catalog.mjs");
|
|
124
|
+
await discoverClaudeModelCatalog({ cwd: options.cwd, command: executable, env });
|
|
125
|
+
}
|
|
126
|
+
return { runtime: options.runtime, state: "ready", executable, ...(version ? { version } : {}) };
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
const classified = error instanceof RuntimePrerequisiteError ? error.readiness
|
|
130
|
+
: classifyRuntimePrerequisite(options.runtime, error, executable);
|
|
131
|
+
return { ...classified, executable, ...(version ? { version } : {}) };
|
|
132
|
+
}
|
|
133
|
+
}
|