adam-agent-server 1.8.0 → 1.9.0

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.
Files changed (135) hide show
  1. package/README.md +8 -0
  2. package/dist/App-5QZKMPRM.js +13 -0
  3. package/dist/adam-tools-FSI5XKDL.js +1 -0
  4. package/dist/{approval-handler-PB7PSLUS.js → approval-handler-JYCGXQUE.js} +1 -1
  5. package/dist/audit-manager-CLKTJPLM.js +1 -0
  6. package/dist/bree-engine-XJR5TKVC.js +1 -0
  7. package/dist/channels-DY2OW7YQ.js +1 -0
  8. package/dist/{channels-ULFUCUUZ.js → channels-ZNMTMMCY.js} +1 -1
  9. package/dist/{chunk-BQ3ZAYHC.js → chunk-3HZE5DQZ.js} +1 -1
  10. package/dist/chunk-3IQADR6L.js +144 -0
  11. package/dist/{chunk-NASJH4NT.js → chunk-3N7MGASP.js} +1 -1
  12. package/dist/{chunk-TAF2DBBC.js → chunk-56QP5ZHF.js} +7 -7
  13. package/dist/{chunk-PG6LMSX6.js → chunk-5AUQIK3Q.js} +1 -1
  14. package/dist/{chunk-NUITL62I.js → chunk-6M2QCKAS.js} +1 -1
  15. package/dist/{chunk-WMB7P64J.js → chunk-6XVWIRR2.js} +1 -1
  16. package/dist/{chunk-5EPG2US5.js → chunk-7F4SZXI2.js} +39 -10
  17. package/dist/{chunk-JJH2RCVC.js → chunk-7WJF65TQ.js} +1 -1
  18. package/dist/{chunk-RZ7LCZVK.js → chunk-ARQF52V6.js} +1 -1
  19. package/dist/{chunk-NWMOV23A.js → chunk-C2SD2NMZ.js} +1 -1
  20. package/dist/{chunk-2L2347UQ.js → chunk-DKMF4B33.js} +1 -1
  21. package/dist/{chunk-EQZFOBAJ.js → chunk-EJBGJLA2.js} +1 -1
  22. package/dist/{chunk-T33BLZV2.js → chunk-HSEP6LNQ.js} +1 -1
  23. package/dist/{chunk-GSFLLRS7.js → chunk-IZ3WZHCM.js} +1 -1
  24. package/dist/chunk-J4Y54LIC.js +50 -0
  25. package/dist/{chunk-AQ3ASS4B.js → chunk-KO7XBNPV.js} +1 -1
  26. package/dist/{chunk-RI3V72RP.js → chunk-KUJFQDT5.js} +2 -2
  27. package/dist/{chunk-DVN3BFPP.js → chunk-LV4XLPCD.js} +1 -1
  28. package/dist/chunk-MYVYH4PQ.js +77 -0
  29. package/dist/chunk-OFTIPZTH.js +1 -0
  30. package/dist/{chunk-K4C43YDD.js → chunk-OY2KVSIX.js} +1 -1
  31. package/dist/{chunk-IKPYPZ64.js → chunk-PFYYS7CI.js} +1 -1
  32. package/dist/chunk-QMW7VEPC.js +0 -0
  33. package/dist/{chunk-A5OCDYTW.js → chunk-QPIWPQWM.js} +1 -1
  34. package/dist/chunk-S6OV7Z6K.js +1 -0
  35. package/dist/{chunk-2YTDCR6A.js → chunk-TTP7QRAQ.js} +1 -1
  36. package/dist/{chunk-B6LOT5CG.js → chunk-UQDC3X6O.js} +1 -1
  37. package/dist/{chunk-M4YI4WVX.js → chunk-UYOLAFUR.js} +1 -1
  38. package/dist/chunk-VPZSOYE5.js +6 -0
  39. package/dist/{chunk-5QZXYKMS.js → chunk-W7U3ASGR.js} +1 -1
  40. package/dist/chunk-XIQVXRZH.js +27 -0
  41. package/dist/{chunk-FPZEZYUB.js → chunk-XTOOD44S.js} +1 -1
  42. package/dist/{chunk-6KF7OO2B.js → chunk-YKMWAVUH.js} +1 -1
  43. package/dist/{chunk-UQJZU3R5.js → chunk-YVVKUPGL.js} +1 -1
  44. package/dist/{chunk-HQRUJQN7.js → chunk-YWUX3ZTO.js} +4 -4
  45. package/dist/cli.js +2 -2
  46. package/dist/{config-HBQPBIWL.js → config-CILWJYZB.js} +1 -1
  47. package/dist/config-W2OD7PXZ.js +1 -0
  48. package/dist/{db-QEWTZGU3.js → db-JO24ZLIN.js} +1 -1
  49. package/dist/{delivery-log-AC476GX7.js → delivery-log-QPQM5YU7.js} +1 -1
  50. package/dist/engine-ZAPYG7G4.js +1 -0
  51. package/dist/{evolution-audit-XMBDUN3T.js → evolution-audit-ZLYQ3ZYV.js} +1 -1
  52. package/dist/{external-api-V74YTLBY.js → external-api-QKRNGSYS.js} +1 -1
  53. package/dist/index.js +20 -16
  54. package/dist/{learner-VCS3Q7BR.js → learner-ACHENH6R.js} +1 -1
  55. package/dist/{memories-VMOGFVPU.js → memories-LXH4VHCH.js} +1 -1
  56. package/dist/{memory-extractor-4WJNHYWR.js → memory-extractor-URH4YHK3.js} +2 -2
  57. package/dist/memory-service-23P6VNKZ.js +1 -0
  58. package/dist/outbound-gateway-Y3P3T3VH.js +1 -0
  59. package/dist/presets-XR2OBXUP.js +1 -0
  60. package/dist/role-presets-DYWDEQYU.js +1 -0
  61. package/dist/role-workspace-LHW7AWPF.js +1 -0
  62. package/dist/{roles-ZYCFQMAY.js → roles-DRPLO4LY.js} +1 -1
  63. package/dist/{runtime-VDBZZ4KG.js → runtime-YPBWWMXW.js} +1 -1
  64. package/dist/session-manager-Z6K4U5X7.js +1 -0
  65. package/dist/{task-templates-4KCZOUN5.js → task-templates-4DWXHLFZ.js} +1 -1
  66. package/dist/workflow-executor-6ZMNL34C.js +1 -0
  67. package/package.json +2 -1
  68. package/web/dist/assets/{AlertDialog-B1zj0Qs3.js → AlertDialog-DhA65f_0.js} +1 -1
  69. package/web/dist/assets/{Button-BehrGSvy.js → Button-CYDgoTTo.js} +1 -1
  70. package/web/dist/assets/{Card-B5E56u94.js → Card-DDGXsHus.js} +1 -1
  71. package/web/dist/assets/{ChannelDetail-BaSlX2yb.js → ChannelDetail-Bb8P8It_.js} +1 -1
  72. package/web/dist/assets/{Channels-CLhgGEmS.js → Channels-8j28oydE.js} +2 -2
  73. package/web/dist/assets/{Chat-BZpf1DSF.js → Chat-BZwLDoYO.js} +2 -2
  74. package/web/dist/assets/{Dashboard-HR4Qmdwg.js → Dashboard-Cv0AtO-o.js} +1 -1
  75. package/web/dist/assets/{EmptyState-tTclFq_B.js → EmptyState-EuQHAv5Y.js} +1 -1
  76. package/web/dist/assets/{EnvVarEditor-BzJNsDt0.js → EnvVarEditor-r-l-u4V7.js} +1 -1
  77. package/web/dist/assets/{EventDefDetail-CjoqsH0e.js → EventDefDetail-asUFrbQE.js} +1 -1
  78. package/web/dist/assets/Events-DtkHL-r2.js +1 -0
  79. package/web/dist/assets/{Evolution-CUn8g34X.js → Evolution-DIqYOSb8.js} +1 -1
  80. package/web/dist/assets/FeatureRequests-BxPqLR1x.js +1 -0
  81. package/web/dist/assets/{GoalDetail-DgPvXb6z.js → GoalDetail-Bkvgg6uI.js} +1 -1
  82. package/web/dist/assets/Goals-CkKJDCiU.js +1 -0
  83. package/web/dist/assets/{Logs-CvFC-GbD.js → Logs-DnaaHV0Y.js} +1 -1
  84. package/web/dist/assets/{Memories-B5pvI6Oj.js → Memories-Dq9S-Tsi.js} +1 -1
  85. package/web/dist/assets/Mistakes-D5lW31Co.js +1 -0
  86. package/web/dist/assets/{NotFound-D-OII_Lp.js → NotFound-gJVrOtER.js} +1 -1
  87. package/web/dist/assets/{PageHeader-B2CgcZ-t.js → PageHeader-CugYeCci.js} +1 -1
  88. package/web/dist/assets/Plugins-CoRmK2UG.js +1 -0
  89. package/web/dist/assets/{RoleDetail-BBJxaZip.js → RoleDetail-BHJA_PAn.js} +2 -2
  90. package/web/dist/assets/Roles-EBUueS_P.js +1 -0
  91. package/web/dist/assets/{SectionHeader-CmXz6PM3.js → SectionHeader-DihC0CnO.js} +1 -1
  92. package/web/dist/assets/Settings-DZHAGazz.js +1 -0
  93. package/web/dist/assets/{Strategies-Ddb5HiUS.js → Strategies-3IV9eueQ.js} +1 -1
  94. package/web/dist/assets/{Switch-yrTepsdl.js → Switch-B3w5KMMc.js} +1 -1
  95. package/web/dist/assets/{Table-CXAcZ8Ru.js → Table-Cf6m8zLu.js} +1 -1
  96. package/web/dist/assets/{TaskDetail-CHwHgfZq.js → TaskDetail-BmXaH3sx.js} +2 -2
  97. package/web/dist/assets/Work-CvQrOKtL.js +1 -0
  98. package/web/dist/assets/api-D-UzHSDq.js +1 -0
  99. package/web/dist/assets/index-BsKlGx3x.js +2 -0
  100. package/web/dist/assets/index-EqsPGp9a.css +2 -0
  101. package/web/dist/assets/{useIsMobileLayout-dYzXP1EC.js → useIsMobileLayout-2GbB90oO.js} +1 -1
  102. package/web/dist/assets/{vendor-icons-Dk0hMuJz.js → vendor-icons-PF9RcPJx.js} +1 -1
  103. package/web/dist/assets/{vendor-react-C6faO6LO.js → vendor-react-Cxy4EVtR.js} +1 -1
  104. package/web/dist/assets/{vendor-state-DahK0J-G.js → vendor-state-aQJ7d4tA.js} +1 -1
  105. package/web/dist/index.html +8 -8
  106. package/dist/App-ZRCRM7WR.js +0 -13
  107. package/dist/adam-automator-skills-EZGBICHT.js +0 -18
  108. package/dist/adam-tools-V5LPU47X.js +0 -1
  109. package/dist/audit-manager-BSBBDUER.js +0 -1
  110. package/dist/bree-engine-7S33CWS7.js +0 -1
  111. package/dist/channels-SITUUC4J.js +0 -1
  112. package/dist/chunk-4PQHGLZH.js +0 -99
  113. package/dist/chunk-5XOTPEAK.js +0 -6
  114. package/dist/chunk-BCH2HAIM.js +0 -23
  115. package/dist/chunk-GSMC3VUM.js +0 -1
  116. package/dist/chunk-IZNEOYRP.js +0 -1
  117. package/dist/chunk-QGYDGZSC.js +0 -49
  118. package/dist/chunk-ULTK7RD6.js +0 -27
  119. package/dist/config-ZBNGRASI.js +0 -1
  120. package/dist/engine-6K4RG644.js +0 -1
  121. package/dist/memory-service-ZS6MBUIC.js +0 -1
  122. package/dist/outbound-gateway-H7RFG6D2.js +0 -1
  123. package/dist/role-presets-XAEOYEAW.js +0 -1
  124. package/dist/role-workspace-NKGAH6J6.js +0 -1
  125. package/dist/session-manager-COLCNIB7.js +0 -1
  126. package/dist/workflow-executor-Z7JFMR56.js +0 -1
  127. package/web/dist/assets/Events-IeznRpCj.js +0 -1
  128. package/web/dist/assets/Goals-DYrggK-M.js +0 -1
  129. package/web/dist/assets/Plugins-BuE7GImW.js +0 -1
  130. package/web/dist/assets/Roles-C5eVA6LM.js +0 -1
  131. package/web/dist/assets/Settings-BblOdOih.js +0 -1
  132. package/web/dist/assets/Work-Corw0ITh.js +0 -1
  133. package/web/dist/assets/api-Bux34u4-.js +0 -1
  134. package/web/dist/assets/index-B3_4_qY6.js +0 -2
  135. package/web/dist/assets/index-Cu5neZGw.css +0 -2
@@ -1,4 +1,4 @@
1
- import{e as R,h as p}from"./chunk-WBAPIPST.js";import{c as m,h as O}from"./chunk-MRTJFYPR.js";import{c as I}from"./chunk-FCV2DPZQ.js";import X from"better-sqlite3";import{existsSync as S,mkdirSync as u}from"fs";import{dirname as g}from"path";function U(e){e.exec(`
1
+ import{e as R,h as I}from"./chunk-WBAPIPST.js";import{c as m,h as O}from"./chunk-MRTJFYPR.js";import{c as p}from"./chunk-FCV2DPZQ.js";import X from"better-sqlite3";import{existsSync as S,mkdirSync as u}from"fs";import{dirname as g}from"path";function U(e){e.exec(`
2
2
  CREATE TABLE IF NOT EXISTS server_state (
3
3
  id INTEGER PRIMARY KEY CHECK(id = 1),
4
4
  sdk_session_id TEXT,
@@ -466,7 +466,7 @@ import{e as R,h as p}from"./chunk-WBAPIPST.js";import{c as m,h as O}from"./chunk
466
466
  source TEXT DEFAULT 'reflection'
467
467
  );
468
468
  CREATE INDEX IF NOT EXISTS idx_evolution_audit_role_id ON evolution_audit(role_id);
469
- `),e.exec("UPDATE server_state SET schema_version = 5 WHERE id = 1")),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<6&&(e.prepare("PRAGMA table_info(roles)").all().some(s=>s.name==="importance_trigger_curr")||e.exec("ALTER TABLE roles ADD COLUMN importance_trigger_curr INTEGER DEFAULT 150"),e.exec("UPDATE server_state SET schema_version = 6 WHERE id = 1")),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<7&&(e.prepare("PRAGMA table_info(tasks)").all().some(s=>s.name==="source_session_id")||e.exec("ALTER TABLE tasks ADD COLUMN source_session_id TEXT"),e.exec("UPDATE server_state SET schema_version = 7 WHERE id = 1")),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<8){let E=e.prepare("PRAGMA table_info(goals)").all();E.some(T=>T.name==="source_session_id")||e.exec("ALTER TABLE goals ADD COLUMN source_session_id TEXT"),E.some(T=>T.name==="notify_targets")||e.exec("ALTER TABLE goals ADD COLUMN notify_targets TEXT");let s=e.prepare("PRAGMA table_info(task_templates)").all();s.some(T=>T.name==="source_session_id")||e.exec("ALTER TABLE task_templates ADD COLUMN source_session_id TEXT"),s.some(T=>T.name==="notify_targets")||e.exec("ALTER TABLE task_templates ADD COLUMN notify_targets TEXT"),s.some(T=>T.name==="goal_ids")||e.exec("ALTER TABLE task_templates ADD COLUMN goal_ids TEXT"),e.exec("UPDATE goals SET status = 'active' WHERE status IN ('pending','planning','executing','evaluating','replanning')"),e.exec("UPDATE server_state SET schema_version = 8 WHERE id = 1")}if((e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<10){e.exec("PRAGMA foreign_keys = OFF"),e.exec("DROP TABLE IF EXISTS tasks_new"),e.exec("DROP TABLE IF EXISTS chat_sessions_new"),e.exec("DROP TABLE IF EXISTS task_plans_new"),e.exec("DROP TABLE IF EXISTS task_plugins_new"),e.exec("DROP TABLE IF EXISTS approval_rules_new"),e.exec("DROP TABLE IF EXISTS manager_decisions_new"),e.exec("DROP TABLE IF EXISTS channels_new");let E=e.prepare("PRAGMA table_info(roles)").all();E.some(r=>r.name==="allowed_tools")||e.exec("ALTER TABLE roles ADD COLUMN allowed_tools TEXT"),E.some(r=>r.name==="disallowed_tools")||e.exec("ALTER TABLE roles ADD COLUMN disallowed_tools TEXT"),E.some(r=>r.name==="evaluation_criteria")||e.exec("ALTER TABLE roles ADD COLUMN evaluation_criteria TEXT"),E.some(r=>r.name==="execution_mode")||e.exec("ALTER TABLE roles ADD COLUMN execution_mode TEXT DEFAULT 'isolated'"),E.some(r=>r.name==="model")||e.exec("ALTER TABLE roles ADD COLUMN model TEXT"),E.some(r=>r.name==="max_budget_usd")||e.exec("ALTER TABLE roles ADD COLUMN max_budget_usd REAL"),E.some(r=>r.name==="approval_required")||e.exec("ALTER TABLE roles ADD COLUMN approval_required TEXT"),E.some(r=>r.name==="source")||e.exec("ALTER TABLE roles ADD COLUMN source TEXT DEFAULT 'system'"),e.exec("DROP TABLE IF EXISTS agents"),e.exec("DROP TABLE IF EXISTS role_skills"),e.exec(`
469
+ `),e.exec("UPDATE server_state SET schema_version = 5 WHERE id = 1")),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<6&&(e.prepare("PRAGMA table_info(roles)").all().some(s=>s.name==="importance_trigger_curr")||e.exec("ALTER TABLE roles ADD COLUMN importance_trigger_curr INTEGER DEFAULT 150"),e.exec("UPDATE server_state SET schema_version = 6 WHERE id = 1")),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<7&&(e.prepare("PRAGMA table_info(tasks)").all().some(s=>s.name==="source_session_id")||e.exec("ALTER TABLE tasks ADD COLUMN source_session_id TEXT"),e.exec("UPDATE server_state SET schema_version = 7 WHERE id = 1")),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<8){let E=e.prepare("PRAGMA table_info(goals)").all();E.some(T=>T.name==="source_session_id")||e.exec("ALTER TABLE goals ADD COLUMN source_session_id TEXT"),E.some(T=>T.name==="notify_targets")||e.exec("ALTER TABLE goals ADD COLUMN notify_targets TEXT");let s=e.prepare("PRAGMA table_info(task_templates)").all();s.some(T=>T.name==="source_session_id")||e.exec("ALTER TABLE task_templates ADD COLUMN source_session_id TEXT"),s.some(T=>T.name==="notify_targets")||e.exec("ALTER TABLE task_templates ADD COLUMN notify_targets TEXT"),s.some(T=>T.name==="goal_ids")||e.exec("ALTER TABLE task_templates ADD COLUMN goal_ids TEXT"),e.exec("UPDATE goals SET status = 'active' WHERE status IN ('pending','planning','executing','evaluating','replanning')"),e.exec("UPDATE server_state SET schema_version = 8 WHERE id = 1")}if((e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<10){e.exec("PRAGMA foreign_keys = OFF"),e.exec("DROP TABLE IF EXISTS tasks_new"),e.exec("DROP TABLE IF EXISTS chat_sessions_new"),e.exec("DROP TABLE IF EXISTS task_plans_new"),e.exec("DROP TABLE IF EXISTS task_plugins_new"),e.exec("DROP TABLE IF EXISTS approval_rules_new"),e.exec("DROP TABLE IF EXISTS manager_decisions_new"),e.exec("DROP TABLE IF EXISTS channels_new");let E=e.prepare("PRAGMA table_info(roles)").all();E.some(t=>t.name==="allowed_tools")||e.exec("ALTER TABLE roles ADD COLUMN allowed_tools TEXT"),E.some(t=>t.name==="disallowed_tools")||e.exec("ALTER TABLE roles ADD COLUMN disallowed_tools TEXT"),E.some(t=>t.name==="evaluation_criteria")||e.exec("ALTER TABLE roles ADD COLUMN evaluation_criteria TEXT"),E.some(t=>t.name==="execution_mode")||e.exec("ALTER TABLE roles ADD COLUMN execution_mode TEXT DEFAULT 'isolated'"),E.some(t=>t.name==="model")||e.exec("ALTER TABLE roles ADD COLUMN model TEXT"),E.some(t=>t.name==="max_budget_usd")||e.exec("ALTER TABLE roles ADD COLUMN max_budget_usd REAL"),E.some(t=>t.name==="approval_required")||e.exec("ALTER TABLE roles ADD COLUMN approval_required TEXT"),E.some(t=>t.name==="source")||e.exec("ALTER TABLE roles ADD COLUMN source TEXT DEFAULT 'system'"),e.exec("DROP TABLE IF EXISTS agents"),e.exec("DROP TABLE IF EXISTS role_skills"),e.exec(`
470
470
  CREATE TABLE IF NOT EXISTS tasks_new (
471
471
  id TEXT PRIMARY KEY,
472
472
  parent_id TEXT,
@@ -491,7 +491,7 @@ import{e as R,h as p}from"./chunk-WBAPIPST.js";import{c as m,h as O}from"./chunk
491
491
  num_turns INTEGER,
492
492
  total_duration_ms INTEGER
493
493
  );
494
- `);let s=new Set(["id","status","prompt","config","created_at"]),T=["id","parent_id","status","prompt","config","result","error","sdk_session_id","template_id","original_prompt","role_id","source_session_id","notify_targets","deliver_to","report_to","created_at","started_at","completed_at","cost_usd","token_usage","num_turns","total_duration_ms"],t=new Set(e.prepare("PRAGMA table_info(tasks)").all().map(r=>r.name)),i=T.map(r=>t.has(r)?s.has(r)?`COALESCE(${r}, '')`:r:"NULL").join(",");e.exec(`INSERT INTO tasks_new SELECT ${i} FROM tasks`),e.exec("DROP TABLE tasks"),e.exec("ALTER TABLE tasks_new RENAME TO tasks"),e.exec("CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status)"),e.exec("CREATE INDEX IF NOT EXISTS idx_tasks_created_at ON tasks(created_at)"),e.exec("CREATE INDEX IF NOT EXISTS idx_tasks_template_id ON tasks(template_id)"),e.exec("CREATE INDEX IF NOT EXISTS idx_tasks_role_id ON tasks(role_id)"),e.exec(`
494
+ `);let s=new Set(["id","status","prompt","config","created_at"]),T=["id","parent_id","status","prompt","config","result","error","sdk_session_id","template_id","original_prompt","role_id","source_session_id","notify_targets","deliver_to","report_to","created_at","started_at","completed_at","cost_usd","token_usage","num_turns","total_duration_ms"],r=new Set(e.prepare("PRAGMA table_info(tasks)").all().map(t=>t.name)),i=T.map(t=>r.has(t)?s.has(t)?`COALESCE(${t}, '')`:t:"NULL").join(",");e.exec(`INSERT INTO tasks_new SELECT ${i} FROM tasks`),e.exec("DROP TABLE tasks"),e.exec("ALTER TABLE tasks_new RENAME TO tasks"),e.exec("CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status)"),e.exec("CREATE INDEX IF NOT EXISTS idx_tasks_created_at ON tasks(created_at)"),e.exec("CREATE INDEX IF NOT EXISTS idx_tasks_template_id ON tasks(template_id)"),e.exec("CREATE INDEX IF NOT EXISTS idx_tasks_role_id ON tasks(role_id)"),e.exec(`
495
495
  CREATE TABLE IF NOT EXISTS chat_sessions_new (
496
496
  id TEXT PRIMARY KEY,
497
497
  status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active', 'archived')),
@@ -517,7 +517,7 @@ import{e as R,h as p}from"./chunk-WBAPIPST.js";import{c as m,h as O}from"./chunk
517
517
  approved_at INTEGER,
518
518
  reviewed_at INTEGER
519
519
  );
520
- `),e.exec("INSERT INTO task_plans_new SELECT id,task_id,plan_json,status,approval_type,deviation_report_json,learned_rules_json,created_at,approved_at,reviewed_at FROM task_plans"),e.exec("DROP TABLE task_plans"),e.exec("ALTER TABLE task_plans_new RENAME TO task_plans"),e.exec("CREATE INDEX IF NOT EXISTS idx_task_plans_task_id ON task_plans(task_id)"),e.exec("CREATE INDEX IF NOT EXISTS idx_task_plans_status ON task_plans(status)"),e.prepare("PRAGMA table_info(task_plugins)").all().some(r=>r.name==="skill_id")&&(e.exec(`
520
+ `),e.exec("INSERT INTO task_plans_new SELECT id,task_id,plan_json,status,approval_type,deviation_report_json,learned_rules_json,created_at,approved_at,reviewed_at FROM task_plans"),e.exec("DROP TABLE task_plans"),e.exec("ALTER TABLE task_plans_new RENAME TO task_plans"),e.exec("CREATE INDEX IF NOT EXISTS idx_task_plans_task_id ON task_plans(task_id)"),e.exec("CREATE INDEX IF NOT EXISTS idx_task_plans_status ON task_plans(status)"),e.prepare("PRAGMA table_info(task_plugins)").all().some(t=>t.name==="skill_id")&&(e.exec(`
521
521
  CREATE TABLE IF NOT EXISTS task_plugins_new (
522
522
  id TEXT PRIMARY KEY,
523
523
  task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
@@ -526,7 +526,7 @@ import{e as R,h as p}from"./chunk-WBAPIPST.js";import{c as m,h as O}from"./chunk
526
526
  role_id TEXT,
527
527
  used_at INTEGER NOT NULL
528
528
  );
529
- `),e.exec("INSERT INTO task_plugins_new SELECT id,task_id,plugin_path,plugin_name,skill_id,used_at FROM task_plugins"),e.exec("DROP TABLE task_plugins"),e.exec("ALTER TABLE task_plugins_new RENAME TO task_plugins")),e.exec("CREATE INDEX IF NOT EXISTS idx_task_plugins_task_id ON task_plugins(task_id)"),e.exec("CREATE INDEX IF NOT EXISTS idx_task_plugins_plugin_path ON task_plugins(plugin_path)"),e.exec("CREATE INDEX IF NOT EXISTS idx_task_plugins_role_id ON task_plugins(role_id)"),e.prepare("PRAGMA table_info(approval_rules)").all().some(r=>r.name==="skill_id")&&(e.exec(`
529
+ `),e.exec("INSERT INTO task_plugins_new SELECT id,task_id,plugin_path,plugin_name,skill_id,used_at FROM task_plugins"),e.exec("DROP TABLE task_plugins"),e.exec("ALTER TABLE task_plugins_new RENAME TO task_plugins")),e.exec("CREATE INDEX IF NOT EXISTS idx_task_plugins_task_id ON task_plugins(task_id)"),e.exec("CREATE INDEX IF NOT EXISTS idx_task_plugins_plugin_path ON task_plugins(plugin_path)"),e.exec("CREATE INDEX IF NOT EXISTS idx_task_plugins_role_id ON task_plugins(role_id)"),e.prepare("PRAGMA table_info(approval_rules)").all().some(t=>t.name==="skill_id")&&(e.exec(`
530
530
  CREATE TABLE IF NOT EXISTS approval_rules_new (
531
531
  id TEXT PRIMARY KEY,
532
532
  role_id TEXT,
@@ -535,7 +535,7 @@ import{e as R,h as p}from"./chunk-WBAPIPST.js";import{c as m,h as O}from"./chunk
535
535
  created_at INTEGER NOT NULL,
536
536
  created_by_task_id TEXT REFERENCES tasks(id)
537
537
  );
538
- `),e.exec("INSERT INTO approval_rules_new SELECT id,skill_id,task_pattern,max_risk_level,created_at,created_by_task_id FROM approval_rules"),e.exec("DROP TABLE approval_rules"),e.exec("ALTER TABLE approval_rules_new RENAME TO approval_rules")),e.exec("CREATE INDEX IF NOT EXISTS idx_approval_rules_role_id ON approval_rules(role_id)"),e.prepare("PRAGMA table_info(manager_decisions)").all().some(r=>r.name==="skill_id")&&(e.exec(`
538
+ `),e.exec("INSERT INTO approval_rules_new SELECT id,skill_id,task_pattern,max_risk_level,created_at,created_by_task_id FROM approval_rules"),e.exec("DROP TABLE approval_rules"),e.exec("ALTER TABLE approval_rules_new RENAME TO approval_rules")),e.exec("CREATE INDEX IF NOT EXISTS idx_approval_rules_role_id ON approval_rules(role_id)"),e.prepare("PRAGMA table_info(manager_decisions)").all().some(t=>t.name==="skill_id")&&(e.exec(`
539
539
  CREATE TABLE IF NOT EXISTS manager_decisions_new (
540
540
  id TEXT PRIMARY KEY,
541
541
  task_id TEXT NOT NULL REFERENCES tasks(id),
@@ -545,7 +545,7 @@ import{e as R,h as p}from"./chunk-WBAPIPST.js";import{c as m,h as O}from"./chunk
545
545
  reason TEXT,
546
546
  created_at INTEGER NOT NULL
547
547
  );
548
- `),e.exec("INSERT INTO manager_decisions_new SELECT id,task_id,skill_id,decision_type,boundary_json,reason,created_at FROM manager_decisions"),e.exec("DROP TABLE manager_decisions"),e.exec("ALTER TABLE manager_decisions_new RENAME TO manager_decisions")),e.exec("CREATE INDEX IF NOT EXISTS idx_manager_decisions_task_id ON manager_decisions(task_id)"),e.exec("CREATE INDEX IF NOT EXISTS idx_manager_decisions_role_id ON manager_decisions(role_id)"),e.prepare("PRAGMA table_info(channels)").all().some(r=>r.name==="linked_skill_id")&&(e.exec(`
548
+ `),e.exec("INSERT INTO manager_decisions_new SELECT id,task_id,skill_id,decision_type,boundary_json,reason,created_at FROM manager_decisions"),e.exec("DROP TABLE manager_decisions"),e.exec("ALTER TABLE manager_decisions_new RENAME TO manager_decisions")),e.exec("CREATE INDEX IF NOT EXISTS idx_manager_decisions_task_id ON manager_decisions(task_id)"),e.exec("CREATE INDEX IF NOT EXISTS idx_manager_decisions_role_id ON manager_decisions(role_id)"),e.prepare("PRAGMA table_info(channels)").all().some(t=>t.name==="linked_skill_id")&&(e.exec(`
549
549
  CREATE TABLE IF NOT EXISTS channels_new (
550
550
  id TEXT PRIMARY KEY,
551
551
  name TEXT NOT NULL,
@@ -567,7 +567,7 @@ import{e as R,h as p}from"./chunk-WBAPIPST.js";import{c as m,h as O}from"./chunk
567
567
  bound_at INTEGER NOT NULL,
568
568
  PRIMARY KEY (role_id, plugin_id)
569
569
  );
570
- `),e.exec("UPDATE server_state SET schema_version = 10 WHERE id = 1"),e.exec("PRAGMA foreign_keys = ON")}if(o<11){try{e.exec("ALTER TABLE task_templates RENAME COLUMN skill_preference TO role_preference")}catch(E){let s=e.prepare("PRAGMA table_info(task_templates)").all(),T=s.some(i=>i.name==="role_preference"),t=s.some(i=>i.name==="skill_preference");if(!T&&t)throw E}e.exec("UPDATE server_state SET schema_version = 11 WHERE id = 1")}if(o<12&&(e.prepare("PRAGMA table_info(server_state)").all().some(s=>s.name==="tools_fingerprint")||e.exec("ALTER TABLE server_state ADD COLUMN tools_fingerprint TEXT"),e.exec("UPDATE server_state SET schema_version = 12 WHERE id = 1")),o<13&&(e.prepare("PRAGMA table_info(roles)").all().some(s=>s.name==="additional_directories")||e.exec("ALTER TABLE roles ADD COLUMN additional_directories TEXT"),e.exec("UPDATE server_state SET schema_version = 13 WHERE id = 1")),o<14){let E=e.prepare("PRAGMA table_info(roles)").all();E.some(t=>t.name==="allowed_channels")||e.exec("ALTER TABLE roles ADD COLUMN allowed_channels TEXT"),E.some(t=>t.name==="mcp_servers")||e.exec("ALTER TABLE roles ADD COLUMN mcp_servers TEXT");let s=e.prepare("PRAGMA table_info(tasks)").all();s.some(t=>t.name==="deliver_to")||e.exec("ALTER TABLE tasks ADD COLUMN deliver_to TEXT"),s.some(t=>t.name==="report_to")||e.exec("ALTER TABLE tasks ADD COLUMN report_to TEXT"),e.prepare("PRAGMA table_info(goals)").all().some(t=>t.name==="deliver_to")||e.exec("ALTER TABLE goals ADD COLUMN deliver_to TEXT"),e.exec("UPDATE server_state SET schema_version = 14 WHERE id = 1")}if(o<15&&(e.prepare("PRAGMA table_info(roles)").all().some(s=>s.name==="inherit_user_settings")||e.exec("ALTER TABLE roles ADD COLUMN inherit_user_settings INTEGER DEFAULT 0"),e.exec("UPDATE server_state SET schema_version = 15 WHERE id = 1")),o<16&&(e.prepare("PRAGMA table_info(task_templates)").all().some(s=>s.name==="deliver_to")||e.exec("ALTER TABLE task_templates ADD COLUMN deliver_to TEXT"),e.exec("UPDATE server_state SET schema_version = 16 WHERE id = 1")),o<17){e.exec("PRAGMA foreign_keys = OFF"),e.exec("DROP TABLE IF EXISTS plugins"),e.exec("DROP TABLE IF EXISTS role_plugins"),e.exec("DROP TABLE IF EXISTS marketplaces"),e.exec("DROP INDEX IF EXISTS idx_plugins_source"),e.exec("DROP INDEX IF EXISTS idx_plugins_enabled");try{let T=e.prepare("SELECT id, additional_directories FROM roles WHERE additional_directories IS NOT NULL").all();for(let t of T)try{let i=JSON.parse(t.additional_directories);if(i.length>0&&typeof i[0]=="object"&&i[0]!==null&&"path"in i[0])continue;let n=i.map(_=>typeof _=="string"?{path:_}:_);e.prepare("UPDATE roles SET additional_directories = ? WHERE id = ?").run(JSON.stringify(n),t.id)}catch{}}catch{}let E=e.prepare("PRAGMA table_info(tasks)").all();E.some(T=>T.name==="deliver_to")||e.exec("ALTER TABLE tasks ADD COLUMN deliver_to TEXT"),E.some(T=>T.name==="report_to")||e.exec("ALTER TABLE tasks ADD COLUMN report_to TEXT");let s=e.prepare("PRAGMA table_info(strategies)").all();s.some(T=>T.name==="role")&&!s.some(T=>T.name==="role_id")&&(e.exec("ALTER TABLE strategies RENAME COLUMN role TO role_id"),e.exec("DROP INDEX IF EXISTS idx_strategies_role_task_type"),e.exec("DROP INDEX IF EXISTS idx_strategies_role"),e.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_strategies_role_task_type ON strategies(role_id, task_type, name)"),e.exec("CREATE INDEX IF NOT EXISTS idx_strategies_role ON strategies(role_id)")),e.exec("UPDATE server_state SET schema_version = 17 WHERE id = 1"),e.exec("PRAGMA foreign_keys = ON")}if(o<18){let E=e.prepare("PRAGMA table_info(tasks)").all();E.some(T=>T.name==="deliver_to")||e.exec("ALTER TABLE tasks ADD COLUMN deliver_to TEXT"),E.some(T=>T.name==="report_to")||e.exec("ALTER TABLE tasks ADD COLUMN report_to TEXT");let s=e.prepare("PRAGMA table_info(strategies)").all();s.some(T=>T.name==="role")&&!s.some(T=>T.name==="role_id")&&(e.exec("ALTER TABLE strategies RENAME COLUMN role TO role_id"),e.exec("DROP INDEX IF EXISTS idx_strategies_role_task_type"),e.exec("DROP INDEX IF EXISTS idx_strategies_role"),e.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_strategies_role_task_type ON strategies(role_id, task_type, name)"),e.exec("CREATE INDEX IF NOT EXISTS idx_strategies_role ON strategies(role_id)")),e.exec("UPDATE server_state SET schema_version = 18 WHERE id = 1")}e.prepare("PRAGMA table_info(delivery_log)").all().some(E=>E.name==="source")||(e.exec(`
570
+ `),e.exec("UPDATE server_state SET schema_version = 10 WHERE id = 1"),e.exec("PRAGMA foreign_keys = ON")}if(o<11){try{e.exec("ALTER TABLE task_templates RENAME COLUMN skill_preference TO role_preference")}catch(E){let s=e.prepare("PRAGMA table_info(task_templates)").all(),T=s.some(i=>i.name==="role_preference"),r=s.some(i=>i.name==="skill_preference");if(!T&&r)throw E}e.exec("UPDATE server_state SET schema_version = 11 WHERE id = 1")}if(o<12&&(e.prepare("PRAGMA table_info(server_state)").all().some(s=>s.name==="tools_fingerprint")||e.exec("ALTER TABLE server_state ADD COLUMN tools_fingerprint TEXT"),e.exec("UPDATE server_state SET schema_version = 12 WHERE id = 1")),o<13&&(e.prepare("PRAGMA table_info(roles)").all().some(s=>s.name==="additional_directories")||e.exec("ALTER TABLE roles ADD COLUMN additional_directories TEXT"),e.exec("UPDATE server_state SET schema_version = 13 WHERE id = 1")),o<14){let E=e.prepare("PRAGMA table_info(roles)").all();E.some(r=>r.name==="allowed_channels")||e.exec("ALTER TABLE roles ADD COLUMN allowed_channels TEXT"),E.some(r=>r.name==="mcp_servers")||e.exec("ALTER TABLE roles ADD COLUMN mcp_servers TEXT");let s=e.prepare("PRAGMA table_info(tasks)").all();s.some(r=>r.name==="deliver_to")||e.exec("ALTER TABLE tasks ADD COLUMN deliver_to TEXT"),s.some(r=>r.name==="report_to")||e.exec("ALTER TABLE tasks ADD COLUMN report_to TEXT"),e.prepare("PRAGMA table_info(goals)").all().some(r=>r.name==="deliver_to")||e.exec("ALTER TABLE goals ADD COLUMN deliver_to TEXT"),e.exec("UPDATE server_state SET schema_version = 14 WHERE id = 1")}if(o<15&&(e.prepare("PRAGMA table_info(roles)").all().some(s=>s.name==="inherit_user_settings")||e.exec("ALTER TABLE roles ADD COLUMN inherit_user_settings INTEGER DEFAULT 0"),e.exec("UPDATE server_state SET schema_version = 15 WHERE id = 1")),o<16&&(e.prepare("PRAGMA table_info(task_templates)").all().some(s=>s.name==="deliver_to")||e.exec("ALTER TABLE task_templates ADD COLUMN deliver_to TEXT"),e.exec("UPDATE server_state SET schema_version = 16 WHERE id = 1")),o<17){e.exec("PRAGMA foreign_keys = OFF"),e.exec("DROP TABLE IF EXISTS plugins"),e.exec("DROP TABLE IF EXISTS role_plugins"),e.exec("DROP TABLE IF EXISTS marketplaces"),e.exec("DROP INDEX IF EXISTS idx_plugins_source"),e.exec("DROP INDEX IF EXISTS idx_plugins_enabled");try{let T=e.prepare("SELECT id, additional_directories FROM roles WHERE additional_directories IS NOT NULL").all();for(let r of T)try{let i=JSON.parse(r.additional_directories);if(i.length>0&&typeof i[0]=="object"&&i[0]!==null&&"path"in i[0])continue;let n=i.map(_=>typeof _=="string"?{path:_}:_);e.prepare("UPDATE roles SET additional_directories = ? WHERE id = ?").run(JSON.stringify(n),r.id)}catch{}}catch{}let E=e.prepare("PRAGMA table_info(tasks)").all();E.some(T=>T.name==="deliver_to")||e.exec("ALTER TABLE tasks ADD COLUMN deliver_to TEXT"),E.some(T=>T.name==="report_to")||e.exec("ALTER TABLE tasks ADD COLUMN report_to TEXT");let s=e.prepare("PRAGMA table_info(strategies)").all();s.some(T=>T.name==="role")&&!s.some(T=>T.name==="role_id")&&(e.exec("ALTER TABLE strategies RENAME COLUMN role TO role_id"),e.exec("DROP INDEX IF EXISTS idx_strategies_role_task_type"),e.exec("DROP INDEX IF EXISTS idx_strategies_role"),e.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_strategies_role_task_type ON strategies(role_id, task_type, name)"),e.exec("CREATE INDEX IF NOT EXISTS idx_strategies_role ON strategies(role_id)")),e.exec("UPDATE server_state SET schema_version = 17 WHERE id = 1"),e.exec("PRAGMA foreign_keys = ON")}if(o<18){let E=e.prepare("PRAGMA table_info(tasks)").all();E.some(T=>T.name==="deliver_to")||e.exec("ALTER TABLE tasks ADD COLUMN deliver_to TEXT"),E.some(T=>T.name==="report_to")||e.exec("ALTER TABLE tasks ADD COLUMN report_to TEXT");let s=e.prepare("PRAGMA table_info(strategies)").all();s.some(T=>T.name==="role")&&!s.some(T=>T.name==="role_id")&&(e.exec("ALTER TABLE strategies RENAME COLUMN role TO role_id"),e.exec("DROP INDEX IF EXISTS idx_strategies_role_task_type"),e.exec("DROP INDEX IF EXISTS idx_strategies_role"),e.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_strategies_role_task_type ON strategies(role_id, task_type, name)"),e.exec("CREATE INDEX IF NOT EXISTS idx_strategies_role ON strategies(role_id)")),e.exec("UPDATE server_state SET schema_version = 18 WHERE id = 1")}e.prepare("PRAGMA table_info(delivery_log)").all().some(E=>E.name==="source")||(e.exec(`
571
571
  CREATE TABLE IF NOT EXISTS delivery_log_new (
572
572
  id TEXT PRIMARY KEY,
573
573
  rule_id TEXT REFERENCES delivery_rules(id),
@@ -633,7 +633,7 @@ import{e as R,h as p}from"./chunk-WBAPIPST.js";import{c as m,h as O}from"./chunk
633
633
  ON artifact_access_log (execution_id, timestamp);
634
634
  CREATE INDEX IF NOT EXISTS idx_artifact_access_log_role
635
635
  ON artifact_access_log (role_id, timestamp);
636
- `;e.exec(E),e.exec(s),e.prepare("PRAGMA table_info(tasks)").all().some(t=>t.name==="step_id")||e.prepare("ALTER TABLE tasks ADD COLUMN step_id TEXT").run(),e.exec("UPDATE server_state SET schema_version = 26 WHERE id = 1")}e.prepare("PRAGMA table_info(roles)").all().some(T=>T.name==="os_capabilities")||e.prepare("ALTER TABLE roles ADD COLUMN os_capabilities TEXT DEFAULT NULL").run(),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<27&&e.prepare("UPDATE server_state SET schema_version = 27 WHERE id = 1").run();{let E=e.prepare("PRAGMA table_info(manager_decisions)").all();E.some(T=>T.name==="requirements_json")||e.prepare("ALTER TABLE manager_decisions ADD COLUMN requirements_json TEXT").run(),E.some(T=>T.name==="fit_score")||e.prepare("ALTER TABLE manager_decisions ADD COLUMN fit_score REAL").run(),E.some(T=>T.name==="candidates_json")||e.prepare("ALTER TABLE manager_decisions ADD COLUMN candidates_json TEXT").run(),E.some(T=>T.name==="tie_break_reason")||e.prepare("ALTER TABLE manager_decisions ADD COLUMN tie_break_reason TEXT").run(),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<28&&e.prepare("UPDATE server_state SET schema_version = 28 WHERE id = 1").run()}{let E=[[/\brm -rf\b/,["rm -rf *"]],[/^git push/,["git push*"]],[/^git reset/,["git reset*"]],[/\bcurl.*POST\b/i,["curl * -X POST*","curl * --request POST*"]]],s=e.prepare("SELECT key, value FROM config WHERE key = 'defaults.approvalRequired'").all();for(let T of s)try{let t=JSON.parse(T.value),i=[];for(let _ of t){let l=!1;for(let[A,r]of E)if(A.test(_)){i.push(...r),l=!0,a.info({from:_,to:r},"Config: migrated approvalRequired pattern from regex to glob");break}l||(/[.+?^${}()|[\]\\]/.test(_)&&a.warn({pattern:_},"Config: approvalRequired pattern contains regex metacharacters that won't work with glob matching; update to glob syntax (use * for wildcards)"),i.push(_))}let n=[...new Set(i)];e.prepare("UPDATE config SET value = ?, updated_at = ? WHERE key = ?").run(JSON.stringify(n),Date.now(),T.key)}catch{}}if((e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<31){let s=e.prepare("SELECT count(*) AS n FROM task_templates WHERE trigger_type IN ('event', 'task_complete')").get();s.n>0&&a.info({legacyCount:s.n},"normalizing legacy template trigger types"),e.prepare("UPDATE task_templates SET trigger_type='workflow_complete' WHERE trigger_type='event' AND trigger_event LIKE 'workflow_complete:%'").run(),e.prepare("UPDATE task_templates SET trigger_type='template_complete' WHERE trigger_type='event'").run(),e.prepare("UPDATE task_templates SET trigger_type='manual' WHERE trigger_type='task_complete'").run();let T=e.prepare("SELECT count(*) AS n FROM task_templates WHERE trigger_type IN ('event', 'task_complete')").get();T.n>0&&a.warn({orphan:T.n},"migration left orphan legacy trigger_type rows; manual inspection required"),e.prepare("UPDATE server_state SET schema_version = 31 WHERE id = 1").run()}(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<32&&(e.exec(`
636
+ `;e.exec(E),e.exec(s),e.prepare("PRAGMA table_info(tasks)").all().some(r=>r.name==="step_id")||e.prepare("ALTER TABLE tasks ADD COLUMN step_id TEXT").run(),e.exec("UPDATE server_state SET schema_version = 26 WHERE id = 1")}e.prepare("PRAGMA table_info(roles)").all().some(T=>T.name==="os_capabilities")||e.prepare("ALTER TABLE roles ADD COLUMN os_capabilities TEXT DEFAULT NULL").run(),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<27&&e.prepare("UPDATE server_state SET schema_version = 27 WHERE id = 1").run();{let E=e.prepare("PRAGMA table_info(manager_decisions)").all();E.some(T=>T.name==="requirements_json")||e.prepare("ALTER TABLE manager_decisions ADD COLUMN requirements_json TEXT").run(),E.some(T=>T.name==="fit_score")||e.prepare("ALTER TABLE manager_decisions ADD COLUMN fit_score REAL").run(),E.some(T=>T.name==="candidates_json")||e.prepare("ALTER TABLE manager_decisions ADD COLUMN candidates_json TEXT").run(),E.some(T=>T.name==="tie_break_reason")||e.prepare("ALTER TABLE manager_decisions ADD COLUMN tie_break_reason TEXT").run(),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<28&&e.prepare("UPDATE server_state SET schema_version = 28 WHERE id = 1").run()}{let E=[[/\brm -rf\b/,["rm -rf *"]],[/^git push/,["git push*"]],[/^git reset/,["git reset*"]],[/\bcurl.*POST\b/i,["curl * -X POST*","curl * --request POST*"]]],s=e.prepare("SELECT key, value FROM config WHERE key = 'defaults.approvalRequired'").all();for(let T of s)try{let r=JSON.parse(T.value),i=[];for(let _ of r){let a=!1;for(let[A,t]of E)if(A.test(_)){i.push(...t),a=!0,l.info({from:_,to:t},"Config: migrated approvalRequired pattern from regex to glob");break}a||(/[.+?^${}()|[\]\\]/.test(_)&&l.warn({pattern:_},"Config: approvalRequired pattern contains regex metacharacters that won't work with glob matching; update to glob syntax (use * for wildcards)"),i.push(_))}let n=[...new Set(i)];e.prepare("UPDATE config SET value = ?, updated_at = ? WHERE key = ?").run(JSON.stringify(n),Date.now(),T.key)}catch{}}if((e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<31){let s=e.prepare("SELECT count(*) AS n FROM task_templates WHERE trigger_type IN ('event', 'task_complete')").get();s.n>0&&l.info({legacyCount:s.n},"normalizing legacy template trigger types"),e.prepare("UPDATE task_templates SET trigger_type='workflow_complete' WHERE trigger_type='event' AND trigger_event LIKE 'workflow_complete:%'").run(),e.prepare("UPDATE task_templates SET trigger_type='template_complete' WHERE trigger_type='event'").run(),e.prepare("UPDATE task_templates SET trigger_type='manual' WHERE trigger_type='task_complete'").run();let T=e.prepare("SELECT count(*) AS n FROM task_templates WHERE trigger_type IN ('event', 'task_complete')").get();T.n>0&&l.warn({orphan:T.n},"migration left orphan legacy trigger_type rows; manual inspection required"),e.prepare("UPDATE server_state SET schema_version = 31 WHERE id = 1").run()}if((e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<32&&(e.exec(`
637
637
  CREATE TABLE IF NOT EXISTS event_defs (
638
638
  id TEXT PRIMARY KEY, name TEXT NOT NULL, source_type TEXT NOT NULL,
639
639
  source_config TEXT NOT NULL, enabled INTEGER NOT NULL DEFAULT 1,
@@ -652,4 +652,33 @@ import{e as R,h as p}from"./chunk-WBAPIPST.js";import{c as m,h as O}from"./chunk
652
652
  CREATE UNIQUE INDEX IF NOT EXISTS idx_events_dedup ON events(source, dedup_key);
653
653
  CREATE INDEX IF NOT EXISTS idx_events_type ON events(type);
654
654
  CREATE INDEX IF NOT EXISTS idx_events_def_id ON events(event_def_id, occurred_at);
655
- `),e.prepare("UPDATE server_state SET schema_version = 32 WHERE id = 1").run()),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<33&&(e.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='workflow_executions'").get()&&(e.prepare("PRAGMA table_info(workflow_executions)").all().some(i=>i.name==="event_id")||e.prepare("ALTER TABLE workflow_executions ADD COLUMN event_id TEXT").run(),e.prepare("CREATE INDEX IF NOT EXISTS idx_workflow_executions_event_id ON workflow_executions(event_id)").run()),e.prepare("UPDATE server_state SET schema_version = 33 WHERE id = 1").run()),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<34&&(e.prepare("PRAGMA table_info(tasks)").all().some(t=>t.name==="block_reason_json")||e.prepare("ALTER TABLE tasks ADD COLUMN block_reason_json TEXT").run(),e.prepare("UPDATE server_state SET schema_version = 34 WHERE id = 1").run());try{let E=e.prepare("SELECT id, name, steps, role_preference FROM task_templates WHERE enabled = 1").all(),s=0;for(let T of E){if(T.role_preference)continue;let t;try{t=JSON.parse(T.steps)}catch{continue}if(!Array.isArray(t))continue;let i=!1;for(let n of t){let _=typeof n.roleId=="string"&&n.roleId.length>0,l=n.autoSelectRole===!0;!_&&!l&&(n.autoSelectRole=!0,n.requirements===void 0&&(n.requirements={}),i=!0)}i&&(e.prepare("UPDATE task_templates SET steps = ?, updated_at = ? WHERE id = ?").run(JSON.stringify(t),Date.now(),T.id),s+=1,console.info(`[db migration] template auto-repaired: id=${T.id} name=${T.name}`))}s>0&&console.info(`[db migration] auto-repaired ${s} enabled template(s) with missing role config`)}catch(E){console.error("[db migration] template auto-repair failed:",E)}}function K(){if(N)return N;let e=process.env.ADAM_DB_PATH||R,c=g(e);return S(c)||u(c,{recursive:!0}),N=new X(e),N.pragma("journal_mode = WAL"),N.pragma("foreign_keys = ON"),N.pragma("trusted_schema = ON"),U(N),N}function W(){N&&(N.close(),N=null)}var a,N,D=I(()=>{p();O();a=m("store"),N=null});export{U as a,K as b,W as c,D as d};
655
+ `),e.prepare("UPDATE server_state SET schema_version = 32 WHERE id = 1").run()),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<33&&(e.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='workflow_executions'").get()&&(e.prepare("PRAGMA table_info(workflow_executions)").all().some(i=>i.name==="event_id")||e.prepare("ALTER TABLE workflow_executions ADD COLUMN event_id TEXT").run(),e.prepare("CREATE INDEX IF NOT EXISTS idx_workflow_executions_event_id ON workflow_executions(event_id)").run()),e.prepare("UPDATE server_state SET schema_version = 33 WHERE id = 1").run()),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<34&&(e.prepare("PRAGMA table_info(tasks)").all().some(r=>r.name==="block_reason_json")||e.prepare("ALTER TABLE tasks ADD COLUMN block_reason_json TEXT").run(),e.prepare("UPDATE server_state SET schema_version = 34 WHERE id = 1").run()),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<35){e.prepare("PRAGMA table_info(roles)").all().some(r=>r.name==="preset_id")||e.prepare("ALTER TABLE roles ADD COLUMN preset_id TEXT").run();let T=e.prepare("PRAGMA table_info(task_templates)").all();T.some(r=>r.name==="is_preset")||e.prepare("ALTER TABLE task_templates ADD COLUMN is_preset INTEGER NOT NULL DEFAULT 0").run(),T.some(r=>r.name==="preset_id")||e.prepare("ALTER TABLE task_templates ADD COLUMN preset_id TEXT").run(),e.prepare("UPDATE server_state SET schema_version = 35 WHERE id = 1").run()}if((e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<36){let s=[["Engineer","engineer"],["Reviewer","reviewer"],["Researcher","researcher"],["Writer","writer"],["Chat Manager","chat-manager"],["adam-automator","adam-automator"]];for(let[T,r]of s)e.prepare("UPDATE roles SET preset_id = ? WHERE name = ? AND preset_id IS NULL").run(r,T);e.prepare("UPDATE server_state SET schema_version = 36 WHERE id = 1").run()}(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<37&&(e.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='feature_requests'").all().length===0&&(e.exec(`
656
+ CREATE TABLE feature_requests (
657
+ id TEXT PRIMARY KEY,
658
+ source_session_id TEXT,
659
+ source_message_id TEXT,
660
+ extracted_at INTEGER NOT NULL,
661
+ extracted_by_role_id TEXT,
662
+ content TEXT NOT NULL,
663
+ summary TEXT,
664
+ status TEXT NOT NULL DEFAULT 'new' CHECK(status IN ('new','reviewed','dismissed','converted')),
665
+ tags TEXT,
666
+ evidence_quote TEXT,
667
+ created_at INTEGER NOT NULL,
668
+ updated_at INTEGER NOT NULL
669
+ )
670
+ `),e.exec("CREATE INDEX IF NOT EXISTS idx_feature_requests_status ON feature_requests(status)"),e.exec("CREATE INDEX IF NOT EXISTS idx_feature_requests_extracted_at ON feature_requests(extracted_at DESC)")),e.prepare("UPDATE server_state SET schema_version = 37 WHERE id = 1").run()),(e.prepare("SELECT schema_version FROM server_state WHERE id = 1").get()?.schema_version??0)<38&&(e.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='mistake_patterns'").all().length===0&&(e.exec(`
671
+ CREATE TABLE mistake_patterns (
672
+ id TEXT PRIMARY KEY,
673
+ dimension_type TEXT NOT NULL,
674
+ dimension_value TEXT NOT NULL,
675
+ count INTEGER NOT NULL DEFAULT 1,
676
+ role_ids TEXT NOT NULL DEFAULT '[]',
677
+ sample_evidence_ids TEXT NOT NULL DEFAULT '[]',
678
+ status TEXT NOT NULL DEFAULT 'new' CHECK(status IN ('new','acknowledged','dismissed')),
679
+ first_seen INTEGER NOT NULL,
680
+ last_seen INTEGER NOT NULL,
681
+ created_at INTEGER NOT NULL,
682
+ updated_at INTEGER NOT NULL
683
+ )
684
+ `),e.exec("CREATE INDEX IF NOT EXISTS idx_mistake_patterns_status ON mistake_patterns(status)"),e.exec("CREATE INDEX IF NOT EXISTS idx_mistake_patterns_last_seen ON mistake_patterns(last_seen)"),e.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_mistake_patterns_dim ON mistake_patterns(dimension_type, dimension_value)")),e.prepare("UPDATE server_state SET schema_version = 38 WHERE id = 1").run());try{let E=e.prepare("SELECT id, name, steps, role_preference FROM task_templates WHERE enabled = 1").all(),s=0;for(let T of E){if(T.role_preference)continue;let r;try{r=JSON.parse(T.steps)}catch{continue}if(!Array.isArray(r))continue;let i=!1;for(let n of r){let _=typeof n.roleId=="string"&&n.roleId.length>0,a=n.autoSelectRole===!0;!_&&!a&&(n.autoSelectRole=!0,n.requirements===void 0&&(n.requirements={}),i=!0)}i&&(e.prepare("UPDATE task_templates SET steps = ?, updated_at = ? WHERE id = ?").run(JSON.stringify(r),Date.now(),T.id),s+=1,console.info(`[db migration] template auto-repaired: id=${T.id} name=${T.name}`))}s>0&&console.info(`[db migration] auto-repaired ${s} enabled template(s) with missing role config`)}catch(E){console.error("[db migration] template auto-repair failed:",E)}}function W(){if(N)return N;let e=process.env.ADAM_DB_PATH||R,c=g(e);return S(c)||u(c,{recursive:!0}),N=new X(e),N.pragma("journal_mode = WAL"),N.pragma("foreign_keys = ON"),N.pragma("trusted_schema = ON"),U(N),N}function K(){N&&(N.close(),N=null)}var l,N,D=p(()=>{I();O();l=m("store"),N=null});export{U as a,W as b,K as c,D as d};
@@ -1 +1 @@
1
- import{f as ue}from"./chunk-B6LOT5CG.js";import{a as le,b as x,c as J,d as ge,e as me}from"./chunk-GSFLLRS7.js";import{c as _,h as M}from"./chunk-MRTJFYPR.js";import{z as g}from"zod/v4";import{v4 as Dt}from"uuid";import{randomUUID as be}from"crypto";import Ye from"crypto";var pe="2.1.7",F="bot";function Ze(t){let e=t.split(".").map(r=>parseInt(r,10)),s=e[0]??0,i=e[1]??0,n=e[2]??0;return(s&255)<<16|(i&255)<<8|n&255}var Y=Ze(pe),et=35e3,fe=15e3,tt=1e4;function L(){return{channel_version:pe}}function nt(t){return t.endsWith("/")?t:`${t}/`}function st(){let t=Ye.randomBytes(4).readUInt32BE(0);return Buffer.from(String(t),"utf-8").toString("base64")}function it(t){let e={"Content-Type":"application/json",AuthorizationType:"ilink_bot_token","Content-Length":String(Buffer.byteLength(t.body,"utf-8")),"X-WECHAT-UIN":st(),"iLink-App-Id":F,"iLink-App-ClientVersion":String(Y)};return t.token?.trim()&&(e.Authorization=`Bearer ${t.token.trim()}`),t.routeTag&&(e.SKRouteTag=t.routeTag),e}async function D(t){let e=nt(t.baseUrl),s=new URL(t.endpoint,e),i=it({token:t.token,routeTag:t.routeTag,body:t.body}),n=new AbortController,r=setTimeout(()=>n.abort(),t.timeoutMs);try{let o=await fetch(s.toString(),{method:"POST",headers:i,body:t.body,signal:n.signal});clearTimeout(r);let a=await o.text();if(!o.ok)throw new Error(`${t.label} ${o.status}: ${a}`);return a}catch(o){throw clearTimeout(r),o}}async function he(t){let e=t.timeoutMs??et;try{let s=await D({baseUrl:t.baseUrl,endpoint:"ilink/bot/getupdates",body:JSON.stringify({get_updates_buf:t.get_updates_buf??"",base_info:L()}),token:t.token,routeTag:t.routeTag,timeoutMs:e,label:"getUpdates"});return JSON.parse(s)}catch(s){if(s instanceof Error&&s.name==="AbortError")return{ret:0,msgs:[],get_updates_buf:t.get_updates_buf};throw s}}var rt={[-2]:2,[-3]:3},ot=1e3;async function E(t){let e=(await import("./logger-WEXZORHP.js")).getLogger("channels"),s=new Map;for(;;){let i=await D({baseUrl:t.baseUrl,endpoint:"ilink/bot/sendmessage",body:JSON.stringify({...t.body,base_info:L()}),token:t.token,routeTag:t.routeTag,timeoutMs:t.timeoutMs??fe,label:"sendMessage"});e.info({status:200,responseBody:i.slice(0,300)},"apiFetch sendMessage response");try{let n=JSON.parse(i);if(n.ret&&n.ret!==0){let r=rt[n.ret],o=(s.get(n.ret)??0)+1;if(s.set(n.ret,o),r!==void 0&&o<r){e.warn({ret:n.ret,attempt:o,maxRetries:r},"sendMessage: retriable iLink error, retrying"),await new Promise(a=>setTimeout(a,ot*o));continue}throw e.error({ret:n.ret,errmsg:n.errmsg,attempt:o},"sendMessage: iLink API error, no more retries"),new Error(`sendMessage failed: iLink ret=${n.ret}${n.errmsg?` errmsg=${n.errmsg}`:""}`)}}catch(n){if(n instanceof SyntaxError)e.warn({rawText:i.slice(0,200)},"sendMessage: non-JSON response, treating as success");else throw n}return}}async function ye(t){await D({baseUrl:t.baseUrl,endpoint:"ilink/bot/sendtyping",body:JSON.stringify({...t.body,base_info:L()}),token:t.token,routeTag:t.routeTag,timeoutMs:t.timeoutMs??tt,label:"sendTyping"})}async function _e(t){let e=await D({baseUrl:t.baseUrl,endpoint:"ilink/bot/getuploadurl",body:JSON.stringify({filekey:t.filekey,media_type:t.media_type,to_user_id:t.to_user_id,rawsize:t.rawsize,rawfilemd5:t.rawfilemd5,filesize:t.filesize,thumb_rawsize:t.thumb_rawsize,thumb_rawfilemd5:t.thumb_rawfilemd5,thumb_filesize:t.thumb_filesize,no_need_thumb:t.no_need_thumb,aeskey:t.aeskey,base_info:L()}),token:t.token,routeTag:t.routeTag,timeoutMs:t.timeoutMs??fe,label:"getUploadUrl"});return JSON.parse(e)}var at=5*6e4,dt=35e3,we="3",w=new Map;function Z(t){return Date.now()-t.startedAt<at}function ct(){for(let[t,e]of w)Z(e)||w.delete(t)}async function xe(t,e,s){let i=t.endsWith("/")?t:`${t}/`,n=new URL(`ilink/bot/get_bot_qrcode?bot_type=${encodeURIComponent(e)}`,i),r={"iLink-App-Id":F};s&&(r.SKRouteTag=s);let o=await fetch(n.toString(),{headers:r});if(!o.ok){let a=await o.text().catch(()=>"(unreadable)");throw new Error(`Failed to fetch QR code: ${o.status} ${o.statusText} body=${a}`)}return await o.json()}async function ut(t,e,s){let i=t.endsWith("/")?t:`${t}/`,n=new URL(`ilink/bot/get_qrcode_status?qrcode=${encodeURIComponent(e)}`,i),r={"iLink-App-Id":F,"iLink-App-ClientVersion":String(Y)};s&&(r.SKRouteTag=s);let o=new AbortController,a=setTimeout(()=>o.abort(),dt);try{let d=await fetch(n.toString(),{headers:r,signal:o.signal});clearTimeout(a);let c=await d.text();if(!d.ok)throw new Error(`Failed to poll QR status: ${d.status} ${d.statusText}`);return JSON.parse(c)}catch(d){if(clearTimeout(a),d instanceof Error&&d.name==="AbortError")return{status:"wait"};throw d}}async function Ie(t){let e=t.accountId||be();ct();let s=w.get(e);if(!t.force&&s&&Z(s)&&s.qrcodeUrl)return{qrcodeUrl:s.qrcodeUrl,message:"QR code ready. Scan with WeChat.",sessionKey:e};if(!t.apiBaseUrl)return{message:"No baseUrl configured for this WeChat channel.",sessionKey:e};try{let i=t.botType||we,n=await xe(t.apiBaseUrl,i,t.routeTag),r={sessionKey:e,id:be(),qrcode:n.qrcode,qrcodeUrl:n.qrcode_img_content,startedAt:Date.now()};return w.set(e,r),{qrcodeUrl:n.qrcode_img_content,message:"Scan the QR code with WeChat to connect.",sessionKey:e}}catch(i){return{message:`Failed to start login: ${String(i)}`,sessionKey:e}}}var lt=3;async function Te(t){let e=w.get(t.sessionKey);if(!e)return{connected:!1,message:"No active login session. Start QR login first."};if(!Z(e))return w.delete(t.sessionKey),{connected:!1,message:"QR code expired. Please start again."};let s=Math.max(t.timeoutMs??48e4,1e3),i=Date.now()+s,n=1;for(;Date.now()<i;){try{let r=await ut(t.apiBaseUrl,e.qrcode,t.routeTag);switch(e.status=r.status,r.status){case"wait":break;case"scaned":break;case"expired":{if(n++,n>lt)return w.delete(t.sessionKey),{connected:!1,message:"Login timeout: QR expired multiple times."};try{let o=t.botType||we,a=await xe(t.apiBaseUrl,o,t.routeTag);e.qrcode=a.qrcode,e.qrcodeUrl=a.qrcode_img_content,e.startedAt=Date.now()}catch(o){return w.delete(t.sessionKey),{connected:!1,message:`QR refresh failed: ${String(o)}`}}break}case"confirmed":return r.ilink_bot_id?(w.delete(t.sessionKey),{connected:!0,botToken:r.bot_token,accountId:r.ilink_bot_id,baseUrl:r.baseurl,userId:r.ilink_user_id,message:"Connected to WeChat successfully!"}):(w.delete(t.sessionKey),{connected:!1,message:"Login failed: server did not return bot ID."})}}catch(r){return w.delete(t.sessionKey),{connected:!1,message:`Login failed: ${String(r)}`}}await new Promise(r=>setTimeout(r,1e3))}return w.delete(t.sessionKey),{connected:!1,message:"Login timeout. Please try again."}}import T from"fs";import*as R from"fs/promises";import I from"path";import{homedir as H}from"os";var W={IMAGE:1,VIDEO:2,FILE:3,VOICE:4},A={NONE:0,USER:1,BOT:2},y={NONE:0,TEXT:1,IMAGE:2,VOICE:3,FILE:4,VIDEO:5},P={NEW:0,GENERATING:1,FINISH:2},Re={TYPING:1,CANCEL:2};M();var gt=_("channels"),ee=-14,B=3600*1e3,C=new Map;function Me(t){let e=Date.now()+B;C.set(t,e),gt.info({channelId:t},`Session paused until ${new Date(e).toISOString()} (${B/1e3}s)`)}function j(t){let e=C.get(t);return e===void 0?!1:Date.now()>=e?(C.delete(t),!1):!0}function Ue(t){let e=C.get(t);if(e===void 0)return 0;let s=e-Date.now();return s<=0?(C.delete(t),0):s}function ke(t){C.delete(t)}M();import*as z from"fs/promises";import $e from"path";import{homedir as wt}from"os";import{createCipheriv as mt,createDecipheriv as pt}from"crypto";function Se(t,e){let s=mt("aes-128-ecb",e,null);return Buffer.concat([s.update(t),s.final()])}function Ce(t,e){let s=pt("aes-128-ecb",e,null);return Buffer.concat([s.update(t),s.final()])}function Ee(t){return Math.ceil((t+1)/16)*16}function te(t,e){return`${e}/download?encrypted_query_param=${encodeURIComponent(t)}`}function Ae(t){return`${t.cdnBaseUrl}/upload?encrypted_query_param=${encodeURIComponent(t.uploadParam)}&filekey=${encodeURIComponent(t.filekey)}`}M();var sn=_("channels");function ft(t){let e=Buffer.from(t,"base64");if(e.length===16)return e;if(e.length===32&&/^[0-9a-fA-F]{32}$/.test(e.toString("ascii")))return Buffer.from(e.toString("ascii"),"hex");throw new Error(`aes_key must decode to 16 raw bytes or 32-char hex, got ${e.length} bytes`)}async function Pe(t){let e=await fetch(t);if(!e.ok)throw new Error(`CDN download ${e.status} ${e.statusText}`);return Buffer.from(await e.arrayBuffer())}async function v(t){let{encryptQueryParam:e,aesKeyBase64:s,cdnBaseUrl:i,fullUrl:n}=t,r=ft(s),o=n?.trim()||(e?te(e,i):null);if(!o)throw new Error("CDN download: need full_url or encrypt_query_param");let a=await Pe(o);return Ce(a,r)}async function ve(t){let{encryptQueryParam:e,cdnBaseUrl:s,fullUrl:i}=t,n=i?.trim()||(e?te(e,s):null);if(!n)throw new Error("CDN download: need full_url or encrypt_query_param");return Pe(n)}M();var Q=_("channels"),Oe=24e3;function ht(t,e){let s=t.byteLength,i=44+s,n=Buffer.allocUnsafe(i),r=0;return n.write("RIFF",r),r+=4,n.writeUInt32LE(i-8,r),r+=4,n.write("WAVE",r),r+=4,n.write("fmt ",r),r+=4,n.writeUInt32LE(16,r),r+=4,n.writeUInt16LE(1,r),r+=2,n.writeUInt16LE(1,r),r+=2,n.writeUInt32LE(e,r),r+=4,n.writeUInt32LE(e*2,r),r+=4,n.writeUInt16LE(2,r),r+=2,n.writeUInt16LE(16,r),r+=2,n.write("data",r),r+=4,n.writeUInt32LE(s,r),r+=4,Buffer.from(t.buffer,t.byteOffset,t.byteLength).copy(n,r),n}async function qe(t){try{let{decode:e}=await import("silk-wasm");Q.debug(`silkToWav: decoding ${t.length} bytes of SILK`);let s=await e(t,Oe);Q.debug(`silkToWav: decoded duration=${s.duration}ms pcmBytes=${s.data.byteLength}`);let i=ht(s.data,Oe);return Q.debug(`silkToWav: WAV size=${i.length}`),i}catch(e){return Q.warn(`silkToWav: transcode failed, will use raw silk err=${String(e)}`),null}}import yt from"path";var _t={".pdf":"application/pdf",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".ppt":"application/vnd.ms-powerpoint",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",".txt":"text/plain",".csv":"text/csv",".zip":"application/zip",".tar":"application/x-tar",".gz":"application/gzip",".mp3":"audio/mpeg",".ogg":"audio/ogg",".wav":"audio/wav",".amr":"audio/amr",".silk":"audio/x-silk",".mp4":"video/mp4",".mov":"video/quicktime",".webm":"video/webm",".mkv":"video/x-matroska",".avi":"video/x-msvideo",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".bmp":"image/bmp"},bt={"image/jpeg":".jpg","image/jpg":".jpg","image/png":".png","image/gif":".gif","image/webp":".webp","image/bmp":".bmp","video/mp4":".mp4","video/quicktime":".mov","video/webm":".webm","video/x-matroska":".mkv","video/x-msvideo":".avi","audio/mpeg":".mp3","audio/ogg":".ogg","audio/wav":".wav","audio/amr":".amr","audio/x-silk":".silk","application/pdf":".pdf","application/zip":".zip","application/x-tar":".tar","application/gzip":".gz","text/plain":".txt","text/csv":".csv"};function V(t){let e=yt.extname(t).toLowerCase();return _t[e]??"application/octet-stream"}function Ne(t){let e=t.split(";")[0].trim().toLowerCase();return bt[e]??".bin"}var S=_("channels"),Fe=100*1024*1024;function xt(t){return Ne(t)??".bin"}async function O(t,e,s,i,n=Fe,r){if(t.length>n)throw new Error(`Media too large: ${t.length} bytes exceeds ${n} bytes`);let o=$e.join(wt(),".adam","wechat","media",i,s);await z.mkdir(o,{recursive:!0});let a;if(r&&/^[a-zA-Z0-9._-]+$/.test(r))a=r;else{let c=e?xt(e):".bin",u=Date.now(),p=Math.random().toString(36).slice(2,7);a=`${u}-${p}${c}`}let d=$e.join(o,a);return await z.writeFile(d,t),S.debug(`saveMedia: saved ${t.length} bytes to ${d}`),d}async function Le(t,e){let{cdnBaseUrl:s,channelId:i}=e;if(t.type===y.IMAGE){let n=t.image_item;if(!n?.media?.encrypt_query_param&&!n?.media?.full_url)return null;let r=n.aeskey?Buffer.from(n.aeskey,"hex").toString("base64"):n.media?.aes_key;try{let o=r?await v({encryptQueryParam:n.media?.encrypt_query_param,aesKeyBase64:r,cdnBaseUrl:s,fullUrl:n.media?.full_url}):await ve({encryptQueryParam:n.media?.encrypt_query_param,cdnBaseUrl:s,fullUrl:n.media?.full_url});return{path:await O(o,"image/png","inbound",i),mimeType:"image/png",type:"image"}}catch(o){return S.error({channelId:i},`Image download/decrypt failed: ${String(o)}`),null}}if(t.type===y.VOICE){let n=t.voice_item;if(!n?.media?.encrypt_query_param&&!n?.media?.full_url||!n?.media?.aes_key)return null;try{let r=await v({encryptQueryParam:n.media.encrypt_query_param,aesKeyBase64:n.media.aes_key,cdnBaseUrl:s,fullUrl:n.media.full_url}),o=await qe(r);if(o){let a=await O(o,"audio/wav","inbound",i);return S.debug(`Voice: saved WAV to ${a}`),{path:a,mimeType:"audio/wav",type:"audio"}}else{let a=await O(r,"audio/silk","inbound",i);return S.debug(`Voice: silk transcode unavailable, saved raw SILK to ${a}`),{path:a,mimeType:"audio/silk",type:"audio"}}}catch(r){return S.error({channelId:i},`Voice download/transcode failed: ${String(r)}`),null}}if(t.type===y.FILE){let n=t.file_item;if(!n?.media?.encrypt_query_param&&!n?.media?.full_url||!n?.media?.aes_key)return null;try{let r=await v({encryptQueryParam:n.media.encrypt_query_param,aesKeyBase64:n.media.aes_key,cdnBaseUrl:s,fullUrl:n.media.full_url}),o=V(n.file_name??"file.bin");return{path:await O(r,o,"inbound",i,Fe,n.file_name),mimeType:o,type:"file"}}catch(r){return S.error({channelId:i},`File download failed: ${String(r)}`),null}}if(t.type===y.VIDEO){let n=t.video_item;if(!n?.media?.encrypt_query_param&&!n?.media?.full_url||!n?.media?.aes_key)return null;try{let r=await v({encryptQueryParam:n.media.encrypt_query_param,aesKeyBase64:n.media.aes_key,cdnBaseUrl:s,fullUrl:n.media.full_url});return{path:await O(r,"video/mp4","inbound",i),mimeType:"video/mp4",type:"video"}}catch(r){return S.error({channelId:i},`Video download failed: ${String(r)}`),null}}return null}import Be from"path";import ne from"crypto";import It from"fs/promises";M();var U=_("channels"),G=3;async function Tt(t){let{buf:e,uploadFullUrl:s,uploadParam:i,filekey:n,cdnBaseUrl:r,label:o,aeskey:a}=t,d=Se(e,a),c=s?.trim(),u;if(c)u=c;else if(i)u=Ae({cdnBaseUrl:r,uploadParam:i,filekey:n});else throw new Error(`${o}: CDN upload URL missing (need upload_full_url or upload_param)`);U.debug(`${o}: CDN POST url=${u} ciphertextSize=${d.length}`);let p,l;for(let h=1;h<=G;h++)try{let m=await fetch(u,{method:"POST",headers:{"Content-Type":"application/octet-stream"},body:new Uint8Array(d)});if(m.status>=400&&m.status<500){let b=m.headers.get("x-error-message")??await m.text();throw U.error(`${o}: CDN client error attempt=${h} status=${m.status} errMsg=${b}`),new Error(`CDN upload client error ${m.status}: ${b}`)}if(m.status!==200){let b=m.headers.get("x-error-message")??`status ${m.status}`;throw U.error(`${o}: CDN server error attempt=${h} status=${m.status} errMsg=${b}`),new Error(`CDN upload server error: ${b}`)}if(p=m.headers.get("x-encrypted-param")??void 0,!p)throw U.error(`${o}: CDN response missing x-encrypted-param header attempt=${h}`),new Error("CDN upload response missing x-encrypted-param header");U.debug(`${o}: CDN upload success attempt=${h}`);break}catch(m){if(l=m,m instanceof Error&&m.message.includes("client error"))throw m;h<G?U.warn(`${o}: attempt ${h} failed, retrying... err=${String(m)}`):U.error(`${o}: all ${G} attempts failed err=${String(m)}`)}if(!p)throw l instanceof Error?l:new Error(`CDN upload failed after ${G} attempts`);return{downloadParam:p}}async function se(t){let{filePath:e,toUserId:s,opts:i,cdnBaseUrl:n,mediaType:r,label:o}=t,a=await It.readFile(e),d=a.length,c=ne.createHash("md5").update(a).digest("hex"),u=Ee(d),p=ne.randomBytes(16).toString("hex"),l=ne.randomBytes(16);U.debug(`${o}: file=${e} rawsize=${d} filesize=${u} md5=${c} filekey=${p}`);let h=await _e({...i,filekey:p,media_type:r,to_user_id:s,rawsize:d,rawfilemd5:c,filesize:u,no_need_thumb:!0,aeskey:l.toString("hex")}),m=h.upload_full_url?.trim(),b=h.upload_param;if(!m&&!b)throw new Error(`${o}: getUploadUrl returned no upload URL (need upload_full_url or upload_param)`);let{downloadParam:Je}=await Tt({buf:a,uploadFullUrl:m||void 0,uploadParam:b??void 0,filekey:p,cdnBaseUrl:n,aeskey:l,label:`${o}[orig filekey=${p}]`});return{filekey:p,downloadEncryptedQueryParam:Je,aeskey:l.toString("hex"),fileSize:d,fileSizeCiphertext:u}}async function De(t){return se({...t,mediaType:W.IMAGE,label:"uploadImageToWeixin"})}async function We(t){return se({...t,mediaType:W.VIDEO,label:"uploadVideoToWeixin"})}async function ie(t){return se({...t,mediaType:W.FILE,label:"uploadFileAttachmentToWeixin"})}M();var q=_("channels");function Rt(){return`adam-wechat-${Date.now()}-${Math.random().toString(36).slice(2,7)}`}function Mt(t){let e=t;return e=e.replace(/```[^\n]*\n?([\s\S]*?)```/g,(s,i)=>i.trim()),e=e.replace(/!\[[^\]]*\]\([^)]*\)/g,""),e=e.replace(/\[([^\]]+)\]\([^)]*\)/g,"$1"),e=e.replace(/^\|[\s:|-]+\|$/gm,""),e=e.replace(/^\|(.+)\|$/gm,(s,i)=>i.split("|").map(n=>n.trim()).join(" ")),e}async function re(t){let{to:e,text:s,mediaItem:i,opts:n,label:r}=t,o=[],a=Mt(s);a&&o.push({type:y.TEXT,text_item:{text:a}}),o.push(i);let d="";for(let c of o){d=Rt();let u={msg:{from_user_id:"",to_user_id:e,client_id:d,message_type:A.BOT,message_state:P.FINISH,item_list:[c],context_token:n.contextToken}};await E({baseUrl:n.baseUrl,token:n.token,routeTag:n.routeTag,body:u})}return q.debug(`${r}: sent to=${e} messageId=${d}`),{messageId:d}}async function Ut(t){let{to:e,text:s,uploaded:i,opts:n}=t,r={type:y.IMAGE,image_item:{media:{encrypt_query_param:i.downloadEncryptedQueryParam,aes_key:Buffer.from(i.aeskey).toString("base64"),encrypt_type:1},mid_size:i.fileSizeCiphertext}};return re({to:e,text:s,mediaItem:r,opts:n,label:"sendImageMessage"})}async function kt(t){let{to:e,text:s,uploaded:i,opts:n}=t,r={type:y.VIDEO,video_item:{media:{encrypt_query_param:i.downloadEncryptedQueryParam,aes_key:Buffer.from(i.aeskey).toString("base64"),encrypt_type:1},video_size:i.fileSizeCiphertext}};return re({to:e,text:s,mediaItem:r,opts:n,label:"sendVideoMessage"})}async function je(t){let{to:e,text:s,fileName:i,uploaded:n,opts:r}=t,o={type:y.FILE,file_item:{media:{encrypt_query_param:n.downloadEncryptedQueryParam,aes_key:Buffer.from(n.aeskey).toString("base64"),encrypt_type:1},file_name:i,len:String(n.fileSize)}};return re({to:e,text:s,mediaItem:o,opts:r,label:"sendFileMessage"})}async function Qe(t){let{filePath:e,to:s,text:i,opts:n,cdnBaseUrl:r}=t,o=V(e),a={baseUrl:n.baseUrl,token:n.token,routeTag:n.routeTag};if(o.startsWith("video/")){q.debug(`sendWeixinMediaFile: uploading video filePath=${e} to=${s}`);let u=await We({filePath:e,toUserId:s,opts:a,cdnBaseUrl:r});return kt({to:s,text:i,uploaded:u,opts:n})}if(o.startsWith("image/")){q.debug(`sendWeixinMediaFile: uploading image filePath=${e} to=${s}`);let u=await De({filePath:e,toUserId:s,opts:a,cdnBaseUrl:r});return Ut({to:s,text:i,uploaded:u,opts:n})}if(o.startsWith("audio/")){let u=Be.basename(e);q.debug(`sendWeixinMediaFile: uploading audio as file filePath=${e} name=${u} to=${s}`);let p=await ie({filePath:e,fileName:u,toUserId:s,opts:a,cdnBaseUrl:r});return je({to:s,text:i,fileName:u,uploaded:p,opts:n})}let d=Be.basename(e);q.debug(`sendWeixinMediaFile: uploading file attachment filePath=${e} name=${d} to=${s}`);let c=await ie({filePath:e,fileName:d,toUserId:s,opts:a,cdnBaseUrl:r});return je({to:s,text:i,fileName:d,uploaded:c,opts:n})}M();var f=_("channels"),Ve="https://novac2c.cdn.weixin.qq.com/c2c",de=new Map;function Ke(t){return I.join(H(),".adam","wechat",`${t}.context-tokens.json`)}function St(t){let e=Ke(t);try{let s=T.readFileSync(e,"utf-8"),i=JSON.parse(s);for(let[n,r]of Object.entries(i))typeof r=="string"&&r&&de.set(`${t}:${n}`,r);f.debug({channelId:t,count:Object.keys(i).length},"Restored context tokens from disk")}catch{}}function Ct(t,e,s){let i=Ke(t);try{let n={};try{let o=T.readFileSync(i,"utf-8");n=JSON.parse(o)}catch{}n[e]=s;let r=I.dirname(i);T.mkdirSync(r,{recursive:!0}),T.writeFileSync(i,JSON.stringify(n),"utf-8")}catch(n){f.warn({channelId:t,userId:e},`Failed to persist context token: ${String(n)}`)}}function Et(t,e,s){de.set(`${t}:${e}`,s),Ct(t,e,s)}function oe(t,e){return de.get(`${t}:${e}`)}function He(t){return I.join(H(),".adam","wechat",`${t}.sync`)}function At(t){try{return T.readFileSync(He(t),"utf-8")}catch{return""}}function Pt(t,e){let s=He(t);T.mkdirSync(I.dirname(s),{recursive:!0}),T.writeFileSync(s,e,"utf-8")}var ae=1440*60*1e3,ze=10,vt=20,Ge=1440*60*1e3,Ot=1320*60*1e3,qt=1,Nt=7200*1e3;function Xe(t){return I.join(H(),".adam","wechat",`${t}.session.json`)}function $t(t){let e=new Map,s=Xe(t);try{let i=T.readFileSync(s,"utf-8"),n=JSON.parse(i);for(let[r,o]of Object.entries(n))o&&typeof o.lastUserMessageAt=="number"&&e.set(r,o);f.debug({channelId:t,count:e.size},"Restored sessions from disk")}catch{}return e}function N(t,e){let s=Xe(t);try{let i={};for(let[r,o]of e)i[r]=o;let n=I.dirname(s);T.mkdirSync(n,{recursive:!0}),T.writeFileSync(s,JSON.stringify(i),"utf-8")}catch(i){f.warn({channelId:t},`Failed to persist sessions: ${String(i)}`)}}var Ft=0;function $(){return`adam-wechat-${Date.now()}-${++Ft}`}var K=class{platform="wechat";id;config;status="disconnected";messageHandler=null;pollAbort=null;getUpdatesBuf="";sessions=new Map;pendingQueue=new Map;lastReminderAt=new Map;constructor(e,s){if(this.id=e,!s.baseUrl)throw new Error("WeChat adapter requires baseUrl");this.config=s}async connect(){if(!this.config.botToken)throw new Error("WeChat adapter requires botToken. Complete QR login first.");this.status="connecting",this.getUpdatesBuf=At(this.id),St(this.id),this.sessions=$t(this.id),this.pollAbort=new AbortController,this.status="connected",f.info({channelId:this.id},"WeChat adapter connected, starting long-poll"),this.startLongPoll()}async disconnect(){this.pollAbort&&(this.pollAbort.abort(),this.pollAbort=null),this.status="disconnected",f.info({channelId:this.id},"WeChat adapter disconnected")}getStatus(){if(this.status==="connected"&&j(this.id))return"error";if(this.status==="connected"){for(let[,e]of this.sessions)if(this.isSessionActive(e)&&e.quotaRemaining<=0)return"degraded"}return this.status}async sendMessage(e,s){if(j(this.id)){let c=Math.ceil(Ue(this.id)/6e4);throw new Error(`WeChat session paused, ${c} min remaining. Re-scan QR to reconnect.`)}let i=this.getOrCreateSession(e),r=this.getSessionRemainingMs(i)/36e5;if(!this.isSessionActive(i))return f.warn({channelId:this.id,chatId:e.slice(0,12),lastUserMessageAt:i.lastUserMessageAt,sessionExpired:!0},"iLink session expired (>24h), message queued"),this.enqueueMessage(e,s),`queued-${$()}`;if(i.quotaRemaining<=0)return f.warn({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:0,remainingHours:r.toFixed(1)},"iLink quota exhausted, message queued"),this.enqueueMessage(e,s),`queued-${$()}`;let o=$(),a=oe(this.id,e),d=this.config.cdnBaseUrl??Ve;try{if(s.mediaUrl){let c=!s.mediaUrl.includes("://")||s.mediaUrl.startsWith("file://"),u=I.join(H(),".adam","wechat","media","outbound-tmp");await R.mkdir(u,{recursive:!0});let p=this.getExtensionFromMediaType(s.mediaType),l;if(c){let m=s.mediaUrl.startsWith("file://")?new URL(s.mediaUrl).pathname:I.isAbsolute(s.mediaUrl)?s.mediaUrl:I.resolve(s.mediaUrl),b=await R.readFile(m);l=I.join(u,`${Date.now()}-${Math.random().toString(36).slice(2,7)}${p}`),await R.writeFile(l,b)}else{let m=await fetch(s.mediaUrl);if(!m.ok)throw new Error(`Failed to fetch media: ${m.status}`);let b=Buffer.from(await m.arrayBuffer());l=I.join(u,`${Date.now()}-${Math.random().toString(36).slice(2,7)}${p}`),await R.writeFile(l,b)}let h=await Qe({filePath:l,to:e,text:s.content??"",opts:{baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,contextToken:a},cdnBaseUrl:d});return await R.unlink(l).catch(()=>{}),i.quotaRemaining--,N(this.id,this.sessions),f.info({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:i.quotaRemaining,sessionRemainingHours:(this.getSessionRemainingMs(i)/36e5).toFixed(1)},"iLink send success: quota decremented"),this.checkAndSendReminder(e,i).catch(m=>{f.warn({channelId:this.id,chatId:e.slice(0,12)},`Reminder send failed: ${String(m)}`)}),h.messageId}return await E({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,body:{msg:{from_user_id:"",to_user_id:e,client_id:o,message_type:A.BOT,message_state:P.FINISH,item_list:s.content?[{type:y.TEXT,text_item:{text:s.content}}]:void 0,context_token:a}}}),i.quotaRemaining--,N(this.id,this.sessions),f.info({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:i.quotaRemaining,sessionRemainingHours:(this.getSessionRemainingMs(i)/36e5).toFixed(1)},"iLink send success: quota decremented"),this.checkAndSendReminder(e,i).catch(c=>{f.warn({channelId:this.id,chatId:e.slice(0,12)},`Reminder send failed: ${String(c)}`)}),o}catch(c){if(c instanceof Error&&c.message.includes("ret=-2"))return i.quotaRemaining=0,N(this.id,this.sessions),f.warn({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:0},"iLink quota exhausted (ret=-2 confirmed), message queued"),this.enqueueMessage(e,s),`queued-${$()}`;throw c}}onMessage(e){this.messageHandler=e}async sendTypingIndicator(e){if(j(this.id))return;let s=oe(this.id,e);try{await ye({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,body:{ilink_user_id:e,status:Re.TYPING}})}catch{}}updateConfig(e){Object.assign(this.config,e)}getOrCreateSession(e){let s=this.sessions.get(e);return s||(s={lastUserMessageAt:0,quotaRemaining:0},this.sessions.set(e,s)),s}isSessionActive(e){return e.lastUserMessageAt>0&&Date.now()-e.lastUserMessageAt<=ae}getSessionRemainingMs(e){return e.lastUserMessageAt===0?0:Math.max(0,ae-(Date.now()-e.lastUserMessageAt))}enqueueMessage(e,s){let i=this.pendingQueue.get(e);i||(i=[],this.pendingQueue.set(e,i));let n=Date.now();i=i.filter(r=>n-r.queuedAt<Ge),i.length>=vt&&(i.shift(),f.warn({channelId:this.id,chatId:e.slice(0,12)},"Queue full, dropping oldest message")),i.push({message:s,queuedAt:n}),this.pendingQueue.set(e,i),f.info({channelId:this.id,chatId:e.slice(0,12),queueDepth:i.length},"Message enqueued")}async flushQueue(e){let s=this.pendingQueue.get(e);if(!s||s.length===0)return;let i=this.getOrCreateSession(e),n=Math.min(s.length,Math.max(0,i.quotaRemaining-2));if(n<=0){f.info({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:i.quotaRemaining},"Queue flush skipped: insufficient quota (reserving 2 for conversation)");return}f.info({channelId:this.id,chatId:e.slice(0,12),queueDepth:s.length,sending:n,quotaRemaining:i.quotaRemaining},"Flushing queued messages");let r=0;for(;r<n&&s.length>0;){let o=s[0];if(Date.now()-o.queuedAt>Ge){s.shift();continue}try{if(await this.sendMessage(e,o.message),s.shift(),r++,i.quotaRemaining<=0)break}catch{f.warn({channelId:this.id,chatId:e.slice(0,12)},"Queue flush: send failed, stopping");break}}s.length===0&&this.pendingQueue.delete(e),f.info({channelId:this.id,chatId:e.slice(0,12),sent:r,remaining:s.length},"Queue flush complete")}async checkAndSendReminder(e,s){let i=Date.now(),n=this.lastReminderAt.get(e)??0;if(i-n<Nt)return;let r=this.getSessionRemainingMs(s),a=i-s.lastUserMessageAt>=Ot,d=s.quotaRemaining<=qt;if(!a&&!d)return;let c=(r/36e5).toFixed(1),u;a&&d?u=`[\u7CFB\u7EDF\u63D0\u9192] \u6D88\u606F\u7A97\u53E3\u5373\u5C06\u5173\u95ED\uFF08\u5269\u4F59${c}\u5C0F\u65F6/${s.quotaRemaining}\u6761\u914D\u989D\uFF09\u3002\u8BF7\u56DE\u590D\u4EFB\u610F\u6D88\u606F\u4EE5\u4FDD\u6301\u8FDE\u63A5\u3002`:a?u=`[\u7CFB\u7EDF\u63D0\u9192] \u6D88\u606F\u7A97\u53E3\u5373\u5C06\u5173\u95ED\uFF08\u5269\u4F59${c}\u5C0F\u65F6\uFF09\u3002\u8BF7\u56DE\u590D\u4EFB\u610F\u6D88\u606F\u4EE5\u4FDD\u6301\u8FDE\u63A5\u3002`:u=`[\u7CFB\u7EDF\u63D0\u9192] \u6D88\u606F\u914D\u989D\u5373\u5C06\u7528\u5B8C\uFF08\u5269\u4F59${s.quotaRemaining}\u6761\uFF09\u3002\u8BF7\u56DE\u590D\u4EFB\u610F\u6D88\u606F\u4EE5\u91CD\u7F6E\u914D\u989D\u3002`;let p=oe(this.id,e);try{await E({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,body:{msg:{from_user_id:"",to_user_id:e,client_id:$(),message_type:A.BOT,message_state:P.FINISH,item_list:[{type:y.TEXT,text_item:{text:u}}],context_token:p}}}),s.quotaRemaining--,this.lastReminderAt.set(e,i),N(this.id,this.sessions),f.info({channelId:this.id,chatId:e.slice(0,12),remainingHours:c,quotaRemaining:s.quotaRemaining,trigger:a?"time":"quota"},"iLink session reminder sent")}catch(l){f.warn({channelId:this.id,chatId:e.slice(0,12)},`Reminder send failed: ${String(l)}`)}}async startLongPoll(){let e=this.pollAbort?.signal,s=0,i=3,n=3e4,r=2e3;for(;!e?.aborted;)try{let o=await he({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,get_updates_buf:this.getUpdatesBuf});if(o.ret===ee||o.errcode===ee){Me(this.id),this.status="error",f.error({channelId:this.id},"Session expired (errcode=-14), pausing for 1 hour"),await this.sleep(B,e),ke(this.id),this.status="connected";continue}if(o.ret!==void 0&&o.ret!==0||o.errcode!==void 0&&o.errcode!==0){s++,f.error({channelId:this.id,ret:o.ret,errcode:o.errcode},"getUpdates API error"),s>=i?(s=0,await this.sleep(n,e)):await this.sleep(r,e);continue}s=0,o.get_updates_buf&&(this.getUpdatesBuf=o.get_updates_buf,Pt(this.id,o.get_updates_buf));for(let d of o.msgs??[])await this.processInbound(d)}catch(o){if(e?.aborted)return;s++,f.error({channelId:this.id,error:o},"getUpdates error"),s>=i?(s=0,await this.sleep(n,e)):await this.sleep(r,e)}}async processInbound(e){if(!this.messageHandler)return;let s=!!e.group_id,i=s?e.group_id:e.from_user_id??"",n=e.from_user_id??"";e.context_token&&i&&Et(this.id,i,e.context_token);let r=this.getOrCreateSession(i),o=r.quotaRemaining;r.lastUserMessageAt=Date.now(),r.quotaRemaining=ze,N(this.id,this.sessions),f.info({channelId:this.id,chatId:i.slice(0,12),quotaReset:!0,prevQuota:o,newQuota:ze,sessionWindowMs:ae},"iLink session reset: user message received, quota restored"),this.flushQueue(i);let a="",d,c=[];for(let l of e.item_list??[])l.type===y.TEXT&&l.text_item?.text&&(a+=l.text_item.text),l.type===y.IMAGE&&(d="image",c.push(l)),l.type===y.VOICE&&(d="audio",c.push(l),l.voice_item?.text&&!a&&(a=l.voice_item.text)),l.type===y.FILE&&(d="file",c.push(l)),l.type===y.VIDEO&&(d="video",c.push(l));if(!a&&!d)return;let u;if(c.length>0){let l=this.config.cdnBaseUrl??Ve;try{let h=await Le(c[0],{cdnBaseUrl:l,channelId:this.id});h&&(u=h.path,d=h.type)}catch(h){f.error({channelId:this.id},`Media download failed: ${String(h)}`)}}let p={channelId:this.id,platform:"wechat",chatId:i,senderId:n,content:a,mediaType:d,mediaPath:u,isGroup:s,timestamp:e.create_time_ms??Date.now(),raw:e};this.messageHandler(p)}getExtensionFromMediaType(e){switch(e){case"image":return".png";case"video":return".mp4";case"audio":return".mp3";default:return".bin"}}sleep(e,s){return new Promise((i,n)=>{let r=setTimeout(i,e);s?.addEventListener("abort",()=>{clearTimeout(r),n(new Error("aborted"))},{once:!0})})}};M();var Lt=_("channels"),X=class{platform="discord";id;config;status="disconnected";messageHandler=null;client=null;constructor(e,s){if(this.id=e,!s.botToken)throw new Error("Discord adapter requires botToken");this.config=s}async connect(){this.status="connecting";try{let{Client:e,GatewayIntentBits:s}=await import("discord.js");this.client=new e({intents:[s.Guilds,s.GuildMessages,s.MessageContent,s.DirectMessages]});let i=this.client;i.on("messageCreate",n=>{if(!this.messageHandler||n.author.bot||this.config.allowedGuildIds?.length&&n.guildId&&!this.config.allowedGuildIds.includes(n.guildId))return;let r={channelId:this.id,platform:"discord",chatId:n.channelId,senderId:n.author.id,senderName:n.author.displayName??n.author.username,content:n.content,isGroup:!!n.guildId,timestamp:n.createdTimestamp,raw:n};this.messageHandler(r)}),await i.login(this.config.botToken),this.status="connected",Lt.info({channelId:this.id},"Discord bot connected")}catch(e){throw this.status="error",e}}async disconnect(){this.client&&await this.client.destroy(),this.client=null,this.status="disconnected"}getStatus(){return this.status}async sendMessage(e,s){if(!this.client)throw new Error("Discord client not connected");let n=await this.client.channels.fetch(e);if(!n||!("send"in n))throw new Error(`Channel ${e} not found or not text channel`);return(await n.send({content:s.content,reply:s.replyToMessageId?{messageReference:s.replyToMessageId}:void 0})).id}onMessage(e){this.messageHandler=e}async sendTypingIndicator(e){if(!this.client)return;let i=await this.client.channels.fetch(e);i&&"sendTyping"in i&&await i.sendTyping()}};var k=g.object({id:g.string().uuid()}),Wt=g.object({name:g.string().min(1,"name is required"),platform:g.string().min(1,"platform is required"),config:g.record(g.string(),g.unknown()),enabled:g.boolean().optional().default(!0),linkedRoleId:g.string().optional(),allowedChatIds:g.array(g.string()).optional()}),Bt=g.object({name:g.string().min(1).optional(),enabled:g.boolean().optional(),config:g.record(g.string(),g.unknown()).optional(),linkedRoleId:g.string().optional(),allowedChatIds:g.array(g.string()).optional()}),ce;function Zn(t){ce=t}function es(){return ce}async function ts(t){let e=ce;t.get("/channels",{schema:{tags:["Channels"],summary:"List channels",querystring:{type:"object",properties:{enabled:{type:"boolean"}}}}},async(s,i)=>({channels:ge(s.query.enabled)})),t.post("/channels",{schema:{tags:["Channels"],summary:"Create a channel",body:{type:"object",required:["name","platform","config"],properties:{name:{type:"string",minLength:1},platform:{type:"string",minLength:1},config:{type:"object"},enabled:{type:"boolean"},linkedRoleId:{type:"string"},allowedChatIds:{type:"array",items:{type:"string"}}}}}},async(s,i)=>{let n=Wt.safeParse(s.body);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let{name:r,platform:o,config:a,enabled:d,linkedRoleId:c,allowedChatIds:u}=n.data,p={id:Dt(),name:r,platform:o,enabled:d,status:"disconnected",config:a,linkedRoleId:c,allowedChatIds:u,createdAt:Date.now(),messageCount:0};return le(p),i.status(201).send({channel:p})}),t.get("/channels/:id",{schema:{tags:["Channels"],summary:"Get channel by ID",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let r=x(n.data.id);return r?{channel:r}:i.status(404).send({code:"NOT_FOUND",message:"Channel not found"})}),t.patch("/channels/:id",{schema:{tags:["Channels"],summary:"Update channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},body:{type:"object",properties:{name:{type:"string"},enabled:{type:"boolean"},config:{type:"object"},linkedRoleId:{type:"string"},allowedChatIds:{type:"array",items:{type:"string"}}}}}},async(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let r=x(n.data.id);if(!r)return i.status(404).send({code:"NOT_FOUND",message:"Channel not found"});let o=Bt.safeParse(s.body);return o.success?(J(r.id,o.data),{channel:x(r.id)}):i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(o.error)})}),t.delete("/channels/:id",{schema:{tags:["Channels"],summary:"Delete channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let r=x(n.data.id);return r?(me(r.id),i.status(204).send()):i.status(404).send({code:"NOT_FOUND",message:"Channel not found"})}),t.post("/channels/:id/connect",{schema:{tags:["Channels"],summary:"Connect channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});if(!e)return i.status(501).send({code:"NOT_IMPLEMENTED",message:"Channel manager not initialized"});let r=x(n.data.id);if(!r)return i.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(!e.hasAdapter(r.id)&&r.platform==="discord"){let o=r.config;if(!o.botToken)return i.status(400).send({code:"MISSING_CONFIG",message:"Discord channel requires botToken in config"});let a=new X(r.id,{botToken:o.botToken});await e.addChannel(r,a)}if(!e.hasAdapter(r.id))return i.status(400).send({code:"NO_ADAPTER",message:"No adapter registered for this channel. Install the appropriate adapter first."});try{return await e.connectChannel(r.id),{channelId:r.id,status:"connected"}}catch(o){return i.status(500).send({code:"CONNECT_FAILED",message:String(o)})}}),t.post("/channels/:id/disconnect",{schema:{tags:["Channels"],summary:"Disconnect channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});if(!e)return i.status(501).send({code:"NOT_IMPLEMENTED",message:"Channel manager not initialized"});let r=x(n.data.id);return r?(await e.disconnectChannel(r.id),{channelId:r.id,status:"disconnected"}):i.status(404).send({code:"NOT_FOUND",message:"Channel not found"})}),t.get("/channels/:id/messages",{schema:{tags:["Channels"],summary:"Get channel message history",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},querystring:{type:"object",properties:{limit:{type:"integer",minimum:1,maximum:200,default:50},offset:{type:"integer",minimum:0,default:0}}}}},async(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let r=x(n.data.id);if(!r)return i.status(404).send({code:"NOT_FOUND",message:"Channel not found"});let{limit:o=50,offset:a=0}=s.query;return{messages:ue(r.id,o,a)}}),t.post("/channels/:id/wechat/qr-start",{schema:{tags:["WeChat"],summary:"Start WeChat QR login",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let r=x(n.data.id);if(!r)return i.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(r.platform!=="wechat")return i.status(400).send({code:"INVALID_PLATFORM",message:"Channel is not a WeChat channel"});let o=r.config;return await Ie({apiBaseUrl:o.baseUrl,routeTag:o.routeTag})}),t.post("/channels/:id/wechat/qr-wait",{schema:{tags:["WeChat"],summary:"Wait for WeChat QR scan",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},body:{type:"object",properties:{sessionKey:{type:"string"},timeoutMs:{type:"number"}}}}},async(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let r=x(n.data.id);if(!r)return i.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(r.platform!=="wechat")return i.status(400).send({code:"INVALID_PLATFORM",message:"Channel is not a WeChat channel"});let o=r.config,{sessionKey:a,timeoutMs:d}=s.body??{},c=await Te({sessionKey:a??"",apiBaseUrl:o.baseUrl,timeoutMs:d??12e4,routeTag:o.routeTag});if(c.connected&&c.botToken){let u={...o,botToken:c.botToken,accountId:c.accountId,baseUrl:c.baseUrl??o.baseUrl,userId:c.userId};if(J(r.id,{config:u}),e){let p=new K(r.id,u),l=x(r.id);l&&await e.addChannel(l,p)}}return{connected:c.connected,accountId:c.accountId,message:c.message}})}export{K as a,X as b,Zn as c,es as d,ts as e};
1
+ import{f as ue}from"./chunk-UQDC3X6O.js";import{a as le,b as x,c as J,d as ge,e as me}from"./chunk-IZ3WZHCM.js";import{c as _,h as M}from"./chunk-MRTJFYPR.js";import{z as g}from"zod/v4";import{v4 as Dt}from"uuid";import{randomUUID as be}from"crypto";import Ye from"crypto";var pe="2.1.7",F="bot";function Ze(t){let e=t.split(".").map(r=>parseInt(r,10)),s=e[0]??0,i=e[1]??0,n=e[2]??0;return(s&255)<<16|(i&255)<<8|n&255}var Y=Ze(pe),et=35e3,fe=15e3,tt=1e4;function L(){return{channel_version:pe}}function nt(t){return t.endsWith("/")?t:`${t}/`}function st(){let t=Ye.randomBytes(4).readUInt32BE(0);return Buffer.from(String(t),"utf-8").toString("base64")}function it(t){let e={"Content-Type":"application/json",AuthorizationType:"ilink_bot_token","Content-Length":String(Buffer.byteLength(t.body,"utf-8")),"X-WECHAT-UIN":st(),"iLink-App-Id":F,"iLink-App-ClientVersion":String(Y)};return t.token?.trim()&&(e.Authorization=`Bearer ${t.token.trim()}`),t.routeTag&&(e.SKRouteTag=t.routeTag),e}async function D(t){let e=nt(t.baseUrl),s=new URL(t.endpoint,e),i=it({token:t.token,routeTag:t.routeTag,body:t.body}),n=new AbortController,r=setTimeout(()=>n.abort(),t.timeoutMs);try{let o=await fetch(s.toString(),{method:"POST",headers:i,body:t.body,signal:n.signal});clearTimeout(r);let a=await o.text();if(!o.ok)throw new Error(`${t.label} ${o.status}: ${a}`);return a}catch(o){throw clearTimeout(r),o}}async function he(t){let e=t.timeoutMs??et;try{let s=await D({baseUrl:t.baseUrl,endpoint:"ilink/bot/getupdates",body:JSON.stringify({get_updates_buf:t.get_updates_buf??"",base_info:L()}),token:t.token,routeTag:t.routeTag,timeoutMs:e,label:"getUpdates"});return JSON.parse(s)}catch(s){if(s instanceof Error&&s.name==="AbortError")return{ret:0,msgs:[],get_updates_buf:t.get_updates_buf};throw s}}var rt={[-2]:2,[-3]:3},ot=1e3;async function E(t){let e=(await import("./logger-WEXZORHP.js")).getLogger("channels"),s=new Map;for(;;){let i=await D({baseUrl:t.baseUrl,endpoint:"ilink/bot/sendmessage",body:JSON.stringify({...t.body,base_info:L()}),token:t.token,routeTag:t.routeTag,timeoutMs:t.timeoutMs??fe,label:"sendMessage"});e.info({status:200,responseBody:i.slice(0,300)},"apiFetch sendMessage response");try{let n=JSON.parse(i);if(n.ret&&n.ret!==0){let r=rt[n.ret],o=(s.get(n.ret)??0)+1;if(s.set(n.ret,o),r!==void 0&&o<r){e.warn({ret:n.ret,attempt:o,maxRetries:r},"sendMessage: retriable iLink error, retrying"),await new Promise(a=>setTimeout(a,ot*o));continue}throw e.error({ret:n.ret,errmsg:n.errmsg,attempt:o},"sendMessage: iLink API error, no more retries"),new Error(`sendMessage failed: iLink ret=${n.ret}${n.errmsg?` errmsg=${n.errmsg}`:""}`)}}catch(n){if(n instanceof SyntaxError)e.warn({rawText:i.slice(0,200)},"sendMessage: non-JSON response, treating as success");else throw n}return}}async function ye(t){await D({baseUrl:t.baseUrl,endpoint:"ilink/bot/sendtyping",body:JSON.stringify({...t.body,base_info:L()}),token:t.token,routeTag:t.routeTag,timeoutMs:t.timeoutMs??tt,label:"sendTyping"})}async function _e(t){let e=await D({baseUrl:t.baseUrl,endpoint:"ilink/bot/getuploadurl",body:JSON.stringify({filekey:t.filekey,media_type:t.media_type,to_user_id:t.to_user_id,rawsize:t.rawsize,rawfilemd5:t.rawfilemd5,filesize:t.filesize,thumb_rawsize:t.thumb_rawsize,thumb_rawfilemd5:t.thumb_rawfilemd5,thumb_filesize:t.thumb_filesize,no_need_thumb:t.no_need_thumb,aeskey:t.aeskey,base_info:L()}),token:t.token,routeTag:t.routeTag,timeoutMs:t.timeoutMs??fe,label:"getUploadUrl"});return JSON.parse(e)}var at=5*6e4,dt=35e3,we="3",w=new Map;function Z(t){return Date.now()-t.startedAt<at}function ct(){for(let[t,e]of w)Z(e)||w.delete(t)}async function xe(t,e,s){let i=t.endsWith("/")?t:`${t}/`,n=new URL(`ilink/bot/get_bot_qrcode?bot_type=${encodeURIComponent(e)}`,i),r={"iLink-App-Id":F};s&&(r.SKRouteTag=s);let o=await fetch(n.toString(),{headers:r});if(!o.ok){let a=await o.text().catch(()=>"(unreadable)");throw new Error(`Failed to fetch QR code: ${o.status} ${o.statusText} body=${a}`)}return await o.json()}async function ut(t,e,s){let i=t.endsWith("/")?t:`${t}/`,n=new URL(`ilink/bot/get_qrcode_status?qrcode=${encodeURIComponent(e)}`,i),r={"iLink-App-Id":F,"iLink-App-ClientVersion":String(Y)};s&&(r.SKRouteTag=s);let o=new AbortController,a=setTimeout(()=>o.abort(),dt);try{let d=await fetch(n.toString(),{headers:r,signal:o.signal});clearTimeout(a);let c=await d.text();if(!d.ok)throw new Error(`Failed to poll QR status: ${d.status} ${d.statusText}`);return JSON.parse(c)}catch(d){if(clearTimeout(a),d instanceof Error&&d.name==="AbortError")return{status:"wait"};throw d}}async function Ie(t){let e=t.accountId||be();ct();let s=w.get(e);if(!t.force&&s&&Z(s)&&s.qrcodeUrl)return{qrcodeUrl:s.qrcodeUrl,message:"QR code ready. Scan with WeChat.",sessionKey:e};if(!t.apiBaseUrl)return{message:"No baseUrl configured for this WeChat channel.",sessionKey:e};try{let i=t.botType||we,n=await xe(t.apiBaseUrl,i,t.routeTag),r={sessionKey:e,id:be(),qrcode:n.qrcode,qrcodeUrl:n.qrcode_img_content,startedAt:Date.now()};return w.set(e,r),{qrcodeUrl:n.qrcode_img_content,message:"Scan the QR code with WeChat to connect.",sessionKey:e}}catch(i){return{message:`Failed to start login: ${String(i)}`,sessionKey:e}}}var lt=3;async function Te(t){let e=w.get(t.sessionKey);if(!e)return{connected:!1,message:"No active login session. Start QR login first."};if(!Z(e))return w.delete(t.sessionKey),{connected:!1,message:"QR code expired. Please start again."};let s=Math.max(t.timeoutMs??48e4,1e3),i=Date.now()+s,n=1;for(;Date.now()<i;){try{let r=await ut(t.apiBaseUrl,e.qrcode,t.routeTag);switch(e.status=r.status,r.status){case"wait":break;case"scaned":break;case"expired":{if(n++,n>lt)return w.delete(t.sessionKey),{connected:!1,message:"Login timeout: QR expired multiple times."};try{let o=t.botType||we,a=await xe(t.apiBaseUrl,o,t.routeTag);e.qrcode=a.qrcode,e.qrcodeUrl=a.qrcode_img_content,e.startedAt=Date.now()}catch(o){return w.delete(t.sessionKey),{connected:!1,message:`QR refresh failed: ${String(o)}`}}break}case"confirmed":return r.ilink_bot_id?(w.delete(t.sessionKey),{connected:!0,botToken:r.bot_token,accountId:r.ilink_bot_id,baseUrl:r.baseurl,userId:r.ilink_user_id,message:"Connected to WeChat successfully!"}):(w.delete(t.sessionKey),{connected:!1,message:"Login failed: server did not return bot ID."})}}catch(r){return w.delete(t.sessionKey),{connected:!1,message:`Login failed: ${String(r)}`}}await new Promise(r=>setTimeout(r,1e3))}return w.delete(t.sessionKey),{connected:!1,message:"Login timeout. Please try again."}}import T from"fs";import*as R from"fs/promises";import I from"path";import{homedir as H}from"os";var W={IMAGE:1,VIDEO:2,FILE:3,VOICE:4},A={NONE:0,USER:1,BOT:2},y={NONE:0,TEXT:1,IMAGE:2,VOICE:3,FILE:4,VIDEO:5},P={NEW:0,GENERATING:1,FINISH:2},Re={TYPING:1,CANCEL:2};M();var gt=_("channels"),ee=-14,B=3600*1e3,C=new Map;function Me(t){let e=Date.now()+B;C.set(t,e),gt.info({channelId:t},`Session paused until ${new Date(e).toISOString()} (${B/1e3}s)`)}function j(t){let e=C.get(t);return e===void 0?!1:Date.now()>=e?(C.delete(t),!1):!0}function Ue(t){let e=C.get(t);if(e===void 0)return 0;let s=e-Date.now();return s<=0?(C.delete(t),0):s}function ke(t){C.delete(t)}M();import*as z from"fs/promises";import $e from"path";import{homedir as wt}from"os";import{createCipheriv as mt,createDecipheriv as pt}from"crypto";function Se(t,e){let s=mt("aes-128-ecb",e,null);return Buffer.concat([s.update(t),s.final()])}function Ce(t,e){let s=pt("aes-128-ecb",e,null);return Buffer.concat([s.update(t),s.final()])}function Ee(t){return Math.ceil((t+1)/16)*16}function te(t,e){return`${e}/download?encrypted_query_param=${encodeURIComponent(t)}`}function Ae(t){return`${t.cdnBaseUrl}/upload?encrypted_query_param=${encodeURIComponent(t.uploadParam)}&filekey=${encodeURIComponent(t.filekey)}`}M();var sn=_("channels");function ft(t){let e=Buffer.from(t,"base64");if(e.length===16)return e;if(e.length===32&&/^[0-9a-fA-F]{32}$/.test(e.toString("ascii")))return Buffer.from(e.toString("ascii"),"hex");throw new Error(`aes_key must decode to 16 raw bytes or 32-char hex, got ${e.length} bytes`)}async function Pe(t){let e=await fetch(t);if(!e.ok)throw new Error(`CDN download ${e.status} ${e.statusText}`);return Buffer.from(await e.arrayBuffer())}async function v(t){let{encryptQueryParam:e,aesKeyBase64:s,cdnBaseUrl:i,fullUrl:n}=t,r=ft(s),o=n?.trim()||(e?te(e,i):null);if(!o)throw new Error("CDN download: need full_url or encrypt_query_param");let a=await Pe(o);return Ce(a,r)}async function ve(t){let{encryptQueryParam:e,cdnBaseUrl:s,fullUrl:i}=t,n=i?.trim()||(e?te(e,s):null);if(!n)throw new Error("CDN download: need full_url or encrypt_query_param");return Pe(n)}M();var Q=_("channels"),Oe=24e3;function ht(t,e){let s=t.byteLength,i=44+s,n=Buffer.allocUnsafe(i),r=0;return n.write("RIFF",r),r+=4,n.writeUInt32LE(i-8,r),r+=4,n.write("WAVE",r),r+=4,n.write("fmt ",r),r+=4,n.writeUInt32LE(16,r),r+=4,n.writeUInt16LE(1,r),r+=2,n.writeUInt16LE(1,r),r+=2,n.writeUInt32LE(e,r),r+=4,n.writeUInt32LE(e*2,r),r+=4,n.writeUInt16LE(2,r),r+=2,n.writeUInt16LE(16,r),r+=2,n.write("data",r),r+=4,n.writeUInt32LE(s,r),r+=4,Buffer.from(t.buffer,t.byteOffset,t.byteLength).copy(n,r),n}async function qe(t){try{let{decode:e}=await import("silk-wasm");Q.debug(`silkToWav: decoding ${t.length} bytes of SILK`);let s=await e(t,Oe);Q.debug(`silkToWav: decoded duration=${s.duration}ms pcmBytes=${s.data.byteLength}`);let i=ht(s.data,Oe);return Q.debug(`silkToWav: WAV size=${i.length}`),i}catch(e){return Q.warn(`silkToWav: transcode failed, will use raw silk err=${String(e)}`),null}}import yt from"path";var _t={".pdf":"application/pdf",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".ppt":"application/vnd.ms-powerpoint",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",".txt":"text/plain",".csv":"text/csv",".zip":"application/zip",".tar":"application/x-tar",".gz":"application/gzip",".mp3":"audio/mpeg",".ogg":"audio/ogg",".wav":"audio/wav",".amr":"audio/amr",".silk":"audio/x-silk",".mp4":"video/mp4",".mov":"video/quicktime",".webm":"video/webm",".mkv":"video/x-matroska",".avi":"video/x-msvideo",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".bmp":"image/bmp"},bt={"image/jpeg":".jpg","image/jpg":".jpg","image/png":".png","image/gif":".gif","image/webp":".webp","image/bmp":".bmp","video/mp4":".mp4","video/quicktime":".mov","video/webm":".webm","video/x-matroska":".mkv","video/x-msvideo":".avi","audio/mpeg":".mp3","audio/ogg":".ogg","audio/wav":".wav","audio/amr":".amr","audio/x-silk":".silk","application/pdf":".pdf","application/zip":".zip","application/x-tar":".tar","application/gzip":".gz","text/plain":".txt","text/csv":".csv"};function V(t){let e=yt.extname(t).toLowerCase();return _t[e]??"application/octet-stream"}function Ne(t){let e=t.split(";")[0].trim().toLowerCase();return bt[e]??".bin"}var S=_("channels"),Fe=100*1024*1024;function xt(t){return Ne(t)??".bin"}async function O(t,e,s,i,n=Fe,r){if(t.length>n)throw new Error(`Media too large: ${t.length} bytes exceeds ${n} bytes`);let o=$e.join(wt(),".adam","wechat","media",i,s);await z.mkdir(o,{recursive:!0});let a;if(r&&/^[a-zA-Z0-9._-]+$/.test(r))a=r;else{let c=e?xt(e):".bin",u=Date.now(),p=Math.random().toString(36).slice(2,7);a=`${u}-${p}${c}`}let d=$e.join(o,a);return await z.writeFile(d,t),S.debug(`saveMedia: saved ${t.length} bytes to ${d}`),d}async function Le(t,e){let{cdnBaseUrl:s,channelId:i}=e;if(t.type===y.IMAGE){let n=t.image_item;if(!n?.media?.encrypt_query_param&&!n?.media?.full_url)return null;let r=n.aeskey?Buffer.from(n.aeskey,"hex").toString("base64"):n.media?.aes_key;try{let o=r?await v({encryptQueryParam:n.media?.encrypt_query_param,aesKeyBase64:r,cdnBaseUrl:s,fullUrl:n.media?.full_url}):await ve({encryptQueryParam:n.media?.encrypt_query_param,cdnBaseUrl:s,fullUrl:n.media?.full_url});return{path:await O(o,"image/png","inbound",i),mimeType:"image/png",type:"image"}}catch(o){return S.error({channelId:i},`Image download/decrypt failed: ${String(o)}`),null}}if(t.type===y.VOICE){let n=t.voice_item;if(!n?.media?.encrypt_query_param&&!n?.media?.full_url||!n?.media?.aes_key)return null;try{let r=await v({encryptQueryParam:n.media.encrypt_query_param,aesKeyBase64:n.media.aes_key,cdnBaseUrl:s,fullUrl:n.media.full_url}),o=await qe(r);if(o){let a=await O(o,"audio/wav","inbound",i);return S.debug(`Voice: saved WAV to ${a}`),{path:a,mimeType:"audio/wav",type:"audio"}}else{let a=await O(r,"audio/silk","inbound",i);return S.debug(`Voice: silk transcode unavailable, saved raw SILK to ${a}`),{path:a,mimeType:"audio/silk",type:"audio"}}}catch(r){return S.error({channelId:i},`Voice download/transcode failed: ${String(r)}`),null}}if(t.type===y.FILE){let n=t.file_item;if(!n?.media?.encrypt_query_param&&!n?.media?.full_url||!n?.media?.aes_key)return null;try{let r=await v({encryptQueryParam:n.media.encrypt_query_param,aesKeyBase64:n.media.aes_key,cdnBaseUrl:s,fullUrl:n.media.full_url}),o=V(n.file_name??"file.bin");return{path:await O(r,o,"inbound",i,Fe,n.file_name),mimeType:o,type:"file"}}catch(r){return S.error({channelId:i},`File download failed: ${String(r)}`),null}}if(t.type===y.VIDEO){let n=t.video_item;if(!n?.media?.encrypt_query_param&&!n?.media?.full_url||!n?.media?.aes_key)return null;try{let r=await v({encryptQueryParam:n.media.encrypt_query_param,aesKeyBase64:n.media.aes_key,cdnBaseUrl:s,fullUrl:n.media.full_url});return{path:await O(r,"video/mp4","inbound",i),mimeType:"video/mp4",type:"video"}}catch(r){return S.error({channelId:i},`Video download failed: ${String(r)}`),null}}return null}import Be from"path";import ne from"crypto";import It from"fs/promises";M();var U=_("channels"),G=3;async function Tt(t){let{buf:e,uploadFullUrl:s,uploadParam:i,filekey:n,cdnBaseUrl:r,label:o,aeskey:a}=t,d=Se(e,a),c=s?.trim(),u;if(c)u=c;else if(i)u=Ae({cdnBaseUrl:r,uploadParam:i,filekey:n});else throw new Error(`${o}: CDN upload URL missing (need upload_full_url or upload_param)`);U.debug(`${o}: CDN POST url=${u} ciphertextSize=${d.length}`);let p,l;for(let h=1;h<=G;h++)try{let m=await fetch(u,{method:"POST",headers:{"Content-Type":"application/octet-stream"},body:new Uint8Array(d)});if(m.status>=400&&m.status<500){let b=m.headers.get("x-error-message")??await m.text();throw U.error(`${o}: CDN client error attempt=${h} status=${m.status} errMsg=${b}`),new Error(`CDN upload client error ${m.status}: ${b}`)}if(m.status!==200){let b=m.headers.get("x-error-message")??`status ${m.status}`;throw U.error(`${o}: CDN server error attempt=${h} status=${m.status} errMsg=${b}`),new Error(`CDN upload server error: ${b}`)}if(p=m.headers.get("x-encrypted-param")??void 0,!p)throw U.error(`${o}: CDN response missing x-encrypted-param header attempt=${h}`),new Error("CDN upload response missing x-encrypted-param header");U.debug(`${o}: CDN upload success attempt=${h}`);break}catch(m){if(l=m,m instanceof Error&&m.message.includes("client error"))throw m;h<G?U.warn(`${o}: attempt ${h} failed, retrying... err=${String(m)}`):U.error(`${o}: all ${G} attempts failed err=${String(m)}`)}if(!p)throw l instanceof Error?l:new Error(`CDN upload failed after ${G} attempts`);return{downloadParam:p}}async function se(t){let{filePath:e,toUserId:s,opts:i,cdnBaseUrl:n,mediaType:r,label:o}=t,a=await It.readFile(e),d=a.length,c=ne.createHash("md5").update(a).digest("hex"),u=Ee(d),p=ne.randomBytes(16).toString("hex"),l=ne.randomBytes(16);U.debug(`${o}: file=${e} rawsize=${d} filesize=${u} md5=${c} filekey=${p}`);let h=await _e({...i,filekey:p,media_type:r,to_user_id:s,rawsize:d,rawfilemd5:c,filesize:u,no_need_thumb:!0,aeskey:l.toString("hex")}),m=h.upload_full_url?.trim(),b=h.upload_param;if(!m&&!b)throw new Error(`${o}: getUploadUrl returned no upload URL (need upload_full_url or upload_param)`);let{downloadParam:Je}=await Tt({buf:a,uploadFullUrl:m||void 0,uploadParam:b??void 0,filekey:p,cdnBaseUrl:n,aeskey:l,label:`${o}[orig filekey=${p}]`});return{filekey:p,downloadEncryptedQueryParam:Je,aeskey:l.toString("hex"),fileSize:d,fileSizeCiphertext:u}}async function De(t){return se({...t,mediaType:W.IMAGE,label:"uploadImageToWeixin"})}async function We(t){return se({...t,mediaType:W.VIDEO,label:"uploadVideoToWeixin"})}async function ie(t){return se({...t,mediaType:W.FILE,label:"uploadFileAttachmentToWeixin"})}M();var q=_("channels");function Rt(){return`adam-wechat-${Date.now()}-${Math.random().toString(36).slice(2,7)}`}function Mt(t){let e=t;return e=e.replace(/```[^\n]*\n?([\s\S]*?)```/g,(s,i)=>i.trim()),e=e.replace(/!\[[^\]]*\]\([^)]*\)/g,""),e=e.replace(/\[([^\]]+)\]\([^)]*\)/g,"$1"),e=e.replace(/^\|[\s:|-]+\|$/gm,""),e=e.replace(/^\|(.+)\|$/gm,(s,i)=>i.split("|").map(n=>n.trim()).join(" ")),e}async function re(t){let{to:e,text:s,mediaItem:i,opts:n,label:r}=t,o=[],a=Mt(s);a&&o.push({type:y.TEXT,text_item:{text:a}}),o.push(i);let d="";for(let c of o){d=Rt();let u={msg:{from_user_id:"",to_user_id:e,client_id:d,message_type:A.BOT,message_state:P.FINISH,item_list:[c],context_token:n.contextToken}};await E({baseUrl:n.baseUrl,token:n.token,routeTag:n.routeTag,body:u})}return q.debug(`${r}: sent to=${e} messageId=${d}`),{messageId:d}}async function Ut(t){let{to:e,text:s,uploaded:i,opts:n}=t,r={type:y.IMAGE,image_item:{media:{encrypt_query_param:i.downloadEncryptedQueryParam,aes_key:Buffer.from(i.aeskey).toString("base64"),encrypt_type:1},mid_size:i.fileSizeCiphertext}};return re({to:e,text:s,mediaItem:r,opts:n,label:"sendImageMessage"})}async function kt(t){let{to:e,text:s,uploaded:i,opts:n}=t,r={type:y.VIDEO,video_item:{media:{encrypt_query_param:i.downloadEncryptedQueryParam,aes_key:Buffer.from(i.aeskey).toString("base64"),encrypt_type:1},video_size:i.fileSizeCiphertext}};return re({to:e,text:s,mediaItem:r,opts:n,label:"sendVideoMessage"})}async function je(t){let{to:e,text:s,fileName:i,uploaded:n,opts:r}=t,o={type:y.FILE,file_item:{media:{encrypt_query_param:n.downloadEncryptedQueryParam,aes_key:Buffer.from(n.aeskey).toString("base64"),encrypt_type:1},file_name:i,len:String(n.fileSize)}};return re({to:e,text:s,mediaItem:o,opts:r,label:"sendFileMessage"})}async function Qe(t){let{filePath:e,to:s,text:i,opts:n,cdnBaseUrl:r}=t,o=V(e),a={baseUrl:n.baseUrl,token:n.token,routeTag:n.routeTag};if(o.startsWith("video/")){q.debug(`sendWeixinMediaFile: uploading video filePath=${e} to=${s}`);let u=await We({filePath:e,toUserId:s,opts:a,cdnBaseUrl:r});return kt({to:s,text:i,uploaded:u,opts:n})}if(o.startsWith("image/")){q.debug(`sendWeixinMediaFile: uploading image filePath=${e} to=${s}`);let u=await De({filePath:e,toUserId:s,opts:a,cdnBaseUrl:r});return Ut({to:s,text:i,uploaded:u,opts:n})}if(o.startsWith("audio/")){let u=Be.basename(e);q.debug(`sendWeixinMediaFile: uploading audio as file filePath=${e} name=${u} to=${s}`);let p=await ie({filePath:e,fileName:u,toUserId:s,opts:a,cdnBaseUrl:r});return je({to:s,text:i,fileName:u,uploaded:p,opts:n})}let d=Be.basename(e);q.debug(`sendWeixinMediaFile: uploading file attachment filePath=${e} name=${d} to=${s}`);let c=await ie({filePath:e,fileName:d,toUserId:s,opts:a,cdnBaseUrl:r});return je({to:s,text:i,fileName:d,uploaded:c,opts:n})}M();var f=_("channels"),Ve="https://novac2c.cdn.weixin.qq.com/c2c",de=new Map;function Ke(t){return I.join(H(),".adam","wechat",`${t}.context-tokens.json`)}function St(t){let e=Ke(t);try{let s=T.readFileSync(e,"utf-8"),i=JSON.parse(s);for(let[n,r]of Object.entries(i))typeof r=="string"&&r&&de.set(`${t}:${n}`,r);f.debug({channelId:t,count:Object.keys(i).length},"Restored context tokens from disk")}catch{}}function Ct(t,e,s){let i=Ke(t);try{let n={};try{let o=T.readFileSync(i,"utf-8");n=JSON.parse(o)}catch{}n[e]=s;let r=I.dirname(i);T.mkdirSync(r,{recursive:!0}),T.writeFileSync(i,JSON.stringify(n),"utf-8")}catch(n){f.warn({channelId:t,userId:e},`Failed to persist context token: ${String(n)}`)}}function Et(t,e,s){de.set(`${t}:${e}`,s),Ct(t,e,s)}function oe(t,e){return de.get(`${t}:${e}`)}function He(t){return I.join(H(),".adam","wechat",`${t}.sync`)}function At(t){try{return T.readFileSync(He(t),"utf-8")}catch{return""}}function Pt(t,e){let s=He(t);T.mkdirSync(I.dirname(s),{recursive:!0}),T.writeFileSync(s,e,"utf-8")}var ae=1440*60*1e3,ze=10,vt=20,Ge=1440*60*1e3,Ot=1320*60*1e3,qt=1,Nt=7200*1e3;function Xe(t){return I.join(H(),".adam","wechat",`${t}.session.json`)}function $t(t){let e=new Map,s=Xe(t);try{let i=T.readFileSync(s,"utf-8"),n=JSON.parse(i);for(let[r,o]of Object.entries(n))o&&typeof o.lastUserMessageAt=="number"&&e.set(r,o);f.debug({channelId:t,count:e.size},"Restored sessions from disk")}catch{}return e}function N(t,e){let s=Xe(t);try{let i={};for(let[r,o]of e)i[r]=o;let n=I.dirname(s);T.mkdirSync(n,{recursive:!0}),T.writeFileSync(s,JSON.stringify(i),"utf-8")}catch(i){f.warn({channelId:t},`Failed to persist sessions: ${String(i)}`)}}var Ft=0;function $(){return`adam-wechat-${Date.now()}-${++Ft}`}var K=class{platform="wechat";id;config;status="disconnected";messageHandler=null;pollAbort=null;getUpdatesBuf="";sessions=new Map;pendingQueue=new Map;lastReminderAt=new Map;constructor(e,s){if(this.id=e,!s.baseUrl)throw new Error("WeChat adapter requires baseUrl");this.config=s}async connect(){if(!this.config.botToken)throw new Error("WeChat adapter requires botToken. Complete QR login first.");this.status="connecting",this.getUpdatesBuf=At(this.id),St(this.id),this.sessions=$t(this.id),this.pollAbort=new AbortController,this.status="connected",f.info({channelId:this.id},"WeChat adapter connected, starting long-poll"),this.startLongPoll()}async disconnect(){this.pollAbort&&(this.pollAbort.abort(),this.pollAbort=null),this.status="disconnected",f.info({channelId:this.id},"WeChat adapter disconnected")}getStatus(){if(this.status==="connected"&&j(this.id))return"error";if(this.status==="connected"){for(let[,e]of this.sessions)if(this.isSessionActive(e)&&e.quotaRemaining<=0)return"degraded"}return this.status}async sendMessage(e,s){if(j(this.id)){let c=Math.ceil(Ue(this.id)/6e4);throw new Error(`WeChat session paused, ${c} min remaining. Re-scan QR to reconnect.`)}let i=this.getOrCreateSession(e),r=this.getSessionRemainingMs(i)/36e5;if(!this.isSessionActive(i))return f.warn({channelId:this.id,chatId:e.slice(0,12),lastUserMessageAt:i.lastUserMessageAt,sessionExpired:!0},"iLink session expired (>24h), message queued"),this.enqueueMessage(e,s),`queued-${$()}`;if(i.quotaRemaining<=0)return f.warn({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:0,remainingHours:r.toFixed(1)},"iLink quota exhausted, message queued"),this.enqueueMessage(e,s),`queued-${$()}`;let o=$(),a=oe(this.id,e),d=this.config.cdnBaseUrl??Ve;try{if(s.mediaUrl){let c=!s.mediaUrl.includes("://")||s.mediaUrl.startsWith("file://"),u=I.join(H(),".adam","wechat","media","outbound-tmp");await R.mkdir(u,{recursive:!0});let p=this.getExtensionFromMediaType(s.mediaType),l;if(c){let m=s.mediaUrl.startsWith("file://")?new URL(s.mediaUrl).pathname:I.isAbsolute(s.mediaUrl)?s.mediaUrl:I.resolve(s.mediaUrl),b=await R.readFile(m);l=I.join(u,`${Date.now()}-${Math.random().toString(36).slice(2,7)}${p}`),await R.writeFile(l,b)}else{let m=await fetch(s.mediaUrl);if(!m.ok)throw new Error(`Failed to fetch media: ${m.status}`);let b=Buffer.from(await m.arrayBuffer());l=I.join(u,`${Date.now()}-${Math.random().toString(36).slice(2,7)}${p}`),await R.writeFile(l,b)}let h=await Qe({filePath:l,to:e,text:s.content??"",opts:{baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,contextToken:a},cdnBaseUrl:d});return await R.unlink(l).catch(()=>{}),i.quotaRemaining--,N(this.id,this.sessions),f.info({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:i.quotaRemaining,sessionRemainingHours:(this.getSessionRemainingMs(i)/36e5).toFixed(1)},"iLink send success: quota decremented"),this.checkAndSendReminder(e,i).catch(m=>{f.warn({channelId:this.id,chatId:e.slice(0,12)},`Reminder send failed: ${String(m)}`)}),h.messageId}return await E({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,body:{msg:{from_user_id:"",to_user_id:e,client_id:o,message_type:A.BOT,message_state:P.FINISH,item_list:s.content?[{type:y.TEXT,text_item:{text:s.content}}]:void 0,context_token:a}}}),i.quotaRemaining--,N(this.id,this.sessions),f.info({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:i.quotaRemaining,sessionRemainingHours:(this.getSessionRemainingMs(i)/36e5).toFixed(1)},"iLink send success: quota decremented"),this.checkAndSendReminder(e,i).catch(c=>{f.warn({channelId:this.id,chatId:e.slice(0,12)},`Reminder send failed: ${String(c)}`)}),o}catch(c){if(c instanceof Error&&c.message.includes("ret=-2"))return i.quotaRemaining=0,N(this.id,this.sessions),f.warn({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:0},"iLink quota exhausted (ret=-2 confirmed), message queued"),this.enqueueMessage(e,s),`queued-${$()}`;throw c}}onMessage(e){this.messageHandler=e}async sendTypingIndicator(e){if(j(this.id))return;let s=oe(this.id,e);try{await ye({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,body:{ilink_user_id:e,status:Re.TYPING}})}catch{}}updateConfig(e){Object.assign(this.config,e)}getOrCreateSession(e){let s=this.sessions.get(e);return s||(s={lastUserMessageAt:0,quotaRemaining:0},this.sessions.set(e,s)),s}isSessionActive(e){return e.lastUserMessageAt>0&&Date.now()-e.lastUserMessageAt<=ae}getSessionRemainingMs(e){return e.lastUserMessageAt===0?0:Math.max(0,ae-(Date.now()-e.lastUserMessageAt))}enqueueMessage(e,s){let i=this.pendingQueue.get(e);i||(i=[],this.pendingQueue.set(e,i));let n=Date.now();i=i.filter(r=>n-r.queuedAt<Ge),i.length>=vt&&(i.shift(),f.warn({channelId:this.id,chatId:e.slice(0,12)},"Queue full, dropping oldest message")),i.push({message:s,queuedAt:n}),this.pendingQueue.set(e,i),f.info({channelId:this.id,chatId:e.slice(0,12),queueDepth:i.length},"Message enqueued")}async flushQueue(e){let s=this.pendingQueue.get(e);if(!s||s.length===0)return;let i=this.getOrCreateSession(e),n=Math.min(s.length,Math.max(0,i.quotaRemaining-2));if(n<=0){f.info({channelId:this.id,chatId:e.slice(0,12),quotaRemaining:i.quotaRemaining},"Queue flush skipped: insufficient quota (reserving 2 for conversation)");return}f.info({channelId:this.id,chatId:e.slice(0,12),queueDepth:s.length,sending:n,quotaRemaining:i.quotaRemaining},"Flushing queued messages");let r=0;for(;r<n&&s.length>0;){let o=s[0];if(Date.now()-o.queuedAt>Ge){s.shift();continue}try{if(await this.sendMessage(e,o.message),s.shift(),r++,i.quotaRemaining<=0)break}catch{f.warn({channelId:this.id,chatId:e.slice(0,12)},"Queue flush: send failed, stopping");break}}s.length===0&&this.pendingQueue.delete(e),f.info({channelId:this.id,chatId:e.slice(0,12),sent:r,remaining:s.length},"Queue flush complete")}async checkAndSendReminder(e,s){let i=Date.now(),n=this.lastReminderAt.get(e)??0;if(i-n<Nt)return;let r=this.getSessionRemainingMs(s),a=i-s.lastUserMessageAt>=Ot,d=s.quotaRemaining<=qt;if(!a&&!d)return;let c=(r/36e5).toFixed(1),u;a&&d?u=`[\u7CFB\u7EDF\u63D0\u9192] \u6D88\u606F\u7A97\u53E3\u5373\u5C06\u5173\u95ED\uFF08\u5269\u4F59${c}\u5C0F\u65F6/${s.quotaRemaining}\u6761\u914D\u989D\uFF09\u3002\u8BF7\u56DE\u590D\u4EFB\u610F\u6D88\u606F\u4EE5\u4FDD\u6301\u8FDE\u63A5\u3002`:a?u=`[\u7CFB\u7EDF\u63D0\u9192] \u6D88\u606F\u7A97\u53E3\u5373\u5C06\u5173\u95ED\uFF08\u5269\u4F59${c}\u5C0F\u65F6\uFF09\u3002\u8BF7\u56DE\u590D\u4EFB\u610F\u6D88\u606F\u4EE5\u4FDD\u6301\u8FDE\u63A5\u3002`:u=`[\u7CFB\u7EDF\u63D0\u9192] \u6D88\u606F\u914D\u989D\u5373\u5C06\u7528\u5B8C\uFF08\u5269\u4F59${s.quotaRemaining}\u6761\uFF09\u3002\u8BF7\u56DE\u590D\u4EFB\u610F\u6D88\u606F\u4EE5\u91CD\u7F6E\u914D\u989D\u3002`;let p=oe(this.id,e);try{await E({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,body:{msg:{from_user_id:"",to_user_id:e,client_id:$(),message_type:A.BOT,message_state:P.FINISH,item_list:[{type:y.TEXT,text_item:{text:u}}],context_token:p}}}),s.quotaRemaining--,this.lastReminderAt.set(e,i),N(this.id,this.sessions),f.info({channelId:this.id,chatId:e.slice(0,12),remainingHours:c,quotaRemaining:s.quotaRemaining,trigger:a?"time":"quota"},"iLink session reminder sent")}catch(l){f.warn({channelId:this.id,chatId:e.slice(0,12)},`Reminder send failed: ${String(l)}`)}}async startLongPoll(){let e=this.pollAbort?.signal,s=0,i=3,n=3e4,r=2e3;for(;!e?.aborted;)try{let o=await he({baseUrl:this.config.baseUrl,token:this.config.botToken,routeTag:this.config.routeTag,get_updates_buf:this.getUpdatesBuf});if(o.ret===ee||o.errcode===ee){Me(this.id),this.status="error",f.error({channelId:this.id},"Session expired (errcode=-14), pausing for 1 hour"),await this.sleep(B,e),ke(this.id),this.status="connected";continue}if(o.ret!==void 0&&o.ret!==0||o.errcode!==void 0&&o.errcode!==0){s++,f.error({channelId:this.id,ret:o.ret,errcode:o.errcode},"getUpdates API error"),s>=i?(s=0,await this.sleep(n,e)):await this.sleep(r,e);continue}s=0,o.get_updates_buf&&(this.getUpdatesBuf=o.get_updates_buf,Pt(this.id,o.get_updates_buf));for(let d of o.msgs??[])await this.processInbound(d)}catch(o){if(e?.aborted)return;s++,f.error({channelId:this.id,error:o},"getUpdates error"),s>=i?(s=0,await this.sleep(n,e)):await this.sleep(r,e)}}async processInbound(e){if(!this.messageHandler)return;let s=!!e.group_id,i=s?e.group_id:e.from_user_id??"",n=e.from_user_id??"";e.context_token&&i&&Et(this.id,i,e.context_token);let r=this.getOrCreateSession(i),o=r.quotaRemaining;r.lastUserMessageAt=Date.now(),r.quotaRemaining=ze,N(this.id,this.sessions),f.info({channelId:this.id,chatId:i.slice(0,12),quotaReset:!0,prevQuota:o,newQuota:ze,sessionWindowMs:ae},"iLink session reset: user message received, quota restored"),this.flushQueue(i);let a="",d,c=[];for(let l of e.item_list??[])l.type===y.TEXT&&l.text_item?.text&&(a+=l.text_item.text),l.type===y.IMAGE&&(d="image",c.push(l)),l.type===y.VOICE&&(d="audio",c.push(l),l.voice_item?.text&&!a&&(a=l.voice_item.text)),l.type===y.FILE&&(d="file",c.push(l)),l.type===y.VIDEO&&(d="video",c.push(l));if(!a&&!d)return;let u;if(c.length>0){let l=this.config.cdnBaseUrl??Ve;try{let h=await Le(c[0],{cdnBaseUrl:l,channelId:this.id});h&&(u=h.path,d=h.type)}catch(h){f.error({channelId:this.id},`Media download failed: ${String(h)}`)}}let p={channelId:this.id,platform:"wechat",chatId:i,senderId:n,content:a,mediaType:d,mediaPath:u,isGroup:s,timestamp:e.create_time_ms??Date.now(),raw:e};this.messageHandler(p)}getExtensionFromMediaType(e){switch(e){case"image":return".png";case"video":return".mp4";case"audio":return".mp3";default:return".bin"}}sleep(e,s){return new Promise((i,n)=>{let r=setTimeout(i,e);s?.addEventListener("abort",()=>{clearTimeout(r),n(new Error("aborted"))},{once:!0})})}};M();var Lt=_("channels"),X=class{platform="discord";id;config;status="disconnected";messageHandler=null;client=null;constructor(e,s){if(this.id=e,!s.botToken)throw new Error("Discord adapter requires botToken");this.config=s}async connect(){this.status="connecting";try{let{Client:e,GatewayIntentBits:s}=await import("discord.js");this.client=new e({intents:[s.Guilds,s.GuildMessages,s.MessageContent,s.DirectMessages]});let i=this.client;i.on("messageCreate",n=>{if(!this.messageHandler||n.author.bot||this.config.allowedGuildIds?.length&&n.guildId&&!this.config.allowedGuildIds.includes(n.guildId))return;let r={channelId:this.id,platform:"discord",chatId:n.channelId,senderId:n.author.id,senderName:n.author.displayName??n.author.username,content:n.content,isGroup:!!n.guildId,timestamp:n.createdTimestamp,raw:n};this.messageHandler(r)}),await i.login(this.config.botToken),this.status="connected",Lt.info({channelId:this.id},"Discord bot connected")}catch(e){throw this.status="error",e}}async disconnect(){this.client&&await this.client.destroy(),this.client=null,this.status="disconnected"}getStatus(){return this.status}async sendMessage(e,s){if(!this.client)throw new Error("Discord client not connected");let n=await this.client.channels.fetch(e);if(!n||!("send"in n))throw new Error(`Channel ${e} not found or not text channel`);return(await n.send({content:s.content,reply:s.replyToMessageId?{messageReference:s.replyToMessageId}:void 0})).id}onMessage(e){this.messageHandler=e}async sendTypingIndicator(e){if(!this.client)return;let i=await this.client.channels.fetch(e);i&&"sendTyping"in i&&await i.sendTyping()}};var k=g.object({id:g.string().uuid()}),Wt=g.object({name:g.string().min(1,"name is required"),platform:g.string().min(1,"platform is required"),config:g.record(g.string(),g.unknown()),enabled:g.boolean().optional().default(!0),linkedRoleId:g.string().optional(),allowedChatIds:g.array(g.string()).optional()}),Bt=g.object({name:g.string().min(1).optional(),enabled:g.boolean().optional(),config:g.record(g.string(),g.unknown()).optional(),linkedRoleId:g.string().optional(),allowedChatIds:g.array(g.string()).optional()}),ce;function Zn(t){ce=t}function es(){return ce}async function ts(t){let e=ce;t.get("/channels",{schema:{tags:["Channels"],summary:"List channels",querystring:{type:"object",properties:{enabled:{type:"boolean"}}}}},async(s,i)=>({channels:ge(s.query.enabled)})),t.post("/channels",{schema:{tags:["Channels"],summary:"Create a channel",body:{type:"object",required:["name","platform","config"],properties:{name:{type:"string",minLength:1},platform:{type:"string",minLength:1},config:{type:"object"},enabled:{type:"boolean"},linkedRoleId:{type:"string"},allowedChatIds:{type:"array",items:{type:"string"}}}}}},async(s,i)=>{let n=Wt.safeParse(s.body);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let{name:r,platform:o,config:a,enabled:d,linkedRoleId:c,allowedChatIds:u}=n.data,p={id:Dt(),name:r,platform:o,enabled:d,status:"disconnected",config:a,linkedRoleId:c,allowedChatIds:u,createdAt:Date.now(),messageCount:0};return le(p),i.status(201).send({channel:p})}),t.get("/channels/:id",{schema:{tags:["Channels"],summary:"Get channel by ID",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let r=x(n.data.id);return r?{channel:r}:i.status(404).send({code:"NOT_FOUND",message:"Channel not found"})}),t.patch("/channels/:id",{schema:{tags:["Channels"],summary:"Update channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},body:{type:"object",properties:{name:{type:"string"},enabled:{type:"boolean"},config:{type:"object"},linkedRoleId:{type:"string"},allowedChatIds:{type:"array",items:{type:"string"}}}}}},async(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let r=x(n.data.id);if(!r)return i.status(404).send({code:"NOT_FOUND",message:"Channel not found"});let o=Bt.safeParse(s.body);return o.success?(J(r.id,o.data),{channel:x(r.id)}):i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(o.error)})}),t.delete("/channels/:id",{schema:{tags:["Channels"],summary:"Delete channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let r=x(n.data.id);return r?(me(r.id),i.status(204).send()):i.status(404).send({code:"NOT_FOUND",message:"Channel not found"})}),t.post("/channels/:id/connect",{schema:{tags:["Channels"],summary:"Connect channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});if(!e)return i.status(501).send({code:"NOT_IMPLEMENTED",message:"Channel manager not initialized"});let r=x(n.data.id);if(!r)return i.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(!e.hasAdapter(r.id)&&r.platform==="discord"){let o=r.config;if(!o.botToken)return i.status(400).send({code:"MISSING_CONFIG",message:"Discord channel requires botToken in config"});let a=new X(r.id,{botToken:o.botToken});await e.addChannel(r,a)}if(!e.hasAdapter(r.id))return i.status(400).send({code:"NO_ADAPTER",message:"No adapter registered for this channel. Install the appropriate adapter first."});try{return await e.connectChannel(r.id),{channelId:r.id,status:"connected"}}catch(o){return i.status(500).send({code:"CONNECT_FAILED",message:String(o)})}}),t.post("/channels/:id/disconnect",{schema:{tags:["Channels"],summary:"Disconnect channel",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});if(!e)return i.status(501).send({code:"NOT_IMPLEMENTED",message:"Channel manager not initialized"});let r=x(n.data.id);return r?(await e.disconnectChannel(r.id),{channelId:r.id,status:"disconnected"}):i.status(404).send({code:"NOT_FOUND",message:"Channel not found"})}),t.get("/channels/:id/messages",{schema:{tags:["Channels"],summary:"Get channel message history",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},querystring:{type:"object",properties:{limit:{type:"integer",minimum:1,maximum:200,default:50},offset:{type:"integer",minimum:0,default:0}}}}},async(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let r=x(n.data.id);if(!r)return i.status(404).send({code:"NOT_FOUND",message:"Channel not found"});let{limit:o=50,offset:a=0}=s.query;return{messages:ue(r.id,o,a)}}),t.post("/channels/:id/wechat/qr-start",{schema:{tags:["WeChat"],summary:"Start WeChat QR login",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let r=x(n.data.id);if(!r)return i.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(r.platform!=="wechat")return i.status(400).send({code:"INVALID_PLATFORM",message:"Channel is not a WeChat channel"});let o=r.config;return await Ie({apiBaseUrl:o.baseUrl,routeTag:o.routeTag})}),t.post("/channels/:id/wechat/qr-wait",{schema:{tags:["WeChat"],summary:"Wait for WeChat QR scan",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},body:{type:"object",properties:{sessionKey:{type:"string"},timeoutMs:{type:"number"}}}}},async(s,i)=>{let n=k.safeParse(s.params);if(!n.success)return i.status(400).send({code:"VALIDATION_ERROR",message:g.prettifyError(n.error)});let r=x(n.data.id);if(!r)return i.status(404).send({code:"NOT_FOUND",message:"Channel not found"});if(r.platform!=="wechat")return i.status(400).send({code:"INVALID_PLATFORM",message:"Channel is not a WeChat channel"});let o=r.config,{sessionKey:a,timeoutMs:d}=s.body??{},c=await Te({sessionKey:a??"",apiBaseUrl:o.baseUrl,timeoutMs:d??12e4,routeTag:o.routeTag});if(c.connected&&c.botToken){let u={...o,botToken:c.botToken,accountId:c.accountId,baseUrl:c.baseUrl??o.baseUrl,userId:c.userId};if(J(r.id,{config:u}),e){let p=new K(r.id,u),l=x(r.id);l&&await e.addChannel(l,p)}}return{connected:c.connected,accountId:c.accountId,message:c.message}})}export{K as a,X as b,Zn as c,es as d,ts as e};
@@ -1,4 +1,4 @@
1
- import{b as s,d as o}from"./chunk-5EPG2US5.js";o();function i(e){return{id:e.id,ruleId:e.rule_id??void 0,taskId:e.task_id??void 0,status:e.status,target:JSON.parse(e.target),content:e.content,attempts:e.attempts,error:e.error??void 0,createdAt:e.created_at,deliveredAt:e.delivered_at??void 0,expiresAt:e.expires_at,source:e.source,messageType:e.message_type??void 0}}var u=1440*60*1e3;function p(e){s().prepare(`
1
+ import{b as s,d as o}from"./chunk-7F4SZXI2.js";o();function i(e){return{id:e.id,ruleId:e.rule_id??void 0,taskId:e.task_id??void 0,status:e.status,target:JSON.parse(e.target),content:e.content,attempts:e.attempts,error:e.error??void 0,createdAt:e.created_at,deliveredAt:e.delivered_at??void 0,expiresAt:e.expires_at,source:e.source,messageType:e.message_type??void 0}}var u=1440*60*1e3;function p(e){s().prepare(`
2
2
  INSERT INTO delivery_log (id, rule_id, task_id, status, target, content,
3
3
  attempts, error, created_at, delivered_at, expires_at, source, message_type)
4
4
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
@@ -1 +1 @@
1
- import{e as T,j as $}from"./chunk-WMB7P64J.js";import{e as R,i as x}from"./chunk-HQRUJQN7.js";import{c as J,e as E}from"./chunk-FCV2DPZQ.js";var F={};E(F,{getGlobalEnabledState:()=>k,getInstalledPlugin:()=>N,getPluginManifest:()=>j,listInstalledPlugins:()=>v,listMarketplaceSources:()=>L,resolvePluginPaths:()=>A,scanDirectoryConfig:()=>w});import{existsSync as m,readFileSync as y,readdirSync as I}from"fs";import{join as u}from"path";import M from"os";function h(n){try{if(!m(n))return null;let t=y(n,"utf-8");return JSON.parse(t)}catch{return null}}function k(){return h(O())?.enabledPlugins??{}}function j(n){let t=n;function o(e,s){let l={};try{if(!m(e))return l;let c=y(e,"utf-8").replace(/^```yaml\r?\n/,"").replace(/^```\r?\n/,"");for(let d of s){let r=new RegExp(`^${d}:\\s*(.+)$`,"m"),g=c.match(r);g&&(l[d]=g[1].trim())}}catch{}return l}try{let e={name:"",skills:[],agents:[],mcpServers:[],hooks:[],lspServers:[]},s=u(t,".claude-plugin","plugin.json");if(m(s))try{let r=JSON.parse(y(s,"utf-8"));e.name=r.name??"",e.version=r.version,e.description=r.description,Array.isArray(r.lspServers)&&(e.lspServers=r.lspServers),Array.isArray(r.mcpServers)&&(e.mcpServers=r.mcpServers),Array.isArray(r.hooks)&&(e.hooks=r.hooks)}catch{}let l=u(t,"skills");if(m(l)){let r=I(l,{withFileTypes:!0});for(let g of r){if(!g.isDirectory()&&!g.isSymbolicLink())continue;let p=u(l,g.name,"SKILL.md"),i=o(p,["name","description"]);i.name&&e.skills.push({name:i.name,description:i.description??""})}}let a=u(t,"agents");if(m(a)){let r=I(a,{withFileTypes:!0});for(let g of r){if(!g.isFile()||!g.name.endsWith(".md"))continue;let p=o(u(a,g.name),["name","description"]);p.name&&e.agents.push({name:p.name,description:p.description??""})}}let c=u(t,".mcp.json");if(m(c))try{let r=JSON.parse(y(c,"utf-8"));r.mcpServers&&typeof r.mcpServers=="object"&&(e.mcpServers=Object.keys(r.mcpServers))}catch{}let d=u(t,"hooks","hooks.json");if(m(d))try{let r=JSON.parse(y(d,"utf-8"));Array.isArray(r)&&(e.hooks=r.map(g=>typeof g=="object"&&g!==null&&"event"in g?String(g.event):String(g)))}catch{}return e}catch{return null}}function v(n){let t=h(S());if(!t?.plugins)return[];let o=k(),e=[];for(let[s,l]of Object.entries(t.plugins))if(!(!Array.isArray(l)||l.length===0))for(let a of l){let c=a.scope??"user";n?.scope&&c!==n.scope||n?.projectPath&&a.projectPath!==n.projectPath||e.push({id:s,name:s.split("@")[0],version:a.version??"",scope:c,projectPath:a.projectPath,installPath:a.installPath??u(P(),s),enabled:o[s]??a.enabled??!0,installedAt:a.installedAt??"",lastUpdated:a.lastUpdated??""})}return e}function N(n){let t=h(S());if(!t?.plugins?.[n])return null;let o=t.plugins[n];if(!Array.isArray(o)||o.length===0)return null;let e=o[0],s=k();return{id:n,name:n.split("@")[0],version:e.version??"",scope:e.scope??"user",projectPath:e.projectPath,installPath:e.installPath??u(P(),n),enabled:s[n]??e.enabled??!0,installedAt:e.installedAt??"",lastUpdated:e.lastUpdated??""}}function A(n){let t=h(S()),o=new Map;for(let e of n){let s=t?.plugins?.[e];Array.isArray(s)&&s.length>0&&o.set(e,s[0].installPath??u(P(),e))}return o}function L(){return h(C())?.marketplaces??[]}function w(n){let t=u(n,".claude","settings.json"),o=h(t);return{enabledPlugins:o?.enabledPlugins??{},mcpServers:o?.mcpServers??{},allowedTools:o?.allowedTools??[],disallowedTools:o?.disallowedTools??[]}}var P,S,C,O,D=J(()=>{"use strict";P=()=>u(M.homedir(),".claude","plugins"),S=()=>u(P(),"installed_plugins.json"),C=()=>u(P(),"known_marketplaces.json"),O=()=>u(M.homedir(),".claude","settings.json")});D();$();x();var _={Read:{category:"File",label:"read"},Write:{category:"File",label:"write"},Edit:{category:"File",label:"edit"},Glob:{category:"Search",label:"find files"},Grep:{category:"Search",label:"search content"},Bash:{category:"Execution",label:"shell commands"},WebSearch:{category:"Web",label:"web search"},WebFetch:{category:"Web",label:"fetch pages"},NotebookEdit:{category:"Execution",label:"Jupyter notebooks"}};function z(n,t){let o=n.allowedTools??[],e=n.osCapabilities??[];if(o.length===0&&e.length===0&&Object.keys(n.mcpServers??{}).length===0&&(n.additionalDirectories?.length??0)===0&&(!t||t.plugins.length===0))return"No tool permissions";let s=new Map,l=[];for(let p of o){let i=_[p];if(i){let f=s.get(i.category)??[];f.push(i.label),s.set(i.category,f)}else l.push(p)}let a=[];for(let[p,i]of s)a.push(`${p} (${i.join(", ")})`);l.length>0&&a.push(l.join(", "));let c=a.join(" \xB7 "),d=p=>{c=c?`${c} \xB7 ${p}`:p},r=Object.keys(n.mcpServers??{});r.length>0&&d(`MCP: ${r.join(", ")}`);let g=n.additionalDirectories??[];if(g.length>0&&d(`Dirs: ${g.map(p=>p.path).join(", ")}`),e.length>0){let p=e.map(i=>{let f=R(i.id);return i.id==="automation"&&i.targets?.length?`${f.label} (${i.targets.join(", ")})`:f.label});d(`OS: ${p.join(", ")}`)}if(t&&t.plugins.length>0){let p=t.plugins.map(i=>{let f=[];return i.skills.length>0&&f.push(`skills: ${i.skills.map(b=>b.name).join(", ")}`),i.agents.length>0&&f.push(`agents: ${i.agents.map(b=>b.name).join(", ")}`),f.length>0?`${i.name} (${f.join("; ")})`:i.name});d(`Plugins: ${p.join(", ")}`)}return c}function W(n){let t=[],o=n.additionalDirectories??[];for(let e of o){if(!e.inheritPlugins&&!e.inheritMcp)continue;let s=w(e.path),l=Object.entries(s.enabledPlugins).filter(([,c])=>c).map(([c])=>c),a=A(l);for(let[,c]of a)t.includes(c)||t.push(c)}try{let e=T(n.name),s=v({scope:"project",projectPath:e});for(let l of s)l.installPath&&!t.includes(l.installPath)&&t.push(l.installPath)}catch{}return t}function Q(n){let t=W(n),o=[];for(let e of t){let s=j(e);s&&o.push({name:s.name||e.split("/").pop()||"unknown",description:s.description,skills:s.skills,agents:s.agents,mcpServers:s.mcpServers,hooks:s.hooks})}return{plugins:o}}export{k as a,j as b,v as c,N as d,L as e,w as f,F as g,D as h,z as i,W as j,Q as k};
1
+ import{e as T,j as $}from"./chunk-6XVWIRR2.js";import{e as R,i as x}from"./chunk-YWUX3ZTO.js";import{c as J,e as E}from"./chunk-FCV2DPZQ.js";var F={};E(F,{getGlobalEnabledState:()=>k,getInstalledPlugin:()=>N,getPluginManifest:()=>j,listInstalledPlugins:()=>v,listMarketplaceSources:()=>L,resolvePluginPaths:()=>A,scanDirectoryConfig:()=>w});import{existsSync as m,readFileSync as y,readdirSync as I}from"fs";import{join as u}from"path";import M from"os";function h(n){try{if(!m(n))return null;let t=y(n,"utf-8");return JSON.parse(t)}catch{return null}}function k(){return h(O())?.enabledPlugins??{}}function j(n){let t=n;function o(e,s){let l={};try{if(!m(e))return l;let c=y(e,"utf-8").replace(/^```yaml\r?\n/,"").replace(/^```\r?\n/,"");for(let d of s){let r=new RegExp(`^${d}:\\s*(.+)$`,"m"),g=c.match(r);g&&(l[d]=g[1].trim())}}catch{}return l}try{let e={name:"",skills:[],agents:[],mcpServers:[],hooks:[],lspServers:[]},s=u(t,".claude-plugin","plugin.json");if(m(s))try{let r=JSON.parse(y(s,"utf-8"));e.name=r.name??"",e.version=r.version,e.description=r.description,Array.isArray(r.lspServers)&&(e.lspServers=r.lspServers),Array.isArray(r.mcpServers)&&(e.mcpServers=r.mcpServers),Array.isArray(r.hooks)&&(e.hooks=r.hooks)}catch{}let l=u(t,"skills");if(m(l)){let r=I(l,{withFileTypes:!0});for(let g of r){if(!g.isDirectory()&&!g.isSymbolicLink())continue;let p=u(l,g.name,"SKILL.md"),i=o(p,["name","description"]);i.name&&e.skills.push({name:i.name,description:i.description??""})}}let a=u(t,"agents");if(m(a)){let r=I(a,{withFileTypes:!0});for(let g of r){if(!g.isFile()||!g.name.endsWith(".md"))continue;let p=o(u(a,g.name),["name","description"]);p.name&&e.agents.push({name:p.name,description:p.description??""})}}let c=u(t,".mcp.json");if(m(c))try{let r=JSON.parse(y(c,"utf-8"));r.mcpServers&&typeof r.mcpServers=="object"&&(e.mcpServers=Object.keys(r.mcpServers))}catch{}let d=u(t,"hooks","hooks.json");if(m(d))try{let r=JSON.parse(y(d,"utf-8"));Array.isArray(r)&&(e.hooks=r.map(g=>typeof g=="object"&&g!==null&&"event"in g?String(g.event):String(g)))}catch{}return e}catch{return null}}function v(n){let t=h(S());if(!t?.plugins)return[];let o=k(),e=[];for(let[s,l]of Object.entries(t.plugins))if(!(!Array.isArray(l)||l.length===0))for(let a of l){let c=a.scope??"user";n?.scope&&c!==n.scope||n?.projectPath&&a.projectPath!==n.projectPath||e.push({id:s,name:s.split("@")[0],version:a.version??"",scope:c,projectPath:a.projectPath,installPath:a.installPath??u(P(),s),enabled:o[s]??a.enabled??!0,installedAt:a.installedAt??"",lastUpdated:a.lastUpdated??""})}return e}function N(n){let t=h(S());if(!t?.plugins?.[n])return null;let o=t.plugins[n];if(!Array.isArray(o)||o.length===0)return null;let e=o[0],s=k();return{id:n,name:n.split("@")[0],version:e.version??"",scope:e.scope??"user",projectPath:e.projectPath,installPath:e.installPath??u(P(),n),enabled:s[n]??e.enabled??!0,installedAt:e.installedAt??"",lastUpdated:e.lastUpdated??""}}function A(n){let t=h(S()),o=new Map;for(let e of n){let s=t?.plugins?.[e];Array.isArray(s)&&s.length>0&&o.set(e,s[0].installPath??u(P(),e))}return o}function L(){return h(C())?.marketplaces??[]}function w(n){let t=u(n,".claude","settings.json"),o=h(t);return{enabledPlugins:o?.enabledPlugins??{},mcpServers:o?.mcpServers??{},allowedTools:o?.allowedTools??[],disallowedTools:o?.disallowedTools??[]}}var P,S,C,O,D=J(()=>{"use strict";P=()=>u(M.homedir(),".claude","plugins"),S=()=>u(P(),"installed_plugins.json"),C=()=>u(P(),"known_marketplaces.json"),O=()=>u(M.homedir(),".claude","settings.json")});D();$();x();var _={Read:{category:"File",label:"read"},Write:{category:"File",label:"write"},Edit:{category:"File",label:"edit"},Glob:{category:"Search",label:"find files"},Grep:{category:"Search",label:"search content"},Bash:{category:"Execution",label:"shell commands"},WebSearch:{category:"Web",label:"web search"},WebFetch:{category:"Web",label:"fetch pages"},NotebookEdit:{category:"Execution",label:"Jupyter notebooks"}};function z(n,t){let o=n.allowedTools??[],e=n.osCapabilities??[];if(o.length===0&&e.length===0&&Object.keys(n.mcpServers??{}).length===0&&(n.additionalDirectories?.length??0)===0&&(!t||t.plugins.length===0))return"No tool permissions";let s=new Map,l=[];for(let p of o){let i=_[p];if(i){let f=s.get(i.category)??[];f.push(i.label),s.set(i.category,f)}else l.push(p)}let a=[];for(let[p,i]of s)a.push(`${p} (${i.join(", ")})`);l.length>0&&a.push(l.join(", "));let c=a.join(" \xB7 "),d=p=>{c=c?`${c} \xB7 ${p}`:p},r=Object.keys(n.mcpServers??{});r.length>0&&d(`MCP: ${r.join(", ")}`);let g=n.additionalDirectories??[];if(g.length>0&&d(`Dirs: ${g.map(p=>p.path).join(", ")}`),e.length>0){let p=e.map(i=>{let f=R(i.id);return i.id==="automation"&&i.targets?.length?`${f.label} (${i.targets.join(", ")})`:f.label});d(`OS: ${p.join(", ")}`)}if(t&&t.plugins.length>0){let p=t.plugins.map(i=>{let f=[];return i.skills.length>0&&f.push(`skills: ${i.skills.map(b=>b.name).join(", ")}`),i.agents.length>0&&f.push(`agents: ${i.agents.map(b=>b.name).join(", ")}`),f.length>0?`${i.name} (${f.join("; ")})`:i.name});d(`Plugins: ${p.join(", ")}`)}return c}function W(n){let t=[],o=n.additionalDirectories??[];for(let e of o){if(!e.inheritPlugins&&!e.inheritMcp)continue;let s=w(e.path),l=Object.entries(s.enabledPlugins).filter(([,c])=>c).map(([c])=>c),a=A(l);for(let[,c]of a)t.includes(c)||t.push(c)}try{let e=T(n.name),s=v({scope:"project",projectPath:e});for(let l of s)l.installPath&&!t.includes(l.installPath)&&t.push(l.installPath)}catch{}return t}function Q(n){let t=W(n),o=[];for(let e of t){let s=j(e);s&&o.push({name:s.name||e.split("/").pop()||"unknown",description:s.description,skills:s.skills,agents:s.agents,mcpServers:s.mcpServers,hooks:s.hooks})}return{plugins:o}}export{k as a,j as b,v as c,N as d,L as e,w as f,F as g,D as h,z as i,W as j,Q as k};
@@ -1,4 +1,4 @@
1
- import{b as e,d as p}from"./chunk-5EPG2US5.js";p();function i(t){return{id:t.id,taskId:t.task_id,index:t.index,type:t.type,content:t.content,toolName:t.tool_name??void 0,toolInput:t.tool_input?JSON.parse(t.tool_input):void 0,toolOutput:t.tool_output??void 0,truncated:t.truncated===1,timestamp:t.timestamp,tokenUsage:t.token_usage?JSON.parse(t.token_usage):void 0,planStepIndex:t.plan_step_index??void 0}}function a(t){e().prepare(`
1
+ import{b as e,d as p}from"./chunk-7F4SZXI2.js";p();function i(t){return{id:t.id,taskId:t.task_id,index:t.index,type:t.type,content:t.content,toolName:t.tool_name??void 0,toolInput:t.tool_input?JSON.parse(t.tool_input):void 0,toolOutput:t.tool_output??void 0,truncated:t.truncated===1,timestamp:t.timestamp,tokenUsage:t.token_usage?JSON.parse(t.token_usage):void 0,planStepIndex:t.plan_step_index??void 0}}function a(t){e().prepare(`
2
2
  INSERT INTO step_logs (id, task_id, "index", type, content, tool_name,
3
3
  tool_input, tool_output, truncated, timestamp, token_usage, plan_step_index)
4
4
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
@@ -1,3 +1,3 @@
1
- import{f as S}from"./chunk-5QZXYKMS.js";import{b as v}from"./chunk-2YTDCR6A.js";import{b as y}from"./chunk-BQ3ZAYHC.js";import{e as m}from"./chunk-B6LOT5CG.js";import{b as g}from"./chunk-K4C43YDD.js";import{b as C}from"./chunk-RI3V72RP.js";import{b as R}from"./chunk-GSFLLRS7.js";import{a as h}from"./chunk-L7JP7DUO.js";import{a as k,b as P,c as o,d as f,e as T,f as x,g as E}from"./chunk-RZ7LCZVK.js";import{c as w,h as _}from"./chunk-MRTJFYPR.js";_();import{v4 as M}from"uuid";var l=w("admin"),I=new Map,u=null,p=null,c=null,D=class{constructor(){h.on("task_status_change",e=>{(e.newStatus==="completed"||e.newStatus==="failed")&&this.handleTaskStatusChange(e.taskId,e.newStatus).catch(n=>{l.error({taskId:e.taskId,error:n},"Delivery processing failed")})}),h.on("plan_approval_request",e=>{this.handlePlanApprovalRequest(e.taskId,e.planId,e.plan).catch(n=>{l.error({taskId:e.taskId,error:n},"Delivery processing failed (plan_approval)")})}),l.info("DeliveryEngine initialized")}async handlePlanApprovalRequest(e,n,r){let t=g(e),i=this.getSourceChannelForTask(e);if(i){let d=y(r),{sendApprovalToChannel:b}=await import("./approval-handler-PB7PSLUS.js");await b(i.channelId,i.chatId,n,e,d)}let a=y(r)+`
1
+ import{f as S}from"./chunk-W7U3ASGR.js";import{b as y}from"./chunk-3HZE5DQZ.js";import{b as v}from"./chunk-TTP7QRAQ.js";import{e as m}from"./chunk-UQDC3X6O.js";import{b as g}from"./chunk-OY2KVSIX.js";import{b as C}from"./chunk-KUJFQDT5.js";import{b as R}from"./chunk-IZ3WZHCM.js";import{a as h}from"./chunk-L7JP7DUO.js";import{a as k,b as P,c as o,d as f,e as T,f as x,g as E}from"./chunk-ARQF52V6.js";import{c as w,h as _}from"./chunk-MRTJFYPR.js";_();import{v4 as M}from"uuid";var l=w("admin"),I=new Map,u=null,p=null,c=null,D=class{constructor(){h.on("task_status_change",e=>{(e.newStatus==="completed"||e.newStatus==="failed")&&this.handleTaskStatusChange(e.taskId,e.newStatus).catch(n=>{l.error({taskId:e.taskId,error:n},"Delivery processing failed")})}),h.on("plan_approval_request",e=>{this.handlePlanApprovalRequest(e.taskId,e.planId,e.plan).catch(n=>{l.error({taskId:e.taskId,error:n},"Delivery processing failed (plan_approval)")})}),l.info("DeliveryEngine initialized")}async handlePlanApprovalRequest(e,n,r){let t=g(e),i=this.getSourceChannelForTask(e);if(i){let d=y(r),{sendApprovalToChannel:b}=await import("./approval-handler-JYCGXQUE.js");await b(i.channelId,i.chatId,n,e,d)}let a=y(r)+`
2
2
 
3
3
  Task: ${e}`;await this.matchAndDeliver("plan_approval_request",{templateId:t?.templateId,roleId:t?.roleId,prompt:t?.prompt,taskStatus:"pending"},a,e)}getSourceChannelForTask(e){try{let n=m(e);if(!n)return null;let r=v(n.sessionId);return!r||r.source.type!=="channel"||!r.source.channelId||!r.source.chatId?null:{channelId:r.source.channelId,chatId:r.source.chatId}}catch{return null}}async handleTaskStatusChange(e,n){let r=g(e);if(!r)return;let t={templateId:r.templateId,roleId:r.roleId,prompt:r.prompt,taskStatus:n},i=n==="completed"?"task_complete":"task_error",a=r.result??r.error??"";await this.matchAndDeliver(i,t,a,e)}async matchAndDeliver(e,n,r,t){let i=S(e,n);if(i.length!==0){l.debug({eventType:e,ruleCount:i.length,taskId:t},"Matched delivery rules");for(let a of i){if(!this.checkRateLimit(a)){l.warn({ruleId:a.id,maxPerMinute:a.maxPerMinute},"Delivery rate limit exceeded, skipping");continue}if(a.skipOriginChannel&&a.target.type==="channel"&&t&&this.isOriginChannel(t,a.target))continue;let d={id:M(),ruleId:a.id,taskId:t,status:"pending",target:a.target,content:r,attempts:0,createdAt:Date.now(),expiresAt:Date.now()+k,source:"rule"};P(d),await this.attemptDelivery(d,a)}}}async attemptDeliveryPublic(e,n){return this.attemptDelivery(e,n)}async attemptDelivery(e,n){let r=C();try{if(e.target.type==="channel"){let t=e.target.chatId;!t&&e.target.channelId&&(t=R(e.target.channelId)?.config?.userId);let i=await r.send({taskId:e.taskId,channelId:e.target.channelId,chatId:t,content:e.content,messageType:"deliver"});i.success?(f(e.id),l.info({entryId:e.id,ruleId:n.id,targetType:"channel"},"Delivery successful")):o(e.id,"failed",i.error??"Gateway returned failure")}else if(e.target.type==="webhook"){let t=await r.send({taskId:e.taskId,webhookUrl:e.target.webhookUrl,content:e.content,messageType:"deliver"});t.success?(f(e.id),l.info({entryId:e.id,ruleId:n.id,targetType:"webhook"},"Webhook delivery successful")):o(e.id,"failed",t.error??"Gateway returned failure")}}catch(t){let i=t instanceof Error?t.message:String(t);o(e.id,"failed",i),l.warn({entryId:e.id,error:i},"Delivery attempt failed")}}checkRateLimit(e){let n=Date.now(),r=6e4,t=I.get(e.id);t||(t=[],I.set(e.id,t));let i=n-r;for(;t.length>0&&t[0]<i;)t.shift();return t.length>=e.maxPerMinute?!1:(t.push(n),!0)}isOriginChannel(e,n){try{if(n.type!=="channel"||!n.channelId)return!1;let r=m(e);if(!r)return!1;let t=v(r.sessionId);return t?t.source.type==="channel"&&t.source.channelId===n.channelId&&(!n.chatId||t.source.chatId===n.chatId):!1}catch{return!1}}async retryPending(){let e=T("rule",50),n=x("rule",50),r=[...e,...n];if(r.length!==0){l.debug({count:r.length},"Retrying pending/failed deliveries");for(let t of r){if(t.attempts>=3){o(t.id,"failed","Max retries (3) exceeded");continue}let i={id:t.ruleId??"retry-synthetic",eventType:"*",matchCriteria:{},target:t.target,maxPerMinute:5,skipOriginChannel:!0,enabled:!0,createdAt:0};await this.attemptDelivery(t,i)}}}};function $(){return c}function H(){c||(c=new D,u=setInterval(()=>{c?.retryPending().catch(s=>{l.error({error:s},"Delivery retry scan failed")})},6e4),p=setInterval(()=>{try{let s=E();s>0&&l.info({cleaned:s},"Expired delivery log entries cleaned up")}catch(s){l.error({error:s},"Delivery cleanup failed")}},36e5),l.info("DeliveryEngine started with retry (60s) and cleanup (1h) timers"))}function J(){u&&(clearInterval(u),u=null),p&&(clearInterval(p),p=null),c=null,I.clear(),l.info("DeliveryEngine stopped")}export{D as a,$ as b,H as c,J as d};
@@ -1 +1 @@
1
- import{d as a}from"./chunk-GSMC3VUM.js";function s(){try{let t=a().server?.timezone;return t==="system"||!t?void 0:t}catch{return}}function p(t){let e=s();return new Date(t).toLocaleTimeString(void 0,e?{timeZone:e}:void 0)}function l(t){let e=t??s(),r=new Date,i=r.toLocaleDateString("en-CA",e?{timeZone:e}:void 0);if(e){let n=(new Intl.DateTimeFormat("en-US",{timeZone:e,timeZoneName:"shortOffset"}).formatToParts(r).find(o=>o.type==="timeZoneName")?.value??"").match(/GMT([+-]?)(\d+)(?::(\d+))?/);if(n){let o=n[1]==="-"?-1:1,m=parseInt(n[2],10),c=parseInt(n[3]??"0",10),f=o*(m*60+c)*6e4;return new Date(`${i}T00:00:00Z`).getTime()-f}}return new Date(`${i}T00:00:00`).getTime()}export{p as a,l as b};
1
+ import{d as a}from"./chunk-OFTIPZTH.js";function s(){try{let t=a().server?.timezone;return t==="system"||!t?void 0:t}catch{return}}function p(t){let e=s();return new Date(t).toLocaleTimeString(void 0,e?{timeZone:e}:void 0)}function l(t){let e=t??s(),r=new Date,i=r.toLocaleDateString("en-CA",e?{timeZone:e}:void 0);if(e){let n=(new Intl.DateTimeFormat("en-US",{timeZone:e,timeZoneName:"shortOffset"}).formatToParts(r).find(o=>o.type==="timeZoneName")?.value??"").match(/GMT([+-]?)(\d+)(?::(\d+))?/);if(n){let o=n[1]==="-"?-1:1,m=parseInt(n[2],10),c=parseInt(n[3]??"0",10),f=o*(m*60+c)*6e4;return new Date(`${i}T00:00:00Z`).getTime()-f}}return new Date(`${i}T00:00:00`).getTime()}export{p as a,l as b};
@@ -1,4 +1,4 @@
1
- import{b as s,d as i}from"./chunk-5EPG2US5.js";i();function l(e){return{id:e.id,name:e.name,platform:e.platform,enabled:e.enabled===1,status:e.status,config:JSON.parse(e.config),linkedRoleId:e.linked_role_id??void 0,allowedChatIds:e.allowed_chat_ids?JSON.parse(e.allowed_chat_ids):void 0,createdAt:e.created_at,updatedAt:e.updated_at??void 0,lastMessageAt:e.last_message_at??void 0,messageCount:e.message_count}}function o(e){s().prepare(`
1
+ import{b as s,d as i}from"./chunk-7F4SZXI2.js";i();function l(e){return{id:e.id,name:e.name,platform:e.platform,enabled:e.enabled===1,status:e.status,config:JSON.parse(e.config),linkedRoleId:e.linked_role_id??void 0,allowedChatIds:e.allowed_chat_ids?JSON.parse(e.allowed_chat_ids):void 0,createdAt:e.created_at,updatedAt:e.updated_at??void 0,lastMessageAt:e.last_message_at??void 0,messageCount:e.message_count}}function o(e){s().prepare(`
2
2
  INSERT INTO channels (id, name, platform, enabled, status, config, linked_role_id,
3
3
  allowed_chat_ids, created_at, updated_at, last_message_at, message_count)
4
4
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
@@ -0,0 +1,50 @@
1
+ import{d as H}from"./chunk-TTP7QRAQ.js";import{p as O}from"./chunk-LV4XLPCD.js";import{b as R}from"./chunk-UQDC3X6O.js";import{e as E}from"./chunk-XIQVXRZH.js";import{i as M,j as J,q as P}from"./chunk-YKMWAVUH.js";import{b as _}from"./chunk-OY2KVSIX.js";import{a as f}from"./chunk-L7JP7DUO.js";import{c as A,d as m,e as S,f as w,h as D}from"./chunk-VPZSOYE5.js";import{d as v}from"./chunk-5AUQIK3Q.js";import{o as C,r as q}from"./chunk-YWUX3ZTO.js";import{c as T,h as b}from"./chunk-MRTJFYPR.js";b();q();import{v4 as h}from"uuid";import{CronExpressionParser as Q}from"cron-parser";b();import{v4 as N}from"uuid";var u=T("scheduler"),V=new E,I=new Map;async function X(o){if(I.has(o.id))throw u.warn({templateId:o.id},"Feature-mining dispatch already in flight"),new Error("already in flight");let e=K(o);I.set(o.id,e);try{return await e}finally{I.delete(o.id)}}async function K(o){let e=o.config??{},t=e.last_run_at??null,s=e.max_sessions??15,r=e.max_messages_per_session??30,n=e.message_char_cap??500,c=Math.min(s,50),i=Math.min(r,100),l=Math.min(n,2e3);(c!==s||i!==r||l!==n)&&u.warn({templateId:o.id,rawMaxSessions:s,rawMaxMessages:r,rawCharCap:n,maxSessions:c,maxMessagesPerSession:i,messageCharCap:l},"Feature-mining caps clamped to hard ceilings (50/100/2000)");let x=H(void 0,c,0).filter(g=>t===null||g.lastActiveAt>t),y=[];for(let g of x){let U=R(g.id,i,0);for(let p of U){let z=p.content.length>l?p.content.slice(0,l)+" [...truncated]":p.content;y.push(`[${new Date(p.createdAt).toLocaleString()}] ${p.role}: ${z}`)}}let B=y.length>0?y.join(`
2
+ `):"No new sessions.",G=t?new Date(t).toLocaleString():"the beginning of recorded history",F=o.steps.map(g=>({...g,prompt:g.prompt.replace(/\{\{CHAT_DATA\}\}/g,B).replace(/\{\{LAST_RUN_AT_HUMAN\}\}/g,G)})),L={...o,steps:F};return u.info({templateId:o.id,sessionCount:x.length,lastRunAt:t},"Feature-mining template rendered"),L}async function W(o,e={}){let t=e.executionId??N();if(u.info({templateName:o.name,executionId:t,trigger:e.triggerContext},"Dispatching template"),o.goalIds&&o.goalIds.length>0){for(let c of o.goalIds){let i=J(c);if(!i){u.warn({goalId:c,templateId:o.id},"Goal reference not found, skipping");continue}let l=N();M({id:l,name:i.name,description:i.description,roleId:i.roleId,metricType:i.metricType,targetValue:i.targetValue,currentValue:0,deadline:i.deadline,budgetUsd:i.budgetUsd,status:"active",createdAt:Date.now(),sourceSessionId:o.sourceSessionId,deliverTo:o.deliverTo,reportTo:o.reportTo});let d=await P({prompt:`Decompose and execute goal: ${i.name}. ${i.description??""}`,roleId:o.rolePreference??i.roleId,config:{...v()},deliverTo:o.deliverTo,reportTo:o.reportTo,sourceSessionId:o.sourceSessionId,parentId:l,templateId:o.id});if(!d.ok){u.error({templateId:o.id,sourceGoalId:c,newGoalId:l,code:d.code,reason:d.reason},"Decomposition task admission failed");continue}u.info({templateId:o.id,sourceGoalId:c,newGoalId:l,taskId:d.taskId},"Goal reference triggered, dispatched decomposition task")}return}let s=o,r=null;if(o.presetId==="feature-mining")try{s=await X(o),r=Date.now()}catch(c){if(c.message==="already in flight"){u.warn({templateId:o.id},"Skipping feature-mining dispatch \u2014 already in flight");return}throw c}let n=await V.execute(s,t,{eventId:e.triggerContext?.eventId});if(o.presetId==="feature-mining"&&r!==null)if(n.status==="completed"||n.status==="partial")try{S(o.id,{config:{...o.config??{},last_run_at:r}}),u.info({templateId:o.id,last_run_at:r},"Feature-mining last_run_at updated")}catch(c){u.error({templateId:o.id,err:c},"Failed to write back feature-mining last_run_at")}else u.warn({templateId:o.id,status:n.status},"Feature-mining execute did not succeed; last_run_at preserved for retry");u.info({templateName:o.name,executionId:t,status:n.status,steps:n.stepResults.size},"Workflow execution finished")}var a=T("scheduler"),k="ai-hourly-digest";function Y(){if(m(k)){a.debug({templateId:k},"Built-in template already exists");return}let e={id:k,name:"AI Hourly Digest",description:"\u6BCF\u5C0F\u65F6\u641C\u7D22 AI \u524D\u6CBF\u6587\u7AE0\uFF0C\u603B\u7ED3\u540E\u4FDD\u5B58\u5230 Omnifocus",trigger:{type:"cron",cron:"0 * * * *"},enabled:!0,steps:[{id:"search_ai_news",autoSelectRole:!0,requirements:{},prompt:`\u641C\u7D22\u8FC7\u53BB 24 \u5C0F\u65F6\u5185\u5173\u4E8E AI/\u4EBA\u5DE5\u667A\u80FD\u7684\u6700\u65B0\u524D\u6CBF\u6587\u7AE0\u3002
3
+
4
+ \u641C\u7D22\u6765\u6E90:
5
+ 1. Hacker News AI \u677F\u5757 (https://news.ycombinator.com/front?day=1)
6
+ 2. ArXiv cs.AI \u6700\u65B0\u8BBA\u6587 (https://arxiv.org/list/cs.AI/recent)
7
+ 3. Reddit r/MachineLearning \u70ED\u95E8\u5E16\u5B50
8
+
9
+ \u627E\u51FA\u4E00\u7BC7\u6700\u6709\u4EF7\u503C\u3001\u6700\u6709\u6280\u672F\u6DF1\u5EA6\u7684\u6587\u7AE0\u3002
10
+
11
+ \u8F93\u51FA\u683C\u5F0F:
12
+ - \u6807\u9898\uFF1A[\u6587\u7AE0\u6807\u9898]
13
+ - \u6765\u6E90\uFF1A[\u7F51\u7AD9/\u5E73\u53F0\u540D\u79F0]
14
+ - \u94FE\u63A5\uFF1A[\u5B8C\u6574 URL]
15
+ - \u6838\u5FC3\u4EF7\u503C\uFF1A[1-2 \u53E5\u8BDD\u8BF4\u660E\u4E3A\u4EC0\u4E48\u8FD9\u7BC7\u6587\u7AE0\u503C\u5F97\u770B]`},{id:"summarize_article",dependsOn:["search_ai_news"],autoSelectRole:!0,requirements:{},prompt:`\u9605\u8BFB\u5E76\u603B\u7ED3\u8FD9\u7BC7\u6587\u7AE0\u3002
16
+
17
+ \u6587\u7AE0\u4FE1\u606F:
18
+ {{search_ai_news.result}}
19
+
20
+ \u8BF7:
21
+ 1. \u7528 WebFetch \u83B7\u53D6\u6587\u7AE0\u5B8C\u6574\u5185\u5BB9
22
+ 2. \u63D0\u53D6\u6838\u5FC3\u89C2\u70B9\u548C\u6280\u672F\u7EC6\u8282
23
+ 3. \u7528\u4E2D\u6587\u5199\u51FA 300-500 \u5B57\u7684\u603B\u7ED3
24
+
25
+ \u603B\u7ED3\u7ED3\u6784:
26
+ ## \u6838\u5FC3\u53D1\u73B0
27
+ [\u6587\u7AE0\u6700\u91CD\u8981\u7684\u53D1\u73B0/\u521B\u65B0\u70B9]
28
+
29
+ ## \u6280\u672F\u7EC6\u8282
30
+ [\u5173\u952E\u7684\u6280\u672F\u65B9\u6CD5/\u5B9E\u73B0\u7EC6\u8282]
31
+
32
+ ## \u5F71\u54CD/\u610F\u4E49
33
+ [\u8FD9\u9879\u5DE5\u4F5C\u7684\u610F\u4E49\u6216\u5BF9\u884C\u4E1A\u7684\u5F71\u54CD]
34
+
35
+ ## \u539F\u6587\u94FE\u63A5
36
+ [\u6587\u7AE0 URL]`},{id:"save_to_omnifocus",dependsOn:["summarize_article"],autoSelectRole:!0,requirements:{},prompt:`\u5C06\u6587\u7AE0\u603B\u7ED3\u4FDD\u5B58\u5230 Omnifocus\u3002
37
+
38
+ \u603B\u7ED3\u5185\u5BB9:
39
+ {{summarize_article.result}}
40
+
41
+ \u63D0\u53D6\u6587\u7AE0\u6807\u9898\u548C\u5B8C\u6574\u603B\u7ED3\uFF0C\u7136\u540E\u6267\u884C\u4EE5\u4E0B\u547D\u4EE4\u6DFB\u52A0\u5230 Omnifocus Inbox\uFF1A
42
+
43
+ osascript /Users/norvyn/Code/Projects/Adam/scripts/add-to-omnifocus.applescript "[\u6587\u7AE0\u6807\u9898] AI \u524D\u6CBF\u901F\u9012" "[\u5B8C\u6574\u603B\u7ED3\u5185\u5BB9]"
44
+
45
+ \u6CE8\u610F\uFF1A
46
+ - \u5C06 [\u6587\u7AE0\u6807\u9898] \u66FF\u6362\u4E3A\u5B9E\u9645\u6807\u9898
47
+ - \u5C06 [\u5B8C\u6574\u603B\u7ED3\u5185\u5BB9] \u66FF\u6362\u4E3A\u5B8C\u6574\u7684\u603B\u7ED3\u6587\u672C\uFF08\u5305\u542B\u6838\u5FC3\u53D1\u73B0\u3001\u6280\u672F\u7EC6\u8282\u3001\u5F71\u54CD/\u610F\u4E49\u548C\u539F\u6587\u94FE\u63A5\uFF09
48
+ - \u603B\u7ED3\u5185\u5BB9\u4F7F\u7528\u6362\u884C\u7B26\u5206\u9694\u5404\u90E8\u5206
49
+
50
+ \u5B8C\u6210\u540E\u8F93\u51FA\uFF1A\u5DF2\u4FDD\u5B58\u5230 Omnifocus\uFF1A[\u4EFB\u52A1\u6807\u9898]`}],config:{timeout:300},tags:["ai","digest","hourly","automation"],createdAt:Date.now()};A(e),a.info({templateId:k,cron:"0 * * * *"},"Registered built-in AI Hourly Digest template")}var $=class{cronJobs=new Map;started=!1;taskCompletionHandler=null;workflowCompletionHandler=null;async start(){if(this.started)return;this.started=!0,Y();let e=w(!0),t=0;for(let r of e)r.trigger.type==="cron"&&r.trigger.cron&&(this.scheduleCronJob(r),t++);let s=0;for(let r of e)r.trigger.type==="once"&&r.trigger.runAt&&(this.scheduleOnceJob(r.id),s++);this.taskCompletionHandler=r=>{r.newStatus==="completed"&&this.checkTemplateCompleteTriggers(r.taskId).catch(n=>{a.error({taskId:r.taskId,error:n},"Template-complete trigger check failed")})},f.on("task_status_change",this.taskCompletionHandler),this.workflowCompletionHandler=r=>{(r.status==="completed"||r.status==="partial")&&this.checkWorkflowCompleteTriggers(r.templateId).catch(n=>{a.error({templateId:r.templateId,error:n},"Workflow-complete trigger check failed")})},f.on("workflow_status_change",this.workflowCompletionHandler),this.cronJobs.set("memory-cleanup",setInterval(()=>{this.runMemoryCleanup()},36e5)),a.info({cronCount:t,onceCount:s},"Bree engine started with cron jobs + memory cleanup")}runMemoryCleanup(){try{let e=C(void 0,1e3,0),t=0;for(let s of e)t+=O(s.id);t>0&&a.info({totalCleaned:t},"Memory cleanup completed")}catch(e){a.warn({error:e},"Memory cleanup failed")}}async stop(){for(let[,e]of this.cronJobs)clearTimeout(e),clearInterval(e);this.cronJobs.clear(),this.taskCompletionHandler&&(f.off("task_status_change",this.taskCompletionHandler),this.taskCompletionHandler=null),this.workflowCompletionHandler&&(f.off("workflow_status_change",this.workflowCompletionHandler),this.workflowCompletionHandler=null),this.started=!1,a.info("Bree engine stopped")}scheduleCronJob(e){let t=`template-${e.id}`;this.cronJobs.has(t)&&(clearTimeout(this.cronJobs.get(t)),this.cronJobs.delete(t));let s;try{s=Q.parse(e.trigger.cron)}catch{a.warn({templateId:e.id,cron:e.trigger.cron},"Invalid cron expression");return}let r=()=>{let d=s.next().getTime()-Date.now();return Math.max(d,1e3)},n=()=>{this.executeCronTrigger(e.id).catch(d=>{a.error({templateId:e.id,error:d},"Cron trigger failed")});let l=setTimeout(n,r());this.cronJobs.set(t,l)},c=r(),i=setTimeout(n,c);this.cronJobs.set(t,i),a.debug({jobName:t,nextRun:new Date(Date.now()+c).toISOString()},"Scheduled cron job")}async executeCronTrigger(e){let t=m(e);!t||!t.enabled||(a.info({templateName:t.name},"Cron triggered"),await this.executeWorkflow(t,h()))}async scheduleJob(e){let t=m(e);t&&t.trigger.type==="cron"&&t.trigger.cron&&this.scheduleCronJob(t)}async unscheduleJob(e){let t=`template-${e}`,s=this.cronJobs.get(t);s&&(clearTimeout(s),this.cronJobs.delete(t))}async runNow(e){let t=m(e);if(!t)throw new Error(`Template ${e} not found`);let s=h();return this.executeWorkflow(t,s).catch(r=>{a.error({templateId:e,error:r},"Workflow execution failed")}),s}async checkTemplateCompleteTriggers(e){let t=_(e);if(!t||!t.templateId)return;let r=w(!0).filter(n=>n.trigger.type!=="template_complete"||!n.trigger.event?!1:n.trigger.event===`template_complete:${t.templateId}`);for(let n of r)a.info({templateName:n.name,sourceTemplateId:t.templateId},"Template-complete trigger matched"),await this.executeWorkflow(n,h())}async executeWorkflow(e,t){await W(e,{executionId:t,triggerContext:{source:"bree"}})}async checkWorkflowCompleteTriggers(e){let s=w(!0).filter(r=>r.trigger.type!=="workflow_complete"||!r.trigger.event?!1:r.trigger.event===`workflow_complete:${e}`);for(let r of s)a.info({templateName:r.name,sourceTemplateId:e},"Workflow-complete trigger matched"),await this.executeWorkflow(r,h())}scheduleOnceJob(e){let t=m(e);if(!t||!t.enabled||t.trigger.type!=="once")return;let r=(t.trigger.runAt?new Date(t.trigger.runAt).getTime():0)-Date.now();if(r<=0){a.info({templateId:e,runAt:t.trigger.runAt},"Once-shot template past due, executing immediately"),this.executeOnceTrigger(e).catch(i=>{a.error({templateId:e,error:i},"Once trigger execution failed")});return}let n=`template-${e}`;this.cronJobs.has(n)&&clearTimeout(this.cronJobs.get(n));let c=setTimeout(()=>{this.cronJobs.delete(n),this.executeOnceTrigger(e).catch(i=>{a.error({templateId:e,error:i},"Once trigger execution failed")})},r);this.cronJobs.set(n,c),a.info({templateId:e,runAt:t.trigger.runAt,delayMs:r},"Scheduled once-shot job")}async executeOnceTrigger(e){let t=m(e);!t||!t.enabled||(a.info({templateName:t.name},"Once-shot triggered"),await this.executeWorkflow(t,h()),D(e),a.info({templateId:e},"Once-shot template auto-disabled after execution"))}},j=null;function ke(){return j}function ye(o){j=o}export{W as a,$ as b,ke as c,ye as d};