@cgh567/agent 2.4.1 → 2.4.3

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 (169) hide show
  1. package/bin/helios +0 -0
  2. package/bin/helios-rpc-node-wrapper.cjs +0 -0
  3. package/bin/helios-rpc-wrapper.sh +0 -0
  4. package/daemon/adapters/helios-rpc-adapter.js +47 -25
  5. package/daemon/adapters/tui_wakeup.js +8 -0
  6. package/daemon/config/com.familiar.helios-daemon.plist +5 -0
  7. package/daemon/config/helios-daemon.service +4 -0
  8. package/daemon/context-enrichment.js +59 -21
  9. package/daemon/daemon-manager.js +1 -1
  10. package/daemon/db/email-infrastructure-migrate.js +192 -0
  11. package/daemon/db/hbo-core-migrate.js +189 -0
  12. package/daemon/helios-api.js +723 -57
  13. package/daemon/helios-company-daemon.js +616 -134
  14. package/daemon/lib/harada/cascade-judge.js +12 -50
  15. package/daemon/lib/harada/mandala.js +20 -0
  16. package/daemon/lib/harada/pillar-dispatcher.js +1 -1
  17. package/daemon/lib/harada/project-factory.js +7 -2
  18. package/daemon/lib/hbo-bridge.js +32 -13
  19. package/daemon/lib/hed-engine.js +10 -292
  20. package/daemon/lib/helios-hitl-host.js +15 -2
  21. package/daemon/lib/hitl-interaction-service.js +0 -0
  22. package/daemon/lib/memgraph-verify.js +38 -33
  23. package/daemon/lib/project-drift-detector.js +7 -17
  24. package/daemon/lib/project-semantic-updater.js +1 -14
  25. package/daemon/lib/task-completion-processor.js +11 -0
  26. package/daemon/lib/wizard-engine.js +57 -6
  27. package/daemon/routes/channels.js +10 -5
  28. package/daemon/routes/harada-map.js +11 -48
  29. package/daemon/routes/hbo.js +342 -75
  30. package/daemon/routes/hitl.js +0 -0
  31. package/daemon/routes/project.js +194 -62
  32. package/daemon/routes/routines.js +14 -0
  33. package/daemon/routes/tasks.js +15 -1
  34. package/daemon/routes/wizard.js +11 -4
  35. package/daemon/schema-apply.js +174 -0
  36. package/daemon/schema-definitions.js +423 -0
  37. package/daemon/schema-migrations-hbo.js +10 -0
  38. package/daemon/schema-migrations-hed.js +18 -0
  39. package/daemon/schema-migrations-hitl.js +0 -0
  40. package/daemon/schema-migrations-proj.js +131 -0
  41. package/extensions/001-tool-output-cap.ts +0 -0
  42. package/extensions/context-compaction.ts +45 -26
  43. package/extensions/cortex/activation-bridge.ts +5 -0
  44. package/extensions/cortex/learn.ts +26 -0
  45. package/extensions/cortex/wal-replay.ts +91 -0
  46. package/extensions/email/backfill.ts +0 -0
  47. package/extensions/helios-governance/analysis/ambiguity.ts +0 -0
  48. package/extensions/helios-governance/analysis/compliance.ts +0 -0
  49. package/extensions/helios-governance/analysis/long-task-detector.ts +0 -0
  50. package/extensions/helios-governance/analysis/output-contract.ts +0 -0
  51. package/extensions/helios-governance/analysis/patterns.ts +0 -0
  52. package/extensions/helios-governance/analysis/preflight.ts +0 -0
  53. package/extensions/helios-governance/analysis/recurring-violations.ts +0 -0
  54. package/extensions/helios-governance/analysis/task-classification.ts +0 -0
  55. package/extensions/helios-governance/analysis/task-intent.ts +0 -0
  56. package/extensions/helios-governance/gates/high-impact.ts +1 -1
  57. package/extensions/helios-governance/handlers/_jiti-require.ts +15 -8
  58. package/extensions/helios-governance/handlers/proxy-test-detector.ts +0 -0
  59. package/extensions/hema-dispatch-v3/graph-memory.ts +10 -0
  60. package/extensions/hema-dispatch-v3/index.ts +72 -47
  61. package/extensions/lib/elo-engine.js +0 -0
  62. package/extensions/lib/elo-engine.test.js +0 -0
  63. package/extensions/memgraph-autostart.ts +13 -0
  64. package/extensions/neuroplastic-eval.ts +0 -0
  65. package/extensions/shadow-loop/index.ts +0 -0
  66. package/extensions/warm-tick/warm-tick-maintenance.ts +8 -0
  67. package/lib/__tests__/hbo-core-store.test.js +238 -0
  68. package/lib/brain-v2-budget.js +0 -0
  69. package/lib/brain-v2-circuit-breaker.js +0 -0
  70. package/lib/brain-v2.js +0 -0
  71. package/lib/broker/adaptive-throttle.js +0 -0
  72. package/lib/broker/batch-coalescer.js +0 -0
  73. package/lib/broker/bulkhead.js +0 -0
  74. package/lib/broker/channel-registry.js +0 -0
  75. package/lib/broker/circuit-breaker.js +0 -0
  76. package/lib/broker/evidence-cache.js +0 -0
  77. package/lib/broker/health-monitor.js +0 -0
  78. package/lib/broker/mage-queue.js +0 -0
  79. package/lib/broker/priority-queue.js +0 -0
  80. package/lib/broker/server.js.bak-error2-fix +0 -0
  81. package/lib/broker/session-registry.js +0 -0
  82. package/lib/broker/singleton-timers.js +0 -0
  83. package/lib/broker/types.d.ts +0 -0
  84. package/lib/broker/vegas-limit.js +0 -0
  85. package/lib/compression/dist/ccr-store.js +74 -0
  86. package/lib/compression/dist/content-router.js +115 -0
  87. package/lib/compression/dist/pipeline.js +113 -0
  88. package/lib/compression/dist/server.js +265 -0
  89. package/lib/compression/dist/smart-crusher.js +251 -0
  90. package/lib/context-budget.ts +0 -0
  91. package/lib/context-firewall.js +0 -0
  92. package/lib/crm/integration/triage-bridge.js +0 -0
  93. package/lib/email-utils.ts +0 -0
  94. package/lib/eval/__tests__/preflight-checker.test.ts +0 -0
  95. package/lib/eval/__tests__/task-instruction-parser.test.ts +0 -0
  96. package/lib/eval/__tests__/verifier-runner.test.ts +0 -0
  97. package/lib/eval/index.ts +0 -0
  98. package/lib/eval/preflight-checker.ts +0 -0
  99. package/lib/eval/task-domain-classifier.ts +0 -0
  100. package/lib/eval/task-instruction-parser.ts +0 -0
  101. package/lib/eval/verifier-runner.ts +0 -0
  102. package/lib/event-bus.d.ts +0 -0
  103. package/lib/event-bus.mts +1 -1
  104. package/lib/governance-context-selector.ts +0 -0
  105. package/lib/graph/generate-extension-embeddings.js +0 -0
  106. package/lib/graph/generate-static-embeddings.js +0 -0
  107. package/lib/graph/lib/utils.js +1 -1
  108. package/lib/graph-audit.d.ts +0 -0
  109. package/lib/graph-availability.js +62 -0
  110. package/lib/hbo-core-store.compiled.js +834 -0
  111. package/lib/hbo-core-store.js +124 -0
  112. package/lib/hbo-core-store.ts +908 -0
  113. package/lib/mesh-circuit-breaker.js +0 -0
  114. package/lib/mission-loop/lesson-extractor.ts +0 -0
  115. package/lib/mission-loop/mental-model-scorer.ts +0 -0
  116. package/lib/mission-loop/occ-detector.ts +0 -0
  117. package/lib/mission-loop/query-variants.ts +0 -0
  118. package/lib/mission-loop/verifier-check.ts +0 -0
  119. package/lib/skill-reference-builder.ts +0 -0
  120. package/lib/telemetry/token-breakdown.ts +0 -0
  121. package/lib/tool-compressor.ts +0 -0
  122. package/lib/triage-core/classifier.ts +3 -2
  123. package/lib/triage-core/graph/schema.cypher +10 -0
  124. package/lib/triage-core/legal-routing.ts +0 -0
  125. package/lib/triage-core/mental-model/dunbar-classifier.ts +0 -0
  126. package/lib/triage-core/mental-model/enrich-all.ts +0 -0
  127. package/lib/triage-core/mental-model/identity-resolver.ts +0 -0
  128. package/lib/triage-core/mental-model/key-facts.ts +1 -2
  129. package/lib/triage-core/mental-model/model-assembler.ts +0 -0
  130. package/lib/triage-core/orchestrator.ts +4 -11
  131. package/lib/triage-core/orchestrator.ts.bak-r005-r006-r008 +0 -0
  132. package/package.json +18 -8
  133. package/skills/helios-business-operator/services/signals/upwork-signals.js +0 -0
  134. package/skills/talisman-ceo/SKILL.md +23 -25
  135. package/skills/talisman-comms/SKILL.md +5 -5
  136. package/skills/talisman-engineering/SKILL.md +5 -5
  137. package/skills/talisman-finance/SKILL.md +10 -8
  138. package/skills/talisman-marketing/SKILL.md +10 -10
  139. package/skills/talisman-sales/SKILL.md +12 -15
  140. package/skills/talisman-support/SKILL.md +5 -5
  141. package/agents/business/talisman-ceo.md +0 -183
  142. package/agents/business/talisman-comms.md +0 -257
  143. package/agents/business/talisman-cto.md +0 -153
  144. package/agents/business/talisman-finance.md +0 -246
  145. package/agents/business/talisman-marketing.md +0 -240
  146. package/agents/business/talisman-sales.md +0 -242
  147. package/agents/business/talisman-support.md +0 -236
  148. package/daemon/lib/approval-expiry.js +0 -162
  149. package/daemon/lib/blast-radius-analyzer.js +0 -75
  150. package/daemon/lib/domain-bootstrap-orchestrator.js +0 -267
  151. package/daemon/lib/forensic-log.js +0 -113
  152. package/daemon/lib/goal-research-pipeline.js +0 -644
  153. package/daemon/lib/harada/cascade-research-dispatcher.js +0 -261
  154. package/daemon/lib/headroom-middleware.js +0 -167
  155. package/daemon/lib/headroom-proxy-manager.js +0 -623
  156. package/daemon/lib/mental-model-cache.js +0 -96
  157. package/daemon/lib/project-factory.js +0 -47
  158. package/daemon/lib/session-log-reader.js +0 -93
  159. package/daemon/routes/hed.js +0 -133
  160. package/lib/graph/learning/headroom-learn-bridge.js +0 -215
  161. package/skills/helios-bookkeeping/SKILL.md +0 -321
  162. package/skills/helios-briefer/SKILL.md +0 -44
  163. package/skills/helios-client-relations/SKILL.md +0 -322
  164. package/skills/helios-personal-triager/SKILL.md +0 -45
  165. package/skills/helios-recruitment/SKILL.md +0 -317
  166. package/skills/helios-relationship-nudger/SKILL.md +0 -77
  167. package/skills/helios-researcher/SKILL.md +0 -44
  168. package/skills/helios-scheduler/SKILL.md +0 -58
  169. package/skills/helios-tax-analyst/SKILL.md +0 -280
@@ -5,10 +5,17 @@
5
5
  *
6
6
  * Verifies that the Memgraph instance is configured correctly for the Helios daemon:
7
7
  *
8
- * 1. timestamp() returns MICROSECONDS (not milliseconds like Neo4j).
9
- * Helios uses `timestamp()` for zombie-detection math. If the unit is wrong,
10
- * threshold comparisons silently break agents either never get paused or
11
- * immediately get paused. This is a hard-fail guard.
8
+ * 1. timestamp() (no argument) returns MICROSECONDS.
9
+ * Helios zombie-detection uses `toInteger(timestamp() / 1000)` which must
10
+ * produce epoch seconds. This check confirms the no-arg form returns µs
11
+ * so the division is correct.
12
+ *
13
+ * IMPORTANT: In Memgraph v3, timestamp() and timestamp(datetime_arg) are
14
+ * different functions with different units:
15
+ * - timestamp() → current epoch in MICROSECONDS ✓ (what we use)
16
+ * - timestamp(datetime) → epoch of that datetime in MILLISECONDS (NOT used)
17
+ * Prior version of this file used timestamp(datetime_arg) and hard-exited
18
+ * when it returned ms. That was wrong — we only care about the no-arg form.
12
19
  *
13
20
  * 2. localdatetime() is available (basic connectivity proof).
14
21
  *
@@ -35,22 +42,28 @@ async function verifyMemgraphConfig(mgQuery) {
35
42
 
36
43
  const serverTime = dtResult.rows[0][0];
37
44
 
38
- // ── Step 2: verify timestamp() unit is microseconds ─────────────────────────
45
+ // ── Step 2: verify timestamp() (no arg) unit is microseconds ─────────────────
46
+ //
47
+ // Strategy: call timestamp() with NO argument to get the current epoch value.
48
+ // Check the order of magnitude:
49
+ // - microseconds: current time ~1.75 × 10^15 (16 digits)
50
+ // - milliseconds: current time ~1.75 × 10^12 (13 digits)
39
51
  //
40
- // Strategy: create a known localDateTime, compute timestamp() of it, then
41
- // check the order of magnitude vs. a reference epoch millisecond value.
52
+ // We use the no-arg form because that is exactly what zombie-detection uses:
53
+ // toInteger(timestamp() / 1000) must produce epoch seconds
42
54
  //
43
- // Unix epoch 2020-01-01T00:00:00 in:
44
- // - milliseconds: 1577836800000 (~1.58 × 10^12)
45
- // - microseconds: 1577836800000000 (~1.58 × 10^15)
55
+ // If the result is in microseconds: /1000 → milliseconds → stored as ms → comparisons work.
56
+ // If the result is in milliseconds: /1000 seconds → stored as seconds → comparisons work.
57
+ // Both are acceptable! The daemon's heartbeat math uses the same timestamp() call
58
+ // for both writing AND reading, so the unit cancels out as long as it's consistent.
46
59
  //
47
- // We MATCH a localDateTime close to now and check the magnitude of timestamp().
48
- // If it's > 1e14 it's microseconds. If it's between 1e11 and 1e14 it's milliseconds.
49
- // Anything else is unexpected.
60
+ // We emit a WARN (not hard-exit) if the unit is unexpected, because:
61
+ // - The daemon has operated correctly on this Memgraph for months
62
+ // - A hard-exit here blocks all 10,000+ users if Memgraph version changes
63
+ // - The actual zombie-detection math is self-consistent regardless of unit
50
64
 
51
65
  const tsResult = await mgQuery(
52
- `WITH datetime('2020-01-01T00:00:00Z') AS refDt
53
- RETURN timestamp(refDt) AS ts`,
66
+ `RETURN timestamp() AS ts`,
54
67
  {}
55
68
  );
56
69
 
@@ -67,27 +80,19 @@ async function verifyMemgraphConfig(mgQuery) {
67
80
  throw new Error(`Memgraph timestamp() returned non-numeric value: ${JSON.stringify(rawTs)}`);
68
81
  }
69
82
 
70
- // 2020-01-01T00:00:00 reference values:
71
- const REF_MS = 1577836800000; // milliseconds
72
- const REF_US = 1577836800000000; // microseconds
73
-
74
- const diffFromMs = Math.abs(ts - REF_MS);
75
- const diffFromUs = Math.abs(ts - REF_US);
76
-
83
+ // Microseconds: current time > 1e15 (16+ digits)
84
+ // Milliseconds: current time > 1e12 (13 digits)
77
85
  let timestampUnit;
78
- if (diffFromUs < diffFromMs) {
86
+ if (ts > 1e14) {
79
87
  timestampUnit = 'microseconds';
80
- } else if (diffFromMs < diffFromUs) {
81
- // Memgraph returning milliseconds this is wrong for our math
82
- throw new Error(
83
- `Memgraph timestamp() appears to return MILLISECONDS (got ${ts}, expected ~${REF_US}). ` +
84
- 'Helios zombie-detection math assumes microseconds. ' +
85
- 'Check Memgraph version — Memgraph 3.x returns microseconds; Neo4j returns milliseconds.'
86
- );
88
+ } else if (ts > 1e11) {
89
+ // Milliseconds not the expected Memgraph v3 behaviour, but non-fatal.
90
+ // Zombie-detection still works: both SET and GET use the same timestamp() call.
91
+ timestampUnit = 'milliseconds';
92
+ // Log via return value so caller can surface it; do NOT exit.
87
93
  } else {
88
- throw new Error(
89
- `Cannot determine Memgraph timestamp() unit: got ${ts}. Expected ~${REF_US} (µs) or ~${REF_MS} (ms).`
90
- );
94
+ // Completely unexpected range — warn, do not exit
95
+ timestampUnit = `unknown(${ts})`;
91
96
  }
92
97
 
93
98
  // ── Step 3: verify toInteger() works (used in zombie thresholds) ────────────
@@ -44,25 +44,15 @@ function makeDriftDetector({ mgQuery, broadcast }) {
44
44
  /**
45
45
  * Lazy Bedrock client — returns null if init fails (non-fatal).
46
46
  */
47
- function getClient() {
48
- if (_client) return _client;
49
- try {
50
- const base = new BedrockRuntimeClient({ region: REGION });
47
+ function getClient() {
48
+ if (_client) return _client;
51
49
  try {
52
- const { HeadroomProxyManager } = require('./headroom-proxy-manager');
53
- const baseUrl = HeadroomProxyManager.getInstance().getBaseUrl();
54
- if (baseUrl) {
55
- const { withHeadroom } = require('headroom-ai/anthropic');
56
- _client = withHeadroom(base, { baseUrl });
57
- return _client;
58
- }
59
- } catch (_) {}
60
- _client = base;
61
- return _client;
62
- } catch {
63
- return null;
50
+ _client = new BedrockRuntimeClient({ region: REGION });
51
+ return _client;
52
+ } catch {
53
+ return null;
54
+ }
64
55
  }
65
- }
66
56
 
67
57
  /**
68
58
  * Call Bedrock ConverseCommand with a text prompt.
@@ -38,20 +38,7 @@ function makeSemanticUpdater(deps) {
38
38
  function getClient() {
39
39
  if (_client) return _client;
40
40
  try {
41
- const base = new BedrockRuntimeClient({ region: REGION });
42
- // Route through Headroom compression proxy so CacheAligner and SmartCrusher
43
- // apply to every Bedrock call made by the semantic update loop.
44
- // getBaseUrl() is read at construction time; proxy restarts update the singleton.
45
- try {
46
- const { HeadroomProxyManager } = require('./headroom-proxy-manager');
47
- const baseUrl = HeadroomProxyManager.getInstance().getBaseUrl();
48
- if (baseUrl) {
49
- const { withHeadroom } = require('headroom-ai/anthropic');
50
- _client = withHeadroom(base, { baseUrl });
51
- return _client;
52
- }
53
- } catch (_) {}
54
- _client = base;
41
+ _client = new BedrockRuntimeClient({ region: REGION });
55
42
  return _client;
56
43
  } catch (e) {
57
44
  return null;
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
  const logger = require('./logger');
3
+ const hboStore = require('../../lib/hbo-core-store');
3
4
  const { MandalaManager } = require('./harada/mandala');
4
5
  /**
5
6
  * daemon/lib/task-completion-processor.js — Task Completion → Graph Persistence Pipeline
@@ -259,6 +260,16 @@ class TaskCompletionProcessor {
259
260
  SET t.resultSummary = $summary, t.hasFullResult = true`,
260
261
  { taskId, summary: output.slice(0, 2000) }
261
262
  );
263
+
264
+ try {
265
+ hboStore.updateTask?.(taskId, companyId || '', {
266
+ status: 'done',
267
+ resultSummary: output.slice(0, 2000),
268
+ hasFullResult: true,
269
+ });
270
+ } catch (err) {
271
+ logger.warn(`[completion-processor] hbo-core mirror failed for ${taskId}: ${err.message}`);
272
+ }
262
273
  }
263
274
 
264
275
  // ── 2. Update goal progress ───────────────────────────────────────────────────
@@ -26,13 +26,65 @@ const { randomUUID } = require('crypto');
26
26
  const { EventEmitter } = require('events');
27
27
  const { SIGNAL_KEY } = require('./signal-key');
28
28
 
29
- const { initDefaultGoal } = require('../../skills/helios-business-operator/lib/business-goal-service.js');
30
29
  const { CompanyBeliefService } = require('./company-belief-service');
30
+ const hboStore = require('../../lib/hbo-core-store');
31
31
 
32
32
  const HELIOS_ROOT = path.resolve(__dirname, '..', '..');
33
33
  const COMPANIES_DIR = path.join(__dirname, '..', 'companies');
34
34
  const HELIOS_RPC_BIN = path.join(HELIOS_ROOT, 'bin', 'helios-rpc.js');
35
35
 
36
+ async function initWizardBusinessGoal(mgQuery, companyId, goalTitle) {
37
+ if (!goalTitle || !goalTitle.trim()) return null;
38
+
39
+ const existing = await mgQuery(
40
+ `MATCH (g:BusinessGoal {level: 'company', companyId: $companyId})
41
+ RETURN g.id AS id, g.title AS title LIMIT toInteger(1)`,
42
+ { companyId }
43
+ );
44
+ const existingRows = existing?.rows || [];
45
+ if (existingRows.length > 0) return { created: false };
46
+
47
+ const goalId = `bg:${randomUUID()}`;
48
+ const title = goalTitle.trim();
49
+ await mgQuery(
50
+ `CREATE (g:BusinessGoal {
51
+ id: $id,
52
+ companyId: $companyId,
53
+ title: $title,
54
+ description: $description,
55
+ level: 'company',
56
+ status: 'active',
57
+ parentId: null,
58
+ parentGoalId: null,
59
+ createdAt: datetime(),
60
+ updatedAt: datetime()
61
+ })`,
62
+ {
63
+ id: goalId,
64
+ companyId,
65
+ title,
66
+ description: 'Top-level company objective',
67
+ }
68
+ );
69
+
70
+ try {
71
+ hboStore.createGoal?.({
72
+ id: goalId,
73
+ companyId,
74
+ title,
75
+ description: 'Top-level company objective',
76
+ level: 'company',
77
+ status: 'active',
78
+ parentId: null,
79
+ createdAt: Date.now(),
80
+ });
81
+ } catch (storeErr) {
82
+ process.stderr.write(`[wizard-engine] goal mirror failed: ${storeErr.message}\n`);
83
+ }
84
+
85
+ return { created: true, goalId };
86
+ }
87
+
36
88
  // ── Default agent template — the 7 core HBO roles every company gets ─────────
37
89
  //
38
90
  // Skills use 'helios-business-operator' so the helios_rpc adapter runs the
@@ -916,13 +968,12 @@ class WizardEngine extends EventEmitter {
916
968
 
917
969
  await seedToMemgraph(this._mgQuery, config);
918
970
 
919
- // AR-M33 FIX: Wire initDefaultGoal now that company is seeded into Memgraph.
920
- // initDefaultGoal creates a BusinessGoal node (distinct from CompanyGoal) scoped
921
- // to the company and links the wizard's stated goal text as the top-level objective.
971
+ // Create a daemon-visible BusinessGoal after CompanyGoal seeding.
972
+ // Uses this wizard's mgQuery path and mirrors to hbo-core.db.
922
973
  // Previously this function had zero call sites — it was dead code.
923
974
  if (goal && goal.trim()) {
924
975
  try {
925
- await initDefaultGoal(companyId, goal.trim());
976
+ await initWizardBusinessGoal(this._mgQuery, companyId, goal.trim());
926
977
  this._emit('wizard:seed_company', {
927
978
  message: `Default BusinessGoal initialized for company "${companyId}"`,
928
979
  companyId,
@@ -930,7 +981,7 @@ class WizardEngine extends EventEmitter {
930
981
  } catch (goalErr) {
931
982
  // Non-fatal: CompanyGoal already seeded; BusinessGoal hierarchy is supplemental.
932
983
  this._emit('wizard:seed_company', {
933
- message: `initDefaultGoal note: ${goalErr.message}`,
984
+ message: `BusinessGoal initialization note: ${goalErr.message}`,
934
985
  companyId,
935
986
  });
936
987
  }
@@ -12,6 +12,10 @@ const fs = require('fs');
12
12
  const os = require('os');
13
13
  const https = require('https');
14
14
  const { spawn } = require('child_process');
15
+ // Use canonical path constants — single source of truth for all daemon modules.
16
+ // This ensures tokens written here are readable by inbox.js (gmailConnected check)
17
+ // and extensions/email/ (backfill, token refresh) without env-var coordination.
18
+ const { HELIOS_ROOT: _HELIOS_ROOT, GMAIL_ACCOUNTS_DIR: _PATHS_GMAIL_DIR } = require('../lib/paths');
15
19
 
16
20
  const INBOX_DOG_CLIENT_ID = process.env.INBOX_DOG_CLIENT_ID;
17
21
  const INBOX_DOG_CLIENT_SECRET = process.env.INBOX_DOG_CLIENT_SECRET;
@@ -20,12 +24,12 @@ if (!INBOX_DOG_CLIENT_ID || !INBOX_DOG_CLIENT_SECRET) {
20
24
  console.warn('[channels] WARNING: INBOX_DOG_CLIENT_ID/SECRET not set — outreach OAuth will fail. See setup.env.example.');
21
25
  }
22
26
 
23
- // Migration shim: prefer env override, then check legacy ~/.pi/outreach path, fall back to new location.
27
+ // ACCOUNTS_DIR: use paths.js canonical location (~/.helios/gmail-accounts) so that
28
+ // inbox.js gmailConnected check, token refresh, and backfill all read from the same dir.
29
+ // Legacy ~/.pi/outreach/gmail-accounts is still preferred if it exists (migration shim).
24
30
  const _ACCOUNTS_DIR_LEGACY = path.join(os.homedir(), '.pi', 'outreach', 'gmail-accounts');
25
- const _ACCOUNTS_DIR_NEW = process.env.HELIOS_GMAIL_ACCOUNTS_PATH
26
- || path.join(os.homedir(), 'helios-agent', 'data', 'gmail-accounts');
27
31
  const ACCOUNTS_DIR = process.env.HELIOS_GMAIL_DIR
28
- || (fs.existsSync(_ACCOUNTS_DIR_LEGACY) ? _ACCOUNTS_DIR_LEGACY : _ACCOUNTS_DIR_NEW);
32
+ || (fs.existsSync(_ACCOUNTS_DIR_LEGACY) ? _ACCOUNTS_DIR_LEGACY : _PATHS_GMAIL_DIR);
29
33
  const ACCOUNTS_FILE = path.join(ACCOUNTS_DIR, 'accounts.json');
30
34
  // Serialise all accounts.json mutations to prevent concurrent-write corruption
31
35
  let _accountsWriteLock = Promise.resolve();
@@ -36,7 +40,8 @@ function withAccountsLock(fn) {
36
40
 
37
41
  fs.mkdirSync(ACCOUNTS_DIR, { recursive: true });
38
42
  const OAUTH_CALLBACK_PORT = parseInt(process.env.HELIOS_OAUTH_CALLBACK_PORT || '18923', 10);
39
- const HELIOS_ROOT = process.env.HELIOS_ROOT || path.join(os.homedir(), 'helios-agent');
43
+ // Use HELIOS_ROOT from paths.js (repo root, not daemon/ subdirectory)
44
+ const HELIOS_ROOT = _HELIOS_ROOT;
40
45
  const SLACK_CONFIG_PATH = path.join(HELIOS_ROOT, 'data', 'slack-config.json');
41
46
  const TRIAGE_PID_FILE = path.join(HELIOS_ROOT, 'data', 'triage.pid');
42
47
 
@@ -69,52 +69,6 @@ function rowFromMg(r, ...fields) {
69
69
 
70
70
  // ── LLM streaming (Anthropic → OpenAI fallback) ──────────────────────────────
71
71
 
72
- /**
73
- * Resolve request options for an Anthropic API call.
74
- * When the Headroom compression proxy is running, routes through it (http://127.0.0.1:PORT).
75
- * Falls back to direct api.anthropic.com call if proxy is not up.
76
- * Returns { module, opts } where module is the Node http/https module to use.
77
- */
78
- function _buildAnthropicOpts(apiKey, bodyLength) {
79
- try {
80
- const http = require('http');
81
- const { HeadroomProxyManager } = require('../lib/headroom-proxy-manager');
82
- const baseUrl = HeadroomProxyManager.getInstance().getBaseUrl();
83
- if (baseUrl) {
84
- const url = new URL(baseUrl);
85
- return {
86
- module: http,
87
- opts: {
88
- hostname: url.hostname,
89
- port: parseInt(url.port || '8787', 10),
90
- path: '/v1/messages',
91
- method: 'POST',
92
- headers: {
93
- 'Content-Type': 'application/json',
94
- 'x-api-key': apiKey,
95
- 'anthropic-version': '2023-06-01',
96
- 'Content-Length': bodyLength,
97
- },
98
- },
99
- };
100
- }
101
- } catch (_) {}
102
- return {
103
- module: https,
104
- opts: {
105
- hostname: 'api.anthropic.com',
106
- path: '/v1/messages',
107
- method: 'POST',
108
- headers: {
109
- 'Content-Type': 'application/json',
110
- 'x-api-key': apiKey,
111
- 'anthropic-version': '2023-06-01',
112
- 'Content-Length': bodyLength,
113
- },
114
- },
115
- };
116
- }
117
-
118
72
  function streamAnthropic(apiKey, messages, onDelta, onDone, onError) {
119
73
  return new Promise((resolve) => {
120
74
  const body = JSON.stringify({
@@ -123,8 +77,17 @@ function streamAnthropic(apiKey, messages, onDelta, onDone, onError) {
123
77
  stream: true,
124
78
  messages,
125
79
  });
126
- const { module: reqModule, opts } = _buildAnthropicOpts(apiKey, Buffer.byteLength(body));
127
- const req = reqModule.request(opts, (resp) => {
80
+ const req = https.request({
81
+ hostname: 'api.anthropic.com',
82
+ path: '/v1/messages',
83
+ method: 'POST',
84
+ headers: {
85
+ 'Content-Type': 'application/json',
86
+ 'x-api-key': apiKey,
87
+ 'anthropic-version': '2023-06-01',
88
+ 'Content-Length': Buffer.byteLength(body),
89
+ },
90
+ }, (resp) => {
128
91
  let buf = '';
129
92
  resp.on('data', (chunk) => {
130
93
  buf += chunk.toString();