larkway 0.3.33 → 0.3.34
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 +2124 -64
- package/dist/main.js +10879 -6244
- 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") {
|
|
@@ -111539,7 +112385,9 @@ var init_channelPostClient = __esm({
|
|
|
111539
112385
|
var channelClient_exports = {};
|
|
111540
112386
|
__export(channelClient_exports, {
|
|
111541
112387
|
ChannelClient: () => ChannelClient,
|
|
112388
|
+
DEFAULT_OPEN_CHAT_DISCOVERY_MS: () => DEFAULT_OPEN_CHAT_DISCOVERY_MS,
|
|
111542
112389
|
channelMsgToLarkEvent: () => channelMsgToLarkEvent,
|
|
112390
|
+
resolveOpenChatDiscoveryMs: () => resolveOpenChatDiscoveryMs,
|
|
111543
112391
|
resolveRecoveredThreadId: () => resolveRecoveredThreadId,
|
|
111544
112392
|
synthesizeCardActionEvent: () => synthesizeCardActionEvent
|
|
111545
112393
|
});
|
|
@@ -112044,6 +112892,20 @@ var init_channelClient = __esm({
|
|
|
112044
112892
|
log(`cardAction \u2192 synthesized turn: value=${JSON.stringify(evt.action?.value)} thread=${ev.thread_id ?? "?"}`);
|
|
112045
112893
|
this.queue.push(ev);
|
|
112046
112894
|
}
|
|
112895
|
+
/**
|
|
112896
|
+
* Push an already-built synthetic LarkMessageEvent onto the inbound queue,
|
|
112897
|
+
* so handler.ts processes it as an ordinary turn. Same mechanism as
|
|
112898
|
+
* {@link handleCardAction}'s cardAction → queue.push, generalized for other
|
|
112899
|
+
* bridge-external signal sources — currently only the task-handle comment
|
|
112900
|
+
* poller (src/tasklist/commentPoller.ts), which synthesizes a turn from a
|
|
112901
|
+
* new Feishu task comment. Public because the poller lives outside this
|
|
112902
|
+
* class (main.ts wires it); the caller is fully responsible for building a
|
|
112903
|
+
* well-formed event (thread_id/root_id resolved, etc.) — this method does
|
|
112904
|
+
* no validation of its own, mirroring handleCardAction's contract.
|
|
112905
|
+
*/
|
|
112906
|
+
enqueueSyntheticEvent(ev) {
|
|
112907
|
+
this.queue.push(ev);
|
|
112908
|
+
}
|
|
112047
112909
|
/**
|
|
112048
112910
|
* Return an OutboundCardClient bound to this client's channel handle.
|
|
112049
112911
|
*
|
|
@@ -112654,6 +113516,403 @@ var init_channelClient = __esm({
|
|
|
112654
113516
|
}
|
|
112655
113517
|
});
|
|
112656
113518
|
|
|
113519
|
+
// src/tasklist/client.ts
|
|
113520
|
+
var client_exports = {};
|
|
113521
|
+
__export(client_exports, {
|
|
113522
|
+
TaskApiError: () => TaskApiError,
|
|
113523
|
+
TaskListClient: () => TaskListClient,
|
|
113524
|
+
TaskRequestTimeoutError: () => TaskRequestTimeoutError,
|
|
113525
|
+
isPermissionDeniedError: () => isPermissionDeniedError,
|
|
113526
|
+
isTaskNotFoundError: () => isTaskNotFoundError,
|
|
113527
|
+
isTaskRequestTimeoutError: () => isTaskRequestTimeoutError
|
|
113528
|
+
});
|
|
113529
|
+
function isTaskNotFoundError(err2) {
|
|
113530
|
+
if (err2 instanceof TaskApiError) {
|
|
113531
|
+
if (err2.status === 404) return true;
|
|
113532
|
+
if (typeof err2.message === "string" && /not.?found|不存在|resource_not_exist/i.test(err2.message)) {
|
|
113533
|
+
return true;
|
|
113534
|
+
}
|
|
113535
|
+
}
|
|
113536
|
+
return false;
|
|
113537
|
+
}
|
|
113538
|
+
function isPermissionDeniedError(err2) {
|
|
113539
|
+
if (err2 instanceof TaskApiError) {
|
|
113540
|
+
if (err2.status === 403) return true;
|
|
113541
|
+
if (typeof err2.message === "string" && /no permission|no.access|forbidden|access.denied|无权限|未授权/i.test(err2.message)) {
|
|
113542
|
+
return true;
|
|
113543
|
+
}
|
|
113544
|
+
}
|
|
113545
|
+
return false;
|
|
113546
|
+
}
|
|
113547
|
+
function parseDueMs(task) {
|
|
113548
|
+
const due = asRecord(task["due"]);
|
|
113549
|
+
const timestamp2 = due["timestamp"];
|
|
113550
|
+
if (typeof timestamp2 !== "string") return void 0;
|
|
113551
|
+
const ms = Number(timestamp2);
|
|
113552
|
+
if (!Number.isFinite(ms)) return void 0;
|
|
113553
|
+
return due["is_all_day"] === true ? ms + MS_PER_DAY : ms;
|
|
113554
|
+
}
|
|
113555
|
+
function asRecord(v) {
|
|
113556
|
+
return typeof v === "object" && v !== null ? v : {};
|
|
113557
|
+
}
|
|
113558
|
+
function wrapErr(label, err2) {
|
|
113559
|
+
if (err2 instanceof TaskApiError) throw err2;
|
|
113560
|
+
const rec = asRecord(err2);
|
|
113561
|
+
const response = asRecord(rec["response"]);
|
|
113562
|
+
const status = typeof response["status"] === "number" ? response["status"] : void 0;
|
|
113563
|
+
const body = asRecord(response["data"]);
|
|
113564
|
+
const code = typeof body["code"] === "number" ? body["code"] : void 0;
|
|
113565
|
+
const bodyMsg = typeof body["msg"] === "string" ? body["msg"] : void 0;
|
|
113566
|
+
const message = `[tasklist.client] ${label} failed: ${bodyMsg ?? err2?.message ?? String(err2)}`;
|
|
113567
|
+
throw new TaskApiError(message, { status, code, cause: err2 });
|
|
113568
|
+
}
|
|
113569
|
+
function isTaskRequestTimeoutError(err2) {
|
|
113570
|
+
if (err2 instanceof TaskRequestTimeoutError) return true;
|
|
113571
|
+
if (err2 instanceof TaskApiError && err2.cause instanceof TaskRequestTimeoutError) return true;
|
|
113572
|
+
return false;
|
|
113573
|
+
}
|
|
113574
|
+
function withTimeout(promise, ms, label) {
|
|
113575
|
+
let timer;
|
|
113576
|
+
const timeout = new Promise((_, reject) => {
|
|
113577
|
+
timer = setTimeout(() => reject(new TaskRequestTimeoutError(`${label} timed out after ${ms}ms`)), ms);
|
|
113578
|
+
});
|
|
113579
|
+
return Promise.race([promise, timeout]).finally(() => clearTimeout(timer));
|
|
113580
|
+
}
|
|
113581
|
+
function isNotFoundLikeRaw(err2) {
|
|
113582
|
+
const rec = asRecord(err2);
|
|
113583
|
+
const response = asRecord(rec["response"]);
|
|
113584
|
+
if (response["status"] === 404) return true;
|
|
113585
|
+
const body = asRecord(response["data"]);
|
|
113586
|
+
const msg = typeof body["msg"] === "string" ? body["msg"] : "";
|
|
113587
|
+
return /not.?found|不存在|resource_not_exist/i.test(msg);
|
|
113588
|
+
}
|
|
113589
|
+
var DEFAULT_TIMEOUT_MS, TaskApiError, MS_PER_DAY, TaskRequestTimeoutError, TASK_V2_BASE, TaskListClient;
|
|
113590
|
+
var init_client = __esm({
|
|
113591
|
+
"src/tasklist/client.ts"() {
|
|
113592
|
+
"use strict";
|
|
113593
|
+
DEFAULT_TIMEOUT_MS = 12e3;
|
|
113594
|
+
TaskApiError = class extends Error {
|
|
113595
|
+
status;
|
|
113596
|
+
code;
|
|
113597
|
+
constructor(message, opts) {
|
|
113598
|
+
super(message);
|
|
113599
|
+
this.name = "TaskApiError";
|
|
113600
|
+
this.status = opts.status;
|
|
113601
|
+
this.code = opts.code;
|
|
113602
|
+
this.cause = opts.cause;
|
|
113603
|
+
}
|
|
113604
|
+
};
|
|
113605
|
+
MS_PER_DAY = 24 * 60 * 6e4;
|
|
113606
|
+
TaskRequestTimeoutError = class extends Error {
|
|
113607
|
+
};
|
|
113608
|
+
TASK_V2_BASE = "/open-apis/task/v2";
|
|
113609
|
+
TaskListClient = class {
|
|
113610
|
+
#requester;
|
|
113611
|
+
#timeoutMs;
|
|
113612
|
+
constructor(requester, opts = {}) {
|
|
113613
|
+
this.#requester = requester;
|
|
113614
|
+
this.#timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
113615
|
+
}
|
|
113616
|
+
/** Single choke point for every outbound call — applies the timeout race uniformly. */
|
|
113617
|
+
#request(config, label) {
|
|
113618
|
+
return withTimeout(this.#requester.request(config), this.#timeoutMs, label);
|
|
113619
|
+
}
|
|
113620
|
+
async getTask(taskGuid) {
|
|
113621
|
+
let resp;
|
|
113622
|
+
try {
|
|
113623
|
+
resp = await this.#request(
|
|
113624
|
+
{
|
|
113625
|
+
method: "GET",
|
|
113626
|
+
url: `${TASK_V2_BASE}/tasks/${encodeURIComponent(taskGuid)}`,
|
|
113627
|
+
params: { user_id_type: "open_id" }
|
|
113628
|
+
},
|
|
113629
|
+
`getTask(${taskGuid})`
|
|
113630
|
+
);
|
|
113631
|
+
} catch (err2) {
|
|
113632
|
+
if (isNotFoundLikeRaw(err2)) return null;
|
|
113633
|
+
wrapErr(`getTask(${taskGuid})`, err2);
|
|
113634
|
+
}
|
|
113635
|
+
const task = resp.data?.task;
|
|
113636
|
+
if (!task) return null;
|
|
113637
|
+
return {
|
|
113638
|
+
guid: String(task["guid"] ?? task["id"] ?? taskGuid),
|
|
113639
|
+
summary: typeof task["summary"] === "string" ? task["summary"] : void 0,
|
|
113640
|
+
description: typeof task["description"] === "string" ? task["description"] : void 0,
|
|
113641
|
+
completedAt: typeof task["completed_at"] === "string" ? task["completed_at"] : void 0,
|
|
113642
|
+
dueMs: parseDueMs(task)
|
|
113643
|
+
};
|
|
113644
|
+
}
|
|
113645
|
+
/** Overwrite the task description (bridge-owned status-snapshot block only — see writeback.ts). */
|
|
113646
|
+
async patchDescription(taskGuid, description) {
|
|
113647
|
+
await this.#patchTask(taskGuid, { description }, ["description"]);
|
|
113648
|
+
}
|
|
113649
|
+
/** Mark the task complete "now". */
|
|
113650
|
+
async complete(taskGuid) {
|
|
113651
|
+
await this.#patchTask(taskGuid, { completed_at: String(Date.now()) }, ["completed_at"]);
|
|
113652
|
+
}
|
|
113653
|
+
/**
|
|
113654
|
+
* Clear completed_at (task v2 patch semantics: an `update_fields` entry with
|
|
113655
|
+
* no corresponding value in `task` clears that field — verified via
|
|
113656
|
+
* `lark-cli schema task tasks patch`).
|
|
113657
|
+
*/
|
|
113658
|
+
async reopen(taskGuid) {
|
|
113659
|
+
await this.#patchTask(taskGuid, {}, ["completed_at"]);
|
|
113660
|
+
}
|
|
113661
|
+
async #patchTask(taskGuid, task, updateFields) {
|
|
113662
|
+
const label = `patchTask(${taskGuid}, fields=${updateFields.join(",")})`;
|
|
113663
|
+
try {
|
|
113664
|
+
await this.#request(
|
|
113665
|
+
{
|
|
113666
|
+
method: "PATCH",
|
|
113667
|
+
url: `${TASK_V2_BASE}/tasks/${encodeURIComponent(taskGuid)}`,
|
|
113668
|
+
params: { user_id_type: "open_id" },
|
|
113669
|
+
data: { task, update_fields: updateFields }
|
|
113670
|
+
},
|
|
113671
|
+
label
|
|
113672
|
+
);
|
|
113673
|
+
} catch (err2) {
|
|
113674
|
+
wrapErr(label, err2);
|
|
113675
|
+
}
|
|
113676
|
+
}
|
|
113677
|
+
async addComment(taskGuid, content) {
|
|
113678
|
+
const label = `addComment(${taskGuid})`;
|
|
113679
|
+
try {
|
|
113680
|
+
await this.#request(
|
|
113681
|
+
{
|
|
113682
|
+
method: "POST",
|
|
113683
|
+
url: `${TASK_V2_BASE}/comments`,
|
|
113684
|
+
data: { resource_type: "task", resource_id: taskGuid, content }
|
|
113685
|
+
},
|
|
113686
|
+
label
|
|
113687
|
+
);
|
|
113688
|
+
} catch (err2) {
|
|
113689
|
+
wrapErr(label, err2);
|
|
113690
|
+
}
|
|
113691
|
+
}
|
|
113692
|
+
async listComments(taskGuid, opts = {}) {
|
|
113693
|
+
const label = `listComments(${taskGuid})`;
|
|
113694
|
+
let resp;
|
|
113695
|
+
try {
|
|
113696
|
+
resp = await this.#request(
|
|
113697
|
+
{
|
|
113698
|
+
method: "GET",
|
|
113699
|
+
url: `${TASK_V2_BASE}/comments`,
|
|
113700
|
+
params: {
|
|
113701
|
+
resource_type: "task",
|
|
113702
|
+
resource_id: taskGuid,
|
|
113703
|
+
page_size: opts.pageSize ?? 50,
|
|
113704
|
+
// Spread-omit: the SDK serializes a literal `undefined` value into
|
|
113705
|
+
// the query string ("page_token=undefined"), which strict endpoints
|
|
113706
|
+
// reject with 1470400 — only send the key when we hold a real token.
|
|
113707
|
+
...opts.pageToken ? { page_token: opts.pageToken } : {}
|
|
113708
|
+
}
|
|
113709
|
+
},
|
|
113710
|
+
label
|
|
113711
|
+
);
|
|
113712
|
+
} catch (err2) {
|
|
113713
|
+
wrapErr(label, err2);
|
|
113714
|
+
}
|
|
113715
|
+
const items = resp.data?.items ?? [];
|
|
113716
|
+
const comments = items.map((raw) => {
|
|
113717
|
+
const creator = asRecord(raw["creator"] ?? raw["commentator"]);
|
|
113718
|
+
return {
|
|
113719
|
+
id: String(raw["id"] ?? raw["comment_id"] ?? ""),
|
|
113720
|
+
content: typeof raw["content"] === "string" ? raw["content"] : "",
|
|
113721
|
+
// Real API response uses `created_at` (string ms). create_milli_time/
|
|
113722
|
+
// create_time are kept as fallbacks only in case a differently-versioned
|
|
113723
|
+
// tenant/response shape uses them — created_at is checked first since
|
|
113724
|
+
// it's the verified real field (2026-07 live check against docs/task-handle.md).
|
|
113725
|
+
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,
|
|
113726
|
+
creatorId: typeof creator["id"] === "string" ? creator["id"] : void 0,
|
|
113727
|
+
creatorType: typeof creator["type"] === "string" ? creator["type"] : void 0
|
|
113728
|
+
};
|
|
113729
|
+
});
|
|
113730
|
+
return {
|
|
113731
|
+
comments,
|
|
113732
|
+
hasMore: Boolean(resp.data?.has_more),
|
|
113733
|
+
pageToken: resp.data?.page_token
|
|
113734
|
+
};
|
|
113735
|
+
}
|
|
113736
|
+
/**
|
|
113737
|
+
* Fetch a tasklist's current guid + member list (verified against live
|
|
113738
|
+
* `lark-cli schema task tasklists get`, 1.0.64 — `GET /tasklists/
|
|
113739
|
+
* :tasklist_guid`). Used by `tasklist-init` as a post-create/post-reuse
|
|
113740
|
+
* safety net: read the membership back and warn if the owner's open_id
|
|
113741
|
+
* didn't actually land as a member (a silently-dropped member is a real
|
|
113742
|
+
* platform failure mode this guards against — see tasklistInit.ts).
|
|
113743
|
+
*/
|
|
113744
|
+
async getTasklist(tasklistGuid) {
|
|
113745
|
+
const label = `getTasklist(${tasklistGuid})`;
|
|
113746
|
+
let resp;
|
|
113747
|
+
try {
|
|
113748
|
+
resp = await this.#request(
|
|
113749
|
+
{
|
|
113750
|
+
method: "GET",
|
|
113751
|
+
url: `${TASK_V2_BASE}/tasklists/${encodeURIComponent(tasklistGuid)}`,
|
|
113752
|
+
params: { user_id_type: "open_id" }
|
|
113753
|
+
},
|
|
113754
|
+
label
|
|
113755
|
+
);
|
|
113756
|
+
} catch (err2) {
|
|
113757
|
+
if (isNotFoundLikeRaw(err2)) return null;
|
|
113758
|
+
wrapErr(label, err2);
|
|
113759
|
+
}
|
|
113760
|
+
const tasklist = resp.data?.tasklist;
|
|
113761
|
+
if (!tasklist) return null;
|
|
113762
|
+
const rawMembers = Array.isArray(tasklist["members"]) ? tasklist["members"] : [];
|
|
113763
|
+
const members = rawMembers.map((m) => ({
|
|
113764
|
+
id: String(m["id"] ?? ""),
|
|
113765
|
+
type: m["type"] === "user" || m["type"] === "chat" || m["type"] === "app" ? m["type"] : void 0,
|
|
113766
|
+
role: m["role"] === "assignee" || m["role"] === "follower" || m["role"] === "editor" || m["role"] === "viewer" ? m["role"] : "editor"
|
|
113767
|
+
}));
|
|
113768
|
+
return { guid: String(tasklist["guid"] ?? tasklistGuid), members };
|
|
113769
|
+
}
|
|
113770
|
+
async createTasklist(name, members = []) {
|
|
113771
|
+
const label = `createTasklist(${name})`;
|
|
113772
|
+
let resp;
|
|
113773
|
+
try {
|
|
113774
|
+
resp = await this.#request(
|
|
113775
|
+
{
|
|
113776
|
+
method: "POST",
|
|
113777
|
+
url: `${TASK_V2_BASE}/tasklists`,
|
|
113778
|
+
params: { user_id_type: "open_id" },
|
|
113779
|
+
data: { name, members }
|
|
113780
|
+
},
|
|
113781
|
+
label
|
|
113782
|
+
);
|
|
113783
|
+
} catch (err2) {
|
|
113784
|
+
wrapErr(label, err2);
|
|
113785
|
+
}
|
|
113786
|
+
const guid = resp.data?.tasklist?.["guid"];
|
|
113787
|
+
if (typeof guid !== "string" || guid.length === 0) {
|
|
113788
|
+
throw new TaskApiError(`[tasklist.client] createTasklist(${name}) returned no guid`, {});
|
|
113789
|
+
}
|
|
113790
|
+
return { guid };
|
|
113791
|
+
}
|
|
113792
|
+
/**
|
|
113793
|
+
* List tasks belonging to a tasklist (used by TasklistPoller,
|
|
113794
|
+
* src/tasklist/tasklistPoller.ts, for the v3 "候选注入" candidate
|
|
113795
|
+
* discovery). `GET /tasklists/:tasklist_guid/tasks` verified live
|
|
113796
|
+
* 2026-07-04 against a real tasklist (200 + items[]); note this endpoint
|
|
113797
|
+
* strictly validates `page_token` (a literal "undefined" query value is a
|
|
113798
|
+
* hard 1470400), hence the spread-omit below. Treat as best-effort like
|
|
113799
|
+
* every other tasklist call: TasklistPoller swallows failures and keeps
|
|
113800
|
+
* its previous candidate snapshot rather than propagating.
|
|
113801
|
+
*/
|
|
113802
|
+
async listTasklistTasks(tasklistGuid, opts = {}) {
|
|
113803
|
+
const label = `listTasklistTasks(${tasklistGuid})`;
|
|
113804
|
+
let resp;
|
|
113805
|
+
try {
|
|
113806
|
+
resp = await this.#request(
|
|
113807
|
+
{
|
|
113808
|
+
method: "GET",
|
|
113809
|
+
url: `${TASK_V2_BASE}/tasklists/${encodeURIComponent(tasklistGuid)}/tasks`,
|
|
113810
|
+
params: {
|
|
113811
|
+
user_id_type: "open_id",
|
|
113812
|
+
page_size: opts.pageSize ?? 50,
|
|
113813
|
+
// Same spread-omit as listComments: "page_token=undefined" in the
|
|
113814
|
+
// query string is a hard 400 (1470400) on this endpoint — verified
|
|
113815
|
+
// live 2026-07-04 against a real tasklist.
|
|
113816
|
+
...opts.pageToken ? { page_token: opts.pageToken } : {}
|
|
113817
|
+
}
|
|
113818
|
+
},
|
|
113819
|
+
label
|
|
113820
|
+
);
|
|
113821
|
+
} catch (err2) {
|
|
113822
|
+
wrapErr(label, err2);
|
|
113823
|
+
}
|
|
113824
|
+
const items = resp.data?.items ?? [];
|
|
113825
|
+
const tasks = items.map((task) => ({
|
|
113826
|
+
guid: String(task["guid"] ?? task["id"] ?? ""),
|
|
113827
|
+
summary: typeof task["summary"] === "string" ? task["summary"] : void 0,
|
|
113828
|
+
description: typeof task["description"] === "string" ? task["description"] : void 0,
|
|
113829
|
+
completedAt: typeof task["completed_at"] === "string" ? task["completed_at"] : void 0,
|
|
113830
|
+
dueMs: parseDueMs(task)
|
|
113831
|
+
}));
|
|
113832
|
+
return { tasks, hasMore: Boolean(resp.data?.has_more), pageToken: resp.data?.page_token };
|
|
113833
|
+
}
|
|
113834
|
+
/**
|
|
113835
|
+
* Add members to an existing tasklist (verified against `lark-cli schema
|
|
113836
|
+
* task tasklists add_members`, 1.0.64 — `POST /tasklists/:tasklist_guid/
|
|
113837
|
+
* members`). Used by `tasklist-init --team` and by a bot's own first-run
|
|
113838
|
+
* self-join (docs/task-handle.md §7 "同一 owner 的一组 bot… 把自己加为
|
|
113839
|
+
* editor") to add sibling bot apps as `editor` members of the shared
|
|
113840
|
+
* "Agent Team" list. Idempotent from the caller's perspective: re-adding an
|
|
113841
|
+
* existing member is a harmless no-op per the platform (not independently
|
|
113842
|
+
* verified against a live 409/duplicate-shaped error — callers should treat
|
|
113843
|
+
* any failure here as best-effort, same swallow-and-warn posture as the
|
|
113844
|
+
* rest of this feature).
|
|
113845
|
+
*/
|
|
113846
|
+
async addTasklistMembers(tasklistGuid, members) {
|
|
113847
|
+
const label = `addTasklistMembers(${tasklistGuid})`;
|
|
113848
|
+
try {
|
|
113849
|
+
await this.#request(
|
|
113850
|
+
{
|
|
113851
|
+
method: "POST",
|
|
113852
|
+
url: `${TASK_V2_BASE}/tasklists/${encodeURIComponent(tasklistGuid)}/members`,
|
|
113853
|
+
params: { user_id_type: "open_id" },
|
|
113854
|
+
data: { members }
|
|
113855
|
+
},
|
|
113856
|
+
label
|
|
113857
|
+
);
|
|
113858
|
+
} catch (err2) {
|
|
113859
|
+
wrapErr(label, err2);
|
|
113860
|
+
}
|
|
113861
|
+
}
|
|
113862
|
+
};
|
|
113863
|
+
}
|
|
113864
|
+
});
|
|
113865
|
+
|
|
113866
|
+
// src/tasklist/teamRegistry.ts
|
|
113867
|
+
var teamRegistry_exports = {};
|
|
113868
|
+
__export(teamRegistry_exports, {
|
|
113869
|
+
claimTeamTasklistGuid: () => claimTeamTasklistGuid,
|
|
113870
|
+
overwriteTeamTasklistGuid: () => overwriteTeamTasklistGuid,
|
|
113871
|
+
readTeamTasklistGuid: () => readTeamTasklistGuid
|
|
113872
|
+
});
|
|
113873
|
+
import { rename as rename4, readFile as readFile6, writeFile as writeFile5, mkdir as mkdir4 } from "node:fs/promises";
|
|
113874
|
+
import { dirname } from "node:path";
|
|
113875
|
+
async function readTeamTasklistGuid(filePath) {
|
|
113876
|
+
try {
|
|
113877
|
+
const raw = await readFile6(filePath, "utf8");
|
|
113878
|
+
const parsed = JSON.parse(raw);
|
|
113879
|
+
if (typeof parsed !== "object" || parsed === null) return void 0;
|
|
113880
|
+
const guid = parsed["tasklistGuid"];
|
|
113881
|
+
return typeof guid === "string" && guid.length > 0 ? guid : void 0;
|
|
113882
|
+
} catch {
|
|
113883
|
+
return void 0;
|
|
113884
|
+
}
|
|
113885
|
+
}
|
|
113886
|
+
async function claimTeamTasklistGuid(filePath, tasklistGuid) {
|
|
113887
|
+
const existing = await readTeamTasklistGuid(filePath);
|
|
113888
|
+
if (existing) return existing;
|
|
113889
|
+
await writeTeamTasklistGuid(filePath, tasklistGuid);
|
|
113890
|
+
return tasklistGuid;
|
|
113891
|
+
}
|
|
113892
|
+
async function overwriteTeamTasklistGuid(filePath, tasklistGuid) {
|
|
113893
|
+
await writeTeamTasklistGuid(filePath, tasklistGuid);
|
|
113894
|
+
}
|
|
113895
|
+
async function writeTeamTasklistGuid(filePath, tasklistGuid) {
|
|
113896
|
+
try {
|
|
113897
|
+
const file = { version: 1, tasklistGuid };
|
|
113898
|
+
const json2 = JSON.stringify(file, null, 2);
|
|
113899
|
+
const tmpPath = `${filePath}.tmp`;
|
|
113900
|
+
await mkdir4(dirname(filePath), { recursive: true });
|
|
113901
|
+
await writeFile5(tmpPath, json2, "utf8");
|
|
113902
|
+
await rename4(tmpPath, filePath);
|
|
113903
|
+
} catch (err2) {
|
|
113904
|
+
console.warn(
|
|
113905
|
+
`[tasklist.teamRegistry] failed to persist tasklistGuid to ${filePath} (continuing, best-effort):`,
|
|
113906
|
+
err2
|
|
113907
|
+
);
|
|
113908
|
+
}
|
|
113909
|
+
}
|
|
113910
|
+
var init_teamRegistry = __esm({
|
|
113911
|
+
"src/tasklist/teamRegistry.ts"() {
|
|
113912
|
+
"use strict";
|
|
113913
|
+
}
|
|
113914
|
+
});
|
|
113915
|
+
|
|
112657
113916
|
// node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/can-promise.js
|
|
112658
113917
|
var require_can_promise = __commonJS({
|
|
112659
113918
|
"node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/can-promise.js"(exports, module) {
|
|
@@ -116991,7 +118250,7 @@ var require_canvas = __commonJS({
|
|
|
116991
118250
|
});
|
|
116992
118251
|
|
|
116993
118252
|
// node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/browser.js
|
|
116994
|
-
var
|
|
118253
|
+
var require_browser2 = __commonJS({
|
|
116995
118254
|
"node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/browser.js"(exports) {
|
|
116996
118255
|
var canPromise = require_can_promise();
|
|
116997
118256
|
var QRCode2 = require_qrcode();
|
|
@@ -117138,7 +118397,7 @@ var require_server = __commonJS({
|
|
|
117138
118397
|
}
|
|
117139
118398
|
}
|
|
117140
118399
|
exports.create = QRCode2.create;
|
|
117141
|
-
exports.toCanvas =
|
|
118400
|
+
exports.toCanvas = require_browser2().toCanvas;
|
|
117142
118401
|
exports.toString = function toString3(text, opts, cb) {
|
|
117143
118402
|
const params = checkParams(text, opts, cb);
|
|
117144
118403
|
const type2 = params.opts ? params.opts.type : void 0;
|
|
@@ -124196,10 +125455,81 @@ var ResponseSurfacePrototypeConfigSchema = external_exports.object({
|
|
|
124196
125455
|
}).default(responseSurfacePrototypeConfigDefaults);
|
|
124197
125456
|
|
|
124198
125457
|
// src/config/botLoader.ts
|
|
125458
|
+
var KNOWN_EFFORT_VALUES = /* @__PURE__ */ new Set(["low", "medium", "high", "max"]);
|
|
124199
125459
|
var GitIdentitySchema = external_exports.object({
|
|
124200
125460
|
name: external_exports.string().min(1),
|
|
124201
125461
|
email: external_exports.string().email()
|
|
124202
125462
|
});
|
|
125463
|
+
var TaskHandleConfigSchema = external_exports.object({
|
|
125464
|
+
/**
|
|
125465
|
+
* owner 的「Agent Team」共享清单 GUID。由 `larkway tasklist-init --team`
|
|
125466
|
+
* provisioning 子命令产出并手工填入,或经共享注册文件(task-team.json)被
|
|
125467
|
+
* 同组 bot 自动发现。缺失 = 功能休眠(main.ts 不会替你建)。
|
|
125468
|
+
*/
|
|
125469
|
+
tasklistGuid: external_exports.string().min(1).optional(),
|
|
125470
|
+
/**
|
|
125471
|
+
* @deprecated v1 遗留字段,v2 已去掉「enabled 开关」语义 —— 真正门槛见上。
|
|
125472
|
+
* 仅为了不 break 现网已写 `enabled: true` 的 yaml(strict schema 否则会拒绝
|
|
125473
|
+
* 未知字段)而接受它;接受后从不读取,loadBots() 会打一条 deprecation warn
|
|
125474
|
+
* 提示删除。新 yaml 不要再写这个字段。
|
|
125475
|
+
*/
|
|
125476
|
+
enabled: external_exports.boolean().optional(),
|
|
125477
|
+
/**
|
|
125478
|
+
* v3.1 停滞检测(docs/task-handle.md §12)全部可选,均有保守默认值——不配
|
|
125479
|
+
* 就用默认阈值,不是新的 enable 开关(检测本身跟 tasklistGuid 一样,只要有
|
|
125480
|
+
* 认领记录就跑;想彻底关掉停滞检测本身,见 stallDetectionDisabled)。
|
|
125481
|
+
*/
|
|
125482
|
+
/** 绑定话题超过这个时长(ms)无活动 → 判定停滞,唤醒认领的 agent。默认 24h。 */
|
|
125483
|
+
stallThresholdMs: external_exports.number().positive().optional(),
|
|
125484
|
+
/** 若该话题最后一轮 turn 以失败/崩溃收场,改用这个更短的阈值(ms)。默认 30min。 */
|
|
125485
|
+
stallFastThresholdMs: external_exports.number().positive().optional(),
|
|
125486
|
+
/**
|
|
125487
|
+
* v3.2 交接断链检测(docs/task-handle.md §13):若最后一轮完成 turn 的回复
|
|
125488
|
+
* @ 了花名册上的另一个 bot,且对方的 bridge 在这个阈值(ms)内在同一话题没
|
|
125489
|
+
* 有收到任何事件,改用这个更短的阈值(优先级高于上面两个,取更短者)。
|
|
125490
|
+
* 默认 5min——协作断链比一般停滞紧急得多,任务多为小时级,理应分钟级发现。
|
|
125491
|
+
* **下限提示**:5min 对应本机 open 模式 bot 的 gap-fill 巡检周期(300s)+
|
|
125492
|
+
* 一个 patrol tick 缓冲——配更短不会被拦,但低于部署实际的 gap-fill 周期
|
|
125493
|
+
* 有跟补投撞车、同一事件被提醒两次的风险,见 docs/task-handle.md §13。只有
|
|
125494
|
+
* 明确 chats 白名单(非 open 模式)的 bot 没有周期性 gap-fill(只有断线重连
|
|
125495
|
+
* 触发),下限可以放宽到 2min。且只对**同一 bridge 进程内**的协作 bot 生
|
|
125496
|
+
* 效——跨 bridge 的 @ 天生观察不到对方的收到时间,走一般停滞阈值。
|
|
125497
|
+
* **收到只是暂缓,不是永久解除**——见 stallHandoffReceiptGraceMs。
|
|
125498
|
+
*/
|
|
125499
|
+
stallHandoffThresholdMs: external_exports.number().positive().optional(),
|
|
125500
|
+
/**
|
|
125501
|
+
* v3.2 revision 3(docs/task-handle.md §13):对方"收到了事件"只在这个阈值
|
|
125502
|
+
* (ms)内被信任——收到之后这段时间里,如果对方**真的跑完一轮 turn**(不是
|
|
125503
|
+
* 又收到一次事件),才算真正解除交接断链;超过这个时长仍没有对方跑完 turn
|
|
125504
|
+
* 的记录,重新判定为断链、再次提醒。默认 30min(相对 handler.ts 自己注释的
|
|
125505
|
+
* 单轮 turn 5-15 分钟耗时留足余量)。防的是反向漏洞:如果"收到"永久解除
|
|
125506
|
+
* 断链判定,对方收到后真的崩了/卡死,就再也不会被判定断链了。
|
|
125507
|
+
*/
|
|
125508
|
+
stallHandoffReceiptGraceMs: external_exports.number().positive().optional(),
|
|
125509
|
+
/** 同一任务两次提醒之间的最短间隔(ms),防止骚扰。默认 24h。 */
|
|
125510
|
+
stallNudgeCooldownMs: external_exports.number().positive().optional(),
|
|
125511
|
+
/** 连续几次提醒仍无进展后改为升级(任务评论通知人类,此后对该任务静默直到有新活动)。默认 2。 */
|
|
125512
|
+
stallEscalateAfterNudges: external_exports.number().int().positive().optional(),
|
|
125513
|
+
/** 彻底关闭停滞检测(默认 false = 开启,阈值保守)。 */
|
|
125514
|
+
stallDetectionDisabled: external_exports.boolean().optional(),
|
|
125515
|
+
/**
|
|
125516
|
+
* v3.3 候选黑洞提示(docs/task-handle.md §14):共享清单里一个未认领候选
|
|
125517
|
+
* 任务连续滞留超过这个时长(ms)仍没被任何话题绑定(自动或人工认领都算解除),
|
|
125518
|
+
* TasklistPoller 就在该任务下留一条机械提示评论(每个候选只提一次,绑定
|
|
125519
|
+
* 成功后从"已提示"集合清除,再次滞留可再提)。默认 1h。只对同一 tasklistGuid
|
|
125520
|
+
* 共享组里"首个解析出该 guid 的 bot"的配置生效(跟 TasklistPoller 本身
|
|
125521
|
+
* "一个 guid 一个实例"的粒度一致,见 clientOwnerBotId 的同款约定)。
|
|
125522
|
+
*/
|
|
125523
|
+
candidateUnboundAlertMs: external_exports.number().positive().optional(),
|
|
125524
|
+
/**
|
|
125525
|
+
* v3.3 全局唤醒保险丝(docs/task-handle.md §14):这个 bot 的 StallDetector
|
|
125526
|
+
* 每小时(滚动窗口,非整点分桶)最多合成几次唤醒 turn(含通用/断链/过期各
|
|
125527
|
+
* 档,不含升级评论)。超限本轮抑制,只打一条点名哪个任务被抑制的 warn 日志,
|
|
125528
|
+
* 不改任何持久状态,下一轮正常重新评估。默认 6——纯粹是防止未知 bug 导致
|
|
125529
|
+
* 唤醒风暴烧推理额度的保险丝,正常路径永远碰不到它,不是需要调优的阈值。
|
|
125530
|
+
*/
|
|
125531
|
+
stallNudgeHourlyCap: external_exports.number().int().positive().optional()
|
|
125532
|
+
}).strict();
|
|
124203
125533
|
var GitCloneUrlSchema = external_exports.string().min(1).refine(
|
|
124204
125534
|
(value) => {
|
|
124205
125535
|
if (/^https?:\/\/\S+$/i.test(value)) return true;
|
|
@@ -124387,7 +125717,67 @@ var BotConfigSchema = external_exports.object({
|
|
|
124387
125717
|
*
|
|
124388
125718
|
* @default "claude"
|
|
124389
125719
|
*/
|
|
124390
|
-
backend: external_exports.string().min(1).default("claude")
|
|
125720
|
+
backend: external_exports.string().min(1).default("claude"),
|
|
125721
|
+
/**
|
|
125722
|
+
* 话题 ↔ 飞书任务句柄(docs/task-handle.md,v2)。省略此字段不代表关闭,但也
|
|
125723
|
+
* 不会触发任何自动建清单——main.ts 在 startup 时只做只读解析(yaml 里的
|
|
125724
|
+
* tasklistGuid,或共享注册文件里已有的 guid);清单本身只由
|
|
125725
|
+
* `larkway tasklist-init --team` 建一次。
|
|
125726
|
+
*/
|
|
125727
|
+
taskHandle: TaskHandleConfigSchema.optional(),
|
|
125728
|
+
/**
|
|
125729
|
+
* Per-bot model override (perf plan 批 C 旋钮). Passed through verbatim to
|
|
125730
|
+
* the backend CLI as `--model <value>` (claude) / `turn/start.model`
|
|
125731
|
+
* (codex) — larkway does not validate or allowlist model ids, same
|
|
125732
|
+
* precedent as `backend` above. Omitted = unchanged host/backend default
|
|
125733
|
+
* behavior (byte-identical to before this field existed).
|
|
125734
|
+
*/
|
|
125735
|
+
model: external_exports.string().min(1).optional(),
|
|
125736
|
+
/**
|
|
125737
|
+
* Per-bot reasoning-effort override (perf plan 批 C 旋钮). Passed through
|
|
125738
|
+
* verbatim as `--effort <value>` on the claude CLI (confirmed supported:
|
|
125739
|
+
* `claude --effort low|medium|high|max`, also non-interactive). Also
|
|
125740
|
+
* confirmed supported on codex via `turn/start.effort`, mapped through
|
|
125741
|
+
* codexEffortFromLarkway (src/codex/runner.ts) since codex's own value
|
|
125742
|
+
* space is low/medium/high/xhigh, not low/medium/high/max. Omitted =
|
|
125743
|
+
* unchanged default behavior.
|
|
125744
|
+
*/
|
|
125745
|
+
effort: external_exports.string().min(1).optional(),
|
|
125746
|
+
/**
|
|
125747
|
+
* docs/larkway-perf-plan.md §4 — opt into a persistent warm process
|
|
125748
|
+
* instead of the default one-shot cold-start-per-turn behavior. Takes
|
|
125749
|
+
* effect for `backend: "codex"` (a single bot-level `codex app-server`
|
|
125750
|
+
* process — src/codex/pool.ts CodexProcessPool) and `backend: "claude"`
|
|
125751
|
+
* (one warm process per active thread — src/claude/pool.ts
|
|
125752
|
+
* ClaudeProcessPool). Any other backend value is a no-op (main.ts only
|
|
125753
|
+
* constructs a pool for these two; botLoader's advisory warn below flags
|
|
125754
|
+
* the mismatch upfront). Byte-identical behavior when unset, matching
|
|
125755
|
+
* every other perf-plan flag in this schema. `.optional()` (not
|
|
125756
|
+
* `.default(false)`, deliberately — B1 fix): a `.default()` would make
|
|
125757
|
+
* every future `larkway bot` yaml write-out include `warmProcess: false`
|
|
125758
|
+
* even when nobody asked for it, and — because this schema is `.strict()`
|
|
125759
|
+
* — would break loading that yaml back with an OLDER larkway build that
|
|
125760
|
+
* predates this field. `undefined` and `false` are treated identically at
|
|
125761
|
+
* both read sites (main.ts's `bot.warmProcess && …` and the advisory warn
|
|
125762
|
+
* below).
|
|
125763
|
+
*/
|
|
125764
|
+
warmProcess: external_exports.boolean().optional(),
|
|
125765
|
+
/**
|
|
125766
|
+
* Idle threshold (ms) before a warm process (see `warmProcess` above) with
|
|
125767
|
+
* no in-flight turn gets SIGTERM'd. Only meaningful when `warmProcess` is
|
|
125768
|
+
* true. @default 10 * 60 * 1000 (10 min) — see DEFAULT_WARM_PROCESS_IDLE_MS
|
|
125769
|
+
* in src/codex/pool.ts (backend "codex") / src/claude/pool.ts (backend
|
|
125770
|
+
* "claude") — both use the same default value.
|
|
125771
|
+
*/
|
|
125772
|
+
warmProcessIdleMs: external_exports.number().int().positive().optional(),
|
|
125773
|
+
/**
|
|
125774
|
+
* `backend: "claude"` only: cap on how many warm per-thread processes
|
|
125775
|
+
* ClaudeProcessPool keeps alive at once (LRU-evicts the longest-idle one
|
|
125776
|
+
* past this). Meaningless for `backend: "codex"`, which only ever holds
|
|
125777
|
+
* one bot-level process regardless. @default 6 — see DEFAULT_MAX_PROCESSES
|
|
125778
|
+
* in src/claude/pool.ts.
|
|
125779
|
+
*/
|
|
125780
|
+
warmProcessMaxProcesses: external_exports.number().int().positive().optional()
|
|
124391
125781
|
}).strict();
|
|
124392
125782
|
async function loadBots(botsDir) {
|
|
124393
125783
|
let entries;
|
|
@@ -124425,6 +125815,21 @@ async function loadBots(botsDir) {
|
|
|
124425
125815
|
${issues}`);
|
|
124426
125816
|
}
|
|
124427
125817
|
const bot = result.data;
|
|
125818
|
+
if (bot.effort && !KNOWN_EFFORT_VALUES.has(bot.effort)) {
|
|
125819
|
+
console.warn(
|
|
125820
|
+
`[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.`
|
|
125821
|
+
);
|
|
125822
|
+
}
|
|
125823
|
+
if (bot.warmProcess && bot.backend !== "codex" && bot.backend !== "claude") {
|
|
125824
|
+
console.warn(
|
|
125825
|
+
`[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.`
|
|
125826
|
+
);
|
|
125827
|
+
}
|
|
125828
|
+
if (bot.taskHandle?.enabled !== void 0) {
|
|
125829
|
+
console.warn(
|
|
125830
|
+
`[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.`
|
|
125831
|
+
);
|
|
125832
|
+
}
|
|
124428
125833
|
if (bot.memory_file) {
|
|
124429
125834
|
const memoryPath2 = path.join(botsDir, bot.memory_file);
|
|
124430
125835
|
try {
|
|
@@ -124456,25 +125861,8 @@ ${issues}`);
|
|
|
124456
125861
|
return bots;
|
|
124457
125862
|
}
|
|
124458
125863
|
|
|
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
125864
|
// src/cli/botsStore.ts
|
|
125865
|
+
init_paths();
|
|
124478
125866
|
function resolveBotsDir() {
|
|
124479
125867
|
const override = process.env.LARKWAY_BOTS_DIR;
|
|
124480
125868
|
if (override && override.trim() !== "") return path2.resolve(override);
|
|
@@ -124637,6 +126025,7 @@ var import_dotenv = __toESM(require_main(), 1);
|
|
|
124637
126025
|
import { readFile as readFile3 } from "node:fs/promises";
|
|
124638
126026
|
import os from "node:os";
|
|
124639
126027
|
import path3 from "node:path";
|
|
126028
|
+
init_paths();
|
|
124640
126029
|
import_dotenv.default.config();
|
|
124641
126030
|
import_dotenv.default.config({ path: path3.join(larkwayHome(), ".env") });
|
|
124642
126031
|
var ConfigSchema = external_exports.object({
|
|
@@ -124696,6 +126085,7 @@ var ConfigJson = external_exports.object({
|
|
|
124696
126085
|
var DEFAULT_CONFIG_PATH = path3.join(larkwayHome(), "config.json");
|
|
124697
126086
|
|
|
124698
126087
|
// src/cli/hostConfig.ts
|
|
126088
|
+
init_paths();
|
|
124699
126089
|
function resolveLarkwayHome() {
|
|
124700
126090
|
return larkwayHome();
|
|
124701
126091
|
}
|
|
@@ -125420,6 +126810,7 @@ async function ensureMemoryScaffold(workspacePath) {
|
|
|
125420
126810
|
}
|
|
125421
126811
|
|
|
125422
126812
|
// src/cli/commands/init.ts
|
|
126813
|
+
init_paths();
|
|
125423
126814
|
var execFileAsync3 = promisify3(execFile3);
|
|
125424
126815
|
function checkNodeVersion() {
|
|
125425
126816
|
const version = process.versions.node;
|
|
@@ -126103,7 +127494,7 @@ async function run(ctx, args) {
|
|
|
126103
127494
|
}
|
|
126104
127495
|
|
|
126105
127496
|
// src/cli/commands/doctor.ts
|
|
126106
|
-
import { access as access6, readdir as readdir4, readFile as
|
|
127497
|
+
import { access as access6, readdir as readdir4, readFile as readFile7, rm } from "node:fs/promises";
|
|
126107
127498
|
import { execFile as execFile5 } from "node:child_process";
|
|
126108
127499
|
import path10 from "node:path";
|
|
126109
127500
|
import { promisify as promisify5 } from "node:util";
|
|
@@ -126325,7 +127716,7 @@ async function checkWorktrees(ctx) {
|
|
|
126325
127716
|
const gitPath = path10.join(worktreeDir, ".git");
|
|
126326
127717
|
let gitContent = null;
|
|
126327
127718
|
try {
|
|
126328
|
-
const stat6 = await
|
|
127719
|
+
const stat6 = await readFile7(gitPath, "utf-8").catch(() => null);
|
|
126329
127720
|
gitContent = stat6;
|
|
126330
127721
|
} catch {
|
|
126331
127722
|
}
|
|
@@ -126471,6 +127862,94 @@ async function checkWsConnectivity(ctx, opts) {
|
|
|
126471
127862
|
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
127863
|
};
|
|
126473
127864
|
}
|
|
127865
|
+
async function probeTaskScope(appId, appSecret, tasklistGuid) {
|
|
127866
|
+
try {
|
|
127867
|
+
const { Client: LarkSdkClient2 } = await Promise.resolve().then(() => __toESM(require_lib2(), 1));
|
|
127868
|
+
const { TaskListClient: TaskListClient2 } = await Promise.resolve().then(() => (init_client(), client_exports));
|
|
127869
|
+
const sdkClient = new LarkSdkClient2({ appId, appSecret });
|
|
127870
|
+
const taskClient = new TaskListClient2({
|
|
127871
|
+
request: (config) => sdkClient.request(config)
|
|
127872
|
+
});
|
|
127873
|
+
await taskClient.listTasklistTasks(tasklistGuid, { pageSize: 1 });
|
|
127874
|
+
return { ok: true };
|
|
127875
|
+
} catch (err2) {
|
|
127876
|
+
return { ok: false, message: err2 instanceof Error ? err2.message : String(err2) };
|
|
127877
|
+
}
|
|
127878
|
+
}
|
|
127879
|
+
var TASK_HANDLE_REQUIRED_SCOPES = [
|
|
127880
|
+
"task:tasklist:read",
|
|
127881
|
+
"task:tasklist:write",
|
|
127882
|
+
"task:task:read",
|
|
127883
|
+
"task:comment:write"
|
|
127884
|
+
];
|
|
127885
|
+
async function checkTaskHandle(ctx, opts) {
|
|
127886
|
+
const results = [];
|
|
127887
|
+
const botIds = await ctx.botsStore.listBots();
|
|
127888
|
+
if (botIds.length === 0) return results;
|
|
127889
|
+
const { resolveTaskTeamRegistryPath: resolveTaskTeamRegistryPath2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
127890
|
+
const { readTeamTasklistGuid: readTeamTasklistGuid2 } = await Promise.resolve().then(() => (init_teamRegistry(), teamRegistry_exports));
|
|
127891
|
+
const registryGuid = await readTeamTasklistGuid2(resolveTaskTeamRegistryPath2());
|
|
127892
|
+
let anyConfigured = false;
|
|
127893
|
+
for (const id of botIds) {
|
|
127894
|
+
let bot;
|
|
127895
|
+
try {
|
|
127896
|
+
bot = await ctx.botsStore.readBot(id);
|
|
127897
|
+
} catch {
|
|
127898
|
+
continue;
|
|
127899
|
+
}
|
|
127900
|
+
const guid = bot.taskHandle?.tasklistGuid ?? registryGuid;
|
|
127901
|
+
if (!guid) continue;
|
|
127902
|
+
anyConfigured = true;
|
|
127903
|
+
if (process.env["LARKWAY_SKIP_WS_PROBE"] === "1") {
|
|
127904
|
+
results.push({
|
|
127905
|
+
id: `task-handle-${id}`,
|
|
127906
|
+
label: `bot "${id}" \u8BDD\u9898\u2194\u4EFB\u52A1\u53E5\u67C4`,
|
|
127907
|
+
status: "ok",
|
|
127908
|
+
message: `\u5DF2\u914D\u7F6E(guid=${guid}),scope \u63A2\u6D4B\u5DF2\u8DF3\u8FC7(LARKWAY_SKIP_WS_PROBE=1)\u3002`
|
|
127909
|
+
});
|
|
127910
|
+
continue;
|
|
127911
|
+
}
|
|
127912
|
+
const appSecret = await ctx.hostConfig.readSecret(bot.app_secret_env);
|
|
127913
|
+
if (!appSecret) {
|
|
127914
|
+
results.push({
|
|
127915
|
+
id: `task-handle-${id}`,
|
|
127916
|
+
label: `bot "${id}" \u8BDD\u9898\u2194\u4EFB\u52A1\u53E5\u67C4`,
|
|
127917
|
+
status: "warn",
|
|
127918
|
+
message: `\u5DF2\u914D\u7F6E guid=${guid},\u4F46 AppSecret \u7F3A\u5931,\u8DF3\u8FC7 scope \u63A2\u6D4B(\u89C1\u98DE\u4E66\u51ED\u636E\u68C0\u67E5\u9879)\u3002`
|
|
127919
|
+
});
|
|
127920
|
+
continue;
|
|
127921
|
+
}
|
|
127922
|
+
const probe = await probeTaskScope(bot.app_id, appSecret, guid);
|
|
127923
|
+
if (probe.ok) {
|
|
127924
|
+
results.push({
|
|
127925
|
+
id: `task-handle-${id}`,
|
|
127926
|
+
label: `bot "${id}" \u8BDD\u9898\u2194\u4EFB\u52A1\u53E5\u67C4`,
|
|
127927
|
+
status: "ok",
|
|
127928
|
+
message: `\u5DF2\u914D\u7F6E(guid=${guid}),task scope \u63A2\u6D4B\u6210\u529F\u3002`
|
|
127929
|
+
});
|
|
127930
|
+
} else {
|
|
127931
|
+
const scopeLink = `https://open.feishu.cn/app/${bot.app_id}/auth?q=${TASK_HANDLE_REQUIRED_SCOPES.join(",")}&op_from=doctor&token_type=tenant`;
|
|
127932
|
+
const looksLikeScopeError = /scope|permission|无权限|未授权|access.denied/i.test(probe.message ?? "");
|
|
127933
|
+
results.push({
|
|
127934
|
+
id: `task-handle-${id}`,
|
|
127935
|
+
label: `bot "${id}" \u8BDD\u9898\u2194\u4EFB\u52A1\u53E5\u67C4`,
|
|
127936
|
+
status: opts.lint && !looksLikeScopeError ? "warn" : "error",
|
|
127937
|
+
message: `\u5DF2\u914D\u7F6E guid=${guid},\u4F46 task scope \u63A2\u6D4B\u5931\u8D25:${probe.message ?? "\u672A\u77E5\u9519\u8BEF"}
|
|
127938
|
+
\u9700\u8981\u4EE5\u4E0B scope:${TASK_HANDLE_REQUIRED_SCOPES.join(", ")}
|
|
127939
|
+
\u5F00\u901A\u94FE\u63A5:${scopeLink}`
|
|
127940
|
+
});
|
|
127941
|
+
}
|
|
127942
|
+
}
|
|
127943
|
+
if (!anyConfigured) {
|
|
127944
|
+
results.push({
|
|
127945
|
+
id: "task-handle-not-configured",
|
|
127946
|
+
label: "\u8BDD\u9898\u2194\u4EFB\u52A1\u53E5\u67C4 (\u53EF\u9009)",
|
|
127947
|
+
status: "ok",
|
|
127948
|
+
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'
|
|
127949
|
+
});
|
|
127950
|
+
}
|
|
127951
|
+
return results;
|
|
127952
|
+
}
|
|
126474
127953
|
async function runAllChecks(ctx, opts) {
|
|
126475
127954
|
const results = [];
|
|
126476
127955
|
results.push(await checkClaude(ctx));
|
|
@@ -126483,6 +127962,8 @@ async function runAllChecks(ctx, opts) {
|
|
|
126483
127962
|
results.push(await checkWsConnectivity(ctx, opts));
|
|
126484
127963
|
const codexChecks = await checkCodex(ctx);
|
|
126485
127964
|
results.push(...codexChecks);
|
|
127965
|
+
const taskHandleChecks = await checkTaskHandle(ctx, opts);
|
|
127966
|
+
results.push(...taskHandleChecks);
|
|
126486
127967
|
return results;
|
|
126487
127968
|
}
|
|
126488
127969
|
function exitCodeFromResults(results) {
|
|
@@ -126664,6 +128145,7 @@ async function run2(ctx, args) {
|
|
|
126664
128145
|
|
|
126665
128146
|
// src/cli/commands/bot.ts
|
|
126666
128147
|
import path11 from "node:path";
|
|
128148
|
+
init_paths();
|
|
126667
128149
|
async function run3(ctx, args) {
|
|
126668
128150
|
const sub = args[0];
|
|
126669
128151
|
const rest = args.slice(1);
|
|
@@ -127265,10 +128747,10 @@ function inferLarkwayHome(botsDir, fallback) {
|
|
|
127265
128747
|
}
|
|
127266
128748
|
|
|
127267
128749
|
// src/cli/commands/memory.ts
|
|
127268
|
-
import { readFile as
|
|
128750
|
+
import { readFile as readFile8 } from "node:fs/promises";
|
|
127269
128751
|
import { spawn } from "node:child_process";
|
|
127270
128752
|
import { tmpdir } from "node:os";
|
|
127271
|
-
import { mkdir as
|
|
128753
|
+
import { mkdir as mkdir5, writeFile as writeFile6, rm as rm2 } from "node:fs/promises";
|
|
127272
128754
|
import path12 from "node:path";
|
|
127273
128755
|
import process2 from "node:process";
|
|
127274
128756
|
function parseArgs(args) {
|
|
@@ -127289,10 +128771,10 @@ function parseArgs(args) {
|
|
|
127289
128771
|
async function openInEditor(initial) {
|
|
127290
128772
|
const editor = process2.env.EDITOR || process2.env.VISUAL || "vi";
|
|
127291
128773
|
const tmpDir = path12.join(tmpdir(), `larkway-memory-${process2.pid}`);
|
|
127292
|
-
await
|
|
128774
|
+
await mkdir5(tmpDir, { recursive: true });
|
|
127293
128775
|
const tmpFile = path12.join(tmpDir, "memory.md");
|
|
127294
128776
|
try {
|
|
127295
|
-
await
|
|
128777
|
+
await writeFile6(tmpFile, initial, "utf-8");
|
|
127296
128778
|
await new Promise((resolve2, reject) => {
|
|
127297
128779
|
const child = spawn(editor, [tmpFile], {
|
|
127298
128780
|
stdio: "inherit",
|
|
@@ -127305,7 +128787,7 @@ async function openInEditor(initial) {
|
|
|
127305
128787
|
else resolve2();
|
|
127306
128788
|
});
|
|
127307
128789
|
});
|
|
127308
|
-
return await
|
|
128790
|
+
return await readFile8(tmpFile, "utf-8");
|
|
127309
128791
|
} finally {
|
|
127310
128792
|
await rm2(tmpDir, { recursive: true, force: true });
|
|
127311
128793
|
}
|
|
@@ -127346,7 +128828,7 @@ async function subSet(ctx, id, file) {
|
|
|
127346
128828
|
if (!await assertBotExists(ctx, id)) return 1;
|
|
127347
128829
|
let content;
|
|
127348
128830
|
try {
|
|
127349
|
-
content = await
|
|
128831
|
+
content = await readFile8(file, "utf-8");
|
|
127350
128832
|
} catch (e) {
|
|
127351
128833
|
const msg = `\u65E0\u6CD5\u8BFB\u53D6\u6587\u4EF6 "${file}": ${e instanceof Error ? e.message : String(e)}`;
|
|
127352
128834
|
if (ctx.flags.json) {
|
|
@@ -127467,8 +128949,9 @@ async function run4(ctx, args) {
|
|
|
127467
128949
|
}
|
|
127468
128950
|
|
|
127469
128951
|
// src/cli/commands/perms.ts
|
|
127470
|
-
import { mkdir as
|
|
128952
|
+
import { mkdir as mkdir6, readFile as readFile9, writeFile as writeFile7 } from "node:fs/promises";
|
|
127471
128953
|
import path13 from "node:path";
|
|
128954
|
+
init_paths();
|
|
127472
128955
|
function parsePermsArgs(args) {
|
|
127473
128956
|
const flags = {
|
|
127474
128957
|
addChats: [],
|
|
@@ -127664,7 +129147,7 @@ async function writePermissionGrants(ctx, id, flags) {
|
|
|
127664
129147
|
const grantedPath = path13.join(workspacePath, "permissions-granted.md");
|
|
127665
129148
|
const grants = [];
|
|
127666
129149
|
if (flags.grantFromRequest) {
|
|
127667
|
-
const requestText = await
|
|
129150
|
+
const requestText = await readFile9(requestPath, "utf8").catch(() => "");
|
|
127668
129151
|
grants.push(...extractRequestLines(requestText));
|
|
127669
129152
|
}
|
|
127670
129153
|
grants.push(...renderCapabilityGrantLines(splitPermissionList(flags.grantPermissions)));
|
|
@@ -127684,8 +129167,8 @@ async function writePermissionGrants(ctx, id, flags) {
|
|
|
127684
129167
|
"Do not record secret values here.",
|
|
127685
129168
|
""
|
|
127686
129169
|
].filter((line) => line !== void 0).join("\n");
|
|
127687
|
-
await
|
|
127688
|
-
await
|
|
129170
|
+
await mkdir6(path13.dirname(grantedPath), { recursive: true });
|
|
129171
|
+
await writeFile7(grantedPath, body, "utf8");
|
|
127689
129172
|
return { filePath: grantedPath, grants };
|
|
127690
129173
|
}
|
|
127691
129174
|
async function editChatsInteractive(config, ctx) {
|
|
@@ -128036,13 +129519,14 @@ __export(bridgeControl_exports, {
|
|
|
128036
129519
|
});
|
|
128037
129520
|
import { spawn as spawn2, execFile as execFile6 } from "node:child_process";
|
|
128038
129521
|
import { openSync, constants as fsConstants } from "node:fs";
|
|
128039
|
-
import { readFile as
|
|
129522
|
+
import { readFile as readFile10, writeFile as writeFile8, unlink as unlink5, mkdir as mkdir7, readdir as readdir5, access as access7 } from "node:fs/promises";
|
|
128040
129523
|
import { promisify as promisify6 } from "node:util";
|
|
128041
129524
|
import path15 from "node:path";
|
|
128042
129525
|
import process3 from "node:process";
|
|
128043
129526
|
import { stat as stat3 } from "node:fs/promises";
|
|
128044
129527
|
|
|
128045
129528
|
// src/bridge/statusFile.ts
|
|
129529
|
+
init_paths();
|
|
128046
129530
|
import fs2 from "node:fs/promises";
|
|
128047
129531
|
import path14 from "node:path";
|
|
128048
129532
|
var DEFAULT_STALE_MS = 9e4;
|
|
@@ -128113,7 +129597,7 @@ async function resolveDistMain() {
|
|
|
128113
129597
|
async function readPid(larkwayDir) {
|
|
128114
129598
|
const pidFile = bridgePidPath(larkwayDir);
|
|
128115
129599
|
try {
|
|
128116
|
-
const raw = (await
|
|
129600
|
+
const raw = (await readFile10(pidFile, "utf-8")).trim();
|
|
128117
129601
|
const n = Number(raw);
|
|
128118
129602
|
return Number.isInteger(n) && n > 0 ? n : null;
|
|
128119
129603
|
} catch (e) {
|
|
@@ -128123,8 +129607,8 @@ async function readPid(larkwayDir) {
|
|
|
128123
129607
|
}
|
|
128124
129608
|
async function writePid(larkwayDir, pid) {
|
|
128125
129609
|
const pidFile = bridgePidPath(larkwayDir);
|
|
128126
|
-
await
|
|
128127
|
-
await
|
|
129610
|
+
await mkdir7(path15.dirname(pidFile), { recursive: true });
|
|
129611
|
+
await writeFile8(pidFile, String(pid) + "\n", "utf-8");
|
|
128128
129612
|
}
|
|
128129
129613
|
async function removePid(larkwayDir) {
|
|
128130
129614
|
const pidFile = bridgePidPath(larkwayDir);
|
|
@@ -128184,7 +129668,7 @@ async function listMainBridgePids(mainProcessPattern) {
|
|
|
128184
129668
|
async function hasAnyFreshStatusJson(larkwayDir, nowMs, staleMs = DEFAULT_STALE_MS) {
|
|
128185
129669
|
const checkFile2 = async (file) => {
|
|
128186
129670
|
try {
|
|
128187
|
-
const raw = await
|
|
129671
|
+
const raw = await readFile10(file, "utf-8");
|
|
128188
129672
|
const parsed = JSON.parse(raw);
|
|
128189
129673
|
if (typeof parsed["updatedAt"] !== "string") return { fresh: false, pid: null };
|
|
128190
129674
|
const updatedMs = Date.parse(parsed["updatedAt"]);
|
|
@@ -128271,7 +129755,7 @@ async function startBridge(larkwayDir, opts) {
|
|
|
128271
129755
|
await stopBridge(larkwayDir, opts);
|
|
128272
129756
|
}
|
|
128273
129757
|
const logPath = bridgeLogPath(larkwayDir);
|
|
128274
|
-
await
|
|
129758
|
+
await mkdir7(path15.dirname(logPath), { recursive: true });
|
|
128275
129759
|
let supervisorExists = false;
|
|
128276
129760
|
try {
|
|
128277
129761
|
await access7(supervisorScript);
|
|
@@ -128382,7 +129866,7 @@ async function tailBridgeLog(larkwayDir, n = 80) {
|
|
|
128382
129866
|
await fh.close();
|
|
128383
129867
|
}
|
|
128384
129868
|
} else {
|
|
128385
|
-
content = await
|
|
129869
|
+
content = await readFile10(logPath, "utf-8");
|
|
128386
129870
|
}
|
|
128387
129871
|
} catch (e) {
|
|
128388
129872
|
if (e.code === "ENOENT") {
|
|
@@ -128645,7 +130129,7 @@ async function run6(ctx, args) {
|
|
|
128645
130129
|
|
|
128646
130130
|
// src/cli/commands/update.ts
|
|
128647
130131
|
import { spawn as spawn4 } from "node:child_process";
|
|
128648
|
-
import { readFile as
|
|
130132
|
+
import { readFile as readFile11, access as access9 } from "node:fs/promises";
|
|
128649
130133
|
import "node:module";
|
|
128650
130134
|
import path17 from "node:path";
|
|
128651
130135
|
var DEFAULT_NPM_PACKAGE_SPEC = "larkway@latest";
|
|
@@ -128724,7 +130208,7 @@ async function findRepoRoot(startDir) {
|
|
|
128724
130208
|
const pkgPath = path17.join(dir, "package.json");
|
|
128725
130209
|
try {
|
|
128726
130210
|
await access9(pkgPath);
|
|
128727
|
-
const raw = await
|
|
130211
|
+
const raw = await readFile11(pkgPath, "utf-8");
|
|
128728
130212
|
const pkg = JSON.parse(raw);
|
|
128729
130213
|
if (pkg.name === "larkway") return dir;
|
|
128730
130214
|
} catch {
|
|
@@ -128961,15 +130445,16 @@ async function run7(ctx, args) {
|
|
|
128961
130445
|
import http from "node:http";
|
|
128962
130446
|
import { randomBytes } from "node:crypto";
|
|
128963
130447
|
import { existsSync } from "node:fs";
|
|
128964
|
-
import { readFile as
|
|
130448
|
+
import { readFile as readFile14, stat as stat5 } from "node:fs/promises";
|
|
128965
130449
|
import path22 from "node:path";
|
|
128966
130450
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
128967
130451
|
|
|
128968
130452
|
// src/web/api.ts
|
|
128969
|
-
import { readdir as readdir6, readFile as
|
|
130453
|
+
import { readdir as readdir6, readFile as readFile13, stat as stat4 } from "node:fs/promises";
|
|
128970
130454
|
import { execFile as execFileCallback2 } from "node:child_process";
|
|
128971
130455
|
import path21 from "node:path";
|
|
128972
130456
|
import { promisify as promisify8 } from "node:util";
|
|
130457
|
+
init_paths();
|
|
128973
130458
|
|
|
128974
130459
|
// src/version.ts
|
|
128975
130460
|
import { readFileSync } from "node:fs";
|
|
@@ -129036,8 +130521,9 @@ function isRuntimeEventRecord(value) {
|
|
|
129036
130521
|
// src/web/onboardSession.ts
|
|
129037
130522
|
var QRCode = __toESM(require_lib3(), 1);
|
|
129038
130523
|
import { randomUUID } from "node:crypto";
|
|
129039
|
-
import { mkdir as
|
|
130524
|
+
import { mkdir as mkdir8, writeFile as writeFile9, rename as rename5, chmod as chmod2, readFile as readFile12 } from "node:fs/promises";
|
|
129040
130525
|
import path20 from "node:path";
|
|
130526
|
+
init_paths();
|
|
129041
130527
|
async function defaultRegisterApp(opts) {
|
|
129042
130528
|
const sdk = await Promise.resolve().then(() => __toESM(require_lib2(), 1));
|
|
129043
130529
|
return sdk.registerApp(opts);
|
|
@@ -129069,10 +130555,10 @@ function quoteIfNeeded2(v) {
|
|
|
129069
130555
|
return /[\s#"'=]/.test(v) ? `"${v.replace(/"/g, '\\"')}"` : v;
|
|
129070
130556
|
}
|
|
129071
130557
|
async function atomicWrite3(file, content) {
|
|
129072
|
-
await
|
|
130558
|
+
await mkdir8(path20.dirname(file), { recursive: true });
|
|
129073
130559
|
const tmp = `${file}.${process.pid}.${Date.now()}.tmp`;
|
|
129074
|
-
await
|
|
129075
|
-
await
|
|
130560
|
+
await writeFile9(tmp, content, "utf-8");
|
|
130561
|
+
await rename5(tmp, file);
|
|
129076
130562
|
}
|
|
129077
130563
|
async function writeSecretTo(envPath, envName, value) {
|
|
129078
130564
|
if (!ENV_NAME_RE.test(envName)) {
|
|
@@ -129080,7 +130566,7 @@ async function writeSecretTo(envPath, envName, value) {
|
|
|
129080
130566
|
}
|
|
129081
130567
|
const map2 = /* @__PURE__ */ new Map();
|
|
129082
130568
|
try {
|
|
129083
|
-
const raw = await
|
|
130569
|
+
const raw = await readFile12(envPath, "utf-8");
|
|
129084
130570
|
for (const line of raw.split("\n")) {
|
|
129085
130571
|
const m = ENV_LINE_RE.exec(line.trim());
|
|
129086
130572
|
if (m) map2.set(m[1], stripQuotes2(m[2]));
|
|
@@ -129095,7 +130581,7 @@ async function writeSecretTo(envPath, envName, value) {
|
|
|
129095
130581
|
}
|
|
129096
130582
|
async function botYamlExists(botsDir, id) {
|
|
129097
130583
|
try {
|
|
129098
|
-
await
|
|
130584
|
+
await readFile12(path20.join(botsDir, `${id}.yaml`), "utf-8");
|
|
129099
130585
|
return true;
|
|
129100
130586
|
} catch {
|
|
129101
130587
|
return false;
|
|
@@ -129524,7 +131010,7 @@ async function readBotFromDir(dir, id) {
|
|
|
129524
131010
|
const memFile = path21.join(dir, `${id}.memory.md`);
|
|
129525
131011
|
let raw;
|
|
129526
131012
|
try {
|
|
129527
|
-
raw = await
|
|
131013
|
+
raw = await readFile13(yamlFile, "utf-8");
|
|
129528
131014
|
} catch (e) {
|
|
129529
131015
|
if (e.code === "ENOENT") {
|
|
129530
131016
|
throw new Error(`Bot "${id}" not found`);
|
|
@@ -129539,7 +131025,7 @@ async function readBotFromDir(dir, id) {
|
|
|
129539
131025
|
}
|
|
129540
131026
|
let memory = null;
|
|
129541
131027
|
try {
|
|
129542
|
-
memory = await
|
|
131028
|
+
memory = await readFile13(memFile, "utf-8");
|
|
129543
131029
|
} catch {
|
|
129544
131030
|
}
|
|
129545
131031
|
return { config, memory };
|
|
@@ -129764,6 +131250,13 @@ var putBot = async (req) => {
|
|
|
129764
131250
|
for (const k of ["name", "description", "chats", "repos", "turn_taking_limit", "backend"]) {
|
|
129765
131251
|
if (k in bodyWithoutTokenFields) merged[k] = bodyWithoutTokenFields[k];
|
|
129766
131252
|
}
|
|
131253
|
+
for (const k of ["model", "effort"]) {
|
|
131254
|
+
if (k in bodyWithoutTokenFields) {
|
|
131255
|
+
const v = bodyWithoutTokenFields[k];
|
|
131256
|
+
if (typeof v === "string" && v.trim().length > 0) merged[k] = v.trim();
|
|
131257
|
+
else delete merged[k];
|
|
131258
|
+
}
|
|
131259
|
+
}
|
|
129767
131260
|
if (tokenValue !== void 0) {
|
|
129768
131261
|
if (tokenValue.trim().length > 0) {
|
|
129769
131262
|
const envName = gitlabTokenEnvNameForBot(id);
|
|
@@ -129786,6 +131279,10 @@ var putBot = async (req) => {
|
|
|
129786
131279
|
backend: "codex",
|
|
129787
131280
|
...bodyWithoutTokenFields
|
|
129788
131281
|
};
|
|
131282
|
+
for (const k of ["model", "effort"]) {
|
|
131283
|
+
const v = draft[k];
|
|
131284
|
+
if (typeof v === "string" && v.trim().length === 0) delete draft[k];
|
|
131285
|
+
}
|
|
129789
131286
|
if (tokenValue !== void 0) {
|
|
129790
131287
|
if (tokenValue.trim().length > 0) {
|
|
129791
131288
|
const envName = gitlabTokenEnvNameForBot(id);
|
|
@@ -130418,7 +131915,7 @@ async function handleStatic(res, pathname, token) {
|
|
|
130418
131915
|
}
|
|
130419
131916
|
let buf;
|
|
130420
131917
|
try {
|
|
130421
|
-
buf = await
|
|
131918
|
+
buf = await readFile14(target);
|
|
130422
131919
|
} catch {
|
|
130423
131920
|
writeText(res, 404, "not found");
|
|
130424
131921
|
return;
|
|
@@ -130531,7 +132028,8 @@ async function run8(ctx, args) {
|
|
|
130531
132028
|
}
|
|
130532
132029
|
|
|
130533
132030
|
// src/cli/commands/dogfood.ts
|
|
130534
|
-
|
|
132031
|
+
init_paths();
|
|
132032
|
+
import { access as access10, readFile as readFile15, readdir as readdir7 } from "node:fs/promises";
|
|
130535
132033
|
import path24 from "node:path";
|
|
130536
132034
|
|
|
130537
132035
|
// src/agent/permissionGate.ts
|
|
@@ -131113,7 +132611,7 @@ async function listMarkdownFiles(root) {
|
|
|
131113
132611
|
}
|
|
131114
132612
|
async function readTextOrNull(filePath) {
|
|
131115
132613
|
try {
|
|
131116
|
-
return await
|
|
132614
|
+
return await readFile15(filePath, "utf8");
|
|
131117
132615
|
} catch {
|
|
131118
132616
|
return null;
|
|
131119
132617
|
}
|
|
@@ -131124,6 +132622,563 @@ function exitCodeFor(checks) {
|
|
|
131124
132622
|
return 0;
|
|
131125
132623
|
}
|
|
131126
132624
|
|
|
132625
|
+
// src/cli/commands/tasklistInit.ts
|
|
132626
|
+
var import_node_sdk2 = __toESM(require_lib2(), 1);
|
|
132627
|
+
init_client();
|
|
132628
|
+
init_paths();
|
|
132629
|
+
init_teamRegistry();
|
|
132630
|
+
|
|
132631
|
+
// src/cli/ownerIdentity.ts
|
|
132632
|
+
import { spawnSync } from "node:child_process";
|
|
132633
|
+
function resolveOwnerOpenId(profile, _spawnSync = spawnSync) {
|
|
132634
|
+
try {
|
|
132635
|
+
const result = _spawnSync("lark-cli", ["auth", "status", "--profile", profile, "--json"], {
|
|
132636
|
+
encoding: "utf-8",
|
|
132637
|
+
timeout: 1e4
|
|
132638
|
+
});
|
|
132639
|
+
if (result.status !== 0) return void 0;
|
|
132640
|
+
const stdout2 = typeof result.stdout === "string" ? result.stdout : "";
|
|
132641
|
+
if (stdout2.trim().length === 0) return void 0;
|
|
132642
|
+
const parsed = JSON.parse(stdout2);
|
|
132643
|
+
if (typeof parsed !== "object" || parsed === null) return void 0;
|
|
132644
|
+
const identities = parsed["identities"];
|
|
132645
|
+
if (typeof identities !== "object" || identities === null) return void 0;
|
|
132646
|
+
const user = identities["user"];
|
|
132647
|
+
if (typeof user !== "object" || user === null) return void 0;
|
|
132648
|
+
const openId = user["openId"];
|
|
132649
|
+
return typeof openId === "string" && openId.length > 0 ? openId : void 0;
|
|
132650
|
+
} catch {
|
|
132651
|
+
return void 0;
|
|
132652
|
+
}
|
|
132653
|
+
}
|
|
132654
|
+
|
|
132655
|
+
// src/lark/profileBootstrap.ts
|
|
132656
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
132657
|
+
function deriveLarkCliProfile(explicitProfile, appId) {
|
|
132658
|
+
return explicitProfile ?? appId;
|
|
132659
|
+
}
|
|
132660
|
+
|
|
132661
|
+
// src/cli/userTasklistOps.ts
|
|
132662
|
+
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
132663
|
+
var SPAWN_TIMEOUT_MS = 15e3;
|
|
132664
|
+
function runLarkCliJson(args, spawnSyncFn) {
|
|
132665
|
+
let result;
|
|
132666
|
+
try {
|
|
132667
|
+
result = spawnSyncFn("lark-cli", args, { encoding: "utf-8", timeout: SPAWN_TIMEOUT_MS });
|
|
132668
|
+
} catch (err2) {
|
|
132669
|
+
return {
|
|
132670
|
+
ok: false,
|
|
132671
|
+
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`
|
|
132672
|
+
};
|
|
132673
|
+
}
|
|
132674
|
+
const stdout2 = typeof result.stdout === "string" ? result.stdout : "";
|
|
132675
|
+
const stderr = typeof result.stderr === "string" ? result.stderr : "";
|
|
132676
|
+
if (stdout2.trim().length === 0) {
|
|
132677
|
+
return {
|
|
132678
|
+
ok: false,
|
|
132679
|
+
error: `lark-cli \u6CA1\u6709\u8F93\u51FA\u4EFB\u4F55\u5185\u5BB9(exit=${result.status ?? "unknown"})\u3002${stderr ? `stderr: ${stderr.slice(0, 500)}` : ""}`
|
|
132680
|
+
};
|
|
132681
|
+
}
|
|
132682
|
+
let parsed;
|
|
132683
|
+
try {
|
|
132684
|
+
parsed = JSON.parse(stdout2);
|
|
132685
|
+
} catch {
|
|
132686
|
+
return { ok: false, error: `lark-cli \u8F93\u51FA\u4E0D\u662F\u5408\u6CD5 JSON(exit=${result.status ?? "unknown"}): ${stdout2.slice(0, 500)}` };
|
|
132687
|
+
}
|
|
132688
|
+
if (typeof parsed === "object" && parsed !== null && parsed["ok"] === false) {
|
|
132689
|
+
const errObj = parsed["error"];
|
|
132690
|
+
const rec = typeof errObj === "object" && errObj !== null ? errObj : {};
|
|
132691
|
+
const message = typeof rec["message"] === "string" ? rec["message"] : "\u672A\u77E5\u9519\u8BEF";
|
|
132692
|
+
const hint = typeof rec["hint"] === "string" && rec["hint"] ? `
|
|
132693
|
+
\u63D0\u793A:${rec["hint"]}` : "";
|
|
132694
|
+
return { ok: false, error: `${message}${hint}` };
|
|
132695
|
+
}
|
|
132696
|
+
return { ok: true, data: parsed };
|
|
132697
|
+
}
|
|
132698
|
+
function listUserTasklists(profile, spawnSyncFn = spawnSync3) {
|
|
132699
|
+
const result = runLarkCliJson(
|
|
132700
|
+
["task", "tasklists", "list", "--as", "user", "--profile", profile, "--page-all", "--json"],
|
|
132701
|
+
spawnSyncFn
|
|
132702
|
+
);
|
|
132703
|
+
if (!result.ok) return result;
|
|
132704
|
+
const data = result.data;
|
|
132705
|
+
const items = typeof data === "object" && data !== null ? data["items"] : void 0;
|
|
132706
|
+
if (!Array.isArray(items)) {
|
|
132707
|
+
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)}` };
|
|
132708
|
+
}
|
|
132709
|
+
const tasklists = [];
|
|
132710
|
+
for (const raw of items) {
|
|
132711
|
+
if (typeof raw !== "object" || raw === null) continue;
|
|
132712
|
+
const guid = raw["guid"];
|
|
132713
|
+
const name = raw["name"];
|
|
132714
|
+
if (typeof guid === "string" && guid.length > 0) {
|
|
132715
|
+
tasklists.push({ guid, name: typeof name === "string" ? name : "(\u65E0\u6807\u9898)" });
|
|
132716
|
+
}
|
|
132717
|
+
}
|
|
132718
|
+
return { ok: true, data: tasklists };
|
|
132719
|
+
}
|
|
132720
|
+
function addTasklistMembersAsUser(profile, tasklistGuid, members, spawnSyncFn = spawnSync3) {
|
|
132721
|
+
const dataJson = JSON.stringify({ members });
|
|
132722
|
+
return runLarkCliJson(
|
|
132723
|
+
[
|
|
132724
|
+
"task",
|
|
132725
|
+
"tasklists",
|
|
132726
|
+
"add_members",
|
|
132727
|
+
"--as",
|
|
132728
|
+
"user",
|
|
132729
|
+
"--profile",
|
|
132730
|
+
profile,
|
|
132731
|
+
"--tasklist-guid",
|
|
132732
|
+
tasklistGuid,
|
|
132733
|
+
"--data",
|
|
132734
|
+
dataJson,
|
|
132735
|
+
"--json"
|
|
132736
|
+
],
|
|
132737
|
+
spawnSyncFn
|
|
132738
|
+
);
|
|
132739
|
+
}
|
|
132740
|
+
function getUserTasklistMembers(profile, tasklistGuid, spawnSyncFn = spawnSync3) {
|
|
132741
|
+
const result = runLarkCliJson(
|
|
132742
|
+
["task", "tasklists", "get", "--as", "user", "--profile", profile, "--tasklist-guid", tasklistGuid, "--json"],
|
|
132743
|
+
spawnSyncFn
|
|
132744
|
+
);
|
|
132745
|
+
if (!result.ok) return result;
|
|
132746
|
+
const data = result.data;
|
|
132747
|
+
const tasklist = typeof data === "object" && data !== null ? data["tasklist"] : void 0;
|
|
132748
|
+
const members = typeof tasklist === "object" && tasklist !== null ? tasklist["members"] : void 0;
|
|
132749
|
+
if (!Array.isArray(members)) {
|
|
132750
|
+
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)}` };
|
|
132751
|
+
}
|
|
132752
|
+
return {
|
|
132753
|
+
ok: true,
|
|
132754
|
+
data: members.filter((m) => typeof m === "object" && m !== null).map((m) => ({
|
|
132755
|
+
id: String(m["id"] ?? ""),
|
|
132756
|
+
type: typeof m["type"] === "string" ? m["type"] : void 0,
|
|
132757
|
+
role: typeof m["role"] === "string" ? m["role"] : void 0
|
|
132758
|
+
}))
|
|
132759
|
+
};
|
|
132760
|
+
}
|
|
132761
|
+
|
|
132762
|
+
// src/cli/commands/tasklistInit.ts
|
|
132763
|
+
function parseArgs2(args) {
|
|
132764
|
+
let team = [];
|
|
132765
|
+
let name = "Agent Team";
|
|
132766
|
+
let owner;
|
|
132767
|
+
let force = false;
|
|
132768
|
+
let adopt;
|
|
132769
|
+
let adoptGuid;
|
|
132770
|
+
for (let i = 0; i < args.length; i++) {
|
|
132771
|
+
const arg = args[i];
|
|
132772
|
+
if (arg === "--team" && i + 1 < args.length) {
|
|
132773
|
+
team = args[++i].split(",").map((s) => s.trim()).filter(Boolean);
|
|
132774
|
+
} else if (arg.startsWith("--team=")) {
|
|
132775
|
+
team = arg.slice("--team=".length).split(",").map((s) => s.trim()).filter(Boolean);
|
|
132776
|
+
} else if (arg === "--name" && i + 1 < args.length) {
|
|
132777
|
+
name = args[++i];
|
|
132778
|
+
} else if (arg.startsWith("--name=")) {
|
|
132779
|
+
name = arg.slice("--name=".length);
|
|
132780
|
+
} else if (arg === "--owner" && i + 1 < args.length) {
|
|
132781
|
+
owner = args[++i];
|
|
132782
|
+
} else if (arg.startsWith("--owner=")) {
|
|
132783
|
+
owner = arg.slice("--owner=".length);
|
|
132784
|
+
} else if (arg === "--force") {
|
|
132785
|
+
force = true;
|
|
132786
|
+
} else if (arg === "--adopt" && i + 1 < args.length) {
|
|
132787
|
+
adopt = args[++i];
|
|
132788
|
+
} else if (arg.startsWith("--adopt=")) {
|
|
132789
|
+
adopt = arg.slice("--adopt=".length);
|
|
132790
|
+
} else if (arg === "--adopt-guid" && i + 1 < args.length) {
|
|
132791
|
+
adoptGuid = args[++i];
|
|
132792
|
+
} else if (arg.startsWith("--adopt-guid=")) {
|
|
132793
|
+
adoptGuid = arg.slice("--adopt-guid=".length);
|
|
132794
|
+
}
|
|
132795
|
+
}
|
|
132796
|
+
return { team, name, owner, force, adopt, adoptGuid };
|
|
132797
|
+
}
|
|
132798
|
+
var USAGE2 = `larkway tasklist-init [--team <bot1,bot2,\u2026>] [--name <\u6E05\u5355\u540D>] [--owner <open_id>] [--force]
|
|
132799
|
+
[--adopt "<\u6E05\u5355\u540D>" | --adopt-guid <guid>]
|
|
132800
|
+
|
|
132801
|
+
\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
|
|
132802
|
+
\u5E2E\u52A9\u7684 agent,\u7B2C\u4E00\u6B65\u5FC5\u7136\u4F1A\u8DD1 \`larkway tasklist-init --help\`(\u5C31\u662F\u4F60\u6B63\u5728\u770B\u7684\u8FD9\u6BB5),
|
|
132803
|
+
\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
|
|
132804
|
+
|
|
132805
|
+
\u96F6\u53C2\u6570\u4E09\u6B65 Quickstart:
|
|
132806
|
+
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
|
|
132807
|
+
2. \u8DD1:larkway tasklist-init
|
|
132808
|
+
\u2014\u2014 \u4F1A\u81EA\u52A8:--team = \u672C\u673A bots/ \u76EE\u5F55\u4E0B\u5168\u90E8\u5DF2\u914D\u7F6E bot;--name = "Agent Team";
|
|
132809
|
+
\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
|
|
132810
|
+
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
|
|
132811
|
+
bot \u7684 app \u8EAB\u4EFD\u65B0\u5EFA\u4E00\u4E2A\u6E05\u5355,\u5E76\u81EA\u52A8\u628A\u4F60\u52A0\u4E3A owner)\u3002
|
|
132812
|
+
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
|
|
132813
|
+
|
|
132814
|
+
\u4EE5\u4E0A\u5168\u90E8\u662F\u7F3A\u7701\u884C\u4E3A,\u4EE5\u4E0B flag \u4EC5\u7528\u4E8E\u8986\u76D6:
|
|
132815
|
+
|
|
132816
|
+
--team <bot1,bot2,\u2026> \u663E\u5F0F\u6307\u5B9A\u8981\u52A0\u5165\u6E05\u5355\u7684 bot(\u9ED8\u8BA4 = \u5168\u90E8\u5DF2\u914D\u7F6E bot)
|
|
132817
|
+
--name <\u6E05\u5355\u540D> \u663E\u5F0F\u6307\u5B9A\u6E05\u5355\u540D(\u9ED8\u8BA4 "Agent Team"),\u4EC5\u5728\u81EA\u52A8/\u663E\u5F0F create
|
|
132818
|
+
\u8DEF\u5F84\u91CC\u751F\u6548;--adopt/--adopt-guid \u4F1A\u5FFD\u7565\u5B83,\u6309\u540D\u5B57/guid \u67E5
|
|
132819
|
+
--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
|
|
132820
|
+
\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)
|
|
132821
|
+
--adopt-guid <guid> \u8DF3\u8FC7\u6309\u540D\u5B57\u67E5\u627E,\u76F4\u63A5 adopt \u8FD9\u4E2A guid \u7684\u6E05\u5355(\u5355\u72EC\u4F7F\u7528\u4E5F
|
|
132822
|
+
\u7B49\u4EF7\u4E8E\u5F3A\u5236 adopt \u6A21\u5F0F);\u591A\u4E2A\u540C\u540D\u6E05\u5355\u65F6\u7528\u5B83\u6D88\u6B67
|
|
132823
|
+
--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
|
|
132824
|
+
owner,\u4E0D\u9700\u8981\u8FD9\u4E2A)
|
|
132825
|
+
--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
|
|
132826
|
+
\u6574\u4E2A\u56E2\u961F\u5207\u5230\u4E00\u4E2A\u65B0\u677F)
|
|
132827
|
+
|
|
132828
|
+
\u2500\u2500 adopt \u6A21\u5F0F\u5185\u90E8\u6B65\u9AA4(\u81EA\u52A8\u9009\u4E2D,\u6216\u663E\u5F0F --adopt/--adopt-guid \u89E6\u53D1)\u2500\u2500
|
|
132829
|
+
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
|
|
132830
|
+
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
|
|
132831
|
+
\u521B\u5EFA\u8DEF\u5F84,\u663E\u5F0F --adopt \u4E0B\u62A5\u9519\u63D0\u793A\u5148\u53BB\u4EFB\u52A1\u4E2D\u5FC3\u5EFA\u4E00\u4E2A)
|
|
132832
|
+
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)
|
|
132833
|
+
3. \u5199\u5165\u5171\u4EAB\u6CE8\u518C\u6587\u4EF6 <LARKWAY_HOME>/task-team.json(\u4E0E\u521B\u5EFA\u8DEF\u5F84\u540C\u4E00\u5957
|
|
132834
|
+
first-writer-wins / --force \u8986\u76D6\u8BED\u4E49)
|
|
132835
|
+
4. \u8BFB\u56DE\u6210\u5458\u5217\u8868,\u6838\u5B9E\u6BCF\u4E2A bot \u771F\u7684\u52A0\u5165\u6210\u529F
|
|
132836
|
+
|
|
132837
|
+
\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
|
|
132838
|
+
\u7533\u8BF7\u4E86 task \u57DF\u6743\u9650:
|
|
132839
|
+
lark-cli auth login --profile <profile> --domain task
|
|
132840
|
+
(\u7528\u54EA\u4E2A profile:\u7B2C\u4E00\u4E2A\u56E2\u961F bot \u7684 lark_cli_profile,\u7F3A\u7701\u65F6\u7528\u5B83\u7684 app_id)\u3002
|
|
132841
|
+
\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
|
|
132842
|
+
|
|
132843
|
+
\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
|
|
132844
|
+
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
|
|
132845
|
+
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
|
|
132846
|
+
3. \u628A\u6BCF\u4E2A bot \u7684 app \u90FD\u52A0\u4E3A\u6E05\u5355\u6210\u5458(role=editor)
|
|
132847
|
+
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)
|
|
132848
|
+
5. (\u4EC5\u65B0\u5EFA\u65F6)\u628A guid \u5199\u8FDB\u5171\u4EAB\u6CE8\u518C\u6587\u4EF6
|
|
132849
|
+
|
|
132850
|
+
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
|
|
132851
|
+
\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\`);
|
|
132852
|
+
\u4E24\u8005\u90FD\u62FF\u4E0D\u5230\u4F1A\u76F4\u63A5\u62A5\u9519\u9000\u51FA,\u4E0D\u5EFA/\u4E0D\u52A8\u4EFB\u4F55\u6E05\u5355\u3002
|
|
132853
|
+
|
|
132854
|
+
\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
|
|
132855
|
+
\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
|
|
132856
|
+
|
|
132857
|
+
\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
|
|
132858
|
+
\u4EA4\u4E92\u5F0F\u95EE\u9898(\u8FD9\u4E2A\u547D\u4EE4\u672C\u6765\u5C31\u8BBE\u8BA1\u7ED9 agent \u5728 headless \u73AF\u5883\u91CC\u8DD1)\u3002
|
|
132859
|
+
|
|
132860
|
+
\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
|
|
132861
|
+
\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
|
|
132862
|
+
|
|
132863
|
+
\u793A\u4F8B:
|
|
132864
|
+
larkway tasklist-init
|
|
132865
|
+
larkway tasklist-init --adopt "Agent Team"
|
|
132866
|
+
larkway tasklist-init --adopt "Agent Team" --adopt-guid abc-123-guid
|
|
132867
|
+
larkway tasklist-init --team larkway-devops,larkway-marketing --name "Agent Team"
|
|
132868
|
+
larkway tasklist-init --team larkway-devops --owner ou_1234567890abcdef
|
|
132869
|
+
larkway tasklist-init --team larkway-devops --force`;
|
|
132870
|
+
async function run10(ctx, args) {
|
|
132871
|
+
if (args.includes("help")) {
|
|
132872
|
+
ctx.ui.print(USAGE2);
|
|
132873
|
+
return 0;
|
|
132874
|
+
}
|
|
132875
|
+
const { team, name, owner: explicitOwner, force, adopt, adoptGuid: explicitAdoptGuid } = parseArgs2(args);
|
|
132876
|
+
let team_ = team;
|
|
132877
|
+
if (team_.length === 0) {
|
|
132878
|
+
team_ = await ctx.botsStore.listBots();
|
|
132879
|
+
if (team_.length === 0) {
|
|
132880
|
+
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";
|
|
132881
|
+
if (ctx.flags.json) ctx.ui.emitJson({ ok: false, error: msg });
|
|
132882
|
+
else {
|
|
132883
|
+
ctx.ui.failure(msg);
|
|
132884
|
+
ctx.ui.print(USAGE2);
|
|
132885
|
+
}
|
|
132886
|
+
return 1;
|
|
132887
|
+
}
|
|
132888
|
+
}
|
|
132889
|
+
const bots = [];
|
|
132890
|
+
for (const botId of team_) {
|
|
132891
|
+
let bot;
|
|
132892
|
+
try {
|
|
132893
|
+
bot = await ctx.botsStore.readBot(botId);
|
|
132894
|
+
} catch (err2) {
|
|
132895
|
+
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
132896
|
+
if (ctx.flags.json) ctx.ui.emitJson({ ok: false, error: msg });
|
|
132897
|
+
else ctx.ui.failure(msg);
|
|
132898
|
+
return 1;
|
|
132899
|
+
}
|
|
132900
|
+
const appSecret = await ctx.hostConfig.readSecret(bot.app_secret_env);
|
|
132901
|
+
if (!appSecret) {
|
|
132902
|
+
const msg = `Bot "${botId}" \u7684 app_secret_env "${bot.app_secret_env}" \u5728 ~/.larkway/.env \u4E2D\u672A\u8BBE\u7F6E\u3002`;
|
|
132903
|
+
if (ctx.flags.json) ctx.ui.emitJson({ ok: false, error: msg });
|
|
132904
|
+
else ctx.ui.failure(msg);
|
|
132905
|
+
return 1;
|
|
132906
|
+
}
|
|
132907
|
+
bots.push({ id: bot.id, app_id: bot.app_id, appSecret, lark_cli_profile: bot.lark_cli_profile });
|
|
132908
|
+
}
|
|
132909
|
+
const creator = bots[0];
|
|
132910
|
+
const creatorProfile = deriveLarkCliProfile(creator.lark_cli_profile, creator.app_id);
|
|
132911
|
+
const loginHint = `lark-cli auth login --profile ${creatorProfile} --domain task`;
|
|
132912
|
+
if (adopt !== void 0 || explicitAdoptGuid !== void 0) {
|
|
132913
|
+
const adoptName = adopt ?? name;
|
|
132914
|
+
if (adoptName.trim().length === 0) {
|
|
132915
|
+
const msg = '--adopt \u9700\u8981\u4E00\u4E2A\u975E\u7A7A\u7684\u6E05\u5355\u540D\u5B57,\u4F8B\u5982 --adopt "Agent Team"\u3002';
|
|
132916
|
+
if (ctx.flags.json) ctx.ui.emitJson({ ok: false, error: msg });
|
|
132917
|
+
else {
|
|
132918
|
+
ctx.ui.failure(msg);
|
|
132919
|
+
ctx.ui.print(USAGE2);
|
|
132920
|
+
}
|
|
132921
|
+
return 1;
|
|
132922
|
+
}
|
|
132923
|
+
const target = resolveAdoptTarget(creatorProfile, adoptName, explicitAdoptGuid, loginHint);
|
|
132924
|
+
if (!target.ok) {
|
|
132925
|
+
if (ctx.flags.json) ctx.ui.emitJson({ ok: false, error: target.message });
|
|
132926
|
+
else {
|
|
132927
|
+
ctx.ui.failure(target.message);
|
|
132928
|
+
if (target.reason === "list-failed") ctx.ui.print(USAGE2);
|
|
132929
|
+
}
|
|
132930
|
+
return 1;
|
|
132931
|
+
}
|
|
132932
|
+
return runAdoptWithGuid(ctx, {
|
|
132933
|
+
guid: target.guid,
|
|
132934
|
+
matchedName: target.matchedName,
|
|
132935
|
+
bots,
|
|
132936
|
+
force,
|
|
132937
|
+
creatorProfile,
|
|
132938
|
+
loginHint
|
|
132939
|
+
});
|
|
132940
|
+
}
|
|
132941
|
+
const autoTarget = resolveAdoptTarget(creatorProfile, name, void 0, loginHint);
|
|
132942
|
+
if (autoTarget.ok) {
|
|
132943
|
+
return runAdoptWithGuid(ctx, {
|
|
132944
|
+
guid: autoTarget.guid,
|
|
132945
|
+
matchedName: autoTarget.matchedName,
|
|
132946
|
+
bots,
|
|
132947
|
+
force,
|
|
132948
|
+
creatorProfile,
|
|
132949
|
+
loginHint
|
|
132950
|
+
});
|
|
132951
|
+
}
|
|
132952
|
+
if (autoTarget.reason === "ambiguous") {
|
|
132953
|
+
if (ctx.flags.json) ctx.ui.emitJson({ ok: false, error: autoTarget.message });
|
|
132954
|
+
else ctx.ui.failure(autoTarget.message);
|
|
132955
|
+
return 1;
|
|
132956
|
+
}
|
|
132957
|
+
if (!ctx.flags.json) {
|
|
132958
|
+
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}"`;
|
|
132959
|
+
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)`));
|
|
132960
|
+
}
|
|
132961
|
+
const ownerOpenId = explicitOwner ?? resolveOwnerOpenId(creatorProfile);
|
|
132962
|
+
if (!ownerOpenId) {
|
|
132963
|
+
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`;
|
|
132964
|
+
if (ctx.flags.json) ctx.ui.emitJson({ ok: false, error: msg });
|
|
132965
|
+
else {
|
|
132966
|
+
ctx.ui.failure(msg);
|
|
132967
|
+
ctx.ui.print(USAGE2);
|
|
132968
|
+
}
|
|
132969
|
+
return 1;
|
|
132970
|
+
}
|
|
132971
|
+
const sdkClient = new import_node_sdk2.Client({ appId: creator.app_id, appSecret: creator.appSecret });
|
|
132972
|
+
const requester = {
|
|
132973
|
+
request: (config) => sdkClient.request(config)
|
|
132974
|
+
};
|
|
132975
|
+
const taskClient = new TaskListClient(requester);
|
|
132976
|
+
const members = [
|
|
132977
|
+
{ id: ownerOpenId, type: "user", role: "editor" },
|
|
132978
|
+
...bots.map((b) => ({ id: b.app_id, type: "app", role: "editor" }))
|
|
132979
|
+
];
|
|
132980
|
+
const registryPath = resolveTaskTeamRegistryPath();
|
|
132981
|
+
const existingGuid = await readTeamTasklistGuid(registryPath);
|
|
132982
|
+
let tasklistGuid;
|
|
132983
|
+
let reused;
|
|
132984
|
+
if (existingGuid && !force) {
|
|
132985
|
+
tasklistGuid = existingGuid;
|
|
132986
|
+
reused = true;
|
|
132987
|
+
try {
|
|
132988
|
+
await taskClient.addTasklistMembers(tasklistGuid, members);
|
|
132989
|
+
} catch (err2) {
|
|
132990
|
+
const msg = `\u590D\u7528\u5DF2\u6709\u6E05\u5355 ${tasklistGuid} \u65F6\u8865\u5145\u6210\u5458\u5931\u8D25: ${err2 instanceof Error ? err2.message : String(err2)}`;
|
|
132991
|
+
if (ctx.flags.json) ctx.ui.emitJson({ ok: false, error: msg });
|
|
132992
|
+
else {
|
|
132993
|
+
ctx.ui.failure(msg);
|
|
132994
|
+
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");
|
|
132995
|
+
}
|
|
132996
|
+
return 1;
|
|
132997
|
+
}
|
|
132998
|
+
} else {
|
|
132999
|
+
reused = false;
|
|
133000
|
+
try {
|
|
133001
|
+
const created = await taskClient.createTasklist(name, members);
|
|
133002
|
+
tasklistGuid = created.guid;
|
|
133003
|
+
} catch (err2) {
|
|
133004
|
+
const msg = `\u5EFA\u6E05\u5355\u5931\u8D25: ${err2 instanceof Error ? err2.message : String(err2)}`;
|
|
133005
|
+
if (ctx.flags.json) ctx.ui.emitJson({ ok: false, error: msg });
|
|
133006
|
+
else {
|
|
133007
|
+
ctx.ui.failure(msg);
|
|
133008
|
+
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");
|
|
133009
|
+
}
|
|
133010
|
+
return 1;
|
|
133011
|
+
}
|
|
133012
|
+
if (force && existingGuid) {
|
|
133013
|
+
await overwriteTeamTasklistGuid(registryPath, tasklistGuid);
|
|
133014
|
+
} else {
|
|
133015
|
+
await claimTeamTasklistGuid(registryPath, tasklistGuid);
|
|
133016
|
+
}
|
|
133017
|
+
}
|
|
133018
|
+
let ownerConfirmedMember;
|
|
133019
|
+
let membershipCheckError;
|
|
133020
|
+
try {
|
|
133021
|
+
const snapshot = await taskClient.getTasklist(tasklistGuid);
|
|
133022
|
+
ownerConfirmedMember = snapshot?.members.some((m) => m.id === ownerOpenId) ?? void 0;
|
|
133023
|
+
} catch (err2) {
|
|
133024
|
+
membershipCheckError = err2 instanceof Error ? err2.message : String(err2);
|
|
133025
|
+
}
|
|
133026
|
+
if (ctx.flags.json) {
|
|
133027
|
+
ctx.ui.emitJson({
|
|
133028
|
+
ok: true,
|
|
133029
|
+
team: team_,
|
|
133030
|
+
name,
|
|
133031
|
+
ownerOpenId,
|
|
133032
|
+
tasklistGuid,
|
|
133033
|
+
reused,
|
|
133034
|
+
ownerConfirmedMember: ownerConfirmedMember ?? null,
|
|
133035
|
+
membershipCheckError: membershipCheckError ?? null
|
|
133036
|
+
});
|
|
133037
|
+
return 0;
|
|
133038
|
+
}
|
|
133039
|
+
if (ownerConfirmedMember === false) {
|
|
133040
|
+
ctx.ui.warning(
|
|
133041
|
+
`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`
|
|
133042
|
+
);
|
|
133043
|
+
} else if (membershipCheckError) {
|
|
133044
|
+
ctx.ui.warning(
|
|
133045
|
+
`\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}`
|
|
133046
|
+
);
|
|
133047
|
+
}
|
|
133048
|
+
if (reused) {
|
|
133049
|
+
ctx.ui.success(`\u590D\u7528\u5DF2\u6709\u6E05\u5355: ${tasklistGuid}`);
|
|
133050
|
+
} else {
|
|
133051
|
+
ctx.ui.success(`\u6E05\u5355 "${name}" \u5DF2\u521B\u5EFA: ${tasklistGuid}`);
|
|
133052
|
+
}
|
|
133053
|
+
ctx.ui.print(`owner \u6210\u5458: ${ownerOpenId}${explicitOwner ? "" : "(\u4ECE lark-cli \u5F53\u524D\u767B\u5F55\u7528\u6237\u81EA\u52A8\u89E3\u6790)"}`);
|
|
133054
|
+
ctx.ui.print(`\u5DF2\u52A0\u5165\u6210\u5458(editor): ${bots.map((b) => b.id).join(", ")}`);
|
|
133055
|
+
ctx.ui.print("");
|
|
133056
|
+
if (!reused) {
|
|
133057
|
+
ctx.ui.print(
|
|
133058
|
+
`\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`
|
|
133059
|
+
);
|
|
133060
|
+
ctx.ui.print("");
|
|
133061
|
+
}
|
|
133062
|
+
ctx.ui.print(
|
|
133063
|
+
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:"
|
|
133064
|
+
);
|
|
133065
|
+
ctx.ui.print(` taskHandle:`);
|
|
133066
|
+
ctx.ui.print(` tasklistGuid: "${tasklistGuid}"`);
|
|
133067
|
+
ctx.ui.print("");
|
|
133068
|
+
ctx.ui.print(
|
|
133069
|
+
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"
|
|
133070
|
+
);
|
|
133071
|
+
return 0;
|
|
133072
|
+
}
|
|
133073
|
+
function resolveAdoptTarget(creatorProfile, name, explicitGuid, loginHint) {
|
|
133074
|
+
if (explicitGuid) {
|
|
133075
|
+
return { ok: true, guid: explicitGuid, matchedName: name };
|
|
133076
|
+
}
|
|
133077
|
+
const listResult = listUserTasklists(creatorProfile);
|
|
133078
|
+
if (!listResult.ok) {
|
|
133079
|
+
return {
|
|
133080
|
+
ok: false,
|
|
133081
|
+
reason: "list-failed",
|
|
133082
|
+
message: `\u65E0\u6CD5\u4EE5\u4F60\u7684\u7528\u6237\u8EAB\u4EFD\u5217\u51FA\u6E05\u5355:${listResult.error}
|
|
133083
|
+
|
|
133084
|
+
\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:
|
|
133085
|
+
${loginHint}
|
|
133086
|
+
(\u53EF\u7528 \`lark-cli auth status --profile ${creatorProfile} --json\` \u68C0\u67E5\u5F53\u524D\u72B6\u6001)`
|
|
133087
|
+
};
|
|
133088
|
+
}
|
|
133089
|
+
const matches = listResult.data.filter((t) => t.name === name);
|
|
133090
|
+
if (matches.length === 0) {
|
|
133091
|
+
return {
|
|
133092
|
+
ok: false,
|
|
133093
|
+
reason: "not-found",
|
|
133094
|
+
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`
|
|
133095
|
+
};
|
|
133096
|
+
}
|
|
133097
|
+
if (matches.length > 1) {
|
|
133098
|
+
return {
|
|
133099
|
+
ok: false,
|
|
133100
|
+
reason: "ambiguous",
|
|
133101
|
+
message: `\u627E\u5230 ${matches.length} \u4E2A\u540C\u540D\u6E05\u5355 "${name}",\u65E0\u6CD5\u786E\u5B9A\u8981 adopt \u54EA\u4E00\u4E2A:
|
|
133102
|
+
` + 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",
|
|
133103
|
+
matches
|
|
133104
|
+
};
|
|
133105
|
+
}
|
|
133106
|
+
return { ok: true, guid: matches[0].guid, matchedName: matches[0].name };
|
|
133107
|
+
}
|
|
133108
|
+
async function runAdoptWithGuid(ctx, opts) {
|
|
133109
|
+
const { guid: tasklistGuid, matchedName, bots, force, creatorProfile, loginHint } = opts;
|
|
133110
|
+
const members = bots.map((b) => ({ id: b.app_id, type: "app", role: "editor" }));
|
|
133111
|
+
const addResult = addTasklistMembersAsUser(creatorProfile, tasklistGuid, members);
|
|
133112
|
+
if (!addResult.ok) {
|
|
133113
|
+
const msg = `\u628A bot app \u52A0\u4E3A\u6E05\u5355 ${tasklistGuid} \u7684 editor \u5931\u8D25:${addResult.error}
|
|
133114
|
+
|
|
133115
|
+
\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:
|
|
133116
|
+
${loginHint}`;
|
|
133117
|
+
if (ctx.flags.json) ctx.ui.emitJson({ ok: false, error: msg });
|
|
133118
|
+
else ctx.ui.failure(msg);
|
|
133119
|
+
return 1;
|
|
133120
|
+
}
|
|
133121
|
+
const registryPath = resolveTaskTeamRegistryPath();
|
|
133122
|
+
let registeredGuid;
|
|
133123
|
+
if (force) {
|
|
133124
|
+
await overwriteTeamTasklistGuid(registryPath, tasklistGuid);
|
|
133125
|
+
registeredGuid = tasklistGuid;
|
|
133126
|
+
} else {
|
|
133127
|
+
registeredGuid = await claimTeamTasklistGuid(registryPath, tasklistGuid);
|
|
133128
|
+
}
|
|
133129
|
+
const registryMismatch = registeredGuid !== tasklistGuid;
|
|
133130
|
+
const membersResult = getUserTasklistMembers(creatorProfile, tasklistGuid);
|
|
133131
|
+
const missingBots = [];
|
|
133132
|
+
let membershipCheckError;
|
|
133133
|
+
if (membersResult.ok) {
|
|
133134
|
+
for (const b of bots) {
|
|
133135
|
+
if (!membersResult.data.some((m) => m.id === b.app_id)) missingBots.push(b.id);
|
|
133136
|
+
}
|
|
133137
|
+
} else {
|
|
133138
|
+
membershipCheckError = membersResult.error;
|
|
133139
|
+
}
|
|
133140
|
+
if (ctx.flags.json) {
|
|
133141
|
+
ctx.ui.emitJson({
|
|
133142
|
+
ok: true,
|
|
133143
|
+
mode: "adopt",
|
|
133144
|
+
adoptedName: matchedName,
|
|
133145
|
+
tasklistGuid,
|
|
133146
|
+
addedMembers: bots.map((b) => b.id),
|
|
133147
|
+
missingBots,
|
|
133148
|
+
membershipCheckError: membershipCheckError ?? null,
|
|
133149
|
+
registeredGuid,
|
|
133150
|
+
registryMismatch
|
|
133151
|
+
});
|
|
133152
|
+
return 0;
|
|
133153
|
+
}
|
|
133154
|
+
ctx.ui.success(`\u5DF2 adopt \u6E05\u5355 "${matchedName}": ${tasklistGuid}`);
|
|
133155
|
+
ctx.ui.print(`\u5DF2\u52A0\u5165\u6210\u5458(editor): ${bots.map((b) => b.id).join(", ")}`);
|
|
133156
|
+
ctx.ui.print("");
|
|
133157
|
+
if (missingBots.length > 0) {
|
|
133158
|
+
ctx.ui.warning(
|
|
133159
|
+
`\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`
|
|
133160
|
+
);
|
|
133161
|
+
} else if (membershipCheckError) {
|
|
133162
|
+
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}`);
|
|
133163
|
+
}
|
|
133164
|
+
if (registryMismatch) {
|
|
133165
|
+
ctx.ui.warning(
|
|
133166
|
+
`\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`
|
|
133167
|
+
);
|
|
133168
|
+
} else {
|
|
133169
|
+
ctx.ui.print(
|
|
133170
|
+
`\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`
|
|
133171
|
+
);
|
|
133172
|
+
}
|
|
133173
|
+
ctx.ui.print("");
|
|
133174
|
+
ctx.ui.print(
|
|
133175
|
+
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:"
|
|
133176
|
+
);
|
|
133177
|
+
ctx.ui.print(` taskHandle:`);
|
|
133178
|
+
ctx.ui.print(` tasklistGuid: "${tasklistGuid}"`);
|
|
133179
|
+
return 0;
|
|
133180
|
+
}
|
|
133181
|
+
|
|
131127
133182
|
// src/cli/index.ts
|
|
131128
133183
|
var _require2 = createRequire3(import.meta.url);
|
|
131129
133184
|
var _pkg = _require2("../../package.json");
|
|
@@ -131140,9 +133195,10 @@ var COMMANDS = {
|
|
|
131140
133195
|
logs: run6,
|
|
131141
133196
|
update: run7,
|
|
131142
133197
|
dogfood: run9,
|
|
131143
|
-
ui: run8
|
|
133198
|
+
ui: run8,
|
|
133199
|
+
"tasklist-init": run10
|
|
131144
133200
|
};
|
|
131145
|
-
var
|
|
133201
|
+
var USAGE3 = `larkway \u2014 Feishu \u2194 local CLI agent bridge host manager
|
|
131146
133202
|
|
|
131147
133203
|
\u7528\u6CD5:
|
|
131148
133204
|
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 +133214,7 @@ var USAGE2 = `larkway \u2014 Feishu \u2194 local CLI agent bridge host manager
|
|
|
131158
133214
|
update pull + install + restart
|
|
131159
133215
|
dogfood preflight|guide [id] v0.3 Phase 1 dogfood \u524D\u7F6E\u9A8C\u6536 / \u4E0B\u4E00\u6B65\u6307\u5F15
|
|
131160
133216
|
ui \u542F\u52A8\u8F7B\u91CF Web UI \u7BA1\u7406\u9762(127.0.0.1 + token)
|
|
133217
|
+
tasklist-init \u4E3A\u8BDD\u9898\u2194\u4EFB\u52A1\u53E5\u67C4 feature provisioning \u5171\u4EAB\u6E05\u5355(docs/task-handle.md)
|
|
131161
133218
|
|
|
131162
133219
|
\u5168\u5C40 flags:
|
|
131163
133220
|
--json \u673A\u5668\u53EF\u8BFB\u8F93\u51FA(\u4E0E\u5176\u4ED6 flag \u6B63\u4EA4)
|
|
@@ -131222,29 +133279,32 @@ async function main(argv) {
|
|
|
131222
133279
|
return 0;
|
|
131223
133280
|
}
|
|
131224
133281
|
if (help) {
|
|
131225
|
-
|
|
133282
|
+
if (command === "tasklist-init") {
|
|
133283
|
+
return run10(buildContext(flags), ["help"]);
|
|
133284
|
+
}
|
|
133285
|
+
print(USAGE3);
|
|
131226
133286
|
return 0;
|
|
131227
133287
|
}
|
|
131228
133288
|
if (command === void 0) {
|
|
131229
133289
|
if (flags.json || flags.nonInteractive) {
|
|
131230
|
-
print(
|
|
133290
|
+
print(USAGE3);
|
|
131231
133291
|
return 1;
|
|
131232
133292
|
}
|
|
131233
133293
|
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
133294
|
print(dim("\u65E0\u6D4F\u89C8\u5668 / \u670D\u52A1\u5668\u573A\u666F\u8BF7\u6539\u7528 `larkway init`(CLI \u5411\u5BFC)\u3002"));
|
|
131235
133295
|
return run8(buildContext(flags), []);
|
|
131236
133296
|
}
|
|
131237
|
-
const
|
|
131238
|
-
if (!
|
|
133297
|
+
const run11 = COMMANDS[command];
|
|
133298
|
+
if (!run11) {
|
|
131239
133299
|
failure(`\u672A\u77E5\u547D\u4EE4: ${command}`);
|
|
131240
133300
|
print("");
|
|
131241
|
-
print(
|
|
133301
|
+
print(USAGE3);
|
|
131242
133302
|
return 1;
|
|
131243
133303
|
}
|
|
131244
133304
|
const ctx = buildContext(flags);
|
|
131245
133305
|
const isLifecycle = command === "start" || command === "stop" || command === "status" || command === "logs";
|
|
131246
133306
|
const runArgs = isLifecycle ? [command, ...args] : args;
|
|
131247
|
-
return
|
|
133307
|
+
return run11(ctx, runArgs);
|
|
131248
133308
|
}
|
|
131249
133309
|
main(process4.argv.slice(2)).then((code) => process4.exit(code)).catch((e) => {
|
|
131250
133310
|
const message = e instanceof Error ? e.message : String(e);
|