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,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.OFFICIAL_LARK_CLI_INSTALL = exports.OFFICIAL_LARK_CLI_VERSION = void 0;
|
|
7
|
+
exports.probeOfficialLarkCli = probeOfficialLarkCli;
|
|
8
|
+
exports.resolveOfficialLarkCli = resolveOfficialLarkCli;
|
|
9
|
+
exports.installOfficialLarkCli = installOfficialLarkCli;
|
|
10
|
+
exports.ensureOfficialLarkCliForSetup = ensureOfficialLarkCliForSetup;
|
|
11
|
+
const node_child_process_1 = require("node:child_process");
|
|
12
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
13
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
14
|
+
exports.OFFICIAL_LARK_CLI_VERSION = "1.0.79";
|
|
15
|
+
exports.OFFICIAL_LARK_CLI_INSTALL = `npm install --global @larksuite/cli@${exports.OFFICIAL_LARK_CLI_VERSION}`;
|
|
16
|
+
function loginShellPath(dependencies) {
|
|
17
|
+
const env = dependencies.env ?? process.env;
|
|
18
|
+
const shell = dependencies.shell || env.SHELL || "/bin/sh";
|
|
19
|
+
const result = (dependencies.spawn ?? node_child_process_1.spawnSync)(shell, ["-lc", "command -v lark-cli 2>/dev/null"], {
|
|
20
|
+
encoding: "utf8", env,
|
|
21
|
+
});
|
|
22
|
+
if (result.status !== 0 || result.error)
|
|
23
|
+
return null;
|
|
24
|
+
const candidate = String(result.stdout || "").split(/\r?\n/).map((line) => line.trim()).find(Boolean) || "";
|
|
25
|
+
return node_path_1.default.isAbsolute(candidate) ? node_path_1.default.resolve(candidate) : null;
|
|
26
|
+
}
|
|
27
|
+
function compatibleVersion(version) {
|
|
28
|
+
const parse = (value) => {
|
|
29
|
+
const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(value);
|
|
30
|
+
return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : null;
|
|
31
|
+
};
|
|
32
|
+
const actual = parse(version);
|
|
33
|
+
const minimum = parse(exports.OFFICIAL_LARK_CLI_VERSION);
|
|
34
|
+
if (!actual)
|
|
35
|
+
return false;
|
|
36
|
+
return actual[0] > minimum[0] || (actual[0] === minimum[0]
|
|
37
|
+
&& (actual[1] > minimum[1] || (actual[1] === minimum[1] && actual[2] >= minimum[2])));
|
|
38
|
+
}
|
|
39
|
+
function officialPackage(executable) {
|
|
40
|
+
let resolved;
|
|
41
|
+
try {
|
|
42
|
+
resolved = node_fs_1.default.realpathSync(executable);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
let directory = node_path_1.default.dirname(resolved);
|
|
48
|
+
while (directory !== node_path_1.default.dirname(directory)) {
|
|
49
|
+
const manifestFile = node_path_1.default.join(directory, "package.json");
|
|
50
|
+
try {
|
|
51
|
+
const manifest = JSON.parse(node_fs_1.default.readFileSync(manifestFile, "utf8"));
|
|
52
|
+
const bin = typeof manifest.bin === "string" ? manifest.bin : manifest.bin?.["lark-cli"];
|
|
53
|
+
if (manifest.name === "@larksuite/cli" && typeof manifest.version === "string" && /^\d+\.\d+\.\d+$/.test(manifest.version) && bin) {
|
|
54
|
+
const packageRoot = node_fs_1.default.realpathSync(directory);
|
|
55
|
+
const requested = node_path_1.default.resolve(packageRoot, bin);
|
|
56
|
+
const relative = node_path_1.default.relative(packageRoot, requested);
|
|
57
|
+
if ((relative === "" || (!relative.startsWith(`..${node_path_1.default.sep}`) && relative !== ".."))
|
|
58
|
+
&& node_fs_1.default.realpathSync(requested) === resolved) {
|
|
59
|
+
return { command: node_path_1.default.resolve(executable), argsPrefix: [], version: manifest.version };
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch { /* Continue towards the filesystem root. */ }
|
|
64
|
+
directory = node_path_1.default.dirname(directory);
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
function probeOfficialLarkCli(dependencies = {}) {
|
|
69
|
+
const executable = loginShellPath(dependencies);
|
|
70
|
+
if (!executable)
|
|
71
|
+
return {
|
|
72
|
+
state: "missing",
|
|
73
|
+
reason: "真实 login shell 找不到官方 lark-cli",
|
|
74
|
+
nextAction: `运行 larkin setup,并确认执行:${exports.OFFICIAL_LARK_CLI_INSTALL}`,
|
|
75
|
+
};
|
|
76
|
+
const command = officialPackage(executable);
|
|
77
|
+
if (!command)
|
|
78
|
+
return {
|
|
79
|
+
state: "conflict",
|
|
80
|
+
reason: `真实 login shell 的 lark-cli 不是兼容的官方 @larksuite/cli ${exports.OFFICIAL_LARK_CLI_VERSION}: ${executable}`,
|
|
81
|
+
nextAction: "移除或调整冲突入口后重新运行 larkin setup",
|
|
82
|
+
};
|
|
83
|
+
if (!compatibleVersion(command.version))
|
|
84
|
+
return {
|
|
85
|
+
state: "outdated",
|
|
86
|
+
reason: `真实 login shell 的官方 @larksuite/cli ${command.version} 低于最低兼容版本 ${exports.OFFICIAL_LARK_CLI_VERSION}`,
|
|
87
|
+
nextAction: `升级:${exports.OFFICIAL_LARK_CLI_INSTALL}`,
|
|
88
|
+
};
|
|
89
|
+
const version = (dependencies.spawn ?? node_child_process_1.spawnSync)(command.command, ["--version"], {
|
|
90
|
+
encoding: "utf8", env: dependencies.env ?? process.env,
|
|
91
|
+
});
|
|
92
|
+
if (version.status !== 0 || version.error || !String(version.stdout || "").includes(command.version))
|
|
93
|
+
return {
|
|
94
|
+
state: "outdated",
|
|
95
|
+
reason: `官方 lark-cli 版本执行验证失败: ${command.command}`,
|
|
96
|
+
nextAction: `重新安装:${exports.OFFICIAL_LARK_CLI_INSTALL}`,
|
|
97
|
+
};
|
|
98
|
+
const bindHelp = (dependencies.spawn ?? node_child_process_1.spawnSync)(command.command, ["config", "bind", "--help"], {
|
|
99
|
+
encoding: "utf8", env: dependencies.env ?? process.env,
|
|
100
|
+
});
|
|
101
|
+
const bindText = `${bindHelp.stdout || ""}\n${bindHelp.stderr || ""}`;
|
|
102
|
+
if (bindHelp.status !== 0 || bindHelp.error || !/--source/.test(bindText) || !/lark-channel/.test(bindText) || !/--identity/.test(bindText))
|
|
103
|
+
return {
|
|
104
|
+
state: "conflict",
|
|
105
|
+
reason: `官方 lark-cli 缺少 lark-channel bot-only bind 能力: ${command.command}`,
|
|
106
|
+
nextAction: `升级:${exports.OFFICIAL_LARK_CLI_INSTALL}`,
|
|
107
|
+
};
|
|
108
|
+
return { state: "ready", command };
|
|
109
|
+
}
|
|
110
|
+
function resolveOfficialLarkCli(dependencies = {}) {
|
|
111
|
+
const result = probeOfficialLarkCli(dependencies);
|
|
112
|
+
if (result.state !== "ready")
|
|
113
|
+
throw new Error(`${result.reason};${result.nextAction}`);
|
|
114
|
+
return result.command;
|
|
115
|
+
}
|
|
116
|
+
function installOfficialLarkCli(dependencies = {}) {
|
|
117
|
+
const run = dependencies.spawn ?? node_child_process_1.spawnSync;
|
|
118
|
+
const result = run("npm", ["install", "--global", `@larksuite/cli@${exports.OFFICIAL_LARK_CLI_VERSION}`], {
|
|
119
|
+
encoding: "utf8", env: dependencies.env ?? process.env, stdio: "inherit",
|
|
120
|
+
});
|
|
121
|
+
if (result.status !== 0 || result.error)
|
|
122
|
+
throw new Error(`官方 lark-cli 安装失败(exit=${result.status ?? "none"})`);
|
|
123
|
+
return resolveOfficialLarkCli(dependencies);
|
|
124
|
+
}
|
|
125
|
+
async function ensureOfficialLarkCliForSetup(input) {
|
|
126
|
+
const probe = probeOfficialLarkCli(input);
|
|
127
|
+
if (probe.state === "ready")
|
|
128
|
+
return { command: probe.command, installed: false };
|
|
129
|
+
if (probe.state === "conflict")
|
|
130
|
+
throw new Error(`${probe.reason};${probe.nextAction}`);
|
|
131
|
+
if (!input.interactive) {
|
|
132
|
+
throw new Error(`${probe.reason};非交互 setup 不会安装或升级依赖。请在终端运行 larkin setup,并确认:${exports.OFFICIAL_LARK_CLI_INSTALL}`);
|
|
133
|
+
}
|
|
134
|
+
if (!await input.confirmInstall(exports.OFFICIAL_LARK_CLI_INSTALL)) {
|
|
135
|
+
throw new Error("未获得明确同意;没有安装官方 lark-cli,也没有写入 Agent 配置");
|
|
136
|
+
}
|
|
137
|
+
return { command: installOfficialLarkCli(input), installed: true };
|
|
138
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
export const OFFICIAL_LARK_CLI_VERSION = "1.0.79";
|
|
5
|
+
export const OFFICIAL_LARK_CLI_INSTALL = `npm install --global @larksuite/cli@${OFFICIAL_LARK_CLI_VERSION}`;
|
|
6
|
+
function loginShellPath(dependencies) {
|
|
7
|
+
const env = dependencies.env ?? process.env;
|
|
8
|
+
const shell = dependencies.shell || env.SHELL || "/bin/sh";
|
|
9
|
+
const result = (dependencies.spawn ?? spawnSync)(shell, ["-lc", "command -v lark-cli 2>/dev/null"], {
|
|
10
|
+
encoding: "utf8", env,
|
|
11
|
+
});
|
|
12
|
+
if (result.status !== 0 || result.error)
|
|
13
|
+
return null;
|
|
14
|
+
const candidate = String(result.stdout || "").split(/\r?\n/).map((line) => line.trim()).find(Boolean) || "";
|
|
15
|
+
return path.isAbsolute(candidate) ? path.resolve(candidate) : null;
|
|
16
|
+
}
|
|
17
|
+
function compatibleVersion(version) {
|
|
18
|
+
const parse = (value) => {
|
|
19
|
+
const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(value);
|
|
20
|
+
return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : null;
|
|
21
|
+
};
|
|
22
|
+
const actual = parse(version);
|
|
23
|
+
const minimum = parse(OFFICIAL_LARK_CLI_VERSION);
|
|
24
|
+
if (!actual)
|
|
25
|
+
return false;
|
|
26
|
+
return actual[0] > minimum[0] || (actual[0] === minimum[0]
|
|
27
|
+
&& (actual[1] > minimum[1] || (actual[1] === minimum[1] && actual[2] >= minimum[2])));
|
|
28
|
+
}
|
|
29
|
+
function officialPackage(executable) {
|
|
30
|
+
let resolved;
|
|
31
|
+
try {
|
|
32
|
+
resolved = fs.realpathSync(executable);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
let directory = path.dirname(resolved);
|
|
38
|
+
while (directory !== path.dirname(directory)) {
|
|
39
|
+
const manifestFile = path.join(directory, "package.json");
|
|
40
|
+
try {
|
|
41
|
+
const manifest = JSON.parse(fs.readFileSync(manifestFile, "utf8"));
|
|
42
|
+
const bin = typeof manifest.bin === "string" ? manifest.bin : manifest.bin?.["lark-cli"];
|
|
43
|
+
if (manifest.name === "@larksuite/cli" && typeof manifest.version === "string" && /^\d+\.\d+\.\d+$/.test(manifest.version) && bin) {
|
|
44
|
+
const packageRoot = fs.realpathSync(directory);
|
|
45
|
+
const requested = path.resolve(packageRoot, bin);
|
|
46
|
+
const relative = path.relative(packageRoot, requested);
|
|
47
|
+
if ((relative === "" || (!relative.startsWith(`..${path.sep}`) && relative !== ".."))
|
|
48
|
+
&& fs.realpathSync(requested) === resolved) {
|
|
49
|
+
return { command: path.resolve(executable), argsPrefix: [], version: manifest.version };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch { /* Continue towards the filesystem root. */ }
|
|
54
|
+
directory = path.dirname(directory);
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
export function probeOfficialLarkCli(dependencies = {}) {
|
|
59
|
+
const executable = loginShellPath(dependencies);
|
|
60
|
+
if (!executable)
|
|
61
|
+
return {
|
|
62
|
+
state: "missing",
|
|
63
|
+
reason: "真实 login shell 找不到官方 lark-cli",
|
|
64
|
+
nextAction: `运行 larkin setup,并确认执行:${OFFICIAL_LARK_CLI_INSTALL}`,
|
|
65
|
+
};
|
|
66
|
+
const command = officialPackage(executable);
|
|
67
|
+
if (!command)
|
|
68
|
+
return {
|
|
69
|
+
state: "conflict",
|
|
70
|
+
reason: `真实 login shell 的 lark-cli 不是兼容的官方 @larksuite/cli ${OFFICIAL_LARK_CLI_VERSION}: ${executable}`,
|
|
71
|
+
nextAction: "移除或调整冲突入口后重新运行 larkin setup",
|
|
72
|
+
};
|
|
73
|
+
if (!compatibleVersion(command.version))
|
|
74
|
+
return {
|
|
75
|
+
state: "outdated",
|
|
76
|
+
reason: `真实 login shell 的官方 @larksuite/cli ${command.version} 低于最低兼容版本 ${OFFICIAL_LARK_CLI_VERSION}`,
|
|
77
|
+
nextAction: `升级:${OFFICIAL_LARK_CLI_INSTALL}`,
|
|
78
|
+
};
|
|
79
|
+
const version = (dependencies.spawn ?? spawnSync)(command.command, ["--version"], {
|
|
80
|
+
encoding: "utf8", env: dependencies.env ?? process.env,
|
|
81
|
+
});
|
|
82
|
+
if (version.status !== 0 || version.error || !String(version.stdout || "").includes(command.version))
|
|
83
|
+
return {
|
|
84
|
+
state: "outdated",
|
|
85
|
+
reason: `官方 lark-cli 版本执行验证失败: ${command.command}`,
|
|
86
|
+
nextAction: `重新安装:${OFFICIAL_LARK_CLI_INSTALL}`,
|
|
87
|
+
};
|
|
88
|
+
const bindHelp = (dependencies.spawn ?? spawnSync)(command.command, ["config", "bind", "--help"], {
|
|
89
|
+
encoding: "utf8", env: dependencies.env ?? process.env,
|
|
90
|
+
});
|
|
91
|
+
const bindText = `${bindHelp.stdout || ""}\n${bindHelp.stderr || ""}`;
|
|
92
|
+
if (bindHelp.status !== 0 || bindHelp.error || !/--source/.test(bindText) || !/lark-channel/.test(bindText) || !/--identity/.test(bindText))
|
|
93
|
+
return {
|
|
94
|
+
state: "conflict",
|
|
95
|
+
reason: `官方 lark-cli 缺少 lark-channel bot-only bind 能力: ${command.command}`,
|
|
96
|
+
nextAction: `升级:${OFFICIAL_LARK_CLI_INSTALL}`,
|
|
97
|
+
};
|
|
98
|
+
return { state: "ready", command };
|
|
99
|
+
}
|
|
100
|
+
export function resolveOfficialLarkCli(dependencies = {}) {
|
|
101
|
+
const result = probeOfficialLarkCli(dependencies);
|
|
102
|
+
if (result.state !== "ready")
|
|
103
|
+
throw new Error(`${result.reason};${result.nextAction}`);
|
|
104
|
+
return result.command;
|
|
105
|
+
}
|
|
106
|
+
export function installOfficialLarkCli(dependencies = {}) {
|
|
107
|
+
const run = dependencies.spawn ?? spawnSync;
|
|
108
|
+
const result = run("npm", ["install", "--global", `@larksuite/cli@${OFFICIAL_LARK_CLI_VERSION}`], {
|
|
109
|
+
encoding: "utf8", env: dependencies.env ?? process.env, stdio: "inherit",
|
|
110
|
+
});
|
|
111
|
+
if (result.status !== 0 || result.error)
|
|
112
|
+
throw new Error(`官方 lark-cli 安装失败(exit=${result.status ?? "none"})`);
|
|
113
|
+
return resolveOfficialLarkCli(dependencies);
|
|
114
|
+
}
|
|
115
|
+
export async function ensureOfficialLarkCliForSetup(input) {
|
|
116
|
+
const probe = probeOfficialLarkCli(input);
|
|
117
|
+
if (probe.state === "ready")
|
|
118
|
+
return { command: probe.command, installed: false };
|
|
119
|
+
if (probe.state === "conflict")
|
|
120
|
+
throw new Error(`${probe.reason};${probe.nextAction}`);
|
|
121
|
+
if (!input.interactive) {
|
|
122
|
+
throw new Error(`${probe.reason};非交互 setup 不会安装或升级依赖。请在终端运行 larkin setup,并确认:${OFFICIAL_LARK_CLI_INSTALL}`);
|
|
123
|
+
}
|
|
124
|
+
if (!await input.confirmInstall(OFFICIAL_LARK_CLI_INSTALL)) {
|
|
125
|
+
throw new Error("未获得明确同意;没有安装官方 lark-cli,也没有写入 Agent 配置");
|
|
126
|
+
}
|
|
127
|
+
return { command: installOfficialLarkCli(input), installed: true };
|
|
128
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import * as larkinConfig from "../platform/config.mjs";
|
|
2
|
+
import { beginBuiltinPiCredentialTransaction, createOfficialPiCredentialRuntime, createOfficialPiLogoutRuntime, logoutOfficialPiProvider, officialPiAuthStatus, } from "../runtime/pi-official-auth.mjs";
|
|
3
|
+
const APP_ID = /^cli_[A-Za-z0-9]+$/;
|
|
4
|
+
function flag(args, name) {
|
|
5
|
+
const index = args.indexOf(name);
|
|
6
|
+
return index >= 0 ? args[index + 1] : undefined;
|
|
7
|
+
}
|
|
8
|
+
export async function main(args = process.argv.slice(2), env = process.env) {
|
|
9
|
+
const action = args[0] || "status";
|
|
10
|
+
const json = args.includes("--json");
|
|
11
|
+
const requestedAgent = flag(args, "--agent");
|
|
12
|
+
let index = action === "logout" ? 2 : 1;
|
|
13
|
+
let valid = action === "status" || action === "logout";
|
|
14
|
+
while (valid && index < args.length) {
|
|
15
|
+
const argument = args[index];
|
|
16
|
+
if (argument === "--json" && action === "status") {
|
|
17
|
+
index += 1;
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
if (argument === "--agent" && args[index + 1]) {
|
|
21
|
+
index += 2;
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
valid = false;
|
|
25
|
+
}
|
|
26
|
+
if (!valid) {
|
|
27
|
+
throw new Error("Usage: larkin pi-auth status [--agent <App ID>] [--json] | larkin pi-auth logout <provider> [--agent <App ID>]");
|
|
28
|
+
}
|
|
29
|
+
const loaded = larkinConfig.loadConfig(env);
|
|
30
|
+
const agentId = requestedAgent || loaded.config.activeAgent || undefined;
|
|
31
|
+
if (!agentId || !APP_ID.test(agentId))
|
|
32
|
+
throw new Error("请用 --agent <App ID> 选择 Agent");
|
|
33
|
+
const agent = loaded.config.agents[agentId];
|
|
34
|
+
if (!agent)
|
|
35
|
+
throw new Error(`Agent ${agentId} 不存在`);
|
|
36
|
+
if (agent.runtime !== "pi" || agent.piDistribution !== "builtin")
|
|
37
|
+
throw new Error(`Agent ${agentId} 不是内置 Pi`);
|
|
38
|
+
if (action === "status") {
|
|
39
|
+
const runtime = await createOfficialPiCredentialRuntime(loaded.configDir, agentId);
|
|
40
|
+
const statuses = await officialPiAuthStatus(runtime);
|
|
41
|
+
if (json)
|
|
42
|
+
console.log(JSON.stringify({ agentId, credentials: statuses }));
|
|
43
|
+
else if (statuses.length === 0)
|
|
44
|
+
console.log(`Agent ${agentId} 尚无已配置的官方 Pi credential`);
|
|
45
|
+
else {
|
|
46
|
+
console.log(`Agent ${agentId} 官方 Pi credential:`);
|
|
47
|
+
for (const entry of statuses)
|
|
48
|
+
console.log(` ${entry.providerName} (${entry.providerId}): ${entry.credentialType}/${entry.source}${entry.stored ? " [stored]" : " [ambient]"}`);
|
|
49
|
+
}
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const providerId = args[1];
|
|
53
|
+
if (!providerId || providerId.startsWith("--") || !/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(providerId)) {
|
|
54
|
+
throw new Error("logout 需要安全的 provider ID");
|
|
55
|
+
}
|
|
56
|
+
const transaction = beginBuiltinPiCredentialTransaction(loaded.configDir, agentId);
|
|
57
|
+
try {
|
|
58
|
+
const runtime = await createOfficialPiLogoutRuntime(loaded.configDir, agentId);
|
|
59
|
+
await logoutOfficialPiProvider(runtime, providerId);
|
|
60
|
+
transaction.commit();
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
transaction.rollback();
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
console.log(`Agent ${agentId} 已退出 ${providerId};其他 provider 未修改`);
|
|
67
|
+
}
|