larkway 0.3.33 → 0.3.35
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 +28 -1
- package/README.zh.md +25 -1
- package/dist/cli/index.js +2298 -71
- package/dist/main.js +11754 -6261
- package/dist/web/public/app.js +121 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -43,6 +43,89 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
43
43
|
mod
|
|
44
44
|
));
|
|
45
45
|
|
|
46
|
+
// src/config/paths.ts
|
|
47
|
+
var paths_exports = {};
|
|
48
|
+
__export(paths_exports, {
|
|
49
|
+
LEGACY_BOT_ID: () => LEGACY_BOT_ID,
|
|
50
|
+
larkwayHome: () => larkwayHome,
|
|
51
|
+
resolveAgentSessionPath: () => resolveAgentSessionPath,
|
|
52
|
+
resolveAgentWorkspacePath: () => resolveAgentWorkspacePath,
|
|
53
|
+
resolveAgentWorkspacePathFromHome: () => resolveAgentWorkspacePathFromHome,
|
|
54
|
+
resolveAgentWorkspaceReposDir: () => resolveAgentWorkspaceReposDir,
|
|
55
|
+
resolveAgentWorkspaceSessionsDir: () => resolveAgentWorkspaceSessionsDir,
|
|
56
|
+
resolveCandidateAlertsPath: () => resolveCandidateAlertsPath,
|
|
57
|
+
resolveLarkwayDir: () => resolveLarkwayDir,
|
|
58
|
+
resolveLogsDir: () => resolveLogsDir,
|
|
59
|
+
resolveSessionsPath: () => resolveSessionsPath,
|
|
60
|
+
resolveTaskHandlesPath: () => resolveTaskHandlesPath,
|
|
61
|
+
resolveTaskTeamRegistryPath: () => resolveTaskTeamRegistryPath,
|
|
62
|
+
resolveWorktreePath: () => resolveWorktreePath,
|
|
63
|
+
resolveWorktreesDir: () => resolveWorktreesDir
|
|
64
|
+
});
|
|
65
|
+
import { homedir } from "node:os";
|
|
66
|
+
import { join, resolve } from "node:path";
|
|
67
|
+
function larkwayHome() {
|
|
68
|
+
const env = process.env.LARKWAY_HOME;
|
|
69
|
+
if (env && env.trim() !== "") return resolve(env);
|
|
70
|
+
return join(homedir(), ".larkway");
|
|
71
|
+
}
|
|
72
|
+
function resolveLarkwayDir(botId) {
|
|
73
|
+
if (botId === void 0 || botId === LEGACY_BOT_ID) {
|
|
74
|
+
return larkwayHome();
|
|
75
|
+
}
|
|
76
|
+
return join(larkwayHome(), botId);
|
|
77
|
+
}
|
|
78
|
+
function resolveSessionsPath(botId) {
|
|
79
|
+
return join(resolveLarkwayDir(botId), "sessions.json");
|
|
80
|
+
}
|
|
81
|
+
function resolveWorktreePath(botId, threadId) {
|
|
82
|
+
return join(resolveLarkwayDir(botId), "worktrees", threadId);
|
|
83
|
+
}
|
|
84
|
+
function resolveWorktreesDir(botId) {
|
|
85
|
+
return join(resolveLarkwayDir(botId), "worktrees");
|
|
86
|
+
}
|
|
87
|
+
function resolveLogsDir(botId) {
|
|
88
|
+
return join(resolveLarkwayDir(botId), "logs");
|
|
89
|
+
}
|
|
90
|
+
function resolveTaskHandlesPath(botId) {
|
|
91
|
+
return join(resolveLarkwayDir(botId), "task-handles.json");
|
|
92
|
+
}
|
|
93
|
+
function resolveTaskTeamRegistryPath() {
|
|
94
|
+
return join(larkwayHome(), "task-team.json");
|
|
95
|
+
}
|
|
96
|
+
function resolveCandidateAlertsPath(tasklistGuid) {
|
|
97
|
+
return join(larkwayHome(), `candidate-alerts-${tasklistGuid}.json`);
|
|
98
|
+
}
|
|
99
|
+
function assertSafePathSegment(label, value) {
|
|
100
|
+
if (!/^[A-Za-z0-9_-]+$/.test(value)) {
|
|
101
|
+
throw new Error(`${label} must be a safe path segment`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function resolveAgentWorkspacePathFromHome(home, agentId) {
|
|
105
|
+
assertSafePathSegment("agentId", agentId);
|
|
106
|
+
return join(home, "agents", agentId, "workspace");
|
|
107
|
+
}
|
|
108
|
+
function resolveAgentWorkspacePath(agentId) {
|
|
109
|
+
return resolveAgentWorkspacePathFromHome(larkwayHome(), agentId);
|
|
110
|
+
}
|
|
111
|
+
function resolveAgentWorkspaceSessionsDir(agentId) {
|
|
112
|
+
return join(resolveAgentWorkspacePath(agentId), "sessions");
|
|
113
|
+
}
|
|
114
|
+
function resolveAgentSessionPath(agentId, threadId) {
|
|
115
|
+
assertSafePathSegment("threadId", threadId);
|
|
116
|
+
return join(resolveAgentWorkspaceSessionsDir(agentId), threadId);
|
|
117
|
+
}
|
|
118
|
+
function resolveAgentWorkspaceReposDir(agentId) {
|
|
119
|
+
return join(resolveAgentWorkspacePath(agentId), "repos");
|
|
120
|
+
}
|
|
121
|
+
var LEGACY_BOT_ID;
|
|
122
|
+
var init_paths = __esm({
|
|
123
|
+
"src/config/paths.ts"() {
|
|
124
|
+
"use strict";
|
|
125
|
+
LEGACY_BOT_ID = "v1-default";
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
|
|
46
129
|
// node_modules/.pnpm/dotenv@16.6.1/node_modules/dotenv/package.json
|
|
47
130
|
var require_package = __commonJS({
|
|
48
131
|
"node_modules/.pnpm/dotenv@16.6.1/node_modules/dotenv/package.json"(exports, module) {
|
|
@@ -10740,6 +10823,769 @@ var require_proxy_from_env = __commonJS({
|
|
|
10740
10823
|
}
|
|
10741
10824
|
});
|
|
10742
10825
|
|
|
10826
|
+
// node_modules/.pnpm/ms@2.1.3/node_modules/ms/index.js
|
|
10827
|
+
var require_ms = __commonJS({
|
|
10828
|
+
"node_modules/.pnpm/ms@2.1.3/node_modules/ms/index.js"(exports, module) {
|
|
10829
|
+
var s = 1e3;
|
|
10830
|
+
var m = s * 60;
|
|
10831
|
+
var h = m * 60;
|
|
10832
|
+
var d = h * 24;
|
|
10833
|
+
var w = d * 7;
|
|
10834
|
+
var y = d * 365.25;
|
|
10835
|
+
module.exports = function(val, options) {
|
|
10836
|
+
options = options || {};
|
|
10837
|
+
var type2 = typeof val;
|
|
10838
|
+
if (type2 === "string" && val.length > 0) {
|
|
10839
|
+
return parse(val);
|
|
10840
|
+
} else if (type2 === "number" && isFinite(val)) {
|
|
10841
|
+
return options.long ? fmtLong(val) : fmtShort(val);
|
|
10842
|
+
}
|
|
10843
|
+
throw new Error(
|
|
10844
|
+
"val is not a non-empty string or a valid number. val=" + JSON.stringify(val)
|
|
10845
|
+
);
|
|
10846
|
+
};
|
|
10847
|
+
function parse(str2) {
|
|
10848
|
+
str2 = String(str2);
|
|
10849
|
+
if (str2.length > 100) {
|
|
10850
|
+
return;
|
|
10851
|
+
}
|
|
10852
|
+
var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(
|
|
10853
|
+
str2
|
|
10854
|
+
);
|
|
10855
|
+
if (!match) {
|
|
10856
|
+
return;
|
|
10857
|
+
}
|
|
10858
|
+
var n = parseFloat(match[1]);
|
|
10859
|
+
var type2 = (match[2] || "ms").toLowerCase();
|
|
10860
|
+
switch (type2) {
|
|
10861
|
+
case "years":
|
|
10862
|
+
case "year":
|
|
10863
|
+
case "yrs":
|
|
10864
|
+
case "yr":
|
|
10865
|
+
case "y":
|
|
10866
|
+
return n * y;
|
|
10867
|
+
case "weeks":
|
|
10868
|
+
case "week":
|
|
10869
|
+
case "w":
|
|
10870
|
+
return n * w;
|
|
10871
|
+
case "days":
|
|
10872
|
+
case "day":
|
|
10873
|
+
case "d":
|
|
10874
|
+
return n * d;
|
|
10875
|
+
case "hours":
|
|
10876
|
+
case "hour":
|
|
10877
|
+
case "hrs":
|
|
10878
|
+
case "hr":
|
|
10879
|
+
case "h":
|
|
10880
|
+
return n * h;
|
|
10881
|
+
case "minutes":
|
|
10882
|
+
case "minute":
|
|
10883
|
+
case "mins":
|
|
10884
|
+
case "min":
|
|
10885
|
+
case "m":
|
|
10886
|
+
return n * m;
|
|
10887
|
+
case "seconds":
|
|
10888
|
+
case "second":
|
|
10889
|
+
case "secs":
|
|
10890
|
+
case "sec":
|
|
10891
|
+
case "s":
|
|
10892
|
+
return n * s;
|
|
10893
|
+
case "milliseconds":
|
|
10894
|
+
case "millisecond":
|
|
10895
|
+
case "msecs":
|
|
10896
|
+
case "msec":
|
|
10897
|
+
case "ms":
|
|
10898
|
+
return n;
|
|
10899
|
+
default:
|
|
10900
|
+
return void 0;
|
|
10901
|
+
}
|
|
10902
|
+
}
|
|
10903
|
+
function fmtShort(ms) {
|
|
10904
|
+
var msAbs = Math.abs(ms);
|
|
10905
|
+
if (msAbs >= d) {
|
|
10906
|
+
return Math.round(ms / d) + "d";
|
|
10907
|
+
}
|
|
10908
|
+
if (msAbs >= h) {
|
|
10909
|
+
return Math.round(ms / h) + "h";
|
|
10910
|
+
}
|
|
10911
|
+
if (msAbs >= m) {
|
|
10912
|
+
return Math.round(ms / m) + "m";
|
|
10913
|
+
}
|
|
10914
|
+
if (msAbs >= s) {
|
|
10915
|
+
return Math.round(ms / s) + "s";
|
|
10916
|
+
}
|
|
10917
|
+
return ms + "ms";
|
|
10918
|
+
}
|
|
10919
|
+
function fmtLong(ms) {
|
|
10920
|
+
var msAbs = Math.abs(ms);
|
|
10921
|
+
if (msAbs >= d) {
|
|
10922
|
+
return plural(ms, msAbs, d, "day");
|
|
10923
|
+
}
|
|
10924
|
+
if (msAbs >= h) {
|
|
10925
|
+
return plural(ms, msAbs, h, "hour");
|
|
10926
|
+
}
|
|
10927
|
+
if (msAbs >= m) {
|
|
10928
|
+
return plural(ms, msAbs, m, "minute");
|
|
10929
|
+
}
|
|
10930
|
+
if (msAbs >= s) {
|
|
10931
|
+
return plural(ms, msAbs, s, "second");
|
|
10932
|
+
}
|
|
10933
|
+
return ms + " ms";
|
|
10934
|
+
}
|
|
10935
|
+
function plural(ms, msAbs, n, name) {
|
|
10936
|
+
var isPlural = msAbs >= n * 1.5;
|
|
10937
|
+
return Math.round(ms / n) + " " + name + (isPlural ? "s" : "");
|
|
10938
|
+
}
|
|
10939
|
+
}
|
|
10940
|
+
});
|
|
10941
|
+
|
|
10942
|
+
// node_modules/.pnpm/debug@4.4.3/node_modules/debug/src/common.js
|
|
10943
|
+
var require_common = __commonJS({
|
|
10944
|
+
"node_modules/.pnpm/debug@4.4.3/node_modules/debug/src/common.js"(exports, module) {
|
|
10945
|
+
function setup(env) {
|
|
10946
|
+
createDebug.debug = createDebug;
|
|
10947
|
+
createDebug.default = createDebug;
|
|
10948
|
+
createDebug.coerce = coerce2;
|
|
10949
|
+
createDebug.disable = disable;
|
|
10950
|
+
createDebug.enable = enable;
|
|
10951
|
+
createDebug.enabled = enabled;
|
|
10952
|
+
createDebug.humanize = require_ms();
|
|
10953
|
+
createDebug.destroy = destroy;
|
|
10954
|
+
Object.keys(env).forEach((key) => {
|
|
10955
|
+
createDebug[key] = env[key];
|
|
10956
|
+
});
|
|
10957
|
+
createDebug.names = [];
|
|
10958
|
+
createDebug.skips = [];
|
|
10959
|
+
createDebug.formatters = {};
|
|
10960
|
+
function selectColor(namespace) {
|
|
10961
|
+
let hash = 0;
|
|
10962
|
+
for (let i = 0; i < namespace.length; i++) {
|
|
10963
|
+
hash = (hash << 5) - hash + namespace.charCodeAt(i);
|
|
10964
|
+
hash |= 0;
|
|
10965
|
+
}
|
|
10966
|
+
return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
|
|
10967
|
+
}
|
|
10968
|
+
createDebug.selectColor = selectColor;
|
|
10969
|
+
function createDebug(namespace) {
|
|
10970
|
+
let prevTime;
|
|
10971
|
+
let enableOverride = null;
|
|
10972
|
+
let namespacesCache;
|
|
10973
|
+
let enabledCache;
|
|
10974
|
+
function debug(...args) {
|
|
10975
|
+
if (!debug.enabled) {
|
|
10976
|
+
return;
|
|
10977
|
+
}
|
|
10978
|
+
const self2 = debug;
|
|
10979
|
+
const curr = Number(/* @__PURE__ */ new Date());
|
|
10980
|
+
const ms = curr - (prevTime || curr);
|
|
10981
|
+
self2.diff = ms;
|
|
10982
|
+
self2.prev = prevTime;
|
|
10983
|
+
self2.curr = curr;
|
|
10984
|
+
prevTime = curr;
|
|
10985
|
+
args[0] = createDebug.coerce(args[0]);
|
|
10986
|
+
if (typeof args[0] !== "string") {
|
|
10987
|
+
args.unshift("%O");
|
|
10988
|
+
}
|
|
10989
|
+
let index = 0;
|
|
10990
|
+
args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {
|
|
10991
|
+
if (match === "%%") {
|
|
10992
|
+
return "%";
|
|
10993
|
+
}
|
|
10994
|
+
index++;
|
|
10995
|
+
const formatter = createDebug.formatters[format];
|
|
10996
|
+
if (typeof formatter === "function") {
|
|
10997
|
+
const val = args[index];
|
|
10998
|
+
match = formatter.call(self2, val);
|
|
10999
|
+
args.splice(index, 1);
|
|
11000
|
+
index--;
|
|
11001
|
+
}
|
|
11002
|
+
return match;
|
|
11003
|
+
});
|
|
11004
|
+
createDebug.formatArgs.call(self2, args);
|
|
11005
|
+
const logFn = self2.log || createDebug.log;
|
|
11006
|
+
logFn.apply(self2, args);
|
|
11007
|
+
}
|
|
11008
|
+
debug.namespace = namespace;
|
|
11009
|
+
debug.useColors = createDebug.useColors();
|
|
11010
|
+
debug.color = createDebug.selectColor(namespace);
|
|
11011
|
+
debug.extend = extend3;
|
|
11012
|
+
debug.destroy = createDebug.destroy;
|
|
11013
|
+
Object.defineProperty(debug, "enabled", {
|
|
11014
|
+
enumerable: true,
|
|
11015
|
+
configurable: false,
|
|
11016
|
+
get: () => {
|
|
11017
|
+
if (enableOverride !== null) {
|
|
11018
|
+
return enableOverride;
|
|
11019
|
+
}
|
|
11020
|
+
if (namespacesCache !== createDebug.namespaces) {
|
|
11021
|
+
namespacesCache = createDebug.namespaces;
|
|
11022
|
+
enabledCache = createDebug.enabled(namespace);
|
|
11023
|
+
}
|
|
11024
|
+
return enabledCache;
|
|
11025
|
+
},
|
|
11026
|
+
set: (v) => {
|
|
11027
|
+
enableOverride = v;
|
|
11028
|
+
}
|
|
11029
|
+
});
|
|
11030
|
+
if (typeof createDebug.init === "function") {
|
|
11031
|
+
createDebug.init(debug);
|
|
11032
|
+
}
|
|
11033
|
+
return debug;
|
|
11034
|
+
}
|
|
11035
|
+
function extend3(namespace, delimiter) {
|
|
11036
|
+
const newDebug = createDebug(this.namespace + (typeof delimiter === "undefined" ? ":" : delimiter) + namespace);
|
|
11037
|
+
newDebug.log = this.log;
|
|
11038
|
+
return newDebug;
|
|
11039
|
+
}
|
|
11040
|
+
function enable(namespaces) {
|
|
11041
|
+
createDebug.save(namespaces);
|
|
11042
|
+
createDebug.namespaces = namespaces;
|
|
11043
|
+
createDebug.names = [];
|
|
11044
|
+
createDebug.skips = [];
|
|
11045
|
+
const split = (typeof namespaces === "string" ? namespaces : "").trim().replace(/\s+/g, ",").split(",").filter(Boolean);
|
|
11046
|
+
for (const ns of split) {
|
|
11047
|
+
if (ns[0] === "-") {
|
|
11048
|
+
createDebug.skips.push(ns.slice(1));
|
|
11049
|
+
} else {
|
|
11050
|
+
createDebug.names.push(ns);
|
|
11051
|
+
}
|
|
11052
|
+
}
|
|
11053
|
+
}
|
|
11054
|
+
function matchesTemplate(search, template) {
|
|
11055
|
+
let searchIndex = 0;
|
|
11056
|
+
let templateIndex = 0;
|
|
11057
|
+
let starIndex = -1;
|
|
11058
|
+
let matchIndex = 0;
|
|
11059
|
+
while (searchIndex < search.length) {
|
|
11060
|
+
if (templateIndex < template.length && (template[templateIndex] === search[searchIndex] || template[templateIndex] === "*")) {
|
|
11061
|
+
if (template[templateIndex] === "*") {
|
|
11062
|
+
starIndex = templateIndex;
|
|
11063
|
+
matchIndex = searchIndex;
|
|
11064
|
+
templateIndex++;
|
|
11065
|
+
} else {
|
|
11066
|
+
searchIndex++;
|
|
11067
|
+
templateIndex++;
|
|
11068
|
+
}
|
|
11069
|
+
} else if (starIndex !== -1) {
|
|
11070
|
+
templateIndex = starIndex + 1;
|
|
11071
|
+
matchIndex++;
|
|
11072
|
+
searchIndex = matchIndex;
|
|
11073
|
+
} else {
|
|
11074
|
+
return false;
|
|
11075
|
+
}
|
|
11076
|
+
}
|
|
11077
|
+
while (templateIndex < template.length && template[templateIndex] === "*") {
|
|
11078
|
+
templateIndex++;
|
|
11079
|
+
}
|
|
11080
|
+
return templateIndex === template.length;
|
|
11081
|
+
}
|
|
11082
|
+
function disable() {
|
|
11083
|
+
const namespaces = [
|
|
11084
|
+
...createDebug.names,
|
|
11085
|
+
...createDebug.skips.map((namespace) => "-" + namespace)
|
|
11086
|
+
].join(",");
|
|
11087
|
+
createDebug.enable("");
|
|
11088
|
+
return namespaces;
|
|
11089
|
+
}
|
|
11090
|
+
function enabled(name) {
|
|
11091
|
+
for (const skip of createDebug.skips) {
|
|
11092
|
+
if (matchesTemplate(name, skip)) {
|
|
11093
|
+
return false;
|
|
11094
|
+
}
|
|
11095
|
+
}
|
|
11096
|
+
for (const ns of createDebug.names) {
|
|
11097
|
+
if (matchesTemplate(name, ns)) {
|
|
11098
|
+
return true;
|
|
11099
|
+
}
|
|
11100
|
+
}
|
|
11101
|
+
return false;
|
|
11102
|
+
}
|
|
11103
|
+
function coerce2(val) {
|
|
11104
|
+
if (val instanceof Error) {
|
|
11105
|
+
return val.stack || val.message;
|
|
11106
|
+
}
|
|
11107
|
+
return val;
|
|
11108
|
+
}
|
|
11109
|
+
function destroy() {
|
|
11110
|
+
console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.");
|
|
11111
|
+
}
|
|
11112
|
+
createDebug.enable(createDebug.load());
|
|
11113
|
+
return createDebug;
|
|
11114
|
+
}
|
|
11115
|
+
module.exports = setup;
|
|
11116
|
+
}
|
|
11117
|
+
});
|
|
11118
|
+
|
|
11119
|
+
// node_modules/.pnpm/debug@4.4.3/node_modules/debug/src/browser.js
|
|
11120
|
+
var require_browser = __commonJS({
|
|
11121
|
+
"node_modules/.pnpm/debug@4.4.3/node_modules/debug/src/browser.js"(exports, module) {
|
|
11122
|
+
exports.formatArgs = formatArgs;
|
|
11123
|
+
exports.save = save;
|
|
11124
|
+
exports.load = load2;
|
|
11125
|
+
exports.useColors = useColors;
|
|
11126
|
+
exports.storage = localstorage();
|
|
11127
|
+
exports.destroy = /* @__PURE__ */ (() => {
|
|
11128
|
+
let warned = false;
|
|
11129
|
+
return () => {
|
|
11130
|
+
if (!warned) {
|
|
11131
|
+
warned = true;
|
|
11132
|
+
console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.");
|
|
11133
|
+
}
|
|
11134
|
+
};
|
|
11135
|
+
})();
|
|
11136
|
+
exports.colors = [
|
|
11137
|
+
"#0000CC",
|
|
11138
|
+
"#0000FF",
|
|
11139
|
+
"#0033CC",
|
|
11140
|
+
"#0033FF",
|
|
11141
|
+
"#0066CC",
|
|
11142
|
+
"#0066FF",
|
|
11143
|
+
"#0099CC",
|
|
11144
|
+
"#0099FF",
|
|
11145
|
+
"#00CC00",
|
|
11146
|
+
"#00CC33",
|
|
11147
|
+
"#00CC66",
|
|
11148
|
+
"#00CC99",
|
|
11149
|
+
"#00CCCC",
|
|
11150
|
+
"#00CCFF",
|
|
11151
|
+
"#3300CC",
|
|
11152
|
+
"#3300FF",
|
|
11153
|
+
"#3333CC",
|
|
11154
|
+
"#3333FF",
|
|
11155
|
+
"#3366CC",
|
|
11156
|
+
"#3366FF",
|
|
11157
|
+
"#3399CC",
|
|
11158
|
+
"#3399FF",
|
|
11159
|
+
"#33CC00",
|
|
11160
|
+
"#33CC33",
|
|
11161
|
+
"#33CC66",
|
|
11162
|
+
"#33CC99",
|
|
11163
|
+
"#33CCCC",
|
|
11164
|
+
"#33CCFF",
|
|
11165
|
+
"#6600CC",
|
|
11166
|
+
"#6600FF",
|
|
11167
|
+
"#6633CC",
|
|
11168
|
+
"#6633FF",
|
|
11169
|
+
"#66CC00",
|
|
11170
|
+
"#66CC33",
|
|
11171
|
+
"#9900CC",
|
|
11172
|
+
"#9900FF",
|
|
11173
|
+
"#9933CC",
|
|
11174
|
+
"#9933FF",
|
|
11175
|
+
"#99CC00",
|
|
11176
|
+
"#99CC33",
|
|
11177
|
+
"#CC0000",
|
|
11178
|
+
"#CC0033",
|
|
11179
|
+
"#CC0066",
|
|
11180
|
+
"#CC0099",
|
|
11181
|
+
"#CC00CC",
|
|
11182
|
+
"#CC00FF",
|
|
11183
|
+
"#CC3300",
|
|
11184
|
+
"#CC3333",
|
|
11185
|
+
"#CC3366",
|
|
11186
|
+
"#CC3399",
|
|
11187
|
+
"#CC33CC",
|
|
11188
|
+
"#CC33FF",
|
|
11189
|
+
"#CC6600",
|
|
11190
|
+
"#CC6633",
|
|
11191
|
+
"#CC9900",
|
|
11192
|
+
"#CC9933",
|
|
11193
|
+
"#CCCC00",
|
|
11194
|
+
"#CCCC33",
|
|
11195
|
+
"#FF0000",
|
|
11196
|
+
"#FF0033",
|
|
11197
|
+
"#FF0066",
|
|
11198
|
+
"#FF0099",
|
|
11199
|
+
"#FF00CC",
|
|
11200
|
+
"#FF00FF",
|
|
11201
|
+
"#FF3300",
|
|
11202
|
+
"#FF3333",
|
|
11203
|
+
"#FF3366",
|
|
11204
|
+
"#FF3399",
|
|
11205
|
+
"#FF33CC",
|
|
11206
|
+
"#FF33FF",
|
|
11207
|
+
"#FF6600",
|
|
11208
|
+
"#FF6633",
|
|
11209
|
+
"#FF9900",
|
|
11210
|
+
"#FF9933",
|
|
11211
|
+
"#FFCC00",
|
|
11212
|
+
"#FFCC33"
|
|
11213
|
+
];
|
|
11214
|
+
function useColors() {
|
|
11215
|
+
if (typeof window !== "undefined" && window.process && (window.process.type === "renderer" || window.process.__nwjs)) {
|
|
11216
|
+
return true;
|
|
11217
|
+
}
|
|
11218
|
+
if (typeof navigator !== "undefined" && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) {
|
|
11219
|
+
return false;
|
|
11220
|
+
}
|
|
11221
|
+
let m;
|
|
11222
|
+
return typeof document !== "undefined" && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance || // Is firebug? http://stackoverflow.com/a/398120/376773
|
|
11223
|
+
typeof window !== "undefined" && window.console && (window.console.firebug || window.console.exception && window.console.table) || // Is firefox >= v31?
|
|
11224
|
+
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
|
|
11225
|
+
typeof navigator !== "undefined" && navigator.userAgent && (m = navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)) && parseInt(m[1], 10) >= 31 || // Double check webkit in userAgent just in case we are in a worker
|
|
11226
|
+
typeof navigator !== "undefined" && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/);
|
|
11227
|
+
}
|
|
11228
|
+
function formatArgs(args) {
|
|
11229
|
+
args[0] = (this.useColors ? "%c" : "") + this.namespace + (this.useColors ? " %c" : " ") + args[0] + (this.useColors ? "%c " : " ") + "+" + module.exports.humanize(this.diff);
|
|
11230
|
+
if (!this.useColors) {
|
|
11231
|
+
return;
|
|
11232
|
+
}
|
|
11233
|
+
const c = "color: " + this.color;
|
|
11234
|
+
args.splice(1, 0, c, "color: inherit");
|
|
11235
|
+
let index = 0;
|
|
11236
|
+
let lastC = 0;
|
|
11237
|
+
args[0].replace(/%[a-zA-Z%]/g, (match) => {
|
|
11238
|
+
if (match === "%%") {
|
|
11239
|
+
return;
|
|
11240
|
+
}
|
|
11241
|
+
index++;
|
|
11242
|
+
if (match === "%c") {
|
|
11243
|
+
lastC = index;
|
|
11244
|
+
}
|
|
11245
|
+
});
|
|
11246
|
+
args.splice(lastC, 0, c);
|
|
11247
|
+
}
|
|
11248
|
+
exports.log = console.debug || console.log || (() => {
|
|
11249
|
+
});
|
|
11250
|
+
function save(namespaces) {
|
|
11251
|
+
try {
|
|
11252
|
+
if (namespaces) {
|
|
11253
|
+
exports.storage.setItem("debug", namespaces);
|
|
11254
|
+
} else {
|
|
11255
|
+
exports.storage.removeItem("debug");
|
|
11256
|
+
}
|
|
11257
|
+
} catch (error) {
|
|
11258
|
+
}
|
|
11259
|
+
}
|
|
11260
|
+
function load2() {
|
|
11261
|
+
let r;
|
|
11262
|
+
try {
|
|
11263
|
+
r = exports.storage.getItem("debug") || exports.storage.getItem("DEBUG");
|
|
11264
|
+
} catch (error) {
|
|
11265
|
+
}
|
|
11266
|
+
if (!r && typeof process !== "undefined" && "env" in process) {
|
|
11267
|
+
r = process.env.DEBUG;
|
|
11268
|
+
}
|
|
11269
|
+
return r;
|
|
11270
|
+
}
|
|
11271
|
+
function localstorage() {
|
|
11272
|
+
try {
|
|
11273
|
+
return localStorage;
|
|
11274
|
+
} catch (error) {
|
|
11275
|
+
}
|
|
11276
|
+
}
|
|
11277
|
+
module.exports = require_common()(exports);
|
|
11278
|
+
var { formatters } = module.exports;
|
|
11279
|
+
formatters.j = function(v) {
|
|
11280
|
+
try {
|
|
11281
|
+
return JSON.stringify(v);
|
|
11282
|
+
} catch (error) {
|
|
11283
|
+
return "[UnexpectedJSONParseError]: " + error.message;
|
|
11284
|
+
}
|
|
11285
|
+
};
|
|
11286
|
+
}
|
|
11287
|
+
});
|
|
11288
|
+
|
|
11289
|
+
// node_modules/.pnpm/has-flag@4.0.0/node_modules/has-flag/index.js
|
|
11290
|
+
var require_has_flag = __commonJS({
|
|
11291
|
+
"node_modules/.pnpm/has-flag@4.0.0/node_modules/has-flag/index.js"(exports, module) {
|
|
11292
|
+
"use strict";
|
|
11293
|
+
module.exports = (flag, argv = process.argv) => {
|
|
11294
|
+
const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
|
|
11295
|
+
const position = argv.indexOf(prefix + flag);
|
|
11296
|
+
const terminatorPosition = argv.indexOf("--");
|
|
11297
|
+
return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
|
|
11298
|
+
};
|
|
11299
|
+
}
|
|
11300
|
+
});
|
|
11301
|
+
|
|
11302
|
+
// node_modules/.pnpm/supports-color@7.2.0/node_modules/supports-color/index.js
|
|
11303
|
+
var require_supports_color = __commonJS({
|
|
11304
|
+
"node_modules/.pnpm/supports-color@7.2.0/node_modules/supports-color/index.js"(exports, module) {
|
|
11305
|
+
"use strict";
|
|
11306
|
+
var os2 = __require("os");
|
|
11307
|
+
var tty = __require("tty");
|
|
11308
|
+
var hasFlag = require_has_flag();
|
|
11309
|
+
var { env } = process;
|
|
11310
|
+
var forceColor;
|
|
11311
|
+
if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
|
|
11312
|
+
forceColor = 0;
|
|
11313
|
+
} else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
|
|
11314
|
+
forceColor = 1;
|
|
11315
|
+
}
|
|
11316
|
+
if ("FORCE_COLOR" in env) {
|
|
11317
|
+
if (env.FORCE_COLOR === "true") {
|
|
11318
|
+
forceColor = 1;
|
|
11319
|
+
} else if (env.FORCE_COLOR === "false") {
|
|
11320
|
+
forceColor = 0;
|
|
11321
|
+
} else {
|
|
11322
|
+
forceColor = env.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env.FORCE_COLOR, 10), 3);
|
|
11323
|
+
}
|
|
11324
|
+
}
|
|
11325
|
+
function translateLevel(level) {
|
|
11326
|
+
if (level === 0) {
|
|
11327
|
+
return false;
|
|
11328
|
+
}
|
|
11329
|
+
return {
|
|
11330
|
+
level,
|
|
11331
|
+
hasBasic: true,
|
|
11332
|
+
has256: level >= 2,
|
|
11333
|
+
has16m: level >= 3
|
|
11334
|
+
};
|
|
11335
|
+
}
|
|
11336
|
+
function supportsColor(haveStream, streamIsTTY) {
|
|
11337
|
+
if (forceColor === 0) {
|
|
11338
|
+
return 0;
|
|
11339
|
+
}
|
|
11340
|
+
if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
|
|
11341
|
+
return 3;
|
|
11342
|
+
}
|
|
11343
|
+
if (hasFlag("color=256")) {
|
|
11344
|
+
return 2;
|
|
11345
|
+
}
|
|
11346
|
+
if (haveStream && !streamIsTTY && forceColor === void 0) {
|
|
11347
|
+
return 0;
|
|
11348
|
+
}
|
|
11349
|
+
const min = forceColor || 0;
|
|
11350
|
+
if (env.TERM === "dumb") {
|
|
11351
|
+
return min;
|
|
11352
|
+
}
|
|
11353
|
+
if (process.platform === "win32") {
|
|
11354
|
+
const osRelease = os2.release().split(".");
|
|
11355
|
+
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
|
|
11356
|
+
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
11357
|
+
}
|
|
11358
|
+
return 1;
|
|
11359
|
+
}
|
|
11360
|
+
if ("CI" in env) {
|
|
11361
|
+
if (["TRAVIS", "CIRCLECI", "APPVEYOR", "GITLAB_CI", "GITHUB_ACTIONS", "BUILDKITE"].some((sign) => sign in env) || env.CI_NAME === "codeship") {
|
|
11362
|
+
return 1;
|
|
11363
|
+
}
|
|
11364
|
+
return min;
|
|
11365
|
+
}
|
|
11366
|
+
if ("TEAMCITY_VERSION" in env) {
|
|
11367
|
+
return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
|
|
11368
|
+
}
|
|
11369
|
+
if (env.COLORTERM === "truecolor") {
|
|
11370
|
+
return 3;
|
|
11371
|
+
}
|
|
11372
|
+
if ("TERM_PROGRAM" in env) {
|
|
11373
|
+
const version = parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
|
|
11374
|
+
switch (env.TERM_PROGRAM) {
|
|
11375
|
+
case "iTerm.app":
|
|
11376
|
+
return version >= 3 ? 3 : 2;
|
|
11377
|
+
case "Apple_Terminal":
|
|
11378
|
+
return 2;
|
|
11379
|
+
}
|
|
11380
|
+
}
|
|
11381
|
+
if (/-256(color)?$/i.test(env.TERM)) {
|
|
11382
|
+
return 2;
|
|
11383
|
+
}
|
|
11384
|
+
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
|
|
11385
|
+
return 1;
|
|
11386
|
+
}
|
|
11387
|
+
if ("COLORTERM" in env) {
|
|
11388
|
+
return 1;
|
|
11389
|
+
}
|
|
11390
|
+
return min;
|
|
11391
|
+
}
|
|
11392
|
+
function getSupportLevel(stream) {
|
|
11393
|
+
const level = supportsColor(stream, stream && stream.isTTY);
|
|
11394
|
+
return translateLevel(level);
|
|
11395
|
+
}
|
|
11396
|
+
module.exports = {
|
|
11397
|
+
supportsColor: getSupportLevel,
|
|
11398
|
+
stdout: translateLevel(supportsColor(true, tty.isatty(1))),
|
|
11399
|
+
stderr: translateLevel(supportsColor(true, tty.isatty(2)))
|
|
11400
|
+
};
|
|
11401
|
+
}
|
|
11402
|
+
});
|
|
11403
|
+
|
|
11404
|
+
// node_modules/.pnpm/debug@4.4.3/node_modules/debug/src/node.js
|
|
11405
|
+
var require_node = __commonJS({
|
|
11406
|
+
"node_modules/.pnpm/debug@4.4.3/node_modules/debug/src/node.js"(exports, module) {
|
|
11407
|
+
var tty = __require("tty");
|
|
11408
|
+
var util2 = __require("util");
|
|
11409
|
+
exports.init = init;
|
|
11410
|
+
exports.log = log;
|
|
11411
|
+
exports.formatArgs = formatArgs;
|
|
11412
|
+
exports.save = save;
|
|
11413
|
+
exports.load = load2;
|
|
11414
|
+
exports.useColors = useColors;
|
|
11415
|
+
exports.destroy = util2.deprecate(
|
|
11416
|
+
() => {
|
|
11417
|
+
},
|
|
11418
|
+
"Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."
|
|
11419
|
+
);
|
|
11420
|
+
exports.colors = [6, 2, 3, 4, 5, 1];
|
|
11421
|
+
try {
|
|
11422
|
+
const supportsColor = require_supports_color();
|
|
11423
|
+
if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) {
|
|
11424
|
+
exports.colors = [
|
|
11425
|
+
20,
|
|
11426
|
+
21,
|
|
11427
|
+
26,
|
|
11428
|
+
27,
|
|
11429
|
+
32,
|
|
11430
|
+
33,
|
|
11431
|
+
38,
|
|
11432
|
+
39,
|
|
11433
|
+
40,
|
|
11434
|
+
41,
|
|
11435
|
+
42,
|
|
11436
|
+
43,
|
|
11437
|
+
44,
|
|
11438
|
+
45,
|
|
11439
|
+
56,
|
|
11440
|
+
57,
|
|
11441
|
+
62,
|
|
11442
|
+
63,
|
|
11443
|
+
68,
|
|
11444
|
+
69,
|
|
11445
|
+
74,
|
|
11446
|
+
75,
|
|
11447
|
+
76,
|
|
11448
|
+
77,
|
|
11449
|
+
78,
|
|
11450
|
+
79,
|
|
11451
|
+
80,
|
|
11452
|
+
81,
|
|
11453
|
+
92,
|
|
11454
|
+
93,
|
|
11455
|
+
98,
|
|
11456
|
+
99,
|
|
11457
|
+
112,
|
|
11458
|
+
113,
|
|
11459
|
+
128,
|
|
11460
|
+
129,
|
|
11461
|
+
134,
|
|
11462
|
+
135,
|
|
11463
|
+
148,
|
|
11464
|
+
149,
|
|
11465
|
+
160,
|
|
11466
|
+
161,
|
|
11467
|
+
162,
|
|
11468
|
+
163,
|
|
11469
|
+
164,
|
|
11470
|
+
165,
|
|
11471
|
+
166,
|
|
11472
|
+
167,
|
|
11473
|
+
168,
|
|
11474
|
+
169,
|
|
11475
|
+
170,
|
|
11476
|
+
171,
|
|
11477
|
+
172,
|
|
11478
|
+
173,
|
|
11479
|
+
178,
|
|
11480
|
+
179,
|
|
11481
|
+
184,
|
|
11482
|
+
185,
|
|
11483
|
+
196,
|
|
11484
|
+
197,
|
|
11485
|
+
198,
|
|
11486
|
+
199,
|
|
11487
|
+
200,
|
|
11488
|
+
201,
|
|
11489
|
+
202,
|
|
11490
|
+
203,
|
|
11491
|
+
204,
|
|
11492
|
+
205,
|
|
11493
|
+
206,
|
|
11494
|
+
207,
|
|
11495
|
+
208,
|
|
11496
|
+
209,
|
|
11497
|
+
214,
|
|
11498
|
+
215,
|
|
11499
|
+
220,
|
|
11500
|
+
221
|
|
11501
|
+
];
|
|
11502
|
+
}
|
|
11503
|
+
} catch (error) {
|
|
11504
|
+
}
|
|
11505
|
+
exports.inspectOpts = Object.keys(process.env).filter((key) => {
|
|
11506
|
+
return /^debug_/i.test(key);
|
|
11507
|
+
}).reduce((obj, key) => {
|
|
11508
|
+
const prop = key.substring(6).toLowerCase().replace(/_([a-z])/g, (_, k) => {
|
|
11509
|
+
return k.toUpperCase();
|
|
11510
|
+
});
|
|
11511
|
+
let val = process.env[key];
|
|
11512
|
+
if (/^(yes|on|true|enabled)$/i.test(val)) {
|
|
11513
|
+
val = true;
|
|
11514
|
+
} else if (/^(no|off|false|disabled)$/i.test(val)) {
|
|
11515
|
+
val = false;
|
|
11516
|
+
} else if (val === "null") {
|
|
11517
|
+
val = null;
|
|
11518
|
+
} else {
|
|
11519
|
+
val = Number(val);
|
|
11520
|
+
}
|
|
11521
|
+
obj[prop] = val;
|
|
11522
|
+
return obj;
|
|
11523
|
+
}, {});
|
|
11524
|
+
function useColors() {
|
|
11525
|
+
return "colors" in exports.inspectOpts ? Boolean(exports.inspectOpts.colors) : tty.isatty(process.stderr.fd);
|
|
11526
|
+
}
|
|
11527
|
+
function formatArgs(args) {
|
|
11528
|
+
const { namespace: name, useColors: useColors2 } = this;
|
|
11529
|
+
if (useColors2) {
|
|
11530
|
+
const c = this.color;
|
|
11531
|
+
const colorCode = "\x1B[3" + (c < 8 ? c : "8;5;" + c);
|
|
11532
|
+
const prefix = ` ${colorCode};1m${name} \x1B[0m`;
|
|
11533
|
+
args[0] = prefix + args[0].split("\n").join("\n" + prefix);
|
|
11534
|
+
args.push(colorCode + "m+" + module.exports.humanize(this.diff) + "\x1B[0m");
|
|
11535
|
+
} else {
|
|
11536
|
+
args[0] = getDate() + name + " " + args[0];
|
|
11537
|
+
}
|
|
11538
|
+
}
|
|
11539
|
+
function getDate() {
|
|
11540
|
+
if (exports.inspectOpts.hideDate) {
|
|
11541
|
+
return "";
|
|
11542
|
+
}
|
|
11543
|
+
return (/* @__PURE__ */ new Date()).toISOString() + " ";
|
|
11544
|
+
}
|
|
11545
|
+
function log(...args) {
|
|
11546
|
+
return process.stderr.write(util2.formatWithOptions(exports.inspectOpts, ...args) + "\n");
|
|
11547
|
+
}
|
|
11548
|
+
function save(namespaces) {
|
|
11549
|
+
if (namespaces) {
|
|
11550
|
+
process.env.DEBUG = namespaces;
|
|
11551
|
+
} else {
|
|
11552
|
+
delete process.env.DEBUG;
|
|
11553
|
+
}
|
|
11554
|
+
}
|
|
11555
|
+
function load2() {
|
|
11556
|
+
return process.env.DEBUG;
|
|
11557
|
+
}
|
|
11558
|
+
function init(debug) {
|
|
11559
|
+
debug.inspectOpts = {};
|
|
11560
|
+
const keys = Object.keys(exports.inspectOpts);
|
|
11561
|
+
for (let i = 0; i < keys.length; i++) {
|
|
11562
|
+
debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
|
|
11563
|
+
}
|
|
11564
|
+
}
|
|
11565
|
+
module.exports = require_common()(exports);
|
|
11566
|
+
var { formatters } = module.exports;
|
|
11567
|
+
formatters.o = function(v) {
|
|
11568
|
+
this.inspectOpts.colors = this.useColors;
|
|
11569
|
+
return util2.inspect(v, this.inspectOpts).split("\n").map((str2) => str2.trim()).join(" ");
|
|
11570
|
+
};
|
|
11571
|
+
formatters.O = function(v) {
|
|
11572
|
+
this.inspectOpts.colors = this.useColors;
|
|
11573
|
+
return util2.inspect(v, this.inspectOpts);
|
|
11574
|
+
};
|
|
11575
|
+
}
|
|
11576
|
+
});
|
|
11577
|
+
|
|
11578
|
+
// node_modules/.pnpm/debug@4.4.3/node_modules/debug/src/index.js
|
|
11579
|
+
var require_src = __commonJS({
|
|
11580
|
+
"node_modules/.pnpm/debug@4.4.3/node_modules/debug/src/index.js"(exports, module) {
|
|
11581
|
+
if (typeof process === "undefined" || process.type === "renderer" || process.browser === true || process.__nwjs) {
|
|
11582
|
+
module.exports = require_browser();
|
|
11583
|
+
} else {
|
|
11584
|
+
module.exports = require_node();
|
|
11585
|
+
}
|
|
11586
|
+
}
|
|
11587
|
+
});
|
|
11588
|
+
|
|
10743
11589
|
// node_modules/.pnpm/follow-redirects@1.16.0/node_modules/follow-redirects/debug.js
|
|
10744
11590
|
var require_debug = __commonJS({
|
|
10745
11591
|
"node_modules/.pnpm/follow-redirects@1.16.0/node_modules/follow-redirects/debug.js"(exports, module) {
|
|
@@ -10747,7 +11593,7 @@ var require_debug = __commonJS({
|
|
|
10747
11593
|
module.exports = function() {
|
|
10748
11594
|
if (!debug) {
|
|
10749
11595
|
try {
|
|
10750
|
-
debug =
|
|
11596
|
+
debug = require_src()("follow-redirects");
|
|
10751
11597
|
} catch (error) {
|
|
10752
11598
|
}
|
|
10753
11599
|
if (typeof debug !== "function") {
|
|
@@ -111535,11 +112381,132 @@ var init_channelPostClient = __esm({
|
|
|
111535
112381
|
}
|
|
111536
112382
|
});
|
|
111537
112383
|
|
|
112384
|
+
// src/lark/channelCotClient.ts
|
|
112385
|
+
async function withTimeout(p, ms, label) {
|
|
112386
|
+
let timer;
|
|
112387
|
+
const timeout = new Promise((_resolve, reject) => {
|
|
112388
|
+
timer = setTimeout(
|
|
112389
|
+
() => reject(new Error(`[channel.cot] ${label} timed out after ${ms}ms`)),
|
|
112390
|
+
ms
|
|
112391
|
+
);
|
|
112392
|
+
timer.unref?.();
|
|
112393
|
+
});
|
|
112394
|
+
try {
|
|
112395
|
+
return await Promise.race([p, timeout]);
|
|
112396
|
+
} finally {
|
|
112397
|
+
if (timer) clearTimeout(timer);
|
|
112398
|
+
}
|
|
112399
|
+
}
|
|
112400
|
+
function assertOk(res, label) {
|
|
112401
|
+
if (res.code !== void 0 && res.code !== 0) {
|
|
112402
|
+
throw new Error(
|
|
112403
|
+
`[channel.cot] ${label} failed: code=${res.code} msg=${res.msg ?? "<no msg>"}`
|
|
112404
|
+
);
|
|
112405
|
+
}
|
|
112406
|
+
}
|
|
112407
|
+
function stringField(data, key) {
|
|
112408
|
+
const value = data?.[key];
|
|
112409
|
+
return typeof value === "string" ? value : void 0;
|
|
112410
|
+
}
|
|
112411
|
+
var COT_REQUEST_TIMEOUT_MS, ChannelCotClient;
|
|
112412
|
+
var init_channelCotClient = __esm({
|
|
112413
|
+
"src/lark/channelCotClient.ts"() {
|
|
112414
|
+
"use strict";
|
|
112415
|
+
COT_REQUEST_TIMEOUT_MS = 8e3;
|
|
112416
|
+
ChannelCotClient = class {
|
|
112417
|
+
resolveChannel;
|
|
112418
|
+
constructor(opts) {
|
|
112419
|
+
this.resolveChannel = opts.resolveChannel;
|
|
112420
|
+
}
|
|
112421
|
+
channel() {
|
|
112422
|
+
const ch = this.resolveChannel();
|
|
112423
|
+
if (!ch) {
|
|
112424
|
+
throw new Error("[channel.cot] outbound called before the Channel SDK connected");
|
|
112425
|
+
}
|
|
112426
|
+
return ch;
|
|
112427
|
+
}
|
|
112428
|
+
/** Every COT call goes through here, so all get the same hard timeout. */
|
|
112429
|
+
request(opts) {
|
|
112430
|
+
return withTimeout(
|
|
112431
|
+
this.channel().rawClient.request(opts),
|
|
112432
|
+
COT_REQUEST_TIMEOUT_MS,
|
|
112433
|
+
`${opts.method} ${opts.url}`
|
|
112434
|
+
);
|
|
112435
|
+
}
|
|
112436
|
+
async create(target) {
|
|
112437
|
+
const receiveIdType = target.threadId ? "thread_id" : "chat_id";
|
|
112438
|
+
const receiveId = target.threadId ?? target.chatId;
|
|
112439
|
+
const res = await this.request({
|
|
112440
|
+
url: "/open-apis/im/v1/message_cot",
|
|
112441
|
+
method: "POST",
|
|
112442
|
+
params: { receive_id_type: receiveIdType },
|
|
112443
|
+
data: {
|
|
112444
|
+
receive_id: receiveId,
|
|
112445
|
+
// origin_message_id only anchors non-thread bubbles; harmless if set,
|
|
112446
|
+
// but omitted for topic threads where the thread id already anchors.
|
|
112447
|
+
...!target.threadId && target.originMessageId ? { origin_message_id: target.originMessageId } : {}
|
|
112448
|
+
}
|
|
112449
|
+
});
|
|
112450
|
+
assertOk(res, "create");
|
|
112451
|
+
const cotId = stringField(res.data, "cot_id");
|
|
112452
|
+
const messageId = stringField(res.data, "message_id");
|
|
112453
|
+
if (!cotId || !messageId) {
|
|
112454
|
+
throw new Error(
|
|
112455
|
+
`[channel.cot] create returned no cot_id/message_id (${JSON.stringify(res.data ?? {}).slice(0, 200)})`
|
|
112456
|
+
);
|
|
112457
|
+
}
|
|
112458
|
+
return { cotId, messageId };
|
|
112459
|
+
}
|
|
112460
|
+
async update(ref, events) {
|
|
112461
|
+
if (events.length === 0) return;
|
|
112462
|
+
const res = await this.request({
|
|
112463
|
+
url: "/open-apis/im/v1/message_cot",
|
|
112464
|
+
method: "PUT",
|
|
112465
|
+
data: { cot_id: ref.cotId, message_id: ref.messageId, events: [...events] }
|
|
112466
|
+
});
|
|
112467
|
+
assertOk(res, "update");
|
|
112468
|
+
}
|
|
112469
|
+
async complete(ref, reason) {
|
|
112470
|
+
const res = await this.request({
|
|
112471
|
+
url: `/open-apis/im/v1/message_cot/complete/${encodeURIComponent(ref.cotId)}`,
|
|
112472
|
+
method: "POST",
|
|
112473
|
+
params: { message_id: ref.messageId, reason }
|
|
112474
|
+
});
|
|
112475
|
+
assertOk(res, "complete");
|
|
112476
|
+
}
|
|
112477
|
+
async resolveThreadId(messageId) {
|
|
112478
|
+
try {
|
|
112479
|
+
const res = await this.request({
|
|
112480
|
+
url: `/open-apis/im/v1/messages/${encodeURIComponent(messageId)}`,
|
|
112481
|
+
method: "GET"
|
|
112482
|
+
});
|
|
112483
|
+
if (res.code !== void 0 && res.code !== 0) return void 0;
|
|
112484
|
+
const items = res.data?.["items"];
|
|
112485
|
+
if (!Array.isArray(items)) return void 0;
|
|
112486
|
+
for (const item of items) {
|
|
112487
|
+
if (item && typeof item === "object") {
|
|
112488
|
+
const threadId = item["thread_id"];
|
|
112489
|
+
if (typeof threadId === "string" && threadId.startsWith("omt_")) {
|
|
112490
|
+
return threadId;
|
|
112491
|
+
}
|
|
112492
|
+
}
|
|
112493
|
+
}
|
|
112494
|
+
return void 0;
|
|
112495
|
+
} catch {
|
|
112496
|
+
return void 0;
|
|
112497
|
+
}
|
|
112498
|
+
}
|
|
112499
|
+
};
|
|
112500
|
+
}
|
|
112501
|
+
});
|
|
112502
|
+
|
|
111538
112503
|
// src/lark/channelClient.ts
|
|
111539
112504
|
var channelClient_exports = {};
|
|
111540
112505
|
__export(channelClient_exports, {
|
|
111541
112506
|
ChannelClient: () => ChannelClient,
|
|
112507
|
+
DEFAULT_OPEN_CHAT_DISCOVERY_MS: () => DEFAULT_OPEN_CHAT_DISCOVERY_MS,
|
|
111542
112508
|
channelMsgToLarkEvent: () => channelMsgToLarkEvent,
|
|
112509
|
+
resolveOpenChatDiscoveryMs: () => resolveOpenChatDiscoveryMs,
|
|
111543
112510
|
resolveRecoveredThreadId: () => resolveRecoveredThreadId,
|
|
111544
112511
|
synthesizeCardActionEvent: () => synthesizeCardActionEvent
|
|
111545
112512
|
});
|
|
@@ -111583,13 +112550,13 @@ function arrayField(obj, key) {
|
|
|
111583
112550
|
const value = obj[key];
|
|
111584
112551
|
return Array.isArray(value) ? value : null;
|
|
111585
112552
|
}
|
|
111586
|
-
function
|
|
112553
|
+
function stringField2(obj, key) {
|
|
111587
112554
|
if (!obj || typeof obj !== "object") return void 0;
|
|
111588
112555
|
const value = obj[key];
|
|
111589
112556
|
return typeof value === "string" ? value : void 0;
|
|
111590
112557
|
}
|
|
111591
112558
|
function nonEmptyStringField(obj, key) {
|
|
111592
|
-
const value =
|
|
112559
|
+
const value = stringField2(obj, key);
|
|
111593
112560
|
return value && value.length > 0 ? value : void 0;
|
|
111594
112561
|
}
|
|
111595
112562
|
function parseLarkCliMessages(stdout2) {
|
|
@@ -111692,6 +112659,7 @@ var init_channelClient = __esm({
|
|
|
111692
112659
|
init_channelCardClient();
|
|
111693
112660
|
init_channelCardKitClient();
|
|
111694
112661
|
init_channelPostClient();
|
|
112662
|
+
init_channelCotClient();
|
|
111695
112663
|
execFile4 = promisify4(execFileCallback);
|
|
111696
112664
|
LEARNED_CHATS_LIMIT = 100;
|
|
111697
112665
|
SEEN_MESSAGES_LIMIT = 1e3;
|
|
@@ -111827,6 +112795,8 @@ var init_channelClient = __esm({
|
|
|
111827
112795
|
cardKitClient = null;
|
|
111828
112796
|
/** Lazily built and only requested by main.ts when post outbound gates are configured. */
|
|
111829
112797
|
postClient = null;
|
|
112798
|
+
/** Lazily built COT (思维链) client; only requested when a bot enables cot != off. */
|
|
112799
|
+
cotClient = null;
|
|
111830
112800
|
constructor(opts) {
|
|
111831
112801
|
if (!opts.appId || !opts.appSecret) {
|
|
111832
112802
|
throw new Error(
|
|
@@ -112044,6 +113014,20 @@ var init_channelClient = __esm({
|
|
|
112044
113014
|
log(`cardAction \u2192 synthesized turn: value=${JSON.stringify(evt.action?.value)} thread=${ev.thread_id ?? "?"}`);
|
|
112045
113015
|
this.queue.push(ev);
|
|
112046
113016
|
}
|
|
113017
|
+
/**
|
|
113018
|
+
* Push an already-built synthetic LarkMessageEvent onto the inbound queue,
|
|
113019
|
+
* so handler.ts processes it as an ordinary turn. Same mechanism as
|
|
113020
|
+
* {@link handleCardAction}'s cardAction → queue.push, generalized for other
|
|
113021
|
+
* bridge-external signal sources — currently only the task-handle comment
|
|
113022
|
+
* poller (src/tasklist/commentPoller.ts), which synthesizes a turn from a
|
|
113023
|
+
* new Feishu task comment. Public because the poller lives outside this
|
|
113024
|
+
* class (main.ts wires it); the caller is fully responsible for building a
|
|
113025
|
+
* well-formed event (thread_id/root_id resolved, etc.) — this method does
|
|
113026
|
+
* no validation of its own, mirroring handleCardAction's contract.
|
|
113027
|
+
*/
|
|
113028
|
+
enqueueSyntheticEvent(ev) {
|
|
113029
|
+
this.queue.push(ev);
|
|
113030
|
+
}
|
|
112047
113031
|
/**
|
|
112048
113032
|
* Return an OutboundCardClient bound to this client's channel handle.
|
|
112049
113033
|
*
|
|
@@ -112078,6 +113062,22 @@ var init_channelClient = __esm({
|
|
|
112078
113062
|
}
|
|
112079
113063
|
return this.cardKitClient;
|
|
112080
113064
|
}
|
|
113065
|
+
/**
|
|
113066
|
+
* Return an OutboundCotClient bound to this client's channel handle.
|
|
113067
|
+
*
|
|
113068
|
+
* main.ts only calls this when the bot's `cot` config is not "off". The COT
|
|
113069
|
+
* bubble uses the SDK's generic rawClient.request() (tenant token auto-
|
|
113070
|
+
* injected via the same token manager as every other outbound call), so it
|
|
113071
|
+
* adds no auth surface. Resolves the live channel lazily at call time.
|
|
113072
|
+
*/
|
|
113073
|
+
outboundCotClient() {
|
|
113074
|
+
if (!this.cotClient) {
|
|
113075
|
+
this.cotClient = new ChannelCotClient({
|
|
113076
|
+
resolveChannel: () => this.channel
|
|
113077
|
+
});
|
|
113078
|
+
}
|
|
113079
|
+
return this.cotClient;
|
|
113080
|
+
}
|
|
112081
113081
|
/**
|
|
112082
113082
|
* Return an OutboundPostClient bound to this client's channel handle.
|
|
112083
113083
|
*
|
|
@@ -112381,7 +113381,7 @@ var init_channelClient = __esm({
|
|
|
112381
113381
|
const chats = parseLarkCliMessages(stdout2) ?? [];
|
|
112382
113382
|
fetched += chats.length;
|
|
112383
113383
|
for (const raw of chats) {
|
|
112384
|
-
const chatId =
|
|
113384
|
+
const chatId = stringField2(raw, "chat_id");
|
|
112385
113385
|
if (!chatId?.startsWith("oc_")) continue;
|
|
112386
113386
|
discoveredChatIds.add(chatId);
|
|
112387
113387
|
const before = this.recentlySeenChatIds.size;
|
|
@@ -112395,7 +113395,7 @@ var init_channelClient = __esm({
|
|
|
112395
113395
|
const hasMore = Boolean(
|
|
112396
113396
|
(data && typeof data === "object" && data["has_more"]) ?? (parsed && typeof parsed === "object" && parsed["has_more"])
|
|
112397
113397
|
);
|
|
112398
|
-
pageToken =
|
|
113398
|
+
pageToken = stringField2(data, "page_token") ?? stringField2(parsed, "page_token") ?? "";
|
|
112399
113399
|
if (!hasMore || !pageToken) break;
|
|
112400
113400
|
}
|
|
112401
113401
|
if (newlyLearned > 0) {
|
|
@@ -112654,6 +113654,403 @@ var init_channelClient = __esm({
|
|
|
112654
113654
|
}
|
|
112655
113655
|
});
|
|
112656
113656
|
|
|
113657
|
+
// src/tasklist/client.ts
|
|
113658
|
+
var client_exports = {};
|
|
113659
|
+
__export(client_exports, {
|
|
113660
|
+
TaskApiError: () => TaskApiError,
|
|
113661
|
+
TaskListClient: () => TaskListClient,
|
|
113662
|
+
TaskRequestTimeoutError: () => TaskRequestTimeoutError,
|
|
113663
|
+
isPermissionDeniedError: () => isPermissionDeniedError,
|
|
113664
|
+
isTaskNotFoundError: () => isTaskNotFoundError,
|
|
113665
|
+
isTaskRequestTimeoutError: () => isTaskRequestTimeoutError
|
|
113666
|
+
});
|
|
113667
|
+
function isTaskNotFoundError(err2) {
|
|
113668
|
+
if (err2 instanceof TaskApiError) {
|
|
113669
|
+
if (err2.status === 404) return true;
|
|
113670
|
+
if (typeof err2.message === "string" && /not.?found|不存在|resource_not_exist/i.test(err2.message)) {
|
|
113671
|
+
return true;
|
|
113672
|
+
}
|
|
113673
|
+
}
|
|
113674
|
+
return false;
|
|
113675
|
+
}
|
|
113676
|
+
function isPermissionDeniedError(err2) {
|
|
113677
|
+
if (err2 instanceof TaskApiError) {
|
|
113678
|
+
if (err2.status === 403) return true;
|
|
113679
|
+
if (typeof err2.message === "string" && /no permission|no.access|forbidden|access.denied|无权限|未授权/i.test(err2.message)) {
|
|
113680
|
+
return true;
|
|
113681
|
+
}
|
|
113682
|
+
}
|
|
113683
|
+
return false;
|
|
113684
|
+
}
|
|
113685
|
+
function parseDueMs(task) {
|
|
113686
|
+
const due = asRecord(task["due"]);
|
|
113687
|
+
const timestamp2 = due["timestamp"];
|
|
113688
|
+
if (typeof timestamp2 !== "string") return void 0;
|
|
113689
|
+
const ms = Number(timestamp2);
|
|
113690
|
+
if (!Number.isFinite(ms)) return void 0;
|
|
113691
|
+
return due["is_all_day"] === true ? ms + MS_PER_DAY : ms;
|
|
113692
|
+
}
|
|
113693
|
+
function asRecord(v) {
|
|
113694
|
+
return typeof v === "object" && v !== null ? v : {};
|
|
113695
|
+
}
|
|
113696
|
+
function wrapErr(label, err2) {
|
|
113697
|
+
if (err2 instanceof TaskApiError) throw err2;
|
|
113698
|
+
const rec = asRecord(err2);
|
|
113699
|
+
const response = asRecord(rec["response"]);
|
|
113700
|
+
const status = typeof response["status"] === "number" ? response["status"] : void 0;
|
|
113701
|
+
const body = asRecord(response["data"]);
|
|
113702
|
+
const code = typeof body["code"] === "number" ? body["code"] : void 0;
|
|
113703
|
+
const bodyMsg = typeof body["msg"] === "string" ? body["msg"] : void 0;
|
|
113704
|
+
const message = `[tasklist.client] ${label} failed: ${bodyMsg ?? err2?.message ?? String(err2)}`;
|
|
113705
|
+
throw new TaskApiError(message, { status, code, cause: err2 });
|
|
113706
|
+
}
|
|
113707
|
+
function isTaskRequestTimeoutError(err2) {
|
|
113708
|
+
if (err2 instanceof TaskRequestTimeoutError) return true;
|
|
113709
|
+
if (err2 instanceof TaskApiError && err2.cause instanceof TaskRequestTimeoutError) return true;
|
|
113710
|
+
return false;
|
|
113711
|
+
}
|
|
113712
|
+
function withTimeout2(promise, ms, label) {
|
|
113713
|
+
let timer;
|
|
113714
|
+
const timeout = new Promise((_, reject) => {
|
|
113715
|
+
timer = setTimeout(() => reject(new TaskRequestTimeoutError(`${label} timed out after ${ms}ms`)), ms);
|
|
113716
|
+
});
|
|
113717
|
+
return Promise.race([promise, timeout]).finally(() => clearTimeout(timer));
|
|
113718
|
+
}
|
|
113719
|
+
function isNotFoundLikeRaw(err2) {
|
|
113720
|
+
const rec = asRecord(err2);
|
|
113721
|
+
const response = asRecord(rec["response"]);
|
|
113722
|
+
if (response["status"] === 404) return true;
|
|
113723
|
+
const body = asRecord(response["data"]);
|
|
113724
|
+
const msg = typeof body["msg"] === "string" ? body["msg"] : "";
|
|
113725
|
+
return /not.?found|不存在|resource_not_exist/i.test(msg);
|
|
113726
|
+
}
|
|
113727
|
+
var DEFAULT_TIMEOUT_MS, TaskApiError, MS_PER_DAY, TaskRequestTimeoutError, TASK_V2_BASE, TaskListClient;
|
|
113728
|
+
var init_client = __esm({
|
|
113729
|
+
"src/tasklist/client.ts"() {
|
|
113730
|
+
"use strict";
|
|
113731
|
+
DEFAULT_TIMEOUT_MS = 12e3;
|
|
113732
|
+
TaskApiError = class extends Error {
|
|
113733
|
+
status;
|
|
113734
|
+
code;
|
|
113735
|
+
constructor(message, opts) {
|
|
113736
|
+
super(message);
|
|
113737
|
+
this.name = "TaskApiError";
|
|
113738
|
+
this.status = opts.status;
|
|
113739
|
+
this.code = opts.code;
|
|
113740
|
+
this.cause = opts.cause;
|
|
113741
|
+
}
|
|
113742
|
+
};
|
|
113743
|
+
MS_PER_DAY = 24 * 60 * 6e4;
|
|
113744
|
+
TaskRequestTimeoutError = class extends Error {
|
|
113745
|
+
};
|
|
113746
|
+
TASK_V2_BASE = "/open-apis/task/v2";
|
|
113747
|
+
TaskListClient = class {
|
|
113748
|
+
#requester;
|
|
113749
|
+
#timeoutMs;
|
|
113750
|
+
constructor(requester, opts = {}) {
|
|
113751
|
+
this.#requester = requester;
|
|
113752
|
+
this.#timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
113753
|
+
}
|
|
113754
|
+
/** Single choke point for every outbound call — applies the timeout race uniformly. */
|
|
113755
|
+
#request(config, label) {
|
|
113756
|
+
return withTimeout2(this.#requester.request(config), this.#timeoutMs, label);
|
|
113757
|
+
}
|
|
113758
|
+
async getTask(taskGuid) {
|
|
113759
|
+
let resp;
|
|
113760
|
+
try {
|
|
113761
|
+
resp = await this.#request(
|
|
113762
|
+
{
|
|
113763
|
+
method: "GET",
|
|
113764
|
+
url: `${TASK_V2_BASE}/tasks/${encodeURIComponent(taskGuid)}`,
|
|
113765
|
+
params: { user_id_type: "open_id" }
|
|
113766
|
+
},
|
|
113767
|
+
`getTask(${taskGuid})`
|
|
113768
|
+
);
|
|
113769
|
+
} catch (err2) {
|
|
113770
|
+
if (isNotFoundLikeRaw(err2)) return null;
|
|
113771
|
+
wrapErr(`getTask(${taskGuid})`, err2);
|
|
113772
|
+
}
|
|
113773
|
+
const task = resp.data?.task;
|
|
113774
|
+
if (!task) return null;
|
|
113775
|
+
return {
|
|
113776
|
+
guid: String(task["guid"] ?? task["id"] ?? taskGuid),
|
|
113777
|
+
summary: typeof task["summary"] === "string" ? task["summary"] : void 0,
|
|
113778
|
+
description: typeof task["description"] === "string" ? task["description"] : void 0,
|
|
113779
|
+
completedAt: typeof task["completed_at"] === "string" ? task["completed_at"] : void 0,
|
|
113780
|
+
dueMs: parseDueMs(task)
|
|
113781
|
+
};
|
|
113782
|
+
}
|
|
113783
|
+
/** Overwrite the task description (bridge-owned status-snapshot block only — see writeback.ts). */
|
|
113784
|
+
async patchDescription(taskGuid, description) {
|
|
113785
|
+
await this.#patchTask(taskGuid, { description }, ["description"]);
|
|
113786
|
+
}
|
|
113787
|
+
/** Mark the task complete "now". */
|
|
113788
|
+
async complete(taskGuid) {
|
|
113789
|
+
await this.#patchTask(taskGuid, { completed_at: String(Date.now()) }, ["completed_at"]);
|
|
113790
|
+
}
|
|
113791
|
+
/**
|
|
113792
|
+
* Clear completed_at (task v2 patch semantics: an `update_fields` entry with
|
|
113793
|
+
* no corresponding value in `task` clears that field — verified via
|
|
113794
|
+
* `lark-cli schema task tasks patch`).
|
|
113795
|
+
*/
|
|
113796
|
+
async reopen(taskGuid) {
|
|
113797
|
+
await this.#patchTask(taskGuid, {}, ["completed_at"]);
|
|
113798
|
+
}
|
|
113799
|
+
async #patchTask(taskGuid, task, updateFields) {
|
|
113800
|
+
const label = `patchTask(${taskGuid}, fields=${updateFields.join(",")})`;
|
|
113801
|
+
try {
|
|
113802
|
+
await this.#request(
|
|
113803
|
+
{
|
|
113804
|
+
method: "PATCH",
|
|
113805
|
+
url: `${TASK_V2_BASE}/tasks/${encodeURIComponent(taskGuid)}`,
|
|
113806
|
+
params: { user_id_type: "open_id" },
|
|
113807
|
+
data: { task, update_fields: updateFields }
|
|
113808
|
+
},
|
|
113809
|
+
label
|
|
113810
|
+
);
|
|
113811
|
+
} catch (err2) {
|
|
113812
|
+
wrapErr(label, err2);
|
|
113813
|
+
}
|
|
113814
|
+
}
|
|
113815
|
+
async addComment(taskGuid, content) {
|
|
113816
|
+
const label = `addComment(${taskGuid})`;
|
|
113817
|
+
try {
|
|
113818
|
+
await this.#request(
|
|
113819
|
+
{
|
|
113820
|
+
method: "POST",
|
|
113821
|
+
url: `${TASK_V2_BASE}/comments`,
|
|
113822
|
+
data: { resource_type: "task", resource_id: taskGuid, content }
|
|
113823
|
+
},
|
|
113824
|
+
label
|
|
113825
|
+
);
|
|
113826
|
+
} catch (err2) {
|
|
113827
|
+
wrapErr(label, err2);
|
|
113828
|
+
}
|
|
113829
|
+
}
|
|
113830
|
+
async listComments(taskGuid, opts = {}) {
|
|
113831
|
+
const label = `listComments(${taskGuid})`;
|
|
113832
|
+
let resp;
|
|
113833
|
+
try {
|
|
113834
|
+
resp = await this.#request(
|
|
113835
|
+
{
|
|
113836
|
+
method: "GET",
|
|
113837
|
+
url: `${TASK_V2_BASE}/comments`,
|
|
113838
|
+
params: {
|
|
113839
|
+
resource_type: "task",
|
|
113840
|
+
resource_id: taskGuid,
|
|
113841
|
+
page_size: opts.pageSize ?? 50,
|
|
113842
|
+
// Spread-omit: the SDK serializes a literal `undefined` value into
|
|
113843
|
+
// the query string ("page_token=undefined"), which strict endpoints
|
|
113844
|
+
// reject with 1470400 — only send the key when we hold a real token.
|
|
113845
|
+
...opts.pageToken ? { page_token: opts.pageToken } : {}
|
|
113846
|
+
}
|
|
113847
|
+
},
|
|
113848
|
+
label
|
|
113849
|
+
);
|
|
113850
|
+
} catch (err2) {
|
|
113851
|
+
wrapErr(label, err2);
|
|
113852
|
+
}
|
|
113853
|
+
const items = resp.data?.items ?? [];
|
|
113854
|
+
const comments = items.map((raw) => {
|
|
113855
|
+
const creator = asRecord(raw["creator"] ?? raw["commentator"]);
|
|
113856
|
+
return {
|
|
113857
|
+
id: String(raw["id"] ?? raw["comment_id"] ?? ""),
|
|
113858
|
+
content: typeof raw["content"] === "string" ? raw["content"] : "",
|
|
113859
|
+
// Real API response uses `created_at` (string ms). create_milli_time/
|
|
113860
|
+
// create_time are kept as fallbacks only in case a differently-versioned
|
|
113861
|
+
// tenant/response shape uses them — created_at is checked first since
|
|
113862
|
+
// it's the verified real field (2026-07 live check against docs/task-handle.md).
|
|
113863
|
+
createMillis: typeof raw["created_at"] === "string" ? raw["created_at"] : typeof raw["create_milli_time"] === "string" ? raw["create_milli_time"] : typeof raw["create_time"] === "string" ? raw["create_time"] : void 0,
|
|
113864
|
+
creatorId: typeof creator["id"] === "string" ? creator["id"] : void 0,
|
|
113865
|
+
creatorType: typeof creator["type"] === "string" ? creator["type"] : void 0
|
|
113866
|
+
};
|
|
113867
|
+
});
|
|
113868
|
+
return {
|
|
113869
|
+
comments,
|
|
113870
|
+
hasMore: Boolean(resp.data?.has_more),
|
|
113871
|
+
pageToken: resp.data?.page_token
|
|
113872
|
+
};
|
|
113873
|
+
}
|
|
113874
|
+
/**
|
|
113875
|
+
* Fetch a tasklist's current guid + member list (verified against live
|
|
113876
|
+
* `lark-cli schema task tasklists get`, 1.0.64 — `GET /tasklists/
|
|
113877
|
+
* :tasklist_guid`). Used by `tasklist-init` as a post-create/post-reuse
|
|
113878
|
+
* safety net: read the membership back and warn if the owner's open_id
|
|
113879
|
+
* didn't actually land as a member (a silently-dropped member is a real
|
|
113880
|
+
* platform failure mode this guards against — see tasklistInit.ts).
|
|
113881
|
+
*/
|
|
113882
|
+
async getTasklist(tasklistGuid) {
|
|
113883
|
+
const label = `getTasklist(${tasklistGuid})`;
|
|
113884
|
+
let resp;
|
|
113885
|
+
try {
|
|
113886
|
+
resp = await this.#request(
|
|
113887
|
+
{
|
|
113888
|
+
method: "GET",
|
|
113889
|
+
url: `${TASK_V2_BASE}/tasklists/${encodeURIComponent(tasklistGuid)}`,
|
|
113890
|
+
params: { user_id_type: "open_id" }
|
|
113891
|
+
},
|
|
113892
|
+
label
|
|
113893
|
+
);
|
|
113894
|
+
} catch (err2) {
|
|
113895
|
+
if (isNotFoundLikeRaw(err2)) return null;
|
|
113896
|
+
wrapErr(label, err2);
|
|
113897
|
+
}
|
|
113898
|
+
const tasklist = resp.data?.tasklist;
|
|
113899
|
+
if (!tasklist) return null;
|
|
113900
|
+
const rawMembers = Array.isArray(tasklist["members"]) ? tasklist["members"] : [];
|
|
113901
|
+
const members = rawMembers.map((m) => ({
|
|
113902
|
+
id: String(m["id"] ?? ""),
|
|
113903
|
+
type: m["type"] === "user" || m["type"] === "chat" || m["type"] === "app" ? m["type"] : void 0,
|
|
113904
|
+
role: m["role"] === "assignee" || m["role"] === "follower" || m["role"] === "editor" || m["role"] === "viewer" ? m["role"] : "editor"
|
|
113905
|
+
}));
|
|
113906
|
+
return { guid: String(tasklist["guid"] ?? tasklistGuid), members };
|
|
113907
|
+
}
|
|
113908
|
+
async createTasklist(name, members = []) {
|
|
113909
|
+
const label = `createTasklist(${name})`;
|
|
113910
|
+
let resp;
|
|
113911
|
+
try {
|
|
113912
|
+
resp = await this.#request(
|
|
113913
|
+
{
|
|
113914
|
+
method: "POST",
|
|
113915
|
+
url: `${TASK_V2_BASE}/tasklists`,
|
|
113916
|
+
params: { user_id_type: "open_id" },
|
|
113917
|
+
data: { name, members }
|
|
113918
|
+
},
|
|
113919
|
+
label
|
|
113920
|
+
);
|
|
113921
|
+
} catch (err2) {
|
|
113922
|
+
wrapErr(label, err2);
|
|
113923
|
+
}
|
|
113924
|
+
const guid = resp.data?.tasklist?.["guid"];
|
|
113925
|
+
if (typeof guid !== "string" || guid.length === 0) {
|
|
113926
|
+
throw new TaskApiError(`[tasklist.client] createTasklist(${name}) returned no guid`, {});
|
|
113927
|
+
}
|
|
113928
|
+
return { guid };
|
|
113929
|
+
}
|
|
113930
|
+
/**
|
|
113931
|
+
* List tasks belonging to a tasklist (used by TasklistPoller,
|
|
113932
|
+
* src/tasklist/tasklistPoller.ts, for the v3 "候选注入" candidate
|
|
113933
|
+
* discovery). `GET /tasklists/:tasklist_guid/tasks` verified live
|
|
113934
|
+
* 2026-07-04 against a real tasklist (200 + items[]); note this endpoint
|
|
113935
|
+
* strictly validates `page_token` (a literal "undefined" query value is a
|
|
113936
|
+
* hard 1470400), hence the spread-omit below. Treat as best-effort like
|
|
113937
|
+
* every other tasklist call: TasklistPoller swallows failures and keeps
|
|
113938
|
+
* its previous candidate snapshot rather than propagating.
|
|
113939
|
+
*/
|
|
113940
|
+
async listTasklistTasks(tasklistGuid, opts = {}) {
|
|
113941
|
+
const label = `listTasklistTasks(${tasklistGuid})`;
|
|
113942
|
+
let resp;
|
|
113943
|
+
try {
|
|
113944
|
+
resp = await this.#request(
|
|
113945
|
+
{
|
|
113946
|
+
method: "GET",
|
|
113947
|
+
url: `${TASK_V2_BASE}/tasklists/${encodeURIComponent(tasklistGuid)}/tasks`,
|
|
113948
|
+
params: {
|
|
113949
|
+
user_id_type: "open_id",
|
|
113950
|
+
page_size: opts.pageSize ?? 50,
|
|
113951
|
+
// Same spread-omit as listComments: "page_token=undefined" in the
|
|
113952
|
+
// query string is a hard 400 (1470400) on this endpoint — verified
|
|
113953
|
+
// live 2026-07-04 against a real tasklist.
|
|
113954
|
+
...opts.pageToken ? { page_token: opts.pageToken } : {}
|
|
113955
|
+
}
|
|
113956
|
+
},
|
|
113957
|
+
label
|
|
113958
|
+
);
|
|
113959
|
+
} catch (err2) {
|
|
113960
|
+
wrapErr(label, err2);
|
|
113961
|
+
}
|
|
113962
|
+
const items = resp.data?.items ?? [];
|
|
113963
|
+
const tasks = items.map((task) => ({
|
|
113964
|
+
guid: String(task["guid"] ?? task["id"] ?? ""),
|
|
113965
|
+
summary: typeof task["summary"] === "string" ? task["summary"] : void 0,
|
|
113966
|
+
description: typeof task["description"] === "string" ? task["description"] : void 0,
|
|
113967
|
+
completedAt: typeof task["completed_at"] === "string" ? task["completed_at"] : void 0,
|
|
113968
|
+
dueMs: parseDueMs(task)
|
|
113969
|
+
}));
|
|
113970
|
+
return { tasks, hasMore: Boolean(resp.data?.has_more), pageToken: resp.data?.page_token };
|
|
113971
|
+
}
|
|
113972
|
+
/**
|
|
113973
|
+
* Add members to an existing tasklist (verified against `lark-cli schema
|
|
113974
|
+
* task tasklists add_members`, 1.0.64 — `POST /tasklists/:tasklist_guid/
|
|
113975
|
+
* members`). Used by `tasklist-init --team` and by a bot's own first-run
|
|
113976
|
+
* self-join (docs/task-handle.md §7 "同一 owner 的一组 bot… 把自己加为
|
|
113977
|
+
* editor") to add sibling bot apps as `editor` members of the shared
|
|
113978
|
+
* "Agent Team" list. Idempotent from the caller's perspective: re-adding an
|
|
113979
|
+
* existing member is a harmless no-op per the platform (not independently
|
|
113980
|
+
* verified against a live 409/duplicate-shaped error — callers should treat
|
|
113981
|
+
* any failure here as best-effort, same swallow-and-warn posture as the
|
|
113982
|
+
* rest of this feature).
|
|
113983
|
+
*/
|
|
113984
|
+
async addTasklistMembers(tasklistGuid, members) {
|
|
113985
|
+
const label = `addTasklistMembers(${tasklistGuid})`;
|
|
113986
|
+
try {
|
|
113987
|
+
await this.#request(
|
|
113988
|
+
{
|
|
113989
|
+
method: "POST",
|
|
113990
|
+
url: `${TASK_V2_BASE}/tasklists/${encodeURIComponent(tasklistGuid)}/members`,
|
|
113991
|
+
params: { user_id_type: "open_id" },
|
|
113992
|
+
data: { members }
|
|
113993
|
+
},
|
|
113994
|
+
label
|
|
113995
|
+
);
|
|
113996
|
+
} catch (err2) {
|
|
113997
|
+
wrapErr(label, err2);
|
|
113998
|
+
}
|
|
113999
|
+
}
|
|
114000
|
+
};
|
|
114001
|
+
}
|
|
114002
|
+
});
|
|
114003
|
+
|
|
114004
|
+
// src/tasklist/teamRegistry.ts
|
|
114005
|
+
var teamRegistry_exports = {};
|
|
114006
|
+
__export(teamRegistry_exports, {
|
|
114007
|
+
claimTeamTasklistGuid: () => claimTeamTasklistGuid,
|
|
114008
|
+
overwriteTeamTasklistGuid: () => overwriteTeamTasklistGuid,
|
|
114009
|
+
readTeamTasklistGuid: () => readTeamTasklistGuid
|
|
114010
|
+
});
|
|
114011
|
+
import { rename as rename4, readFile as readFile6, writeFile as writeFile5, mkdir as mkdir4 } from "node:fs/promises";
|
|
114012
|
+
import { dirname } from "node:path";
|
|
114013
|
+
async function readTeamTasklistGuid(filePath) {
|
|
114014
|
+
try {
|
|
114015
|
+
const raw = await readFile6(filePath, "utf8");
|
|
114016
|
+
const parsed = JSON.parse(raw);
|
|
114017
|
+
if (typeof parsed !== "object" || parsed === null) return void 0;
|
|
114018
|
+
const guid = parsed["tasklistGuid"];
|
|
114019
|
+
return typeof guid === "string" && guid.length > 0 ? guid : void 0;
|
|
114020
|
+
} catch {
|
|
114021
|
+
return void 0;
|
|
114022
|
+
}
|
|
114023
|
+
}
|
|
114024
|
+
async function claimTeamTasklistGuid(filePath, tasklistGuid) {
|
|
114025
|
+
const existing = await readTeamTasklistGuid(filePath);
|
|
114026
|
+
if (existing) return existing;
|
|
114027
|
+
await writeTeamTasklistGuid(filePath, tasklistGuid);
|
|
114028
|
+
return tasklistGuid;
|
|
114029
|
+
}
|
|
114030
|
+
async function overwriteTeamTasklistGuid(filePath, tasklistGuid) {
|
|
114031
|
+
await writeTeamTasklistGuid(filePath, tasklistGuid);
|
|
114032
|
+
}
|
|
114033
|
+
async function writeTeamTasklistGuid(filePath, tasklistGuid) {
|
|
114034
|
+
try {
|
|
114035
|
+
const file = { version: 1, tasklistGuid };
|
|
114036
|
+
const json2 = JSON.stringify(file, null, 2);
|
|
114037
|
+
const tmpPath = `${filePath}.tmp`;
|
|
114038
|
+
await mkdir4(dirname(filePath), { recursive: true });
|
|
114039
|
+
await writeFile5(tmpPath, json2, "utf8");
|
|
114040
|
+
await rename4(tmpPath, filePath);
|
|
114041
|
+
} catch (err2) {
|
|
114042
|
+
console.warn(
|
|
114043
|
+
`[tasklist.teamRegistry] failed to persist tasklistGuid to ${filePath} (continuing, best-effort):`,
|
|
114044
|
+
err2
|
|
114045
|
+
);
|
|
114046
|
+
}
|
|
114047
|
+
}
|
|
114048
|
+
var init_teamRegistry = __esm({
|
|
114049
|
+
"src/tasklist/teamRegistry.ts"() {
|
|
114050
|
+
"use strict";
|
|
114051
|
+
}
|
|
114052
|
+
});
|
|
114053
|
+
|
|
112657
114054
|
// node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/can-promise.js
|
|
112658
114055
|
var require_can_promise = __commonJS({
|
|
112659
114056
|
"node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/can-promise.js"(exports, module) {
|
|
@@ -116991,7 +118388,7 @@ var require_canvas = __commonJS({
|
|
|
116991
118388
|
});
|
|
116992
118389
|
|
|
116993
118390
|
// node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/browser.js
|
|
116994
|
-
var
|
|
118391
|
+
var require_browser2 = __commonJS({
|
|
116995
118392
|
"node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/browser.js"(exports) {
|
|
116996
118393
|
var canPromise = require_can_promise();
|
|
116997
118394
|
var QRCode2 = require_qrcode();
|
|
@@ -117138,7 +118535,7 @@ var require_server = __commonJS({
|
|
|
117138
118535
|
}
|
|
117139
118536
|
}
|
|
117140
118537
|
exports.create = QRCode2.create;
|
|
117141
|
-
exports.toCanvas =
|
|
118538
|
+
exports.toCanvas = require_browser2().toCanvas;
|
|
117142
118539
|
exports.toString = function toString3(text, opts, cb) {
|
|
117143
118540
|
const params = checkParams(text, opts, cb);
|
|
117144
118541
|
const type2 = params.opts ? params.opts.type : void 0;
|
|
@@ -124196,10 +125593,81 @@ var ResponseSurfacePrototypeConfigSchema = external_exports.object({
|
|
|
124196
125593
|
}).default(responseSurfacePrototypeConfigDefaults);
|
|
124197
125594
|
|
|
124198
125595
|
// src/config/botLoader.ts
|
|
125596
|
+
var KNOWN_EFFORT_VALUES = /* @__PURE__ */ new Set(["low", "medium", "high", "max"]);
|
|
124199
125597
|
var GitIdentitySchema = external_exports.object({
|
|
124200
125598
|
name: external_exports.string().min(1),
|
|
124201
125599
|
email: external_exports.string().email()
|
|
124202
125600
|
});
|
|
125601
|
+
var TaskHandleConfigSchema = external_exports.object({
|
|
125602
|
+
/**
|
|
125603
|
+
* owner 的「Agent Team」共享清单 GUID。由 `larkway tasklist-init --team`
|
|
125604
|
+
* provisioning 子命令产出并手工填入,或经共享注册文件(task-team.json)被
|
|
125605
|
+
* 同组 bot 自动发现。缺失 = 功能休眠(main.ts 不会替你建)。
|
|
125606
|
+
*/
|
|
125607
|
+
tasklistGuid: external_exports.string().min(1).optional(),
|
|
125608
|
+
/**
|
|
125609
|
+
* @deprecated v1 遗留字段,v2 已去掉「enabled 开关」语义 —— 真正门槛见上。
|
|
125610
|
+
* 仅为了不 break 现网已写 `enabled: true` 的 yaml(strict schema 否则会拒绝
|
|
125611
|
+
* 未知字段)而接受它;接受后从不读取,loadBots() 会打一条 deprecation warn
|
|
125612
|
+
* 提示删除。新 yaml 不要再写这个字段。
|
|
125613
|
+
*/
|
|
125614
|
+
enabled: external_exports.boolean().optional(),
|
|
125615
|
+
/**
|
|
125616
|
+
* v3.1 停滞检测(docs/task-handle.md §12)全部可选,均有保守默认值——不配
|
|
125617
|
+
* 就用默认阈值,不是新的 enable 开关(检测本身跟 tasklistGuid 一样,只要有
|
|
125618
|
+
* 认领记录就跑;想彻底关掉停滞检测本身,见 stallDetectionDisabled)。
|
|
125619
|
+
*/
|
|
125620
|
+
/** 绑定话题超过这个时长(ms)无活动 → 判定停滞,唤醒认领的 agent。默认 24h。 */
|
|
125621
|
+
stallThresholdMs: external_exports.number().positive().optional(),
|
|
125622
|
+
/** 若该话题最后一轮 turn 以失败/崩溃收场,改用这个更短的阈值(ms)。默认 30min。 */
|
|
125623
|
+
stallFastThresholdMs: external_exports.number().positive().optional(),
|
|
125624
|
+
/**
|
|
125625
|
+
* v3.2 交接断链检测(docs/task-handle.md §13):若最后一轮完成 turn 的回复
|
|
125626
|
+
* @ 了花名册上的另一个 bot,且对方的 bridge 在这个阈值(ms)内在同一话题没
|
|
125627
|
+
* 有收到任何事件,改用这个更短的阈值(优先级高于上面两个,取更短者)。
|
|
125628
|
+
* 默认 5min——协作断链比一般停滞紧急得多,任务多为小时级,理应分钟级发现。
|
|
125629
|
+
* **下限提示**:5min 对应本机 open 模式 bot 的 gap-fill 巡检周期(300s)+
|
|
125630
|
+
* 一个 patrol tick 缓冲——配更短不会被拦,但低于部署实际的 gap-fill 周期
|
|
125631
|
+
* 有跟补投撞车、同一事件被提醒两次的风险,见 docs/task-handle.md §13。只有
|
|
125632
|
+
* 明确 chats 白名单(非 open 模式)的 bot 没有周期性 gap-fill(只有断线重连
|
|
125633
|
+
* 触发),下限可以放宽到 2min。且只对**同一 bridge 进程内**的协作 bot 生
|
|
125634
|
+
* 效——跨 bridge 的 @ 天生观察不到对方的收到时间,走一般停滞阈值。
|
|
125635
|
+
* **收到只是暂缓,不是永久解除**——见 stallHandoffReceiptGraceMs。
|
|
125636
|
+
*/
|
|
125637
|
+
stallHandoffThresholdMs: external_exports.number().positive().optional(),
|
|
125638
|
+
/**
|
|
125639
|
+
* v3.2 revision 3(docs/task-handle.md §13):对方"收到了事件"只在这个阈值
|
|
125640
|
+
* (ms)内被信任——收到之后这段时间里,如果对方**真的跑完一轮 turn**(不是
|
|
125641
|
+
* 又收到一次事件),才算真正解除交接断链;超过这个时长仍没有对方跑完 turn
|
|
125642
|
+
* 的记录,重新判定为断链、再次提醒。默认 30min(相对 handler.ts 自己注释的
|
|
125643
|
+
* 单轮 turn 5-15 分钟耗时留足余量)。防的是反向漏洞:如果"收到"永久解除
|
|
125644
|
+
* 断链判定,对方收到后真的崩了/卡死,就再也不会被判定断链了。
|
|
125645
|
+
*/
|
|
125646
|
+
stallHandoffReceiptGraceMs: external_exports.number().positive().optional(),
|
|
125647
|
+
/** 同一任务两次提醒之间的最短间隔(ms),防止骚扰。默认 24h。 */
|
|
125648
|
+
stallNudgeCooldownMs: external_exports.number().positive().optional(),
|
|
125649
|
+
/** 连续几次提醒仍无进展后改为升级(任务评论通知人类,此后对该任务静默直到有新活动)。默认 2。 */
|
|
125650
|
+
stallEscalateAfterNudges: external_exports.number().int().positive().optional(),
|
|
125651
|
+
/** 彻底关闭停滞检测(默认 false = 开启,阈值保守)。 */
|
|
125652
|
+
stallDetectionDisabled: external_exports.boolean().optional(),
|
|
125653
|
+
/**
|
|
125654
|
+
* v3.3 候选黑洞提示(docs/task-handle.md §14):共享清单里一个未认领候选
|
|
125655
|
+
* 任务连续滞留超过这个时长(ms)仍没被任何话题绑定(自动或人工认领都算解除),
|
|
125656
|
+
* TasklistPoller 就在该任务下留一条机械提示评论(每个候选只提一次,绑定
|
|
125657
|
+
* 成功后从"已提示"集合清除,再次滞留可再提)。默认 1h。只对同一 tasklistGuid
|
|
125658
|
+
* 共享组里"首个解析出该 guid 的 bot"的配置生效(跟 TasklistPoller 本身
|
|
125659
|
+
* "一个 guid 一个实例"的粒度一致,见 clientOwnerBotId 的同款约定)。
|
|
125660
|
+
*/
|
|
125661
|
+
candidateUnboundAlertMs: external_exports.number().positive().optional(),
|
|
125662
|
+
/**
|
|
125663
|
+
* v3.3 全局唤醒保险丝(docs/task-handle.md §14):这个 bot 的 StallDetector
|
|
125664
|
+
* 每小时(滚动窗口,非整点分桶)最多合成几次唤醒 turn(含通用/断链/过期各
|
|
125665
|
+
* 档,不含升级评论)。超限本轮抑制,只打一条点名哪个任务被抑制的 warn 日志,
|
|
125666
|
+
* 不改任何持久状态,下一轮正常重新评估。默认 6——纯粹是防止未知 bug 导致
|
|
125667
|
+
* 唤醒风暴烧推理额度的保险丝,正常路径永远碰不到它,不是需要调优的阈值。
|
|
125668
|
+
*/
|
|
125669
|
+
stallNudgeHourlyCap: external_exports.number().int().positive().optional()
|
|
125670
|
+
}).strict();
|
|
124203
125671
|
var GitCloneUrlSchema = external_exports.string().min(1).refine(
|
|
124204
125672
|
(value) => {
|
|
124205
125673
|
if (/^https?:\/\/\S+$/i.test(value)) return true;
|
|
@@ -124387,7 +125855,92 @@ var BotConfigSchema = external_exports.object({
|
|
|
124387
125855
|
*
|
|
124388
125856
|
* @default "claude"
|
|
124389
125857
|
*/
|
|
124390
|
-
backend: external_exports.string().min(1).default("claude")
|
|
125858
|
+
backend: external_exports.string().min(1).default("claude"),
|
|
125859
|
+
/**
|
|
125860
|
+
* COT (思维链) 气泡:把 agent 的 thinking 思考过程 + 工具调用摘要实时推到飞书
|
|
125861
|
+
* 原生的可折叠思维链气泡(与最终答案卡片互不干扰,最终答案永远只走卡片)。
|
|
125862
|
+
*
|
|
125863
|
+
* - "off":完全不调用 message_cot API(零网络、零副作用)。
|
|
125864
|
+
* - "brief"(默认):思考过程 + 工具名摘要。
|
|
125865
|
+
* - "detailed":额外推工具入参(TOOL_CALL_ARGS)与截断后的工具结果。
|
|
125866
|
+
*
|
|
125867
|
+
* message_cot 是无公开文档的 API —— 任何一步失败都会在本次会话内自动降级、
|
|
125868
|
+
* 只记 warn,绝不影响卡片和最终答案(见 src/bridge/cotProgress.ts)。
|
|
125869
|
+
*/
|
|
125870
|
+
cot: external_exports.enum(["off", "brief", "detailed"]).default("brief"),
|
|
125871
|
+
/**
|
|
125872
|
+
* COT 展示形态。`cot` 管密度(off/brief/detailed),这个管落点:
|
|
125873
|
+
* - "bubble"(默认):走飞书原生 message_cot 思维链气泡(src/bridge/cotProgress.ts)——
|
|
125874
|
+
* 客户端原生渲染(工具图标列表 + 可折叠头),真机体验最好。已知限制:话题内
|
|
125875
|
+
* 锚定不可用(气泡落群顶层,本租户 thread 通道判死),收尾 bug 已在 main 修复。
|
|
125876
|
+
* - "card":思考过程内嵌进答案卡片里的 collapsible_panel(懒创建、答案上方)。
|
|
125877
|
+
* ⚠️ 实验选项 —— 2026-07-05 真机实测:飞书客户端**不渲染 collapsible_panel 的
|
|
125878
|
+
* 折叠交互**(API 全 code=0,但面板被拍平成普通文本、无折叠箭头、终态也不可折叠;
|
|
125879
|
+
* CardKit 无 GET 读回、只能真机人眼验)。故 card 形态目前仅作纯文本内嵌展示用,
|
|
125880
|
+
* 体验不如气泡,不建议作默认。见 memory feishu-message-cot-api。
|
|
125881
|
+
* cot="off" 时本字段无意义(两种形态都不产出)。
|
|
125882
|
+
*/
|
|
125883
|
+
cotSurface: external_exports.enum(["card", "bubble"]).default("bubble"),
|
|
125884
|
+
/**
|
|
125885
|
+
* 话题 ↔ 飞书任务句柄(docs/task-handle.md,v2)。省略此字段不代表关闭,但也
|
|
125886
|
+
* 不会触发任何自动建清单——main.ts 在 startup 时只做只读解析(yaml 里的
|
|
125887
|
+
* tasklistGuid,或共享注册文件里已有的 guid);清单本身只由
|
|
125888
|
+
* `larkway tasklist-init --team` 建一次。
|
|
125889
|
+
*/
|
|
125890
|
+
taskHandle: TaskHandleConfigSchema.optional(),
|
|
125891
|
+
/**
|
|
125892
|
+
* Per-bot model override (perf plan 批 C 旋钮). Passed through verbatim to
|
|
125893
|
+
* the backend CLI as `--model <value>` (claude) / `turn/start.model`
|
|
125894
|
+
* (codex) — larkway does not validate or allowlist model ids, same
|
|
125895
|
+
* precedent as `backend` above. Omitted = unchanged host/backend default
|
|
125896
|
+
* behavior (byte-identical to before this field existed).
|
|
125897
|
+
*/
|
|
125898
|
+
model: external_exports.string().min(1).optional(),
|
|
125899
|
+
/**
|
|
125900
|
+
* Per-bot reasoning-effort override (perf plan 批 C 旋钮). Passed through
|
|
125901
|
+
* verbatim as `--effort <value>` on the claude CLI (confirmed supported:
|
|
125902
|
+
* `claude --effort low|medium|high|max`, also non-interactive). Also
|
|
125903
|
+
* confirmed supported on codex via `turn/start.effort`, mapped through
|
|
125904
|
+
* codexEffortFromLarkway (src/codex/runner.ts) since codex's own value
|
|
125905
|
+
* space is low/medium/high/xhigh, not low/medium/high/max. Omitted =
|
|
125906
|
+
* unchanged default behavior.
|
|
125907
|
+
*/
|
|
125908
|
+
effort: external_exports.string().min(1).optional(),
|
|
125909
|
+
/**
|
|
125910
|
+
* docs/larkway-perf-plan.md §4 — opt into a persistent warm process
|
|
125911
|
+
* instead of the default one-shot cold-start-per-turn behavior. Takes
|
|
125912
|
+
* effect for `backend: "codex"` (a single bot-level `codex app-server`
|
|
125913
|
+
* process — src/codex/pool.ts CodexProcessPool) and `backend: "claude"`
|
|
125914
|
+
* (one warm process per active thread — src/claude/pool.ts
|
|
125915
|
+
* ClaudeProcessPool). Any other backend value is a no-op (main.ts only
|
|
125916
|
+
* constructs a pool for these two; botLoader's advisory warn below flags
|
|
125917
|
+
* the mismatch upfront). Byte-identical behavior when unset, matching
|
|
125918
|
+
* every other perf-plan flag in this schema. `.optional()` (not
|
|
125919
|
+
* `.default(false)`, deliberately — B1 fix): a `.default()` would make
|
|
125920
|
+
* every future `larkway bot` yaml write-out include `warmProcess: false`
|
|
125921
|
+
* even when nobody asked for it, and — because this schema is `.strict()`
|
|
125922
|
+
* — would break loading that yaml back with an OLDER larkway build that
|
|
125923
|
+
* predates this field. `undefined` and `false` are treated identically at
|
|
125924
|
+
* both read sites (main.ts's `bot.warmProcess && …` and the advisory warn
|
|
125925
|
+
* below).
|
|
125926
|
+
*/
|
|
125927
|
+
warmProcess: external_exports.boolean().optional(),
|
|
125928
|
+
/**
|
|
125929
|
+
* Idle threshold (ms) before a warm process (see `warmProcess` above) with
|
|
125930
|
+
* no in-flight turn gets SIGTERM'd. Only meaningful when `warmProcess` is
|
|
125931
|
+
* true. @default 10 * 60 * 1000 (10 min) — see DEFAULT_WARM_PROCESS_IDLE_MS
|
|
125932
|
+
* in src/codex/pool.ts (backend "codex") / src/claude/pool.ts (backend
|
|
125933
|
+
* "claude") — both use the same default value.
|
|
125934
|
+
*/
|
|
125935
|
+
warmProcessIdleMs: external_exports.number().int().positive().optional(),
|
|
125936
|
+
/**
|
|
125937
|
+
* `backend: "claude"` only: cap on how many warm per-thread processes
|
|
125938
|
+
* ClaudeProcessPool keeps alive at once (LRU-evicts the longest-idle one
|
|
125939
|
+
* past this). Meaningless for `backend: "codex"`, which only ever holds
|
|
125940
|
+
* one bot-level process regardless. @default 6 — see DEFAULT_MAX_PROCESSES
|
|
125941
|
+
* in src/claude/pool.ts.
|
|
125942
|
+
*/
|
|
125943
|
+
warmProcessMaxProcesses: external_exports.number().int().positive().optional()
|
|
124391
125944
|
}).strict();
|
|
124392
125945
|
async function loadBots(botsDir) {
|
|
124393
125946
|
let entries;
|
|
@@ -124425,6 +125978,21 @@ async function loadBots(botsDir) {
|
|
|
124425
125978
|
${issues}`);
|
|
124426
125979
|
}
|
|
124427
125980
|
const bot = result.data;
|
|
125981
|
+
if (bot.effort && !KNOWN_EFFORT_VALUES.has(bot.effort)) {
|
|
125982
|
+
console.warn(
|
|
125983
|
+
`[botLoader] Bot "${bot.id}" effort "${bot.effort}" is not one of the known values (${[...KNOWN_EFFORT_VALUES].join(", ")}). Continuing \u2014 the value is still passed through to the backend CLI verbatim (claude: --effort; codex: mapped through codexEffortFromLarkway), but a typo here will silently fail the bot's spawn every turn.`
|
|
125984
|
+
);
|
|
125985
|
+
}
|
|
125986
|
+
if (bot.warmProcess && bot.backend !== "codex" && bot.backend !== "claude") {
|
|
125987
|
+
console.warn(
|
|
125988
|
+
`[botLoader] Bot "${bot.id}" sets warmProcess:true but backend is "${bot.backend}" (only "codex"/"claude" are supported as of this writing). warmProcess will be a no-op for this bot.`
|
|
125989
|
+
);
|
|
125990
|
+
}
|
|
125991
|
+
if (bot.taskHandle?.enabled !== void 0) {
|
|
125992
|
+
console.warn(
|
|
125993
|
+
`[botLoader] Bot "${bot.id}" has taskHandle.enabled set, but this field was removed in v2 (docs/task-handle.md \xA76.3 \u2014 the gate is now whether a tasklistGuid resolves, not a flag). The value is accepted for backward compat but never read; safe to delete it from the yaml.`
|
|
125994
|
+
);
|
|
125995
|
+
}
|
|
124428
125996
|
if (bot.memory_file) {
|
|
124429
125997
|
const memoryPath2 = path.join(botsDir, bot.memory_file);
|
|
124430
125998
|
try {
|
|
@@ -124456,25 +126024,8 @@ ${issues}`);
|
|
|
124456
126024
|
return bots;
|
|
124457
126025
|
}
|
|
124458
126026
|
|
|
124459
|
-
// src/config/paths.ts
|
|
124460
|
-
import { homedir } from "node:os";
|
|
124461
|
-
import { join, resolve } from "node:path";
|
|
124462
|
-
function larkwayHome() {
|
|
124463
|
-
const env = process.env.LARKWAY_HOME;
|
|
124464
|
-
if (env && env.trim() !== "") return resolve(env);
|
|
124465
|
-
return join(homedir(), ".larkway");
|
|
124466
|
-
}
|
|
124467
|
-
function assertSafePathSegment(label, value) {
|
|
124468
|
-
if (!/^[A-Za-z0-9_-]+$/.test(value)) {
|
|
124469
|
-
throw new Error(`${label} must be a safe path segment`);
|
|
124470
|
-
}
|
|
124471
|
-
}
|
|
124472
|
-
function resolveAgentWorkspacePathFromHome(home, agentId) {
|
|
124473
|
-
assertSafePathSegment("agentId", agentId);
|
|
124474
|
-
return join(home, "agents", agentId, "workspace");
|
|
124475
|
-
}
|
|
124476
|
-
|
|
124477
126027
|
// src/cli/botsStore.ts
|
|
126028
|
+
init_paths();
|
|
124478
126029
|
function resolveBotsDir() {
|
|
124479
126030
|
const override = process.env.LARKWAY_BOTS_DIR;
|
|
124480
126031
|
if (override && override.trim() !== "") return path2.resolve(override);
|
|
@@ -124637,6 +126188,7 @@ var import_dotenv = __toESM(require_main(), 1);
|
|
|
124637
126188
|
import { readFile as readFile3 } from "node:fs/promises";
|
|
124638
126189
|
import os from "node:os";
|
|
124639
126190
|
import path3 from "node:path";
|
|
126191
|
+
init_paths();
|
|
124640
126192
|
import_dotenv.default.config();
|
|
124641
126193
|
import_dotenv.default.config({ path: path3.join(larkwayHome(), ".env") });
|
|
124642
126194
|
var ConfigSchema = external_exports.object({
|
|
@@ -124696,6 +126248,7 @@ var ConfigJson = external_exports.object({
|
|
|
124696
126248
|
var DEFAULT_CONFIG_PATH = path3.join(larkwayHome(), "config.json");
|
|
124697
126249
|
|
|
124698
126250
|
// src/cli/hostConfig.ts
|
|
126251
|
+
init_paths();
|
|
124699
126252
|
function resolveLarkwayHome() {
|
|
124700
126253
|
return larkwayHome();
|
|
124701
126254
|
}
|
|
@@ -125420,6 +126973,7 @@ async function ensureMemoryScaffold(workspacePath) {
|
|
|
125420
126973
|
}
|
|
125421
126974
|
|
|
125422
126975
|
// src/cli/commands/init.ts
|
|
126976
|
+
init_paths();
|
|
125423
126977
|
var execFileAsync3 = promisify3(execFile3);
|
|
125424
126978
|
function checkNodeVersion() {
|
|
125425
126979
|
const version = process.versions.node;
|
|
@@ -125805,6 +127359,8 @@ async function runCreateBot(ctx, creds, basics) {
|
|
|
125805
127359
|
response_surface_prototype: DEFAULT_RESPONSE_SURFACE_PROTOTYPE,
|
|
125806
127360
|
runtime: "agent_workspace",
|
|
125807
127361
|
backend: basics.backend,
|
|
127362
|
+
cot: "brief",
|
|
127363
|
+
cotSurface: "bubble",
|
|
125808
127364
|
memory_file: memoryFile,
|
|
125809
127365
|
...basics.gitlabTokenEnv ? { gitlab_token_env: basics.gitlabTokenEnv } : {},
|
|
125810
127366
|
...basics.gitName && basics.gitEmail ? { git_identity: { name: basics.gitName, email: basics.gitEmail } } : {}
|
|
@@ -126103,7 +127659,7 @@ async function run(ctx, args) {
|
|
|
126103
127659
|
}
|
|
126104
127660
|
|
|
126105
127661
|
// src/cli/commands/doctor.ts
|
|
126106
|
-
import { access as access6, readdir as readdir4, readFile as
|
|
127662
|
+
import { access as access6, readdir as readdir4, readFile as readFile7, rm } from "node:fs/promises";
|
|
126107
127663
|
import { execFile as execFile5 } from "node:child_process";
|
|
126108
127664
|
import path10 from "node:path";
|
|
126109
127665
|
import { promisify as promisify5 } from "node:util";
|
|
@@ -126325,7 +127881,7 @@ async function checkWorktrees(ctx) {
|
|
|
126325
127881
|
const gitPath = path10.join(worktreeDir, ".git");
|
|
126326
127882
|
let gitContent = null;
|
|
126327
127883
|
try {
|
|
126328
|
-
const stat6 = await
|
|
127884
|
+
const stat6 = await readFile7(gitPath, "utf-8").catch(() => null);
|
|
126329
127885
|
gitContent = stat6;
|
|
126330
127886
|
} catch {
|
|
126331
127887
|
}
|
|
@@ -126471,6 +128027,94 @@ async function checkWsConnectivity(ctx, opts) {
|
|
|
126471
128027
|
message: `WS \u63A2\u6D4B\u5931\u8D25: ${result.message ?? "\u672A\u77E5\u9519\u8BEF"}\u3002${opts.lint ? "(CI \u6A21\u5F0F: \u7F51\u7EDC/\u8D85\u65F6\u4E0D\u8BA1\u5165 error)" : "\u8BF7\u68C0\u67E5\u98DE\u4E66 app \u51ED\u636E\u53CA\u7F51\u7EDC\u53EF\u8FBE\u6027\u3002"}`
|
|
126472
128028
|
};
|
|
126473
128029
|
}
|
|
128030
|
+
async function probeTaskScope(appId, appSecret, tasklistGuid) {
|
|
128031
|
+
try {
|
|
128032
|
+
const { Client: LarkSdkClient2 } = await Promise.resolve().then(() => __toESM(require_lib2(), 1));
|
|
128033
|
+
const { TaskListClient: TaskListClient2 } = await Promise.resolve().then(() => (init_client(), client_exports));
|
|
128034
|
+
const sdkClient = new LarkSdkClient2({ appId, appSecret });
|
|
128035
|
+
const taskClient = new TaskListClient2({
|
|
128036
|
+
request: (config) => sdkClient.request(config)
|
|
128037
|
+
});
|
|
128038
|
+
await taskClient.listTasklistTasks(tasklistGuid, { pageSize: 1 });
|
|
128039
|
+
return { ok: true };
|
|
128040
|
+
} catch (err2) {
|
|
128041
|
+
return { ok: false, message: err2 instanceof Error ? err2.message : String(err2) };
|
|
128042
|
+
}
|
|
128043
|
+
}
|
|
128044
|
+
var TASK_HANDLE_REQUIRED_SCOPES = [
|
|
128045
|
+
"task:tasklist:read",
|
|
128046
|
+
"task:tasklist:write",
|
|
128047
|
+
"task:task:read",
|
|
128048
|
+
"task:comment:write"
|
|
128049
|
+
];
|
|
128050
|
+
async function checkTaskHandle(ctx, opts) {
|
|
128051
|
+
const results = [];
|
|
128052
|
+
const botIds = await ctx.botsStore.listBots();
|
|
128053
|
+
if (botIds.length === 0) return results;
|
|
128054
|
+
const { resolveTaskTeamRegistryPath: resolveTaskTeamRegistryPath2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
128055
|
+
const { readTeamTasklistGuid: readTeamTasklistGuid2 } = await Promise.resolve().then(() => (init_teamRegistry(), teamRegistry_exports));
|
|
128056
|
+
const registryGuid = await readTeamTasklistGuid2(resolveTaskTeamRegistryPath2());
|
|
128057
|
+
let anyConfigured = false;
|
|
128058
|
+
for (const id of botIds) {
|
|
128059
|
+
let bot;
|
|
128060
|
+
try {
|
|
128061
|
+
bot = await ctx.botsStore.readBot(id);
|
|
128062
|
+
} catch {
|
|
128063
|
+
continue;
|
|
128064
|
+
}
|
|
128065
|
+
const guid = bot.taskHandle?.tasklistGuid ?? registryGuid;
|
|
128066
|
+
if (!guid) continue;
|
|
128067
|
+
anyConfigured = true;
|
|
128068
|
+
if (process.env["LARKWAY_SKIP_WS_PROBE"] === "1") {
|
|
128069
|
+
results.push({
|
|
128070
|
+
id: `task-handle-${id}`,
|
|
128071
|
+
label: `bot "${id}" \u8BDD\u9898\u2194\u4EFB\u52A1\u53E5\u67C4`,
|
|
128072
|
+
status: "ok",
|
|
128073
|
+
message: `\u5DF2\u914D\u7F6E(guid=${guid}),scope \u63A2\u6D4B\u5DF2\u8DF3\u8FC7(LARKWAY_SKIP_WS_PROBE=1)\u3002`
|
|
128074
|
+
});
|
|
128075
|
+
continue;
|
|
128076
|
+
}
|
|
128077
|
+
const appSecret = await ctx.hostConfig.readSecret(bot.app_secret_env);
|
|
128078
|
+
if (!appSecret) {
|
|
128079
|
+
results.push({
|
|
128080
|
+
id: `task-handle-${id}`,
|
|
128081
|
+
label: `bot "${id}" \u8BDD\u9898\u2194\u4EFB\u52A1\u53E5\u67C4`,
|
|
128082
|
+
status: "warn",
|
|
128083
|
+
message: `\u5DF2\u914D\u7F6E guid=${guid},\u4F46 AppSecret \u7F3A\u5931,\u8DF3\u8FC7 scope \u63A2\u6D4B(\u89C1\u98DE\u4E66\u51ED\u636E\u68C0\u67E5\u9879)\u3002`
|
|
128084
|
+
});
|
|
128085
|
+
continue;
|
|
128086
|
+
}
|
|
128087
|
+
const probe = await probeTaskScope(bot.app_id, appSecret, guid);
|
|
128088
|
+
if (probe.ok) {
|
|
128089
|
+
results.push({
|
|
128090
|
+
id: `task-handle-${id}`,
|
|
128091
|
+
label: `bot "${id}" \u8BDD\u9898\u2194\u4EFB\u52A1\u53E5\u67C4`,
|
|
128092
|
+
status: "ok",
|
|
128093
|
+
message: `\u5DF2\u914D\u7F6E(guid=${guid}),task scope \u63A2\u6D4B\u6210\u529F\u3002`
|
|
128094
|
+
});
|
|
128095
|
+
} else {
|
|
128096
|
+
const scopeLink = `https://open.feishu.cn/app/${bot.app_id}/auth?q=${TASK_HANDLE_REQUIRED_SCOPES.join(",")}&op_from=doctor&token_type=tenant`;
|
|
128097
|
+
const looksLikeScopeError = /scope|permission|无权限|未授权|access.denied/i.test(probe.message ?? "");
|
|
128098
|
+
results.push({
|
|
128099
|
+
id: `task-handle-${id}`,
|
|
128100
|
+
label: `bot "${id}" \u8BDD\u9898\u2194\u4EFB\u52A1\u53E5\u67C4`,
|
|
128101
|
+
status: opts.lint && !looksLikeScopeError ? "warn" : "error",
|
|
128102
|
+
message: `\u5DF2\u914D\u7F6E guid=${guid},\u4F46 task scope \u63A2\u6D4B\u5931\u8D25:${probe.message ?? "\u672A\u77E5\u9519\u8BEF"}
|
|
128103
|
+
\u9700\u8981\u4EE5\u4E0B scope:${TASK_HANDLE_REQUIRED_SCOPES.join(", ")}
|
|
128104
|
+
\u5F00\u901A\u94FE\u63A5:${scopeLink}`
|
|
128105
|
+
});
|
|
128106
|
+
}
|
|
128107
|
+
}
|
|
128108
|
+
if (!anyConfigured) {
|
|
128109
|
+
results.push({
|
|
128110
|
+
id: "task-handle-not-configured",
|
|
128111
|
+
label: "\u8BDD\u9898\u2194\u4EFB\u52A1\u53E5\u67C4 (\u53EF\u9009)",
|
|
128112
|
+
status: "ok",
|
|
128113
|
+
message: '\u672A\u914D\u7F6E\u4EFB\u4F55 bot \u7684\u8BDD\u9898\u2194\u4EFB\u52A1\u53E5\u67C4(\u53EF\u9009\u529F\u80FD)\u3002\u60F3\u542F\u7528:larkway tasklist-init --adopt "<\u6E05\u5355\u540D>" --team <bot1,bot2,\u2026>(\u89C1 docs/task-handle.md \xA77)\u3002'
|
|
128114
|
+
});
|
|
128115
|
+
}
|
|
128116
|
+
return results;
|
|
128117
|
+
}
|
|
126474
128118
|
async function runAllChecks(ctx, opts) {
|
|
126475
128119
|
const results = [];
|
|
126476
128120
|
results.push(await checkClaude(ctx));
|
|
@@ -126483,6 +128127,8 @@ async function runAllChecks(ctx, opts) {
|
|
|
126483
128127
|
results.push(await checkWsConnectivity(ctx, opts));
|
|
126484
128128
|
const codexChecks = await checkCodex(ctx);
|
|
126485
128129
|
results.push(...codexChecks);
|
|
128130
|
+
const taskHandleChecks = await checkTaskHandle(ctx, opts);
|
|
128131
|
+
results.push(...taskHandleChecks);
|
|
126486
128132
|
return results;
|
|
126487
128133
|
}
|
|
126488
128134
|
function exitCodeFromResults(results) {
|
|
@@ -126664,6 +128310,7 @@ async function run2(ctx, args) {
|
|
|
126664
128310
|
|
|
126665
128311
|
// src/cli/commands/bot.ts
|
|
126666
128312
|
import path11 from "node:path";
|
|
128313
|
+
init_paths();
|
|
126667
128314
|
async function run3(ctx, args) {
|
|
126668
128315
|
const sub = args[0];
|
|
126669
128316
|
const rest = args.slice(1);
|
|
@@ -127265,10 +128912,10 @@ function inferLarkwayHome(botsDir, fallback) {
|
|
|
127265
128912
|
}
|
|
127266
128913
|
|
|
127267
128914
|
// src/cli/commands/memory.ts
|
|
127268
|
-
import { readFile as
|
|
128915
|
+
import { readFile as readFile8 } from "node:fs/promises";
|
|
127269
128916
|
import { spawn } from "node:child_process";
|
|
127270
128917
|
import { tmpdir } from "node:os";
|
|
127271
|
-
import { mkdir as
|
|
128918
|
+
import { mkdir as mkdir5, writeFile as writeFile6, rm as rm2 } from "node:fs/promises";
|
|
127272
128919
|
import path12 from "node:path";
|
|
127273
128920
|
import process2 from "node:process";
|
|
127274
128921
|
function parseArgs(args) {
|
|
@@ -127289,10 +128936,10 @@ function parseArgs(args) {
|
|
|
127289
128936
|
async function openInEditor(initial) {
|
|
127290
128937
|
const editor = process2.env.EDITOR || process2.env.VISUAL || "vi";
|
|
127291
128938
|
const tmpDir = path12.join(tmpdir(), `larkway-memory-${process2.pid}`);
|
|
127292
|
-
await
|
|
128939
|
+
await mkdir5(tmpDir, { recursive: true });
|
|
127293
128940
|
const tmpFile = path12.join(tmpDir, "memory.md");
|
|
127294
128941
|
try {
|
|
127295
|
-
await
|
|
128942
|
+
await writeFile6(tmpFile, initial, "utf-8");
|
|
127296
128943
|
await new Promise((resolve2, reject) => {
|
|
127297
128944
|
const child = spawn(editor, [tmpFile], {
|
|
127298
128945
|
stdio: "inherit",
|
|
@@ -127305,7 +128952,7 @@ async function openInEditor(initial) {
|
|
|
127305
128952
|
else resolve2();
|
|
127306
128953
|
});
|
|
127307
128954
|
});
|
|
127308
|
-
return await
|
|
128955
|
+
return await readFile8(tmpFile, "utf-8");
|
|
127309
128956
|
} finally {
|
|
127310
128957
|
await rm2(tmpDir, { recursive: true, force: true });
|
|
127311
128958
|
}
|
|
@@ -127346,7 +128993,7 @@ async function subSet(ctx, id, file) {
|
|
|
127346
128993
|
if (!await assertBotExists(ctx, id)) return 1;
|
|
127347
128994
|
let content;
|
|
127348
128995
|
try {
|
|
127349
|
-
content = await
|
|
128996
|
+
content = await readFile8(file, "utf-8");
|
|
127350
128997
|
} catch (e) {
|
|
127351
128998
|
const msg = `\u65E0\u6CD5\u8BFB\u53D6\u6587\u4EF6 "${file}": ${e instanceof Error ? e.message : String(e)}`;
|
|
127352
128999
|
if (ctx.flags.json) {
|
|
@@ -127467,8 +129114,9 @@ async function run4(ctx, args) {
|
|
|
127467
129114
|
}
|
|
127468
129115
|
|
|
127469
129116
|
// src/cli/commands/perms.ts
|
|
127470
|
-
import { mkdir as
|
|
129117
|
+
import { mkdir as mkdir6, readFile as readFile9, writeFile as writeFile7 } from "node:fs/promises";
|
|
127471
129118
|
import path13 from "node:path";
|
|
129119
|
+
init_paths();
|
|
127472
129120
|
function parsePermsArgs(args) {
|
|
127473
129121
|
const flags = {
|
|
127474
129122
|
addChats: [],
|
|
@@ -127664,7 +129312,7 @@ async function writePermissionGrants(ctx, id, flags) {
|
|
|
127664
129312
|
const grantedPath = path13.join(workspacePath, "permissions-granted.md");
|
|
127665
129313
|
const grants = [];
|
|
127666
129314
|
if (flags.grantFromRequest) {
|
|
127667
|
-
const requestText = await
|
|
129315
|
+
const requestText = await readFile9(requestPath, "utf8").catch(() => "");
|
|
127668
129316
|
grants.push(...extractRequestLines(requestText));
|
|
127669
129317
|
}
|
|
127670
129318
|
grants.push(...renderCapabilityGrantLines(splitPermissionList(flags.grantPermissions)));
|
|
@@ -127684,8 +129332,8 @@ async function writePermissionGrants(ctx, id, flags) {
|
|
|
127684
129332
|
"Do not record secret values here.",
|
|
127685
129333
|
""
|
|
127686
129334
|
].filter((line) => line !== void 0).join("\n");
|
|
127687
|
-
await
|
|
127688
|
-
await
|
|
129335
|
+
await mkdir6(path13.dirname(grantedPath), { recursive: true });
|
|
129336
|
+
await writeFile7(grantedPath, body, "utf8");
|
|
127689
129337
|
return { filePath: grantedPath, grants };
|
|
127690
129338
|
}
|
|
127691
129339
|
async function editChatsInteractive(config, ctx) {
|
|
@@ -128036,13 +129684,14 @@ __export(bridgeControl_exports, {
|
|
|
128036
129684
|
});
|
|
128037
129685
|
import { spawn as spawn2, execFile as execFile6 } from "node:child_process";
|
|
128038
129686
|
import { openSync, constants as fsConstants } from "node:fs";
|
|
128039
|
-
import { readFile as
|
|
129687
|
+
import { readFile as readFile10, writeFile as writeFile8, unlink as unlink5, mkdir as mkdir7, readdir as readdir5, access as access7 } from "node:fs/promises";
|
|
128040
129688
|
import { promisify as promisify6 } from "node:util";
|
|
128041
129689
|
import path15 from "node:path";
|
|
128042
129690
|
import process3 from "node:process";
|
|
128043
129691
|
import { stat as stat3 } from "node:fs/promises";
|
|
128044
129692
|
|
|
128045
129693
|
// src/bridge/statusFile.ts
|
|
129694
|
+
init_paths();
|
|
128046
129695
|
import fs2 from "node:fs/promises";
|
|
128047
129696
|
import path14 from "node:path";
|
|
128048
129697
|
var DEFAULT_STALE_MS = 9e4;
|
|
@@ -128113,7 +129762,7 @@ async function resolveDistMain() {
|
|
|
128113
129762
|
async function readPid(larkwayDir) {
|
|
128114
129763
|
const pidFile = bridgePidPath(larkwayDir);
|
|
128115
129764
|
try {
|
|
128116
|
-
const raw = (await
|
|
129765
|
+
const raw = (await readFile10(pidFile, "utf-8")).trim();
|
|
128117
129766
|
const n = Number(raw);
|
|
128118
129767
|
return Number.isInteger(n) && n > 0 ? n : null;
|
|
128119
129768
|
} catch (e) {
|
|
@@ -128123,8 +129772,8 @@ async function readPid(larkwayDir) {
|
|
|
128123
129772
|
}
|
|
128124
129773
|
async function writePid(larkwayDir, pid) {
|
|
128125
129774
|
const pidFile = bridgePidPath(larkwayDir);
|
|
128126
|
-
await
|
|
128127
|
-
await
|
|
129775
|
+
await mkdir7(path15.dirname(pidFile), { recursive: true });
|
|
129776
|
+
await writeFile8(pidFile, String(pid) + "\n", "utf-8");
|
|
128128
129777
|
}
|
|
128129
129778
|
async function removePid(larkwayDir) {
|
|
128130
129779
|
const pidFile = bridgePidPath(larkwayDir);
|
|
@@ -128184,7 +129833,7 @@ async function listMainBridgePids(mainProcessPattern) {
|
|
|
128184
129833
|
async function hasAnyFreshStatusJson(larkwayDir, nowMs, staleMs = DEFAULT_STALE_MS) {
|
|
128185
129834
|
const checkFile2 = async (file) => {
|
|
128186
129835
|
try {
|
|
128187
|
-
const raw = await
|
|
129836
|
+
const raw = await readFile10(file, "utf-8");
|
|
128188
129837
|
const parsed = JSON.parse(raw);
|
|
128189
129838
|
if (typeof parsed["updatedAt"] !== "string") return { fresh: false, pid: null };
|
|
128190
129839
|
const updatedMs = Date.parse(parsed["updatedAt"]);
|
|
@@ -128271,7 +129920,7 @@ async function startBridge(larkwayDir, opts) {
|
|
|
128271
129920
|
await stopBridge(larkwayDir, opts);
|
|
128272
129921
|
}
|
|
128273
129922
|
const logPath = bridgeLogPath(larkwayDir);
|
|
128274
|
-
await
|
|
129923
|
+
await mkdir7(path15.dirname(logPath), { recursive: true });
|
|
128275
129924
|
let supervisorExists = false;
|
|
128276
129925
|
try {
|
|
128277
129926
|
await access7(supervisorScript);
|
|
@@ -128382,7 +130031,7 @@ async function tailBridgeLog(larkwayDir, n = 80) {
|
|
|
128382
130031
|
await fh.close();
|
|
128383
130032
|
}
|
|
128384
130033
|
} else {
|
|
128385
|
-
content = await
|
|
130034
|
+
content = await readFile10(logPath, "utf-8");
|
|
128386
130035
|
}
|
|
128387
130036
|
} catch (e) {
|
|
128388
130037
|
if (e.code === "ENOENT") {
|
|
@@ -128645,7 +130294,7 @@ async function run6(ctx, args) {
|
|
|
128645
130294
|
|
|
128646
130295
|
// src/cli/commands/update.ts
|
|
128647
130296
|
import { spawn as spawn4 } from "node:child_process";
|
|
128648
|
-
import { readFile as
|
|
130297
|
+
import { readFile as readFile11, access as access9 } from "node:fs/promises";
|
|
128649
130298
|
import "node:module";
|
|
128650
130299
|
import path17 from "node:path";
|
|
128651
130300
|
var DEFAULT_NPM_PACKAGE_SPEC = "larkway@latest";
|
|
@@ -128724,7 +130373,7 @@ async function findRepoRoot(startDir) {
|
|
|
128724
130373
|
const pkgPath = path17.join(dir, "package.json");
|
|
128725
130374
|
try {
|
|
128726
130375
|
await access9(pkgPath);
|
|
128727
|
-
const raw = await
|
|
130376
|
+
const raw = await readFile11(pkgPath, "utf-8");
|
|
128728
130377
|
const pkg = JSON.parse(raw);
|
|
128729
130378
|
if (pkg.name === "larkway") return dir;
|
|
128730
130379
|
} catch {
|
|
@@ -128961,15 +130610,16 @@ async function run7(ctx, args) {
|
|
|
128961
130610
|
import http from "node:http";
|
|
128962
130611
|
import { randomBytes } from "node:crypto";
|
|
128963
130612
|
import { existsSync } from "node:fs";
|
|
128964
|
-
import { readFile as
|
|
130613
|
+
import { readFile as readFile14, stat as stat5 } from "node:fs/promises";
|
|
128965
130614
|
import path22 from "node:path";
|
|
128966
130615
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
128967
130616
|
|
|
128968
130617
|
// src/web/api.ts
|
|
128969
|
-
import { readdir as readdir6, readFile as
|
|
130618
|
+
import { readdir as readdir6, readFile as readFile13, stat as stat4 } from "node:fs/promises";
|
|
128970
130619
|
import { execFile as execFileCallback2 } from "node:child_process";
|
|
128971
130620
|
import path21 from "node:path";
|
|
128972
130621
|
import { promisify as promisify8 } from "node:util";
|
|
130622
|
+
init_paths();
|
|
128973
130623
|
|
|
128974
130624
|
// src/version.ts
|
|
128975
130625
|
import { readFileSync } from "node:fs";
|
|
@@ -129036,8 +130686,9 @@ function isRuntimeEventRecord(value) {
|
|
|
129036
130686
|
// src/web/onboardSession.ts
|
|
129037
130687
|
var QRCode = __toESM(require_lib3(), 1);
|
|
129038
130688
|
import { randomUUID } from "node:crypto";
|
|
129039
|
-
import { mkdir as
|
|
130689
|
+
import { mkdir as mkdir8, writeFile as writeFile9, rename as rename5, chmod as chmod2, readFile as readFile12 } from "node:fs/promises";
|
|
129040
130690
|
import path20 from "node:path";
|
|
130691
|
+
init_paths();
|
|
129041
130692
|
async function defaultRegisterApp(opts) {
|
|
129042
130693
|
const sdk = await Promise.resolve().then(() => __toESM(require_lib2(), 1));
|
|
129043
130694
|
return sdk.registerApp(opts);
|
|
@@ -129069,10 +130720,10 @@ function quoteIfNeeded2(v) {
|
|
|
129069
130720
|
return /[\s#"'=]/.test(v) ? `"${v.replace(/"/g, '\\"')}"` : v;
|
|
129070
130721
|
}
|
|
129071
130722
|
async function atomicWrite3(file, content) {
|
|
129072
|
-
await
|
|
130723
|
+
await mkdir8(path20.dirname(file), { recursive: true });
|
|
129073
130724
|
const tmp = `${file}.${process.pid}.${Date.now()}.tmp`;
|
|
129074
|
-
await
|
|
129075
|
-
await
|
|
130725
|
+
await writeFile9(tmp, content, "utf-8");
|
|
130726
|
+
await rename5(tmp, file);
|
|
129076
130727
|
}
|
|
129077
130728
|
async function writeSecretTo(envPath, envName, value) {
|
|
129078
130729
|
if (!ENV_NAME_RE.test(envName)) {
|
|
@@ -129080,7 +130731,7 @@ async function writeSecretTo(envPath, envName, value) {
|
|
|
129080
130731
|
}
|
|
129081
130732
|
const map2 = /* @__PURE__ */ new Map();
|
|
129082
130733
|
try {
|
|
129083
|
-
const raw = await
|
|
130734
|
+
const raw = await readFile12(envPath, "utf-8");
|
|
129084
130735
|
for (const line of raw.split("\n")) {
|
|
129085
130736
|
const m = ENV_LINE_RE.exec(line.trim());
|
|
129086
130737
|
if (m) map2.set(m[1], stripQuotes2(m[2]));
|
|
@@ -129095,7 +130746,7 @@ async function writeSecretTo(envPath, envName, value) {
|
|
|
129095
130746
|
}
|
|
129096
130747
|
async function botYamlExists(botsDir, id) {
|
|
129097
130748
|
try {
|
|
129098
|
-
await
|
|
130749
|
+
await readFile12(path20.join(botsDir, `${id}.yaml`), "utf-8");
|
|
129099
130750
|
return true;
|
|
129100
130751
|
} catch {
|
|
129101
130752
|
return false;
|
|
@@ -129164,6 +130815,8 @@ async function createBotFromCreds(opts) {
|
|
|
129164
130815
|
response_surface_prototype: DEFAULT_RESPONSE_SURFACE_PROTOTYPE,
|
|
129165
130816
|
runtime: "agent_workspace",
|
|
129166
130817
|
backend: form.backend && form.backend.trim() ? form.backend.trim() : "codex",
|
|
130818
|
+
cot: "brief",
|
|
130819
|
+
cotSurface: "bubble",
|
|
129167
130820
|
// Persist the Feishu avatar URL so the Web 管理面 can show an avatar before
|
|
129168
130821
|
// the bridge writes status.json (pre-bridge / central roster). Best-effort:
|
|
129169
130822
|
// only set when resolveBotIdentity returned a valid url.
|
|
@@ -129524,7 +131177,7 @@ async function readBotFromDir(dir, id) {
|
|
|
129524
131177
|
const memFile = path21.join(dir, `${id}.memory.md`);
|
|
129525
131178
|
let raw;
|
|
129526
131179
|
try {
|
|
129527
|
-
raw = await
|
|
131180
|
+
raw = await readFile13(yamlFile, "utf-8");
|
|
129528
131181
|
} catch (e) {
|
|
129529
131182
|
if (e.code === "ENOENT") {
|
|
129530
131183
|
throw new Error(`Bot "${id}" not found`);
|
|
@@ -129539,7 +131192,7 @@ async function readBotFromDir(dir, id) {
|
|
|
129539
131192
|
}
|
|
129540
131193
|
let memory = null;
|
|
129541
131194
|
try {
|
|
129542
|
-
memory = await
|
|
131195
|
+
memory = await readFile13(memFile, "utf-8");
|
|
129543
131196
|
} catch {
|
|
129544
131197
|
}
|
|
129545
131198
|
return { config, memory };
|
|
@@ -129696,8 +131349,8 @@ async function loadChatNameMap(profile) {
|
|
|
129696
131349
|
try {
|
|
129697
131350
|
const { stdout: stdout2 } = await eventExecFile("lark-cli", args, { timeout: 8e3 });
|
|
129698
131351
|
for (const chat of extractLarkCliChats(stdout2)) {
|
|
129699
|
-
const chatId =
|
|
129700
|
-
const name =
|
|
131352
|
+
const chatId = stringField3(chat, "chat_id");
|
|
131353
|
+
const name = stringField3(chat, "name");
|
|
129701
131354
|
if (chatId && name) names.set(chatId, name);
|
|
129702
131355
|
}
|
|
129703
131356
|
} catch {
|
|
@@ -129724,7 +131377,7 @@ function extractLarkCliChats(stdout2) {
|
|
|
129724
131377
|
function isLarkOpenChatId(value) {
|
|
129725
131378
|
return typeof value === "string" && value.startsWith("oc_");
|
|
129726
131379
|
}
|
|
129727
|
-
function
|
|
131380
|
+
function stringField3(value, key) {
|
|
129728
131381
|
if (!value || typeof value !== "object") return void 0;
|
|
129729
131382
|
const out = value[key];
|
|
129730
131383
|
return typeof out === "string" ? out : void 0;
|
|
@@ -129764,6 +131417,13 @@ var putBot = async (req) => {
|
|
|
129764
131417
|
for (const k of ["name", "description", "chats", "repos", "turn_taking_limit", "backend"]) {
|
|
129765
131418
|
if (k in bodyWithoutTokenFields) merged[k] = bodyWithoutTokenFields[k];
|
|
129766
131419
|
}
|
|
131420
|
+
for (const k of ["model", "effort"]) {
|
|
131421
|
+
if (k in bodyWithoutTokenFields) {
|
|
131422
|
+
const v = bodyWithoutTokenFields[k];
|
|
131423
|
+
if (typeof v === "string" && v.trim().length > 0) merged[k] = v.trim();
|
|
131424
|
+
else delete merged[k];
|
|
131425
|
+
}
|
|
131426
|
+
}
|
|
129767
131427
|
if (tokenValue !== void 0) {
|
|
129768
131428
|
if (tokenValue.trim().length > 0) {
|
|
129769
131429
|
const envName = gitlabTokenEnvNameForBot(id);
|
|
@@ -129786,6 +131446,10 @@ var putBot = async (req) => {
|
|
|
129786
131446
|
backend: "codex",
|
|
129787
131447
|
...bodyWithoutTokenFields
|
|
129788
131448
|
};
|
|
131449
|
+
for (const k of ["model", "effort"]) {
|
|
131450
|
+
const v = draft[k];
|
|
131451
|
+
if (typeof v === "string" && v.trim().length === 0) delete draft[k];
|
|
131452
|
+
}
|
|
129789
131453
|
if (tokenValue !== void 0) {
|
|
129790
131454
|
if (tokenValue.trim().length > 0) {
|
|
129791
131455
|
const envName = gitlabTokenEnvNameForBot(id);
|
|
@@ -130418,7 +132082,7 @@ async function handleStatic(res, pathname, token) {
|
|
|
130418
132082
|
}
|
|
130419
132083
|
let buf;
|
|
130420
132084
|
try {
|
|
130421
|
-
buf = await
|
|
132085
|
+
buf = await readFile14(target);
|
|
130422
132086
|
} catch {
|
|
130423
132087
|
writeText(res, 404, "not found");
|
|
130424
132088
|
return;
|
|
@@ -130531,7 +132195,8 @@ async function run8(ctx, args) {
|
|
|
130531
132195
|
}
|
|
130532
132196
|
|
|
130533
132197
|
// src/cli/commands/dogfood.ts
|
|
130534
|
-
|
|
132198
|
+
init_paths();
|
|
132199
|
+
import { access as access10, readFile as readFile15, readdir as readdir7 } from "node:fs/promises";
|
|
130535
132200
|
import path24 from "node:path";
|
|
130536
132201
|
|
|
130537
132202
|
// src/agent/permissionGate.ts
|
|
@@ -131113,7 +132778,7 @@ async function listMarkdownFiles(root) {
|
|
|
131113
132778
|
}
|
|
131114
132779
|
async function readTextOrNull(filePath) {
|
|
131115
132780
|
try {
|
|
131116
|
-
return await
|
|
132781
|
+
return await readFile15(filePath, "utf8");
|
|
131117
132782
|
} catch {
|
|
131118
132783
|
return null;
|
|
131119
132784
|
}
|
|
@@ -131124,6 +132789,563 @@ function exitCodeFor(checks) {
|
|
|
131124
132789
|
return 0;
|
|
131125
132790
|
}
|
|
131126
132791
|
|
|
132792
|
+
// src/cli/commands/tasklistInit.ts
|
|
132793
|
+
var import_node_sdk2 = __toESM(require_lib2(), 1);
|
|
132794
|
+
init_client();
|
|
132795
|
+
init_paths();
|
|
132796
|
+
init_teamRegistry();
|
|
132797
|
+
|
|
132798
|
+
// src/cli/ownerIdentity.ts
|
|
132799
|
+
import { spawnSync } from "node:child_process";
|
|
132800
|
+
function resolveOwnerOpenId(profile, _spawnSync = spawnSync) {
|
|
132801
|
+
try {
|
|
132802
|
+
const result = _spawnSync("lark-cli", ["auth", "status", "--profile", profile, "--json"], {
|
|
132803
|
+
encoding: "utf-8",
|
|
132804
|
+
timeout: 1e4
|
|
132805
|
+
});
|
|
132806
|
+
if (result.status !== 0) return void 0;
|
|
132807
|
+
const stdout2 = typeof result.stdout === "string" ? result.stdout : "";
|
|
132808
|
+
if (stdout2.trim().length === 0) return void 0;
|
|
132809
|
+
const parsed = JSON.parse(stdout2);
|
|
132810
|
+
if (typeof parsed !== "object" || parsed === null) return void 0;
|
|
132811
|
+
const identities = parsed["identities"];
|
|
132812
|
+
if (typeof identities !== "object" || identities === null) return void 0;
|
|
132813
|
+
const user = identities["user"];
|
|
132814
|
+
if (typeof user !== "object" || user === null) return void 0;
|
|
132815
|
+
const openId = user["openId"];
|
|
132816
|
+
return typeof openId === "string" && openId.length > 0 ? openId : void 0;
|
|
132817
|
+
} catch {
|
|
132818
|
+
return void 0;
|
|
132819
|
+
}
|
|
132820
|
+
}
|
|
132821
|
+
|
|
132822
|
+
// src/lark/profileBootstrap.ts
|
|
132823
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
132824
|
+
function deriveLarkCliProfile(explicitProfile, appId) {
|
|
132825
|
+
return explicitProfile ?? appId;
|
|
132826
|
+
}
|
|
132827
|
+
|
|
132828
|
+
// src/cli/userTasklistOps.ts
|
|
132829
|
+
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
132830
|
+
var SPAWN_TIMEOUT_MS = 15e3;
|
|
132831
|
+
function runLarkCliJson(args, spawnSyncFn) {
|
|
132832
|
+
let result;
|
|
132833
|
+
try {
|
|
132834
|
+
result = spawnSyncFn("lark-cli", args, { encoding: "utf-8", timeout: SPAWN_TIMEOUT_MS });
|
|
132835
|
+
} catch (err2) {
|
|
132836
|
+
return {
|
|
132837
|
+
ok: false,
|
|
132838
|
+
error: `\u65E0\u6CD5\u6267\u884C lark-cli(${err2 instanceof Error ? err2.message : String(err2)})\u2014\u2014 \u786E\u8BA4 lark-cli \u5DF2\u5B89\u88C5\u4E14\u5728 PATH \u91CC\u3002`
|
|
132839
|
+
};
|
|
132840
|
+
}
|
|
132841
|
+
const stdout2 = typeof result.stdout === "string" ? result.stdout : "";
|
|
132842
|
+
const stderr = typeof result.stderr === "string" ? result.stderr : "";
|
|
132843
|
+
if (stdout2.trim().length === 0) {
|
|
132844
|
+
return {
|
|
132845
|
+
ok: false,
|
|
132846
|
+
error: `lark-cli \u6CA1\u6709\u8F93\u51FA\u4EFB\u4F55\u5185\u5BB9(exit=${result.status ?? "unknown"})\u3002${stderr ? `stderr: ${stderr.slice(0, 500)}` : ""}`
|
|
132847
|
+
};
|
|
132848
|
+
}
|
|
132849
|
+
let parsed;
|
|
132850
|
+
try {
|
|
132851
|
+
parsed = JSON.parse(stdout2);
|
|
132852
|
+
} catch {
|
|
132853
|
+
return { ok: false, error: `lark-cli \u8F93\u51FA\u4E0D\u662F\u5408\u6CD5 JSON(exit=${result.status ?? "unknown"}): ${stdout2.slice(0, 500)}` };
|
|
132854
|
+
}
|
|
132855
|
+
if (typeof parsed === "object" && parsed !== null && parsed["ok"] === false) {
|
|
132856
|
+
const errObj = parsed["error"];
|
|
132857
|
+
const rec = typeof errObj === "object" && errObj !== null ? errObj : {};
|
|
132858
|
+
const message = typeof rec["message"] === "string" ? rec["message"] : "\u672A\u77E5\u9519\u8BEF";
|
|
132859
|
+
const hint = typeof rec["hint"] === "string" && rec["hint"] ? `
|
|
132860
|
+
\u63D0\u793A:${rec["hint"]}` : "";
|
|
132861
|
+
return { ok: false, error: `${message}${hint}` };
|
|
132862
|
+
}
|
|
132863
|
+
return { ok: true, data: parsed };
|
|
132864
|
+
}
|
|
132865
|
+
function listUserTasklists(profile, spawnSyncFn = spawnSync3) {
|
|
132866
|
+
const result = runLarkCliJson(
|
|
132867
|
+
["task", "tasklists", "list", "--as", "user", "--profile", profile, "--page-all", "--json"],
|
|
132868
|
+
spawnSyncFn
|
|
132869
|
+
);
|
|
132870
|
+
if (!result.ok) return result;
|
|
132871
|
+
const data = result.data;
|
|
132872
|
+
const items = typeof data === "object" && data !== null ? data["items"] : void 0;
|
|
132873
|
+
if (!Array.isArray(items)) {
|
|
132874
|
+
return { ok: false, error: `lark-cli \u8FD4\u56DE\u7684\u6E05\u5355\u5217\u8868\u5F62\u72B6\u4E0D\u5BF9(\u7F3A\u5C11 items \u6570\u7EC4):${JSON.stringify(data).slice(0, 300)}` };
|
|
132875
|
+
}
|
|
132876
|
+
const tasklists = [];
|
|
132877
|
+
for (const raw of items) {
|
|
132878
|
+
if (typeof raw !== "object" || raw === null) continue;
|
|
132879
|
+
const guid = raw["guid"];
|
|
132880
|
+
const name = raw["name"];
|
|
132881
|
+
if (typeof guid === "string" && guid.length > 0) {
|
|
132882
|
+
tasklists.push({ guid, name: typeof name === "string" ? name : "(\u65E0\u6807\u9898)" });
|
|
132883
|
+
}
|
|
132884
|
+
}
|
|
132885
|
+
return { ok: true, data: tasklists };
|
|
132886
|
+
}
|
|
132887
|
+
function addTasklistMembersAsUser(profile, tasklistGuid, members, spawnSyncFn = spawnSync3) {
|
|
132888
|
+
const dataJson = JSON.stringify({ members });
|
|
132889
|
+
return runLarkCliJson(
|
|
132890
|
+
[
|
|
132891
|
+
"task",
|
|
132892
|
+
"tasklists",
|
|
132893
|
+
"add_members",
|
|
132894
|
+
"--as",
|
|
132895
|
+
"user",
|
|
132896
|
+
"--profile",
|
|
132897
|
+
profile,
|
|
132898
|
+
"--tasklist-guid",
|
|
132899
|
+
tasklistGuid,
|
|
132900
|
+
"--data",
|
|
132901
|
+
dataJson,
|
|
132902
|
+
"--json"
|
|
132903
|
+
],
|
|
132904
|
+
spawnSyncFn
|
|
132905
|
+
);
|
|
132906
|
+
}
|
|
132907
|
+
function getUserTasklistMembers(profile, tasklistGuid, spawnSyncFn = spawnSync3) {
|
|
132908
|
+
const result = runLarkCliJson(
|
|
132909
|
+
["task", "tasklists", "get", "--as", "user", "--profile", profile, "--tasklist-guid", tasklistGuid, "--json"],
|
|
132910
|
+
spawnSyncFn
|
|
132911
|
+
);
|
|
132912
|
+
if (!result.ok) return result;
|
|
132913
|
+
const data = result.data;
|
|
132914
|
+
const tasklist = typeof data === "object" && data !== null ? data["tasklist"] : void 0;
|
|
132915
|
+
const members = typeof tasklist === "object" && tasklist !== null ? tasklist["members"] : void 0;
|
|
132916
|
+
if (!Array.isArray(members)) {
|
|
132917
|
+
return { ok: false, error: `lark-cli \u8FD4\u56DE\u7684\u6E05\u5355\u8BE6\u60C5\u5F62\u72B6\u4E0D\u5BF9(\u7F3A\u5C11 tasklist.members \u6570\u7EC4):${JSON.stringify(data).slice(0, 300)}` };
|
|
132918
|
+
}
|
|
132919
|
+
return {
|
|
132920
|
+
ok: true,
|
|
132921
|
+
data: members.filter((m) => typeof m === "object" && m !== null).map((m) => ({
|
|
132922
|
+
id: String(m["id"] ?? ""),
|
|
132923
|
+
type: typeof m["type"] === "string" ? m["type"] : void 0,
|
|
132924
|
+
role: typeof m["role"] === "string" ? m["role"] : void 0
|
|
132925
|
+
}))
|
|
132926
|
+
};
|
|
132927
|
+
}
|
|
132928
|
+
|
|
132929
|
+
// src/cli/commands/tasklistInit.ts
|
|
132930
|
+
function parseArgs2(args) {
|
|
132931
|
+
let team = [];
|
|
132932
|
+
let name = "Agent Team";
|
|
132933
|
+
let owner;
|
|
132934
|
+
let force = false;
|
|
132935
|
+
let adopt;
|
|
132936
|
+
let adoptGuid;
|
|
132937
|
+
for (let i = 0; i < args.length; i++) {
|
|
132938
|
+
const arg = args[i];
|
|
132939
|
+
if (arg === "--team" && i + 1 < args.length) {
|
|
132940
|
+
team = args[++i].split(",").map((s) => s.trim()).filter(Boolean);
|
|
132941
|
+
} else if (arg.startsWith("--team=")) {
|
|
132942
|
+
team = arg.slice("--team=".length).split(",").map((s) => s.trim()).filter(Boolean);
|
|
132943
|
+
} else if (arg === "--name" && i + 1 < args.length) {
|
|
132944
|
+
name = args[++i];
|
|
132945
|
+
} else if (arg.startsWith("--name=")) {
|
|
132946
|
+
name = arg.slice("--name=".length);
|
|
132947
|
+
} else if (arg === "--owner" && i + 1 < args.length) {
|
|
132948
|
+
owner = args[++i];
|
|
132949
|
+
} else if (arg.startsWith("--owner=")) {
|
|
132950
|
+
owner = arg.slice("--owner=".length);
|
|
132951
|
+
} else if (arg === "--force") {
|
|
132952
|
+
force = true;
|
|
132953
|
+
} else if (arg === "--adopt" && i + 1 < args.length) {
|
|
132954
|
+
adopt = args[++i];
|
|
132955
|
+
} else if (arg.startsWith("--adopt=")) {
|
|
132956
|
+
adopt = arg.slice("--adopt=".length);
|
|
132957
|
+
} else if (arg === "--adopt-guid" && i + 1 < args.length) {
|
|
132958
|
+
adoptGuid = args[++i];
|
|
132959
|
+
} else if (arg.startsWith("--adopt-guid=")) {
|
|
132960
|
+
adoptGuid = arg.slice("--adopt-guid=".length);
|
|
132961
|
+
}
|
|
132962
|
+
}
|
|
132963
|
+
return { team, name, owner, force, adopt, adoptGuid };
|
|
132964
|
+
}
|
|
132965
|
+
var USAGE2 = `larkway tasklist-init [--team <bot1,bot2,\u2026>] [--name <\u6E05\u5355\u540D>] [--owner <open_id>] [--force]
|
|
132966
|
+
[--adopt "<\u6E05\u5355\u540D>" | --adopt-guid <guid>]
|
|
132967
|
+
|
|
132968
|
+
\u5BF9\u7740 Claude Code / Codex \u8BF4\u4E00\u53E5\u300C\u5E2E\u6211\u914D\u7F6E\u4E00\u4E0B Agent Team\u300D\u5C31\u591F\u4E86 \u2014\u2014 \u4E00\u4E2A\u6CA1\u8BFB\u8FC7\u8FD9\u4EFD
|
|
132969
|
+
\u5E2E\u52A9\u7684 agent,\u7B2C\u4E00\u6B65\u5FC5\u7136\u4F1A\u8DD1 \`larkway tasklist-init --help\`(\u5C31\u662F\u4F60\u6B63\u5728\u770B\u7684\u8FD9\u6BB5),
|
|
132970
|
+
\u4ECE\u8FD9\u91CC\u5C31\u80FD\u5B66\u4F1A\u600E\u4E48\u628A\u672C\u673A\u6240\u6709\u5DF2\u914D\u7F6E\u7684 bot \u90FD\u914D\u6210\u6E05\u5355\u6210\u5458,\u4E0D\u9700\u8981\u4F60\u518D\u624B\u52A8\u4F20\u4EFB\u4F55\u53C2\u6570\u3002
|
|
132971
|
+
|
|
132972
|
+
\u96F6\u53C2\u6570\u4E09\u6B65 Quickstart:
|
|
132973
|
+
1. (\u53EF\u9009)\u5148\u5728\u98DE\u4E66\u4EFB\u52A1\u4E2D\u5FC3\u624B\u52A8\u5EFA\u4E00\u4E2A\u6E05\u5355,\u540D\u5B57\u968F\u4FBF\u53D6,\u6BD4\u5982 "Agent Team"\u3002
|
|
132974
|
+
2. \u8DD1:larkway tasklist-init
|
|
132975
|
+
\u2014\u2014 \u4F1A\u81EA\u52A8:--team = \u672C\u673A bots/ \u76EE\u5F55\u4E0B\u5168\u90E8\u5DF2\u914D\u7F6E bot;--name = "Agent Team";
|
|
132976
|
+
\u7528\u4F60\u7684 lark-cli \u7528\u6237\u8EAB\u4EFD\u6309\u540D\u5B57\u67E5\u4E00\u904D\u80FD\u770B\u5230\u7684\u6E05\u5355 \u2014\u2014 \u67E5\u5230\u540C\u540D\u7684\u5C31 adopt(\u628A\u8FD9\u4E9B
|
|
132977
|
+
bot \u52A0\u4E3A editor);\u67E5\u4E0D\u5230(\u6216\u6CA1\u767B\u5F55/\u7F3A scope)\u5C31\u9759\u9ED8\u56DE\u9000\u5230\u65E7\u7684\u521B\u5EFA\u8DEF\u5F84(\u7528\u7B2C\u4E00\u4E2A
|
|
132978
|
+
bot \u7684 app \u8EAB\u4EFD\u65B0\u5EFA\u4E00\u4E2A\u6E05\u5355,\u5E76\u81EA\u52A8\u628A\u4F60\u52A0\u4E3A owner)\u3002
|
|
132979
|
+
3. \u53BB\u98DE\u4E66\u4EFB\u52A1\u4E2D\u5FC3\u786E\u8BA4\u8FD9\u4E2A\u6E05\u5355\u5728\u4F60\u7684\u5217\u8868\u91CC\u53EF\u89C1,\u4E4B\u540E\u53F3\u952E\u8BDD\u9898\u6D88\u606F\u9009"\u8F6C\u4EFB\u52A1"\u5373\u53EF\u3002
|
|
132980
|
+
|
|
132981
|
+
\u4EE5\u4E0A\u5168\u90E8\u662F\u7F3A\u7701\u884C\u4E3A,\u4EE5\u4E0B flag \u4EC5\u7528\u4E8E\u8986\u76D6:
|
|
132982
|
+
|
|
132983
|
+
--team <bot1,bot2,\u2026> \u663E\u5F0F\u6307\u5B9A\u8981\u52A0\u5165\u6E05\u5355\u7684 bot(\u9ED8\u8BA4 = \u5168\u90E8\u5DF2\u914D\u7F6E bot)
|
|
132984
|
+
--name <\u6E05\u5355\u540D> \u663E\u5F0F\u6307\u5B9A\u6E05\u5355\u540D(\u9ED8\u8BA4 "Agent Team"),\u4EC5\u5728\u81EA\u52A8/\u663E\u5F0F create
|
|
132985
|
+
\u8DEF\u5F84\u91CC\u751F\u6548;--adopt/--adopt-guid \u4F1A\u5FFD\u7565\u5B83,\u6309\u540D\u5B57/guid \u67E5
|
|
132986
|
+
--adopt "<\u6E05\u5355\u540D>" \u5F3A\u5236\u8D70 adopt \u6A21\u5F0F\u5E76\u7528\u8FD9\u4E2A\u540D\u5B57\u67E5\u627E\u2014\u2014\u67E5\u4E0D\u5230/\u67E5\u51FA\u591A\u4E2A\u90FD\u4F1A
|
|
132987
|
+
\u76F4\u63A5\u62A5\u9519\u9000\u51FA,\u4E0D\u4F1A\u9759\u9ED8\u56DE\u9000\u5230\u521B\u5EFA\u8DEF\u5F84(\u4F60\u5DF2\u7ECF\u660E\u786E\u8981 adopt\u4E86)
|
|
132988
|
+
--adopt-guid <guid> \u8DF3\u8FC7\u6309\u540D\u5B57\u67E5\u627E,\u76F4\u63A5 adopt \u8FD9\u4E2A guid \u7684\u6E05\u5355(\u5355\u72EC\u4F7F\u7528\u4E5F
|
|
132989
|
+
\u7B49\u4EF7\u4E8E\u5F3A\u5236 adopt \u6A21\u5F0F);\u591A\u4E2A\u540C\u540D\u6E05\u5355\u65F6\u7528\u5B83\u6D88\u6B67
|
|
132990
|
+
--owner <open_id> \u663E\u5F0F\u6307\u5B9A\u4EBA\u7C7B owner(\u4EC5\u521B\u5EFA\u8DEF\u5F84\u7528\u5230,adopt \u6A21\u5F0F\u4E0B\u4F60\u672C\u6765\u5C31\u662F
|
|
132991
|
+
owner,\u4E0D\u9700\u8981\u8FD9\u4E2A)
|
|
132992
|
+
--force \u8986\u76D6\u5171\u4EAB\u6CE8\u518C\u6587\u4EF6\u91CC\u5DF2\u6709\u7684 guid(\u9ED8\u8BA4\u4E0D\u8986\u76D6,\u907F\u514D\u8BEF\u64CD\u4F5C\u628A
|
|
132993
|
+
\u6574\u4E2A\u56E2\u961F\u5207\u5230\u4E00\u4E2A\u65B0\u677F)
|
|
132994
|
+
|
|
132995
|
+
\u2500\u2500 adopt \u6A21\u5F0F\u5185\u90E8\u6B65\u9AA4(\u81EA\u52A8\u9009\u4E2D,\u6216\u663E\u5F0F --adopt/--adopt-guid \u89E6\u53D1)\u2500\u2500
|
|
132996
|
+
1. \u4EE5\u4F60(\u64CD\u4F5C\u8005)\u7684\u7528\u6237\u8EAB\u4EFD\u6309\u540D\u5B57\u7CBE\u786E\u5339\u914D\u4F60\u80FD\u770B\u5230\u7684\u6E05\u5355(\u91CD\u540D \u2192 \u62A5\u9519\u5217\u51FA\u5168\u90E8
|
|
132997
|
+
guid,\u8BA9\u4F60\u52A0 --adopt-guid <guid> \u6D88\u6B67\u91CD\u8DD1;\u4E00\u4E2A\u90FD\u627E\u4E0D\u5230 \u2192 \u81EA\u52A8\u6A21\u5F0F\u4E0B\u9759\u9ED8\u56DE\u9000
|
|
132998
|
+
\u521B\u5EFA\u8DEF\u5F84,\u663E\u5F0F --adopt \u4E0B\u62A5\u9519\u63D0\u793A\u5148\u53BB\u4EFB\u52A1\u4E2D\u5FC3\u5EFA\u4E00\u4E2A)
|
|
132999
|
+
2. \u628A\u6BCF\u4E2A bot \u7684 app \u52A0\u4E3A\u6E05\u5355\u6210\u5458(role=editor,\u5E42\u7B49,\u5DF2\u662F\u6210\u5458\u7684\u8DF3\u8FC7/\u65E0\u5BB3\u91CD\u590D)
|
|
133000
|
+
3. \u5199\u5165\u5171\u4EAB\u6CE8\u518C\u6587\u4EF6 <LARKWAY_HOME>/task-team.json(\u4E0E\u521B\u5EFA\u8DEF\u5F84\u540C\u4E00\u5957
|
|
133001
|
+
first-writer-wins / --force \u8986\u76D6\u8BED\u4E49)
|
|
133002
|
+
4. \u8BFB\u56DE\u6210\u5458\u5217\u8868,\u6838\u5B9E\u6BCF\u4E2A bot \u771F\u7684\u52A0\u5165\u6210\u529F
|
|
133003
|
+
|
|
133004
|
+
\u524D\u7F6E\u6761\u4EF6(\u4EC5 adopt \u9700\u8981):\u8FD9\u4E2A profile \u5FC5\u987B\u5DF2\u7ECF\u7528**\u7528\u6237\u8EAB\u4EFD**\u767B\u5F55\u8FC7 lark-cli \u4E14
|
|
133005
|
+
\u7533\u8BF7\u4E86 task \u57DF\u6743\u9650:
|
|
133006
|
+
lark-cli auth login --profile <profile> --domain task
|
|
133007
|
+
(\u7528\u54EA\u4E2A profile:\u7B2C\u4E00\u4E2A\u56E2\u961F bot \u7684 lark_cli_profile,\u7F3A\u7701\u65F6\u7528\u5B83\u7684 app_id)\u3002
|
|
133008
|
+
\u6CA1\u6709\u4E8B\u5148\u767B\u5F55/\u7F3A scope \u4F1A\u5728 adopt \u6B65\u9AA4 1 \u62A5\u9519,\u62A5\u9519\u4FE1\u606F\u4F1A\u5E26\u4E0A\u9762\u8FD9\u6761\u547D\u4EE4\u4F5C\u4E3A\u63D0\u793A\u3002
|
|
133009
|
+
|
|
133010
|
+
\u2500\u2500 \u521B\u5EFA\u8DEF\u5F84\u5185\u90E8\u6B65\u9AA4(\u81EA\u52A8\u56DE\u9000,\u6216\u672A\u5339\u914D\u5230\u540C\u540D\u6E05\u5355\u65F6\u89E6\u53D1)\u2500\u2500
|
|
133011
|
+
1. \u5148\u67E5\u5171\u4EAB\u6CE8\u518C\u6587\u4EF6:\u5DF2\u6709 guid \u4E14\u672A\u4F20 --force \u2192 \u590D\u7528;\u5426\u5219\u5EFA\u4E00\u4E2A\u65B0\u6E05\u5355
|
|
133012
|
+
2. \u628A\u4F60(owner)\u52A0\u4E3A\u4EBA\u7C7B\u6210\u5458(role=editor)\u2014\u2014 \u5426\u5219\u4F60\u5728\u98DE\u4E66\u4EFB\u52A1\u4E2D\u5FC3\u770B\u4E0D\u5230\u8FD9\u4E2A\u6E05\u5355
|
|
133013
|
+
3. \u628A\u6BCF\u4E2A bot \u7684 app \u90FD\u52A0\u4E3A\u6E05\u5355\u6210\u5458(role=editor)
|
|
133014
|
+
4. \u8BFB\u56DE\u6210\u5458\u5217\u8868,\u82E5 owner \u672A\u6210\u529F\u52A0\u5165\u4F1A\u6253\u5370\u4E00\u6761 warning(\u4E0D\u4F1A\u8BA9\u547D\u4EE4\u5931\u8D25)
|
|
133015
|
+
5. (\u4EC5\u65B0\u5EFA\u65F6)\u628A guid \u5199\u8FDB\u5171\u4EAB\u6CE8\u518C\u6587\u4EF6
|
|
133016
|
+
|
|
133017
|
+
owner open_id \u89E3\u6790\u987A\u5E8F(\u4EC5\u521B\u5EFA\u8DEF\u5F84\u7528\u5230):\u663E\u5F0F --owner \u4F18\u5148;\u7701\u7565\u65F6\u5C1D\u8BD5\u4ECE lark-cli
|
|
133018
|
+
\u5F53\u524D\u767B\u5F55\u7684\u7528\u6237\u8EAB\u4EFD\u81EA\u52A8\u89E3\u6790(\u9700\u8981\u4F60\u4E4B\u524D\u5BF9\u8BE5 profile \u8DD1\u8FC7 \`lark-cli auth login\`);
|
|
133019
|
+
\u4E24\u8005\u90FD\u62FF\u4E0D\u5230\u4F1A\u76F4\u63A5\u62A5\u9519\u9000\u51FA,\u4E0D\u5EFA/\u4E0D\u52A8\u4EFB\u4F55\u6E05\u5355\u3002
|
|
133020
|
+
|
|
133021
|
+
\u4E0D\u4F1A\u628A\u4EFB\u4F55\u7FA4\u52A0\u4E3A\u6210\u5458 \u2014\u2014 v2 \u6E05\u5355\u9ED8\u8BA4\u53EA\u5BF9 owner \u79C1\u6709;\u5206\u4EAB\u7ED9\u540C\u4E8B\u770B,\u8981\u7ED9 editor \u6743\u9650
|
|
133022
|
+
\u5BF9\u65B9\u624D\u80FD\u628A\u8BDD\u9898\u8F6C\u4EFB\u52A1\u8FDB\u6765,\u7ED9 viewer \u53EA\u80FD\u770B\u4E0D\u80FD\u8F6C(\u89C1 docs/task-handle.md \xA75.3)\u3002
|
|
133023
|
+
|
|
133024
|
+
\u5168\u7A0B\u975E\u4EA4\u4E92:\u4EFB\u4F55\u6B67\u4E49\u90FD\u76F4\u63A5\u975E\u96F6\u9000\u51FA\u5E76\u628A\u5019\u9009 + \u4E0B\u4E00\u6B65\u6307\u5F15\u6253\u5230 stderr,\u4E0D\u4F1A\u5F39\u4EFB\u4F55
|
|
133025
|
+
\u4EA4\u4E92\u5F0F\u95EE\u9898(\u8FD9\u4E2A\u547D\u4EE4\u672C\u6765\u5C31\u8BBE\u8BA1\u7ED9 agent \u5728 headless \u73AF\u5883\u91CC\u8DD1)\u3002
|
|
133026
|
+
|
|
133027
|
+
\u26A0\uFE0F \u9996\u6B21\u8DD1\u5B8C\u540E,\u8BF7\u5728\u98DE\u4E66\u4EFB\u52A1\u4E2D\u5FC3\u786E\u8BA4\u8FD9\u4E2A\u6E05\u5355\u786E\u5B9E\u53EF\u89C1(\u89C1 docs/task-handle.md \xA77 \u2014
|
|
133028
|
+
\u672C\u5B9E\u73B0\u65E0\u6CD5\u5728\u65E0\u7F51\u7EDC\u73AF\u5883\u4E0B\u7AEF\u5230\u7AEF\u9A8C\u8BC1 editor \u6210\u5458\u7684\u53EF\u89C1\u6027,\u7559\u7ED9\u8FD9\u4E00\u6B65\u4EBA\u5DE5\u786E\u8BA4)\u3002
|
|
133029
|
+
|
|
133030
|
+
\u793A\u4F8B:
|
|
133031
|
+
larkway tasklist-init
|
|
133032
|
+
larkway tasklist-init --adopt "Agent Team"
|
|
133033
|
+
larkway tasklist-init --adopt "Agent Team" --adopt-guid abc-123-guid
|
|
133034
|
+
larkway tasklist-init --team larkway-devops,larkway-marketing --name "Agent Team"
|
|
133035
|
+
larkway tasklist-init --team larkway-devops --owner ou_1234567890abcdef
|
|
133036
|
+
larkway tasklist-init --team larkway-devops --force`;
|
|
133037
|
+
async function run10(ctx, args) {
|
|
133038
|
+
if (args.includes("help")) {
|
|
133039
|
+
ctx.ui.print(USAGE2);
|
|
133040
|
+
return 0;
|
|
133041
|
+
}
|
|
133042
|
+
const { team, name, owner: explicitOwner, force, adopt, adoptGuid: explicitAdoptGuid } = parseArgs2(args);
|
|
133043
|
+
let team_ = team;
|
|
133044
|
+
if (team_.length === 0) {
|
|
133045
|
+
team_ = await ctx.botsStore.listBots();
|
|
133046
|
+
if (team_.length === 0) {
|
|
133047
|
+
const msg = "\u672C\u673A\u6CA1\u6709\u914D\u7F6E\u4EFB\u4F55 bot\u3002\u5148\u8FD0\u884C `larkway bot add` \u6DFB\u52A0\u81F3\u5C11\u4E00\u4E2A bot,\u518D\u91CD\u8DD1\u8FD9\u4E2A\u547D\u4EE4\u3002";
|
|
133048
|
+
if (ctx.flags.json) ctx.ui.emitJson({ ok: false, error: msg });
|
|
133049
|
+
else {
|
|
133050
|
+
ctx.ui.failure(msg);
|
|
133051
|
+
ctx.ui.print(USAGE2);
|
|
133052
|
+
}
|
|
133053
|
+
return 1;
|
|
133054
|
+
}
|
|
133055
|
+
}
|
|
133056
|
+
const bots = [];
|
|
133057
|
+
for (const botId of team_) {
|
|
133058
|
+
let bot;
|
|
133059
|
+
try {
|
|
133060
|
+
bot = await ctx.botsStore.readBot(botId);
|
|
133061
|
+
} catch (err2) {
|
|
133062
|
+
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
133063
|
+
if (ctx.flags.json) ctx.ui.emitJson({ ok: false, error: msg });
|
|
133064
|
+
else ctx.ui.failure(msg);
|
|
133065
|
+
return 1;
|
|
133066
|
+
}
|
|
133067
|
+
const appSecret = await ctx.hostConfig.readSecret(bot.app_secret_env);
|
|
133068
|
+
if (!appSecret) {
|
|
133069
|
+
const msg = `Bot "${botId}" \u7684 app_secret_env "${bot.app_secret_env}" \u5728 ~/.larkway/.env \u4E2D\u672A\u8BBE\u7F6E\u3002`;
|
|
133070
|
+
if (ctx.flags.json) ctx.ui.emitJson({ ok: false, error: msg });
|
|
133071
|
+
else ctx.ui.failure(msg);
|
|
133072
|
+
return 1;
|
|
133073
|
+
}
|
|
133074
|
+
bots.push({ id: bot.id, app_id: bot.app_id, appSecret, lark_cli_profile: bot.lark_cli_profile });
|
|
133075
|
+
}
|
|
133076
|
+
const creator = bots[0];
|
|
133077
|
+
const creatorProfile = deriveLarkCliProfile(creator.lark_cli_profile, creator.app_id);
|
|
133078
|
+
const loginHint = `lark-cli auth login --profile ${creatorProfile} --domain task`;
|
|
133079
|
+
if (adopt !== void 0 || explicitAdoptGuid !== void 0) {
|
|
133080
|
+
const adoptName = adopt ?? name;
|
|
133081
|
+
if (adoptName.trim().length === 0) {
|
|
133082
|
+
const msg = '--adopt \u9700\u8981\u4E00\u4E2A\u975E\u7A7A\u7684\u6E05\u5355\u540D\u5B57,\u4F8B\u5982 --adopt "Agent Team"\u3002';
|
|
133083
|
+
if (ctx.flags.json) ctx.ui.emitJson({ ok: false, error: msg });
|
|
133084
|
+
else {
|
|
133085
|
+
ctx.ui.failure(msg);
|
|
133086
|
+
ctx.ui.print(USAGE2);
|
|
133087
|
+
}
|
|
133088
|
+
return 1;
|
|
133089
|
+
}
|
|
133090
|
+
const target = resolveAdoptTarget(creatorProfile, adoptName, explicitAdoptGuid, loginHint);
|
|
133091
|
+
if (!target.ok) {
|
|
133092
|
+
if (ctx.flags.json) ctx.ui.emitJson({ ok: false, error: target.message });
|
|
133093
|
+
else {
|
|
133094
|
+
ctx.ui.failure(target.message);
|
|
133095
|
+
if (target.reason === "list-failed") ctx.ui.print(USAGE2);
|
|
133096
|
+
}
|
|
133097
|
+
return 1;
|
|
133098
|
+
}
|
|
133099
|
+
return runAdoptWithGuid(ctx, {
|
|
133100
|
+
guid: target.guid,
|
|
133101
|
+
matchedName: target.matchedName,
|
|
133102
|
+
bots,
|
|
133103
|
+
force,
|
|
133104
|
+
creatorProfile,
|
|
133105
|
+
loginHint
|
|
133106
|
+
});
|
|
133107
|
+
}
|
|
133108
|
+
const autoTarget = resolveAdoptTarget(creatorProfile, name, void 0, loginHint);
|
|
133109
|
+
if (autoTarget.ok) {
|
|
133110
|
+
return runAdoptWithGuid(ctx, {
|
|
133111
|
+
guid: autoTarget.guid,
|
|
133112
|
+
matchedName: autoTarget.matchedName,
|
|
133113
|
+
bots,
|
|
133114
|
+
force,
|
|
133115
|
+
creatorProfile,
|
|
133116
|
+
loginHint
|
|
133117
|
+
});
|
|
133118
|
+
}
|
|
133119
|
+
if (autoTarget.reason === "ambiguous") {
|
|
133120
|
+
if (ctx.flags.json) ctx.ui.emitJson({ ok: false, error: autoTarget.message });
|
|
133121
|
+
else ctx.ui.failure(autoTarget.message);
|
|
133122
|
+
return 1;
|
|
133123
|
+
}
|
|
133124
|
+
if (!ctx.flags.json) {
|
|
133125
|
+
const why = autoTarget.reason === "list-failed" ? "\u65E0\u6CD5\u4EE5\u4F60\u7684\u7528\u6237\u8EAB\u4EFD\u67E5\u8BE2\u6E05\u5355" : `\u6CA1\u627E\u5230\u540C\u540D\u6E05\u5355 "${name}"`;
|
|
133126
|
+
ctx.ui.print(ctx.ui.dim(`(${why},\u56DE\u9000\u5230\u7528 bot app \u8EAB\u4EFD\u521B\u5EFA/\u590D\u7528\u6E05\u5355\u2014\u2014\u5982\u9700\u5F3A\u5236 adopt \u89C1 --adopt)`));
|
|
133127
|
+
}
|
|
133128
|
+
const ownerOpenId = explicitOwner ?? resolveOwnerOpenId(creatorProfile);
|
|
133129
|
+
if (!ownerOpenId) {
|
|
133130
|
+
const msg = `\u65E0\u6CD5\u786E\u5B9A\u6E05\u5355\u7684\u4EBA\u7C7B owner:\u672A\u4F20 --owner,\u4E14\u65E0\u6CD5\u4ECE lark-cli \u5F53\u524D\u767B\u5F55\u7684\u7528\u6237\u8EAB\u4EFD\u81EA\u52A8\u89E3\u6790(\u5C1D\u8BD5\u7684 profile: "${creatorProfile}")\u3002\u8BF7\u663E\u5F0F\u4F20\u5165 --owner <open_id>(\u53EF\u7528 \`lark-cli auth status --profile ${creatorProfile} --json\` \u67E5\u770B\u662F\u5426\u5DF2\u767B\u5F55\u7528\u6237\u8EAB\u4EFD,\u6216\u7528 lark-cli contact \u6309\u59D3\u540D/\u90AE\u7BB1\u67E5 open_id)\u3002\u4E0D\u4F1A\u5EFA/\u4E0D\u4F1A\u52A8\u4EFB\u4F55\u6E05\u5355\u3002`;
|
|
133131
|
+
if (ctx.flags.json) ctx.ui.emitJson({ ok: false, error: msg });
|
|
133132
|
+
else {
|
|
133133
|
+
ctx.ui.failure(msg);
|
|
133134
|
+
ctx.ui.print(USAGE2);
|
|
133135
|
+
}
|
|
133136
|
+
return 1;
|
|
133137
|
+
}
|
|
133138
|
+
const sdkClient = new import_node_sdk2.Client({ appId: creator.app_id, appSecret: creator.appSecret });
|
|
133139
|
+
const requester = {
|
|
133140
|
+
request: (config) => sdkClient.request(config)
|
|
133141
|
+
};
|
|
133142
|
+
const taskClient = new TaskListClient(requester);
|
|
133143
|
+
const members = [
|
|
133144
|
+
{ id: ownerOpenId, type: "user", role: "editor" },
|
|
133145
|
+
...bots.map((b) => ({ id: b.app_id, type: "app", role: "editor" }))
|
|
133146
|
+
];
|
|
133147
|
+
const registryPath = resolveTaskTeamRegistryPath();
|
|
133148
|
+
const existingGuid = await readTeamTasklistGuid(registryPath);
|
|
133149
|
+
let tasklistGuid;
|
|
133150
|
+
let reused;
|
|
133151
|
+
if (existingGuid && !force) {
|
|
133152
|
+
tasklistGuid = existingGuid;
|
|
133153
|
+
reused = true;
|
|
133154
|
+
try {
|
|
133155
|
+
await taskClient.addTasklistMembers(tasklistGuid, members);
|
|
133156
|
+
} catch (err2) {
|
|
133157
|
+
const msg = `\u590D\u7528\u5DF2\u6709\u6E05\u5355 ${tasklistGuid} \u65F6\u8865\u5145\u6210\u5458\u5931\u8D25: ${err2 instanceof Error ? err2.message : String(err2)}`;
|
|
133158
|
+
if (ctx.flags.json) ctx.ui.emitJson({ ok: false, error: msg });
|
|
133159
|
+
else {
|
|
133160
|
+
ctx.ui.failure(msg);
|
|
133161
|
+
ctx.ui.print("\u5E38\u89C1\u539F\u56E0:app \u672A\u5728\u5F00\u653E\u5E73\u53F0\u540E\u53F0\u52FE\u9009 task:tasklist:write / task:task:write scope(\u89C1 docs/task-handle.md \xA77)\u3002");
|
|
133162
|
+
}
|
|
133163
|
+
return 1;
|
|
133164
|
+
}
|
|
133165
|
+
} else {
|
|
133166
|
+
reused = false;
|
|
133167
|
+
try {
|
|
133168
|
+
const created = await taskClient.createTasklist(name, members);
|
|
133169
|
+
tasklistGuid = created.guid;
|
|
133170
|
+
} catch (err2) {
|
|
133171
|
+
const msg = `\u5EFA\u6E05\u5355\u5931\u8D25: ${err2 instanceof Error ? err2.message : String(err2)}`;
|
|
133172
|
+
if (ctx.flags.json) ctx.ui.emitJson({ ok: false, error: msg });
|
|
133173
|
+
else {
|
|
133174
|
+
ctx.ui.failure(msg);
|
|
133175
|
+
ctx.ui.print("\u5E38\u89C1\u539F\u56E0:app \u672A\u5728\u5F00\u653E\u5E73\u53F0\u540E\u53F0\u52FE\u9009 task:tasklist:write / task:task:write scope(\u89C1 docs/task-handle.md \xA77)\u3002");
|
|
133176
|
+
}
|
|
133177
|
+
return 1;
|
|
133178
|
+
}
|
|
133179
|
+
if (force && existingGuid) {
|
|
133180
|
+
await overwriteTeamTasklistGuid(registryPath, tasklistGuid);
|
|
133181
|
+
} else {
|
|
133182
|
+
await claimTeamTasklistGuid(registryPath, tasklistGuid);
|
|
133183
|
+
}
|
|
133184
|
+
}
|
|
133185
|
+
let ownerConfirmedMember;
|
|
133186
|
+
let membershipCheckError;
|
|
133187
|
+
try {
|
|
133188
|
+
const snapshot = await taskClient.getTasklist(tasklistGuid);
|
|
133189
|
+
ownerConfirmedMember = snapshot?.members.some((m) => m.id === ownerOpenId) ?? void 0;
|
|
133190
|
+
} catch (err2) {
|
|
133191
|
+
membershipCheckError = err2 instanceof Error ? err2.message : String(err2);
|
|
133192
|
+
}
|
|
133193
|
+
if (ctx.flags.json) {
|
|
133194
|
+
ctx.ui.emitJson({
|
|
133195
|
+
ok: true,
|
|
133196
|
+
team: team_,
|
|
133197
|
+
name,
|
|
133198
|
+
ownerOpenId,
|
|
133199
|
+
tasklistGuid,
|
|
133200
|
+
reused,
|
|
133201
|
+
ownerConfirmedMember: ownerConfirmedMember ?? null,
|
|
133202
|
+
membershipCheckError: membershipCheckError ?? null
|
|
133203
|
+
});
|
|
133204
|
+
return 0;
|
|
133205
|
+
}
|
|
133206
|
+
if (ownerConfirmedMember === false) {
|
|
133207
|
+
ctx.ui.warning(
|
|
133208
|
+
`owner(${ownerOpenId})\u672A\u51FA\u73B0\u5728\u6E05\u5355 ${tasklistGuid} \u7684\u6210\u5458\u5217\u8868\u91CC\u2014\u2014\u53EF\u80FD\u88AB\u9759\u9ED8\u4E22\u5F03,owner \u5927\u6982\u7387\u770B\u4E0D\u5230\u8FD9\u4E2A\u677F\u3002\u8BF7\u68C0\u67E5 open_id \u662F\u5426\u6B63\u786E\u3001\u662F\u5426\u8DE8\u79DF\u6237,\u6216\u624B\u52A8\u5728\u98DE\u4E66\u4EFB\u52A1\u4E2D\u5FC3\u628A owner \u52A0\u4E3A\u8BE5\u6E05\u5355\u6210\u5458\u3002`
|
|
133209
|
+
);
|
|
133210
|
+
} else if (membershipCheckError) {
|
|
133211
|
+
ctx.ui.warning(
|
|
133212
|
+
`\u65E0\u6CD5\u8BFB\u56DE\u6E05\u5355 ${tasklistGuid} \u7684\u6210\u5458\u5217\u8868\u4EE5\u6838\u5B9E owner \u662F\u5426\u52A0\u5165\u6210\u529F(\u7EE7\u7EED,\u4E0D\u5F71\u54CD\u672C\u6B21\u7ED3\u679C): ${membershipCheckError}`
|
|
133213
|
+
);
|
|
133214
|
+
}
|
|
133215
|
+
if (reused) {
|
|
133216
|
+
ctx.ui.success(`\u590D\u7528\u5DF2\u6709\u6E05\u5355: ${tasklistGuid}`);
|
|
133217
|
+
} else {
|
|
133218
|
+
ctx.ui.success(`\u6E05\u5355 "${name}" \u5DF2\u521B\u5EFA: ${tasklistGuid}`);
|
|
133219
|
+
}
|
|
133220
|
+
ctx.ui.print(`owner \u6210\u5458: ${ownerOpenId}${explicitOwner ? "" : "(\u4ECE lark-cli \u5F53\u524D\u767B\u5F55\u7528\u6237\u81EA\u52A8\u89E3\u6790)"}`);
|
|
133221
|
+
ctx.ui.print(`\u5DF2\u52A0\u5165\u6210\u5458(editor): ${bots.map((b) => b.id).join(", ")}`);
|
|
133222
|
+
ctx.ui.print("");
|
|
133223
|
+
if (!reused) {
|
|
133224
|
+
ctx.ui.print(
|
|
133225
|
+
`\u5DF2\u5199\u5165\u5171\u4EAB\u6CE8\u518C\u6587\u4EF6 ${registryPath} \u2014\u2014 \u56E2\u961F\u91CC\u7684 bot \u4E0B\u6B21\u91CD\u542F\u4F1A\u81EA\u52A8\u53D1\u73B0\u5E76\u4F7F\u7528\u8FD9\u4E2A guid,\u4E0D\u9700\u8981\u624B\u5DE5\u6539 yaml\u3002`
|
|
133226
|
+
);
|
|
133227
|
+
ctx.ui.print("");
|
|
133228
|
+
}
|
|
133229
|
+
ctx.ui.print(
|
|
133230
|
+
ctx.ui.bold("\u53EF\u9009:") + " \u5982\u679C\u60F3\u56FA\u5B9A\u7ED1\u5B9A\u3001\u4E0D\u4F9D\u8D56\u5171\u4EAB\u6CE8\u518C\u6587\u4EF6\u7684\u81EA\u52A8\u53D1\u73B0,\u4E5F\u53EF\u4EE5\u628A guid \u624B\u5199\u8FDB\u5404 bot \u7684 bots/<id>.yaml:"
|
|
133231
|
+
);
|
|
133232
|
+
ctx.ui.print(` taskHandle:`);
|
|
133233
|
+
ctx.ui.print(` tasklistGuid: "${tasklistGuid}"`);
|
|
133234
|
+
ctx.ui.print("");
|
|
133235
|
+
ctx.ui.print(
|
|
133236
|
+
ctx.ui.bold("\u26A0\uFE0F \u8BF7\u624B\u52A8\u786E\u8BA4:") + " \u53BB\u98DE\u4E66\u4EFB\u52A1\u4E2D\u5FC3\u786E\u8BA4\u8FD9\u4E2A\u6E05\u5355\u786E\u5B9E\u53EF\u89C1(\u89C1 docs/task-handle.md \xA77)\u3002"
|
|
133237
|
+
);
|
|
133238
|
+
return 0;
|
|
133239
|
+
}
|
|
133240
|
+
function resolveAdoptTarget(creatorProfile, name, explicitGuid, loginHint) {
|
|
133241
|
+
if (explicitGuid) {
|
|
133242
|
+
return { ok: true, guid: explicitGuid, matchedName: name };
|
|
133243
|
+
}
|
|
133244
|
+
const listResult = listUserTasklists(creatorProfile);
|
|
133245
|
+
if (!listResult.ok) {
|
|
133246
|
+
return {
|
|
133247
|
+
ok: false,
|
|
133248
|
+
reason: "list-failed",
|
|
133249
|
+
message: `\u65E0\u6CD5\u4EE5\u4F60\u7684\u7528\u6237\u8EAB\u4EFD\u5217\u51FA\u6E05\u5355:${listResult.error}
|
|
133250
|
+
|
|
133251
|
+
\u8BF7\u5148\u786E\u8BA4\u5DF2\u7528\u8FD9\u4E2A profile \u767B\u5F55\u8FC7\u7528\u6237\u8EAB\u4EFD\u3001\u4E14\u7533\u8BF7\u4E86 task \u57DF\u6743\u9650:
|
|
133252
|
+
${loginHint}
|
|
133253
|
+
(\u53EF\u7528 \`lark-cli auth status --profile ${creatorProfile} --json\` \u68C0\u67E5\u5F53\u524D\u72B6\u6001)`
|
|
133254
|
+
};
|
|
133255
|
+
}
|
|
133256
|
+
const matches = listResult.data.filter((t) => t.name === name);
|
|
133257
|
+
if (matches.length === 0) {
|
|
133258
|
+
return {
|
|
133259
|
+
ok: false,
|
|
133260
|
+
reason: "not-found",
|
|
133261
|
+
message: `\u5728\u4F60\u80FD\u770B\u5230\u7684\u6E05\u5355\u91CC\u6CA1\u627E\u5230\u540D\u4E3A "${name}" \u7684\u6E05\u5355\u3002\u8BF7\u5148\u53BB\u98DE\u4E66\u4EFB\u52A1\u4E2D\u5FC3\u65B0\u5EFA\u4E00\u4E2A\u540C\u540D\u6E05\u5355,\u518D\u91CD\u8DD1\u8FD9\u4E2A\u547D\u4EE4;\u6216\u8005\u68C0\u67E5\u540D\u5B57\u662F\u5426\u5B8C\u5168\u4E00\u81F4(\u6CE8\u610F\u5168\u534A\u89D2\u5B57\u7B26\u3001\u591A\u4F59\u7A7A\u683C)\u3002`
|
|
133262
|
+
};
|
|
133263
|
+
}
|
|
133264
|
+
if (matches.length > 1) {
|
|
133265
|
+
return {
|
|
133266
|
+
ok: false,
|
|
133267
|
+
reason: "ambiguous",
|
|
133268
|
+
message: `\u627E\u5230 ${matches.length} \u4E2A\u540C\u540D\u6E05\u5355 "${name}",\u65E0\u6CD5\u786E\u5B9A\u8981 adopt \u54EA\u4E00\u4E2A:
|
|
133269
|
+
` + matches.map((t) => ` - ${t.guid}`).join("\n") + "\n\u8BF7\u52A0 --adopt-guid <guid> \u663E\u5F0F\u6307\u5B9A\u5176\u4E2D\u4E00\u4E2A\u91CD\u8DD1,\u6216\u53BB\u98DE\u4E66\u4EFB\u52A1\u4E2D\u5FC3\u628A\u5176\u4E2D\u4E00\u4E2A\u6539\u540D\u540E\u518D\u91CD\u8DD1\u3002",
|
|
133270
|
+
matches
|
|
133271
|
+
};
|
|
133272
|
+
}
|
|
133273
|
+
return { ok: true, guid: matches[0].guid, matchedName: matches[0].name };
|
|
133274
|
+
}
|
|
133275
|
+
async function runAdoptWithGuid(ctx, opts) {
|
|
133276
|
+
const { guid: tasklistGuid, matchedName, bots, force, creatorProfile, loginHint } = opts;
|
|
133277
|
+
const members = bots.map((b) => ({ id: b.app_id, type: "app", role: "editor" }));
|
|
133278
|
+
const addResult = addTasklistMembersAsUser(creatorProfile, tasklistGuid, members);
|
|
133279
|
+
if (!addResult.ok) {
|
|
133280
|
+
const msg = `\u628A bot app \u52A0\u4E3A\u6E05\u5355 ${tasklistGuid} \u7684 editor \u5931\u8D25:${addResult.error}
|
|
133281
|
+
|
|
133282
|
+
\u5E38\u89C1\u539F\u56E0:\u8FD9\u4E2A profile \u7684\u7528\u6237\u8EAB\u4EFD\u7F3A task:tasklist:write scope \u2014\u2014 \u91CD\u65B0\u767B\u5F55\u5E76\u7533\u8BF7 task \u57DF\u6743\u9650:
|
|
133283
|
+
${loginHint}`;
|
|
133284
|
+
if (ctx.flags.json) ctx.ui.emitJson({ ok: false, error: msg });
|
|
133285
|
+
else ctx.ui.failure(msg);
|
|
133286
|
+
return 1;
|
|
133287
|
+
}
|
|
133288
|
+
const registryPath = resolveTaskTeamRegistryPath();
|
|
133289
|
+
let registeredGuid;
|
|
133290
|
+
if (force) {
|
|
133291
|
+
await overwriteTeamTasklistGuid(registryPath, tasklistGuid);
|
|
133292
|
+
registeredGuid = tasklistGuid;
|
|
133293
|
+
} else {
|
|
133294
|
+
registeredGuid = await claimTeamTasklistGuid(registryPath, tasklistGuid);
|
|
133295
|
+
}
|
|
133296
|
+
const registryMismatch = registeredGuid !== tasklistGuid;
|
|
133297
|
+
const membersResult = getUserTasklistMembers(creatorProfile, tasklistGuid);
|
|
133298
|
+
const missingBots = [];
|
|
133299
|
+
let membershipCheckError;
|
|
133300
|
+
if (membersResult.ok) {
|
|
133301
|
+
for (const b of bots) {
|
|
133302
|
+
if (!membersResult.data.some((m) => m.id === b.app_id)) missingBots.push(b.id);
|
|
133303
|
+
}
|
|
133304
|
+
} else {
|
|
133305
|
+
membershipCheckError = membersResult.error;
|
|
133306
|
+
}
|
|
133307
|
+
if (ctx.flags.json) {
|
|
133308
|
+
ctx.ui.emitJson({
|
|
133309
|
+
ok: true,
|
|
133310
|
+
mode: "adopt",
|
|
133311
|
+
adoptedName: matchedName,
|
|
133312
|
+
tasklistGuid,
|
|
133313
|
+
addedMembers: bots.map((b) => b.id),
|
|
133314
|
+
missingBots,
|
|
133315
|
+
membershipCheckError: membershipCheckError ?? null,
|
|
133316
|
+
registeredGuid,
|
|
133317
|
+
registryMismatch
|
|
133318
|
+
});
|
|
133319
|
+
return 0;
|
|
133320
|
+
}
|
|
133321
|
+
ctx.ui.success(`\u5DF2 adopt \u6E05\u5355 "${matchedName}": ${tasklistGuid}`);
|
|
133322
|
+
ctx.ui.print(`\u5DF2\u52A0\u5165\u6210\u5458(editor): ${bots.map((b) => b.id).join(", ")}`);
|
|
133323
|
+
ctx.ui.print("");
|
|
133324
|
+
if (missingBots.length > 0) {
|
|
133325
|
+
ctx.ui.warning(
|
|
133326
|
+
`\u4EE5\u4E0B bot \u7684 app \u672A\u51FA\u73B0\u5728\u6E05\u5355\u6210\u5458\u5217\u8868\u91CC\u2014\u2014\u53EF\u80FD\u88AB\u9759\u9ED8\u4E22\u5F03:${missingBots.join(", ")}\u3002\u8BF7\u68C0\u67E5 app_id \u662F\u5426\u6B63\u786E,\u6216\u624B\u52A8\u5728\u98DE\u4E66\u4EFB\u52A1\u4E2D\u5FC3\u628A\u5B83\u4EEC\u52A0\u4E3A\u8BE5\u6E05\u5355\u7684 editor\u3002`
|
|
133327
|
+
);
|
|
133328
|
+
} else if (membershipCheckError) {
|
|
133329
|
+
ctx.ui.warning(`\u65E0\u6CD5\u8BFB\u56DE\u6E05\u5355 ${tasklistGuid} \u7684\u6210\u5458\u5217\u8868\u4EE5\u6838\u5B9E\u662F\u5426\u52A0\u5165\u6210\u529F(\u7EE7\u7EED,\u4E0D\u5F71\u54CD\u672C\u6B21\u7ED3\u679C): ${membershipCheckError}`);
|
|
133330
|
+
}
|
|
133331
|
+
if (registryMismatch) {
|
|
133332
|
+
ctx.ui.warning(
|
|
133333
|
+
`\u5171\u4EAB\u6CE8\u518C\u6587\u4EF6\u91CC\u5DF2\u7ECF\u7ED1\u5B9A\u4E86\u53E6\u4E00\u4E2A\u6E05\u5355(${registeredGuid}),\u8FD9\u6B21 adopt \u7684\u6E05\u5355(${tasklistGuid})\u672A\u5199\u5165\u5171\u4EAB\u6CE8\u518C\u6587\u4EF6\u2014\u2014\u907F\u514D\u7834\u574F\u73B0\u6709\u56E2\u961F\u7ED1\u5B9A\u3002\u5982\u679C\u786E\u5B9E\u60F3\u5207\u6362\u5230\u8FD9\u4E2A\u65B0\u6E05\u5355,\u52A0 --force \u91CD\u8DD1\u3002`
|
|
133334
|
+
);
|
|
133335
|
+
} else {
|
|
133336
|
+
ctx.ui.print(
|
|
133337
|
+
`\u5DF2\u5199\u5165\u5171\u4EAB\u6CE8\u518C\u6587\u4EF6 ${registryPath} \u2014\u2014 \u56E2\u961F\u91CC\u7684 bot \u4E0B\u6B21\u91CD\u542F\u4F1A\u81EA\u52A8\u53D1\u73B0\u5E76\u4F7F\u7528\u8FD9\u4E2A guid,\u4E0D\u9700\u8981\u624B\u5DE5\u6539 yaml\u3002`
|
|
133338
|
+
);
|
|
133339
|
+
}
|
|
133340
|
+
ctx.ui.print("");
|
|
133341
|
+
ctx.ui.print(
|
|
133342
|
+
ctx.ui.bold("\u53EF\u9009:") + " \u5982\u679C\u60F3\u56FA\u5B9A\u7ED1\u5B9A\u3001\u4E0D\u4F9D\u8D56\u5171\u4EAB\u6CE8\u518C\u6587\u4EF6\u7684\u81EA\u52A8\u53D1\u73B0,\u4E5F\u53EF\u4EE5\u628A guid \u624B\u5199\u8FDB\u5404 bot \u7684 bots/<id>.yaml:"
|
|
133343
|
+
);
|
|
133344
|
+
ctx.ui.print(` taskHandle:`);
|
|
133345
|
+
ctx.ui.print(` tasklistGuid: "${tasklistGuid}"`);
|
|
133346
|
+
return 0;
|
|
133347
|
+
}
|
|
133348
|
+
|
|
131127
133349
|
// src/cli/index.ts
|
|
131128
133350
|
var _require2 = createRequire3(import.meta.url);
|
|
131129
133351
|
var _pkg = _require2("../../package.json");
|
|
@@ -131140,9 +133362,10 @@ var COMMANDS = {
|
|
|
131140
133362
|
logs: run6,
|
|
131141
133363
|
update: run7,
|
|
131142
133364
|
dogfood: run9,
|
|
131143
|
-
ui: run8
|
|
133365
|
+
ui: run8,
|
|
133366
|
+
"tasklist-init": run10
|
|
131144
133367
|
};
|
|
131145
|
-
var
|
|
133368
|
+
var USAGE3 = `larkway \u2014 Feishu \u2194 local CLI agent bridge host manager
|
|
131146
133369
|
|
|
131147
133370
|
\u7528\u6CD5:
|
|
131148
133371
|
larkway \u76F4\u63A5\u6253\u5F00\u7F51\u9875\u7BA1\u7406\u9762(\u63A8\u8350 \u2014\u2014 \u626B\u7801\u7ED1\u5B9A + \u914D\u7F6E\u5168\u5728\u6D4F\u89C8\u5668\u91CC\u70B9\u70B9\u70B9)
|
|
@@ -131158,6 +133381,7 @@ var USAGE2 = `larkway \u2014 Feishu \u2194 local CLI agent bridge host manager
|
|
|
131158
133381
|
update pull + install + restart
|
|
131159
133382
|
dogfood preflight|guide [id] v0.3 Phase 1 dogfood \u524D\u7F6E\u9A8C\u6536 / \u4E0B\u4E00\u6B65\u6307\u5F15
|
|
131160
133383
|
ui \u542F\u52A8\u8F7B\u91CF Web UI \u7BA1\u7406\u9762(127.0.0.1 + token)
|
|
133384
|
+
tasklist-init \u4E3A\u8BDD\u9898\u2194\u4EFB\u52A1\u53E5\u67C4 feature provisioning \u5171\u4EAB\u6E05\u5355(docs/task-handle.md)
|
|
131161
133385
|
|
|
131162
133386
|
\u5168\u5C40 flags:
|
|
131163
133387
|
--json \u673A\u5668\u53EF\u8BFB\u8F93\u51FA(\u4E0E\u5176\u4ED6 flag \u6B63\u4EA4)
|
|
@@ -131222,29 +133446,32 @@ async function main(argv) {
|
|
|
131222
133446
|
return 0;
|
|
131223
133447
|
}
|
|
131224
133448
|
if (help) {
|
|
131225
|
-
|
|
133449
|
+
if (command === "tasklist-init") {
|
|
133450
|
+
return run10(buildContext(flags), ["help"]);
|
|
133451
|
+
}
|
|
133452
|
+
print(USAGE3);
|
|
131226
133453
|
return 0;
|
|
131227
133454
|
}
|
|
131228
133455
|
if (command === void 0) {
|
|
131229
133456
|
if (flags.json || flags.nonInteractive) {
|
|
131230
|
-
print(
|
|
133457
|
+
print(USAGE3);
|
|
131231
133458
|
return 1;
|
|
131232
133459
|
}
|
|
131233
133460
|
print("\u542F\u52A8\u7F51\u9875\u7BA1\u7406\u9762\u2026(\u9996\u6B21\u4F7F\u7528:\u5728\u6D4F\u89C8\u5668\u91CC\u626B\u7801\u7ED1\u5B9A + \u914D\u7F6E,\u5168\u7A0B\u70B9\u70B9\u70B9)");
|
|
131234
133461
|
print(dim("\u65E0\u6D4F\u89C8\u5668 / \u670D\u52A1\u5668\u573A\u666F\u8BF7\u6539\u7528 `larkway init`(CLI \u5411\u5BFC)\u3002"));
|
|
131235
133462
|
return run8(buildContext(flags), []);
|
|
131236
133463
|
}
|
|
131237
|
-
const
|
|
131238
|
-
if (!
|
|
133464
|
+
const run11 = COMMANDS[command];
|
|
133465
|
+
if (!run11) {
|
|
131239
133466
|
failure(`\u672A\u77E5\u547D\u4EE4: ${command}`);
|
|
131240
133467
|
print("");
|
|
131241
|
-
print(
|
|
133468
|
+
print(USAGE3);
|
|
131242
133469
|
return 1;
|
|
131243
133470
|
}
|
|
131244
133471
|
const ctx = buildContext(flags);
|
|
131245
133472
|
const isLifecycle = command === "start" || command === "stop" || command === "status" || command === "logs";
|
|
131246
133473
|
const runArgs = isLifecycle ? [command, ...args] : args;
|
|
131247
|
-
return
|
|
133474
|
+
return run11(ctx, runArgs);
|
|
131248
133475
|
}
|
|
131249
133476
|
main(process4.argv.slice(2)).then((code) => process4.exit(code)).catch((e) => {
|
|
131250
133477
|
const message = e instanceof Error ? e.message : String(e);
|