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/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 = __require("debug")("follow-redirects");
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 require_browser = __commonJS({
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 = require_browser().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 readFile6, rm } from "node:fs/promises";
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 readFile6(gitPath, "utf-8").catch(() => null);
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 readFile7 } from "node:fs/promises";
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 mkdir4, writeFile as writeFile5, rm as rm2 } from "node:fs/promises";
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 mkdir4(tmpDir, { recursive: true });
128774
+ await mkdir5(tmpDir, { recursive: true });
127293
128775
  const tmpFile = path12.join(tmpDir, "memory.md");
127294
128776
  try {
127295
- await writeFile5(tmpFile, initial, "utf-8");
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 readFile7(tmpFile, "utf-8");
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 readFile7(file, "utf-8");
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 mkdir5, readFile as readFile8, writeFile as writeFile6 } from "node:fs/promises";
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 readFile8(requestPath, "utf8").catch(() => "");
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 mkdir5(path13.dirname(grantedPath), { recursive: true });
127688
- await writeFile6(grantedPath, body, "utf8");
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 readFile9, writeFile as writeFile7, unlink as unlink5, mkdir as mkdir6, readdir as readdir5, access as access7 } from "node:fs/promises";
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 readFile9(pidFile, "utf-8")).trim();
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 mkdir6(path15.dirname(pidFile), { recursive: true });
128127
- await writeFile7(pidFile, String(pid) + "\n", "utf-8");
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 readFile9(file, "utf-8");
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 mkdir6(path15.dirname(logPath), { recursive: true });
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 readFile9(logPath, "utf-8");
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 readFile10, access as access9 } from "node:fs/promises";
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 readFile10(pkgPath, "utf-8");
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 readFile13, stat as stat5 } from "node:fs/promises";
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 readFile12, stat as stat4 } from "node:fs/promises";
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 mkdir7, writeFile as writeFile8, rename as rename4, chmod as chmod2, readFile as readFile11 } from "node:fs/promises";
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 mkdir7(path20.dirname(file), { recursive: true });
130558
+ await mkdir8(path20.dirname(file), { recursive: true });
129073
130559
  const tmp = `${file}.${process.pid}.${Date.now()}.tmp`;
129074
- await writeFile8(tmp, content, "utf-8");
129075
- await rename4(tmp, file);
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 readFile11(envPath, "utf-8");
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 readFile11(path20.join(botsDir, `${id}.yaml`), "utf-8");
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 readFile12(yamlFile, "utf-8");
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 readFile12(memFile, "utf-8");
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 readFile13(target);
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
- import { access as access10, readFile as readFile14, readdir as readdir7 } from "node:fs/promises";
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 readFile14(filePath, "utf8");
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 USAGE2 = `larkway \u2014 Feishu \u2194 local CLI agent bridge host manager
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
- print(USAGE2);
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(USAGE2);
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 run10 = COMMANDS[command];
131238
- if (!run10) {
133297
+ const run11 = COMMANDS[command];
133298
+ if (!run11) {
131239
133299
  failure(`\u672A\u77E5\u547D\u4EE4: ${command}`);
131240
133300
  print("");
131241
- print(USAGE2);
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 run10(ctx, runArgs);
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);