@cgh567/agent 2.4.2 → 2.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agents/business/talisman-ceo.md +183 -0
- package/agents/business/talisman-comms.md +257 -0
- package/agents/business/talisman-cto.md +153 -0
- package/agents/business/talisman-finance.md +246 -0
- package/agents/business/talisman-marketing.md +240 -0
- package/agents/business/talisman-sales.md +242 -0
- package/agents/business/talisman-support.md +236 -0
- package/bin/helios-rpc.js +19 -0
- package/daemon/adapters/helios-rpc-adapter.js +5 -12
- package/daemon/adapters/tui_wakeup.js +8 -0
- package/daemon/context-enrichment.js +27 -0
- package/daemon/daemon-manager.js +1 -1
- package/daemon/db/email-infrastructure-migrate.js +192 -0
- package/daemon/db/hbo-core-migrate.js +189 -0
- package/daemon/helios-api.js +863 -64
- package/daemon/helios-company-daemon.js +233 -33
- package/daemon/lib/blast-radius-analyzer.js +75 -0
- package/daemon/lib/domain-bootstrap-orchestrator.js +267 -0
- package/daemon/lib/forensic-log.js +113 -0
- package/daemon/lib/goal-research-pipeline.js +644 -0
- package/daemon/lib/harada/cascade-judge.js +84 -1
- package/daemon/lib/harada/cascade-research-dispatcher.js +282 -0
- package/daemon/lib/harada/pillar-dispatcher.js +23 -2
- package/daemon/lib/hbo-bridge.js +74 -6
- package/daemon/lib/headroom-middleware.js +129 -0
- package/daemon/lib/headroom-proxy-manager.js +309 -0
- package/daemon/lib/hed-engine.js +25 -0
- package/daemon/lib/intelligence/department-page-generator.js +46 -1
- package/daemon/lib/interpretation-engine.js +92 -0
- package/daemon/lib/mental-model-cache.js +96 -0
- package/daemon/lib/project-factory.js +47 -0
- package/daemon/lib/session-log-reader.js +93 -0
- package/daemon/lib/standard-work-bootstrap.js +87 -1
- package/daemon/lib/task-completion-processor.js +23 -0
- package/daemon/lib/wizard-engine.js +57 -6
- package/daemon/package.json +2 -1
- package/daemon/routes/agents.js +51 -6
- package/daemon/routes/channels.js +116 -2
- package/daemon/routes/crm.js +85 -0
- package/daemon/routes/dashboard.js +62 -16
- package/daemon/routes/dept.js +10 -1
- package/daemon/routes/email-triage.js +19 -10
- package/daemon/routes/hbo.js +618 -58
- package/daemon/routes/hed.js +133 -0
- package/daemon/routes/inbox.js +397 -8
- package/daemon/routes/project.js +580 -66
- package/daemon/routes/routines.js +14 -0
- package/daemon/routes/tasks.js +15 -1
- package/daemon/schema-apply.js +174 -0
- package/daemon/schema-definitions.js +433 -0
- package/daemon/schema-migrations-hbo.js +20 -0
- package/daemon/schema-migrations-hed.js +18 -0
- package/daemon/schema-migrations-proj.js +153 -0
- package/extensions/__tests__/codebase-index.test.ts +73 -0
- package/extensions/__tests__/extension-command-registration.test.ts +35 -0
- package/extensions/__tests__/git-push-guard.test.ts +68 -0
- package/extensions/context-compaction.ts +104 -76
- package/extensions/cortex/__tests__/cortex-core.test.ts +100 -0
- package/extensions/cortex/wal-replay.ts +91 -0
- package/extensions/email/actions/draft-response.ts +21 -1
- package/extensions/email/auth/accounts.ts +5 -11
- package/extensions/email/auth/inbox-dog.ts +5 -2
- package/extensions/email/backfill.ts +20 -13
- package/extensions/email/providers/gmail.ts +164 -0
- package/extensions/email/providers/google-calendar.ts +34 -5
- package/extensions/helios-browser/__tests__/browser-routing.test.ts +57 -0
- package/extensions/helios-browser/backends/playwright.ts +3 -1
- package/extensions/helios-governance/__tests__/governance-gates.test.ts +40 -0
- package/extensions/helios-governance/__tests__/tournament-consumer.test.js +66 -0
- package/extensions/hema-dispatch-v3/headroom-compress.ts +103 -0
- package/extensions/hema-dispatch-v3/index.ts +46 -72
- package/extensions/interview/__tests__/server.test.ts +117 -0
- package/extensions/lib/helios-root.cjs +46 -0
- package/extensions/subagent-mesh/__tests__/handlers.test.ts +98 -0
- package/extensions/warm-tick/warm-tick-maintenance.ts +164 -0
- package/lib/__tests__/bulk-ingest.live.test.ts +66 -0
- package/lib/__tests__/crash-fixes.test.ts +49 -0
- package/lib/__tests__/hbo-core-store.test.js +238 -0
- package/lib/__tests__/maintenance-mission-wiring.test.ts +35 -0
- package/lib/broker/__tests__/jit-subscription.test.js +44 -1
- package/lib/broker/__tests__/lifecycle-channels.test.js +25 -1
- package/lib/compression/__tests__/ccr-store.test.js +138 -0
- package/lib/compression/__tests__/pipeline.test.js +280 -0
- package/lib/compression/__tests__/smart-crusher.test.js +242 -0
- package/lib/compression/dist/server.js +34 -1
- package/lib/compression/dist/start-server.js +77 -0
- package/lib/event-bus.mts +1 -1
- package/lib/graph/learning/headroom-learn-bridge.js +175 -0
- package/lib/graph-availability.js +62 -0
- package/lib/hbo-core-store.compiled.js +834 -0
- package/lib/hbo-core-store.js +124 -0
- package/lib/hbo-core-store.ts +979 -0
- package/lib/mission-loop/__tests__/research-handler.test.ts +143 -0
- package/lib/skill-sync.js +6 -1
- package/lib/startup-integrity.js +9 -2
- package/lib/triage-core/__tests__/classifier-fixture.test.ts +254 -0
- package/lib/triage-core/__tests__/classifier-post-norm.test.ts +1 -1
- package/lib/triage-core/__tests__/classifier.test.ts +45 -7
- package/lib/triage-core/__tests__/correction-detector.test.ts +36 -0
- package/lib/triage-core/__tests__/d6-dunbar-boost.test.ts +5 -5
- package/lib/triage-core/__tests__/orchestrator-pipeline.test.ts +107 -0
- package/lib/triage-core/__tests__/orchestrator.test.ts +113 -1
- package/lib/triage-core/__tests__/signals.test.ts +357 -0
- package/lib/triage-core/__tests__/sql-parity.test.ts +216 -0
- package/lib/triage-core/backfill-cost-estimator.ts +91 -0
- package/lib/triage-core/backfill-orchestrator.ts +119 -0
- package/lib/triage-core/classifier.ts +41 -8
- package/lib/triage-core/cos/cross-channel-escalation.ts +2 -3
- package/lib/triage-core/cos/response-debt.ts +2 -2
- package/lib/triage-core/graph/__tests__/batch-persistence.test.ts +283 -0
- package/lib/triage-core/graph/batch-persistence.ts +66 -2
- package/lib/triage-core/graph/betweenness-worker.js +75 -0
- package/lib/triage-core/graph/graph-rank-sql.ts +67 -0
- package/lib/triage-core/graph/persistence.ts +1 -1
- package/lib/triage-core/graph/schema-v2.ts +2 -0
- package/lib/triage-core/graph/schema.cypher +11 -0
- package/lib/triage-core/graph/triage-query.ts +1 -1
- package/lib/triage-core/learning.ts +15 -20
- package/lib/triage-core/mental-model/bedrock-config.ts +78 -0
- package/lib/triage-core/mental-model/cos-integration.ts +1 -1
- package/lib/triage-core/mental-model/entity-extractor.ts +51 -4
- package/lib/triage-core/mental-model/identity-resolver.ts +5 -5
- package/lib/triage-core/mental-model/key-facts.ts +1 -2
- package/lib/triage-core/mental-model/model-assembler-sql.ts +200 -0
- package/lib/triage-core/mental-model/model-assembler.ts +16 -3
- package/lib/triage-core/orchestrator.ts +8 -15
- package/lib/triage-core/scheduled-sends.ts +39 -2
- package/lib/triage-core/signals/comms-style.ts +1 -1
- package/lib/triage-core/signals/cross-channel-escalation.ts +2 -2
- package/lib/triage-core/signals/favee-type.ts +6 -1
- package/lib/triage-core/signals/goal-relevance.ts +31 -2
- package/lib/triage-core/signals/personal-importance.ts +1 -1
- package/lib/triage-core/signals/referral-chain.ts +0 -1
- package/lib/triage-core/signals/relationship-decay.ts +4 -0
- package/lib/triage-core/signals/relationship-health.ts +6 -1
- package/lib/triage-core/signals/trajectory-signal.ts +38 -3
- package/lib/triage-core/tournament-runner.js +11 -1
- package/lib/triage-core/triage-llm-factory.ts +110 -0
- package/lib/triage-core/triage-local-llm.ts +145 -0
- package/lib/triage-core/triage-sql-store.ts +337 -0
- package/lib/triage-core/types.ts +2 -2
- package/lib/unified-graph.atomic.test.ts +52 -0
- package/lib/unified-graph.failure-categories.test.ts +55 -0
- package/package.json +18 -7
- package/prebuilds/darwin-arm64/better_sqlite3.node +0 -0
- package/prebuilds/linux-x64/better_sqlite3.node +0 -0
- package/prebuilds/win32-x64/better_sqlite3.node +0 -0
- package/skills/helios-bookkeeping/SKILL.md +321 -0
- package/skills/helios-briefer/SKILL.md +44 -0
- package/skills/helios-client-relations/SKILL.md +322 -0
- package/skills/helios-personal-triager/SKILL.md +45 -0
- package/skills/helios-recruitment/SKILL.md +317 -0
- package/skills/helios-relationship-nudger/SKILL.md +77 -0
- package/skills/helios-researcher/SKILL.md +44 -0
- package/skills/helios-scheduler/SKILL.md +58 -0
- package/skills/helios-tax-analyst/SKILL.md +280 -0
- package/lib/triage-core/orchestrator.ts.bak-r005-r006-r008 +0 -1823
|
@@ -29,16 +29,28 @@ async function handleGetCosts(req, res, ctx) {
|
|
|
29
29
|
|
|
30
30
|
const url = new URL(req.url, 'http://localhost');
|
|
31
31
|
const groupBy = url.searchParams.get('groupBy');
|
|
32
|
+
// G-01: date range filtering — ?from=ISO&to=ISO
|
|
33
|
+
const fromDate = url.searchParams.get('from') || null;
|
|
34
|
+
const toDate = url.searchParams.get('to') || null;
|
|
32
35
|
|
|
33
36
|
try {
|
|
34
37
|
if (groupBy && ['provider', 'model', 'agent'].includes(groupBy)) {
|
|
35
38
|
const field = groupBy === 'agent' ? 'agentId' : groupBy;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
let groupCypher = `MATCH (c:CostEvent {companyId: $cid})`;
|
|
40
|
+
const groupParams = { cid: ctx.cid };
|
|
41
|
+
if (fromDate && toDate) {
|
|
42
|
+
groupCypher += ' WHERE c.createdAt >= $from AND c.createdAt <= $to';
|
|
43
|
+
groupParams.from = fromDate;
|
|
44
|
+
groupParams.to = toDate;
|
|
45
|
+
} else if (fromDate) {
|
|
46
|
+
groupCypher += ' WHERE c.createdAt >= $from';
|
|
47
|
+
groupParams.from = fromDate;
|
|
48
|
+
} else if (toDate) {
|
|
49
|
+
groupCypher += ' WHERE c.createdAt <= $to';
|
|
50
|
+
groupParams.to = toDate;
|
|
51
|
+
}
|
|
52
|
+
groupCypher += ` RETURN c.${field} AS groupKey, sum(coalesce(c.costCents, c.amount * 100, 0)) / 100.0 AS total, count(c) AS count ORDER BY total DESC`;
|
|
53
|
+
const result = await mgQuery(groupCypher, groupParams);
|
|
42
54
|
const rows = (result?.rows ?? []);
|
|
43
55
|
const groups = rows.map(r => ({ [groupBy]: r[0], total: r[1], count: r[2] }));
|
|
44
56
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
@@ -46,8 +58,20 @@ async function handleGetCosts(req, res, ctx) {
|
|
|
46
58
|
return;
|
|
47
59
|
}
|
|
48
60
|
|
|
49
|
-
|
|
50
|
-
|
|
61
|
+
let listCypher = `MATCH (c:CostEvent {companyId: $cid})`;
|
|
62
|
+
const listParams = { cid: ctx.cid, limit: 100 };
|
|
63
|
+
if (fromDate && toDate) {
|
|
64
|
+
listCypher += ' WHERE c.createdAt >= $from AND c.createdAt <= $to';
|
|
65
|
+
listParams.from = fromDate;
|
|
66
|
+
listParams.to = toDate;
|
|
67
|
+
} else if (fromDate) {
|
|
68
|
+
listCypher += ' WHERE c.createdAt >= $from';
|
|
69
|
+
listParams.from = fromDate;
|
|
70
|
+
} else if (toDate) {
|
|
71
|
+
listCypher += ' WHERE c.createdAt <= $to';
|
|
72
|
+
listParams.to = toDate;
|
|
73
|
+
}
|
|
74
|
+
listCypher += `
|
|
51
75
|
RETURN c.id AS id, c.provider AS provider, c.model AS model,
|
|
52
76
|
c.agentId AS agentId,
|
|
53
77
|
coalesce(c.costCents, c.amount * 100, 0) / 100.0 AS amount,
|
|
@@ -55,9 +79,8 @@ async function handleGetCosts(req, res, ctx) {
|
|
|
55
79
|
c.inputTokens AS inputTokens, c.outputTokens AS outputTokens,
|
|
56
80
|
c.createdAt AS createdAt
|
|
57
81
|
ORDER BY c.createdAt DESC
|
|
58
|
-
LIMIT toInteger($limit)
|
|
59
|
-
|
|
60
|
-
);
|
|
82
|
+
LIMIT toInteger($limit)`;
|
|
83
|
+
const result = await mgQuery(listCypher, listParams);
|
|
61
84
|
const rows = (result?.rows ?? []);
|
|
62
85
|
const keys = ['id', 'provider', 'model', 'agentId', 'amount', 'biller', 'inputTokens', 'outputTokens', 'createdAt'];
|
|
63
86
|
const events = rows.map(r => {
|
|
@@ -78,14 +101,31 @@ async function handleGetCosts(req, res, ctx) {
|
|
|
78
101
|
* Returns all budget policies with current spend percentage.
|
|
79
102
|
*/
|
|
80
103
|
async function handleGetBudgetStatus(req, res, ctx) {
|
|
104
|
+
// C-1 fix: filter by agentId when provided — prevents one agent seeing another's budget policy
|
|
105
|
+
const url = new URL(req.url, 'http://localhost');
|
|
106
|
+
const agentIdFilter = url.searchParams.get('agentId') || null;
|
|
107
|
+
// M-3 fix: guard against Memgraph unavailability
|
|
108
|
+
if (!ctx.mgQuery) {
|
|
109
|
+
res.writeHead(503, { 'Content-Type': 'application/json' });
|
|
110
|
+
res.end(JSON.stringify({ error: 'Memgraph not connected', policies: [] }));
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
81
113
|
try {
|
|
82
|
-
|
|
83
|
-
|
|
114
|
+
let cypher, params;
|
|
115
|
+
if (agentIdFilter) {
|
|
116
|
+
cypher = `MATCH (bp:BudgetPolicy {companyId: $cid, agentId: $agentId})
|
|
117
|
+
RETURN bp.id AS id, bp.scope AS scope, bp.agentId AS agentId,
|
|
118
|
+
bp.limitCents AS limitCents, bp.spentCents AS spentCents,
|
|
119
|
+
bp.warnPercent AS warnPercent`;
|
|
120
|
+
params = { cid: ctx.cid, agentId: agentIdFilter };
|
|
121
|
+
} else {
|
|
122
|
+
cypher = `MATCH (bp:BudgetPolicy {companyId: $cid})
|
|
84
123
|
RETURN bp.id AS id, bp.scope AS scope, bp.agentId AS agentId,
|
|
85
124
|
bp.limitCents AS limitCents, bp.spentCents AS spentCents,
|
|
86
|
-
bp.warnPercent AS warnPercent
|
|
87
|
-
{ cid: ctx.cid }
|
|
88
|
-
|
|
125
|
+
bp.warnPercent AS warnPercent`;
|
|
126
|
+
params = { cid: ctx.cid };
|
|
127
|
+
}
|
|
128
|
+
const result = await ctx.mgQuery(cypher, params);
|
|
89
129
|
|
|
90
130
|
const policies = (result?.rows ?? []).map(([id, scope, agentId, limitCents, spentCents, warnPercent]) => {
|
|
91
131
|
const limit = limitCents ?? 0;
|
|
@@ -116,6 +156,12 @@ module.exports = function createDashboardRouter(handlers) {
|
|
|
116
156
|
return async function dashboardRoute(req, res, ctx, pathname, method) {
|
|
117
157
|
// POST /api/companies -- register a company at runtime (for tests and dynamic wizard creation)
|
|
118
158
|
if (method === 'POST' && pathname === '/api/companies') {
|
|
159
|
+
// C-2 fix: guard against null handler — use /api/daemon/register-company instead
|
|
160
|
+
if (!handleRegisterCompany) {
|
|
161
|
+
res.writeHead(501, { 'Content-Type': 'application/json' });
|
|
162
|
+
res.end(JSON.stringify({ error: 'Company registration via /api/companies is not configured. Use POST /api/daemon/register-company instead.' }));
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
119
165
|
await handleRegisterCompany(req, res, ctx);
|
|
120
166
|
return true;
|
|
121
167
|
}
|
package/daemon/routes/dept.js
CHANGED
|
@@ -149,7 +149,16 @@ module.exports = function createDeptRoute({ mgQuery, broadcast, semanticUpdater
|
|
|
149
149
|
pcp.rationale = $rationale,
|
|
150
150
|
pcp.status = 'pending',
|
|
151
151
|
pcp.updatedAt = datetime()`,
|
|
152
|
-
|
|
152
|
+
{ proposalId, cid, pillarId, dept, section, proposedChange: String(proposedChange), rationale: rationale ? String(rationale) : '', authorId }
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
// P1-C: Create Approval node for plan_change_review so it surfaces in GET /api/hbo/approvals
|
|
156
|
+
await mgQuery(
|
|
157
|
+
`MERGE (a:Approval {id: $approvalId})
|
|
158
|
+
ON CREATE SET a.type = 'plan_change_review', a.companyId = $cid, a.status = 'pending',
|
|
159
|
+
a.proposalId = $proposalId, a.createdAt = datetime()
|
|
160
|
+
ON MATCH SET a.status = 'pending', a.proposalId = $proposalId`,
|
|
161
|
+
{ approvalId: `approval:pcp:${proposalId}`, proposalId, cid }
|
|
153
162
|
);
|
|
154
163
|
|
|
155
164
|
// Respond immediately — LLM analysis is async
|
|
@@ -16,14 +16,16 @@ const { spawn } = require('child_process');
|
|
|
16
16
|
const path = require('path');
|
|
17
17
|
|
|
18
18
|
const HOME = homedir();
|
|
19
|
-
const
|
|
19
|
+
const HELIOS_ROOT = process.env.HELIOS_ROOT
|
|
20
|
+
|| join(HOME, 'Desktop', 'Helios', 'helios-agent-main');
|
|
21
|
+
const TRIAGE_DATA = join(HELIOS_ROOT, 'data', 'email-triage');
|
|
20
22
|
const BRIEFING_PATH = join(TRIAGE_DATA, 'latest-briefing.json');
|
|
21
23
|
const INBOX_PATH = join(TRIAGE_DATA, 'latest-inbox.json');
|
|
22
24
|
const DRAFTS_PATH = join(TRIAGE_DATA, 'drafted-responses.json');
|
|
23
|
-
const DASHBOARD_PATH = join(
|
|
25
|
+
const DASHBOARD_PATH = join(HELIOS_ROOT, 'daemon', 'triage', 'dashboard.html');
|
|
24
26
|
|
|
25
27
|
// ─── Backfill Process Mutex (PID file) ──────────────────────────────────────
|
|
26
|
-
const BACKFILL_PID_FILE = path.join(
|
|
28
|
+
const BACKFILL_PID_FILE = path.join(HELIOS_ROOT, 'data', 'backfill.pid');
|
|
27
29
|
|
|
28
30
|
function isBackfillRunning() {
|
|
29
31
|
try {
|
|
@@ -64,14 +66,14 @@ function jsonResponse(res, status, data) {
|
|
|
64
66
|
*/
|
|
65
67
|
async function regenerateDashboard() {
|
|
66
68
|
return new Promise((resolve) => {
|
|
67
|
-
const updaterPath = join(
|
|
69
|
+
const updaterPath = join(HELIOS_ROOT, 'scripts', 'update-dashboard.js');
|
|
68
70
|
if (!existsSync(updaterPath)) {
|
|
69
71
|
console.warn('[email-triage] update-dashboard.js not found — skipping regen');
|
|
70
72
|
resolve();
|
|
71
73
|
return;
|
|
72
74
|
}
|
|
73
75
|
const child = spawn(process.execPath, [updaterPath], {
|
|
74
|
-
cwd:
|
|
76
|
+
cwd: HELIOS_ROOT,
|
|
75
77
|
env: { ...process.env },
|
|
76
78
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
77
79
|
windowsHide: true,
|
|
@@ -237,6 +239,7 @@ module.exports = function emailTriageRoute({ broadcast } = {}) {
|
|
|
237
239
|
// Parse optional body for config
|
|
238
240
|
let since = '30d';
|
|
239
241
|
let limit = 100;
|
|
242
|
+
let account = null;
|
|
240
243
|
try {
|
|
241
244
|
const chunks = [];
|
|
242
245
|
await new Promise((resolve, reject) => {
|
|
@@ -247,6 +250,7 @@ module.exports = function emailTriageRoute({ broadcast } = {}) {
|
|
|
247
250
|
const body = chunks.length > 0 ? JSON.parse(Buffer.concat(chunks).toString()) : {};
|
|
248
251
|
if (body.since) since = body.since;
|
|
249
252
|
if (body.limit) limit = parseInt(body.limit, 10) || 100;
|
|
253
|
+
if (body.account) account = body.account;
|
|
250
254
|
} catch (_) { /* use defaults */ }
|
|
251
255
|
|
|
252
256
|
// Set up SSE headers
|
|
@@ -268,10 +272,12 @@ module.exports = function emailTriageRoute({ broadcast } = {}) {
|
|
|
268
272
|
|
|
269
273
|
// Resolve the backfill script — prefer run-backfill-30d.ts (full triage + drafts)
|
|
270
274
|
const scriptCandidates = [
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
join(
|
|
275
|
+
process.env.HELIOS_ROOT
|
|
276
|
+
? join(process.env.HELIOS_ROOT, 'run-backfill-30d.ts')
|
|
277
|
+
: join(HOME, 'Desktop', 'Helios', 'helios-agent-main', 'run-backfill-30d.ts'), // W1-3: correct script (full 5-phase email triage + drafts)
|
|
278
|
+
join(HELIOS_ROOT, 'run-triage-backfill.ts'), // legacy name (does not exist, kept as fallback)
|
|
279
|
+
join(HELIOS_ROOT, 'extensions', 'email', 'backfill.ts'), // graph ingestion only
|
|
280
|
+
join(HELIOS_ROOT, 'scripts', 'run-backfill.ts'), // full graph backfill (wrong for email triage)
|
|
275
281
|
];
|
|
276
282
|
|
|
277
283
|
const scriptPath = scriptCandidates.find(p => existsSync(p));
|
|
@@ -293,17 +299,20 @@ module.exports = function emailTriageRoute({ broadcast } = {}) {
|
|
|
293
299
|
}
|
|
294
300
|
|
|
295
301
|
const args = [scriptPath, '--since', sinceDate, '--limit', limit];
|
|
302
|
+
if (account) args.push('--account', account);
|
|
296
303
|
sendSSE({ phase: 1, message: `Running: npx tsx ${path.basename(scriptPath)} --since ${sinceDate} --limit ${limit}` });
|
|
297
304
|
|
|
298
305
|
let child;
|
|
299
306
|
try {
|
|
300
307
|
// C6: use npx.cmd on Windows so spawn finds the correct executable
|
|
308
|
+
// shell:true required on Windows for .cmd files (EINVAL without it)
|
|
301
309
|
const npxBin = process.platform === 'win32' ? 'npx.cmd' : 'npx';
|
|
302
310
|
child = spawn(npxBin, ['tsx', ...args], {
|
|
303
|
-
cwd:
|
|
311
|
+
cwd: HELIOS_ROOT,
|
|
304
312
|
env: { ...process.env, HELIOS_SKIP_INTERNAL_DASHBOARD_REGEN: '1' },
|
|
305
313
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
306
314
|
windowsHide: true,
|
|
315
|
+
shell: process.platform === 'win32',
|
|
307
316
|
});
|
|
308
317
|
} catch (spawnErr) {
|
|
309
318
|
sendSSE({ phase: -1, message: `Spawn error: ${spawnErr.message}`, error: true, done: true });
|