@askexenow/exe-os 0.9.217 → 0.9.219
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/deploy/compose/.env.customer.example +12 -2
- package/deploy/compose/.env.example +42 -16
- package/deploy/compose/PROTECTED_FILES.md +1 -0
- package/deploy/compose/README.md +1 -1
- package/deploy/compose/backup.sh +3 -1
- package/deploy/compose/clickhouse-config.xml +18 -0
- package/deploy/compose/docker-compose.yml +37 -13
- package/deploy/compose/gateway.json +12 -2
- package/deploy/compose/generate-env.ts +17 -1
- package/deploy/compose/init-db.sql +12 -0
- package/deploy/compose/restore.sh +1 -0
- package/deploy/compose/setup.sh +3 -1
- package/deploy/compose/uptime-check.sh +143 -0
- package/deploy/stack-manifests/v0.9.json +4 -4
- package/dist/{active-agent-R7QDYADX.js → active-agent-65SRKUVF.js} +2 -2
- package/dist/{active-agent-4XH2Q6KJ.js → active-agent-YLIAU6SX.js} +2 -2
- package/dist/{agentic-ontology-CHAWPTEY.js → agentic-ontology-VZWBROYO.js} +1 -1
- package/dist/{backfill-metadata-I6VR7JZ2.js → backfill-metadata-YUN6DXIE.js} +3 -3
- package/dist/{behaviors-YJ3HEQED.js → behaviors-4PGM7IJJ.js} +2 -2
- package/dist/bin/agentic-ontology-backfill.js +4 -4
- package/dist/bin/agentic-reflection-backfill.js +5 -5
- package/dist/bin/agentic-semantic-label.js +4 -4
- package/dist/bin/backfill-conversations.js +3 -3
- package/dist/bin/backfill-responses.js +3 -3
- package/dist/bin/backfill-vectors.js +4 -4
- package/dist/bin/bulk-sync-postgres.js +5 -5
- package/dist/bin/cleanup-stale-review-tasks.js +8 -8
- package/dist/bin/cli.js +30 -12
- package/dist/bin/exe-agent-config.js +1 -1
- package/dist/bin/exe-agent.js +6 -6
- package/dist/bin/exe-assign.js +4 -4
- package/dist/bin/exe-boot.js +15 -15
- package/dist/bin/exe-call.js +3 -3
- package/dist/bin/exe-cloud.js +3 -3
- package/dist/bin/exe-dispatch.js +8 -8
- package/dist/bin/exe-doctor.js +1 -1
- package/dist/bin/exe-export-behaviors.js +6 -6
- package/dist/bin/exe-forget.js +5 -5
- package/dist/bin/exe-gateway.js +38 -12
- package/dist/bin/exe-heartbeat.js +8 -8
- package/dist/bin/exe-kill.js +11 -11
- package/dist/bin/exe-launch-agent.js +15 -15
- package/dist/bin/exe-new-employee.js +5 -5
- package/dist/bin/exe-pending-messages.js +9 -9
- package/dist/bin/exe-pending-notifications.js +8 -8
- package/dist/bin/exe-pending-reviews.js +8 -8
- package/dist/bin/exe-rename.js +3 -3
- package/dist/bin/exe-review.js +10 -10
- package/dist/bin/exe-search.js +4 -4
- package/dist/bin/exe-session-cleanup.js +13 -13
- package/dist/bin/exe-settings.js +3 -3
- package/dist/bin/exe-start-codex.js +10 -10
- package/dist/bin/exe-start-opencode.js +7 -7
- package/dist/bin/exe-status.js +9 -9
- package/dist/bin/exe-team.js +2 -2
- package/dist/bin/git-sweep.js +8 -8
- package/dist/bin/graph-backfill.js +3 -3
- package/dist/bin/graph-export.js +4 -4
- package/dist/bin/import-history.js +4 -4
- package/dist/bin/install.js +5 -5
- package/dist/bin/intercom-check.js +4 -4
- package/dist/bin/mcp-sessions.js +2 -2
- package/dist/bin/orchestration-metrics.js +3 -3
- package/dist/bin/postgres-agentic-reflection-backfill.js +2 -2
- package/dist/bin/postgres-agentic-semantic-backfill.js +1 -1
- package/dist/bin/scan-tasks.js +8 -8
- package/dist/bin/setup.js +1 -1
- package/dist/bin/shard-migrate.js +3 -3
- package/dist/bin/stack-update.js +1 -1
- package/dist/bin/vps-health-gate.js +1 -1
- package/dist/{capacity-monitor-XFMZSJDB.js → capacity-monitor-A6TMCY5F.js} +9 -9
- package/dist/{catchup-brief-D5IZFZDO.js → catchup-brief-TU4C22MJ.js} +10 -10
- package/dist/{chunk-F54CVIXL.js → chunk-222EGJ6Z.js} +1 -1
- package/dist/{chunk-6UY62EGD.js → chunk-2F7URV5H.js} +4 -4
- package/dist/{chunk-2DRWIXOO.js → chunk-2OERQW4L.js} +2 -2
- package/dist/{chunk-4GXXYDNU.js → chunk-3XGZAFHE.js} +36 -0
- package/dist/{chunk-BN3HRSEU.js → chunk-443YQ2FS.js} +2 -2
- package/dist/{chunk-5QKUR5KS.js → chunk-4UHKYQZJ.js} +1 -1
- package/dist/{chunk-QOY6CTHV.js → chunk-55VWU47L.js} +2 -2
- package/dist/{chunk-ACOW43IN.js → chunk-56NWZFB2.js} +1 -1
- package/dist/{chunk-UO3IEPSY.js → chunk-5ZTZ3SHF.js} +233 -333
- package/dist/{chunk-GKNYEJQ3.js → chunk-7DYKIMN2.js} +1 -1
- package/dist/{chunk-5G643UWZ.js → chunk-7EUYGWPH.js} +117 -8
- package/dist/{chunk-FXD53Q32.js → chunk-7F5MJSWJ.js} +3 -3
- package/dist/{chunk-2QNMGFIF.js → chunk-7WEP4DNC.js} +2 -2
- package/dist/{chunk-S5TTV7PC.js → chunk-A24RUKU6.js} +1 -1
- package/dist/{chunk-NEGJAEZ7.js → chunk-AAMUHY6Y.js} +3 -3
- package/dist/{chunk-46WQ76VA.js → chunk-AMGEPNUB.js} +1 -1
- package/dist/{chunk-HURS5JVX.js → chunk-BCREJ6FD.js} +21 -3
- package/dist/{chunk-S2T7CE4P.js → chunk-BMRLKOGT.js} +1 -1
- package/dist/{chunk-S4I3UITZ.js → chunk-BXLA6CQM.js} +1 -1
- package/dist/{chunk-JXJV64JW.js → chunk-D7DRYXDE.js} +1 -1
- package/dist/{chunk-5VOC35A3.js → chunk-DAE4I3UN.js} +1 -1
- package/dist/{chunk-R766IOBQ.js → chunk-DF67VZ2H.js} +1 -1
- package/dist/{chunk-HW46Q4AR.js → chunk-DZE2MBOW.js} +257 -10
- package/dist/{chunk-RTGN42GD.js → chunk-E6KXZF4B.js} +2 -2
- package/dist/{chunk-IFSAR5IX.js → chunk-EB3AAVAK.js} +5 -5
- package/dist/{chunk-PKIOJQ2N.js → chunk-EUS7TKVR.js} +1 -1
- package/dist/{chunk-T43SC2XX.js → chunk-FJQPH2W3.js} +2 -2
- package/dist/{chunk-GEFZHKEN.js → chunk-GJFS27NL.js} +5 -5
- package/dist/{chunk-KEFHCL4U.js → chunk-GT5E5PW6.js} +1 -1
- package/dist/{chunk-XPKACO5A.js → chunk-GYIPOKH6.js} +8 -8
- package/dist/chunk-I3MJHU76.js +225 -0
- package/dist/{chunk-2IMUAL3X.js → chunk-IEAXNG3H.js} +8 -8
- package/dist/{chunk-YJNRRQOG.js → chunk-ILTZBCLW.js} +2 -2
- package/dist/{chunk-SDQSOQOE.js → chunk-JEBWC4VU.js} +2 -2
- package/dist/{chunk-7X6QKJGM.js → chunk-JHEABI3I.js} +2 -2
- package/dist/{chunk-R2MZDZTQ.js → chunk-JUWC7V2I.js} +3 -3
- package/dist/{chunk-6I7O6YW3.js → chunk-OM3CETSN.js} +3 -3
- package/dist/{chunk-WEJ45ZFF.js → chunk-PBI526CO.js} +2 -2
- package/dist/{chunk-I22ZH3XF.js → chunk-PXO6SF6L.js} +1 -1
- package/dist/{chunk-B7NO5U7H.js → chunk-Q4GGIM3A.js} +1 -1
- package/dist/{chunk-I6474EQW.js → chunk-QG6IPAT6.js} +1 -1
- package/dist/{chunk-NO5GHSNU.js → chunk-QPU5QQLX.js} +4 -3
- package/dist/{chunk-4ANCHFE2.js → chunk-R6JBGFSE.js} +1 -1
- package/dist/{chunk-ALVYUOBW.js → chunk-RQJDO6LP.js} +1 -1
- package/dist/{chunk-BFLBZGPZ.js → chunk-S5KQLCYU.js} +1 -1
- package/dist/{chunk-NUUAYDD6.js → chunk-SRJLG6RC.js} +1 -1
- package/dist/{chunk-O6LFXATW.js → chunk-SURCM7EO.js} +3 -3
- package/dist/{chunk-CIANVJ3G.js → chunk-UVUA2DQM.js} +61 -6
- package/dist/{chunk-64DYFA5X.js → chunk-V224L2GJ.js} +3 -3
- package/dist/{chunk-W7OCXE2L.js → chunk-V24ZGSQW.js} +1 -1
- package/dist/{chunk-RSHVFBKD.js → chunk-V2BQL663.js} +8 -8
- package/dist/{chunk-JJHJOGYR.js → chunk-WYPNZALJ.js} +1 -1
- package/dist/{chunk-RSVJQ4E2.js → chunk-YTBT3SW2.js} +1 -1
- package/dist/{chunk-CUKIMXQ7.js → chunk-YTPLK6QP.js} +1 -1
- package/dist/{co-occurrence-EWVCCFOI.js → co-occurrence-FBP2GTER.js} +1 -1
- package/dist/{crdt-sync-TSO4O67N.js → crdt-sync-KFPZWAIE.js} +1 -1
- package/dist/{crm-webhook-WMAW6ZT2.js → crm-webhook-56OJDKXK.js} +2 -2
- package/dist/{cto-delegation-gate-YNWMQEQB.js → cto-delegation-gate-5WNDH4IL.js} +7 -7
- package/dist/{daemon-orchestration-5KUKQOZ4.js → daemon-orchestration-KYK662AN.js} +14 -10
- package/dist/{exe-drift-KP5RZCXA.js → exe-drift-C254MZW4.js} +2 -2
- package/dist/{exe-export-RAYK76SO.js → exe-export-S56FIA5P.js} +4 -4
- package/dist/{exe-import-SAJBGUN5.js → exe-import-7F7Y4I6T.js} +4 -4
- package/dist/{exe-key-W3CME65M.js → exe-key-U7TAND3I.js} +1 -1
- package/dist/{fast-db-init-5VDTKVKX.js → fast-db-init-6DG7B7NO.js} +1 -1
- package/dist/gateway/index.js +6 -6
- package/dist/{git-staleness-M7WLXBAA.js → git-staleness-FDYT34WP.js} +1 -1
- package/dist/{git-task-sweep-GED54WTZ.js → git-task-sweep-EERTURH7.js} +8 -8
- package/dist/{global-procedures-EYWKFVOO.js → global-procedures-74U75Y2I.js} +2 -2
- package/dist/{graph-auto-extract-B4W4BEOZ.js → graph-auto-extract-VUBFSL6D.js} +1 -1
- package/dist/hooks/bug-report-worker.js +9 -9
- package/dist/hooks/codex-stop-task-finalizer.js +9 -9
- package/dist/hooks/commit-complete.js +10 -10
- package/dist/hooks/error-recall.js +5 -5
- package/dist/hooks/exe-heartbeat-hook.js +2 -2
- package/dist/hooks/ingest.js +5 -5
- package/dist/hooks/instructions-loaded.js +3 -3
- package/dist/hooks/manifest.json +19 -19
- package/dist/hooks/notification.js +3 -3
- package/dist/hooks/post-compact.js +9 -9
- package/dist/hooks/post-tool-combined.js +4 -4
- package/dist/hooks/pre-compact.js +10 -10
- package/dist/hooks/pre-tool-use.js +13 -13
- package/dist/hooks/prompt-submit.js +19 -19
- package/dist/hooks/session-end.js +13 -13
- package/dist/hooks/session-start.js +28 -9
- package/dist/hooks/stop.js +13 -13
- package/dist/hooks/subagent-stop.js +9 -9
- package/dist/hooks/summary-worker.js +13 -13
- package/dist/import-conversations-FO4IQCOP.js +23 -0
- package/dist/index.js +15 -15
- package/dist/{installer-EYRABPEC.js → installer-MWLYK37L.js} +4 -4
- package/dist/{installer-WVPFKMDW.js → installer-XIP332UC.js} +4 -4
- package/dist/{installer-X6XJE2EA.js → installer-XZ4H2J3J.js} +4 -4
- package/dist/lib/cloud-sync.js +3 -3
- package/dist/lib/consolidation.js +4 -4
- package/dist/lib/database.js +1 -1
- package/dist/lib/db.js +1 -1
- package/dist/lib/employee-templates.js +3 -3
- package/dist/lib/employees.js +1 -1
- package/dist/lib/exe-daemon.js +65 -25
- package/dist/lib/hybrid-search.js +4 -4
- package/dist/lib/identity.js +1 -1
- package/dist/lib/messaging.js +8 -8
- package/dist/lib/reminders.js +2 -2
- package/dist/lib/schedules.js +4 -4
- package/dist/lib/session-registry.js +3 -3
- package/dist/lib/skill-learning.js +3 -3
- package/dist/lib/store.js +3 -3
- package/dist/lib/task-router.js +2 -2
- package/dist/lib/tasks.js +8 -8
- package/dist/lib/tmux-routing.js +7 -7
- package/dist/lib/token-spend.js +2 -2
- package/dist/mcp/register-tools.js +47 -46
- package/dist/mcp/server.js +48 -47
- package/dist/mcp/tools/complete-reminder.js +3 -3
- package/dist/mcp/tools/create-reminder.js +3 -3
- package/dist/mcp/tools/create-task.js +10 -10
- package/dist/mcp/tools/deactivate-behavior.js +4 -4
- package/dist/mcp/tools/list-reminders.js +3 -3
- package/dist/mcp/tools/list-tasks.js +10 -10
- package/dist/mcp/tools/send-message.js +10 -10
- package/dist/mcp/tools/update-task.js +9 -9
- package/dist/{mcp-http-config-L4U52ZAF.js → mcp-http-config-GYVAS5HQ.js} +2 -2
- package/dist/{memory-cards-I55OBMVE.js → memory-cards-HU5WIUTY.js} +1 -1
- package/dist/{memory-graph-extractor-6M6J5FNX.js → memory-graph-extractor-PNRAGL4V.js} +2 -2
- package/dist/{memory-poisoning-defense-UXB75NB7.js → memory-poisoning-defense-KBBWI6ZL.js} +1 -1
- package/dist/{memory-reflection-3BMVNA6T.js → memory-reflection-UP56KTJ5.js} +1 -1
- package/dist/{notifications-SCHILQCQ.js → notifications-VWAMI4ZE.js} +7 -7
- package/dist/{orchestration-events-RDW7BTCK.js → orchestration-events-7XAYQ2MT.js} +2 -2
- package/dist/{orchestrator-NCEFZF32.js → orchestrator-D7NWJTJO.js} +9 -9
- package/dist/{plan-limits-YE5WKMQM.js → plan-limits-EA3VBZJ2.js} +2 -2
- package/dist/{projection-worker-ENYZ7THQ.js → projection-worker-HNI2TOO3.js} +1 -1
- package/dist/{reranker-QFLVGVRT.js → reranker-M52JJADT.js} +1 -1
- package/dist/{review-polling-ZKYFETP3.js → review-polling-YT3BEKPV.js} +8 -8
- package/dist/runtime/index.js +10 -10
- package/dist/{session-events-XCNQDXF4.js → session-events-7EN6W4EX.js} +8 -8
- package/dist/{session-kill-telemetry-SPB6LEI5.js → session-kill-telemetry-XIFWDG3L.js} +2 -2
- package/dist/{session-scope-FEZQJMD4.js → session-scope-7F3JL2RJ.js} +7 -7
- package/dist/{setup-wizard-KUYMMP35.js → setup-wizard-OT5R6PJ6.js} +1 -1
- package/dist/{skill-refinement-QHOS6CGQ.js → skill-refinement-N5RINY42.js} +1 -1
- package/dist/{stack-update-UCIPCTBO.js → stack-update-SASYGDOB.js} +1 -1
- package/dist/{task-enforcement-HVY36QRD.js → task-enforcement-DCBYO3R6.js} +7 -7
- package/dist/{task-scope-ODSOEGTH.js → task-scope-NM2C2QZX.js} +7 -7
- package/dist/{tasks-crud-RIUHZJGR.js → tasks-crud-AVVOQKZY.js} +17 -7
- package/dist/{tasks-review-EBUVFQUJ.js → tasks-review-QNBO3D7U.js} +7 -7
- package/dist/{telemetry-upload-DFISOB2V.js → telemetry-upload-ZJ4UP2RP.js} +3 -3
- package/dist/{token-budget-6TTILQW7.js → token-budget-SPQB44ZI.js} +1 -1
- package/dist/{tool-telemetry-BNZJICWG.js → tool-telemetry-EIRCR2VO.js} +1 -1
- package/dist/tui/App.js +15 -15
- package/dist/{tui-data-UM6LR4EQ.js → tui-data-5B6YA4VV.js} +7 -7
- package/dist/{worker-gate-K5YTO2H5.js → worker-gate-WQV3FR4R.js} +1 -1
- package/dist/{workflow-engine-WUU5OZ3N.js → workflow-engine-TZKS5QB7.js} +2 -2
- package/dist/{worktree-XZBJQWQZ.js → worktree-KI3X6POI.js} +3 -3
- package/package.json +1 -1
- package/release-notes.json +52 -52
- /package/dist/{chunk-MQA6K7DH.js → chunk-3OZ7LXUY.js} +0 -0
- /package/dist/{chunk-KVOTLCAX.js → chunk-4B7JKVUT.js} +0 -0
- /package/dist/{chunk-HNXHUG7A.js → chunk-HUVQ2NUX.js} +0 -0
- /package/dist/{chunk-Y2B6MB3J.js → chunk-PN7MTAYN.js} +0 -0
- /package/dist/{chunk-54JMB5UI.js → chunk-Q3YGPFZH.js} +0 -0
- /package/dist/{chunk-WRVFZ433.js → chunk-QSWZI7NH.js} +0 -0
- /package/dist/{chunk-4AJYZFDE.js → chunk-V3CEFPKS.js} +0 -0
- /package/dist/{chunk-K77FHRYS.js → chunk-V3NHFF3Z.js} +0 -0
- /package/dist/{chunk-DXB3CB2O.js → chunk-ZPQ2RUIU.js} +0 -0
- /package/dist/{core-memory-NZOLAIOE.js → core-memory-3XHQZ5EI.js} +0 -0
- /package/dist/{wiki-acl-QYGMJDUT.js → wiki-acl-QSO37KYW.js} +0 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import {
|
|
2
|
+
conversationsToMemories,
|
|
3
|
+
detectFormat,
|
|
4
|
+
parseChatGPT,
|
|
5
|
+
parseClaude,
|
|
6
|
+
parseGeneric
|
|
7
|
+
} from "./chunk-Q2G5C3HV.js";
|
|
8
|
+
import {
|
|
9
|
+
extractMemoryGraph
|
|
10
|
+
} from "./chunk-7WEP4DNC.js";
|
|
11
|
+
import {
|
|
12
|
+
flushBatch,
|
|
13
|
+
writeMemory
|
|
14
|
+
} from "./chunk-IEAXNG3H.js";
|
|
15
|
+
import {
|
|
16
|
+
extractKeywords,
|
|
17
|
+
keywordsToString
|
|
18
|
+
} from "./chunk-CHCA3ZM2.js";
|
|
19
|
+
import {
|
|
20
|
+
getActiveAgent
|
|
21
|
+
} from "./chunk-BXLA6CQM.js";
|
|
22
|
+
|
|
23
|
+
// src/mcp/tools/import-conversations.ts
|
|
24
|
+
import { z } from "zod";
|
|
25
|
+
import crypto from "crypto";
|
|
26
|
+
import { readFile, readdir, stat } from "fs/promises";
|
|
27
|
+
import path from "path";
|
|
28
|
+
var DEFAULT_MAX_MEMORIES = 5e4;
|
|
29
|
+
var YIELD_INTERVAL = 50;
|
|
30
|
+
async function parseFile(filePath, format) {
|
|
31
|
+
const content = await readFile(filePath, "utf-8");
|
|
32
|
+
const detectedFormat = format === "auto" ? detectFormat(content, filePath) : format;
|
|
33
|
+
let conversations;
|
|
34
|
+
switch (detectedFormat) {
|
|
35
|
+
case "chatgpt":
|
|
36
|
+
conversations = parseChatGPT(content, filePath);
|
|
37
|
+
break;
|
|
38
|
+
case "claude":
|
|
39
|
+
conversations = parseClaude(content, filePath);
|
|
40
|
+
break;
|
|
41
|
+
case "markdown":
|
|
42
|
+
case "generic":
|
|
43
|
+
default:
|
|
44
|
+
conversations = parseGeneric(content, filePath);
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
return { conversations, detectedFormat };
|
|
48
|
+
}
|
|
49
|
+
async function collectFiles(dirPath) {
|
|
50
|
+
const entries = await readdir(dirPath, { withFileTypes: true });
|
|
51
|
+
const files = [];
|
|
52
|
+
for (const entry of entries) {
|
|
53
|
+
const full = path.join(dirPath, entry.name);
|
|
54
|
+
if (entry.isDirectory()) {
|
|
55
|
+
files.push(...await collectFiles(full));
|
|
56
|
+
} else if (entry.isFile()) {
|
|
57
|
+
const ext = path.extname(entry.name).toLowerCase();
|
|
58
|
+
if ([".json", ".md", ".markdown", ".txt"].includes(ext)) {
|
|
59
|
+
files.push(full);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return files;
|
|
64
|
+
}
|
|
65
|
+
function registerImportConversations(server) {
|
|
66
|
+
server.registerTool(
|
|
67
|
+
"import_conversations",
|
|
68
|
+
{
|
|
69
|
+
title: "Import Conversations",
|
|
70
|
+
description: "Import conversation history from ChatGPT, Claude, or generic exports. Parses conversations, extracts keywords and graph entities, stores as memories. Supports conversations.json (ChatGPT), Claude JSON export, markdown files, and generic JSON arrays. Deduplicates by content hash.",
|
|
71
|
+
inputSchema: {
|
|
72
|
+
path: z.string().describe("File path or directory to import from"),
|
|
73
|
+
format: z.enum(["chatgpt", "claude", "generic", "markdown", "auto"]).default("auto").describe("Conversation format. 'auto' detects from content."),
|
|
74
|
+
project_name: z.string().optional().describe("Project name for memory scoping"),
|
|
75
|
+
dry_run: z.boolean().default(false).describe("Parse and report counts without storing"),
|
|
76
|
+
force: z.boolean().default(false).describe("Override the 50K memory safety cap"),
|
|
77
|
+
max_memories: z.number().optional().describe("Custom memory cap (default 50000)")
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
async ({ path: inputPath, format, project_name, dry_run, force, max_memories }) => {
|
|
81
|
+
const { agentId, agentRole } = getActiveAgent();
|
|
82
|
+
const cap = max_memories ?? DEFAULT_MAX_MEMORIES;
|
|
83
|
+
const resolvedPath = path.resolve(inputPath);
|
|
84
|
+
let files;
|
|
85
|
+
try {
|
|
86
|
+
const stats = await stat(resolvedPath);
|
|
87
|
+
if (stats.isDirectory()) {
|
|
88
|
+
files = await collectFiles(resolvedPath);
|
|
89
|
+
} else {
|
|
90
|
+
files = [resolvedPath];
|
|
91
|
+
}
|
|
92
|
+
} catch (err) {
|
|
93
|
+
return {
|
|
94
|
+
content: [{
|
|
95
|
+
type: "text",
|
|
96
|
+
text: `Path not found: ${resolvedPath}
|
|
97
|
+
${err instanceof Error ? err.message : String(err)}`
|
|
98
|
+
}],
|
|
99
|
+
isError: true
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
if (files.length === 0) {
|
|
103
|
+
return {
|
|
104
|
+
content: [{
|
|
105
|
+
type: "text",
|
|
106
|
+
text: `No importable files found in ${resolvedPath}. Supported: .json, .md, .markdown, .txt`
|
|
107
|
+
}],
|
|
108
|
+
isError: true
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
let totalConversations = 0;
|
|
112
|
+
let allDetectedFormat = "generic";
|
|
113
|
+
const allConversations = [];
|
|
114
|
+
for (const file of files) {
|
|
115
|
+
try {
|
|
116
|
+
const { conversations, detectedFormat } = await parseFile(file, format);
|
|
117
|
+
allConversations.push(...conversations);
|
|
118
|
+
totalConversations += conversations.length;
|
|
119
|
+
allDetectedFormat = detectedFormat;
|
|
120
|
+
} catch (err) {
|
|
121
|
+
console.warn(`[import] Skipping ${file}: ${err instanceof Error ? err.message : String(err)}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (allConversations.length === 0) {
|
|
125
|
+
return {
|
|
126
|
+
content: [{
|
|
127
|
+
type: "text",
|
|
128
|
+
text: `No conversations found in ${files.length} file(s). Format: ${format}. Path: ${resolvedPath}`
|
|
129
|
+
}]
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
const memories = conversationsToMemories(allConversations, allDetectedFormat);
|
|
133
|
+
if (memories.length > cap && !force) {
|
|
134
|
+
return {
|
|
135
|
+
content: [{
|
|
136
|
+
type: "text",
|
|
137
|
+
text: `Import would create ${memories.length} memories (cap: ${cap}). Use force=true to override.
|
|
138
|
+
Files: ${files.length} | Conversations: ${totalConversations} | Format: ${allDetectedFormat}`
|
|
139
|
+
}]
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
if (dry_run) {
|
|
143
|
+
return {
|
|
144
|
+
content: [{
|
|
145
|
+
type: "text",
|
|
146
|
+
text: `[dry run] Import summary:
|
|
147
|
+
Files: ${files.length}
|
|
148
|
+
Format: ${allDetectedFormat}
|
|
149
|
+
Conversations: ${totalConversations}
|
|
150
|
+
Memories to create: ${memories.length}
|
|
151
|
+
Path: ${resolvedPath}`
|
|
152
|
+
}]
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
let stored = 0;
|
|
156
|
+
let skipped = 0;
|
|
157
|
+
const projectName = project_name ?? "import";
|
|
158
|
+
const sessionId = process.env.SESSION_ID ?? "import";
|
|
159
|
+
for (let i = 0; i < memories.length; i++) {
|
|
160
|
+
const mem = memories[i];
|
|
161
|
+
const keywords = extractKeywords(mem.text);
|
|
162
|
+
const graphResult = extractMemoryGraph(
|
|
163
|
+
mem.text,
|
|
164
|
+
agentId,
|
|
165
|
+
projectName,
|
|
166
|
+
"import_conversations"
|
|
167
|
+
);
|
|
168
|
+
const memoryId = crypto.randomUUID();
|
|
169
|
+
try {
|
|
170
|
+
await writeMemory({
|
|
171
|
+
id: memoryId,
|
|
172
|
+
agent_id: agentId,
|
|
173
|
+
agent_role: agentRole,
|
|
174
|
+
session_id: sessionId,
|
|
175
|
+
timestamp: mem.metadata.original_timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
176
|
+
tool_name: "import_conversations",
|
|
177
|
+
project_name: projectName,
|
|
178
|
+
has_error: false,
|
|
179
|
+
raw_text: mem.text,
|
|
180
|
+
vector: null,
|
|
181
|
+
// NULL vectors — backfill later
|
|
182
|
+
source_path: mem.metadata.source_path,
|
|
183
|
+
source_type: "conversation_import",
|
|
184
|
+
memory_type: "conversation",
|
|
185
|
+
tier: 3,
|
|
186
|
+
// Passive ingestion
|
|
187
|
+
importance: 4,
|
|
188
|
+
// Imported conversations are moderate importance
|
|
189
|
+
intent: "import",
|
|
190
|
+
domain: "conversation",
|
|
191
|
+
keywords: keywordsToString(keywords),
|
|
192
|
+
referenced_entities: graphResult.entities.length > 0 ? JSON.stringify(graphResult.entities.map((e) => e.name)) : null
|
|
193
|
+
});
|
|
194
|
+
stored++;
|
|
195
|
+
} catch {
|
|
196
|
+
skipped++;
|
|
197
|
+
}
|
|
198
|
+
if ((i + 1) % YIELD_INTERVAL === 0) {
|
|
199
|
+
await flushBatch();
|
|
200
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
201
|
+
if ((i + 1) % (YIELD_INTERVAL * 10) === 0) {
|
|
202
|
+
console.log(`[import] ${i + 1}/${memories.length} memories processed, ${stored} stored`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
await flushBatch();
|
|
207
|
+
return {
|
|
208
|
+
content: [{
|
|
209
|
+
type: "text",
|
|
210
|
+
text: `Import complete.
|
|
211
|
+
Files: ${files.length}
|
|
212
|
+
Format: ${allDetectedFormat}
|
|
213
|
+
Conversations: ${totalConversations}
|
|
214
|
+
Memories stored: ${stored}
|
|
215
|
+
Skipped (duplicates): ${skipped}
|
|
216
|
+
Path: ${resolvedPath}`
|
|
217
|
+
}]
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export {
|
|
224
|
+
registerImportConversations
|
|
225
|
+
};
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
findScopedDuplicate,
|
|
7
7
|
governMemoryRecord,
|
|
8
8
|
schedulePostWriteMemoryHygiene
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-PN7MTAYN.js";
|
|
10
10
|
import {
|
|
11
11
|
orgBus
|
|
12
12
|
} from "./chunk-MP2AFCGL.js";
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
ensureSchema,
|
|
16
16
|
getClient,
|
|
17
17
|
initTurso
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-3XGZAFHE.js";
|
|
19
19
|
import {
|
|
20
20
|
EMBEDDING_DIM
|
|
21
21
|
} from "./chunk-FXU7JOXK.js";
|
|
@@ -65,7 +65,7 @@ function recordShardFailure(project, error) {
|
|
|
65
65
|
`[store] Shard circuit OPEN for "${project}" after ${state.failures} consecutive failures. Will retry in ${SHARD_CB_COOLDOWN_MS / 6e4}min. Last error: ${error}
|
|
66
66
|
`
|
|
67
67
|
);
|
|
68
|
-
void import("./orchestration-events-
|
|
68
|
+
void import("./orchestration-events-7XAYQ2MT.js").then(({ recordOrchestrationEventBestEffort }) => {
|
|
69
69
|
recordOrchestrationEventBestEffort({
|
|
70
70
|
eventType: "shard.circuit_open",
|
|
71
71
|
source: "store.recordShardFailure",
|
|
@@ -162,7 +162,7 @@ async function initStore(options) {
|
|
|
162
162
|
);
|
|
163
163
|
_nextVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
|
|
164
164
|
try {
|
|
165
|
-
const { loadGlobalProcedures } = await import("./global-procedures-
|
|
165
|
+
const { loadGlobalProcedures } = await import("./global-procedures-74U75Y2I.js");
|
|
166
166
|
await loadGlobalProcedures();
|
|
167
167
|
} catch (e) {
|
|
168
168
|
logStoreWarn("catch", e);
|
|
@@ -289,7 +289,7 @@ async function writeMemory(record) {
|
|
|
289
289
|
keywords: record.keywords ?? keywordsToString(extractKeywords(record.raw_text))
|
|
290
290
|
};
|
|
291
291
|
try {
|
|
292
|
-
const { checkMemoryPoisoning } = await import("./memory-poisoning-defense-
|
|
292
|
+
const { checkMemoryPoisoning } = await import("./memory-poisoning-defense-KBBWI6ZL.js");
|
|
293
293
|
const poisonResult = await checkMemoryPoisoning({
|
|
294
294
|
memoryId: dbRow.id,
|
|
295
295
|
vector: Array.isArray(dbRow.vector) ? dbRow.vector : void 0,
|
|
@@ -475,19 +475,19 @@ async function flushBatch() {
|
|
|
475
475
|
}
|
|
476
476
|
_nextVersion = baseVersion;
|
|
477
477
|
try {
|
|
478
|
-
const { insertMemoryCardsForBatch } = await import("./memory-cards-
|
|
478
|
+
const { insertMemoryCardsForBatch } = await import("./memory-cards-HU5WIUTY.js");
|
|
479
479
|
await insertMemoryCardsForBatch(batch);
|
|
480
480
|
} catch (e) {
|
|
481
481
|
logStoreWarn("catch", e);
|
|
482
482
|
}
|
|
483
483
|
try {
|
|
484
|
-
const { insertOntologyForBatch } = await import("./agentic-ontology-
|
|
484
|
+
const { insertOntologyForBatch } = await import("./agentic-ontology-VZWBROYO.js");
|
|
485
485
|
await insertOntologyForBatch(batch);
|
|
486
486
|
} catch (e) {
|
|
487
487
|
logStoreWarn("catch", e);
|
|
488
488
|
}
|
|
489
489
|
try {
|
|
490
|
-
const { extractGraphForBatch } = await import("./memory-graph-extractor-
|
|
490
|
+
const { extractGraphForBatch } = await import("./memory-graph-extractor-PNRAGL4V.js");
|
|
491
491
|
await extractGraphForBatch(batch);
|
|
492
492
|
} catch (e) {
|
|
493
493
|
logStoreWarn("catch", e);
|
|
@@ -859,7 +859,7 @@ function formatReport(report, flags) {
|
|
|
859
859
|
return lines.join("\n");
|
|
860
860
|
}
|
|
861
861
|
async function fixNullVectors() {
|
|
862
|
-
const { tryAcquireWorkerSlot, registerWorkerPid } = await import("./worker-gate-
|
|
862
|
+
const { tryAcquireWorkerSlot, registerWorkerPid } = await import("./worker-gate-WQV3FR4R.js");
|
|
863
863
|
if (!tryAcquireWorkerSlot()) {
|
|
864
864
|
process.stderr.write("[exe-doctor] Worker gate full \u2014 waiting for existing backfill workers to finish\n");
|
|
865
865
|
await new Promise((r) => setTimeout(r, 5e3));
|
|
@@ -982,7 +982,7 @@ function splitAtSentences(text, maxChunkSize) {
|
|
|
982
982
|
}
|
|
983
983
|
async function main(argv = process.argv.slice(2)) {
|
|
984
984
|
const flags = parseFlags(argv);
|
|
985
|
-
const { fastDbInit } = await import("./fast-db-init-
|
|
985
|
+
const { fastDbInit } = await import("./fast-db-init-6DG7B7NO.js");
|
|
986
986
|
const client = await fastDbInit();
|
|
987
987
|
const report = await runAudit(client, flags);
|
|
988
988
|
console.log(formatReport(report, flags));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
sessionScopeFilter
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-DZE2MBOW.js";
|
|
4
4
|
|
|
5
5
|
// src/lib/git-task-sweep.ts
|
|
6
6
|
import { execSync } from "child_process";
|
|
@@ -178,7 +178,7 @@ async function sweepTasks(projectName, options = {}) {
|
|
|
178
178
|
}
|
|
179
179
|
if (!dryRun) {
|
|
180
180
|
try {
|
|
181
|
-
const { updateTaskStatus } = await import("./tasks-crud-
|
|
181
|
+
const { updateTaskStatus } = await import("./tasks-crud-AVVOQKZY.js");
|
|
182
182
|
await updateTaskStatus({
|
|
183
183
|
taskId: task.id,
|
|
184
184
|
status: "needs_review",
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
import {
|
|
14
14
|
createCRMWebhookHandler,
|
|
15
15
|
parseTwentyWebhook
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-BMRLKOGT.js";
|
|
17
17
|
import {
|
|
18
18
|
WhatsAppAdapter
|
|
19
19
|
} from "./chunk-ECSNSHZ7.js";
|
|
@@ -49,7 +49,7 @@ import {
|
|
|
49
49
|
retryWithBackoff,
|
|
50
50
|
routeMessage,
|
|
51
51
|
validateGatewayConfig
|
|
52
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-FJQPH2W3.js";
|
|
53
53
|
import {
|
|
54
54
|
getAccountByName,
|
|
55
55
|
getAccountByPhoneNumberId,
|
|
@@ -4,13 +4,13 @@ import {
|
|
|
4
4
|
resolveExeSession,
|
|
5
5
|
sendIntercom,
|
|
6
6
|
strictSessionScopeFilter
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-DZE2MBOW.js";
|
|
8
8
|
import {
|
|
9
9
|
recordOrchestrationEventBestEffort
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-BCREJ6FD.js";
|
|
11
11
|
import {
|
|
12
12
|
getClient
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-3XGZAFHE.js";
|
|
14
14
|
|
|
15
15
|
// src/lib/messaging.ts
|
|
16
16
|
import crypto from "crypto";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isCrdtSyncEnabled
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-QSWZI7NH.js";
|
|
4
4
|
import {
|
|
5
5
|
decryptSyncBlob,
|
|
6
6
|
encryptSyncBlob,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
loadEmployees,
|
|
13
13
|
registerBinSymlinks,
|
|
14
14
|
saveEmployees
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-3XGZAFHE.js";
|
|
16
16
|
import {
|
|
17
17
|
loadDeviceId
|
|
18
18
|
} from "./chunk-72DJ42IE.js";
|
|
@@ -489,7 +489,7 @@ async function cloudSync(config) {
|
|
|
489
489
|
let pulled = 0;
|
|
490
490
|
if (pullResult.records.length > 0) {
|
|
491
491
|
if (isCrdtSyncEnabled()) {
|
|
492
|
-
const { initCrdtDoc, importExistingMemories, readAllMemories } = await import("./crdt-sync-
|
|
492
|
+
const { initCrdtDoc, importExistingMemories, readAllMemories } = await import("./crdt-sync-KFPZWAIE.js");
|
|
493
493
|
initCrdtDoc();
|
|
494
494
|
importExistingMemories(
|
|
495
495
|
pullResult.records.map((rec) => ({
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-GNHN5HRQ.js";
|
|
4
4
|
import {
|
|
5
5
|
buildClaudeHttpMcpEntry
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-A24RUKU6.js";
|
|
7
7
|
import {
|
|
8
8
|
EXE_HOOKS,
|
|
9
9
|
isLegacyHomeDirHookCommand,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "./chunk-L3TB7CC3.js";
|
|
12
12
|
import {
|
|
13
13
|
ensureAllAgentSymlinks
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-4UHKYQZJ.js";
|
|
15
15
|
import {
|
|
16
16
|
MCP_LEGACY_KEY,
|
|
17
17
|
MCP_PRIMARY_KEY
|
|
@@ -864,6 +864,7 @@ function setupTmux(home) {
|
|
|
864
864
|
const userTmuxConf = path.join(homeDir, ".tmux.conf");
|
|
865
865
|
const backupPath = path.join(homeDir, ".tmux.conf.backup");
|
|
866
866
|
const sourceLine = "source-file ~/.exe-os/tmux.conf";
|
|
867
|
+
const shellQuote = (value) => `'${value.replace(/'/g, "'\\''")}'`;
|
|
867
868
|
const pkgRoot = resolvePackageRoot();
|
|
868
869
|
const assetPath = path.join(pkgRoot, "dist", "assets", "tmux.conf");
|
|
869
870
|
if (!existsSync(assetPath)) {
|
|
@@ -913,7 +914,7 @@ ${sourceLine}
|
|
|
913
914
|
`);
|
|
914
915
|
}
|
|
915
916
|
try {
|
|
916
|
-
execSync(`tmux source-file ${
|
|
917
|
+
execSync(`tmux source-file ${shellQuote(userTmuxConf)} 2>/dev/null`);
|
|
917
918
|
} catch {
|
|
918
919
|
}
|
|
919
920
|
process.stderr.write("exe-os: tmux config installed\n");
|
|
@@ -111,7 +111,7 @@ function releaseBackfillLock() {
|
|
|
111
111
|
}
|
|
112
112
|
async function getTaskAwareCapacity() {
|
|
113
113
|
const { getClient } = await import("./lib/database.js");
|
|
114
|
-
const { sessionScopeFilter } = await import("./task-scope-
|
|
114
|
+
const { sessionScopeFilter } = await import("./task-scope-NM2C2QZX.js");
|
|
115
115
|
const client = getClient();
|
|
116
116
|
const scope = sessionScopeFilter();
|
|
117
117
|
const result = await client.execute({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
routeTask
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-SRJLG6RC.js";
|
|
4
4
|
import {
|
|
5
5
|
createTaskCore,
|
|
6
6
|
employeeSessionName,
|
|
@@ -9,11 +9,11 @@ import {
|
|
|
9
9
|
isEmployeeAlive,
|
|
10
10
|
sessionScopeFilter,
|
|
11
11
|
updateTaskStatus
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-DZE2MBOW.js";
|
|
13
13
|
import {
|
|
14
14
|
DEFAULT_COORDINATOR_TEMPLATE_NAME,
|
|
15
15
|
getCoordinatorName
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-3XGZAFHE.js";
|
|
17
17
|
|
|
18
18
|
// src/runtime/orchestrator.ts
|
|
19
19
|
var STALE_THRESHOLD_MS = 2 * 60 * 60 * 1e3;
|
|
@@ -61,7 +61,7 @@ async function rollbackStackUpdate(options) {
|
|
|
61
61
|
}
|
|
62
62
|
writeFileSync(options.envFile, readFileSync(rollbackEnv), { mode: 384 });
|
|
63
63
|
const composeArgs = ["compose", "--file", options.composeFile, "--env-file", options.envFile];
|
|
64
|
-
exec("docker", [...composeArgs, "up", "-d"]);
|
|
64
|
+
exec("docker", [...composeArgs, "up", "-d", "--remove-orphans"]);
|
|
65
65
|
return { status: "rolled_back", targetVersion: "previous", changes: [], backupEnvFile: rollbackEnv, lockFile: options.lockFile ?? path.join(path.dirname(options.envFile), ".exe-stack-lock.json") };
|
|
66
66
|
}
|
|
67
67
|
function parseStackManifest(raw, publicKey) {
|
|
@@ -414,6 +414,11 @@ function bootstrapStackHost(options) {
|
|
|
414
414
|
}
|
|
415
415
|
copyTemplateIfMissing("deploy/compose/docker-compose.yml", options.composeFile, createdFiles);
|
|
416
416
|
copyTemplateIfMissing("deploy/compose/.env.customer.example", options.envFile, createdFiles);
|
|
417
|
+
copyTemplateIfMissing(
|
|
418
|
+
"deploy/compose/clickhouse-config.xml",
|
|
419
|
+
path.join(path.dirname(options.envFile), "clickhouse-config.xml"),
|
|
420
|
+
createdFiles
|
|
421
|
+
);
|
|
417
422
|
const brandingDest = path.join(path.dirname(options.envFile), "branding.json");
|
|
418
423
|
copyTemplateIfMissing("deploy/compose/gateway.json", path.join(path.dirname(options.envFile), "gateway.json"), createdFiles);
|
|
419
424
|
if (!existsSync(brandingDest)) writeFileSync(brandingDest, JSON.stringify({ brandName: "Hygo", productName: "Hygo OS" }, null, 2) + "\n", { mode: 384 });
|
|
@@ -471,7 +476,8 @@ function areStackContainersRunning(composeFile, envFile) {
|
|
|
471
476
|
}
|
|
472
477
|
var CRITICAL_BIND_MOUNTS = [
|
|
473
478
|
{ file: ".env", description: "secrets and image tags" },
|
|
474
|
-
{ file: "gateway.json", description: "gateway connector config" }
|
|
479
|
+
{ file: "gateway.json", description: "gateway connector config" },
|
|
480
|
+
{ file: "clickhouse-config.xml", description: "ClickHouse memory/log guardrails" }
|
|
475
481
|
];
|
|
476
482
|
var CRITICAL_VOLUMES = [
|
|
477
483
|
"postgres_data",
|
|
@@ -509,6 +515,44 @@ function assertVolumesIntact() {
|
|
|
509
515
|
console.warn("[stack-update] Data may have been lost. Check if 'docker compose down -v' was used.");
|
|
510
516
|
}
|
|
511
517
|
}
|
|
518
|
+
function warnLegacyDaemonVolume() {
|
|
519
|
+
const legacy = spawnSync("docker", ["volume", "inspect", "exe-os_exed_data"], {
|
|
520
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
521
|
+
timeout: 5e3
|
|
522
|
+
});
|
|
523
|
+
const current = spawnSync("docker", ["volume", "inspect", "exe-os_exe_os_data"], {
|
|
524
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
525
|
+
timeout: 5e3
|
|
526
|
+
});
|
|
527
|
+
if (legacy.status === 0 && current.status === 0) {
|
|
528
|
+
console.warn("[stack-update] \u26A0 Legacy volume exe-os_exed_data exists alongside exe-os_exe_os_data.");
|
|
529
|
+
console.warn("[stack-update] Keeping both volumes intact; after verifying exe_os_data has current daemon state, remove exed_data manually if desired.");
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
function applyPostgresInitSql(composeArgs, envFile, composeFile, exec) {
|
|
533
|
+
const initSql = path.join(path.dirname(composeFile), "init-db.sql");
|
|
534
|
+
if (!existsSync(initSql)) return;
|
|
535
|
+
const env = parseEnv(readFileSync(envFile, "utf8"));
|
|
536
|
+
const postgresUser = env.get("POSTGRES_USER") || "exe";
|
|
537
|
+
const postgresDb = env.get("POSTGRES_DB") || "exedb";
|
|
538
|
+
console.log("[stack-update] Applying idempotent Postgres init SQL for existing volumes...");
|
|
539
|
+
exec("docker", [
|
|
540
|
+
...composeArgs,
|
|
541
|
+
"exec",
|
|
542
|
+
"-T",
|
|
543
|
+
"exe-db",
|
|
544
|
+
"psql",
|
|
545
|
+
"-v",
|
|
546
|
+
"ON_ERROR_STOP=1",
|
|
547
|
+
"-U",
|
|
548
|
+
postgresUser,
|
|
549
|
+
"-d",
|
|
550
|
+
postgresDb,
|
|
551
|
+
"-f",
|
|
552
|
+
"/docker-entrypoint-initdb.d/01-init.sql"
|
|
553
|
+
]);
|
|
554
|
+
console.log("[stack-update] \u2713 Postgres init SQL applied");
|
|
555
|
+
}
|
|
512
556
|
async function runStackUpdate(options) {
|
|
513
557
|
const exec = options.exec ?? defaultExec;
|
|
514
558
|
const now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
@@ -518,6 +562,7 @@ async function runStackUpdate(options) {
|
|
|
518
562
|
if (!options.dryRun) assertHostReadyForApply(report);
|
|
519
563
|
}
|
|
520
564
|
assertBindMountsExist(path.dirname(options.envFile));
|
|
565
|
+
warnLegacyDaemonVolume();
|
|
521
566
|
if (!options.dryRun) {
|
|
522
567
|
try {
|
|
523
568
|
const { runPreflight } = await import("./preflight-EAH2MI76.js");
|
|
@@ -587,7 +632,7 @@ async function runStackUpdate(options) {
|
|
|
587
632
|
mkdirSync(updateBackupDir, { recursive: true });
|
|
588
633
|
const backupEnvFile = path.join(updateBackupDir, "env.bak");
|
|
589
634
|
writeFileSync(backupEnvFile, envRaw, { mode: 384 });
|
|
590
|
-
const protectedFiles = ["gateway.json", "branding.json"];
|
|
635
|
+
const protectedFiles = ["gateway.json", "branding.json", "clickhouse-config.xml"];
|
|
591
636
|
for (const f of protectedFiles) {
|
|
592
637
|
const src = path.join(stackDir, f);
|
|
593
638
|
try {
|
|
@@ -690,9 +735,11 @@ async function runStackUpdate(options) {
|
|
|
690
735
|
const RESTART_ORDER = [
|
|
691
736
|
"exe-db",
|
|
692
737
|
// data layer — must be healthy before apps
|
|
738
|
+
"gotrue",
|
|
739
|
+
// auth — depends on idempotent init-db.sql applied after exe-db
|
|
693
740
|
"clickhouse",
|
|
694
741
|
"redis",
|
|
695
|
-
"
|
|
742
|
+
"exe-os",
|
|
696
743
|
// daemon — has its own health endpoint
|
|
697
744
|
"exe-crm",
|
|
698
745
|
// CRM app
|
|
@@ -706,6 +753,7 @@ async function runStackUpdate(options) {
|
|
|
706
753
|
const preSnapshot = spawnSync("docker", ["ps", "--format", "json"], { encoding: "utf8", timeout: 1e4 });
|
|
707
754
|
const preContainerCount = preSnapshot.stdout?.split("\n").filter(Boolean).length ?? 0;
|
|
708
755
|
console.log(`[stack-update] Pre-update snapshot: ${preContainerCount} containers`);
|
|
756
|
+
let restartedAnyService = false;
|
|
709
757
|
for (const service of RESTART_ORDER) {
|
|
710
758
|
const psResult = spawnSync("docker", [...composeArgs, "ps", "--quiet", service], {
|
|
711
759
|
encoding: "utf8",
|
|
@@ -713,7 +761,8 @@ async function runStackUpdate(options) {
|
|
|
713
761
|
timeout: 1e4
|
|
714
762
|
});
|
|
715
763
|
if (psResult.status !== 0) continue;
|
|
716
|
-
exec("docker", [...composeArgs, "up", "-d", "--no-deps", service]);
|
|
764
|
+
exec("docker", [...composeArgs, "up", "-d", "--remove-orphans", "--no-deps", service]);
|
|
765
|
+
restartedAnyService = true;
|
|
717
766
|
const maxWait = 60;
|
|
718
767
|
let healthy = false;
|
|
719
768
|
for (let i = 0; i < maxWait; i++) {
|
|
@@ -736,8 +785,14 @@ async function runStackUpdate(options) {
|
|
|
736
785
|
if (!healthy) {
|
|
737
786
|
throw new Error(`Service ${service} failed health check after ${maxWait}s \u2014 aborting update`);
|
|
738
787
|
}
|
|
788
|
+
if (service === "exe-db") {
|
|
789
|
+
applyPostgresInitSql(composeArgs, options.envFile, options.composeFile, exec);
|
|
790
|
+
}
|
|
739
791
|
console.log(`[stack-update] \u2713 ${service} restarted and healthy`);
|
|
740
792
|
}
|
|
793
|
+
if (!restartedAnyService) {
|
|
794
|
+
exec("docker", [...composeArgs, "up", "-d", "--remove-orphans"]);
|
|
795
|
+
}
|
|
741
796
|
const postSnapshot = spawnSync("docker", ["ps", "--format", "json"], { encoding: "utf8", timeout: 1e4 });
|
|
742
797
|
const postContainerCount = postSnapshot.stdout?.split("\n").filter(Boolean).length ?? 0;
|
|
743
798
|
console.log(`[stack-update] Post-update snapshot: ${postContainerCount} containers (was ${preContainerCount})`);
|
|
@@ -785,7 +840,7 @@ async function runStackUpdate(options) {
|
|
|
785
840
|
} catch (err) {
|
|
786
841
|
writeFileSync(options.envFile, envRaw, { mode: 384 });
|
|
787
842
|
try {
|
|
788
|
-
exec("docker", [...composeArgs, "up", "-d"]);
|
|
843
|
+
exec("docker", [...composeArgs, "up", "-d", "--remove-orphans"]);
|
|
789
844
|
} catch {
|
|
790
845
|
}
|
|
791
846
|
const reason = err instanceof Error ? err.message : String(err);
|