duclaw-cli 1.8.46 → 1.8.48

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/bundle.js CHANGED
@@ -115,7 +115,7 @@ var require_package = __commonJS({
115
115
  var require_main = __commonJS({
116
116
  "node_modules/.pnpm/dotenv@17.3.1/node_modules/dotenv/lib/main.js"(exports2, module2) {
117
117
  var fs3 = require("fs");
118
- var path19 = require("path");
118
+ var path20 = require("path");
119
119
  var os = require("os");
120
120
  var crypto2 = require("crypto");
121
121
  var packageJson = require_package();
@@ -261,7 +261,7 @@ var require_main = __commonJS({
261
261
  possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
262
262
  }
263
263
  } else {
264
- possibleVaultPath = path19.resolve(process.cwd(), ".env.vault");
264
+ possibleVaultPath = path20.resolve(process.cwd(), ".env.vault");
265
265
  }
266
266
  if (fs3.existsSync(possibleVaultPath)) {
267
267
  return possibleVaultPath;
@@ -269,7 +269,7 @@ var require_main = __commonJS({
269
269
  return null;
270
270
  }
271
271
  function _resolveHome(envPath) {
272
- return envPath[0] === "~" ? path19.join(os.homedir(), envPath.slice(1)) : envPath;
272
+ return envPath[0] === "~" ? path20.join(os.homedir(), envPath.slice(1)) : envPath;
273
273
  }
274
274
  function _configVault(options) {
275
275
  const debug = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || options && options.debug);
@@ -286,7 +286,7 @@ var require_main = __commonJS({
286
286
  return { parsed };
287
287
  }
288
288
  function configDotenv(options) {
289
- const dotenvPath = path19.resolve(process.cwd(), ".env");
289
+ const dotenvPath = path20.resolve(process.cwd(), ".env");
290
290
  let encoding = "utf8";
291
291
  let processEnv = process.env;
292
292
  if (options && options.processEnv != null) {
@@ -314,13 +314,13 @@ var require_main = __commonJS({
314
314
  }
315
315
  let lastError;
316
316
  const parsedAll = {};
317
- for (const path20 of optionPaths) {
317
+ for (const path21 of optionPaths) {
318
318
  try {
319
- const parsed = DotenvModule.parse(fs3.readFileSync(path20, { encoding }));
319
+ const parsed = DotenvModule.parse(fs3.readFileSync(path21, { encoding }));
320
320
  DotenvModule.populate(parsedAll, parsed, options);
321
321
  } catch (e) {
322
322
  if (debug) {
323
- _debug(`Failed to load ${path20} ${e.message}`);
323
+ _debug(`Failed to load ${path21} ${e.message}`);
324
324
  }
325
325
  lastError = e;
326
326
  }
@@ -333,7 +333,7 @@ var require_main = __commonJS({
333
333
  const shortPaths = [];
334
334
  for (const filePath of optionPaths) {
335
335
  try {
336
- const relative4 = path19.relative(process.cwd(), filePath);
336
+ const relative4 = path20.relative(process.cwd(), filePath);
337
337
  shortPaths.push(relative4);
338
338
  } catch (e) {
339
339
  if (debug) {
@@ -8237,8 +8237,8 @@ var require_MODULE_LOAD = __commonJS({
8237
8237
  * @param moduleArguments - Optional arguments to pass to the module
8238
8238
  * @see https://redis.io/commands/module-load/
8239
8239
  */
8240
- parseCommand(parser, path19, moduleArguments) {
8241
- parser.push("MODULE", "LOAD", path19);
8240
+ parseCommand(parser, path20, moduleArguments) {
8241
+ parser.push("MODULE", "LOAD", path20);
8242
8242
  if (moduleArguments) {
8243
8243
  parser.push(...moduleArguments);
8244
8244
  }
@@ -23539,10 +23539,10 @@ var require_ARRAPPEND = __commonJS({
23539
23539
  * @param json - The first value to append
23540
23540
  * @param jsons - Additional values to append
23541
23541
  */
23542
- parseCommand(parser, key, path19, json, ...jsons) {
23542
+ parseCommand(parser, key, path20, json, ...jsons) {
23543
23543
  parser.push("JSON.ARRAPPEND");
23544
23544
  parser.pushKey(key);
23545
- parser.push(path19, (0, generic_transformers_1.transformRedisJsonArgument)(json));
23545
+ parser.push(path20, (0, generic_transformers_1.transformRedisJsonArgument)(json));
23546
23546
  for (let i = 0; i < jsons.length; i++) {
23547
23547
  parser.push((0, generic_transformers_1.transformRedisJsonArgument)(jsons[i]));
23548
23548
  }
@@ -23572,10 +23572,10 @@ var require_ARRINDEX = __commonJS({
23572
23572
  * @param options.range.start - Starting index for the search
23573
23573
  * @param options.range.stop - Optional ending index for the search
23574
23574
  */
23575
- parseCommand(parser, key, path19, json, options) {
23575
+ parseCommand(parser, key, path20, json, options) {
23576
23576
  parser.push("JSON.ARRINDEX");
23577
23577
  parser.pushKey(key);
23578
- parser.push(path19, (0, generic_transformers_1.transformRedisJsonArgument)(json));
23578
+ parser.push(path20, (0, generic_transformers_1.transformRedisJsonArgument)(json));
23579
23579
  if (options?.range) {
23580
23580
  parser.push(options.range.start.toString());
23581
23581
  if (options.range.stop !== void 0) {
@@ -23607,10 +23607,10 @@ var require_ARRINSERT = __commonJS({
23607
23607
  * @param json - The first value to insert
23608
23608
  * @param jsons - Additional values to insert
23609
23609
  */
23610
- parseCommand(parser, key, path19, index, json, ...jsons) {
23610
+ parseCommand(parser, key, path20, index, json, ...jsons) {
23611
23611
  parser.push("JSON.ARRINSERT");
23612
23612
  parser.pushKey(key);
23613
- parser.push(path19, index.toString(), (0, generic_transformers_1.transformRedisJsonArgument)(json));
23613
+ parser.push(path20, index.toString(), (0, generic_transformers_1.transformRedisJsonArgument)(json));
23614
23614
  for (let i = 0; i < jsons.length; i++) {
23615
23615
  parser.push((0, generic_transformers_1.transformRedisJsonArgument)(jsons[i]));
23616
23616
  }
@@ -23700,10 +23700,10 @@ var require_ARRTRIM = __commonJS({
23700
23700
  * @param start - Starting index (inclusive)
23701
23701
  * @param stop - Ending index (inclusive)
23702
23702
  */
23703
- parseCommand(parser, key, path19, start, stop) {
23703
+ parseCommand(parser, key, path20, start, stop) {
23704
23704
  parser.push("JSON.ARRTRIM");
23705
23705
  parser.pushKey(key);
23706
- parser.push(path19, start.toString(), stop.toString());
23706
+ parser.push(path20, start.toString(), stop.toString());
23707
23707
  },
23708
23708
  transformReply: void 0
23709
23709
  };
@@ -23868,10 +23868,10 @@ var require_MERGE3 = __commonJS({
23868
23868
  * @param path - Path to merge into
23869
23869
  * @param value - JSON value to merge
23870
23870
  */
23871
- parseCommand(parser, key, path19, value) {
23871
+ parseCommand(parser, key, path20, value) {
23872
23872
  parser.push("JSON.MERGE");
23873
23873
  parser.pushKey(key);
23874
- parser.push(path19, (0, generic_transformers_1.transformRedisJsonArgument)(value));
23874
+ parser.push(path20, (0, generic_transformers_1.transformRedisJsonArgument)(value));
23875
23875
  },
23876
23876
  transformReply: void 0
23877
23877
  };
@@ -23894,10 +23894,10 @@ var require_MGET2 = __commonJS({
23894
23894
  * @param keys - Array of keys containing JSON documents
23895
23895
  * @param path - Path to retrieve from each document
23896
23896
  */
23897
- parseCommand(parser, keys, path19) {
23897
+ parseCommand(parser, keys, path20) {
23898
23898
  parser.push("JSON.MGET");
23899
23899
  parser.pushKeys(keys);
23900
- parser.push(path19);
23900
+ parser.push(path20);
23901
23901
  },
23902
23902
  transformReply(reply) {
23903
23903
  return reply.map((json) => (0, generic_transformers_1.transformRedisJsonNullReply)(json));
@@ -23952,10 +23952,10 @@ var require_NUMINCRBY = __commonJS({
23952
23952
  * @param path - Path to the numeric value
23953
23953
  * @param by - Amount to increment by
23954
23954
  */
23955
- parseCommand(parser, key, path19, by) {
23955
+ parseCommand(parser, key, path20, by) {
23956
23956
  parser.push("JSON.NUMINCRBY");
23957
23957
  parser.pushKey(key);
23958
- parser.push(path19, by.toString());
23958
+ parser.push(path20, by.toString());
23959
23959
  },
23960
23960
  transformReply: {
23961
23961
  2: (reply) => {
@@ -23987,10 +23987,10 @@ var require_NUMMULTBY = __commonJS({
23987
23987
  * @param path - Path to the numeric value
23988
23988
  * @param by - Amount to multiply by
23989
23989
  */
23990
- parseCommand(parser, key, path19, by) {
23990
+ parseCommand(parser, key, path20, by) {
23991
23991
  parser.push("JSON.NUMMULTBY");
23992
23992
  parser.pushKey(key);
23993
- parser.push(path19, by.toString());
23993
+ parser.push(path20, by.toString());
23994
23994
  },
23995
23995
  transformReply: NUMINCRBY_1.default.transformReply
23996
23996
  };
@@ -24074,10 +24074,10 @@ var require_SET2 = __commonJS({
24074
24074
  * @deprecated options.NX - Use options.condition instead
24075
24075
  * @deprecated options.XX - Use options.condition instead
24076
24076
  */
24077
- parseCommand(parser, key, path19, json, options) {
24077
+ parseCommand(parser, key, path20, json, options) {
24078
24078
  parser.push("JSON.SET");
24079
24079
  parser.pushKey(key);
24080
- parser.push(path19, (0, generic_transformers_1.transformRedisJsonArgument)(json));
24080
+ parser.push(path20, (0, generic_transformers_1.transformRedisJsonArgument)(json));
24081
24081
  if (options?.condition) {
24082
24082
  parser.push(options?.condition);
24083
24083
  } else if (options?.NX) {
@@ -24165,10 +24165,10 @@ var require_TOGGLE = __commonJS({
24165
24165
  * @param key - The key containing the JSON document
24166
24166
  * @param path - Path to the boolean value
24167
24167
  */
24168
- parseCommand(parser, key, path19) {
24168
+ parseCommand(parser, key, path20) {
24169
24169
  parser.push("JSON.TOGGLE");
24170
24170
  parser.pushKey(key);
24171
- parser.push(path19);
24171
+ parser.push(path20);
24172
24172
  },
24173
24173
  transformReply: void 0
24174
24174
  };
@@ -30242,7 +30242,7 @@ function printHelp() {
30242
30242
  `);
30243
30243
  }
30244
30244
  function printVersion() {
30245
- console.log(`duclaw-cli v${true ? "1.8.46" : "unknown"}`);
30245
+ console.log(`duclaw-cli v${true ? "1.8.48" : "unknown"}`);
30246
30246
  }
30247
30247
  function getDuclawTemplate() {
30248
30248
  return {
@@ -30757,10 +30757,530 @@ var feishuChannelPlugin = {
30757
30757
  }
30758
30758
  };
30759
30759
 
30760
+ // src/mobile/mobileStore.ts
30761
+ var import_node_crypto = require("node:crypto");
30762
+
30763
+ // src/db/createDB.ts
30764
+ var import_better_sqlite3 = __toESM(require("better-sqlite3"));
30765
+ var import_node_path2 = require("node:path");
30766
+ var _db = null;
30767
+ var _tableEnsured = false;
30768
+ var createSqliteDB = () => {
30769
+ if (!_db) {
30770
+ const dbDir = getDuclawDataDir();
30771
+ _db = new import_better_sqlite3.default((0, import_node_path2.join)(dbDir, "duclaw.db"));
30772
+ _db.pragma("journal_mode = WAL");
30773
+ }
30774
+ if (!_tableEnsured) {
30775
+ _tableEnsured = true;
30776
+ _ensure_table_exist();
30777
+ }
30778
+ return _db;
30779
+ };
30780
+ var _ensure_table_exist = () => {
30781
+ create_workspace_table();
30782
+ create_mailbox_table();
30783
+ create_mailbox_events_table();
30784
+ create_ceo_followups_table();
30785
+ create_agent_events_table();
30786
+ create_mobile_tables();
30787
+ };
30788
+ var create_workspace_table = () => {
30789
+ const db3 = createSqliteDB();
30790
+ db3.exec(`
30791
+ CREATE TABLE IF NOT EXISTS workspace (
30792
+ id TEXT PRIMARY KEY,
30793
+ team_name TEXT NOT NULL,
30794
+ teammate_name TEXT,
30795
+ team_workpath TEXT NOT NULL,
30796
+ created_at INTEGER DEFAULT (strftime('%s', 'now')),
30797
+ updated_at INTEGER DEFAULT (strftime('%s', 'now'))
30798
+ );
30799
+
30800
+ CREATE INDEX IF NOT EXISTS idx_team ON workspace(team_name);
30801
+ `);
30802
+ };
30803
+ var create_mailbox_table = () => {
30804
+ const db3 = createSqliteDB();
30805
+ db3.exec(`
30806
+ CREATE TABLE IF NOT EXISTS mailbox (
30807
+ id TEXT PRIMARY KEY,
30808
+ to_mailbox_id TEXT NOT NULL,
30809
+ from_mailbox_id TEXT NOT NULL,
30810
+ content TEXT NOT NULL,
30811
+ status TEXT DEFAULT ('pending') NOT NULL,
30812
+ origin_user_id TEXT,
30813
+ origin_platform TEXT,
30814
+ thread_id TEXT,
30815
+ parent_message_id TEXT,
30816
+ work_item_id TEXT,
30817
+ work_item_role TEXT,
30818
+ upstream_message_id TEXT,
30819
+ send_time INTEGER DEFAULT ((strftime('%s', 'now')) * 1000),
30820
+ created_at INTEGER DEFAULT ((strftime('%s', 'now')) * 1000),
30821
+ updated_at INTEGER DEFAULT ((strftime('%s', 'now')) * 1000)
30822
+ );
30823
+
30824
+ CREATE INDEX IF NOT EXISTS idx_mailbox ON mailbox(to_mailbox_id);
30825
+ `);
30826
+ try {
30827
+ db3.exec(`ALTER TABLE mailbox ADD COLUMN origin_user_id TEXT`);
30828
+ } catch (_) {
30829
+ }
30830
+ try {
30831
+ db3.exec(`ALTER TABLE mailbox ADD COLUMN origin_platform TEXT`);
30832
+ } catch (_) {
30833
+ }
30834
+ try {
30835
+ db3.exec(`ALTER TABLE mailbox ADD COLUMN thread_id TEXT`);
30836
+ } catch (_) {
30837
+ }
30838
+ try {
30839
+ db3.exec(`ALTER TABLE mailbox ADD COLUMN parent_message_id TEXT`);
30840
+ } catch (_) {
30841
+ }
30842
+ try {
30843
+ db3.exec(`ALTER TABLE mailbox ADD COLUMN work_item_id TEXT`);
30844
+ } catch (_) {
30845
+ }
30846
+ try {
30847
+ db3.exec(`ALTER TABLE mailbox ADD COLUMN work_item_role TEXT`);
30848
+ } catch (_) {
30849
+ }
30850
+ try {
30851
+ db3.exec(`ALTER TABLE mailbox ADD COLUMN upstream_message_id TEXT`);
30852
+ } catch (_) {
30853
+ }
30854
+ const columns = db3.prepare(`PRAGMA table_info(mailbox)`).all();
30855
+ const hasThreadId = columns.some((column) => column.name === "thread_id");
30856
+ const hasParentMessageId = columns.some((column) => column.name === "parent_message_id");
30857
+ const hasWorkItemId = columns.some((column) => column.name === "work_item_id");
30858
+ const hasUpstreamMessageId = columns.some((column) => column.name === "upstream_message_id");
30859
+ if (hasThreadId) {
30860
+ db3.exec(`
30861
+ CREATE INDEX IF NOT EXISTS idx_mailbox_thread
30862
+ ON mailbox(thread_id, send_time DESC)
30863
+ `);
30864
+ db3.exec(`UPDATE mailbox SET thread_id = id WHERE thread_id IS NULL`);
30865
+ }
30866
+ if (hasParentMessageId) {
30867
+ db3.exec(`
30868
+ CREATE INDEX IF NOT EXISTS idx_mailbox_parent
30869
+ ON mailbox(parent_message_id)
30870
+ `);
30871
+ }
30872
+ if (hasWorkItemId) {
30873
+ db3.exec(`
30874
+ CREATE INDEX IF NOT EXISTS idx_mailbox_work_item
30875
+ ON mailbox(work_item_id, send_time DESC)
30876
+ `);
30877
+ }
30878
+ if (hasUpstreamMessageId) {
30879
+ db3.exec(`
30880
+ CREATE INDEX IF NOT EXISTS idx_mailbox_upstream
30881
+ ON mailbox(upstream_message_id)
30882
+ `);
30883
+ }
30884
+ };
30885
+ var create_mailbox_events_table = () => {
30886
+ const db3 = createSqliteDB();
30887
+ db3.exec(`
30888
+ CREATE TABLE IF NOT EXISTS mailbox_events (
30889
+ id TEXT PRIMARY KEY,
30890
+ message_id TEXT,
30891
+ mailbox_id TEXT NOT NULL,
30892
+ actor_mailbox_id TEXT,
30893
+ counterpart_mailbox_id TEXT,
30894
+ event_type TEXT NOT NULL,
30895
+ detail_json TEXT,
30896
+ created_at INTEGER DEFAULT ((strftime('%s', 'now')) * 1000)
30897
+ );
30898
+
30899
+ CREATE INDEX IF NOT EXISTS idx_mailbox_events_mailbox_created
30900
+ ON mailbox_events(mailbox_id, created_at DESC);
30901
+
30902
+ CREATE INDEX IF NOT EXISTS idx_mailbox_events_message_created
30903
+ ON mailbox_events(message_id, created_at DESC);
30904
+ `);
30905
+ try {
30906
+ db3.exec(`ALTER TABLE mailbox_events ADD COLUMN actor_mailbox_id TEXT`);
30907
+ } catch (_) {
30908
+ }
30909
+ try {
30910
+ db3.exec(`ALTER TABLE mailbox_events ADD COLUMN counterpart_mailbox_id TEXT`);
30911
+ } catch (_) {
30912
+ }
30913
+ try {
30914
+ db3.exec(`ALTER TABLE mailbox_events ADD COLUMN detail_json TEXT`);
30915
+ } catch (_) {
30916
+ }
30917
+ };
30918
+ var create_ceo_followups_table = () => {
30919
+ const db3 = createSqliteDB();
30920
+ db3.exec(`
30921
+ CREATE TABLE IF NOT EXISTS ceo_followups (
30922
+ id TEXT PRIMARY KEY,
30923
+ source_message_id TEXT NOT NULL UNIQUE,
30924
+ status TEXT DEFAULT ('pending') NOT NULL,
30925
+ origin_user_id TEXT NOT NULL,
30926
+ origin_platform TEXT NOT NULL,
30927
+ from_mailbox_id TEXT NOT NULL,
30928
+ thread_id TEXT,
30929
+ parent_message_id TEXT,
30930
+ work_item_id TEXT,
30931
+ content TEXT NOT NULL,
30932
+ attempts INTEGER DEFAULT 0 NOT NULL,
30933
+ last_error TEXT,
30934
+ created_at INTEGER DEFAULT ((strftime('%s', 'now')) * 1000),
30935
+ updated_at INTEGER DEFAULT ((strftime('%s', 'now')) * 1000),
30936
+ completed_at INTEGER
30937
+ );
30938
+
30939
+ CREATE INDEX IF NOT EXISTS idx_ceo_followups_status_created
30940
+ ON ceo_followups(status, created_at);
30941
+
30942
+ CREATE INDEX IF NOT EXISTS idx_ceo_followups_user_status
30943
+ ON ceo_followups(origin_user_id, status, created_at);
30944
+ `);
30945
+ };
30946
+ var create_agent_events_table = () => {
30947
+ const db3 = createSqliteDB();
30948
+ db3.exec(`
30949
+ CREATE TABLE IF NOT EXISTS agent_events (
30950
+ id TEXT PRIMARY KEY,
30951
+ user_id TEXT NOT NULL,
30952
+ type TEXT NOT NULL,
30953
+ source TEXT NOT NULL,
30954
+ source_id TEXT NOT NULL,
30955
+ status TEXT DEFAULT ('pending') NOT NULL,
30956
+ payload_json TEXT NOT NULL,
30957
+ created_at INTEGER DEFAULT ((strftime('%s', 'now')) * 1000),
30958
+ injected_at INTEGER,
30959
+ handled_at INTEGER,
30960
+ updated_at INTEGER DEFAULT ((strftime('%s', 'now')) * 1000),
30961
+ UNIQUE(type, source, source_id)
30962
+ );
30963
+
30964
+ CREATE INDEX IF NOT EXISTS idx_agent_events_user_status_created
30965
+ ON agent_events(user_id, status, created_at);
30966
+
30967
+ CREATE INDEX IF NOT EXISTS idx_agent_events_source
30968
+ ON agent_events(type, source, source_id);
30969
+ `);
30970
+ };
30971
+ var create_mobile_tables = () => {
30972
+ const db3 = createSqliteDB();
30973
+ db3.exec(`
30974
+ CREATE TABLE IF NOT EXISTS mobile_messages (
30975
+ id TEXT PRIMARY KEY,
30976
+ thread_id TEXT NOT NULL,
30977
+ user_id TEXT NOT NULL,
30978
+ goal_id TEXT,
30979
+ client_message_id TEXT,
30980
+ role TEXT NOT NULL,
30981
+ text TEXT NOT NULL,
30982
+ status TEXT NOT NULL,
30983
+ attachments_json TEXT,
30984
+ metadata_json TEXT,
30985
+ created_at INTEGER NOT NULL,
30986
+ updated_at INTEGER NOT NULL
30987
+ );
30988
+
30989
+ CREATE INDEX IF NOT EXISTS idx_mobile_messages_thread_created
30990
+ ON mobile_messages(thread_id, created_at DESC);
30991
+
30992
+ CREATE TABLE IF NOT EXISTS mobile_runs (
30993
+ thread_id TEXT PRIMARY KEY,
30994
+ user_id TEXT NOT NULL,
30995
+ goal_id TEXT,
30996
+ running INTEGER DEFAULT 0 NOT NULL,
30997
+ interrupted INTEGER,
30998
+ logs_json TEXT NOT NULL,
30999
+ last_result TEXT,
31000
+ error TEXT,
31001
+ updated_at INTEGER NOT NULL
31002
+ );
31003
+
31004
+ CREATE TABLE IF NOT EXISTS mobile_attachments (
31005
+ id TEXT PRIMARY KEY,
31006
+ type TEXT,
31007
+ name TEXT,
31008
+ mime_type TEXT,
31009
+ size INTEGER,
31010
+ path TEXT,
31011
+ url TEXT,
31012
+ created_at INTEGER NOT NULL,
31013
+ updated_at INTEGER NOT NULL
31014
+ );
31015
+ `);
31016
+ };
31017
+
31018
+ // src/mobile/mobileStore.ts
31019
+ var lastMobileMessageTimestamp = 0;
31020
+ var nextMobileMessageTimestamp = () => {
31021
+ const now = Date.now();
31022
+ lastMobileMessageTimestamp = Math.max(now, lastMobileMessageTimestamp + 1);
31023
+ return lastMobileMessageTimestamp;
31024
+ };
31025
+ var parseJson = (value, fallback) => {
31026
+ if (!value) return fallback;
31027
+ try {
31028
+ return JSON.parse(value);
31029
+ } catch {
31030
+ return fallback;
31031
+ }
31032
+ };
31033
+ var clampLimit = (limit) => {
31034
+ if (!Number.isFinite(limit)) return 20;
31035
+ return Math.max(1, Math.min(100, Math.floor(limit ?? 20)));
31036
+ };
31037
+ var rowToMessage = (row) => ({
31038
+ id: row.id,
31039
+ threadId: row.thread_id,
31040
+ userId: row.user_id,
31041
+ goalId: row.goal_id ?? void 0,
31042
+ clientMessageId: row.client_message_id ?? void 0,
31043
+ role: row.role,
31044
+ text: row.text,
31045
+ status: row.status,
31046
+ attachments: parseJson(row.attachments_json, void 0),
31047
+ metadata: parseJson(row.metadata_json, void 0),
31048
+ createdAt: row.created_at,
31049
+ updatedAt: row.updated_at
31050
+ });
31051
+ var rowToAttachment = (row) => ({
31052
+ id: row.id,
31053
+ type: row.type ?? void 0,
31054
+ name: row.name ?? void 0,
31055
+ mimeType: row.mime_type ?? void 0,
31056
+ size: row.size ?? void 0,
31057
+ path: row.path ?? void 0,
31058
+ url: row.url ?? void 0
31059
+ });
31060
+ var rowToRun = (row) => ({
31061
+ threadId: row.thread_id,
31062
+ userId: row.user_id,
31063
+ goalId: row.goal_id ?? void 0,
31064
+ running: row.running === 1,
31065
+ interrupted: row.interrupted === null ? void 0 : row.interrupted === 1,
31066
+ logs: parseJson(row.logs_json, []),
31067
+ lastResult: row.last_result ?? void 0,
31068
+ error: row.error ?? void 0,
31069
+ updatedAt: row.updated_at
31070
+ });
31071
+ var saveMobileAttachment = (attachment) => {
31072
+ const now = Date.now();
31073
+ const saved = {
31074
+ ...attachment,
31075
+ id: attachment.id ?? (0, import_node_crypto.randomUUID)()
31076
+ };
31077
+ createSqliteDB().prepare(`
31078
+ INSERT OR REPLACE INTO mobile_attachments
31079
+ (id, type, name, mime_type, size, path, url, created_at, updated_at)
31080
+ VALUES (@id, @type, @name, @mimeType, @size, @path, @url, @createdAt, @updatedAt)
31081
+ `).run({
31082
+ id: saved.id,
31083
+ type: saved.type ?? null,
31084
+ name: saved.name ?? null,
31085
+ mimeType: saved.mimeType ?? null,
31086
+ size: saved.size ?? null,
31087
+ path: saved.path ?? null,
31088
+ url: saved.url ?? null,
31089
+ createdAt: now,
31090
+ updatedAt: now
31091
+ });
31092
+ return saved;
31093
+ };
31094
+ var getMobileAttachment = (id) => {
31095
+ const row = createSqliteDB().prepare(`SELECT id, type, name, mime_type, size, path, url FROM mobile_attachments WHERE id = ?`).get(id);
31096
+ return row ? rowToAttachment(row) : void 0;
31097
+ };
31098
+ var appendMobileMessage = (input) => {
31099
+ const now = nextMobileMessageTimestamp();
31100
+ const message = {
31101
+ ...input,
31102
+ id: input.id ?? (0, import_node_crypto.randomUUID)(),
31103
+ createdAt: now,
31104
+ updatedAt: now
31105
+ };
31106
+ createSqliteDB().prepare(`
31107
+ INSERT OR REPLACE INTO mobile_messages
31108
+ (id, thread_id, user_id, goal_id, client_message_id, role, text, status, attachments_json, metadata_json, created_at, updated_at)
31109
+ VALUES (@id, @threadId, @userId, @goalId, @clientMessageId, @role, @text, @status, @attachmentsJson, @metadataJson, @createdAt, @updatedAt)
31110
+ `).run({
31111
+ id: message.id,
31112
+ threadId: message.threadId,
31113
+ userId: message.userId,
31114
+ goalId: message.goalId ?? null,
31115
+ clientMessageId: message.clientMessageId ?? null,
31116
+ role: message.role,
31117
+ text: message.text,
31118
+ status: message.status,
31119
+ attachmentsJson: message.attachments ? JSON.stringify(message.attachments) : null,
31120
+ metadataJson: message.metadata ? JSON.stringify(message.metadata) : null,
31121
+ createdAt: message.createdAt,
31122
+ updatedAt: message.updatedAt
31123
+ });
31124
+ return message;
31125
+ };
31126
+ var listMobileMessagesPage = (threadId, options = {}) => {
31127
+ const limit = clampLimit(options.limit);
31128
+ const rows = createSqliteDB().prepare(`
31129
+ SELECT *
31130
+ FROM mobile_messages
31131
+ WHERE thread_id = @threadId
31132
+ ${options.before ? "AND created_at < @before" : ""}
31133
+ ORDER BY created_at DESC
31134
+ LIMIT @limitPlusOne
31135
+ `).all({
31136
+ threadId,
31137
+ before: options.before,
31138
+ limitPlusOne: limit + 1
31139
+ });
31140
+ const hasMore = rows.length > limit;
31141
+ const messages = rows.slice(0, limit).map(rowToMessage).reverse();
31142
+ return {
31143
+ messages,
31144
+ hasMore,
31145
+ nextBefore: messages[0]?.createdAt
31146
+ };
31147
+ };
31148
+ var listMobileMessages = (threadId) => {
31149
+ return listMobileMessagesPage(threadId, { limit: 100 }).messages;
31150
+ };
31151
+ var upsertMobileRun = (threadId, patch) => {
31152
+ const existing = getMobileRun(threadId);
31153
+ const run = {
31154
+ threadId,
31155
+ userId: patch.userId ?? existing.userId ?? threadId,
31156
+ goalId: patch.goalId ?? existing.goalId,
31157
+ running: patch.running ?? existing.running ?? false,
31158
+ interrupted: patch.interrupted ?? existing.interrupted,
31159
+ logs: patch.logs ?? existing.logs ?? [],
31160
+ lastResult: patch.lastResult ?? existing.lastResult,
31161
+ error: patch.error,
31162
+ updatedAt: Date.now()
31163
+ };
31164
+ createSqliteDB().prepare(`
31165
+ INSERT OR REPLACE INTO mobile_runs
31166
+ (thread_id, user_id, goal_id, running, interrupted, logs_json, last_result, error, updated_at)
31167
+ VALUES (@threadId, @userId, @goalId, @running, @interrupted, @logsJson, @lastResult, @error, @updatedAt)
31168
+ `).run({
31169
+ threadId: run.threadId,
31170
+ userId: run.userId,
31171
+ goalId: run.goalId ?? null,
31172
+ running: run.running ? 1 : 0,
31173
+ interrupted: run.interrupted === void 0 ? null : run.interrupted ? 1 : 0,
31174
+ logsJson: JSON.stringify(run.logs),
31175
+ lastResult: run.lastResult ?? null,
31176
+ error: run.error ?? null,
31177
+ updatedAt: run.updatedAt
31178
+ });
31179
+ return run;
31180
+ };
31181
+ var appendMobileRunLog = (threadId, line) => {
31182
+ const existing = getMobileRun(threadId);
31183
+ return upsertMobileRun(threadId, {
31184
+ userId: existing.userId ?? threadId,
31185
+ goalId: existing.goalId,
31186
+ running: existing.running ?? false,
31187
+ interrupted: existing.interrupted,
31188
+ logs: [...existing.logs ?? [], line],
31189
+ lastResult: existing.lastResult,
31190
+ error: existing.error
31191
+ });
31192
+ };
31193
+ var getMobileRun = (threadId) => {
31194
+ const row = createSqliteDB().prepare(`SELECT * FROM mobile_runs WHERE thread_id = ?`).get(threadId);
31195
+ return row ? rowToRun(row) : {
31196
+ threadId,
31197
+ userId: threadId,
31198
+ running: false,
31199
+ logs: [],
31200
+ updatedAt: Date.now()
31201
+ };
31202
+ };
31203
+
31204
+ // src/channels/mobile/mobileChannelPlugin.ts
31205
+ async function postControlPlaneMobileMessage(ctx, threadId) {
31206
+ const baseUrl = process.env.DUCLAW_CONTROL_PLANE_BASE_URL?.replace(/\/$/, "");
31207
+ const token = process.env.DUCLAW_CONTROL_PLANE_METERING_TOKEN;
31208
+ const tenantId = process.env.DUCLAW_TENANT_ID;
31209
+ if (!baseUrl || !token || !tenantId) return;
31210
+ try {
31211
+ const response = await fetch(`${baseUrl}/internal/runtime/mobile/messages`, {
31212
+ method: "POST",
31213
+ signal: AbortSignal.timeout(2500),
31214
+ headers: {
31215
+ authorization: `Bearer ${token}`,
31216
+ "content-type": "application/json"
31217
+ },
31218
+ body: JSON.stringify({
31219
+ tenantId,
31220
+ threadId,
31221
+ userId: threadId,
31222
+ role: "assistant",
31223
+ text: ctx.text,
31224
+ status: "finished",
31225
+ metadata: {
31226
+ ...ctx.metadata ?? {},
31227
+ accountId: ctx.accountId,
31228
+ source: "mobile-channel"
31229
+ }
31230
+ })
31231
+ });
31232
+ if (!response.ok) {
31233
+ console.warn(`[mobile-channel] control-plane \u56DE\u5199\u5931\u8D25: http=${response.status}`);
31234
+ }
31235
+ } catch (err) {
31236
+ console.warn(`[mobile-channel] control-plane \u56DE\u5199\u5F02\u5E38: ${err.message}`);
31237
+ }
31238
+ }
31239
+ var mobileChannelPlugin = {
31240
+ id: "mobile-channel",
31241
+ meta: {
31242
+ id: "mobile-channel",
31243
+ label: "mobile channel",
31244
+ blurb: "In-app mobile delivery for Duclaw iOS clients"
31245
+ },
31246
+ config: {
31247
+ resolveAccount: (cfg) => cfg
31248
+ },
31249
+ outbound: {
31250
+ sendText: async (ctx) => {
31251
+ const threadId = ctx.to;
31252
+ await postControlPlaneMobileMessage(ctx, threadId);
31253
+ appendMobileMessage({
31254
+ threadId,
31255
+ userId: threadId,
31256
+ role: "assistant",
31257
+ text: ctx.text,
31258
+ status: "finished",
31259
+ metadata: {
31260
+ ...ctx.metadata ?? {},
31261
+ accountId: ctx.accountId,
31262
+ source: "mobile-channel"
31263
+ }
31264
+ });
31265
+ upsertMobileRun(threadId, {
31266
+ userId: threadId,
31267
+ running: false,
31268
+ lastResult: ctx.text
31269
+ });
31270
+ appendMobileRunLog(threadId, `[\u5B8C\u6210] ${ctx.text.slice(0, 500)}`);
31271
+ }
31272
+ },
31273
+ gateway: {
31274
+ startAccount: async () => void 0,
31275
+ stopAccount: async () => void 0
31276
+ }
31277
+ };
31278
+
30760
31279
  // src/channels/index.ts
30761
31280
  var createDefaultChannels = () => {
30762
31281
  const registry2 = createChannelRegistry();
30763
31282
  registerChannel(registry2, feishuChannelPlugin);
31283
+ registerChannel(registry2, mobileChannelPlugin);
30764
31284
  return {
30765
31285
  registry: registry2
30766
31286
  };
@@ -30901,7 +31421,7 @@ var sp2 = __toESM(require("node:path"), 1);
30901
31421
 
30902
31422
  // node_modules/.pnpm/readdirp@5.0.0/node_modules/readdirp/index.js
30903
31423
  var import_promises2 = require("node:fs/promises");
30904
- var import_node_path2 = require("node:path");
31424
+ var import_node_path3 = require("node:path");
30905
31425
  var import_node_stream = require("node:stream");
30906
31426
  var EntryTypes = {
30907
31427
  FILE_TYPE: "files",
@@ -30983,7 +31503,7 @@ var ReaddirpStream = class extends import_node_stream.Readable {
30983
31503
  this._directoryFilter = normalizeFilter(opts.directoryFilter);
30984
31504
  const statMethod = opts.lstat ? import_promises2.lstat : import_promises2.stat;
30985
31505
  if (wantBigintFsStats) {
30986
- this._stat = (path19) => statMethod(path19, { bigint: true });
31506
+ this._stat = (path20) => statMethod(path20, { bigint: true });
30987
31507
  } else {
30988
31508
  this._stat = statMethod;
30989
31509
  }
@@ -30991,7 +31511,7 @@ var ReaddirpStream = class extends import_node_stream.Readable {
30991
31511
  this._wantsDir = type ? DIR_TYPES.has(type) : false;
30992
31512
  this._wantsFile = type ? FILE_TYPES.has(type) : false;
30993
31513
  this._wantsEverything = type === EntryTypes.EVERYTHING_TYPE;
30994
- this._root = (0, import_node_path2.resolve)(root);
31514
+ this._root = (0, import_node_path3.resolve)(root);
30995
31515
  this._isDirent = !opts.alwaysStat;
30996
31516
  this._statsProp = this._isDirent ? "dirent" : "stats";
30997
31517
  this._rdOptions = { encoding: "utf8", withFileTypes: this._isDirent };
@@ -31008,8 +31528,8 @@ var ReaddirpStream = class extends import_node_stream.Readable {
31008
31528
  const par = this.parent;
31009
31529
  const fil = par && par.files;
31010
31530
  if (fil && fil.length > 0) {
31011
- const { path: path19, depth } = par;
31012
- const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path19));
31531
+ const { path: path20, depth } = par;
31532
+ const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path20));
31013
31533
  const awaited = await Promise.all(slice);
31014
31534
  for (const entry of awaited) {
31015
31535
  if (!entry)
@@ -31049,21 +31569,21 @@ var ReaddirpStream = class extends import_node_stream.Readable {
31049
31569
  this.reading = false;
31050
31570
  }
31051
31571
  }
31052
- async _exploreDir(path19, depth) {
31572
+ async _exploreDir(path20, depth) {
31053
31573
  let files;
31054
31574
  try {
31055
- files = await (0, import_promises2.readdir)(path19, this._rdOptions);
31575
+ files = await (0, import_promises2.readdir)(path20, this._rdOptions);
31056
31576
  } catch (error) {
31057
31577
  this._onError(error);
31058
31578
  }
31059
- return { files, depth, path: path19 };
31579
+ return { files, depth, path: path20 };
31060
31580
  }
31061
- async _formatEntry(dirent, path19) {
31581
+ async _formatEntry(dirent, path20) {
31062
31582
  let entry;
31063
31583
  const basename4 = this._isDirent ? dirent.name : dirent;
31064
31584
  try {
31065
- const fullPath = (0, import_node_path2.resolve)((0, import_node_path2.join)(path19, basename4));
31066
- entry = { path: (0, import_node_path2.relative)(this._root, fullPath), fullPath, basename: basename4 };
31585
+ const fullPath = (0, import_node_path3.resolve)((0, import_node_path3.join)(path20, basename4));
31586
+ entry = { path: (0, import_node_path3.relative)(this._root, fullPath), fullPath, basename: basename4 };
31067
31587
  entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
31068
31588
  } catch (err) {
31069
31589
  this._onError(err);
@@ -31097,7 +31617,7 @@ var ReaddirpStream = class extends import_node_stream.Readable {
31097
31617
  }
31098
31618
  if (entryRealPathStats.isDirectory()) {
31099
31619
  const len = entryRealPath.length;
31100
- if (full.startsWith(entryRealPath) && full.substr(len, 1) === import_node_path2.sep) {
31620
+ if (full.startsWith(entryRealPath) && full.substr(len, 1) === import_node_path3.sep) {
31101
31621
  const recursiveError = new Error(`Circular symlink detected: "${full}" points to "${entryRealPath}"`);
31102
31622
  recursiveError.code = RECURSIVE_ERROR_CODE;
31103
31623
  return this._onError(recursiveError);
@@ -31462,16 +31982,16 @@ var delFromSet = (main2, prop, item) => {
31462
31982
  };
31463
31983
  var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
31464
31984
  var FsWatchInstances = /* @__PURE__ */ new Map();
31465
- function createFsWatchInstance(path19, options, listener, errHandler, emitRaw) {
31985
+ function createFsWatchInstance(path20, options, listener, errHandler, emitRaw) {
31466
31986
  const handleEvent = (rawEvent, evPath) => {
31467
- listener(path19);
31468
- emitRaw(rawEvent, evPath, { watchedPath: path19 });
31469
- if (evPath && path19 !== evPath) {
31470
- fsWatchBroadcast(sp.resolve(path19, evPath), KEY_LISTENERS, sp.join(path19, evPath));
31987
+ listener(path20);
31988
+ emitRaw(rawEvent, evPath, { watchedPath: path20 });
31989
+ if (evPath && path20 !== evPath) {
31990
+ fsWatchBroadcast(sp.resolve(path20, evPath), KEY_LISTENERS, sp.join(path20, evPath));
31471
31991
  }
31472
31992
  };
31473
31993
  try {
31474
- return (0, import_node_fs.watch)(path19, {
31994
+ return (0, import_node_fs.watch)(path20, {
31475
31995
  persistent: options.persistent
31476
31996
  }, handleEvent);
31477
31997
  } catch (error) {
@@ -31487,12 +32007,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
31487
32007
  listener(val1, val2, val3);
31488
32008
  });
31489
32009
  };
31490
- var setFsWatchListener = (path19, fullPath, options, handlers) => {
32010
+ var setFsWatchListener = (path20, fullPath, options, handlers) => {
31491
32011
  const { listener, errHandler, rawEmitter } = handlers;
31492
32012
  let cont = FsWatchInstances.get(fullPath);
31493
32013
  let watcher;
31494
32014
  if (!options.persistent) {
31495
- watcher = createFsWatchInstance(path19, options, listener, errHandler, rawEmitter);
32015
+ watcher = createFsWatchInstance(path20, options, listener, errHandler, rawEmitter);
31496
32016
  if (!watcher)
31497
32017
  return;
31498
32018
  return watcher.close.bind(watcher);
@@ -31503,7 +32023,7 @@ var setFsWatchListener = (path19, fullPath, options, handlers) => {
31503
32023
  addAndConvert(cont, KEY_RAW, rawEmitter);
31504
32024
  } else {
31505
32025
  watcher = createFsWatchInstance(
31506
- path19,
32026
+ path20,
31507
32027
  options,
31508
32028
  fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
31509
32029
  errHandler,
@@ -31518,7 +32038,7 @@ var setFsWatchListener = (path19, fullPath, options, handlers) => {
31518
32038
  cont.watcherUnusable = true;
31519
32039
  if (isWindows && error.code === "EPERM") {
31520
32040
  try {
31521
- const fd = await (0, import_promises3.open)(path19, "r");
32041
+ const fd = await (0, import_promises3.open)(path20, "r");
31522
32042
  await fd.close();
31523
32043
  broadcastErr(error);
31524
32044
  } catch (err) {
@@ -31549,7 +32069,7 @@ var setFsWatchListener = (path19, fullPath, options, handlers) => {
31549
32069
  };
31550
32070
  };
31551
32071
  var FsWatchFileInstances = /* @__PURE__ */ new Map();
31552
- var setFsWatchFileListener = (path19, fullPath, options, handlers) => {
32072
+ var setFsWatchFileListener = (path20, fullPath, options, handlers) => {
31553
32073
  const { listener, rawEmitter } = handlers;
31554
32074
  let cont = FsWatchFileInstances.get(fullPath);
31555
32075
  const copts = cont && cont.options;
@@ -31571,7 +32091,7 @@ var setFsWatchFileListener = (path19, fullPath, options, handlers) => {
31571
32091
  });
31572
32092
  const currmtime = curr.mtimeMs;
31573
32093
  if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
31574
- foreach(cont.listeners, (listener2) => listener2(path19, curr));
32094
+ foreach(cont.listeners, (listener2) => listener2(path20, curr));
31575
32095
  }
31576
32096
  })
31577
32097
  };
@@ -31601,13 +32121,13 @@ var NodeFsHandler = class {
31601
32121
  * @param listener on fs change
31602
32122
  * @returns closer for the watcher instance
31603
32123
  */
31604
- _watchWithNodeFs(path19, listener) {
32124
+ _watchWithNodeFs(path20, listener) {
31605
32125
  const opts = this.fsw.options;
31606
- const directory = sp.dirname(path19);
31607
- const basename4 = sp.basename(path19);
32126
+ const directory = sp.dirname(path20);
32127
+ const basename4 = sp.basename(path20);
31608
32128
  const parent = this.fsw._getWatchedDir(directory);
31609
32129
  parent.add(basename4);
31610
- const absolutePath = sp.resolve(path19);
32130
+ const absolutePath = sp.resolve(path20);
31611
32131
  const options = {
31612
32132
  persistent: opts.persistent
31613
32133
  };
@@ -31617,12 +32137,12 @@ var NodeFsHandler = class {
31617
32137
  if (opts.usePolling) {
31618
32138
  const enableBin = opts.interval !== opts.binaryInterval;
31619
32139
  options.interval = enableBin && isBinaryPath(basename4) ? opts.binaryInterval : opts.interval;
31620
- closer = setFsWatchFileListener(path19, absolutePath, options, {
32140
+ closer = setFsWatchFileListener(path20, absolutePath, options, {
31621
32141
  listener,
31622
32142
  rawEmitter: this.fsw._emitRaw
31623
32143
  });
31624
32144
  } else {
31625
- closer = setFsWatchListener(path19, absolutePath, options, {
32145
+ closer = setFsWatchListener(path20, absolutePath, options, {
31626
32146
  listener,
31627
32147
  errHandler: this._boundHandleError,
31628
32148
  rawEmitter: this.fsw._emitRaw
@@ -31644,7 +32164,7 @@ var NodeFsHandler = class {
31644
32164
  let prevStats = stats;
31645
32165
  if (parent.has(basename4))
31646
32166
  return;
31647
- const listener = async (path19, newStats) => {
32167
+ const listener = async (path20, newStats) => {
31648
32168
  if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
31649
32169
  return;
31650
32170
  if (!newStats || newStats.mtimeMs === 0) {
@@ -31658,11 +32178,11 @@ var NodeFsHandler = class {
31658
32178
  this.fsw._emit(EV.CHANGE, file, newStats2);
31659
32179
  }
31660
32180
  if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
31661
- this.fsw._closeFile(path19);
32181
+ this.fsw._closeFile(path20);
31662
32182
  prevStats = newStats2;
31663
32183
  const closer2 = this._watchWithNodeFs(file, listener);
31664
32184
  if (closer2)
31665
- this.fsw._addPathCloser(path19, closer2);
32185
+ this.fsw._addPathCloser(path20, closer2);
31666
32186
  } else {
31667
32187
  prevStats = newStats2;
31668
32188
  }
@@ -31694,7 +32214,7 @@ var NodeFsHandler = class {
31694
32214
  * @param item basename of this item
31695
32215
  * @returns true if no more processing is needed for this entry.
31696
32216
  */
31697
- async _handleSymlink(entry, directory, path19, item) {
32217
+ async _handleSymlink(entry, directory, path20, item) {
31698
32218
  if (this.fsw.closed) {
31699
32219
  return;
31700
32220
  }
@@ -31704,7 +32224,7 @@ var NodeFsHandler = class {
31704
32224
  this.fsw._incrReadyCount();
31705
32225
  let linkPath;
31706
32226
  try {
31707
- linkPath = await (0, import_promises3.realpath)(path19);
32227
+ linkPath = await (0, import_promises3.realpath)(path20);
31708
32228
  } catch (e) {
31709
32229
  this.fsw._emitReady();
31710
32230
  return true;
@@ -31714,12 +32234,12 @@ var NodeFsHandler = class {
31714
32234
  if (dir.has(item)) {
31715
32235
  if (this.fsw._symlinkPaths.get(full) !== linkPath) {
31716
32236
  this.fsw._symlinkPaths.set(full, linkPath);
31717
- this.fsw._emit(EV.CHANGE, path19, entry.stats);
32237
+ this.fsw._emit(EV.CHANGE, path20, entry.stats);
31718
32238
  }
31719
32239
  } else {
31720
32240
  dir.add(item);
31721
32241
  this.fsw._symlinkPaths.set(full, linkPath);
31722
- this.fsw._emit(EV.ADD, path19, entry.stats);
32242
+ this.fsw._emit(EV.ADD, path20, entry.stats);
31723
32243
  }
31724
32244
  this.fsw._emitReady();
31725
32245
  return true;
@@ -31749,9 +32269,9 @@ var NodeFsHandler = class {
31749
32269
  return;
31750
32270
  }
31751
32271
  const item = entry.path;
31752
- let path19 = sp.join(directory, item);
32272
+ let path20 = sp.join(directory, item);
31753
32273
  current.add(item);
31754
- if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path19, item)) {
32274
+ if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path20, item)) {
31755
32275
  return;
31756
32276
  }
31757
32277
  if (this.fsw.closed) {
@@ -31760,8 +32280,8 @@ var NodeFsHandler = class {
31760
32280
  }
31761
32281
  if (item === target || !target && !previous.has(item)) {
31762
32282
  this.fsw._incrReadyCount();
31763
- path19 = sp.join(dir, sp.relative(dir, path19));
31764
- this._addToNodeFs(path19, initialAdd, wh, depth + 1);
32283
+ path20 = sp.join(dir, sp.relative(dir, path20));
32284
+ this._addToNodeFs(path20, initialAdd, wh, depth + 1);
31765
32285
  }
31766
32286
  }).on(EV.ERROR, this._boundHandleError);
31767
32287
  return new Promise((resolve11, reject) => {
@@ -31830,13 +32350,13 @@ var NodeFsHandler = class {
31830
32350
  * @param depth Child path actually targeted for watch
31831
32351
  * @param target Child path actually targeted for watch
31832
32352
  */
31833
- async _addToNodeFs(path19, initialAdd, priorWh, depth, target) {
32353
+ async _addToNodeFs(path20, initialAdd, priorWh, depth, target) {
31834
32354
  const ready = this.fsw._emitReady;
31835
- if (this.fsw._isIgnored(path19) || this.fsw.closed) {
32355
+ if (this.fsw._isIgnored(path20) || this.fsw.closed) {
31836
32356
  ready();
31837
32357
  return false;
31838
32358
  }
31839
- const wh = this.fsw._getWatchHelpers(path19);
32359
+ const wh = this.fsw._getWatchHelpers(path20);
31840
32360
  if (priorWh) {
31841
32361
  wh.filterPath = (entry) => priorWh.filterPath(entry);
31842
32362
  wh.filterDir = (entry) => priorWh.filterDir(entry);
@@ -31852,8 +32372,8 @@ var NodeFsHandler = class {
31852
32372
  const follow = this.fsw.options.followSymlinks;
31853
32373
  let closer;
31854
32374
  if (stats.isDirectory()) {
31855
- const absPath = sp.resolve(path19);
31856
- const targetPath = follow ? await (0, import_promises3.realpath)(path19) : path19;
32375
+ const absPath = sp.resolve(path20);
32376
+ const targetPath = follow ? await (0, import_promises3.realpath)(path20) : path20;
31857
32377
  if (this.fsw.closed)
31858
32378
  return;
31859
32379
  closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
@@ -31863,29 +32383,29 @@ var NodeFsHandler = class {
31863
32383
  this.fsw._symlinkPaths.set(absPath, targetPath);
31864
32384
  }
31865
32385
  } else if (stats.isSymbolicLink()) {
31866
- const targetPath = follow ? await (0, import_promises3.realpath)(path19) : path19;
32386
+ const targetPath = follow ? await (0, import_promises3.realpath)(path20) : path20;
31867
32387
  if (this.fsw.closed)
31868
32388
  return;
31869
32389
  const parent = sp.dirname(wh.watchPath);
31870
32390
  this.fsw._getWatchedDir(parent).add(wh.watchPath);
31871
32391
  this.fsw._emit(EV.ADD, wh.watchPath, stats);
31872
- closer = await this._handleDir(parent, stats, initialAdd, depth, path19, wh, targetPath);
32392
+ closer = await this._handleDir(parent, stats, initialAdd, depth, path20, wh, targetPath);
31873
32393
  if (this.fsw.closed)
31874
32394
  return;
31875
32395
  if (targetPath !== void 0) {
31876
- this.fsw._symlinkPaths.set(sp.resolve(path19), targetPath);
32396
+ this.fsw._symlinkPaths.set(sp.resolve(path20), targetPath);
31877
32397
  }
31878
32398
  } else {
31879
32399
  closer = this._handleFile(wh.watchPath, stats, initialAdd);
31880
32400
  }
31881
32401
  ready();
31882
32402
  if (closer)
31883
- this.fsw._addPathCloser(path19, closer);
32403
+ this.fsw._addPathCloser(path20, closer);
31884
32404
  return false;
31885
32405
  } catch (error) {
31886
32406
  if (this.fsw._handleError(error)) {
31887
32407
  ready();
31888
- return path19;
32408
+ return path20;
31889
32409
  }
31890
32410
  }
31891
32411
  }
@@ -31928,24 +32448,24 @@ function createPattern(matcher) {
31928
32448
  }
31929
32449
  return () => false;
31930
32450
  }
31931
- function normalizePath(path19) {
31932
- if (typeof path19 !== "string")
32451
+ function normalizePath(path20) {
32452
+ if (typeof path20 !== "string")
31933
32453
  throw new Error("string expected");
31934
- path19 = sp2.normalize(path19);
31935
- path19 = path19.replace(/\\/g, "/");
32454
+ path20 = sp2.normalize(path20);
32455
+ path20 = path20.replace(/\\/g, "/");
31936
32456
  let prepend = false;
31937
- if (path19.startsWith("//"))
32457
+ if (path20.startsWith("//"))
31938
32458
  prepend = true;
31939
- path19 = path19.replace(DOUBLE_SLASH_RE, "/");
32459
+ path20 = path20.replace(DOUBLE_SLASH_RE, "/");
31940
32460
  if (prepend)
31941
- path19 = "/" + path19;
31942
- return path19;
32461
+ path20 = "/" + path20;
32462
+ return path20;
31943
32463
  }
31944
32464
  function matchPatterns(patterns, testString, stats) {
31945
- const path19 = normalizePath(testString);
32465
+ const path20 = normalizePath(testString);
31946
32466
  for (let index = 0; index < patterns.length; index++) {
31947
32467
  const pattern = patterns[index];
31948
- if (pattern(path19, stats)) {
32468
+ if (pattern(path20, stats)) {
31949
32469
  return true;
31950
32470
  }
31951
32471
  }
@@ -31983,19 +32503,19 @@ var toUnix = (string) => {
31983
32503
  }
31984
32504
  return str;
31985
32505
  };
31986
- var normalizePathToUnix = (path19) => toUnix(sp2.normalize(toUnix(path19)));
31987
- var normalizeIgnored = (cwd = "") => (path19) => {
31988
- if (typeof path19 === "string") {
31989
- return normalizePathToUnix(sp2.isAbsolute(path19) ? path19 : sp2.join(cwd, path19));
32506
+ var normalizePathToUnix = (path20) => toUnix(sp2.normalize(toUnix(path20)));
32507
+ var normalizeIgnored = (cwd = "") => (path20) => {
32508
+ if (typeof path20 === "string") {
32509
+ return normalizePathToUnix(sp2.isAbsolute(path20) ? path20 : sp2.join(cwd, path20));
31990
32510
  } else {
31991
- return path19;
32511
+ return path20;
31992
32512
  }
31993
32513
  };
31994
- var getAbsolutePath = (path19, cwd) => {
31995
- if (sp2.isAbsolute(path19)) {
31996
- return path19;
32514
+ var getAbsolutePath = (path20, cwd) => {
32515
+ if (sp2.isAbsolute(path20)) {
32516
+ return path20;
31997
32517
  }
31998
- return sp2.join(cwd, path19);
32518
+ return sp2.join(cwd, path20);
31999
32519
  };
32000
32520
  var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
32001
32521
  var DirEntry = class {
@@ -32060,10 +32580,10 @@ var WatchHelper = class {
32060
32580
  dirParts;
32061
32581
  followSymlinks;
32062
32582
  statMethod;
32063
- constructor(path19, follow, fsw) {
32583
+ constructor(path20, follow, fsw) {
32064
32584
  this.fsw = fsw;
32065
- const watchPath = path19;
32066
- this.path = path19 = path19.replace(REPLACER_RE, "");
32585
+ const watchPath = path20;
32586
+ this.path = path20 = path20.replace(REPLACER_RE, "");
32067
32587
  this.watchPath = watchPath;
32068
32588
  this.fullWatchPath = sp2.resolve(watchPath);
32069
32589
  this.dirParts = [];
@@ -32203,20 +32723,20 @@ var FSWatcher = class extends import_node_events.EventEmitter {
32203
32723
  this._closePromise = void 0;
32204
32724
  let paths = unifyPaths(paths_);
32205
32725
  if (cwd) {
32206
- paths = paths.map((path19) => {
32207
- const absPath = getAbsolutePath(path19, cwd);
32726
+ paths = paths.map((path20) => {
32727
+ const absPath = getAbsolutePath(path20, cwd);
32208
32728
  return absPath;
32209
32729
  });
32210
32730
  }
32211
- paths.forEach((path19) => {
32212
- this._removeIgnoredPath(path19);
32731
+ paths.forEach((path20) => {
32732
+ this._removeIgnoredPath(path20);
32213
32733
  });
32214
32734
  this._userIgnored = void 0;
32215
32735
  if (!this._readyCount)
32216
32736
  this._readyCount = 0;
32217
32737
  this._readyCount += paths.length;
32218
- Promise.all(paths.map(async (path19) => {
32219
- const res = await this._nodeFsHandler._addToNodeFs(path19, !_internal, void 0, 0, _origAdd);
32738
+ Promise.all(paths.map(async (path20) => {
32739
+ const res = await this._nodeFsHandler._addToNodeFs(path20, !_internal, void 0, 0, _origAdd);
32220
32740
  if (res)
32221
32741
  this._emitReady();
32222
32742
  return res;
@@ -32238,17 +32758,17 @@ var FSWatcher = class extends import_node_events.EventEmitter {
32238
32758
  return this;
32239
32759
  const paths = unifyPaths(paths_);
32240
32760
  const { cwd } = this.options;
32241
- paths.forEach((path19) => {
32242
- if (!sp2.isAbsolute(path19) && !this._closers.has(path19)) {
32761
+ paths.forEach((path20) => {
32762
+ if (!sp2.isAbsolute(path20) && !this._closers.has(path20)) {
32243
32763
  if (cwd)
32244
- path19 = sp2.join(cwd, path19);
32245
- path19 = sp2.resolve(path19);
32764
+ path20 = sp2.join(cwd, path20);
32765
+ path20 = sp2.resolve(path20);
32246
32766
  }
32247
- this._closePath(path19);
32248
- this._addIgnoredPath(path19);
32249
- if (this._watched.has(path19)) {
32767
+ this._closePath(path20);
32768
+ this._addIgnoredPath(path20);
32769
+ if (this._watched.has(path20)) {
32250
32770
  this._addIgnoredPath({
32251
- path: path19,
32771
+ path: path20,
32252
32772
  recursive: true
32253
32773
  });
32254
32774
  }
@@ -32312,38 +32832,38 @@ var FSWatcher = class extends import_node_events.EventEmitter {
32312
32832
  * @param stats arguments to be passed with event
32313
32833
  * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
32314
32834
  */
32315
- async _emit(event, path19, stats) {
32835
+ async _emit(event, path20, stats) {
32316
32836
  if (this.closed)
32317
32837
  return;
32318
32838
  const opts = this.options;
32319
32839
  if (isWindows)
32320
- path19 = sp2.normalize(path19);
32840
+ path20 = sp2.normalize(path20);
32321
32841
  if (opts.cwd)
32322
- path19 = sp2.relative(opts.cwd, path19);
32323
- const args = [path19];
32842
+ path20 = sp2.relative(opts.cwd, path20);
32843
+ const args = [path20];
32324
32844
  if (stats != null)
32325
32845
  args.push(stats);
32326
32846
  const awf = opts.awaitWriteFinish;
32327
32847
  let pw;
32328
- if (awf && (pw = this._pendingWrites.get(path19))) {
32848
+ if (awf && (pw = this._pendingWrites.get(path20))) {
32329
32849
  pw.lastChange = /* @__PURE__ */ new Date();
32330
32850
  return this;
32331
32851
  }
32332
32852
  if (opts.atomic) {
32333
32853
  if (event === EVENTS.UNLINK) {
32334
- this._pendingUnlinks.set(path19, [event, ...args]);
32854
+ this._pendingUnlinks.set(path20, [event, ...args]);
32335
32855
  setTimeout(() => {
32336
- this._pendingUnlinks.forEach((entry, path20) => {
32856
+ this._pendingUnlinks.forEach((entry, path21) => {
32337
32857
  this.emit(...entry);
32338
32858
  this.emit(EVENTS.ALL, ...entry);
32339
- this._pendingUnlinks.delete(path20);
32859
+ this._pendingUnlinks.delete(path21);
32340
32860
  });
32341
32861
  }, typeof opts.atomic === "number" ? opts.atomic : 100);
32342
32862
  return this;
32343
32863
  }
32344
- if (event === EVENTS.ADD && this._pendingUnlinks.has(path19)) {
32864
+ if (event === EVENTS.ADD && this._pendingUnlinks.has(path20)) {
32345
32865
  event = EVENTS.CHANGE;
32346
- this._pendingUnlinks.delete(path19);
32866
+ this._pendingUnlinks.delete(path20);
32347
32867
  }
32348
32868
  }
32349
32869
  if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
@@ -32361,16 +32881,16 @@ var FSWatcher = class extends import_node_events.EventEmitter {
32361
32881
  this.emitWithAll(event, args);
32362
32882
  }
32363
32883
  };
32364
- this._awaitWriteFinish(path19, awf.stabilityThreshold, event, awfEmit);
32884
+ this._awaitWriteFinish(path20, awf.stabilityThreshold, event, awfEmit);
32365
32885
  return this;
32366
32886
  }
32367
32887
  if (event === EVENTS.CHANGE) {
32368
- const isThrottled = !this._throttle(EVENTS.CHANGE, path19, 50);
32888
+ const isThrottled = !this._throttle(EVENTS.CHANGE, path20, 50);
32369
32889
  if (isThrottled)
32370
32890
  return this;
32371
32891
  }
32372
32892
  if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
32373
- const fullPath = opts.cwd ? sp2.join(opts.cwd, path19) : path19;
32893
+ const fullPath = opts.cwd ? sp2.join(opts.cwd, path20) : path20;
32374
32894
  let stats2;
32375
32895
  try {
32376
32896
  stats2 = await (0, import_promises4.stat)(fullPath);
@@ -32401,23 +32921,23 @@ var FSWatcher = class extends import_node_events.EventEmitter {
32401
32921
  * @param timeout duration of time to suppress duplicate actions
32402
32922
  * @returns tracking object or false if action should be suppressed
32403
32923
  */
32404
- _throttle(actionType, path19, timeout) {
32924
+ _throttle(actionType, path20, timeout) {
32405
32925
  if (!this._throttled.has(actionType)) {
32406
32926
  this._throttled.set(actionType, /* @__PURE__ */ new Map());
32407
32927
  }
32408
32928
  const action = this._throttled.get(actionType);
32409
32929
  if (!action)
32410
32930
  throw new Error("invalid throttle");
32411
- const actionPath = action.get(path19);
32931
+ const actionPath = action.get(path20);
32412
32932
  if (actionPath) {
32413
32933
  actionPath.count++;
32414
32934
  return false;
32415
32935
  }
32416
32936
  let timeoutObject;
32417
32937
  const clear = () => {
32418
- const item = action.get(path19);
32938
+ const item = action.get(path20);
32419
32939
  const count = item ? item.count : 0;
32420
- action.delete(path19);
32940
+ action.delete(path20);
32421
32941
  clearTimeout(timeoutObject);
32422
32942
  if (item)
32423
32943
  clearTimeout(item.timeoutObject);
@@ -32425,7 +32945,7 @@ var FSWatcher = class extends import_node_events.EventEmitter {
32425
32945
  };
32426
32946
  timeoutObject = setTimeout(clear, timeout);
32427
32947
  const thr = { timeoutObject, clear, count: 0 };
32428
- action.set(path19, thr);
32948
+ action.set(path20, thr);
32429
32949
  return thr;
32430
32950
  }
32431
32951
  _incrReadyCount() {
@@ -32439,44 +32959,44 @@ var FSWatcher = class extends import_node_events.EventEmitter {
32439
32959
  * @param event
32440
32960
  * @param awfEmit Callback to be called when ready for event to be emitted.
32441
32961
  */
32442
- _awaitWriteFinish(path19, threshold, event, awfEmit) {
32962
+ _awaitWriteFinish(path20, threshold, event, awfEmit) {
32443
32963
  const awf = this.options.awaitWriteFinish;
32444
32964
  if (typeof awf !== "object")
32445
32965
  return;
32446
32966
  const pollInterval = awf.pollInterval;
32447
32967
  let timeoutHandler;
32448
- let fullPath = path19;
32449
- if (this.options.cwd && !sp2.isAbsolute(path19)) {
32450
- fullPath = sp2.join(this.options.cwd, path19);
32968
+ let fullPath = path20;
32969
+ if (this.options.cwd && !sp2.isAbsolute(path20)) {
32970
+ fullPath = sp2.join(this.options.cwd, path20);
32451
32971
  }
32452
32972
  const now = /* @__PURE__ */ new Date();
32453
32973
  const writes = this._pendingWrites;
32454
32974
  function awaitWriteFinishFn(prevStat) {
32455
32975
  (0, import_node_fs2.stat)(fullPath, (err, curStat) => {
32456
- if (err || !writes.has(path19)) {
32976
+ if (err || !writes.has(path20)) {
32457
32977
  if (err && err.code !== "ENOENT")
32458
32978
  awfEmit(err);
32459
32979
  return;
32460
32980
  }
32461
32981
  const now2 = Number(/* @__PURE__ */ new Date());
32462
32982
  if (prevStat && curStat.size !== prevStat.size) {
32463
- writes.get(path19).lastChange = now2;
32983
+ writes.get(path20).lastChange = now2;
32464
32984
  }
32465
- const pw = writes.get(path19);
32985
+ const pw = writes.get(path20);
32466
32986
  const df = now2 - pw.lastChange;
32467
32987
  if (df >= threshold) {
32468
- writes.delete(path19);
32988
+ writes.delete(path20);
32469
32989
  awfEmit(void 0, curStat);
32470
32990
  } else {
32471
32991
  timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
32472
32992
  }
32473
32993
  });
32474
32994
  }
32475
- if (!writes.has(path19)) {
32476
- writes.set(path19, {
32995
+ if (!writes.has(path20)) {
32996
+ writes.set(path20, {
32477
32997
  lastChange: now,
32478
32998
  cancelWait: () => {
32479
- writes.delete(path19);
32999
+ writes.delete(path20);
32480
33000
  clearTimeout(timeoutHandler);
32481
33001
  return event;
32482
33002
  }
@@ -32487,8 +33007,8 @@ var FSWatcher = class extends import_node_events.EventEmitter {
32487
33007
  /**
32488
33008
  * Determines whether user has asked to ignore this path.
32489
33009
  */
32490
- _isIgnored(path19, stats) {
32491
- if (this.options.atomic && DOT_RE.test(path19))
33010
+ _isIgnored(path20, stats) {
33011
+ if (this.options.atomic && DOT_RE.test(path20))
32492
33012
  return true;
32493
33013
  if (!this._userIgnored) {
32494
33014
  const { cwd } = this.options;
@@ -32498,17 +33018,17 @@ var FSWatcher = class extends import_node_events.EventEmitter {
32498
33018
  const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
32499
33019
  this._userIgnored = anymatch(list, void 0);
32500
33020
  }
32501
- return this._userIgnored(path19, stats);
33021
+ return this._userIgnored(path20, stats);
32502
33022
  }
32503
- _isntIgnored(path19, stat10) {
32504
- return !this._isIgnored(path19, stat10);
33023
+ _isntIgnored(path20, stat10) {
33024
+ return !this._isIgnored(path20, stat10);
32505
33025
  }
32506
33026
  /**
32507
33027
  * Provides a set of common helpers and properties relating to symlink handling.
32508
33028
  * @param path file or directory pattern being watched
32509
33029
  */
32510
- _getWatchHelpers(path19) {
32511
- return new WatchHelper(path19, this.options.followSymlinks, this);
33030
+ _getWatchHelpers(path20) {
33031
+ return new WatchHelper(path20, this.options.followSymlinks, this);
32512
33032
  }
32513
33033
  // Directory helpers
32514
33034
  // -----------------
@@ -32540,63 +33060,63 @@ var FSWatcher = class extends import_node_events.EventEmitter {
32540
33060
  * @param item base path of item/directory
32541
33061
  */
32542
33062
  _remove(directory, item, isDirectory) {
32543
- const path19 = sp2.join(directory, item);
32544
- const fullPath = sp2.resolve(path19);
32545
- isDirectory = isDirectory != null ? isDirectory : this._watched.has(path19) || this._watched.has(fullPath);
32546
- if (!this._throttle("remove", path19, 100))
33063
+ const path20 = sp2.join(directory, item);
33064
+ const fullPath = sp2.resolve(path20);
33065
+ isDirectory = isDirectory != null ? isDirectory : this._watched.has(path20) || this._watched.has(fullPath);
33066
+ if (!this._throttle("remove", path20, 100))
32547
33067
  return;
32548
33068
  if (!isDirectory && this._watched.size === 1) {
32549
33069
  this.add(directory, item, true);
32550
33070
  }
32551
- const wp = this._getWatchedDir(path19);
33071
+ const wp = this._getWatchedDir(path20);
32552
33072
  const nestedDirectoryChildren = wp.getChildren();
32553
- nestedDirectoryChildren.forEach((nested) => this._remove(path19, nested));
33073
+ nestedDirectoryChildren.forEach((nested) => this._remove(path20, nested));
32554
33074
  const parent = this._getWatchedDir(directory);
32555
33075
  const wasTracked = parent.has(item);
32556
33076
  parent.remove(item);
32557
33077
  if (this._symlinkPaths.has(fullPath)) {
32558
33078
  this._symlinkPaths.delete(fullPath);
32559
33079
  }
32560
- let relPath = path19;
33080
+ let relPath = path20;
32561
33081
  if (this.options.cwd)
32562
- relPath = sp2.relative(this.options.cwd, path19);
33082
+ relPath = sp2.relative(this.options.cwd, path20);
32563
33083
  if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
32564
33084
  const event = this._pendingWrites.get(relPath).cancelWait();
32565
33085
  if (event === EVENTS.ADD)
32566
33086
  return;
32567
33087
  }
32568
- this._watched.delete(path19);
33088
+ this._watched.delete(path20);
32569
33089
  this._watched.delete(fullPath);
32570
33090
  const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
32571
- if (wasTracked && !this._isIgnored(path19))
32572
- this._emit(eventName, path19);
32573
- this._closePath(path19);
33091
+ if (wasTracked && !this._isIgnored(path20))
33092
+ this._emit(eventName, path20);
33093
+ this._closePath(path20);
32574
33094
  }
32575
33095
  /**
32576
33096
  * Closes all watchers for a path
32577
33097
  */
32578
- _closePath(path19) {
32579
- this._closeFile(path19);
32580
- const dir = sp2.dirname(path19);
32581
- this._getWatchedDir(dir).remove(sp2.basename(path19));
33098
+ _closePath(path20) {
33099
+ this._closeFile(path20);
33100
+ const dir = sp2.dirname(path20);
33101
+ this._getWatchedDir(dir).remove(sp2.basename(path20));
32582
33102
  }
32583
33103
  /**
32584
33104
  * Closes only file-specific watchers
32585
33105
  */
32586
- _closeFile(path19) {
32587
- const closers = this._closers.get(path19);
33106
+ _closeFile(path20) {
33107
+ const closers = this._closers.get(path20);
32588
33108
  if (!closers)
32589
33109
  return;
32590
33110
  closers.forEach((closer) => closer());
32591
- this._closers.delete(path19);
33111
+ this._closers.delete(path20);
32592
33112
  }
32593
- _addPathCloser(path19, closer) {
33113
+ _addPathCloser(path20, closer) {
32594
33114
  if (!closer)
32595
33115
  return;
32596
- let list = this._closers.get(path19);
33116
+ let list = this._closers.get(path20);
32597
33117
  if (!list) {
32598
33118
  list = [];
32599
- this._closers.set(path19, list);
33119
+ this._closers.set(path20, list);
32600
33120
  }
32601
33121
  list.push(closer);
32602
33122
  }
@@ -32629,7 +33149,7 @@ var chokidar_default = { watch, FSWatcher };
32629
33149
  var import_node_cron = __toESM(require_node_cron());
32630
33150
 
32631
33151
  // src/agent/createAgent.ts
32632
- var import_node_crypto13 = require("node:crypto");
33152
+ var import_node_crypto14 = require("node:crypto");
32633
33153
  var import_node_fs7 = require("node:fs");
32634
33154
 
32635
33155
  // src/background/BackgroundManager.ts
@@ -34060,12 +34580,12 @@ function encodeURIPath(str) {
34060
34580
  return str.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g, encodeURIComponent);
34061
34581
  }
34062
34582
  var EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null));
34063
- var createPathTagFunction = (pathEncoder = encodeURIPath) => function path19(statics, ...params) {
34583
+ var createPathTagFunction = (pathEncoder = encodeURIPath) => function path20(statics, ...params) {
34064
34584
  if (statics.length === 1)
34065
34585
  return statics[0];
34066
34586
  let postPath = false;
34067
34587
  const invalidSegments = [];
34068
- const path20 = statics.reduce((previousValue, currentValue, index) => {
34588
+ const path21 = statics.reduce((previousValue, currentValue, index) => {
34069
34589
  if (/[?#]/.test(currentValue)) {
34070
34590
  postPath = true;
34071
34591
  }
@@ -34082,7 +34602,7 @@ var createPathTagFunction = (pathEncoder = encodeURIPath) => function path19(sta
34082
34602
  }
34083
34603
  return previousValue + currentValue + (index === params.length ? "" : encoded);
34084
34604
  }, "");
34085
- const pathOnly = path20.split(/[?#]/, 1)[0];
34605
+ const pathOnly = path21.split(/[?#]/, 1)[0];
34086
34606
  const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi;
34087
34607
  let match2;
34088
34608
  while ((match2 = invalidSegmentPattern.exec(pathOnly)) !== null) {
@@ -34103,10 +34623,10 @@ var createPathTagFunction = (pathEncoder = encodeURIPath) => function path19(sta
34103
34623
  }, "");
34104
34624
  throw new AnthropicError(`Path parameters result in path with invalid segments:
34105
34625
  ${invalidSegments.map((e) => e.error).join("\n")}
34106
- ${path20}
34626
+ ${path21}
34107
34627
  ${underline}`);
34108
34628
  }
34109
- return path20;
34629
+ return path21;
34110
34630
  };
34111
34631
  var path4 = /* @__PURE__ */ createPathTagFunction(encodeURIPath);
34112
34632
 
@@ -37217,9 +37737,9 @@ var BaseAnthropic = class {
37217
37737
  makeStatusError(status, error, message, headers) {
37218
37738
  return APIError.generate(status, error, message, headers);
37219
37739
  }
37220
- buildURL(path19, query, defaultBaseURL) {
37740
+ buildURL(path20, query, defaultBaseURL) {
37221
37741
  const baseURL = !__classPrivateFieldGet(this, _BaseAnthropic_instances, "m", _BaseAnthropic_baseURLOverridden).call(this) && defaultBaseURL || this.baseURL;
37222
- const url = isAbsoluteURL(path19) ? new URL(path19) : new URL(baseURL + (baseURL.endsWith("/") && path19.startsWith("/") ? path19.slice(1) : path19));
37742
+ const url = isAbsoluteURL(path20) ? new URL(path20) : new URL(baseURL + (baseURL.endsWith("/") && path20.startsWith("/") ? path20.slice(1) : path20));
37223
37743
  const defaultQuery = this.defaultQuery();
37224
37744
  if (!isEmptyObj(defaultQuery)) {
37225
37745
  query = { ...defaultQuery, ...query };
@@ -37250,24 +37770,24 @@ var BaseAnthropic = class {
37250
37770
  */
37251
37771
  async prepareRequest(request, { url, options }) {
37252
37772
  }
37253
- get(path19, opts) {
37254
- return this.methodRequest("get", path19, opts);
37773
+ get(path20, opts) {
37774
+ return this.methodRequest("get", path20, opts);
37255
37775
  }
37256
- post(path19, opts) {
37257
- return this.methodRequest("post", path19, opts);
37776
+ post(path20, opts) {
37777
+ return this.methodRequest("post", path20, opts);
37258
37778
  }
37259
- patch(path19, opts) {
37260
- return this.methodRequest("patch", path19, opts);
37779
+ patch(path20, opts) {
37780
+ return this.methodRequest("patch", path20, opts);
37261
37781
  }
37262
- put(path19, opts) {
37263
- return this.methodRequest("put", path19, opts);
37782
+ put(path20, opts) {
37783
+ return this.methodRequest("put", path20, opts);
37264
37784
  }
37265
- delete(path19, opts) {
37266
- return this.methodRequest("delete", path19, opts);
37785
+ delete(path20, opts) {
37786
+ return this.methodRequest("delete", path20, opts);
37267
37787
  }
37268
- methodRequest(method, path19, opts) {
37788
+ methodRequest(method, path20, opts) {
37269
37789
  return this.request(Promise.resolve(opts).then((opts2) => {
37270
- return { method, path: path19, ...opts2 };
37790
+ return { method, path: path20, ...opts2 };
37271
37791
  }));
37272
37792
  }
37273
37793
  request(options, remainingRetries = null) {
@@ -37371,8 +37891,8 @@ var BaseAnthropic = class {
37371
37891
  }));
37372
37892
  return { response, options, controller, requestLogID, retryOfRequestLogID, startTime: startTime2 };
37373
37893
  }
37374
- getAPIList(path19, Page2, opts) {
37375
- return this.requestAPIList(Page2, opts && "then" in opts ? opts.then((opts2) => ({ method: "get", path: path19, ...opts2 })) : { method: "get", path: path19, ...opts });
37894
+ getAPIList(path20, Page2, opts) {
37895
+ return this.requestAPIList(Page2, opts && "then" in opts ? opts.then((opts2) => ({ method: "get", path: path20, ...opts2 })) : { method: "get", path: path20, ...opts });
37376
37896
  }
37377
37897
  requestAPIList(Page2, options) {
37378
37898
  const request = this.makeRequest(options, null, void 0);
@@ -37460,8 +37980,8 @@ var BaseAnthropic = class {
37460
37980
  }
37461
37981
  async buildRequest(inputOptions, { retryCount = 0 } = {}) {
37462
37982
  const options = { ...inputOptions };
37463
- const { method, path: path19, query, defaultBaseURL } = options;
37464
- const url = this.buildURL(path19, query, defaultBaseURL);
37983
+ const { method, path: path20, query, defaultBaseURL } = options;
37984
+ const url = this.buildURL(path20, query, defaultBaseURL);
37465
37985
  if ("timeout" in options)
37466
37986
  validatePositiveInteger("timeout", options.timeout);
37467
37987
  options.timeout = options.timeout ?? this.timeout;
@@ -37830,12 +38350,12 @@ var toInternalContent = (sdkContent) => {
37830
38350
 
37831
38351
  // src/storage/FileStorage.ts
37832
38352
  var import_promises5 = require("node:fs/promises");
37833
- var import_node_path3 = __toESM(require("node:path"));
38353
+ var import_node_path4 = __toESM(require("node:path"));
37834
38354
  var encodeKey = (key) => Buffer.from(key).toString("base64url");
37835
38355
  var normalizePrefix = (prefix) => prefix.replace(/[:/\\]+$/g, "") || "agent";
37836
38356
  var createFileStorage = (options = {}) => {
37837
- const rootDir = import_node_path3.default.join(options.rootDir || getDuclawDataDir(), "kv", normalizePrefix(options.prefix || "agent"));
37838
- const fileForKey = (key) => import_node_path3.default.join(rootDir, `${encodeKey(key)}.json`);
38357
+ const rootDir = import_node_path4.default.join(options.rootDir || getDuclawDataDir(), "kv", normalizePrefix(options.prefix || "agent"));
38358
+ const fileForKey = (key) => import_node_path4.default.join(rootDir, `${encodeKey(key)}.json`);
37839
38359
  return {
37840
38360
  async get(key) {
37841
38361
  try {
@@ -38814,14 +39334,14 @@ var taskUpdate = {
38814
39334
  };
38815
39335
 
38816
39336
  // src/tools/tools/Glob.ts
38817
- var import_node_path5 = require("node:path");
39337
+ var import_node_path6 = require("node:path");
38818
39338
  var import_promises6 = require("node:fs/promises");
38819
39339
 
38820
39340
  // src/tools/utils/workspaceGuard.ts
38821
- var import_node_path4 = require("node:path");
39341
+ var import_node_path5 = require("node:path");
38822
39342
  var validateWorkspacePath = (filePath, workspacePath) => {
38823
- const resolved = (0, import_node_path4.isAbsolute)(filePath) ? (0, import_node_path4.resolve)(filePath) : (0, import_node_path4.resolve)(process.cwd(), filePath);
38824
- const workspace = (0, import_node_path4.resolve)(workspacePath);
39343
+ const resolved = (0, import_node_path5.isAbsolute)(filePath) ? (0, import_node_path5.resolve)(filePath) : (0, import_node_path5.resolve)(process.cwd(), filePath);
39344
+ const workspace = (0, import_node_path5.resolve)(workspacePath);
38825
39345
  if (!resolved.startsWith(workspace + "/") && resolved !== workspace) {
38826
39346
  return `\u8DEF\u5F84 ${resolved} \u4E0D\u5728\u5DE5\u4F5C\u533A ${workspace} \u8303\u56F4\u5185\uFF0C\u64CD\u4F5C\u88AB\u62D2\u7EDD\u3002\u8BF7\u5C06\u6587\u4EF6\u653E\u5728\u5DE5\u4F5C\u533A\u76EE\u5F55\u4E0B\u3002`;
38827
39347
  }
@@ -38879,7 +39399,7 @@ var globTool = {
38879
39399
  const pattern = input.pattern;
38880
39400
  const effectiveCwd = getEffectiveCwd(userRequest);
38881
39401
  const searchDir = input.path || effectiveCwd;
38882
- const resolvedDir = (0, import_node_path5.isAbsolute)(searchDir) ? searchDir : (0, import_node_path5.resolve)(effectiveCwd, searchDir);
39402
+ const resolvedDir = (0, import_node_path6.isAbsolute)(searchDir) ? searchDir : (0, import_node_path6.resolve)(effectiveCwd, searchDir);
38883
39403
  const LIMIT = 100;
38884
39404
  const regex = globToRegex(pattern);
38885
39405
  const files = [];
@@ -38893,7 +39413,7 @@ var globTool = {
38893
39413
  for (const entry of entries) {
38894
39414
  const normalized = entry.replace(/\\/g, "/");
38895
39415
  if (!regex.test(normalized)) continue;
38896
- const fullPath = (0, import_node_path5.resolve)(resolvedDir, entry);
39416
+ const fullPath = (0, import_node_path6.resolve)(resolvedDir, entry);
38897
39417
  try {
38898
39418
  const s = await (0, import_promises6.stat)(fullPath);
38899
39419
  if (!s.isFile()) continue;
@@ -38916,7 +39436,7 @@ var globTool = {
38916
39436
  };
38917
39437
 
38918
39438
  // src/tools/tools/Grep.ts
38919
- var import_node_path6 = require("node:path");
39439
+ var import_node_path7 = require("node:path");
38920
39440
  var import_promises7 = require("node:fs/promises");
38921
39441
  var MAX_LINE_LENGTH = 2e3;
38922
39442
  var DESCRIPTION2 = `
@@ -38989,7 +39509,7 @@ var grepTool = {
38989
39509
  const effectiveCwd = getEffectiveCwd(userRequest);
38990
39510
  const searchDir = input.path || effectiveCwd;
38991
39511
  const includePattern = input.include;
38992
- const resolvedDir = (0, import_node_path6.isAbsolute)(searchDir) ? searchDir : (0, import_node_path6.resolve)(effectiveCwd, searchDir);
39512
+ const resolvedDir = (0, import_node_path7.isAbsolute)(searchDir) ? searchDir : (0, import_node_path7.resolve)(effectiveCwd, searchDir);
38993
39513
  let regex;
38994
39514
  try {
38995
39515
  regex = new RegExp(pattern);
@@ -39013,7 +39533,7 @@ var grepTool = {
39013
39533
  const fileName = normalized.split("/").pop() || normalized;
39014
39534
  if (!includeRegex.test(fileName)) continue;
39015
39535
  }
39016
- const fullPath = (0, import_node_path6.resolve)(resolvedDir, entry);
39536
+ const fullPath = (0, import_node_path7.resolve)(resolvedDir, entry);
39017
39537
  let s;
39018
39538
  try {
39019
39539
  s = await (0, import_promises7.stat)(fullPath);
@@ -39156,7 +39676,7 @@ var codeSearchTool = {
39156
39676
  };
39157
39677
 
39158
39678
  // src/tools/tools/Read.ts
39159
- var import_node_path7 = require("node:path");
39679
+ var import_node_path8 = require("node:path");
39160
39680
  var import_promises8 = require("node:fs/promises");
39161
39681
  var DEFAULT_READ_LIMIT = 2e3;
39162
39682
  var MAX_LINE_LENGTH2 = 2e3;
@@ -39217,7 +39737,7 @@ var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
39217
39737
  ".heif"
39218
39738
  ]);
39219
39739
  async function isBinaryFile(filePath) {
39220
- const ext = (0, import_node_path7.extname)(filePath).toLowerCase();
39740
+ const ext = (0, import_node_path8.extname)(filePath).toLowerCase();
39221
39741
  if (BINARY_EXTENSIONS.has(ext)) return true;
39222
39742
  let buffer;
39223
39743
  try {
@@ -39259,20 +39779,20 @@ var readTool = {
39259
39779
  },
39260
39780
  async execute(input, userRequest) {
39261
39781
  let filePath = input.filePath;
39262
- if (!(0, import_node_path7.isAbsolute)(filePath)) {
39263
- filePath = (0, import_node_path7.resolve)(getEffectiveCwd(userRequest), filePath);
39782
+ if (!(0, import_node_path8.isAbsolute)(filePath)) {
39783
+ filePath = (0, import_node_path8.resolve)(getEffectiveCwd(userRequest), filePath);
39264
39784
  }
39265
39785
  let fileStat;
39266
39786
  try {
39267
39787
  fileStat = await (0, import_promises8.stat)(filePath);
39268
39788
  } catch {
39269
39789
  try {
39270
- const dir = (0, import_node_path7.dirname)(filePath);
39271
- const base = (0, import_node_path7.basename)(filePath);
39790
+ const dir = (0, import_node_path8.dirname)(filePath);
39791
+ const base = (0, import_node_path8.basename)(filePath);
39272
39792
  const dirEntries = await (0, import_promises8.readdir)(dir);
39273
39793
  const suggestions = dirEntries.filter(
39274
39794
  (entry) => entry.toLowerCase().includes(base.toLowerCase()) || base.toLowerCase().includes(entry.toLowerCase())
39275
- ).map((entry) => (0, import_node_path7.join)(dir, entry)).slice(0, 3);
39795
+ ).map((entry) => (0, import_node_path8.join)(dir, entry)).slice(0, 3);
39276
39796
  if (suggestions.length > 0) {
39277
39797
  return `File not found: ${filePath}
39278
39798
 
@@ -39289,7 +39809,7 @@ ${suggestions.join("\n")}`;
39289
39809
  if (fileStat.size === 0) {
39290
39810
  return `<system-reminder>File exists but has empty contents: ${filePath}</system-reminder>`;
39291
39811
  }
39292
- const ext = (0, import_node_path7.extname)(filePath).toLowerCase();
39812
+ const ext = (0, import_node_path8.extname)(filePath).toLowerCase();
39293
39813
  if (IMAGE_EXTENSIONS.has(ext)) {
39294
39814
  return `Cannot read image file with this tool. Use the image_understand tool instead to analyze image: ${filePath}`;
39295
39815
  }
@@ -39463,7 +39983,7 @@ var webSearchTool = {
39463
39983
  };
39464
39984
 
39465
39985
  // src/tools/tools/Write.ts
39466
- var import_node_path8 = require("node:path");
39986
+ var import_node_path9 = require("node:path");
39467
39987
  var import_promises9 = require("node:fs/promises");
39468
39988
 
39469
39989
  // node_modules/.pnpm/diff@8.0.3/node_modules/diff/libesm/diff/base.js
@@ -39566,16 +40086,16 @@ var Diff = class {
39566
40086
  }
39567
40087
  }
39568
40088
  }
39569
- addToPath(path19, added, removed, oldPosInc, options) {
39570
- const last = path19.lastComponent;
40089
+ addToPath(path20, added, removed, oldPosInc, options) {
40090
+ const last = path20.lastComponent;
39571
40091
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
39572
40092
  return {
39573
- oldPos: path19.oldPos + oldPosInc,
40093
+ oldPos: path20.oldPos + oldPosInc,
39574
40094
  lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
39575
40095
  };
39576
40096
  } else {
39577
40097
  return {
39578
- oldPos: path19.oldPos + oldPosInc,
40098
+ oldPos: path20.oldPos + oldPosInc,
39579
40099
  lastComponent: { count: 1, added, removed, previousComponent: last }
39580
40100
  };
39581
40101
  }
@@ -39928,8 +40448,8 @@ var writeTool = {
39928
40448
  async execute(input, userRequest) {
39929
40449
  let filePath = input.filePath;
39930
40450
  const content = input.content;
39931
- if (!(0, import_node_path8.isAbsolute)(filePath)) {
39932
- filePath = (0, import_node_path8.resolve)(getEffectiveCwd(userRequest), filePath);
40451
+ if (!(0, import_node_path9.isAbsolute)(filePath)) {
40452
+ filePath = (0, import_node_path9.resolve)(getEffectiveCwd(userRequest), filePath);
39933
40453
  }
39934
40454
  if (userRequest?.workspacePath) {
39935
40455
  const rejection = validateWorkspacePath(filePath, userRequest.workspacePath);
@@ -39945,7 +40465,7 @@ var writeTool = {
39945
40465
  }
39946
40466
  } catch {
39947
40467
  }
39948
- await (0, import_promises9.mkdir)((0, import_node_path8.dirname)(filePath), { recursive: true });
40468
+ await (0, import_promises9.mkdir)((0, import_node_path9.dirname)(filePath), { recursive: true });
39949
40469
  await (0, import_promises9.writeFile)(filePath, content, "utf-8");
39950
40470
  let output = `\u6587\u4EF6\u5199\u5165\u6210\u529F: ${filePath}`;
39951
40471
  if (exists) {
@@ -39967,7 +40487,7 @@ ${trimmed}${suffix}
39967
40487
  };
39968
40488
 
39969
40489
  // src/tools/tools/Edit.ts
39970
- var import_node_path9 = require("node:path");
40490
+ var import_node_path10 = require("node:path");
39971
40491
  var import_promises10 = require("node:fs/promises");
39972
40492
  var DESCRIPTION7 = `Performs exact string replacements in files.
39973
40493
 
@@ -40366,8 +40886,8 @@ var editTool = {
40366
40886
  if (oldString === newString) {
40367
40887
  return "\u9519\u8BEF: oldString \u548C newString \u5FC5\u987B\u4E0D\u540C";
40368
40888
  }
40369
- if (!(0, import_node_path9.isAbsolute)(filePath)) {
40370
- filePath = (0, import_node_path9.resolve)(getEffectiveCwd(userRequest), filePath);
40889
+ if (!(0, import_node_path10.isAbsolute)(filePath)) {
40890
+ filePath = (0, import_node_path10.resolve)(getEffectiveCwd(userRequest), filePath);
40371
40891
  }
40372
40892
  if (userRequest?.workspacePath) {
40373
40893
  const rejection = validateWorkspacePath(filePath, userRequest.workspacePath);
@@ -40750,7 +41270,7 @@ var isToolUseBlock = (block) => block.type === "tool_use";
40750
41270
  var extractText = (blocks) => blocks.filter(isTextBlock).map((b) => b.text).join("\n");
40751
41271
 
40752
41272
  // src/tools/tools/ImageUnderstandMetering.ts
40753
- var import_node_crypto = require("node:crypto");
41273
+ var import_node_crypto2 = require("node:crypto");
40754
41274
  var ImageUnderstandMeteringError = class extends Error {
40755
41275
  constructor(message, statusCode, meteringStatus) {
40756
41276
  super(message);
@@ -40840,7 +41360,7 @@ function inferImageProvider(baseUrl) {
40840
41360
  }
40841
41361
  }
40842
41362
  function fingerprintImageSource(imageSource) {
40843
- return (0, import_node_crypto.createHash)("sha256").update(imageSource).digest("hex");
41363
+ return (0, import_node_crypto2.createHash)("sha256").update(imageSource).digest("hex");
40844
41364
  }
40845
41365
  function imageSourceKind(imageSource) {
40846
41366
  if (imageSource.startsWith("http://") || imageSource.startsWith("https://")) return "url";
@@ -41407,218 +41927,10 @@ var goalDelete = {
41407
41927
  };
41408
41928
 
41409
41929
  // src/tools/tools/department/DepartmentCreate.ts
41410
- var import_node_crypto6 = require("node:crypto");
41930
+ var import_node_crypto7 = require("node:crypto");
41411
41931
 
41412
41932
  // src/department/mailbox/mailbox.ts
41413
- var import_node_crypto5 = require("node:crypto");
41414
-
41415
- // src/db/createDB.ts
41416
- var import_better_sqlite3 = __toESM(require("better-sqlite3"));
41417
- var import_node_path10 = require("node:path");
41418
- var _db = null;
41419
- var _tableEnsured = false;
41420
- var createSqliteDB = () => {
41421
- if (!_db) {
41422
- const dbDir = getDuclawDataDir();
41423
- _db = new import_better_sqlite3.default((0, import_node_path10.join)(dbDir, "duclaw.db"));
41424
- _db.pragma("journal_mode = WAL");
41425
- }
41426
- if (!_tableEnsured) {
41427
- _tableEnsured = true;
41428
- _ensure_table_exist();
41429
- }
41430
- return _db;
41431
- };
41432
- var _ensure_table_exist = () => {
41433
- create_workspace_table();
41434
- create_mailbox_table();
41435
- create_mailbox_events_table();
41436
- create_ceo_followups_table();
41437
- create_agent_events_table();
41438
- };
41439
- var create_workspace_table = () => {
41440
- const db3 = createSqliteDB();
41441
- db3.exec(`
41442
- CREATE TABLE IF NOT EXISTS workspace (
41443
- id TEXT PRIMARY KEY,
41444
- team_name TEXT NOT NULL,
41445
- teammate_name TEXT,
41446
- team_workpath TEXT NOT NULL,
41447
- created_at INTEGER DEFAULT (strftime('%s', 'now')),
41448
- updated_at INTEGER DEFAULT (strftime('%s', 'now'))
41449
- );
41450
-
41451
- CREATE INDEX IF NOT EXISTS idx_team ON workspace(team_name);
41452
- `);
41453
- };
41454
- var create_mailbox_table = () => {
41455
- const db3 = createSqliteDB();
41456
- db3.exec(`
41457
- CREATE TABLE IF NOT EXISTS mailbox (
41458
- id TEXT PRIMARY KEY,
41459
- to_mailbox_id TEXT NOT NULL,
41460
- from_mailbox_id TEXT NOT NULL,
41461
- content TEXT NOT NULL,
41462
- status TEXT DEFAULT ('pending') NOT NULL,
41463
- origin_user_id TEXT,
41464
- origin_platform TEXT,
41465
- thread_id TEXT,
41466
- parent_message_id TEXT,
41467
- work_item_id TEXT,
41468
- work_item_role TEXT,
41469
- upstream_message_id TEXT,
41470
- send_time INTEGER DEFAULT ((strftime('%s', 'now')) * 1000),
41471
- created_at INTEGER DEFAULT ((strftime('%s', 'now')) * 1000),
41472
- updated_at INTEGER DEFAULT ((strftime('%s', 'now')) * 1000)
41473
- );
41474
-
41475
- CREATE INDEX IF NOT EXISTS idx_mailbox ON mailbox(to_mailbox_id);
41476
- `);
41477
- try {
41478
- db3.exec(`ALTER TABLE mailbox ADD COLUMN origin_user_id TEXT`);
41479
- } catch (_) {
41480
- }
41481
- try {
41482
- db3.exec(`ALTER TABLE mailbox ADD COLUMN origin_platform TEXT`);
41483
- } catch (_) {
41484
- }
41485
- try {
41486
- db3.exec(`ALTER TABLE mailbox ADD COLUMN thread_id TEXT`);
41487
- } catch (_) {
41488
- }
41489
- try {
41490
- db3.exec(`ALTER TABLE mailbox ADD COLUMN parent_message_id TEXT`);
41491
- } catch (_) {
41492
- }
41493
- try {
41494
- db3.exec(`ALTER TABLE mailbox ADD COLUMN work_item_id TEXT`);
41495
- } catch (_) {
41496
- }
41497
- try {
41498
- db3.exec(`ALTER TABLE mailbox ADD COLUMN work_item_role TEXT`);
41499
- } catch (_) {
41500
- }
41501
- try {
41502
- db3.exec(`ALTER TABLE mailbox ADD COLUMN upstream_message_id TEXT`);
41503
- } catch (_) {
41504
- }
41505
- const columns = db3.prepare(`PRAGMA table_info(mailbox)`).all();
41506
- const hasThreadId = columns.some((column) => column.name === "thread_id");
41507
- const hasParentMessageId = columns.some((column) => column.name === "parent_message_id");
41508
- const hasWorkItemId = columns.some((column) => column.name === "work_item_id");
41509
- const hasUpstreamMessageId = columns.some((column) => column.name === "upstream_message_id");
41510
- if (hasThreadId) {
41511
- db3.exec(`
41512
- CREATE INDEX IF NOT EXISTS idx_mailbox_thread
41513
- ON mailbox(thread_id, send_time DESC)
41514
- `);
41515
- db3.exec(`UPDATE mailbox SET thread_id = id WHERE thread_id IS NULL`);
41516
- }
41517
- if (hasParentMessageId) {
41518
- db3.exec(`
41519
- CREATE INDEX IF NOT EXISTS idx_mailbox_parent
41520
- ON mailbox(parent_message_id)
41521
- `);
41522
- }
41523
- if (hasWorkItemId) {
41524
- db3.exec(`
41525
- CREATE INDEX IF NOT EXISTS idx_mailbox_work_item
41526
- ON mailbox(work_item_id, send_time DESC)
41527
- `);
41528
- }
41529
- if (hasUpstreamMessageId) {
41530
- db3.exec(`
41531
- CREATE INDEX IF NOT EXISTS idx_mailbox_upstream
41532
- ON mailbox(upstream_message_id)
41533
- `);
41534
- }
41535
- };
41536
- var create_mailbox_events_table = () => {
41537
- const db3 = createSqliteDB();
41538
- db3.exec(`
41539
- CREATE TABLE IF NOT EXISTS mailbox_events (
41540
- id TEXT PRIMARY KEY,
41541
- message_id TEXT,
41542
- mailbox_id TEXT NOT NULL,
41543
- actor_mailbox_id TEXT,
41544
- counterpart_mailbox_id TEXT,
41545
- event_type TEXT NOT NULL,
41546
- detail_json TEXT,
41547
- created_at INTEGER DEFAULT ((strftime('%s', 'now')) * 1000)
41548
- );
41549
-
41550
- CREATE INDEX IF NOT EXISTS idx_mailbox_events_mailbox_created
41551
- ON mailbox_events(mailbox_id, created_at DESC);
41552
-
41553
- CREATE INDEX IF NOT EXISTS idx_mailbox_events_message_created
41554
- ON mailbox_events(message_id, created_at DESC);
41555
- `);
41556
- try {
41557
- db3.exec(`ALTER TABLE mailbox_events ADD COLUMN actor_mailbox_id TEXT`);
41558
- } catch (_) {
41559
- }
41560
- try {
41561
- db3.exec(`ALTER TABLE mailbox_events ADD COLUMN counterpart_mailbox_id TEXT`);
41562
- } catch (_) {
41563
- }
41564
- try {
41565
- db3.exec(`ALTER TABLE mailbox_events ADD COLUMN detail_json TEXT`);
41566
- } catch (_) {
41567
- }
41568
- };
41569
- var create_ceo_followups_table = () => {
41570
- const db3 = createSqliteDB();
41571
- db3.exec(`
41572
- CREATE TABLE IF NOT EXISTS ceo_followups (
41573
- id TEXT PRIMARY KEY,
41574
- source_message_id TEXT NOT NULL UNIQUE,
41575
- status TEXT DEFAULT ('pending') NOT NULL,
41576
- origin_user_id TEXT NOT NULL,
41577
- origin_platform TEXT NOT NULL,
41578
- from_mailbox_id TEXT NOT NULL,
41579
- thread_id TEXT,
41580
- parent_message_id TEXT,
41581
- work_item_id TEXT,
41582
- content TEXT NOT NULL,
41583
- attempts INTEGER DEFAULT 0 NOT NULL,
41584
- last_error TEXT,
41585
- created_at INTEGER DEFAULT ((strftime('%s', 'now')) * 1000),
41586
- updated_at INTEGER DEFAULT ((strftime('%s', 'now')) * 1000),
41587
- completed_at INTEGER
41588
- );
41589
-
41590
- CREATE INDEX IF NOT EXISTS idx_ceo_followups_status_created
41591
- ON ceo_followups(status, created_at);
41592
-
41593
- CREATE INDEX IF NOT EXISTS idx_ceo_followups_user_status
41594
- ON ceo_followups(origin_user_id, status, created_at);
41595
- `);
41596
- };
41597
- var create_agent_events_table = () => {
41598
- const db3 = createSqliteDB();
41599
- db3.exec(`
41600
- CREATE TABLE IF NOT EXISTS agent_events (
41601
- id TEXT PRIMARY KEY,
41602
- user_id TEXT NOT NULL,
41603
- type TEXT NOT NULL,
41604
- source TEXT NOT NULL,
41605
- source_id TEXT NOT NULL,
41606
- status TEXT DEFAULT ('pending') NOT NULL,
41607
- payload_json TEXT NOT NULL,
41608
- created_at INTEGER DEFAULT ((strftime('%s', 'now')) * 1000),
41609
- injected_at INTEGER,
41610
- handled_at INTEGER,
41611
- updated_at INTEGER DEFAULT ((strftime('%s', 'now')) * 1000),
41612
- UNIQUE(type, source, source_id)
41613
- );
41614
-
41615
- CREATE INDEX IF NOT EXISTS idx_agent_events_user_status_created
41616
- ON agent_events(user_id, status, created_at);
41617
-
41618
- CREATE INDEX IF NOT EXISTS idx_agent_events_source
41619
- ON agent_events(type, source, source_id);
41620
- `);
41621
- };
41933
+ var import_node_crypto6 = require("node:crypto");
41622
41934
 
41623
41935
  // src/agent/interruptRegistry.ts
41624
41936
  var registry = /* @__PURE__ */ new Map();
@@ -41669,7 +41981,7 @@ var drainInterrupts = (userId) => {
41669
41981
  };
41670
41982
 
41671
41983
  // src/agent/events.ts
41672
- var import_node_crypto2 = require("node:crypto");
41984
+ var import_node_crypto3 = require("node:crypto");
41673
41985
  var rowToEvent = (row) => ({
41674
41986
  id: row.id,
41675
41987
  userId: row.userId,
@@ -41686,7 +41998,7 @@ var rowToEvent = (row) => ({
41686
41998
  var recordAgentEvent = (input) => {
41687
41999
  const db3 = createSqliteDB();
41688
42000
  const now = Date.now();
41689
- const id = `evt_${(0, import_node_crypto2.randomUUID)().slice(0, 12)}`;
42001
+ const id = `evt_${(0, import_node_crypto3.randomUUID)().slice(0, 12)}`;
41690
42002
  const payloadJson = JSON.stringify(input.payload);
41691
42003
  db3.prepare(`
41692
42004
  INSERT INTO agent_events (
@@ -41817,7 +42129,7 @@ ${ceoFollowupInstruction}
41817
42129
  };
41818
42130
 
41819
42131
  // src/department/mailbox/events.ts
41820
- var import_node_crypto3 = require("node:crypto");
42132
+ var import_node_crypto4 = require("node:crypto");
41821
42133
  var parseDetail = (detailJson) => {
41822
42134
  if (!detailJson) return void 0;
41823
42135
  try {
@@ -41858,7 +42170,7 @@ var mapMailboxEventRow = (row) => {
41858
42170
  var recordMailboxEvent = (input) => {
41859
42171
  const db3 = createSqliteDB();
41860
42172
  const event = {
41861
- id: (0, import_node_crypto3.randomUUID)().slice(0, 12),
42173
+ id: (0, import_node_crypto4.randomUUID)().slice(0, 12),
41862
42174
  messageId: input.messageId,
41863
42175
  mailboxId: input.mailboxId,
41864
42176
  actorMailboxId: input.actorMailboxId,
@@ -42142,7 +42454,7 @@ var deleteDepartmentMemberById = (departmentName, memberId) => {
42142
42454
  };
42143
42455
 
42144
42456
  // src/department/mailbox/ceoFollowup.ts
42145
- var import_node_crypto4 = require("node:crypto");
42457
+ var import_node_crypto5 = require("node:crypto");
42146
42458
  var rowToFollowup = (row) => ({
42147
42459
  id: row.id,
42148
42460
  sourceMessageId: row.sourceMessageId,
@@ -42189,7 +42501,7 @@ var enqueueCeoFollowupFromMailbox = (message) => {
42189
42501
  if (!message.originUserId || !message.originPlatform) return null;
42190
42502
  const db3 = createSqliteDB();
42191
42503
  const now = Date.now();
42192
- const id = `cfu_${(0, import_node_crypto4.randomUUID)().slice(0, 12)}`;
42504
+ const id = `cfu_${(0, import_node_crypto5.randomUUID)().slice(0, 12)}`;
42193
42505
  db3.prepare(`
42194
42506
  INSERT INTO ceo_followups (
42195
42507
  id,
@@ -42519,7 +42831,7 @@ var recordMailboxReceivedAgentEvent = (msg) => {
42519
42831
  };
42520
42832
  var sendMessage2 = (fromMailboxId, toMailboxId, content, options) => {
42521
42833
  const db3 = createSqliteDB();
42522
- const id = (0, import_node_crypto5.randomUUID)().slice(0, 8);
42834
+ const id = (0, import_node_crypto6.randomUUID)().slice(0, 8);
42523
42835
  const threadId = options?.threadId || id;
42524
42836
  const workItemContext = resolveWorkItemContext(fromMailboxId, toMailboxId, id, options);
42525
42837
  const stmt = db3.prepare(`insert into mailbox (
@@ -42662,7 +42974,7 @@ var departmentCreate = {
42662
42974
  return `[departmentCreate] \u4E0D\u5B58\u5728 id=${sourceGoalId} \u7684\u76EE\u6807`;
42663
42975
  }
42664
42976
  let departmentDefinition = {
42665
- id: (0, import_node_crypto6.randomUUID)().slice(0, 8),
42977
+ id: (0, import_node_crypto7.randomUUID)().slice(0, 8),
42666
42978
  name,
42667
42979
  charter,
42668
42980
  sourceGoalId,
@@ -42929,7 +43241,7 @@ var departmentList = {
42929
43241
  };
42930
43242
 
42931
43243
  // src/tools/tools/department/DepartmentMemberCreate.ts
42932
- var import_node_crypto7 = require("node:crypto");
43244
+ var import_node_crypto8 = require("node:crypto");
42933
43245
  var DESCRIPTION24 = `
42934
43246
  \u521B\u5EFA\u90E8\u95E8\u6210\u5458\u3002
42935
43247
 
@@ -42995,7 +43307,7 @@ var departmentMemberCreate = {
42995
43307
  }
42996
43308
  }
42997
43309
  let departmentMember = {
42998
- id: (0, import_node_crypto7.randomUUID)().slice(0, 8),
43310
+ id: (0, import_node_crypto8.randomUUID)().slice(0, 8),
42999
43311
  name,
43000
43312
  departmentId: department.id,
43001
43313
  mailBoxId: getMailBoxId(department.name, name),
@@ -43186,7 +43498,7 @@ ${replies}`;
43186
43498
  // src/department/learning.ts
43187
43499
  var import_node_fs4 = require("node:fs");
43188
43500
  var import_node_path12 = __toESM(require("node:path"));
43189
- var import_node_crypto8 = require("node:crypto");
43501
+ var import_node_crypto9 = require("node:crypto");
43190
43502
 
43191
43503
  // src/skill/SkillValidator.ts
43192
43504
  var import_node_fs3 = require("node:fs");
@@ -43424,7 +43736,7 @@ var listDepartmentMemories = (departmentName) => {
43424
43736
  var createDepartmentMemory = (departmentName, input) => {
43425
43737
  const now = Date.now();
43426
43738
  const memory = {
43427
- id: (0, import_node_crypto8.randomUUID)().slice(0, 8),
43739
+ id: (0, import_node_crypto9.randomUUID)().slice(0, 8),
43428
43740
  departmentName,
43429
43741
  title: input.title,
43430
43742
  content: input.content,
@@ -43475,7 +43787,7 @@ ${formatSkillValidationIssues(validation)}`);
43475
43787
  }
43476
43788
  const now = Date.now();
43477
43789
  const skill = {
43478
- id: (0, import_node_crypto8.randomUUID)().slice(0, 8),
43790
+ id: (0, import_node_crypto9.randomUUID)().slice(0, 8),
43479
43791
  departmentName,
43480
43792
  skillName: input.skillName,
43481
43793
  description: input.description,
@@ -43527,7 +43839,7 @@ var createDepartmentProposal = (input) => {
43527
43839
  const records = readJsonArray(proposalsPath());
43528
43840
  const proposal = {
43529
43841
  ...input,
43530
- id: (0, import_node_crypto8.randomUUID)().slice(0, 8),
43842
+ id: (0, import_node_crypto9.randomUUID)().slice(0, 8),
43531
43843
  status: "pending",
43532
43844
  createdAt: Date.now()
43533
43845
  };
@@ -43766,10 +44078,14 @@ var CEO_MAILBOX_ID2 = `manager`;
43766
44078
  var DESCRIPTION28 = `
43767
44079
  \u5728\u5F53\u524D mailbox \u7EBF\u7A0B\u4E2D\u8FFD\u52A0\u4E00\u6761\u8865\u5145\u6D88\u606F\uFF0C\u4F46\u4E0D\u7ED3\u675F\u539F\u6D88\u606F\u7684\u5904\u7406\u3002
43768
44080
 
44081
+ \u5B83\u5728\u7EC4\u7EC7\u91CC\u7684\u542B\u4E49\u66F4\u63A5\u8FD1\u201C\u540C\u4E00\u4EF6\u4E8B\u7684\u7EE7\u7EED\u6C9F\u901A\u201D\uFF1A\u8BA9\u5BF9\u65B9\u77E5\u9053\u4F60\u5DF2\u7ECF\u5B89\u6392\u3001\u6B63\u5728\u7B49\u8C01\u3001\u50AC\u4E86\u8C01\u3001\u76EE\u524D\u770B\u5230\u4E86\u54EA\u4E9B\u90E8\u5206\u7ED3\u679C\uFF0C\u6216\u9700\u8981\u5BF9\u65B9\u8865\u5145\u4EC0\u4E48\u3002
44082
+ \u7279\u522B\u662F\u7ED9 CEO/manager \u540C\u6B65\u201C\u5DF2\u59D4\u6D3E\u3001\u6B63\u5728\u68C0\u67E5\u3001\u7B49\u5F85\u4E0B\u5C5E\u7ED3\u679C\u3001\u5DF2\u50AC\u4FC3\u201D\u8FD9\u7C7B\u8FDB\u5EA6\u65F6\uFF0C\u4F18\u5148\u4F7F\u7528\u5B83\uFF1B\u7B49\u4F60\u9A8C\u6536\u5B8C\u771F\u5B9E\u7ED3\u679C\u3001\u53EF\u4EE5\u4EA4\u4ED8\u6700\u7EC8\u7ED3\u8BBA\u65F6\uFF0C\u518D\u4F7F\u7528 reply_mailbox\u3002
44083
+
43769
44084
  \u9002\u7528\u573A\u666F\uFF1A
43770
44085
  - \u540C\u6B65\u9636\u6BB5\u6027\u8FDB\u5C55
43771
44086
  - \u4E3B\u52A8\u8FFD\u95EE\u6F84\u6E05\u4FE1\u606F
43772
44087
  - \u5148\u53D1\u51FA\u90E8\u5206\u7ED3\u679C\uFF0C\u7A0D\u540E\u7EE7\u7EED\u8865\u5145
44088
+ - \u544A\u77E5\u4E0A\u6E38\u5DF2\u5B89\u6392\u4E0B\u5C5E\u3001\u6B63\u5728\u7B49\u5F85\u4E0B\u5C5E\u7ED3\u679C\uFF0C\u6216\u5DF2\u7ECF\u50AC\u529E
43773
44089
  - CEO \u6536\u5230\u67D0\u4E2A\u90E8\u95E8\u6210\u5458\u7684\u7ED3\u679C\u540E\uFF0C\u82E5\u7528\u6237\u7EE7\u7EED\u63D0\u4FEE\u6539\u610F\u89C1\u3001bug \u53CD\u9988\u3001\u6253\u4E0D\u5F00\u7B49\u95EE\u9898\uFF0C\u5E94\u4F18\u5148\u5BF9\u8BE5\u6210\u5458\u4E0A\u4E00\u6761\u76F8\u5173\u56DE\u4FE1\u8C03\u7528 mailbox_followup\uFF0C\u628A\u53CD\u9988\u6CBF\u539F\u7EBF\u7A0B\u53D1\u56DE\u539F\u8D23\u4EFB\u4EBA
43774
44090
 
43775
44091
  \u53C2\u6570\uFF1A
@@ -43858,7 +44174,7 @@ var mailboxFollowup = {
43858
44174
 
43859
44175
  // src/tools/tools/Bash.ts
43860
44176
  var import_node_child_process = require("node:child_process");
43861
- var import_node_crypto9 = require("node:crypto");
44177
+ var import_node_crypto10 = require("node:crypto");
43862
44178
  var import_node_fs5 = require("node:fs");
43863
44179
  var DESCRIPTION29 = `\u5728\u7CFB\u7EDF shell \u4E2D\u6267\u884C\u547D\u4EE4\u3002
43864
44180
 
@@ -44062,7 +44378,7 @@ var bashTool = {
44062
44378
  ...options,
44063
44379
  stdio: ["pipe", "pipe", "pipe"]
44064
44380
  });
44065
- const id = (0, import_node_crypto9.randomUUID)().slice(0, 8);
44381
+ const id = (0, import_node_crypto10.randomUUID)().slice(0, 8);
44066
44382
  const session = {
44067
44383
  id,
44068
44384
  command,
@@ -44643,7 +44959,7 @@ var readDreamHistoryLimit = () => {
44643
44959
  var import_node_fs6 = require("node:fs");
44644
44960
  var import_node_os2 = require("node:os");
44645
44961
  var import_node_path13 = require("node:path");
44646
- var import_node_crypto10 = require("node:crypto");
44962
+ var import_node_crypto11 = require("node:crypto");
44647
44963
  var SkillForgeEngine = class {
44648
44964
  proposalStorage;
44649
44965
  draftRoot;
@@ -44677,7 +44993,7 @@ ${formatSkillValidationIssues(validation)}`);
44677
44993
  if (pending.some((p) => p.skillName === skillName)) {
44678
44994
  return null;
44679
44995
  }
44680
- const id = (0, import_node_crypto10.randomBytes)(4).toString("hex");
44996
+ const id = (0, import_node_crypto11.randomBytes)(4).toString("hex");
44681
44997
  const draftDir = (0, import_node_path13.join)(this.draftRoot, userId, id);
44682
44998
  (0, import_node_fs6.mkdirSync)(draftDir, { recursive: true });
44683
44999
  (0, import_node_fs6.writeFileSync)((0, import_node_path13.join)(draftDir, "SKILL.md"), skillMd, "utf-8");
@@ -44959,7 +45275,7 @@ var skillForgeDrop = (engine) => ({
44959
45275
  });
44960
45276
 
44961
45277
  // src/memory/MemoryEngine.ts
44962
- var import_node_crypto11 = require("node:crypto");
45278
+ var import_node_crypto12 = require("node:crypto");
44963
45279
  var MemoryEngine = class {
44964
45280
  storage;
44965
45281
  recallIndexStorage;
@@ -44987,7 +45303,7 @@ var MemoryEngine = class {
44987
45303
  }
44988
45304
  const now = Date.now();
44989
45305
  const memory = {
44990
- id: (0, import_node_crypto11.randomBytes)(4).toString("hex"),
45306
+ id: (0, import_node_crypto12.randomBytes)(4).toString("hex"),
44991
45307
  userId,
44992
45308
  title,
44993
45309
  content,
@@ -45639,13 +45955,13 @@ var COMPANY_VALUES_PROMPT = `<\u516C\u53F8\u5171\u540C\u4FE1\u5FF5>
45639
45955
  </\u516C\u53F8\u5171\u540C\u4FE1\u5FF5>`;
45640
45956
 
45641
45957
  // src/agent/outboundDedup.ts
45642
- var import_node_crypto12 = require("node:crypto");
45958
+ var import_node_crypto13 = require("node:crypto");
45643
45959
  var DEFAULT_WINDOW_MS = 15e3;
45644
45960
  var recentSends = /* @__PURE__ */ new Map();
45645
45961
  var lastSweepAt = 0;
45646
45962
  var normalize3 = (text2) => text2.replace(/\s+/g, " ").trim();
45647
45963
  var keyFor = (userId, normalized) => {
45648
- const hash = (0, import_node_crypto12.createHash)("sha1").update(normalized).digest("hex");
45964
+ const hash = (0, import_node_crypto13.createHash)("sha1").update(normalized).digest("hex");
45649
45965
  return `${userId}::${hash}`;
45650
45966
  };
45651
45967
  var sweep = (now, windowMs) => {
@@ -45683,7 +45999,7 @@ var isAbortError2 = (error) => {
45683
45999
  return error.name === "AbortError" || error.message.includes("aborted") || error.message.includes("AbortError");
45684
46000
  };
45685
46001
  var llmRequestIdForTurn = (request, messages, system, tools) => {
45686
- const hash = (0, import_node_crypto13.createHash)("sha256").update(request.requestId).update("\0").update(system).update("\0").update(JSON.stringify(messages)).update("\0").update(JSON.stringify(tools.map((tool) => tool.name).sort())).digest("hex").slice(0, 40);
46002
+ const hash = (0, import_node_crypto14.createHash)("sha256").update(request.requestId).update("\0").update(system).update("\0").update(JSON.stringify(messages)).update("\0").update(JSON.stringify(tools.map((tool) => tool.name).sort())).digest("hex").slice(0, 40);
45687
46003
  return `dreq_${hash}`;
45688
46004
  };
45689
46005
  var getDefaultAgentConfig = (tools, systemPrompt) => {
@@ -46276,7 +46592,8 @@ ${memoryInjection}` : "") + dreamInjection;
46276
46592
  cfg: {},
46277
46593
  to: userId2,
46278
46594
  text: answer,
46279
- accountId: request.requestId
46595
+ accountId: request.requestId,
46596
+ metadata: request.metadata
46280
46597
  });
46281
46598
  } else {
46282
46599
  console.log(`[outbound-dedup] \u8DF3\u8FC7\u5BF9\u7528\u6237 ${userId2} \u7684\u8FD1\u91CD\u590D\u53D1\u9001\uFF08\u5355\u4E00\u58F0\u97F3\u515C\u5E95\uFF09`);
@@ -46362,7 +46679,8 @@ ${msg}</user-interrupt>`
46362
46679
  cfg: {},
46363
46680
  to: request.userId,
46364
46681
  text: textContent2,
46365
- accountId: request.requestId
46682
+ accountId: request.requestId,
46683
+ metadata: request.metadata
46366
46684
  });
46367
46685
  } else {
46368
46686
  console.log(`[outbound-dedup] \u8DF3\u8FC7\u5BF9\u7528\u6237 ${request.userId} \u7684\u8FD1\u91CD\u590D\u515C\u5E95\u53D1\u9001`);
@@ -46796,6 +47114,38 @@ var DESCRIPTION39 = `
46796
47114
  \u53C2\u6570\uFF1A
46797
47115
  - message_id: \u90AE\u4EF6\u7684 id\uFF08\u4ECE list_mailbox \u4E2D\u83B7\u53D6\uFF09
46798
47116
  `;
47117
+ var buildUpstreamContext = (msg) => {
47118
+ if (msg.workItemRole !== "executor_result" || !msg.workItemId) return "";
47119
+ const db3 = createSqliteDB();
47120
+ const upstreamId = msg.upstreamMessageId || msg.workItemId;
47121
+ const upstream = db3.prepare(
47122
+ `SELECT
47123
+ id,
47124
+ from_mailbox_id as fromMailboxId,
47125
+ to_mailbox_id as toMailboxId,
47126
+ content,
47127
+ status
47128
+ FROM mailbox
47129
+ WHERE id = ?
47130
+ OR (
47131
+ work_item_id = ?
47132
+ AND from_mailbox_id = 'manager'
47133
+ AND to_mailbox_id = ?
47134
+ )
47135
+ ORDER BY CASE WHEN id = ? THEN 0 ELSE 1 END, send_time ASC
47136
+ LIMIT 1`
47137
+ ).get(upstreamId, msg.workItemId, msg.toMailboxId, upstreamId);
47138
+ if (!upstream) return "";
47139
+ const preview2 = upstream.content.length > 180 ? `${upstream.content.slice(0, 180)}...` : upstream.content;
47140
+ return [
47141
+ ``,
47142
+ `--- \u4E0A\u6E38\u8D23\u4EFB\u4E0A\u4E0B\u6587 ---`,
47143
+ `\u8FD9\u5C01\u90AE\u4EF6\u662F\u4E0B\u5C5E\u5BF9\u4F60\u59D4\u6D3E\u5DE5\u4F5C\u7684\u7ED3\u679C\uFF0C\u5173\u8054\u5230 CEO/manager \u7ED9\u4F60\u7684\u539F\u59CB\u59D4\u6258\u3002`,
47144
+ `\u4E0A\u6E38\u90AE\u4EF6: ${upstream.id}\uFF08\u72B6\u6001: ${upstream.status}\uFF09`,
47145
+ `\u4E0A\u6E38\u59D4\u6258\u6458\u8981: ${preview2}`,
47146
+ `\u50CF\u8D1F\u8D23\u4EBA\u4E00\u6837\u5148\u9A8C\u6536\u8FD9\u4EFD\u4E0B\u5C5E\u7ED3\u679C\uFF1B\u5982\u679C\u5B83\u5DF2\u7ECF\u8DB3\u591F\u6210\u4E3A\u6700\u7EC8\u7ED3\u8BBA\uFF0C\u8BF7\u6574\u7406\u6210 CEO \u80FD\u76F4\u63A5\u8F6C\u8FF0\u7ED9\u8001\u677F\u7684\u6C47\u603B\uFF0C\u5E76\u56DE\u5230\u4E0A\u6E38\u7EBF\u7A0B\u4EA4\u4EE3\u3002`
47147
+ ].join("\n");
47148
+ };
46799
47149
  var getMailbox = {
46800
47150
  name: `get_mailbox`,
46801
47151
  description: DESCRIPTION39,
@@ -46824,7 +47174,10 @@ var getMailbox = {
46824
47174
  send_time as sendTime,
46825
47175
  status,
46826
47176
  thread_id as threadId,
46827
- parent_message_id as parentMessageId
47177
+ parent_message_id as parentMessageId,
47178
+ work_item_id as workItemId,
47179
+ work_item_role as workItemRole,
47180
+ upstream_message_id as upstreamMessageId
46828
47181
  FROM mailbox WHERE id = ?`
46829
47182
  );
46830
47183
  const msg = stmt.get(messageId);
@@ -46857,13 +47210,14 @@ var getMailbox = {
46857
47210
  });
46858
47211
  const time = new Date(msg.sendTime).toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" });
46859
47212
  const threadId = msg.threadId || msg.id;
47213
+ const upstreamContext = buildUpstreamContext(msg);
46860
47214
  return `[getMailbox] \u90AE\u4EF6\u8BE6\u60C5\uFF1A
46861
47215
  id: ${msg.id}
46862
47216
  \u6765\u81EA: ${msg.fromMailboxId}
46863
47217
  \u65F6\u95F4: ${time}
46864
47218
  \u72B6\u6001: ${msg.status}
46865
47219
  thread: ${threadId}
46866
- parent: ${msg.parentMessageId || "-"}
47220
+ parent: ${msg.parentMessageId || "-"}${upstreamContext}
46867
47221
 
46868
47222
  --- \u90AE\u4EF6\u6B63\u6587 ---
46869
47223
  ${msg.content}`;
@@ -46972,11 +47326,14 @@ var discardMailbox = {
46972
47326
 
46973
47327
  // src/tools/tools/department/ReplyMailbox.ts
46974
47328
  var DESCRIPTION41 = `
46975
- \u6B63\u5F0F\u56DE\u590D\u4E00\u5C01\u90AE\u4EF6\u3002\u5BF9\u5F53\u524D\u6D88\u606F\u5F62\u6210\u660E\u786E\u7ED3\u8BBA\u540E\uFF0C\u4F7F\u7528\u6B64\u5DE5\u5177\u5C06\u7ED3\u679C\u53D1\u56DE\u7ED9\u90AE\u4EF6\u53D1\u9001\u8005\uFF0C\u5E76\u7ED3\u675F\u8FD9\u5C01\u6D88\u606F\u7684\u5904\u7406\u3002
47329
+ \u6B63\u5F0F\u56DE\u590D\u4E00\u5C01\u90AE\u4EF6\u3002\u5BF9\u5F53\u524D\u6D88\u606F\u5F62\u6210\u53EF\u4EE5\u4EA4\u4ED8\u7ED9\u5BF9\u65B9\u7684\u6700\u7EC8\u7ED3\u8BBA\u540E\uFF0C\u4F7F\u7528\u6B64\u5DE5\u5177\u5C06\u7ED3\u679C\u53D1\u56DE\u7ED9\u90AE\u4EF6\u53D1\u9001\u8005\uFF0C\u5E76\u7ED3\u675F\u8FD9\u5C01\u6D88\u606F\u7684\u5904\u7406\u3002
47330
+
47331
+ \u5B83\u5728\u7EC4\u7EC7\u91CC\u7684\u542B\u4E49\u66F4\u63A5\u8FD1\u201C\u6211\u5DF2\u7ECF\u628A\u8FD9\u4EF6\u4E8B\u9A8C\u6536\u6E05\u695A\uFF0C\u53EF\u4EE5\u7ED9\u4F60\u4E00\u4E2A\u7ED3\u8BBA\u201D\uFF0C\u800C\u4E0D\u662F\u666E\u901A\u804A\u5929\u56DE\u590D\u3002
47332
+ \u5982\u679C\u53EA\u662F\u540C\u6B65\u9636\u6BB5\u6027\u8FDB\u5C55\u3001\u8BF4\u660E\u5DF2\u5B89\u6392\u4E0B\u5C5E\u3001\u8FD8\u5728\u7B49\u5F85\u6267\u884C\u7ED3\u679C\u3001\u50AC\u529E\u3001\u8865\u5145\u4E0A\u4E0B\u6587\u6216\u5148\u7ED9\u90E8\u5206\u53D1\u73B0\uFF0C\u5E94\u4F7F\u7528 mailbox_followup\uFF0C\u8BA9\u539F\u90AE\u4EF6\u7EE7\u7EED\u4FDD\u6301\u672A\u5B8C\u5F85\u7EED\u3002
46976
47333
 
46977
47334
  \u53C2\u6570\uFF1A
46978
47335
  - message_id: \u8981\u56DE\u590D\u7684\u90AE\u4EF6 id\uFF08\u4ECE list_mailbox \u6216 get_mailbox \u4E2D\u83B7\u53D6\uFF09
46979
- - content: \u56DE\u590D\u5185\u5BB9\uFF08\u4F60\u7684\u6B63\u5F0F\u5904\u7406\u7ED3\u679C\u3001\u9636\u6BB5\u7ED3\u8BBA\u3001\u6216\u660E\u786E\u8BF4\u660E\u6682\u4E0D\u5904\u7406\u7684\u539F\u56E0\uFF09
47336
+ - content: \u56DE\u590D\u5185\u5BB9\uFF08\u4F60\u7684\u6B63\u5F0F\u5904\u7406\u7ED3\u679C\u3001\u6700\u7EC8\u6C47\u603B\u3001\u9A8C\u6536\u7ED3\u8BBA\uFF0C\u6216\u660E\u786E\u8BF4\u660E\u65E0\u6CD5\u7EE7\u7EED\u5904\u7406\u7684\u539F\u56E0\uFF09
46980
47337
 
46981
47338
  \u6B64\u5DE5\u5177\u4F1A\u81EA\u52A8\uFF1A
46982
47339
  1. \u5C06\u56DE\u590D\u5185\u5BB9\u53D1\u9001\u5230\u539F\u53D1\u9001\u8005\u7684\u90AE\u7BB1
@@ -47274,6 +47631,9 @@ var handleCeoFollowupGroup = async (followups) => {
47274
47631
  }
47275
47632
  };
47276
47633
  const config2 = getDefaultAgentConfig();
47634
+ if (originPlatform === "ios") {
47635
+ config2.channelPlugin = mobileChannelPlugin;
47636
+ }
47277
47637
  const mainAgent = createAgent(config2);
47278
47638
  const result = await mainAgent(request);
47279
47639
  console.log(`[mailbox] \u4E3B agent \u5904\u7406\u5B8C ${followups.length} \u5C01\u56DE\u4FE1, user=${originUserId}, alreadySent=${result.alreadySent}`);
@@ -47593,9 +47953,11 @@ var getDepartmentAgentConfig = (tools, memberFocusOn, workspacePath, departmentN
47593
47953
 
47594
47954
  \u4E13\u4E1A\u7684\u6267\u884C\u6D3B\u2014\u2014\u5199\u4EE3\u7801\u3001\u8BFB\u4EE3\u7801\u5B9A\u4F4D\u95EE\u9898\u3001\u6539\u6587\u4EF6\u3001\u8DD1\u6D4B\u8BD5\u3001\u8C03\u8BD5\u3001\u90E8\u7F72\uFF0C\u5904\u7406\u6570\u636E/\u6587\u6863/\u97F3\u89C6\u9891/\u56FE\u7247\uFF0C\u67E5\u8BC1\u5916\u90E8 API\uFF0C\u751F\u6210\u590D\u6742\u4EA7\u7269\uFF0C\u5168\u9762\u9A8C\u8BC1\u2014\u2014\u4F60\u7684\u7B2C\u4E00\u53CD\u5E94\u662F\u770B\u770B\u624B\u4E0B\u8C01\u5408\u9002\uFF08department_member_list\uFF09\uFF0C\u628A\u5177\u4F53\u4EFB\u52A1\u6D3E\u7ED9\u5BF9\u5E94\u7684 Executor\uFF08department_communicate\uFF09\uFF1B\u624B\u4E0B\u8FD8\u6CA1\u6709\u5408\u9002\u7684\u4EBA\uFF0C\u4F60\u5C31\u5148\u62DB\u4E00\u4E2A\u804C\u8D23\u6E05\u695A\u7684 Executor\uFF08department_member_create\uFF09\u518D\u6D3E\u6D3B\u3002\u4EFB\u52A1\u600E\u4E48\u62C6\u3001\u6D4B\u8BD5\u8BA1\u5212\u3001\u9A8C\u6536\u6807\u51C6\u3001\u98CE\u9669\u5224\u65AD\u3001\u8FFD\u95EE\u8FDB\u5EA6\u3001\u6700\u7EC8\u6C47\u603B\uFF0C\u8FD9\u4E9B\u624D\u662F\u4F60\u81EA\u5DF1\u7684\u6D3B\u3002
47595
47955
 
47956
+ \u4F60\u4E0D\u662F\u6D88\u606F\u642C\u8FD0\u5DE5\u3002Executor \u628A\u7ED3\u679C\u4EA4\u7ED9\u4F60\u4EE5\u540E\uFF0C\u4F60\u8981\u50CF\u4E00\u4E2A\u8D1F\u8D23\u4EBA\u90A3\u6837\u5148\u9A8C\u6536\u3001\u63D0\u70BC\u3001\u5224\u65AD\u98CE\u9669\u548C\u4E0B\u4E00\u6B65\uFF0C\u518D\u628A\u4E0B\u5C5E\u4EA4\u4ED8\u8F6C\u6210 CEO \u80FD\u770B\u61C2\u3001\u80FD\u62FF\u53BB\u5411\u8001\u677F\u4EA4\u4EE3\u7684\u7ED3\u8BBA\u3002\u5BF9\u4E0B\u5C5E\u8BF4\u201C\u6536\u5230/\u8BA4\u53EF\u201D\u53EA\u662F\u90E8\u95E8\u5185\u786E\u8BA4\uFF1B\u628A\u771F\u5B9E\u7ED3\u8BBA\u4EA4\u56DE\u7ED9\u4E0A\u6E38\uFF0C\u624D\u662F\u8D1F\u8D23\u4EBA\u8FD9\u4EF6\u4E8B\u7684\u6536\u5C3E\u3002
47957
+
47596
47958
  \u8C01\u628A\u4E8B\u4EA4\u7ED9\u4F60\u3001\u8C01\u6765\u95EE\u4F60\uFF08\u901A\u5E38\u662F CEO\uFF09\uFF0C\u4F60\u5C31\u6B20\u4ED6\u4E00\u4E2A\u4EA4\u4EE3\u3002\u5728\u4F60\u628A\u6838\u5B9E\u8FC7\u7684\u771F\u5B9E\u7ED3\u8BBA\u4EA4\u56DE\u5230\u95EE\u4F60\u7684\u4EBA\u624B\u4E0A\u4E4B\u524D\uFF0C\u8FD9\u4EF6\u4E8B\u5BF9\u4F60\u90FD\u6CA1\u7B97\u5B8C\u2014\u2014\u4F60\u987A\u7740\u539F\u6765\u90A3\u5C01\u8BF7\u6C42\u7684\u7EBF\u7A0B\uFF0C\u7528\u5B83\u7684 message_id \u56DE\u7ED9\u4E0A\u6E38\uFF08reply_mailbox \u6216 mailbox_followup\uFF09\uFF1B\u53EA\u56DE\u590D Executor \u4E0D\u7B49\u4E8E\u5411\u4E0A\u6E38\u4EA4\u4EE3\u4E86\uFF0C\u90A3\u6837 CEO \u548C\u8001\u677F\u90A3\u8FB9\u6536\u4E0D\u5230\u3002\u4E0A\u6E38\u518D\u6765\u50AC\u540C\u4E00\u4EF6\u4E8B\uFF0C\u54EA\u6015\u4F60\u624B\u91CC\u5DF2\u7ECF\u6709\u6700\u7EC8\u62A5\u544A\uFF0C\u4E5F\u7167\u6837\u628A\u62A5\u544A\u6216\u7B80\u660E\u72B6\u6001\u56DE\u7ED9\u4ED6\u3002
47597
47959
 
47598
- Executor \u56DE\u5F97\u6162\u3001\u6682\u65F6\u6CA1\u56DE\uFF0C\u4E0D\u662F\u4F60\u81EA\u5DF1\u4E0B\u573A\u91CD\u505A\u7684\u7406\u7531\u2014\u2014\u8BE5\u505A\u7684\u662F mailbox_followup \u50AC\u4E00\u4E0B\uFF0C\u5E76\u5982\u5B9E\u8DDF\u4E0A\u6E38\u8BF4\u8FD8\u5728\u7B49\u6267\u884C\u7ED3\u679C\u3002\u53EA\u6709\u4E0A\u6E38\u660E\u786E\u8981\u4F60\u4EB2\u81EA\u505A\u3001\u90E8\u95E8\u91CC\u786E\u5B9E\u6CA1\u6709\u4E5F\u6765\u4E0D\u53CA\u7EC4\u5EFA\u5408\u9002\u7684 Executor\u3001\u6216 Executor \u660E\u786E\u505A\u4E0D\u6210\u4E14\u4E0A\u6E38\u540C\u610F\u4F60\u63A5\u7BA1\u65F6\uFF0C\u4F60\u624D\u81EA\u5DF1\u4E0A\u624B\u90A3\u4E9B\u6267\u884C\u7C7B\u5DE5\u5177\u3002` : `\u4F60\u662F\u6267\u884C\u8005\uFF08Executor\uFF09\u3002\u522B\u4EBA\uFF08\u901A\u5E38\u662F\u4F60\u7684\u90E8\u95E8\u8D1F\u8D23\u4EBA\uFF09\u628A\u5177\u4F53\u4EFB\u52A1\u6D3E\u7ED9\u4F60\uFF0C\u4F60\u5C31\u7528\u81EA\u5DF1\u7684\u4E13\u4E1A\u80FD\u529B\u548C\u5DE5\u5177\u628A\u5B83\u505A\u51FA\u6765\uFF0C\u518D\u5982\u5B9E\u628A\u7ED3\u679C\u56DE\u7ED9\u95EE\u4F60\u7684\u4EBA\u3002\u4F60\u4E13\u6CE8\u505A\u4E8B\uFF0C\u4E0D\u53BB\u67E5\u770B\u6574\u4E2A\u90E8\u95E8\u6210\u5458\u540D\u518C\uFF0C\u4E5F\u4E0D\u521B\u5EFA\u6210\u5458\u2014\u2014\u7EC4\u5EFA\u56E2\u961F\u662F\u8D1F\u8D23\u4EBA\u7684\u4E8B\u3002`;
47960
+ Executor \u56DE\u5F97\u6162\u3001\u6682\u65F6\u6CA1\u56DE\uFF0C\u4E0D\u662F\u4F60\u81EA\u5DF1\u4E0B\u573A\u91CD\u505A\u7684\u7406\u7531\u2014\u2014\u8BE5\u505A\u7684\u662F mailbox_followup \u50AC\u4E00\u4E0B\uFF0C\u5E76\u5982\u5B9E\u8DDF\u4E0A\u6E38\u8BF4\u8FD8\u5728\u7B49\u6267\u884C\u7ED3\u679C\u3002\u7ED9\u4E0A\u6E38\u540C\u6B65\u201C\u5DF2\u5B89\u6392\u3001\u8FD8\u5728\u7B49\u3001\u5DF2\u50AC\u4FC3\u3001\u5DF2\u6709\u90E8\u5206\u53D1\u73B0\u201D\u8FD9\u7C7B\u8FDB\u5C55\uFF0C\u7528 mailbox_followup\uFF1B\u7B49\u4F60\u9A8C\u6536\u5B8C\u771F\u5B9E\u7ED3\u679C\u3001\u53EF\u4EE5\u7ED9\u51FA\u6700\u7EC8\u6C47\u603B\u65F6\uFF0C\u518D\u7528 reply_mailbox \u6B63\u5F0F\u4EA4\u4ED8\u7ED3\u8BBA\u3002\u53EA\u6709\u4E0A\u6E38\u660E\u786E\u8981\u4F60\u4EB2\u81EA\u505A\u3001\u90E8\u95E8\u91CC\u786E\u5B9E\u6CA1\u6709\u4E5F\u6765\u4E0D\u53CA\u7EC4\u5EFA\u5408\u9002\u7684 Executor\u3001\u6216 Executor \u660E\u786E\u505A\u4E0D\u6210\u4E14\u4E0A\u6E38\u540C\u610F\u4F60\u63A5\u7BA1\u65F6\uFF0C\u4F60\u624D\u81EA\u5DF1\u4E0A\u624B\u90A3\u4E9B\u6267\u884C\u7C7B\u5DE5\u5177\u3002` : `\u4F60\u662F\u6267\u884C\u8005\uFF08Executor\uFF09\u3002\u522B\u4EBA\uFF08\u901A\u5E38\u662F\u4F60\u7684\u90E8\u95E8\u8D1F\u8D23\u4EBA\uFF09\u628A\u5177\u4F53\u4EFB\u52A1\u6D3E\u7ED9\u4F60\uFF0C\u4F60\u5C31\u7528\u81EA\u5DF1\u7684\u4E13\u4E1A\u80FD\u529B\u548C\u5DE5\u5177\u628A\u5B83\u505A\u51FA\u6765\uFF0C\u518D\u5982\u5B9E\u628A\u7ED3\u679C\u56DE\u7ED9\u95EE\u4F60\u7684\u4EBA\u3002\u4F60\u4E13\u6CE8\u505A\u4E8B\uFF0C\u4E0D\u53BB\u67E5\u770B\u6574\u4E2A\u90E8\u95E8\u6210\u5458\u540D\u518C\uFF0C\u4E5F\u4E0D\u521B\u5EFA\u6210\u5458\u2014\u2014\u7EC4\u5EFA\u56E2\u961F\u662F\u8D1F\u8D23\u4EBA\u7684\u4E8B\u3002`;
47599
47961
  const defaultSystemPrompt = `
47600
47962
  ${COMPANY_VALUES_PROMPT}
47601
47963
 
@@ -47625,7 +47987,7 @@ ${workspacePath ? `
47625
47987
 
47626
47988
  \u51E0\u4E2A\u5DE5\u5177\u7684\u542B\u4E49\u8981\u5206\u6E05\uFF0C\u522B\u53EA\u7528\u81EA\u7136\u8BED\u8A00\u8BF4\u8BF4\u5C31\u7B97\u6570\uFF1A
47627
47989
  - mailbox_followup(message_id, content)\uFF1A\u5728\u540C\u4E00\u7EBF\u7A0B\u91CC\u7EE7\u7EED\u6C9F\u901A\u2014\u2014\u540C\u6B65\u8FDB\u5C55\u3001\u8865\u5145\u7ED3\u679C\u3001\u8FFD\u95EE\u6216\u50AC\u529E\uFF1B\u53EF\u4EE5\u591A\u6B21\uFF0C\u4E0D\u4F1A\u7ED3\u675F\u8FD9\u5C01\u90AE\u4EF6\u3002
47628
- - reply_mailbox(message_id, content)\uFF1A\u4F60\u5BF9\u8FD9\u5C01\u90AE\u4EF6\u5DF2\u7ECF\u5F62\u6210\u6B63\u5F0F\u7ED3\u8BBA\uFF0C\u56DE\u590D\u5E76\u7ED3\u675F\u5B83\u3002\u6BCF\u5C01\u90AE\u4EF6\u7528\u5B83\u81EA\u5DF1\u7684 message_id \u56DE\u590D\uFF0C\u522B\u62FF\u4E00\u6BB5\u8BDD\u540C\u65F6\u5145\u5F53\u591A\u5C01\u90AE\u4EF6\u7684\u7B54\u590D\u3002\u53D1\u9001\u8005\u9700\u8981\u77E5\u9053\u7ED3\u8BBA\u7684\uFF0C\u4E00\u5F8B\u7528\u5B83\u3002
47990
+ - reply_mailbox(message_id, content)\uFF1A\u4F60\u5BF9\u8FD9\u5C01\u90AE\u4EF6\u5DF2\u7ECF\u5F62\u6210\u53EF\u4EE5\u4EA4\u4ED8\u7ED9\u5BF9\u65B9\u7684\u6B63\u5F0F\u7ED3\u8BBA\uFF0C\u56DE\u590D\u5E76\u7ED3\u675F\u5B83\u3002\u6BCF\u5C01\u90AE\u4EF6\u7528\u5B83\u81EA\u5DF1\u7684 message_id \u56DE\u590D\uFF0C\u522B\u62FF\u4E00\u6BB5\u8BDD\u540C\u65F6\u5145\u5F53\u591A\u5C01\u90AE\u4EF6\u7684\u7B54\u590D\u3002\u8FD8\u5728\u7B49\u5F85\u4E0B\u6E38\u3001\u53EA\u662F\u540C\u6B65\u5B89\u6392\u6216\u50AC\u529E\u65F6\uFF0C\u4E0D\u8981\u7528\u5B83\u7ED3\u675F\u4E0A\u6E38\u8BF7\u6C42\u3002
47629
47991
  - discard_mailbox(message_id, reason)\uFF1A\u53EA\u6709\u5F53\u8FD9\u5C01\u90AE\u4EF6\u786E\u5B9E\u65E0\u9700\u4E1A\u52A1\u56DE\u590D\uFF08\u7EAF\u56DE\u6267\u3001\u91CD\u590D\u901A\u77E5\u3001\u5DF2\u88AB\u5176\u4ED6\u90AE\u4EF6\u8986\u76D6\uFF09\u65F6\u624D\u7528\uFF1B\u5B83\u4F1A\u7ED3\u675F\u90AE\u4EF6\uFF0C\u4F46\u4E0D\u4F1A\u7ED9\u53D1\u9001\u8005\u56DE\u4FE1\u3002
47630
47992
  - \u9700\u8981\u4E3B\u52A8\u8054\u7CFB\u522B\u7684\u90E8\u95E8\u6210\u5458\uFF0C\u7528 department_communicate\u3002
47631
47993
 
@@ -47825,26 +48187,26 @@ var handleParsingNestedValues = (form, key, value) => {
47825
48187
  };
47826
48188
 
47827
48189
  // node_modules/.pnpm/hono@4.12.9/node_modules/hono/dist/utils/url.js
47828
- var splitPath = (path19) => {
47829
- const paths = path19.split("/");
48190
+ var splitPath = (path20) => {
48191
+ const paths = path20.split("/");
47830
48192
  if (paths[0] === "") {
47831
48193
  paths.shift();
47832
48194
  }
47833
48195
  return paths;
47834
48196
  };
47835
48197
  var splitRoutingPath = (routePath) => {
47836
- const { groups, path: path19 } = extractGroupsFromPath(routePath);
47837
- const paths = splitPath(path19);
48198
+ const { groups, path: path20 } = extractGroupsFromPath(routePath);
48199
+ const paths = splitPath(path20);
47838
48200
  return replaceGroupMarks(paths, groups);
47839
48201
  };
47840
- var extractGroupsFromPath = (path19) => {
48202
+ var extractGroupsFromPath = (path20) => {
47841
48203
  const groups = [];
47842
- path19 = path19.replace(/\{[^}]+\}/g, (match2, index) => {
48204
+ path20 = path20.replace(/\{[^}]+\}/g, (match2, index) => {
47843
48205
  const mark = `@${index}`;
47844
48206
  groups.push([mark, match2]);
47845
48207
  return mark;
47846
48208
  });
47847
- return { groups, path: path19 };
48209
+ return { groups, path: path20 };
47848
48210
  };
47849
48211
  var replaceGroupMarks = (paths, groups) => {
47850
48212
  for (let i = groups.length - 1; i >= 0; i--) {
@@ -47901,8 +48263,8 @@ var getPath = (request) => {
47901
48263
  const queryIndex = url.indexOf("?", i);
47902
48264
  const hashIndex = url.indexOf("#", i);
47903
48265
  const end = queryIndex === -1 ? hashIndex === -1 ? void 0 : hashIndex : hashIndex === -1 ? queryIndex : Math.min(queryIndex, hashIndex);
47904
- const path19 = url.slice(start, end);
47905
- return tryDecodeURI(path19.includes("%25") ? path19.replace(/%25/g, "%2525") : path19);
48266
+ const path20 = url.slice(start, end);
48267
+ return tryDecodeURI(path20.includes("%25") ? path20.replace(/%25/g, "%2525") : path20);
47906
48268
  } else if (charCode === 63 || charCode === 35) {
47907
48269
  break;
47908
48270
  }
@@ -47919,11 +48281,11 @@ var mergePath = (base, sub, ...rest) => {
47919
48281
  }
47920
48282
  return `${base?.[0] === "/" ? "" : "/"}${base}${sub === "/" ? "" : `${base?.at(-1) === "/" ? "" : "/"}${sub?.[0] === "/" ? sub.slice(1) : sub}`}`;
47921
48283
  };
47922
- var checkOptionalParameter = (path19) => {
47923
- if (path19.charCodeAt(path19.length - 1) !== 63 || !path19.includes(":")) {
48284
+ var checkOptionalParameter = (path20) => {
48285
+ if (path20.charCodeAt(path20.length - 1) !== 63 || !path20.includes(":")) {
47924
48286
  return null;
47925
48287
  }
47926
- const segments = path19.split("/");
48288
+ const segments = path20.split("/");
47927
48289
  const results = [];
47928
48290
  let basePath = "";
47929
48291
  segments.forEach((segment) => {
@@ -48064,9 +48426,9 @@ var HonoRequest = class {
48064
48426
  */
48065
48427
  path;
48066
48428
  bodyCache = {};
48067
- constructor(request, path19 = "/", matchResult = [[]]) {
48429
+ constructor(request, path20 = "/", matchResult = [[]]) {
48068
48430
  this.raw = request;
48069
- this.path = path19;
48431
+ this.path = path20;
48070
48432
  this.#matchResult = matchResult;
48071
48433
  this.#validatedData = {};
48072
48434
  }
@@ -48803,8 +49165,8 @@ var Hono = class _Hono {
48803
49165
  return this;
48804
49166
  };
48805
49167
  });
48806
- this.on = (method, path19, ...handlers) => {
48807
- for (const p of [path19].flat()) {
49168
+ this.on = (method, path20, ...handlers) => {
49169
+ for (const p of [path20].flat()) {
48808
49170
  this.#path = p;
48809
49171
  for (const m of [method].flat()) {
48810
49172
  handlers.map((handler) => {
@@ -48861,8 +49223,8 @@ var Hono = class _Hono {
48861
49223
  * app.route("/api", app2) // GET /api/user
48862
49224
  * ```
48863
49225
  */
48864
- route(path19, app) {
48865
- const subApp = this.basePath(path19);
49226
+ route(path20, app) {
49227
+ const subApp = this.basePath(path20);
48866
49228
  app.routes.map((r) => {
48867
49229
  let handler;
48868
49230
  if (app.errorHandler === errorHandler) {
@@ -48888,9 +49250,9 @@ var Hono = class _Hono {
48888
49250
  * const api = new Hono().basePath('/api')
48889
49251
  * ```
48890
49252
  */
48891
- basePath(path19) {
49253
+ basePath(path20) {
48892
49254
  const subApp = this.#clone();
48893
- subApp._basePath = mergePath(this._basePath, path19);
49255
+ subApp._basePath = mergePath(this._basePath, path20);
48894
49256
  return subApp;
48895
49257
  }
48896
49258
  /**
@@ -48964,7 +49326,7 @@ var Hono = class _Hono {
48964
49326
  * })
48965
49327
  * ```
48966
49328
  */
48967
- mount(path19, applicationHandler, options) {
49329
+ mount(path20, applicationHandler, options) {
48968
49330
  let replaceRequest;
48969
49331
  let optionHandler;
48970
49332
  if (options) {
@@ -48991,7 +49353,7 @@ var Hono = class _Hono {
48991
49353
  return [c.env, executionContext];
48992
49354
  };
48993
49355
  replaceRequest ||= (() => {
48994
- const mergedPath = mergePath(this._basePath, path19);
49356
+ const mergedPath = mergePath(this._basePath, path20);
48995
49357
  const pathPrefixLength = mergedPath === "/" ? 0 : mergedPath.length;
48996
49358
  return (request) => {
48997
49359
  const url = new URL(request.url);
@@ -49006,14 +49368,14 @@ var Hono = class _Hono {
49006
49368
  }
49007
49369
  await next();
49008
49370
  };
49009
- this.#addRoute(METHOD_NAME_ALL, mergePath(path19, "*"), handler);
49371
+ this.#addRoute(METHOD_NAME_ALL, mergePath(path20, "*"), handler);
49010
49372
  return this;
49011
49373
  }
49012
- #addRoute(method, path19, handler) {
49374
+ #addRoute(method, path20, handler) {
49013
49375
  method = method.toUpperCase();
49014
- path19 = mergePath(this._basePath, path19);
49015
- const r = { basePath: this._basePath, path: path19, method, handler };
49016
- this.router.add(method, path19, [handler, r]);
49376
+ path20 = mergePath(this._basePath, path20);
49377
+ const r = { basePath: this._basePath, path: path20, method, handler };
49378
+ this.router.add(method, path20, [handler, r]);
49017
49379
  this.routes.push(r);
49018
49380
  }
49019
49381
  #handleError(err, c) {
@@ -49026,10 +49388,10 @@ var Hono = class _Hono {
49026
49388
  if (method === "HEAD") {
49027
49389
  return (async () => new Response(null, await this.#dispatch(request, executionCtx, env, "GET")))();
49028
49390
  }
49029
- const path19 = this.getPath(request, { env });
49030
- const matchResult = this.router.match(method, path19);
49391
+ const path20 = this.getPath(request, { env });
49392
+ const matchResult = this.router.match(method, path20);
49031
49393
  const c = new Context(request, {
49032
- path: path19,
49394
+ path: path20,
49033
49395
  matchResult,
49034
49396
  env,
49035
49397
  executionCtx,
@@ -49129,7 +49491,7 @@ var Hono = class _Hono {
49129
49491
 
49130
49492
  // node_modules/.pnpm/hono@4.12.9/node_modules/hono/dist/router/reg-exp-router/matcher.js
49131
49493
  var emptyParam = [];
49132
- function match(method, path19) {
49494
+ function match(method, path20) {
49133
49495
  const matchers = this.buildAllMatchers();
49134
49496
  const match2 = ((method2, path22) => {
49135
49497
  const matcher = matchers[method2] || matchers[METHOD_NAME_ALL];
@@ -49145,7 +49507,7 @@ function match(method, path19) {
49145
49507
  return [matcher[1][index], match3];
49146
49508
  });
49147
49509
  this.match = match2;
49148
- return match2(method, path19);
49510
+ return match2(method, path20);
49149
49511
  }
49150
49512
 
49151
49513
  // node_modules/.pnpm/hono@4.12.9/node_modules/hono/dist/router/reg-exp-router/node.js
@@ -49260,12 +49622,12 @@ var Node = class _Node {
49260
49622
  var Trie = class {
49261
49623
  #context = { varIndex: 0 };
49262
49624
  #root = new Node();
49263
- insert(path19, index, pathErrorCheckOnly) {
49625
+ insert(path20, index, pathErrorCheckOnly) {
49264
49626
  const paramAssoc = [];
49265
49627
  const groups = [];
49266
49628
  for (let i = 0; ; ) {
49267
49629
  let replaced = false;
49268
- path19 = path19.replace(/\{[^}]+\}/g, (m) => {
49630
+ path20 = path20.replace(/\{[^}]+\}/g, (m) => {
49269
49631
  const mark = `@\\${i}`;
49270
49632
  groups[i] = [mark, m];
49271
49633
  i++;
@@ -49276,7 +49638,7 @@ var Trie = class {
49276
49638
  break;
49277
49639
  }
49278
49640
  }
49279
- const tokens = path19.match(/(?::[^\/]+)|(?:\/\*$)|./g) || [];
49641
+ const tokens = path20.match(/(?::[^\/]+)|(?:\/\*$)|./g) || [];
49280
49642
  for (let i = groups.length - 1; i >= 0; i--) {
49281
49643
  const [mark] = groups[i];
49282
49644
  for (let j = tokens.length - 1; j >= 0; j--) {
@@ -49315,9 +49677,9 @@ var Trie = class {
49315
49677
  // node_modules/.pnpm/hono@4.12.9/node_modules/hono/dist/router/reg-exp-router/router.js
49316
49678
  var nullMatcher = [/^$/, [], /* @__PURE__ */ Object.create(null)];
49317
49679
  var wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
49318
- function buildWildcardRegExp(path19) {
49319
- return wildcardRegExpCache[path19] ??= new RegExp(
49320
- path19 === "*" ? "" : `^${path19.replace(
49680
+ function buildWildcardRegExp(path20) {
49681
+ return wildcardRegExpCache[path20] ??= new RegExp(
49682
+ path20 === "*" ? "" : `^${path20.replace(
49321
49683
  /\/\*$|([.\\+*[^\]$()])/g,
49322
49684
  (_, metaChar) => metaChar ? `\\${metaChar}` : "(?:|/.*)"
49323
49685
  )}$`
@@ -49339,17 +49701,17 @@ function buildMatcherFromPreprocessedRoutes(routes) {
49339
49701
  );
49340
49702
  const staticMap = /* @__PURE__ */ Object.create(null);
49341
49703
  for (let i = 0, j = -1, len = routesWithStaticPathFlag.length; i < len; i++) {
49342
- const [pathErrorCheckOnly, path19, handlers] = routesWithStaticPathFlag[i];
49704
+ const [pathErrorCheckOnly, path20, handlers] = routesWithStaticPathFlag[i];
49343
49705
  if (pathErrorCheckOnly) {
49344
- staticMap[path19] = [handlers.map(([h]) => [h, /* @__PURE__ */ Object.create(null)]), emptyParam];
49706
+ staticMap[path20] = [handlers.map(([h]) => [h, /* @__PURE__ */ Object.create(null)]), emptyParam];
49345
49707
  } else {
49346
49708
  j++;
49347
49709
  }
49348
49710
  let paramAssoc;
49349
49711
  try {
49350
- paramAssoc = trie.insert(path19, j, pathErrorCheckOnly);
49712
+ paramAssoc = trie.insert(path20, j, pathErrorCheckOnly);
49351
49713
  } catch (e) {
49352
- throw e === PATH_ERROR ? new UnsupportedPathError(path19) : e;
49714
+ throw e === PATH_ERROR ? new UnsupportedPathError(path20) : e;
49353
49715
  }
49354
49716
  if (pathErrorCheckOnly) {
49355
49717
  continue;
@@ -49383,12 +49745,12 @@ function buildMatcherFromPreprocessedRoutes(routes) {
49383
49745
  }
49384
49746
  return [regexp, handlerMap, staticMap];
49385
49747
  }
49386
- function findMiddleware(middleware, path19) {
49748
+ function findMiddleware(middleware, path20) {
49387
49749
  if (!middleware) {
49388
49750
  return void 0;
49389
49751
  }
49390
49752
  for (const k of Object.keys(middleware).sort((a, b) => b.length - a.length)) {
49391
- if (buildWildcardRegExp(k).test(path19)) {
49753
+ if (buildWildcardRegExp(k).test(path20)) {
49392
49754
  return [...middleware[k]];
49393
49755
  }
49394
49756
  }
@@ -49402,7 +49764,7 @@ var RegExpRouter = class {
49402
49764
  this.#middleware = { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
49403
49765
  this.#routes = { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
49404
49766
  }
49405
- add(method, path19, handler) {
49767
+ add(method, path20, handler) {
49406
49768
  const middleware = this.#middleware;
49407
49769
  const routes = this.#routes;
49408
49770
  if (!middleware || !routes) {
@@ -49417,18 +49779,18 @@ var RegExpRouter = class {
49417
49779
  });
49418
49780
  });
49419
49781
  }
49420
- if (path19 === "/*") {
49421
- path19 = "*";
49782
+ if (path20 === "/*") {
49783
+ path20 = "*";
49422
49784
  }
49423
- const paramCount = (path19.match(/\/:/g) || []).length;
49424
- if (/\*$/.test(path19)) {
49425
- const re = buildWildcardRegExp(path19);
49785
+ const paramCount = (path20.match(/\/:/g) || []).length;
49786
+ if (/\*$/.test(path20)) {
49787
+ const re = buildWildcardRegExp(path20);
49426
49788
  if (method === METHOD_NAME_ALL) {
49427
49789
  Object.keys(middleware).forEach((m) => {
49428
- middleware[m][path19] ||= findMiddleware(middleware[m], path19) || findMiddleware(middleware[METHOD_NAME_ALL], path19) || [];
49790
+ middleware[m][path20] ||= findMiddleware(middleware[m], path20) || findMiddleware(middleware[METHOD_NAME_ALL], path20) || [];
49429
49791
  });
49430
49792
  } else {
49431
- middleware[method][path19] ||= findMiddleware(middleware[method], path19) || findMiddleware(middleware[METHOD_NAME_ALL], path19) || [];
49793
+ middleware[method][path20] ||= findMiddleware(middleware[method], path20) || findMiddleware(middleware[METHOD_NAME_ALL], path20) || [];
49432
49794
  }
49433
49795
  Object.keys(middleware).forEach((m) => {
49434
49796
  if (method === METHOD_NAME_ALL || method === m) {
@@ -49446,7 +49808,7 @@ var RegExpRouter = class {
49446
49808
  });
49447
49809
  return;
49448
49810
  }
49449
- const paths = checkOptionalParameter(path19) || [path19];
49811
+ const paths = checkOptionalParameter(path20) || [path20];
49450
49812
  for (let i = 0, len = paths.length; i < len; i++) {
49451
49813
  const path22 = paths[i];
49452
49814
  Object.keys(routes).forEach((m) => {
@@ -49473,13 +49835,13 @@ var RegExpRouter = class {
49473
49835
  const routes = [];
49474
49836
  let hasOwnRoute = method === METHOD_NAME_ALL;
49475
49837
  [this.#middleware, this.#routes].forEach((r) => {
49476
- const ownRoute = r[method] ? Object.keys(r[method]).map((path19) => [path19, r[method][path19]]) : [];
49838
+ const ownRoute = r[method] ? Object.keys(r[method]).map((path20) => [path20, r[method][path20]]) : [];
49477
49839
  if (ownRoute.length !== 0) {
49478
49840
  hasOwnRoute ||= true;
49479
49841
  routes.push(...ownRoute);
49480
49842
  } else if (method !== METHOD_NAME_ALL) {
49481
49843
  routes.push(
49482
- ...Object.keys(r[METHOD_NAME_ALL]).map((path19) => [path19, r[METHOD_NAME_ALL][path19]])
49844
+ ...Object.keys(r[METHOD_NAME_ALL]).map((path20) => [path20, r[METHOD_NAME_ALL][path20]])
49483
49845
  );
49484
49846
  }
49485
49847
  });
@@ -49499,13 +49861,13 @@ var SmartRouter = class {
49499
49861
  constructor(init) {
49500
49862
  this.#routers = init.routers;
49501
49863
  }
49502
- add(method, path19, handler) {
49864
+ add(method, path20, handler) {
49503
49865
  if (!this.#routes) {
49504
49866
  throw new Error(MESSAGE_MATCHER_IS_ALREADY_BUILT);
49505
49867
  }
49506
- this.#routes.push([method, path19, handler]);
49868
+ this.#routes.push([method, path20, handler]);
49507
49869
  }
49508
- match(method, path19) {
49870
+ match(method, path20) {
49509
49871
  if (!this.#routes) {
49510
49872
  throw new Error("Fatal error");
49511
49873
  }
@@ -49520,7 +49882,7 @@ var SmartRouter = class {
49520
49882
  for (let i2 = 0, len2 = routes.length; i2 < len2; i2++) {
49521
49883
  router.add(...routes[i2]);
49522
49884
  }
49523
- res = router.match(method, path19);
49885
+ res = router.match(method, path20);
49524
49886
  } catch (e) {
49525
49887
  if (e instanceof UnsupportedPathError) {
49526
49888
  continue;
@@ -49570,10 +49932,10 @@ var Node2 = class _Node2 {
49570
49932
  }
49571
49933
  this.#patterns = [];
49572
49934
  }
49573
- insert(method, path19, handler) {
49935
+ insert(method, path20, handler) {
49574
49936
  this.#order = ++this.#order;
49575
49937
  let curNode = this;
49576
- const parts = splitRoutingPath(path19);
49938
+ const parts = splitRoutingPath(path20);
49577
49939
  const possibleKeys = [];
49578
49940
  for (let i = 0, len = parts.length; i < len; i++) {
49579
49941
  const p = parts[i];
@@ -49622,12 +49984,12 @@ var Node2 = class _Node2 {
49622
49984
  }
49623
49985
  }
49624
49986
  }
49625
- search(method, path19) {
49987
+ search(method, path20) {
49626
49988
  const handlerSets = [];
49627
49989
  this.#params = emptyParams;
49628
49990
  const curNode = this;
49629
49991
  let curNodes = [curNode];
49630
- const parts = splitPath(path19);
49992
+ const parts = splitPath(path20);
49631
49993
  const curNodesQueue = [];
49632
49994
  const len = parts.length;
49633
49995
  let partOffsets = null;
@@ -49669,13 +50031,13 @@ var Node2 = class _Node2 {
49669
50031
  if (matcher instanceof RegExp) {
49670
50032
  if (partOffsets === null) {
49671
50033
  partOffsets = new Array(len);
49672
- let offset = path19[0] === "/" ? 1 : 0;
50034
+ let offset = path20[0] === "/" ? 1 : 0;
49673
50035
  for (let p = 0; p < len; p++) {
49674
50036
  partOffsets[p] = offset;
49675
50037
  offset += parts[p].length + 1;
49676
50038
  }
49677
50039
  }
49678
- const restPathString = path19.substring(partOffsets[i]);
50040
+ const restPathString = path20.substring(partOffsets[i]);
49679
50041
  const m = matcher.exec(restPathString);
49680
50042
  if (m) {
49681
50043
  params[name] = m[0];
@@ -49728,18 +50090,18 @@ var TrieRouter = class {
49728
50090
  constructor() {
49729
50091
  this.#node = new Node2();
49730
50092
  }
49731
- add(method, path19, handler) {
49732
- const results = checkOptionalParameter(path19);
50093
+ add(method, path20, handler) {
50094
+ const results = checkOptionalParameter(path20);
49733
50095
  if (results) {
49734
50096
  for (let i = 0, len = results.length; i < len; i++) {
49735
50097
  this.#node.insert(method, results[i], handler);
49736
50098
  }
49737
50099
  return;
49738
50100
  }
49739
- this.#node.insert(method, path19, handler);
50101
+ this.#node.insert(method, path20, handler);
49740
50102
  }
49741
- match(method, path19) {
49742
- return this.#node.search(method, path19);
50103
+ match(method, path20) {
50104
+ return this.#node.search(method, path20);
49743
50105
  }
49744
50106
  };
49745
50107
 
@@ -50441,10 +50803,10 @@ var createStreamBody = (stream) => {
50441
50803
  });
50442
50804
  return body;
50443
50805
  };
50444
- var getStats = (path19) => {
50806
+ var getStats = (path20) => {
50445
50807
  let stats;
50446
50808
  try {
50447
- stats = (0, import_fs15.statSync)(path19);
50809
+ stats = (0, import_fs15.statSync)(path20);
50448
50810
  } catch {
50449
50811
  }
50450
50812
  return stats;
@@ -50487,21 +50849,21 @@ var serveStatic = (options = { root: "" }) => {
50487
50849
  return next();
50488
50850
  }
50489
50851
  }
50490
- let path19 = (0, import_path20.join)(
50852
+ let path20 = (0, import_path20.join)(
50491
50853
  root,
50492
50854
  !optionPath && options.rewriteRequestPath ? options.rewriteRequestPath(filename, c) : filename
50493
50855
  );
50494
- let stats = getStats(path19);
50856
+ let stats = getStats(path20);
50495
50857
  if (stats && stats.isDirectory()) {
50496
50858
  const indexFile = options.index ?? "index.html";
50497
- path19 = (0, import_path20.join)(path19, indexFile);
50498
- stats = getStats(path19);
50859
+ path20 = (0, import_path20.join)(path20, indexFile);
50860
+ stats = getStats(path20);
50499
50861
  }
50500
50862
  if (!stats) {
50501
- await options.onNotFound?.(path19, c);
50863
+ await options.onNotFound?.(path20, c);
50502
50864
  return next();
50503
50865
  }
50504
- const mimeType = getMimeType(path19);
50866
+ const mimeType = getMimeType(path20);
50505
50867
  c.header("Content-Type", mimeType || "application/octet-stream");
50506
50868
  if (options.precompressed && (!mimeType || COMPRESSIBLE_CONTENT_TYPE_REGEX.test(mimeType))) {
50507
50869
  const acceptEncodingSet = new Set(
@@ -50511,12 +50873,12 @@ var serveStatic = (options = { root: "" }) => {
50511
50873
  if (!acceptEncodingSet.has(encoding)) {
50512
50874
  continue;
50513
50875
  }
50514
- const precompressedStats = getStats(path19 + ENCODINGS[encoding]);
50876
+ const precompressedStats = getStats(path20 + ENCODINGS[encoding]);
50515
50877
  if (precompressedStats) {
50516
50878
  c.header("Content-Encoding", encoding);
50517
50879
  c.header("Vary", "Accept-Encoding", { append: true });
50518
50880
  stats = precompressedStats;
50519
- path19 = path19 + ENCODINGS[encoding];
50881
+ path20 = path20 + ENCODINGS[encoding];
50520
50882
  break;
50521
50883
  }
50522
50884
  }
@@ -50530,7 +50892,7 @@ var serveStatic = (options = { root: "" }) => {
50530
50892
  result = c.body(null);
50531
50893
  } else if (!range) {
50532
50894
  c.header("Content-Length", size.toString());
50533
- result = c.body(createStreamBody((0, import_fs15.createReadStream)(path19)), 200);
50895
+ result = c.body(createStreamBody((0, import_fs15.createReadStream)(path20)), 200);
50534
50896
  } else {
50535
50897
  c.header("Accept-Ranges", "bytes");
50536
50898
  c.header("Date", stats.birthtime.toUTCString());
@@ -50541,12 +50903,12 @@ var serveStatic = (options = { root: "" }) => {
50541
50903
  end = size - 1;
50542
50904
  }
50543
50905
  const chunksize = end - start + 1;
50544
- const stream = (0, import_fs15.createReadStream)(path19, { start, end });
50906
+ const stream = (0, import_fs15.createReadStream)(path20, { start, end });
50545
50907
  c.header("Content-Length", chunksize.toString());
50546
50908
  c.header("Content-Range", `bytes ${start}-${end}/${stats.size}`);
50547
50909
  result = c.body(createStreamBody(stream), 206);
50548
50910
  }
50549
- await options.onFound?.(path19, c);
50911
+ await options.onFound?.(path20, c);
50550
50912
  return result;
50551
50913
  };
50552
50914
  };
@@ -50640,8 +51002,8 @@ var cors = (options) => {
50640
51002
  };
50641
51003
 
50642
51004
  // src/server/index.ts
50643
- var import_promises11 = require("node:fs/promises");
50644
- var import_node_path15 = __toESM(require("node:path"));
51005
+ var import_promises12 = require("node:fs/promises");
51006
+ var import_node_path16 = __toESM(require("node:path"));
50645
51007
 
50646
51008
  // src/git/worktree.ts
50647
51009
  var import_child_process2 = require("child_process");
@@ -52600,13 +52962,323 @@ var systemRoutes = new Hono2();
52600
52962
  var startTime = Date.now();
52601
52963
  systemRoutes.get("/system/info", (c) => {
52602
52964
  return c.json({
52603
- version: true ? "1.8.46" : "unknown",
52965
+ version: true ? "1.8.48" : "unknown",
52604
52966
  uptime: Math.floor((Date.now() - startTime) / 1e3),
52605
52967
  env: process.env.NODE_ENV || "development",
52606
52968
  nodeVersion: process.version
52607
52969
  });
52608
52970
  });
52609
52971
 
52972
+ // src/server/routes/mobile.ts
52973
+ var import_node_crypto15 = require("node:crypto");
52974
+ var import_promises11 = require("node:fs/promises");
52975
+ var import_node_path15 = __toESM(require("node:path"));
52976
+ var mobileRoutes = new Hono2();
52977
+ var resolveMobileUserId = (body, headerUserId) => {
52978
+ return body.userId?.trim() || headerUserId?.trim() || "ios:local-user";
52979
+ };
52980
+ var resolveThreadId = (goalId, mobileUserId) => {
52981
+ if (!goalId) return `ios:user:${mobileUserId}`;
52982
+ const existing = getGoalConversationContext(goalId);
52983
+ if (existing?.originPlatform === "ios" && existing.threadId) return existing.threadId;
52984
+ const threadId = `ios:goal:${goalId}`;
52985
+ ensureGoalConversationContext(goalId, {
52986
+ threadId,
52987
+ originPlatform: "ios",
52988
+ originUserId: threadId,
52989
+ syncReplyToOrigin: false
52990
+ });
52991
+ return threadId;
52992
+ };
52993
+ var buildGoalPrompt = (goalId, text2) => {
52994
+ if (!goalId) return text2;
52995
+ const goal = getGoalById(goalId);
52996
+ if (!goal) return text2;
52997
+ const lines = [
52998
+ `\u4F60\u73B0\u5728\u5728\u56F4\u7ED5\u4E00\u4E2A iOS App \u4E2D\u7684\u201C\u9700\u6C42\u201D\u7EE7\u7EED\u5BF9\u8BDD\u3002`,
52999
+ ``,
53000
+ `\u3010\u5F53\u524D\u9700\u6C42\u3011${goal.subject}`,
53001
+ goal.description ? `\u3010\u539F\u59CB\u9700\u6C42\u63CF\u8FF0\u3011${goal.description}` : void 0,
53002
+ goal.summary ? `\u3010\u5F53\u524D\u6458\u8981\u3011${goal.summary}` : void 0,
53003
+ goal.currentFocus ? `\u3010\u5F53\u524D\u91CD\u70B9\u3011${goal.currentFocus}` : void 0,
53004
+ goal.nextAction ? `\u3010\u4E0B\u4E00\u6B65\u3011${goal.nextAction}` : void 0,
53005
+ goal.blockers?.length ? `\u3010\u963B\u585E\u9879\u3011${goal.blockers.join("\uFF1B")}` : void 0,
53006
+ goal.tasks.length > 0 ? `
53007
+ \u3010\u5F53\u524D\u4EFB\u52A1\u5217\u8868\u3011
53008
+ ${goal.tasks.map((task) => `- [${task.status}] ${task.subject}`).join("\n")}` : void 0,
53009
+ ``,
53010
+ `\u8BF7\u57FA\u4E8E\u6574\u4E2A\u9700\u6C42\u4E0A\u4E0B\u6587\u56DE\u7B54\u7528\u6237\u3002`,
53011
+ ``,
53012
+ `\u7528\u6237\u6D88\u606F\uFF1A${text2}`
53013
+ ].filter((line) => typeof line === "string");
53014
+ return lines.join("\n");
53015
+ };
53016
+ var sanitizeFileName = (fileName) => {
53017
+ const cleaned = import_node_path15.default.basename(fileName).replace(/[^\w.\-()\u4e00-\u9fa5 ]+/g, "_").trim();
53018
+ return cleaned || `attachment-${Date.now()}`;
53019
+ };
53020
+ var inferAttachmentType = (mimeType = "", fileName = "") => {
53021
+ if (mimeType.startsWith("image/")) return "image";
53022
+ const ext = import_node_path15.default.extname(fileName).toLowerCase();
53023
+ if ([".png", ".jpg", ".jpeg", ".gif", ".webp"].includes(ext)) return "image";
53024
+ return "file";
53025
+ };
53026
+ var resolveAttachments = (attachments) => {
53027
+ return attachments.map((attachment) => getMobileAttachment(attachment.id) ?? attachment);
53028
+ };
53029
+ var buildContentWithAttachments = (text2, attachments) => {
53030
+ const imageAttachments = attachments.filter((attachment) => attachment.type === "image");
53031
+ const fileAttachments = attachments.filter((attachment) => attachment.type !== "image");
53032
+ const metadata = {
53033
+ attachments
53034
+ };
53035
+ const lines = [];
53036
+ if (text2.trim()) lines.push(text2.trim());
53037
+ if (imageAttachments.length > 0) {
53038
+ const primaryImage = imageAttachments[0];
53039
+ const imageSource = primaryImage.url || primaryImage.path;
53040
+ if (imageSource) {
53041
+ metadata.imageUrl = imageSource;
53042
+ metadata.imageKey = primaryImage.id;
53043
+ metadata.imageKeys = imageAttachments.map((attachment) => attachment.id);
53044
+ }
53045
+ const reminder = imageAttachments.length > 1 ? `\u63A5\u6536\u5230\u7528\u6237\u901A\u8FC7 iOS App \u53D1\u6765\u7684${imageAttachments.length}\u5F20\u56FE\u7247,\u5F53\u524D\u5DF2\u5C06\u7B2C1\u5F20\u56FE\u7247\u5B58\u50A8\u5728\u4E0A\u4E0B\u6587\u4E2D,\u8BF7\u7ED3\u5408\u7528\u6237\u6587\u5B57\u4F18\u5148\u5206\u6790\u8FD9\u5F20\u56FE\u7247(\u4E0D\u9700\u8981\u4F20image_url\u53C2\u6570,\u5DE5\u5177\u4F1A\u81EA\u52A8\u83B7\u53D6\u56FE\u7247)` : `\u63A5\u6536\u5230\u7528\u6237\u901A\u8FC7 iOS App \u53D1\u6765\u7684\u56FE\u7247,\u56FE\u7247\u5DF2\u5B58\u50A8\u5728\u4E0A\u4E0B\u6587\u4E2D,\u8BF7\u4F7F\u7528image_understand\u5DE5\u5177\u5206\u6790\u56FE\u7247(\u4E0D\u9700\u8981\u4F20image_url\u53C2\u6570,\u5DE5\u5177\u4F1A\u81EA\u52A8\u83B7\u53D6\u56FE\u7247)`;
53046
+ lines.push(`<system-reminder>${reminder}</system-reminder>`);
53047
+ }
53048
+ if (fileAttachments.length > 0) {
53049
+ const primaryFile = fileAttachments[0];
53050
+ metadata.fileUrl = primaryFile.url || primaryFile.path;
53051
+ metadata.fileName = primaryFile.name;
53052
+ lines.push([
53053
+ `\u7528\u6237\u901A\u8FC7 iOS App \u53D1\u9001\u4E86${fileAttachments.length > 1 ? `${fileAttachments.length}\u4E2A\u6587\u4EF6` : "\u4E00\u4E2A\u6587\u4EF6"}\u3002`,
53054
+ ...fileAttachments.map((attachment) => {
53055
+ const location = attachment.url || attachment.path || attachment.id;
53056
+ return `\u6587\u4EF6\u540D: ${attachment.name ?? attachment.id}
53057
+ \u6587\u4EF6\u4F4D\u7F6E: ${location}`;
53058
+ })
53059
+ ].join("\n"));
53060
+ }
53061
+ if (lines.length === 0) {
53062
+ lines.push("\u7528\u6237\u901A\u8FC7 iOS App \u53D1\u9001\u4E86\u9644\u4EF6\u3002");
53063
+ }
53064
+ return {
53065
+ content: lines.join("\n\n"),
53066
+ metadata
53067
+ };
53068
+ };
53069
+ mobileRoutes.post("/mobile/attachments", async (c) => {
53070
+ const body = await c.req.json();
53071
+ const dataBase64 = body.dataBase64?.trim();
53072
+ if (!dataBase64) return c.json({ error: "dataBase64 is required" }, 400);
53073
+ const mobileUserId = resolveMobileUserId(body, c.req.header("x-user-id"));
53074
+ const fileName = sanitizeFileName(body.fileName || `attachment-${Date.now()}`);
53075
+ const mimeType = body.mimeType || "application/octet-stream";
53076
+ const type = inferAttachmentType(mimeType, fileName);
53077
+ const attachmentId = (0, import_node_crypto15.randomUUID)();
53078
+ const buffer = Buffer.from(dataBase64, "base64");
53079
+ const dir = import_node_path15.default.join(getDuclawWorkspaceDir(), mobileUserId, "mobile", type === "image" ? "images" : "files");
53080
+ await (0, import_promises11.mkdir)(dir, { recursive: true });
53081
+ const localPath = import_node_path15.default.join(dir, `${attachmentId}-${fileName}`);
53082
+ await (0, import_promises11.writeFile)(localPath, buffer);
53083
+ const attachment = saveMobileAttachment({
53084
+ id: attachmentId,
53085
+ type,
53086
+ name: fileName,
53087
+ mimeType,
53088
+ size: buffer.length,
53089
+ path: localPath,
53090
+ url: localPath
53091
+ });
53092
+ return c.json({
53093
+ ok: true,
53094
+ attachment
53095
+ });
53096
+ });
53097
+ mobileRoutes.post("/mobile/messages", async (c) => {
53098
+ const body = await c.req.json();
53099
+ const text2 = body.text?.trim() ?? "";
53100
+ const attachments = resolveAttachments(body.attachments ?? []);
53101
+ if (!text2 && attachments.length === 0) {
53102
+ return c.json({ error: "text or attachments is required" }, 400);
53103
+ }
53104
+ if (body.goalId && !getGoalById(body.goalId)) {
53105
+ return c.json({ error: "Goal not found" }, 404);
53106
+ }
53107
+ const mobileUserId = resolveMobileUserId(body, c.req.header("x-user-id"));
53108
+ const threadId = resolveThreadId(body.goalId, mobileUserId);
53109
+ const requestId = body.clientMessageId?.trim() || (0, import_node_crypto15.randomUUID)();
53110
+ const agentText = body.contextText?.trim() || text2;
53111
+ const attachmentContent = buildContentWithAttachments(agentText, attachments);
53112
+ const content = buildGoalPrompt(body.goalId, attachmentContent.content);
53113
+ const teamMetadata = {
53114
+ ...body.teamId?.trim() ? { teamId: body.teamId.trim() } : {},
53115
+ ...body.teamName?.trim() ? { teamName: body.teamName.trim() } : {}
53116
+ };
53117
+ const userMessage2 = appendMobileMessage({
53118
+ threadId,
53119
+ userId: mobileUserId,
53120
+ goalId: body.goalId,
53121
+ clientMessageId: requestId,
53122
+ role: "user",
53123
+ text: text2,
53124
+ attachments,
53125
+ status: "accepted",
53126
+ metadata: {
53127
+ ...teamMetadata,
53128
+ source: "ios"
53129
+ }
53130
+ });
53131
+ if (hasRunningAgent(threadId)) {
53132
+ queueInterrupt(threadId, {
53133
+ content,
53134
+ metadata: {
53135
+ platform: "ios",
53136
+ goalId: body.goalId,
53137
+ ...teamMetadata,
53138
+ clientMessageId: requestId,
53139
+ attachments,
53140
+ ...attachmentContent.metadata
53141
+ }
53142
+ });
53143
+ appendMobileRunLog(threadId, `[\u4E2D\u65AD] \u7528\u6237\u8865\u5145: ${text2.slice(0, 160)}`);
53144
+ const run = upsertMobileRun(threadId, {
53145
+ userId: mobileUserId,
53146
+ goalId: body.goalId,
53147
+ running: true,
53148
+ interrupted: true
53149
+ });
53150
+ appendMobileMessage({
53151
+ threadId,
53152
+ userId: mobileUserId,
53153
+ goalId: body.goalId,
53154
+ role: "system",
53155
+ text: "\u5DF2\u8865\u5145\u7ED9\u6B63\u5728\u5904\u7406\u7684 CEO\u3002",
53156
+ status: "accepted",
53157
+ metadata: {
53158
+ source: "interrupt-ack",
53159
+ ...teamMetadata,
53160
+ clientMessageId: requestId
53161
+ }
53162
+ });
53163
+ return c.json({
53164
+ ok: true,
53165
+ accepted: true,
53166
+ interrupted: true,
53167
+ threadId,
53168
+ message: userMessage2,
53169
+ run
53170
+ }, 202);
53171
+ }
53172
+ const config2 = getDefaultAgentConfig();
53173
+ config2.channelPlugin = mobileChannelPlugin;
53174
+ const agent = createAgent(config2);
53175
+ const request = {
53176
+ platform: "ios",
53177
+ userId: threadId,
53178
+ requestId,
53179
+ departmentAgentId: "",
53180
+ content,
53181
+ metadata: {
53182
+ goalId: body.goalId,
53183
+ mobileUserId,
53184
+ ...teamMetadata,
53185
+ ...attachmentContent.metadata,
53186
+ clientMessageId: requestId,
53187
+ device: "ios"
53188
+ }
53189
+ };
53190
+ markRunning(threadId);
53191
+ upsertMobileRun(threadId, {
53192
+ userId: mobileUserId,
53193
+ goalId: body.goalId,
53194
+ running: true,
53195
+ interrupted: false,
53196
+ logs: ["[\u5F00\u59CB] CEO \u5F00\u59CB\u5904\u7406 iOS \u6D88\u606F"],
53197
+ error: void 0
53198
+ });
53199
+ void agent(request).then((result) => {
53200
+ if (!result.alreadySent && result.content) {
53201
+ appendMobileMessage({
53202
+ threadId,
53203
+ userId: mobileUserId,
53204
+ goalId: body.goalId,
53205
+ role: "assistant",
53206
+ text: result.content,
53207
+ status: "finished",
53208
+ metadata: {
53209
+ ...teamMetadata,
53210
+ source: "agent-result"
53211
+ }
53212
+ });
53213
+ }
53214
+ upsertMobileRun(threadId, {
53215
+ userId: mobileUserId,
53216
+ goalId: body.goalId,
53217
+ running: false,
53218
+ lastResult: result.content,
53219
+ error: void 0
53220
+ });
53221
+ appendMobileRunLog(threadId, `[\u5B8C\u6210] ${result.content.slice(0, 500)}`);
53222
+ }).catch((err) => {
53223
+ appendMobileMessage({
53224
+ threadId,
53225
+ userId: mobileUserId,
53226
+ goalId: body.goalId,
53227
+ role: "system",
53228
+ text: `\u5904\u7406\u5931\u8D25\uFF1A${err.message}`,
53229
+ status: "failed",
53230
+ metadata: {
53231
+ ...teamMetadata,
53232
+ source: "agent-error"
53233
+ }
53234
+ });
53235
+ upsertMobileRun(threadId, {
53236
+ userId: mobileUserId,
53237
+ goalId: body.goalId,
53238
+ running: false,
53239
+ error: err.message
53240
+ });
53241
+ appendMobileRunLog(threadId, `[\u9519\u8BEF] ${err.message}`);
53242
+ });
53243
+ return c.json({
53244
+ ok: true,
53245
+ accepted: true,
53246
+ interrupted: false,
53247
+ threadId,
53248
+ message: userMessage2,
53249
+ run: getMobileRun(threadId)
53250
+ }, 202);
53251
+ });
53252
+ mobileRoutes.get("/mobile/messages", (c) => {
53253
+ const threadId = c.req.query("threadId");
53254
+ if (!threadId) return c.json({ error: "threadId is required" }, 400);
53255
+ const limit = Number(c.req.query("limit") ?? 20);
53256
+ const before = c.req.query("before") ? Number(c.req.query("before")) : void 0;
53257
+ const page = listMobileMessagesPage(threadId, { limit, before });
53258
+ return c.json({
53259
+ threadId,
53260
+ messages: page.messages,
53261
+ hasMore: page.hasMore,
53262
+ nextBefore: page.nextBefore
53263
+ });
53264
+ });
53265
+ mobileRoutes.get("/mobile/status", (c) => {
53266
+ const threadId = c.req.query("threadId");
53267
+ if (!threadId) return c.json({ error: "threadId is required" }, 400);
53268
+ return c.json(getMobileRun(threadId));
53269
+ });
53270
+ mobileRoutes.get("/mobile/threads/:threadId/messages", (c) => {
53271
+ const threadId = c.req.param("threadId");
53272
+ return c.json({
53273
+ threadId,
53274
+ messages: listMobileMessages(threadId)
53275
+ });
53276
+ });
53277
+ mobileRoutes.get("/mobile/threads/:threadId/status", (c) => {
53278
+ const threadId = c.req.param("threadId");
53279
+ return c.json(getMobileRun(threadId));
53280
+ });
53281
+
52610
53282
  // src/server/index.ts
52611
53283
  function createServer() {
52612
53284
  const app = new Hono2();
@@ -52622,9 +53294,10 @@ function createServer() {
52622
53294
  app.route("/api", memoryRoutes);
52623
53295
  app.route("/api", toolRoutes);
52624
53296
  app.route("/api", systemRoutes);
53297
+ app.route("/api", mobileRoutes);
52625
53298
  app.use("/*", serveStatic({ root: webDistRoot }));
52626
53299
  app.get("/*", async (c) => {
52627
- const indexHtml = await (0, import_promises11.readFile)(import_node_path15.default.join(webDistRoot, "index.html"), "utf8");
53300
+ const indexHtml = await (0, import_promises12.readFile)(import_node_path16.default.join(webDistRoot, "index.html"), "utf8");
52628
53301
  const tenantId = c.req.header("x-tenant-id");
52629
53302
  const assetBase = tenantId ? `/t/${tenantId}` : "";
52630
53303
  const html = indexHtml.replaceAll('"./', `"${assetBase}/`);
@@ -52652,9 +53325,9 @@ function shouldStartCoreChannelGateways(env = process.env) {
52652
53325
 
52653
53326
  // src/runtime/saasAssets.ts
52654
53327
  var import_node_fs9 = require("node:fs");
52655
- var import_promises12 = require("node:fs/promises");
53328
+ var import_promises13 = require("node:fs/promises");
52656
53329
  var import_node_os3 = require("node:os");
52657
- var import_node_path16 = __toESM(require("node:path"));
53330
+ var import_node_path17 = __toESM(require("node:path"));
52658
53331
  var MAX_CONTEXT_ASSETS = Number(process.env.DUCLAW_SAAS_ASSET_CONTEXT_LIMIT ?? 1e3);
52659
53332
  var MAX_SKILL_ASSETS = Number(process.env.DUCLAW_SAAS_ASSET_SKILL_LIMIT ?? 200);
52660
53333
  async function restoreSaasRuntimeAssets(reason) {
@@ -52685,8 +53358,8 @@ async function restoreContextAsset(context, overwrite) {
52685
53358
  const target = contextPathForSourceKey(context.sourceKey);
52686
53359
  if (!target) return false;
52687
53360
  if (!overwrite && (0, import_node_fs9.existsSync)(target)) return false;
52688
- await (0, import_promises12.mkdir)(import_node_path16.default.dirname(target), { recursive: true });
52689
- await (0, import_promises12.writeFile)(target, JSON.stringify(context.payload), "utf8");
53361
+ await (0, import_promises13.mkdir)(import_node_path17.default.dirname(target), { recursive: true });
53362
+ await (0, import_promises13.writeFile)(target, JSON.stringify(context.payload), "utf8");
52690
53363
  return true;
52691
53364
  }
52692
53365
  async function restoreSkillAsset(skill, overwrite) {
@@ -52694,8 +53367,8 @@ async function restoreSkillAsset(skill, overwrite) {
52694
53367
  const target = safeSkillTargetPath(skill.sourcePath, skill.skillName);
52695
53368
  if (!target) return false;
52696
53369
  if (!overwrite && (0, import_node_fs9.existsSync)(target)) return false;
52697
- await (0, import_promises12.mkdir)(import_node_path16.default.dirname(target), { recursive: true });
52698
- await (0, import_promises12.writeFile)(target, skill.skillMd, "utf8");
53370
+ await (0, import_promises13.mkdir)(import_node_path17.default.dirname(target), { recursive: true });
53371
+ await (0, import_promises13.writeFile)(target, skill.skillMd, "utf8");
52699
53372
  return true;
52700
53373
  }
52701
53374
  function runtimeAssetClient() {
@@ -52727,30 +53400,30 @@ function runtimeAssetClient() {
52727
53400
  function contextPathForSourceKey(sourceKey) {
52728
53401
  if (sourceKey.startsWith("agent:")) {
52729
53402
  const logicalKey = sourceKey.slice("agent:".length);
52730
- return import_node_path16.default.join(getDuclawDataDir(), "kv", "agent", `${Buffer.from(logicalKey).toString("base64url")}.json`);
53403
+ return import_node_path17.default.join(getDuclawDataDir(), "kv", "agent", `${Buffer.from(logicalKey).toString("base64url")}.json`);
52731
53404
  }
52732
53405
  if (sourceKey.startsWith("goal-context:")) {
52733
- return import_node_path16.default.join(getDuclawHomeDir(), "goal-context", `${sourceKey.slice("goal-context:".length)}.json`);
53406
+ return import_node_path17.default.join(getDuclawHomeDir(), "goal-context", `${sourceKey.slice("goal-context:".length)}.json`);
52734
53407
  }
52735
53408
  if (sourceKey.startsWith("tasks:")) {
52736
- return import_node_path16.default.join(getDuclawHomeDir(), "tasks", `${sourceKey.slice("tasks:".length)}.json`);
53409
+ return import_node_path17.default.join(getDuclawHomeDir(), "tasks", `${sourceKey.slice("tasks:".length)}.json`);
52737
53410
  }
52738
53411
  return null;
52739
53412
  }
52740
53413
  function safeSkillTargetPath(sourcePath, skillName) {
52741
- const allowedRoots = skillRoots().map((root) => import_node_path16.default.resolve(root));
52742
- const normalized = import_node_path16.default.resolve(sourcePath);
52743
- if (allowedRoots.some((root) => normalized === import_node_path16.default.join(root, import_node_path16.default.basename(import_node_path16.default.dirname(normalized)), "SKILL.md"))) {
53414
+ const allowedRoots = skillRoots().map((root) => import_node_path17.default.resolve(root));
53415
+ const normalized = import_node_path17.default.resolve(sourcePath);
53416
+ if (allowedRoots.some((root) => normalized === import_node_path17.default.join(root, import_node_path17.default.basename(import_node_path17.default.dirname(normalized)), "SKILL.md"))) {
52744
53417
  return normalized;
52745
53418
  }
52746
53419
  const safeName = skillName.replace(/[^a-zA-Z0-9._-]/g, "-").slice(0, 120) || "imported-skill";
52747
- return import_node_path16.default.join("/home/user/app/skills", safeName, "SKILL.md");
53420
+ return import_node_path17.default.join("/home/user/app/skills", safeName, "SKILL.md");
52748
53421
  }
52749
53422
  function skillRoots() {
52750
53423
  return [
52751
53424
  "/home/user/app/skills",
52752
- import_node_path16.default.join(getDuclawHomeDir(), "skills"),
52753
- import_node_path16.default.join((0, import_node_os3.homedir)(), ".agents", "skills")
53425
+ import_node_path17.default.join(getDuclawHomeDir(), "skills"),
53426
+ import_node_path17.default.join((0, import_node_os3.homedir)(), ".agents", "skills")
52754
53427
  ];
52755
53428
  }
52756
53429