dreamcontext 0.8.1 → 0.8.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.
- package/README.md +97 -3
- package/agents/sleep-product.md +22 -0
- package/agents/sleep-state.md +3 -1
- package/agents/sleep-tasks.md +3 -1
- package/dist/agents/sleep-product.md +22 -0
- package/dist/agents/sleep-state.md +3 -1
- package/dist/agents/sleep-tasks.md +3 -1
- package/dist/dashboard/assets/{BrainCanvas3D-CNDjMlun.js → BrainCanvas3D-CoTzHqzT.js} +1 -1
- package/dist/dashboard/assets/{_baseUniq-DtoPVYjz.js → _baseUniq-BlQ6XWxs.js} +1 -1
- package/dist/dashboard/assets/{ar-SA-G6X2FPQ2-D_dXe_8i.js → ar-SA-G6X2FPQ2-C4qyHe9L.js} +1 -1
- package/dist/dashboard/assets/{arc-8LFYH4lG.js → arc-uGukQNxI.js} +1 -1
- package/dist/dashboard/assets/{architectureDiagram-Q4EWVU46-BIgEpM4v.js → architectureDiagram-Q4EWVU46-BhtWTFvf.js} +1 -1
- package/dist/dashboard/assets/{az-AZ-76LH7QW2-C30ZBwgT.js → az-AZ-76LH7QW2-HfK2pIVQ.js} +1 -1
- package/dist/dashboard/assets/{bg-BG-XCXSNQG7-D0R9pSdG.js → bg-BG-XCXSNQG7-L7TlhXli.js} +1 -1
- package/dist/dashboard/assets/{blockDiagram-DXYQGD6D-DRTa0DpJ.js → blockDiagram-DXYQGD6D-BmPhQEp6.js} +1 -1
- package/dist/dashboard/assets/{bn-BD-2XOGV67Q-vkWxteG3.js → bn-BD-2XOGV67Q-DE0uNoU6.js} +1 -1
- package/dist/dashboard/assets/{c4Diagram-AHTNJAMY-Do_gB8Cs.js → c4Diagram-AHTNJAMY-DtQKYrmP.js} +1 -1
- package/dist/dashboard/assets/{ca-ES-6MX7JW3Y-CTyxGdzW.js → ca-ES-6MX7JW3Y-7JHCTA6b.js} +1 -1
- package/dist/dashboard/assets/channel-3OfE-PZ3.js +1 -0
- package/dist/dashboard/assets/{chunk-4BX2VUAB-DJlttKoY.js → chunk-4BX2VUAB-BvnLY9qE.js} +1 -1
- package/dist/dashboard/assets/{chunk-4TB4RGXK-BdixZX4J.js → chunk-4TB4RGXK--piiFXgS.js} +1 -1
- package/dist/dashboard/assets/{chunk-55IACEB6-CPhKaTLr.js → chunk-55IACEB6-C7uvmawY.js} +1 -1
- package/dist/dashboard/assets/{chunk-EDXVE4YY-Bv0bQVvi.js → chunk-EDXVE4YY-BuWBKOPY.js} +1 -1
- package/dist/dashboard/assets/{chunk-FMBD7UC4-DGjRdLDd.js → chunk-FMBD7UC4-C1Le6hxh.js} +1 -1
- package/dist/dashboard/assets/{chunk-OYMX7WX6-B-wzkRri.js → chunk-OYMX7WX6-B8JE8Wz4.js} +1 -1
- package/dist/dashboard/assets/{chunk-QZHKN3VN-BwK1NqpV.js → chunk-QZHKN3VN-U9FJi59p.js} +1 -1
- package/dist/dashboard/assets/{chunk-YZCP3GAM-DjEwJGlh.js → chunk-YZCP3GAM-BNc94uy1.js} +1 -1
- package/dist/dashboard/assets/classDiagram-6PBFFD2Q-Dpt9qwZI.js +1 -0
- package/dist/dashboard/assets/classDiagram-v2-HSJHXN6E-Dpt9qwZI.js +1 -0
- package/dist/dashboard/assets/clone-CZ-InUnR.js +1 -0
- package/dist/dashboard/assets/{cose-bilkent-S5V4N54A-BJXUn11L.js → cose-bilkent-S5V4N54A-D0hUzBCj.js} +1 -1
- package/dist/dashboard/assets/{cs-CZ-2BRQDIVT-BjRikaNe.js → cs-CZ-2BRQDIVT-B0rWHDIi.js} +1 -1
- package/dist/dashboard/assets/{da-DK-5WZEPLOC-Cn3GTxbV.js → da-DK-5WZEPLOC-D_PQO_T0.js} +1 -1
- package/dist/dashboard/assets/{dagre-KV5264BT-BHn2c24z.js → dagre-KV5264BT-B_bjkEDQ.js} +1 -1
- package/dist/dashboard/assets/{de-DE-XR44H4JA-IvGsdpTt.js → de-DE-XR44H4JA-D1G4J6Mz.js} +1 -1
- package/dist/dashboard/assets/{diagram-5BDNPKRD-YrlF3B5a.js → diagram-5BDNPKRD-B63uEoiS.js} +1 -1
- package/dist/dashboard/assets/{diagram-G4DWMVQ6-DHONF1OD.js → diagram-G4DWMVQ6-DShdwm3D.js} +1 -1
- package/dist/dashboard/assets/{diagram-MMDJMWI5-B1vJLt5b.js → diagram-MMDJMWI5-DdVsHQ-l.js} +1 -1
- package/dist/dashboard/assets/{diagram-TYMM5635-C8P5-4A3.js → diagram-TYMM5635-BdHifyqU.js} +1 -1
- package/dist/dashboard/assets/{el-GR-BZB4AONW-B9GA8_lO.js → el-GR-BZB4AONW-a0CO4RfB.js} +1 -1
- package/dist/dashboard/assets/{erDiagram-SMLLAGMA-CjWWTCWe.js → erDiagram-SMLLAGMA-CYxdxNcb.js} +1 -1
- package/dist/dashboard/assets/{es-ES-U4NZUMDT-Ct1wP_9r.js → es-ES-U4NZUMDT-ejRYVYRf.js} +1 -1
- package/dist/dashboard/assets/{eu-ES-A7QVB2H4-C-49gWlR.js → eu-ES-A7QVB2H4-B-4OXJLd.js} +1 -1
- package/dist/dashboard/assets/{fa-IR-HGAKTJCU-DUo8t-xv.js → fa-IR-HGAKTJCU-DhOcLy7v.js} +1 -1
- package/dist/dashboard/assets/{fi-FI-Z5N7JZ37-DCObnr3i.js → fi-FI-Z5N7JZ37-CKQF9xKf.js} +1 -1
- package/dist/dashboard/assets/{flowDiagram-DWJPFMVM-OQ_IRMqG.js → flowDiagram-DWJPFMVM-azQUtREP.js} +1 -1
- package/dist/dashboard/assets/{fr-FR-RHASNOE6-0EGg3zhN.js → fr-FR-RHASNOE6-CsGekBXq.js} +1 -1
- package/dist/dashboard/assets/{ganttDiagram-T4ZO3ILL-DPTSBcnu.js → ganttDiagram-T4ZO3ILL-DjXmGcb4.js} +2 -2
- package/dist/dashboard/assets/{gitGraphDiagram-UUTBAWPF-BxfeiCqm.js → gitGraphDiagram-UUTBAWPF-Dz87wo6e.js} +1 -1
- package/dist/dashboard/assets/{gl-ES-HMX3MZ6V-WtVwXY6x.js → gl-ES-HMX3MZ6V-NRfsjlmW.js} +1 -1
- package/dist/dashboard/assets/{graph-Du_3_o8q.js → graph-BMW3t-Jz.js} +1 -1
- package/dist/dashboard/assets/{he-IL-6SHJWFNN-CfgspIku.js → he-IL-6SHJWFNN-CK4gfEss.js} +1 -1
- package/dist/dashboard/assets/{hi-IN-IWLTKZ5I-CS9l2g3B.js → hi-IN-IWLTKZ5I-CqyBl1jA.js} +1 -1
- package/dist/dashboard/assets/{hu-HU-A5ZG7DT2-BQ46AerM.js → hu-HU-A5ZG7DT2-BO0SthvO.js} +1 -1
- package/dist/dashboard/assets/{id-ID-SAP4L64H-BeShJyKQ.js → id-ID-SAP4L64H-CrHxJe1s.js} +1 -1
- package/dist/dashboard/assets/{index-D7dWmypK.js → index-B0pCDfL8.js} +1 -1
- package/dist/dashboard/assets/index-rIZLhbl7.js +480 -0
- package/dist/dashboard/assets/index-sax--nf3.css +1 -0
- package/dist/dashboard/assets/{infoDiagram-42DDH7IO-CcFhyaQp.js → infoDiagram-42DDH7IO-zG-8q9HR.js} +1 -1
- package/dist/dashboard/assets/{ishikawaDiagram-UXIWVN3A-9QJeD00p.js → ishikawaDiagram-UXIWVN3A-5OzPmL1c.js} +1 -1
- package/dist/dashboard/assets/{it-IT-JPQ66NNP-csyvfk0t.js → it-IT-JPQ66NNP-CW6fpZrT.js} +1 -1
- package/dist/dashboard/assets/{ja-JP-DBVTYXUO-DctpJ2yz.js → ja-JP-DBVTYXUO-DMJRiMhd.js} +1 -1
- package/dist/dashboard/assets/{journeyDiagram-VCZTEJTY-CU4EYedt.js → journeyDiagram-VCZTEJTY-f8lbDQ22.js} +1 -1
- package/dist/dashboard/assets/{kaa-6HZHGXH3-D0tWzHt3.js → kaa-6HZHGXH3-C4yr2X6j.js} +1 -1
- package/dist/dashboard/assets/{kab-KAB-ZGHBKWFO-BC-g4xJU.js → kab-KAB-ZGHBKWFO-BtwhZ5Ak.js} +1 -1
- package/dist/dashboard/assets/{kanban-definition-6JOO6SKY-BxXqVmz1.js → kanban-definition-6JOO6SKY-BJtF1llZ.js} +1 -1
- package/dist/dashboard/assets/{kk-KZ-P5N5QNE5-TLB3Lxri.js → kk-KZ-P5N5QNE5-BiS5ISFw.js} +1 -1
- package/dist/dashboard/assets/{km-KH-HSX4SM5Z-DCh7cRAS.js → km-KH-HSX4SM5Z-CJcAjj0D.js} +1 -1
- package/dist/dashboard/assets/{ko-KR-MTYHY66A-BPIl5ido.js → ko-KR-MTYHY66A-yw6XRj7m.js} +1 -1
- package/dist/dashboard/assets/{ku-TR-6OUDTVRD-TUpeN1Tm.js → ku-TR-6OUDTVRD-nAwdHGyN.js} +1 -1
- package/dist/dashboard/assets/{layout-CyrgfqIp.js → layout-guqP2e-e.js} +1 -1
- package/dist/dashboard/assets/linear-W2_Ct9N6.js +1 -0
- package/dist/dashboard/assets/{lt-LT-XHIRWOB4-BRKyR_Xw.js → lt-LT-XHIRWOB4-D7h1NJrv.js} +1 -1
- package/dist/dashboard/assets/{lv-LV-5QDEKY6T-BANbTe4s.js → lv-LV-5QDEKY6T-DJfUJgRc.js} +1 -1
- package/dist/dashboard/assets/{min-lcwVZhZ7.js → min-BlLHklQU.js} +1 -1
- package/dist/dashboard/assets/{mindmap-definition-QFDTVHPH-fVIbdlXp.js → mindmap-definition-QFDTVHPH-Ch2AO4mc.js} +1 -1
- package/dist/dashboard/assets/{mr-IN-CRQNXWMA-DLFutdXk.js → mr-IN-CRQNXWMA-BV3znx0p.js} +1 -1
- package/dist/dashboard/assets/{my-MM-5M5IBNSE-CGWrcNBC.js → my-MM-5M5IBNSE-IjUN-e5U.js} +1 -1
- package/dist/dashboard/assets/{nb-NO-T6EIAALU-CGRDupuc.js → nb-NO-T6EIAALU-MMsvbc2a.js} +1 -1
- package/dist/dashboard/assets/{nl-NL-IS3SIHDZ-BKwBfrzp.js → nl-NL-IS3SIHDZ-ByYTJGOK.js} +1 -1
- package/dist/dashboard/assets/{nn-NO-6E72VCQL-DDQkGe44.js → nn-NO-6E72VCQL-Bgbgzvhm.js} +1 -1
- package/dist/dashboard/assets/{oc-FR-POXYY2M6-DufeHCWh.js → oc-FR-POXYY2M6-BMBbvfQp.js} +1 -1
- package/dist/dashboard/assets/{pa-IN-N4M65BXN-BUzelJDX.js → pa-IN-N4M65BXN-CgcUC9Zd.js} +1 -1
- package/dist/dashboard/assets/{percentages-BXMCSKIN-FxAvjywS.js → percentages-BXMCSKIN-AuedyVVS.js} +7 -7
- package/dist/dashboard/assets/{pica-Cek5bFnr.js → pica-DxO5y0j_.js} +1 -1
- package/dist/dashboard/assets/{pieDiagram-DEJITSTG-PgIrKPnB.js → pieDiagram-DEJITSTG-q-J8tI3B.js} +1 -1
- package/dist/dashboard/assets/{pl-PL-T2D74RX3-Bd-rxZs3.js → pl-PL-T2D74RX3-BaZSYTKJ.js} +1 -1
- package/dist/dashboard/assets/{pt-BR-5N22H2LF-D0QJGoo5.js → pt-BR-5N22H2LF-DSPF7aLm.js} +1 -1
- package/dist/dashboard/assets/{pt-PT-UZXXM6DQ-DjumltMq.js → pt-PT-UZXXM6DQ-aoPTHC3m.js} +1 -1
- package/dist/dashboard/assets/{quadrantDiagram-34T5L4WZ-C30tZOBh.js → quadrantDiagram-34T5L4WZ-CGbfFson.js} +1 -1
- package/dist/dashboard/assets/{requirementDiagram-MS252O5E-D3vhi-ZB.js → requirementDiagram-MS252O5E-ThxVmoCe.js} +1 -1
- package/dist/dashboard/assets/{ro-RO-JPDTUUEW-DmEo8cEd.js → ro-RO-JPDTUUEW-YfCwiIS2.js} +1 -1
- package/dist/dashboard/assets/{ru-RU-B4JR7IUQ-ZHCu1nBu.js → ru-RU-B4JR7IUQ-zIVsVhsz.js} +1 -1
- package/dist/dashboard/assets/{sankeyDiagram-XADWPNL6-Cmbs-PxO.js → sankeyDiagram-XADWPNL6-BvEv917s.js} +1 -1
- package/dist/dashboard/assets/{sequenceDiagram-FGHM5R23-DlBqk4uQ.js → sequenceDiagram-FGHM5R23-JrhjN3MG.js} +1 -1
- package/dist/dashboard/assets/{si-LK-N5RQ5JYF-iuqtpRqI.js → si-LK-N5RQ5JYF-CegSAwip.js} +1 -1
- package/dist/dashboard/assets/{sk-SK-C5VTKIMK-BWFUWdaQ.js → sk-SK-C5VTKIMK-C_K-Uoai.js} +1 -1
- package/dist/dashboard/assets/{sl-SI-NN7IZMDC-irYTfiq_.js → sl-SI-NN7IZMDC-DHGXOoZl.js} +1 -1
- package/dist/dashboard/assets/{stateDiagram-FHFEXIEX-B6T9ib8G.js → stateDiagram-FHFEXIEX-BzOtZESp.js} +1 -1
- package/dist/dashboard/assets/stateDiagram-v2-QKLJ7IA2-CjcHIbj7.js +1 -0
- package/dist/dashboard/assets/{subset-shared.chunk-LTgWgeng.js → subset-shared.chunk-BWfXaC19.js} +1 -1
- package/dist/dashboard/assets/{subset-worker.chunk-CT_2iDuG.js → subset-worker.chunk-DHcqLDUZ.js} +1 -1
- package/dist/dashboard/assets/{sv-SE-XGPEYMSR-BvDzjArd.js → sv-SE-XGPEYMSR-BoNob2y3.js} +1 -1
- package/dist/dashboard/assets/{ta-IN-2NMHFXQM-DdsS_3Yq.js → ta-IN-2NMHFXQM-C8UHJYct.js} +1 -1
- package/dist/dashboard/assets/{th-TH-HPSO5L25-Duadkok3.js → th-TH-HPSO5L25-D7wP1iSi.js} +1 -1
- package/dist/dashboard/assets/{timeline-definition-GMOUNBTQ-CHTQqVpC.js → timeline-definition-GMOUNBTQ-Gwb0w7bX.js} +1 -1
- package/dist/dashboard/assets/{tr-TR-DEFEU3FU-CTnPpl_3.js → tr-TR-DEFEU3FU-He51QB-L.js} +1 -1
- package/dist/dashboard/assets/{uk-UA-QMV73CPH-CAqmQ01_.js → uk-UA-QMV73CPH-Blg5n9CR.js} +1 -1
- package/dist/dashboard/assets/{vennDiagram-DHZGUBPP-tWl34rwo.js → vennDiagram-DHZGUBPP-y2S0dZjp.js} +1 -1
- package/dist/dashboard/assets/{vi-VN-M7AON7JQ-Cz7FDG8R.js → vi-VN-M7AON7JQ-2z-4xcM3.js} +1 -1
- package/dist/dashboard/assets/{wardley-RL74JXVD-UjdnBcpJ.js → wardley-RL74JXVD-BNThyuCt.js} +1 -1
- package/dist/dashboard/assets/{wardleyDiagram-NUSXRM2D-KhVWSzPf.js → wardleyDiagram-NUSXRM2D-Sljri5hz.js} +1 -1
- package/dist/dashboard/assets/{xychartDiagram-5P7HB3ND-SwtVQYTW.js → xychartDiagram-5P7HB3ND-BIFYd4_d.js} +1 -1
- package/dist/dashboard/assets/{zh-CN-LNUGB5OW-B7cbFS35.js → zh-CN-LNUGB5OW-DZ8sfmlq.js} +1 -1
- package/dist/dashboard/assets/{zh-HK-E62DVLB3-CLi9BFmp.js → zh-HK-E62DVLB3-Zvqwoloz.js} +1 -1
- package/dist/dashboard/assets/{zh-TW-RAJ6MFWO-XAcgJHay.js → zh-TW-RAJ6MFWO-Ck_uDtMQ.js} +1 -1
- package/dist/dashboard/index.html +2 -2
- package/dist/index.js +931 -483
- package/package.json +1 -1
- package/dist/dashboard/assets/channel-C5p1t-nJ.js +0 -1
- package/dist/dashboard/assets/classDiagram-6PBFFD2Q-sTJpbWV4.js +0 -1
- package/dist/dashboard/assets/classDiagram-v2-HSJHXN6E-sTJpbWV4.js +0 -1
- package/dist/dashboard/assets/clone-DTslXBzp.js +0 -1
- package/dist/dashboard/assets/index-C9VT2u9E.js +0 -480
- package/dist/dashboard/assets/index-DoFaQKCx.css +0 -1
- package/dist/dashboard/assets/linear-B6cMUkoc.js +0 -1
- package/dist/dashboard/assets/stateDiagram-v2-QKLJ7IA2-CN0hAOp7.js +0 -1
package/dist/index.js
CHANGED
|
@@ -18458,11 +18458,11 @@ var init_install_claude_md = __esm({
|
|
|
18458
18458
|
import { existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync7, writeFileSync as writeFileSync7 } from "fs";
|
|
18459
18459
|
import { dirname as dirname4, join as join6 } from "path";
|
|
18460
18460
|
function applyClaudeAutoMemory(projectRoot, disable) {
|
|
18461
|
-
const
|
|
18461
|
+
const settingsPath2 = join6(projectRoot, ".claude", "settings.json");
|
|
18462
18462
|
let settings = {};
|
|
18463
|
-
if (existsSync6(
|
|
18463
|
+
if (existsSync6(settingsPath2)) {
|
|
18464
18464
|
try {
|
|
18465
|
-
const parsed = JSON.parse(readFileSync7(
|
|
18465
|
+
const parsed = JSON.parse(readFileSync7(settingsPath2, "utf-8"));
|
|
18466
18466
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
18467
18467
|
settings = parsed;
|
|
18468
18468
|
}
|
|
@@ -18473,8 +18473,8 @@ function applyClaudeAutoMemory(projectRoot, disable) {
|
|
|
18473
18473
|
const desired = !disable;
|
|
18474
18474
|
if (settings.autoMemoryEnabled === desired) return false;
|
|
18475
18475
|
settings.autoMemoryEnabled = desired;
|
|
18476
|
-
mkdirSync4(dirname4(
|
|
18477
|
-
writeFileSync7(
|
|
18476
|
+
mkdirSync4(dirname4(settingsPath2), { recursive: true });
|
|
18477
|
+
writeFileSync7(settingsPath2, JSON.stringify(settings, null, 2) + "\n", "utf-8");
|
|
18478
18478
|
return true;
|
|
18479
18479
|
}
|
|
18480
18480
|
var init_claude_settings = __esm({
|
|
@@ -22458,12 +22458,12 @@ async function resolvePlatforms(projectRoot, raw) {
|
|
|
22458
22458
|
return platforms;
|
|
22459
22459
|
}
|
|
22460
22460
|
function ensureClaudeHooks(projectRoot) {
|
|
22461
|
-
const
|
|
22461
|
+
const settingsPath2 = join9(projectRoot, ".claude", "settings.json");
|
|
22462
22462
|
const result = { added: [], migrated: false };
|
|
22463
22463
|
let settings = {};
|
|
22464
|
-
if (existsSync9(
|
|
22464
|
+
if (existsSync9(settingsPath2)) {
|
|
22465
22465
|
try {
|
|
22466
|
-
settings = JSON.parse(readFileSync10(
|
|
22466
|
+
settings = JSON.parse(readFileSync10(settingsPath2, "utf-8"));
|
|
22467
22467
|
} catch {
|
|
22468
22468
|
settings = {};
|
|
22469
22469
|
}
|
|
@@ -22497,7 +22497,7 @@ function ensureClaudeHooks(projectRoot) {
|
|
|
22497
22497
|
}
|
|
22498
22498
|
}
|
|
22499
22499
|
mkdirSync6(join9(projectRoot, ".claude"), { recursive: true });
|
|
22500
|
-
writeFileSync9(
|
|
22500
|
+
writeFileSync9(settingsPath2, JSON.stringify(settings, null, 2) + "\n", "utf-8");
|
|
22501
22501
|
return result;
|
|
22502
22502
|
}
|
|
22503
22503
|
function findPackageFile(subdir, filename) {
|
|
@@ -34672,6 +34672,170 @@ var init_migration_runner = __esm({
|
|
|
34672
34672
|
}
|
|
34673
34673
|
});
|
|
34674
34674
|
|
|
34675
|
+
// src/lib/sleep-consolidation.ts
|
|
34676
|
+
function sleepinessLevel(debt) {
|
|
34677
|
+
if (debt <= 3) return "Alert";
|
|
34678
|
+
if (debt <= 6) return "Drowsy";
|
|
34679
|
+
if (debt <= 9) return "Sleepy";
|
|
34680
|
+
return "Must Sleep";
|
|
34681
|
+
}
|
|
34682
|
+
function sleepinessRange(debt) {
|
|
34683
|
+
if (debt <= 3) return "0-3";
|
|
34684
|
+
if (debt <= 6) return "4-6";
|
|
34685
|
+
if (debt <= 9) return "7-9";
|
|
34686
|
+
return "10+";
|
|
34687
|
+
}
|
|
34688
|
+
function recomputeDebt(sessions) {
|
|
34689
|
+
return sessions.reduce((sum, s) => sum + (s.score ?? 0), 0);
|
|
34690
|
+
}
|
|
34691
|
+
function depthFromDebt(debt) {
|
|
34692
|
+
if (debt <= 3) return "light";
|
|
34693
|
+
if (debt <= 9) return "standard";
|
|
34694
|
+
return "deep";
|
|
34695
|
+
}
|
|
34696
|
+
function consolidationDepth(debt, opts = {}) {
|
|
34697
|
+
const base = depthFromDebt(debt);
|
|
34698
|
+
if (opts.userRequestedDeep) {
|
|
34699
|
+
return { depth: "deep", reason: "user requested deep consolidation", source: "user" };
|
|
34700
|
+
}
|
|
34701
|
+
const bump = Math.max(0, Math.min(2, opts.agentBump ?? 0));
|
|
34702
|
+
if (bump > 0) {
|
|
34703
|
+
const baseIdx = DEPTH_ORDER.indexOf(base);
|
|
34704
|
+
const idx = Math.min(DEPTH_ORDER.length - 1, baseIdx + bump);
|
|
34705
|
+
return {
|
|
34706
|
+
depth: DEPTH_ORDER[idx],
|
|
34707
|
+
reason: `agent bumped depth by ${bump} tier(s) from ${base}`,
|
|
34708
|
+
source: "agent"
|
|
34709
|
+
};
|
|
34710
|
+
}
|
|
34711
|
+
return { depth: base, reason: `debt ${debt} \u2192 ${base}`, source: "debt" };
|
|
34712
|
+
}
|
|
34713
|
+
function isDestructiveAllowed(depth) {
|
|
34714
|
+
return depth === "deep";
|
|
34715
|
+
}
|
|
34716
|
+
function applyConsolidation(state, epoch) {
|
|
34717
|
+
const next = cloneState(state);
|
|
34718
|
+
let sessionsProcessed = 0;
|
|
34719
|
+
let bookmarksProcessed = 0;
|
|
34720
|
+
let processedSessionIds = [];
|
|
34721
|
+
if (epoch) {
|
|
34722
|
+
const processedSessions = next.sessions.filter((s) => !s.stopped_at || s.stopped_at <= epoch);
|
|
34723
|
+
sessionsProcessed = processedSessions.length;
|
|
34724
|
+
processedSessionIds = processedSessions.map((s) => s.session_id);
|
|
34725
|
+
bookmarksProcessed = next.bookmarks.filter((b) => b.created_at <= epoch).length;
|
|
34726
|
+
next.sessions = next.sessions.filter((s) => {
|
|
34727
|
+
if (!s.stopped_at) return false;
|
|
34728
|
+
return s.stopped_at > epoch;
|
|
34729
|
+
});
|
|
34730
|
+
next.bookmarks = next.bookmarks.filter((b) => b.created_at > epoch);
|
|
34731
|
+
next.dashboard_changes = next.dashboard_changes.filter((c) => c.timestamp > epoch);
|
|
34732
|
+
next.debt = recomputeDebt(next.sessions);
|
|
34733
|
+
} else {
|
|
34734
|
+
sessionsProcessed = next.sessions.length;
|
|
34735
|
+
processedSessionIds = next.sessions.map((s) => s.session_id);
|
|
34736
|
+
bookmarksProcessed = next.bookmarks.length;
|
|
34737
|
+
next.sessions = [];
|
|
34738
|
+
next.bookmarks = [];
|
|
34739
|
+
next.dashboard_changes = [];
|
|
34740
|
+
next.debt = 0;
|
|
34741
|
+
}
|
|
34742
|
+
next.triggers = next.triggers.filter((t) => t.fired_count < t.max_fires);
|
|
34743
|
+
return { state: next, sessionsProcessed, bookmarksProcessed, processedSessionIds };
|
|
34744
|
+
}
|
|
34745
|
+
function upsertSessionOnStop(state, input2) {
|
|
34746
|
+
const next = cloneState(state);
|
|
34747
|
+
const existing = next.sessions.findIndex((s) => s.session_id === input2.session_id);
|
|
34748
|
+
if (existing >= 0) {
|
|
34749
|
+
const oldScore = next.sessions[existing].score ?? 0;
|
|
34750
|
+
next.debt = Math.max(0, next.debt - oldScore);
|
|
34751
|
+
const existingSlugs = next.sessions[existing].task_slugs ?? [];
|
|
34752
|
+
next.sessions[existing] = {
|
|
34753
|
+
...next.sessions[existing],
|
|
34754
|
+
transcript_path: input2.transcript_path,
|
|
34755
|
+
stopped_at: input2.stopped_at,
|
|
34756
|
+
last_assistant_message: input2.last_assistant_message,
|
|
34757
|
+
change_count: input2.change_count,
|
|
34758
|
+
tool_count: input2.tool_count,
|
|
34759
|
+
score: input2.score,
|
|
34760
|
+
task_slugs: [.../* @__PURE__ */ new Set([...existingSlugs, ...input2.task_slugs])]
|
|
34761
|
+
};
|
|
34762
|
+
next.debt += input2.score;
|
|
34763
|
+
} else {
|
|
34764
|
+
next.sessions.unshift({
|
|
34765
|
+
session_id: input2.session_id,
|
|
34766
|
+
transcript_path: input2.transcript_path,
|
|
34767
|
+
stopped_at: input2.stopped_at,
|
|
34768
|
+
last_assistant_message: input2.last_assistant_message,
|
|
34769
|
+
change_count: input2.change_count,
|
|
34770
|
+
tool_count: input2.tool_count,
|
|
34771
|
+
score: input2.score,
|
|
34772
|
+
task_slugs: input2.task_slugs
|
|
34773
|
+
});
|
|
34774
|
+
next.debt += input2.score;
|
|
34775
|
+
next.sessions_since_last_sleep = (next.sessions_since_last_sleep || 0) + 1;
|
|
34776
|
+
}
|
|
34777
|
+
return next;
|
|
34778
|
+
}
|
|
34779
|
+
function appendCompactionRecord(state, record) {
|
|
34780
|
+
const next = cloneState(state);
|
|
34781
|
+
next.compaction_log.unshift(record);
|
|
34782
|
+
if (next.compaction_log.length > COMPACTION_LOG_CAP) {
|
|
34783
|
+
next.compaction_log = next.compaction_log.slice(0, COMPACTION_LOG_CAP);
|
|
34784
|
+
}
|
|
34785
|
+
return next;
|
|
34786
|
+
}
|
|
34787
|
+
function validateSleepAdd(scoreStr, desc) {
|
|
34788
|
+
const score = parseInt(scoreStr, 10);
|
|
34789
|
+
if (isNaN(score) || score < 1 || score > 3) {
|
|
34790
|
+
return { ok: false, error: "Score must be 1, 2, or 3." };
|
|
34791
|
+
}
|
|
34792
|
+
if (!desc.trim()) {
|
|
34793
|
+
return { ok: false, error: "Description is required." };
|
|
34794
|
+
}
|
|
34795
|
+
return { ok: true };
|
|
34796
|
+
}
|
|
34797
|
+
function buildHistoryEntry(prevDebt, result, summary, today2) {
|
|
34798
|
+
return {
|
|
34799
|
+
date: today2,
|
|
34800
|
+
consolidated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
34801
|
+
summary: summary.trim(),
|
|
34802
|
+
debt_before: prevDebt,
|
|
34803
|
+
debt_after: result.state.debt,
|
|
34804
|
+
sessions_processed: result.sessionsProcessed,
|
|
34805
|
+
bookmarks_processed: result.bookmarksProcessed,
|
|
34806
|
+
session_ids: result.processedSessionIds
|
|
34807
|
+
};
|
|
34808
|
+
}
|
|
34809
|
+
function finalizeSleepState(state, summary, today2) {
|
|
34810
|
+
const next = cloneState(state);
|
|
34811
|
+
next.last_sleep = today2;
|
|
34812
|
+
next.last_sleep_summary = summary.trim();
|
|
34813
|
+
next.sleep_started_at = null;
|
|
34814
|
+
next.sessions_since_last_sleep = 0;
|
|
34815
|
+
next.consolidation_depth = null;
|
|
34816
|
+
return next;
|
|
34817
|
+
}
|
|
34818
|
+
function cloneState(state) {
|
|
34819
|
+
return {
|
|
34820
|
+
...state,
|
|
34821
|
+
sessions: state.sessions.map((s) => ({ ...s, task_slugs: [...s.task_slugs ?? []] })),
|
|
34822
|
+
bookmarks: state.bookmarks.map((b) => ({ ...b })),
|
|
34823
|
+
triggers: state.triggers.map((t) => ({ ...t })),
|
|
34824
|
+
knowledge_access: { ...state.knowledge_access },
|
|
34825
|
+
dashboard_changes: state.dashboard_changes.map((c) => ({ ...c })),
|
|
34826
|
+
compaction_log: state.compaction_log.map((c) => ({ ...c })),
|
|
34827
|
+
pendingMigrationNotices: [...state.pendingMigrationNotices]
|
|
34828
|
+
};
|
|
34829
|
+
}
|
|
34830
|
+
var DEPTH_ORDER, COMPACTION_LOG_CAP;
|
|
34831
|
+
var init_sleep_consolidation = __esm({
|
|
34832
|
+
"src/lib/sleep-consolidation.ts"() {
|
|
34833
|
+
"use strict";
|
|
34834
|
+
DEPTH_ORDER = ["light", "standard", "deep"];
|
|
34835
|
+
COMPACTION_LOG_CAP = 20;
|
|
34836
|
+
}
|
|
34837
|
+
});
|
|
34838
|
+
|
|
34675
34839
|
// src/cli/commands/sleep.ts
|
|
34676
34840
|
import { existsSync as existsSync37 } from "fs";
|
|
34677
34841
|
import { join as join37, dirname as dirname18 } from "path";
|
|
@@ -34695,6 +34859,7 @@ function freshDefaults() {
|
|
|
34695
34859
|
dashboard_changes: [],
|
|
34696
34860
|
compaction_log: [],
|
|
34697
34861
|
recall_mode: "haiku",
|
|
34862
|
+
consolidation_depth: null,
|
|
34698
34863
|
pendingMigrationNotices: []
|
|
34699
34864
|
};
|
|
34700
34865
|
}
|
|
@@ -34757,25 +34922,13 @@ function bumpKnowledgeAccess(state, slug) {
|
|
|
34757
34922
|
state.knowledge_access[slug].last_accessed = today();
|
|
34758
34923
|
state.knowledge_access[slug].count++;
|
|
34759
34924
|
}
|
|
34760
|
-
function getSleepinessLevel(debt) {
|
|
34761
|
-
if (debt <= 3) return "Alert";
|
|
34762
|
-
if (debt <= 6) return "Drowsy";
|
|
34763
|
-
if (debt <= 9) return "Sleepy";
|
|
34764
|
-
return "Must Sleep";
|
|
34765
|
-
}
|
|
34766
|
-
function getSleepinessRange(debt) {
|
|
34767
|
-
if (debt <= 3) return "0-3";
|
|
34768
|
-
if (debt <= 6) return "4-6";
|
|
34769
|
-
if (debt <= 9) return "7-9";
|
|
34770
|
-
return "10+";
|
|
34771
|
-
}
|
|
34772
34925
|
function registerSleepCommand(program2) {
|
|
34773
34926
|
const sleep2 = program2.command("sleep").description("Track sleep debt and consolidation state");
|
|
34774
34927
|
sleep2.command("status").description("Show current sleep debt level and history").action(() => {
|
|
34775
34928
|
const root = ensureContextRoot();
|
|
34776
34929
|
const state = readSleepState(root);
|
|
34777
|
-
const level =
|
|
34778
|
-
const range =
|
|
34930
|
+
const level = sleepinessLevel(state.debt);
|
|
34931
|
+
const range = sleepinessRange(state.debt);
|
|
34779
34932
|
console.log(header("Sleep State"));
|
|
34780
34933
|
console.log(` Debt: ${source_default.bold(String(state.debt))} ${source_default.dim(`(${range})`)} ${source_default.magentaBright(level)}`);
|
|
34781
34934
|
console.log(` Last sleep: ${state.last_sleep ? source_default.white(state.last_sleep) : source_default.dim("never")}`);
|
|
@@ -34803,16 +34956,13 @@ function registerSleepCommand(program2) {
|
|
|
34803
34956
|
}
|
|
34804
34957
|
});
|
|
34805
34958
|
sleep2.command("add").argument("<score>", "Debt score to add (1-3)").argument("<description...>", "Description of what happened").description("Record a debt-accumulating action").action((scoreStr, descParts) => {
|
|
34806
|
-
const score = parseInt(scoreStr, 10);
|
|
34807
|
-
if (isNaN(score) || score < 1 || score > 3) {
|
|
34808
|
-
error("Score must be 1, 2, or 3.");
|
|
34809
|
-
return;
|
|
34810
|
-
}
|
|
34811
34959
|
const description = descParts.join(" ");
|
|
34812
|
-
|
|
34813
|
-
|
|
34960
|
+
const valid = validateSleepAdd(scoreStr, description);
|
|
34961
|
+
if (!valid.ok) {
|
|
34962
|
+
error(valid.error);
|
|
34814
34963
|
return;
|
|
34815
34964
|
}
|
|
34965
|
+
const score = parseInt(scoreStr, 10);
|
|
34816
34966
|
const root = ensureContextRoot();
|
|
34817
34967
|
const state = readSleepState(root);
|
|
34818
34968
|
state.sessions.unshift({
|
|
@@ -34827,7 +34977,7 @@ function registerSleepCommand(program2) {
|
|
|
34827
34977
|
});
|
|
34828
34978
|
state.debt += score;
|
|
34829
34979
|
writeSleepState(root, state);
|
|
34830
|
-
const level =
|
|
34980
|
+
const level = sleepinessLevel(state.debt);
|
|
34831
34981
|
success(`Sleep debt: ${state.debt} (${level})`);
|
|
34832
34982
|
if (state.debt >= 10) {
|
|
34833
34983
|
warn("Must sleep! Debt is 10+. Consolidation needed.");
|
|
@@ -34835,12 +34985,14 @@ function registerSleepCommand(program2) {
|
|
|
34835
34985
|
info("Getting sleepy. Consider consolidating soon.");
|
|
34836
34986
|
}
|
|
34837
34987
|
});
|
|
34838
|
-
sleep2.command("start").description("Mark beginning of consolidation (sets epoch for safe clearing)").action(() => {
|
|
34988
|
+
sleep2.command("start").description("Mark beginning of consolidation (sets epoch for safe clearing)").option("--deep", "Force a deep consolidation (authorizes destructive knowledge ops)").action((opts) => {
|
|
34839
34989
|
const root = ensureContextRoot();
|
|
34840
34990
|
const state = readSleepState(root);
|
|
34841
34991
|
if (state.sleep_started_at) {
|
|
34842
34992
|
warn(`Consolidation already in progress (started ${state.sleep_started_at}). Overwriting epoch.`);
|
|
34843
34993
|
}
|
|
34994
|
+
const decision = consolidationDepth(state.debt, { userRequestedDeep: !!opts.deep });
|
|
34995
|
+
state.consolidation_depth = decision.depth;
|
|
34844
34996
|
state.pendingMigrationNotices = [];
|
|
34845
34997
|
const projectRoot = dirname18(root);
|
|
34846
34998
|
const config = readSetupConfig(projectRoot);
|
|
@@ -34864,6 +35016,10 @@ function registerSleepCommand(program2) {
|
|
|
34864
35016
|
state.sleep_started_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
34865
35017
|
writeSleepState(root, state);
|
|
34866
35018
|
success(`Consolidation epoch set: ${state.sleep_started_at}`);
|
|
35019
|
+
info(`Consolidation depth: ${decision.depth} (source: ${decision.source}) \u2014 ${decision.reason}`);
|
|
35020
|
+
if (decision.depth !== "deep") {
|
|
35021
|
+
info("Light/standard consolidation: do NOT merge/summarize-replace/delete knowledge \u2014 flag candidates in the report instead.");
|
|
35022
|
+
}
|
|
34867
35023
|
});
|
|
34868
35024
|
sleep2.command("done").argument("<summary...>", "Summary of what was consolidated").description("Mark consolidation complete, reset debt").action(async (summaryParts) => {
|
|
34869
35025
|
const summary = summaryParts.join(" ");
|
|
@@ -34875,52 +35031,17 @@ function registerSleepCommand(program2) {
|
|
|
34875
35031
|
const state = readSleepState(root);
|
|
34876
35032
|
const previousDebt = state.debt;
|
|
34877
35033
|
const epoch = state.sleep_started_at;
|
|
34878
|
-
|
|
34879
|
-
|
|
34880
|
-
let processedSessionIds = [];
|
|
34881
|
-
if (epoch) {
|
|
34882
|
-
const processedSessions = state.sessions.filter((s) => !s.stopped_at || s.stopped_at <= epoch);
|
|
34883
|
-
sessionsProcessed = processedSessions.length;
|
|
34884
|
-
processedSessionIds = processedSessions.map((s) => s.session_id);
|
|
34885
|
-
bookmarksProcessed = state.bookmarks.filter((b) => b.created_at <= epoch).length;
|
|
34886
|
-
state.sessions = state.sessions.filter((s) => {
|
|
34887
|
-
if (!s.stopped_at) return false;
|
|
34888
|
-
return s.stopped_at > epoch;
|
|
34889
|
-
});
|
|
34890
|
-
state.bookmarks = state.bookmarks.filter((b) => b.created_at > epoch);
|
|
34891
|
-
state.dashboard_changes = state.dashboard_changes.filter((c) => c.timestamp > epoch);
|
|
34892
|
-
state.debt = state.sessions.reduce((sum, s) => sum + (s.score ?? 0), 0);
|
|
34893
|
-
} else {
|
|
34894
|
-
sessionsProcessed = state.sessions.length;
|
|
34895
|
-
processedSessionIds = state.sessions.map((s) => s.session_id);
|
|
34896
|
-
bookmarksProcessed = state.bookmarks.length;
|
|
34897
|
-
state.sessions = [];
|
|
34898
|
-
state.bookmarks = [];
|
|
34899
|
-
state.dashboard_changes = [];
|
|
34900
|
-
state.debt = 0;
|
|
34901
|
-
}
|
|
34902
|
-
state.triggers = state.triggers.filter((t) => t.fired_count < t.max_fires);
|
|
35034
|
+
const result = applyConsolidation(state, epoch);
|
|
35035
|
+
const today_ = today();
|
|
34903
35036
|
const history = readSleepHistory(root);
|
|
34904
|
-
history.unshift(
|
|
34905
|
-
date: today(),
|
|
34906
|
-
consolidated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
34907
|
-
summary: summary.trim(),
|
|
34908
|
-
debt_before: previousDebt,
|
|
34909
|
-
debt_after: state.debt,
|
|
34910
|
-
sessions_processed: sessionsProcessed,
|
|
34911
|
-
bookmarks_processed: bookmarksProcessed,
|
|
34912
|
-
session_ids: processedSessionIds
|
|
34913
|
-
});
|
|
35037
|
+
history.unshift(buildHistoryEntry(previousDebt, result, summary, today_));
|
|
34914
35038
|
writeSleepHistory(root, history);
|
|
34915
|
-
|
|
34916
|
-
|
|
34917
|
-
|
|
34918
|
-
|
|
34919
|
-
writeSleepState(root, state);
|
|
34920
|
-
if (epoch && state.sessions.length > 0) {
|
|
34921
|
-
success(`Consolidation complete. Debt reduced from ${previousDebt} to ${state.debt}. ${state.sessions.length} post-epoch session(s) preserved.`);
|
|
35039
|
+
const finalState = finalizeSleepState(result.state, summary, today_);
|
|
35040
|
+
writeSleepState(root, finalState);
|
|
35041
|
+
if (epoch && finalState.sessions.length > 0) {
|
|
35042
|
+
success(`Consolidation complete. Debt reduced from ${previousDebt} to ${finalState.debt}. ${finalState.sessions.length} post-epoch session(s) preserved.`);
|
|
34922
35043
|
} else {
|
|
34923
|
-
success(`Consolidation complete. Debt reset from ${previousDebt} to ${
|
|
35044
|
+
success(`Consolidation complete. Debt reset from ${previousDebt} to ${finalState.debt}.`);
|
|
34924
35045
|
}
|
|
34925
35046
|
try {
|
|
34926
35047
|
const backend = getTaskBackend(root);
|
|
@@ -35012,6 +35133,7 @@ var init_sleep = __esm({
|
|
|
35012
35133
|
init_migration_runner();
|
|
35013
35134
|
init_setup_config();
|
|
35014
35135
|
init_manifest();
|
|
35136
|
+
init_sleep_consolidation();
|
|
35015
35137
|
}
|
|
35016
35138
|
});
|
|
35017
35139
|
|
|
@@ -37695,6 +37817,53 @@ var init_snapshot2 = __esm({
|
|
|
37695
37817
|
}
|
|
37696
37818
|
});
|
|
37697
37819
|
|
|
37820
|
+
// src/lib/salience.ts
|
|
37821
|
+
function clamp(text) {
|
|
37822
|
+
const oneLine = text.replace(/\s+/g, " ").trim();
|
|
37823
|
+
return oneLine.length <= MAX_MESSAGE_CHARS ? oneLine : oneLine.slice(0, MAX_MESSAGE_CHARS - 1) + "\u2026";
|
|
37824
|
+
}
|
|
37825
|
+
function detectSalience(distilled) {
|
|
37826
|
+
const moments = [];
|
|
37827
|
+
const seen = /* @__PURE__ */ new Set();
|
|
37828
|
+
const push = (message, salience) => {
|
|
37829
|
+
const clamped = clamp(message);
|
|
37830
|
+
if (!clamped) return;
|
|
37831
|
+
const key = `${salience}::${clamped.toLowerCase()}`;
|
|
37832
|
+
if (seen.has(key)) return;
|
|
37833
|
+
seen.add(key);
|
|
37834
|
+
moments.push({ message: clamped, salience });
|
|
37835
|
+
};
|
|
37836
|
+
for (const msg of distilled.userMessages) {
|
|
37837
|
+
if (CORRECTION_RE.test(msg)) {
|
|
37838
|
+
push(`User correction: ${msg}`, 2);
|
|
37839
|
+
}
|
|
37840
|
+
}
|
|
37841
|
+
if (distilled.errors.length > 0 && distilled.codeChanges.length > 0) {
|
|
37842
|
+
const firstError = distilled.errors[0];
|
|
37843
|
+
push(`Error resolved by code change: ${firstError}`, 1);
|
|
37844
|
+
}
|
|
37845
|
+
const decisionSources = [
|
|
37846
|
+
...distilled.agentDecisions.filter((d) => !d.startsWith("[thinking]")),
|
|
37847
|
+
...distilled.userMessages
|
|
37848
|
+
];
|
|
37849
|
+
for (const src of decisionSources) {
|
|
37850
|
+
if (DECISION_RE.test(src)) {
|
|
37851
|
+
push(`Decision: ${src}`, 2);
|
|
37852
|
+
}
|
|
37853
|
+
}
|
|
37854
|
+
return moments.slice(0, MAX_MOMENTS);
|
|
37855
|
+
}
|
|
37856
|
+
var CORRECTION_RE, DECISION_RE, MAX_MOMENTS, MAX_MESSAGE_CHARS;
|
|
37857
|
+
var init_salience = __esm({
|
|
37858
|
+
"src/lib/salience.ts"() {
|
|
37859
|
+
"use strict";
|
|
37860
|
+
CORRECTION_RE = /\b(no|actually|wrong|instead|hayır|yanlış|değil)\b/i;
|
|
37861
|
+
DECISION_RE = /\b(decided|chose|switched to|will use|karar|seçtik)\b/i;
|
|
37862
|
+
MAX_MOMENTS = 5;
|
|
37863
|
+
MAX_MESSAGE_CHARS = 200;
|
|
37864
|
+
}
|
|
37865
|
+
});
|
|
37866
|
+
|
|
37698
37867
|
// src/cli/commands/transcript.ts
|
|
37699
37868
|
import { readFileSync as readFileSync35, existsSync as existsSync46, statSync as statSync6 } from "fs";
|
|
37700
37869
|
function distillTranscript(transcriptPath, sinceTimestamp) {
|
|
@@ -38889,53 +39058,6 @@ var init_session_digest = __esm({
|
|
|
38889
39058
|
}
|
|
38890
39059
|
});
|
|
38891
39060
|
|
|
38892
|
-
// src/lib/salience.ts
|
|
38893
|
-
function clamp(text) {
|
|
38894
|
-
const oneLine = text.replace(/\s+/g, " ").trim();
|
|
38895
|
-
return oneLine.length <= MAX_MESSAGE_CHARS ? oneLine : oneLine.slice(0, MAX_MESSAGE_CHARS - 1) + "\u2026";
|
|
38896
|
-
}
|
|
38897
|
-
function detectSalience(distilled) {
|
|
38898
|
-
const moments = [];
|
|
38899
|
-
const seen = /* @__PURE__ */ new Set();
|
|
38900
|
-
const push = (message, salience) => {
|
|
38901
|
-
const clamped = clamp(message);
|
|
38902
|
-
if (!clamped) return;
|
|
38903
|
-
const key = `${salience}::${clamped.toLowerCase()}`;
|
|
38904
|
-
if (seen.has(key)) return;
|
|
38905
|
-
seen.add(key);
|
|
38906
|
-
moments.push({ message: clamped, salience });
|
|
38907
|
-
};
|
|
38908
|
-
for (const msg of distilled.userMessages) {
|
|
38909
|
-
if (CORRECTION_RE.test(msg)) {
|
|
38910
|
-
push(`User correction: ${msg}`, 2);
|
|
38911
|
-
}
|
|
38912
|
-
}
|
|
38913
|
-
if (distilled.errors.length > 0 && distilled.codeChanges.length > 0) {
|
|
38914
|
-
const firstError = distilled.errors[0];
|
|
38915
|
-
push(`Error resolved by code change: ${firstError}`, 1);
|
|
38916
|
-
}
|
|
38917
|
-
const decisionSources = [
|
|
38918
|
-
...distilled.agentDecisions.filter((d) => !d.startsWith("[thinking]")),
|
|
38919
|
-
...distilled.userMessages
|
|
38920
|
-
];
|
|
38921
|
-
for (const src of decisionSources) {
|
|
38922
|
-
if (DECISION_RE.test(src)) {
|
|
38923
|
-
push(`Decision: ${src}`, 2);
|
|
38924
|
-
}
|
|
38925
|
-
}
|
|
38926
|
-
return moments.slice(0, MAX_MOMENTS);
|
|
38927
|
-
}
|
|
38928
|
-
var CORRECTION_RE, DECISION_RE, MAX_MOMENTS, MAX_MESSAGE_CHARS;
|
|
38929
|
-
var init_salience = __esm({
|
|
38930
|
-
"src/lib/salience.ts"() {
|
|
38931
|
-
"use strict";
|
|
38932
|
-
CORRECTION_RE = /\b(no|actually|wrong|instead|hayır|yanlış|değil)\b/i;
|
|
38933
|
-
DECISION_RE = /\b(decided|chose|switched to|will use|karar|seçtik)\b/i;
|
|
38934
|
-
MAX_MOMENTS = 5;
|
|
38935
|
-
MAX_MESSAGE_CHARS = 200;
|
|
38936
|
-
}
|
|
38937
|
-
});
|
|
38938
|
-
|
|
38939
39061
|
// src/lib/marketing/path-guards.ts
|
|
38940
39062
|
import { existsSync as existsSync49, realpathSync } from "fs";
|
|
38941
39063
|
import { basename as basename14, dirname as dirname24, resolve as resolve8, sep as sep5 } from "path";
|
|
@@ -39498,15 +39620,76 @@ function analyzeTranscript(transcriptPath) {
|
|
|
39498
39620
|
for (const m of content.matchAll(/"file_path"\s*:\s*"[^"]*_dream_context\/state\/([a-z0-9][a-z0-9-]*)\.md"/g)) {
|
|
39499
39621
|
slugs.add(m[1]);
|
|
39500
39622
|
}
|
|
39623
|
+
let userTurns = 0;
|
|
39624
|
+
let assistantChars = 0;
|
|
39625
|
+
let decisionMarkers = 0;
|
|
39626
|
+
for (const line of content.split("\n")) {
|
|
39627
|
+
const trimmed = line.trim();
|
|
39628
|
+
if (!trimmed) continue;
|
|
39629
|
+
if (DECISION_RE.test(trimmed) || CORRECTION_RE.test(trimmed)) {
|
|
39630
|
+
decisionMarkers++;
|
|
39631
|
+
}
|
|
39632
|
+
let rec;
|
|
39633
|
+
try {
|
|
39634
|
+
rec = JSON.parse(trimmed);
|
|
39635
|
+
} catch {
|
|
39636
|
+
continue;
|
|
39637
|
+
}
|
|
39638
|
+
if (!rec || typeof rec !== "object") continue;
|
|
39639
|
+
const role = recordRole(rec);
|
|
39640
|
+
if (role === "user") {
|
|
39641
|
+
userTurns++;
|
|
39642
|
+
} else if (role === "assistant") {
|
|
39643
|
+
assistantChars += sumAssistantTextChars(rec);
|
|
39644
|
+
}
|
|
39645
|
+
}
|
|
39501
39646
|
return {
|
|
39502
39647
|
changeCount: changeMatches ? changeMatches.length : 0,
|
|
39503
39648
|
toolCount: toolMatches ? toolMatches.length : 0,
|
|
39504
|
-
taskSlugs: [...slugs]
|
|
39649
|
+
taskSlugs: [...slugs],
|
|
39650
|
+
userTurns,
|
|
39651
|
+
assistantChars,
|
|
39652
|
+
decisionMarkers
|
|
39505
39653
|
};
|
|
39506
39654
|
} catch {
|
|
39507
39655
|
return ZERO_ANALYSIS;
|
|
39508
39656
|
}
|
|
39509
39657
|
}
|
|
39658
|
+
function recordRole(rec) {
|
|
39659
|
+
const r = rec;
|
|
39660
|
+
if (typeof r.role === "string") return r.role;
|
|
39661
|
+
if (r.message && typeof r.message === "object" && typeof r.message.role === "string") {
|
|
39662
|
+
return r.message.role;
|
|
39663
|
+
}
|
|
39664
|
+
return null;
|
|
39665
|
+
}
|
|
39666
|
+
function sumAssistantTextChars(rec) {
|
|
39667
|
+
const r = rec;
|
|
39668
|
+
const content = (r.message && typeof r.message === "object" ? r.message.content : void 0) ?? r.content;
|
|
39669
|
+
let total = 0;
|
|
39670
|
+
if (typeof content === "string") {
|
|
39671
|
+
return Math.min(MAX_TEXT_BLOCK_CHARS, content.length);
|
|
39672
|
+
}
|
|
39673
|
+
if (Array.isArray(content)) {
|
|
39674
|
+
for (const block of content) {
|
|
39675
|
+
if (block && typeof block === "object") {
|
|
39676
|
+
const b = block;
|
|
39677
|
+
if (b.type === "text" && typeof b.text === "string") {
|
|
39678
|
+
total += Math.min(MAX_TEXT_BLOCK_CHARS, b.text.length);
|
|
39679
|
+
}
|
|
39680
|
+
}
|
|
39681
|
+
}
|
|
39682
|
+
}
|
|
39683
|
+
return total;
|
|
39684
|
+
}
|
|
39685
|
+
function scoreFromSubstance(signals2) {
|
|
39686
|
+
let pts = 0;
|
|
39687
|
+
if (signals2.userTurns >= 6) pts++;
|
|
39688
|
+
if (signals2.assistantChars >= 6e3) pts++;
|
|
39689
|
+
if (signals2.decisionMarkers >= 1) pts++;
|
|
39690
|
+
if (signals2.taskSlugs.length >= 2) pts++;
|
|
39691
|
+
return Math.min(3, pts);
|
|
39692
|
+
}
|
|
39510
39693
|
function scoreFromChangeCount(count) {
|
|
39511
39694
|
if (count <= 0) return 0;
|
|
39512
39695
|
if (count <= 3) return 1;
|
|
@@ -39698,6 +39881,29 @@ function getConsolidationDirective(state) {
|
|
|
39698
39881
|
}
|
|
39699
39882
|
return null;
|
|
39700
39883
|
}
|
|
39884
|
+
function userPromptReminder(state) {
|
|
39885
|
+
const { debt, bookmarks, sleep_started_at } = state;
|
|
39886
|
+
if (sleep_started_at) {
|
|
39887
|
+
if (debt >= 4) {
|
|
39888
|
+
return `Consolidation already in progress (started: ${sleep_started_at}). Do NOT dispatch another sleep agent.`;
|
|
39889
|
+
}
|
|
39890
|
+
return null;
|
|
39891
|
+
}
|
|
39892
|
+
const criticalBookmarks = bookmarks.filter((b) => b.salience === 3);
|
|
39893
|
+
if (debt >= 10) {
|
|
39894
|
+
return `Sleep debt is ${debt}. CONSOLIDATION REQUIRED. Run sleep flow per SKILL.md (parallel specialist fan-out) NOW.`;
|
|
39895
|
+
}
|
|
39896
|
+
if (criticalBookmarks.length > 0) {
|
|
39897
|
+
return `${criticalBookmarks.length} critical bookmark(s) need consolidation. Run sleep flow per SKILL.md.`;
|
|
39898
|
+
}
|
|
39899
|
+
if (debt >= 7) {
|
|
39900
|
+
return `Sleep debt is ${debt}. Consolidation recommended before starting new work.`;
|
|
39901
|
+
}
|
|
39902
|
+
if (debt >= 4) {
|
|
39903
|
+
return `Sleep debt is ${debt}. After completing the current task, offer to consolidate.`;
|
|
39904
|
+
}
|
|
39905
|
+
return null;
|
|
39906
|
+
}
|
|
39701
39907
|
function resolveDashboardPort() {
|
|
39702
39908
|
const raw = process.env.DREAMCONTEXT_DASHBOARD_PORT;
|
|
39703
39909
|
if (raw) {
|
|
@@ -39760,7 +39966,11 @@ function registerHookCommand(program2) {
|
|
|
39760
39966
|
const stoppedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
39761
39967
|
const analysis = transcriptPath ? analyzeTranscript(transcriptPath) : ZERO_ANALYSIS;
|
|
39762
39968
|
const { changeCount, toolCount } = analysis;
|
|
39763
|
-
const score = Math.max(
|
|
39969
|
+
const score = Math.max(
|
|
39970
|
+
scoreFromChangeCount(changeCount),
|
|
39971
|
+
scoreFromToolCount(toolCount),
|
|
39972
|
+
scoreFromSubstance(analysis)
|
|
39973
|
+
);
|
|
39764
39974
|
for (const bookmark of state.bookmarks) {
|
|
39765
39975
|
if (!bookmark.session_id) {
|
|
39766
39976
|
bookmark.session_id = sessionId;
|
|
@@ -39769,35 +39979,18 @@ function registerHookCommand(program2) {
|
|
|
39769
39979
|
const bookmarkTaskSlugs = state.bookmarks.filter((b) => b.session_id === sessionId && b.task_slug).map((b) => b.task_slug);
|
|
39770
39980
|
const transcriptTaskSlugs = analysis.taskSlugs;
|
|
39771
39981
|
const taskSlugs = [.../* @__PURE__ */ new Set([...transcriptTaskSlugs, ...bookmarkTaskSlugs])];
|
|
39772
|
-
const
|
|
39773
|
-
|
|
39774
|
-
|
|
39775
|
-
|
|
39776
|
-
|
|
39777
|
-
|
|
39778
|
-
|
|
39779
|
-
|
|
39780
|
-
|
|
39781
|
-
|
|
39782
|
-
|
|
39783
|
-
|
|
39784
|
-
} else {
|
|
39785
|
-
state.sessions.unshift({
|
|
39786
|
-
session_id: sessionId,
|
|
39787
|
-
transcript_path: transcriptPath,
|
|
39788
|
-
stopped_at: stoppedAt,
|
|
39789
|
-
last_assistant_message: lastAssistantMessage,
|
|
39790
|
-
change_count: changeCount,
|
|
39791
|
-
tool_count: toolCount,
|
|
39792
|
-
score,
|
|
39793
|
-
task_slugs: taskSlugs
|
|
39794
|
-
});
|
|
39795
|
-
}
|
|
39796
|
-
state.debt += score;
|
|
39797
|
-
if (existing < 0) {
|
|
39798
|
-
state.sessions_since_last_sleep = (state.sessions_since_last_sleep || 0) + 1;
|
|
39799
|
-
}
|
|
39800
|
-
writeSleepState(root, state);
|
|
39982
|
+
const upsertInput = {
|
|
39983
|
+
session_id: sessionId,
|
|
39984
|
+
transcript_path: transcriptPath,
|
|
39985
|
+
stopped_at: stoppedAt,
|
|
39986
|
+
last_assistant_message: lastAssistantMessage,
|
|
39987
|
+
change_count: changeCount,
|
|
39988
|
+
tool_count: toolCount,
|
|
39989
|
+
score,
|
|
39990
|
+
task_slugs: taskSlugs
|
|
39991
|
+
};
|
|
39992
|
+
const nextState = upsertSessionOnStop(state, upsertInput);
|
|
39993
|
+
writeSleepState(root, nextState);
|
|
39801
39994
|
});
|
|
39802
39995
|
hook.command("session-start").description("Analyze previous session + output context snapshot (called by Claude Code SessionStart hook)").action(() => {
|
|
39803
39996
|
const input2 = readStdin();
|
|
@@ -39819,7 +40012,11 @@ function registerHookCommand(program2) {
|
|
|
39819
40012
|
continue;
|
|
39820
40013
|
}
|
|
39821
40014
|
const analysis = analyzeTranscript(session.transcript_path);
|
|
39822
|
-
const score = Math.max(
|
|
40015
|
+
const score = Math.max(
|
|
40016
|
+
scoreFromChangeCount(analysis.changeCount),
|
|
40017
|
+
scoreFromToolCount(analysis.toolCount),
|
|
40018
|
+
scoreFromSubstance(analysis)
|
|
40019
|
+
);
|
|
39823
40020
|
session.change_count = analysis.changeCount;
|
|
39824
40021
|
session.tool_count = analysis.toolCount;
|
|
39825
40022
|
session.score = score;
|
|
@@ -39924,23 +40121,12 @@ function registerHookCommand(program2) {
|
|
|
39924
40121
|
const root = resolveContextRoot();
|
|
39925
40122
|
if (!root) process.exit(0);
|
|
39926
40123
|
const state = readSleepState(root);
|
|
39927
|
-
const
|
|
39928
|
-
if (sleep_started_at) {
|
|
39929
|
-
if (
|
|
39930
|
-
console.log(`Consolidation already in progress (started: ${sleep_started_at}). Do NOT dispatch another sleep agent.`);
|
|
39931
|
-
}
|
|
40124
|
+
const reminder = userPromptReminder(state);
|
|
40125
|
+
if (state.sleep_started_at) {
|
|
40126
|
+
if (reminder) console.log(reminder);
|
|
39932
40127
|
return;
|
|
39933
40128
|
}
|
|
39934
|
-
|
|
39935
|
-
if (debt >= 10) {
|
|
39936
|
-
console.log(`Sleep debt is ${debt}. CONSOLIDATION REQUIRED. Run sleep flow per SKILL.md (parallel specialist fan-out) NOW.`);
|
|
39937
|
-
} else if (criticalBookmarks.length > 0) {
|
|
39938
|
-
console.log(`${criticalBookmarks.length} critical bookmark(s) need consolidation. Run sleep flow per SKILL.md.`);
|
|
39939
|
-
} else if (debt >= 7) {
|
|
39940
|
-
console.log(`Sleep debt is ${debt}. Consolidation recommended before starting new work.`);
|
|
39941
|
-
} else if (debt >= 4) {
|
|
39942
|
-
console.log(`Sleep debt is ${debt}. After completing the current task, offer to consolidate.`);
|
|
39943
|
-
}
|
|
40129
|
+
if (reminder) console.log(reminder);
|
|
39944
40130
|
try {
|
|
39945
40131
|
const stale = listStaleRecs(24);
|
|
39946
40132
|
if (stale.length > 0) {
|
|
@@ -40090,17 +40276,14 @@ function registerHookCommand(program2) {
|
|
|
40090
40276
|
if (!root) process.exit(0);
|
|
40091
40277
|
const state = readSleepState(root);
|
|
40092
40278
|
const trigger = input2 && typeof input2.trigger === "string" ? input2.trigger : "unknown";
|
|
40093
|
-
state
|
|
40279
|
+
const nextState = appendCompactionRecord(state, {
|
|
40094
40280
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
40095
40281
|
trigger,
|
|
40096
40282
|
debt_at_compaction: state.debt,
|
|
40097
40283
|
sessions_count: state.sessions.length,
|
|
40098
40284
|
bookmarks_count: state.bookmarks.length
|
|
40099
40285
|
});
|
|
40100
|
-
|
|
40101
|
-
state.compaction_log = state.compaction_log.slice(0, 20);
|
|
40102
|
-
}
|
|
40103
|
-
writeSleepState(root, state);
|
|
40286
|
+
writeSleepState(root, nextState);
|
|
40104
40287
|
try {
|
|
40105
40288
|
const sessionId = input2 && typeof input2.session_id === "string" ? input2.session_id : "";
|
|
40106
40289
|
const transcriptPath = input2 && typeof input2.transcript_path === "string" ? input2.transcript_path : "";
|
|
@@ -40129,12 +40312,14 @@ function registerHookCommand(program2) {
|
|
|
40129
40312
|
process.exit(0);
|
|
40130
40313
|
});
|
|
40131
40314
|
}
|
|
40132
|
-
var MAX_TRANSCRIPT_BYTES2, SKILL_SCORE_THRESHOLD, ZERO_ANALYSIS, JS_TS_EXTENSIONS, MAX_WALK_LEVELS, BIOME_CONFIGS, PRETTIER_CONFIGS, DEFAULT_DASHBOARD_PORT;
|
|
40315
|
+
var MAX_TRANSCRIPT_BYTES2, SKILL_SCORE_THRESHOLD, ZERO_ANALYSIS, MAX_TEXT_BLOCK_CHARS, JS_TS_EXTENSIONS, MAX_WALK_LEVELS, BIOME_CONFIGS, PRETTIER_CONFIGS, DEFAULT_DASHBOARD_PORT;
|
|
40133
40316
|
var init_hook = __esm({
|
|
40134
40317
|
"src/cli/commands/hook.ts"() {
|
|
40135
40318
|
"use strict";
|
|
40136
40319
|
init_context_path();
|
|
40137
40320
|
init_sleep();
|
|
40321
|
+
init_sleep_consolidation();
|
|
40322
|
+
init_salience();
|
|
40138
40323
|
init_transcript();
|
|
40139
40324
|
init_session_digest();
|
|
40140
40325
|
init_salience();
|
|
@@ -40151,7 +40336,15 @@ var init_hook = __esm({
|
|
|
40151
40336
|
init_install_skill();
|
|
40152
40337
|
MAX_TRANSCRIPT_BYTES2 = 50 * 1024 * 1024;
|
|
40153
40338
|
SKILL_SCORE_THRESHOLD = 1;
|
|
40154
|
-
ZERO_ANALYSIS = {
|
|
40339
|
+
ZERO_ANALYSIS = {
|
|
40340
|
+
changeCount: 0,
|
|
40341
|
+
toolCount: 0,
|
|
40342
|
+
taskSlugs: [],
|
|
40343
|
+
userTurns: 0,
|
|
40344
|
+
assistantChars: 0,
|
|
40345
|
+
decisionMarkers: 0
|
|
40346
|
+
};
|
|
40347
|
+
MAX_TEXT_BLOCK_CHARS = 2e4;
|
|
40155
40348
|
JS_TS_EXTENSIONS = /* @__PURE__ */ new Set([".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs", ".mts", ".cts"]);
|
|
40156
40349
|
MAX_WALK_LEVELS = 10;
|
|
40157
40350
|
BIOME_CONFIGS = ["biome.json", "biome.jsonc"];
|
|
@@ -41091,8 +41284,8 @@ async function handleCoreGet(_req, res, params, contextRoot) {
|
|
|
41091
41284
|
return;
|
|
41092
41285
|
}
|
|
41093
41286
|
if (filename.endsWith(".json")) {
|
|
41094
|
-
const { readFileSync:
|
|
41095
|
-
const raw2 =
|
|
41287
|
+
const { readFileSync: readFileSync67 } = await import("fs");
|
|
41288
|
+
const raw2 = readFileSync67(filePath, "utf-8");
|
|
41096
41289
|
try {
|
|
41097
41290
|
const data = JSON.parse(raw2);
|
|
41098
41291
|
sendJson(res, 200, { filename, type: "json", data });
|
|
@@ -41126,8 +41319,8 @@ async function handleCoreGet(_req, res, params, contextRoot) {
|
|
|
41126
41319
|
});
|
|
41127
41320
|
return;
|
|
41128
41321
|
}
|
|
41129
|
-
const { readFileSync:
|
|
41130
|
-
const raw =
|
|
41322
|
+
const { readFileSync: readFileSync66 } = await import("fs");
|
|
41323
|
+
const raw = readFileSync66(filePath, "utf-8");
|
|
41131
41324
|
sendJson(res, 200, { filename, type: "text", content: raw });
|
|
41132
41325
|
}
|
|
41133
41326
|
async function handleCoreUpdate(req, res, params, contextRoot) {
|
|
@@ -41177,8 +41370,8 @@ async function handleCoreUpdate(req, res, params, contextRoot) {
|
|
|
41177
41370
|
return;
|
|
41178
41371
|
}
|
|
41179
41372
|
changedParts.push("content");
|
|
41180
|
-
const { writeFileSync:
|
|
41181
|
-
|
|
41373
|
+
const { writeFileSync: writeFileSync45 } = await import("fs");
|
|
41374
|
+
writeFileSync45(filePath, body.content, "utf-8");
|
|
41182
41375
|
}
|
|
41183
41376
|
const what = changedParts.length > 0 ? changedParts.join(" and ") : "file";
|
|
41184
41377
|
recordDashboardChange(contextRoot, {
|
|
@@ -42793,8 +42986,9 @@ function buildAskPrompt(question) {
|
|
|
42793
42986
|
|
|
42794
42987
|
Question: "${question}"`;
|
|
42795
42988
|
}
|
|
42796
|
-
function buildSleepPrompt() {
|
|
42797
|
-
|
|
42989
|
+
function buildSleepPrompt(depth) {
|
|
42990
|
+
const depthLine = isDestructiveAllowed(depth) ? `This is a DEEP consolidation: you ARE authorized to perform destructive/expensive knowledge ops (merge-with-delete, summarize-and-replace still-valid detail, archive/delete stale files) \u2014 but first copy any file you will merge/replace/delete to \`_dream_context/knowledge/.archive/<slug>-<YYYYMMDD>.md\` (create the dir if absent).` : `This is a ${depth.toUpperCase()} consolidation: do NOT merge, summarize-and-replace, or delete any knowledge. Only create/extend/retag/tick. If you spot merge or deletion candidates, FLAG them in your report instead of acting on them.`;
|
|
42991
|
+
return `Think hard. Run a dreamcontext memory consolidation ("sleep") for THIS project now, fully autonomously \u2014 do NOT ask any questions. Follow the project's dreamcontext sleep/consolidation flow: pin the epoch with \`dreamcontext sleep start\`, reconcile the task/changelog/knowledge/feature files to current truth as warranted (prefer updating existing entities over creating new ones), then close the cycle with \`dreamcontext sleep done "<one-paragraph summary>"\` to reset the debt. ${depthLine} When finished, reply with a SHORT GitHub-flavored Markdown summary (a few bullets) of what was consolidated. Keep it concise.`;
|
|
42798
42992
|
}
|
|
42799
42993
|
async function handleLauncherCapture(req, res, _params, _contextRoot) {
|
|
42800
42994
|
const body = await parseJsonBody(req);
|
|
@@ -42852,7 +43046,18 @@ async function handleLauncherCapture(req, res, _params, _contextRoot) {
|
|
|
42852
43046
|
captureRuns.set(captureId, run2);
|
|
42853
43047
|
try {
|
|
42854
43048
|
const shell = process.env.SHELL || "/bin/zsh";
|
|
42855
|
-
|
|
43049
|
+
let sleepDepth = "deep";
|
|
43050
|
+
if (mode === "sleep") {
|
|
43051
|
+
try {
|
|
43052
|
+
sleepDepth = consolidationDepth(readSleepState(cwd).debt, {
|
|
43053
|
+
userRequestedDeep: true
|
|
43054
|
+
}).depth;
|
|
43055
|
+
} catch (err) {
|
|
43056
|
+
console.error("[launcher] could not read sleep state for depth:", err);
|
|
43057
|
+
sleepDepth = "deep";
|
|
43058
|
+
}
|
|
43059
|
+
}
|
|
43060
|
+
const prompt = mode === "sleep" ? buildSleepPrompt(sleepDepth) : mode === "ask" ? buildAskPrompt(text) : buildCapturePrompt(text);
|
|
42856
43061
|
const child = spawn4(shell, ["-ilc", 'exec claude --model sonnet -p "$0"', prompt], {
|
|
42857
43062
|
cwd,
|
|
42858
43063
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -42899,6 +43104,177 @@ async function handleLauncherDefaults(_req, res, _params, _contextRoot) {
|
|
|
42899
43104
|
const home = homedir3();
|
|
42900
43105
|
sendJson(res, 200, { home, defaultParent: join59(home, "projects") });
|
|
42901
43106
|
}
|
|
43107
|
+
function computeVaultStatus(v, latest) {
|
|
43108
|
+
const exists = existsSync63(resolve15(v.path));
|
|
43109
|
+
let setupVersion = "0.0.0";
|
|
43110
|
+
let shareable = false;
|
|
43111
|
+
if (exists) {
|
|
43112
|
+
try {
|
|
43113
|
+
const cfg = readSetupConfig(resolve15(v.path));
|
|
43114
|
+
if (cfg) {
|
|
43115
|
+
setupVersion = cfg.setupVersion || "0.0.0";
|
|
43116
|
+
shareable = cfg.shareable === true;
|
|
43117
|
+
}
|
|
43118
|
+
} catch {
|
|
43119
|
+
}
|
|
43120
|
+
}
|
|
43121
|
+
const needsUpdate = exists && compareVersions(setupVersion, latest) < 0;
|
|
43122
|
+
return { name: v.name, path: v.path, exists, setupVersion, latestVersion: latest, needsUpdate, shareable };
|
|
43123
|
+
}
|
|
43124
|
+
async function handleLauncherStatus(_req, res, _params, _contextRoot) {
|
|
43125
|
+
const latest = dreamcontextVersion();
|
|
43126
|
+
const vaults = listVaults().map((v) => computeVaultStatus(v, latest));
|
|
43127
|
+
sendJson(res, 200, { vaults, latestVersion: latest });
|
|
43128
|
+
}
|
|
43129
|
+
async function handleLauncherUnregister(req, res, _params, _contextRoot) {
|
|
43130
|
+
const body = await parseJsonBody(req);
|
|
43131
|
+
if (!body) {
|
|
43132
|
+
sendError(res, 400, "invalid_body", "Request body must be valid JSON.");
|
|
43133
|
+
return;
|
|
43134
|
+
}
|
|
43135
|
+
const name = typeof body.name === "string" ? body.name.trim() : "";
|
|
43136
|
+
if (!name) {
|
|
43137
|
+
sendError(res, 400, "invalid_name", "name must be a non-empty string.");
|
|
43138
|
+
return;
|
|
43139
|
+
}
|
|
43140
|
+
const removed = removeVault(name);
|
|
43141
|
+
sendJson(res, 200, { removed, vaults: listVaults() });
|
|
43142
|
+
}
|
|
43143
|
+
async function handleLauncherUpdate(req, res, _params, _contextRoot) {
|
|
43144
|
+
const body = await parseJsonBody(req);
|
|
43145
|
+
if (!body) {
|
|
43146
|
+
sendError(res, 400, "invalid_body", "Request body must be valid JSON.");
|
|
43147
|
+
return;
|
|
43148
|
+
}
|
|
43149
|
+
const name = typeof body.name === "string" ? body.name.trim() : "";
|
|
43150
|
+
if (!name) {
|
|
43151
|
+
sendError(res, 400, "invalid_name", "name must be a non-empty string.");
|
|
43152
|
+
return;
|
|
43153
|
+
}
|
|
43154
|
+
const vault = listVaults().find((v) => v.name === name);
|
|
43155
|
+
if (!vault) {
|
|
43156
|
+
sendError(res, 400, "unknown_vault", `No registered vault named "${name}".`);
|
|
43157
|
+
return;
|
|
43158
|
+
}
|
|
43159
|
+
const target = resolve15(vault.path);
|
|
43160
|
+
if (!existsSync63(target)) {
|
|
43161
|
+
sendError(res, 400, "missing_vault", `Vault path no longer exists: ${target}`);
|
|
43162
|
+
return;
|
|
43163
|
+
}
|
|
43164
|
+
try {
|
|
43165
|
+
await defaultCliRunner(["update"], target);
|
|
43166
|
+
const latest = dreamcontextVersion();
|
|
43167
|
+
sendJson(res, 200, { ok: true, status: computeVaultStatus(vault, latest) });
|
|
43168
|
+
} catch (err) {
|
|
43169
|
+
console.error("[launcher] update failed:", err);
|
|
43170
|
+
const detail = err instanceof Error ? err.message : "unknown error";
|
|
43171
|
+
sendError(res, 500, "update_failed", `Update failed: ${detail}`);
|
|
43172
|
+
}
|
|
43173
|
+
}
|
|
43174
|
+
async function handleLauncherFederationGraph(_req, res, _params, _contextRoot) {
|
|
43175
|
+
const latest = dreamcontextVersion();
|
|
43176
|
+
const vaults = listVaults();
|
|
43177
|
+
const nodes = vaults.map((v) => computeVaultStatus(v, latest));
|
|
43178
|
+
const shareableByName = new Map(nodes.map((n) => [n.name, n.shareable]));
|
|
43179
|
+
const known = new Set(vaults.map((v) => v.name));
|
|
43180
|
+
const edges = [];
|
|
43181
|
+
const seen = /* @__PURE__ */ new Set();
|
|
43182
|
+
for (const v of vaults) {
|
|
43183
|
+
if (!existsSync63(resolve15(v.path))) continue;
|
|
43184
|
+
const conns = listConnections(join59(resolve15(v.path), "_dream_context"));
|
|
43185
|
+
for (const c of conns) {
|
|
43186
|
+
if (c.direction !== "out" && c.direction !== "both") continue;
|
|
43187
|
+
if (!known.has(c.vault)) continue;
|
|
43188
|
+
if (c.status === "stale") continue;
|
|
43189
|
+
const key = `${v.name}\0${c.vault}`;
|
|
43190
|
+
if (seen.has(key)) continue;
|
|
43191
|
+
seen.add(key);
|
|
43192
|
+
edges.push({ source: v.name, target: c.vault, active: shareableByName.get(c.vault) === true });
|
|
43193
|
+
}
|
|
43194
|
+
}
|
|
43195
|
+
sendJson(res, 200, { nodes, edges, latestVersion: latest });
|
|
43196
|
+
}
|
|
43197
|
+
async function handleLauncherConnectionCreate(req, res, _params, _contextRoot) {
|
|
43198
|
+
const body = await parseJsonBody(req);
|
|
43199
|
+
if (!body) {
|
|
43200
|
+
sendError(res, 400, "invalid_body", "Request body must be valid JSON.");
|
|
43201
|
+
return;
|
|
43202
|
+
}
|
|
43203
|
+
const from = typeof body.from === "string" ? body.from.trim() : "";
|
|
43204
|
+
const to = typeof body.to === "string" ? body.to.trim() : "";
|
|
43205
|
+
if (!from || !to) {
|
|
43206
|
+
sendError(res, 400, "invalid_body", "from and to must be non-empty strings.");
|
|
43207
|
+
return;
|
|
43208
|
+
}
|
|
43209
|
+
const fromVault = listVaults().find((v) => v.name === from);
|
|
43210
|
+
if (!fromVault) {
|
|
43211
|
+
sendError(res, 400, "unknown_vault", `No registered vault named "${from}".`);
|
|
43212
|
+
return;
|
|
43213
|
+
}
|
|
43214
|
+
const fromRoot = join59(resolve15(fromVault.path), "_dream_context");
|
|
43215
|
+
try {
|
|
43216
|
+
addConnection(fromRoot, from, to, "out", null);
|
|
43217
|
+
sendJson(res, 200, { ok: true });
|
|
43218
|
+
} catch (err) {
|
|
43219
|
+
if (err instanceof VaultError) {
|
|
43220
|
+
sendError(res, 400, "invalid_connection", err.message);
|
|
43221
|
+
return;
|
|
43222
|
+
}
|
|
43223
|
+
console.error("[launcher] connection create failed:", err);
|
|
43224
|
+
sendError(res, 500, "connection_failed", "Failed to create connection.");
|
|
43225
|
+
}
|
|
43226
|
+
}
|
|
43227
|
+
async function handleLauncherConnectionRemove(req, res, _params, _contextRoot) {
|
|
43228
|
+
const body = await parseJsonBody(req);
|
|
43229
|
+
if (!body) {
|
|
43230
|
+
sendError(res, 400, "invalid_body", "Request body must be valid JSON.");
|
|
43231
|
+
return;
|
|
43232
|
+
}
|
|
43233
|
+
const from = typeof body.from === "string" ? body.from.trim() : "";
|
|
43234
|
+
const to = typeof body.to === "string" ? body.to.trim() : "";
|
|
43235
|
+
if (!from || !to) {
|
|
43236
|
+
sendError(res, 400, "invalid_body", "from and to must be non-empty strings.");
|
|
43237
|
+
return;
|
|
43238
|
+
}
|
|
43239
|
+
const fromVault = listVaults().find((v) => v.name === from);
|
|
43240
|
+
if (!fromVault) {
|
|
43241
|
+
sendError(res, 400, "unknown_vault", `No registered vault named "${from}".`);
|
|
43242
|
+
return;
|
|
43243
|
+
}
|
|
43244
|
+
const fromRoot = join59(resolve15(fromVault.path), "_dream_context");
|
|
43245
|
+
const removed = removeConnection(fromRoot, to);
|
|
43246
|
+
sendJson(res, 200, { ok: true, removed });
|
|
43247
|
+
}
|
|
43248
|
+
async function handleLauncherShareable(req, res, _params, _contextRoot) {
|
|
43249
|
+
const body = await parseJsonBody(req);
|
|
43250
|
+
if (!body) {
|
|
43251
|
+
sendError(res, 400, "invalid_body", "Request body must be valid JSON.");
|
|
43252
|
+
return;
|
|
43253
|
+
}
|
|
43254
|
+
const name = typeof body.name === "string" ? body.name.trim() : "";
|
|
43255
|
+
const shareable = body.shareable === true;
|
|
43256
|
+
if (!name) {
|
|
43257
|
+
sendError(res, 400, "invalid_name", "name must be a non-empty string.");
|
|
43258
|
+
return;
|
|
43259
|
+
}
|
|
43260
|
+
const vault = listVaults().find((v) => v.name === name);
|
|
43261
|
+
if (!vault) {
|
|
43262
|
+
sendError(res, 400, "unknown_vault", `No registered vault named "${name}".`);
|
|
43263
|
+
return;
|
|
43264
|
+
}
|
|
43265
|
+
const root = resolve15(vault.path);
|
|
43266
|
+
if (!existsSync63(root)) {
|
|
43267
|
+
sendError(res, 400, "missing_vault", `Vault path no longer exists: ${root}`);
|
|
43268
|
+
return;
|
|
43269
|
+
}
|
|
43270
|
+
try {
|
|
43271
|
+
updateSetupConfig(root, { shareable });
|
|
43272
|
+
sendJson(res, 200, { ok: true, name, shareable });
|
|
43273
|
+
} catch (err) {
|
|
43274
|
+
console.error("[launcher] shareable toggle failed:", err);
|
|
43275
|
+
sendError(res, 500, "shareable_failed", "Failed to update sharing.");
|
|
43276
|
+
}
|
|
43277
|
+
}
|
|
42902
43278
|
var execFileAsync2, captureRuns, CAPTURE_RUN_TTL_MS, CAPTURE_RUNS_MAX, ScaffoldError, defaultCliRunner, SAFE_NAME_RE, SLEEPY_MODES;
|
|
42903
43279
|
var init_launcher = __esm({
|
|
42904
43280
|
"src/server/routes/launcher.ts"() {
|
|
@@ -42906,12 +43282,18 @@ var init_launcher = __esm({
|
|
|
42906
43282
|
init_middleware();
|
|
42907
43283
|
init_vault_discovery();
|
|
42908
43284
|
init_vaults();
|
|
43285
|
+
init_connections();
|
|
43286
|
+
init_setup_config();
|
|
43287
|
+
init_manifest();
|
|
43288
|
+
init_version_check();
|
|
42909
43289
|
init_tech_stack();
|
|
42910
43290
|
init_ensure_cli();
|
|
42911
43291
|
init_platforms();
|
|
42912
43292
|
init_catalog();
|
|
42913
43293
|
init_json_file();
|
|
42914
43294
|
init_id();
|
|
43295
|
+
init_sleep();
|
|
43296
|
+
init_sleep_consolidation();
|
|
42915
43297
|
execFileAsync2 = promisify2(execFile2);
|
|
42916
43298
|
captureRuns = /* @__PURE__ */ new Map();
|
|
42917
43299
|
CAPTURE_RUN_TTL_MS = 10 * 60 * 1e3;
|
|
@@ -42940,6 +43322,62 @@ var init_launcher = __esm({
|
|
|
42940
43322
|
}
|
|
42941
43323
|
});
|
|
42942
43324
|
|
|
43325
|
+
// src/server/routes/ui-settings.ts
|
|
43326
|
+
import { dirname as dirname30, join as join60 } from "path";
|
|
43327
|
+
import { existsSync as existsSync64, mkdirSync as mkdirSync26, readFileSync as readFileSync46, writeFileSync as writeFileSync33 } from "fs";
|
|
43328
|
+
function settingsPath(contextRoot) {
|
|
43329
|
+
return join60(contextRoot, BRAIN_SETTINGS_REL_PATH);
|
|
43330
|
+
}
|
|
43331
|
+
async function handleBrainSettingsGet(_req, res, _params, contextRoot) {
|
|
43332
|
+
const path2 = settingsPath(contextRoot);
|
|
43333
|
+
if (!existsSync64(path2)) {
|
|
43334
|
+
sendJson(res, 200, { settings: {} });
|
|
43335
|
+
return;
|
|
43336
|
+
}
|
|
43337
|
+
try {
|
|
43338
|
+
const raw = JSON.parse(readFileSync46(path2, "utf-8"));
|
|
43339
|
+
const settings = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
43340
|
+
sendJson(res, 200, { settings });
|
|
43341
|
+
} catch {
|
|
43342
|
+
sendJson(res, 200, { settings: {} });
|
|
43343
|
+
}
|
|
43344
|
+
}
|
|
43345
|
+
async function handleBrainSettingsPut(req, res, _params, contextRoot) {
|
|
43346
|
+
const body = await parseJsonBody(req);
|
|
43347
|
+
if (!body) {
|
|
43348
|
+
sendError(res, 400, "invalid_body", "Request body must be valid JSON.");
|
|
43349
|
+
return;
|
|
43350
|
+
}
|
|
43351
|
+
const settings = body.settings;
|
|
43352
|
+
if (settings === null || typeof settings !== "object" || Array.isArray(settings)) {
|
|
43353
|
+
sendError(res, 400, "invalid_settings", "settings must be a JSON object.");
|
|
43354
|
+
return;
|
|
43355
|
+
}
|
|
43356
|
+
const serialized = JSON.stringify(settings, null, 2);
|
|
43357
|
+
if (Buffer.byteLength(serialized, "utf-8") > MAX_BYTES) {
|
|
43358
|
+
sendError(res, 400, "too_large", "settings payload is too large.");
|
|
43359
|
+
return;
|
|
43360
|
+
}
|
|
43361
|
+
try {
|
|
43362
|
+
const path2 = settingsPath(contextRoot);
|
|
43363
|
+
mkdirSync26(dirname30(path2), { recursive: true });
|
|
43364
|
+
writeFileSync33(path2, serialized + "\n", "utf-8");
|
|
43365
|
+
sendJson(res, 200, { ok: true });
|
|
43366
|
+
} catch (err) {
|
|
43367
|
+
console.error("[ui-settings] brain-settings write failed:", err);
|
|
43368
|
+
sendError(res, 500, "write_failed", "Failed to persist brain settings.");
|
|
43369
|
+
}
|
|
43370
|
+
}
|
|
43371
|
+
var BRAIN_SETTINGS_REL_PATH, MAX_BYTES;
|
|
43372
|
+
var init_ui_settings = __esm({
|
|
43373
|
+
"src/server/routes/ui-settings.ts"() {
|
|
43374
|
+
"use strict";
|
|
43375
|
+
init_middleware();
|
|
43376
|
+
BRAIN_SETTINGS_REL_PATH = "state/.brain-settings.json";
|
|
43377
|
+
MAX_BYTES = 256 * 1024;
|
|
43378
|
+
}
|
|
43379
|
+
});
|
|
43380
|
+
|
|
42943
43381
|
// src/lib/federation-config.ts
|
|
42944
43382
|
function isShareable(projectRoot) {
|
|
42945
43383
|
const cfg = readSetupConfig(projectRoot);
|
|
@@ -42953,7 +43391,7 @@ var init_federation_config = __esm({
|
|
|
42953
43391
|
});
|
|
42954
43392
|
|
|
42955
43393
|
// src/lib/federation-recall.ts
|
|
42956
|
-
import { basename as basename19, dirname as
|
|
43394
|
+
import { basename as basename19, dirname as dirname31 } from "path";
|
|
42957
43395
|
function namespacedKey(vault, type, slug) {
|
|
42958
43396
|
return `${vault}::${type}/${slug}`;
|
|
42959
43397
|
}
|
|
@@ -42978,7 +43416,7 @@ function crossVaultRecall(query, opts) {
|
|
|
42978
43416
|
}
|
|
42979
43417
|
const isCurrent = target.current === true;
|
|
42980
43418
|
if (!isCurrent) {
|
|
42981
|
-
const projectRoot =
|
|
43419
|
+
const projectRoot = dirname31(contextRoot);
|
|
42982
43420
|
if (!isShareable(projectRoot)) continue;
|
|
42983
43421
|
}
|
|
42984
43422
|
const corpus = buildCorpus(contextRoot, opts.types ? { types: opts.types } : {}).filter((doc) => !isFederated(doc));
|
|
@@ -43051,9 +43489,9 @@ var init_federation_recall = __esm({
|
|
|
43051
43489
|
});
|
|
43052
43490
|
|
|
43053
43491
|
// src/server/routes/connections.ts
|
|
43054
|
-
import { dirname as
|
|
43492
|
+
import { dirname as dirname32 } from "path";
|
|
43055
43493
|
function currentVaultName(contextRoot) {
|
|
43056
|
-
return currentVaultTarget(
|
|
43494
|
+
return currentVaultTarget(dirname32(contextRoot)).name;
|
|
43057
43495
|
}
|
|
43058
43496
|
async function handleConnectionsList(_req, res, _params, contextRoot) {
|
|
43059
43497
|
sendJson(res, 200, { connections: listConnections(contextRoot) });
|
|
@@ -43128,8 +43566,8 @@ var init_connections2 = __esm({
|
|
|
43128
43566
|
});
|
|
43129
43567
|
|
|
43130
43568
|
// src/lib/federation-digest.ts
|
|
43131
|
-
import { existsSync as
|
|
43132
|
-
import { join as
|
|
43569
|
+
import { existsSync as existsSync65 } from "fs";
|
|
43570
|
+
import { join as join61 } from "path";
|
|
43133
43571
|
function buildInterestProfile(peerRoot, topics) {
|
|
43134
43572
|
if (topics && topics.length > 0) {
|
|
43135
43573
|
const terms2 = Array.from(new Set(tokenize(topics.join(" "))));
|
|
@@ -43148,8 +43586,8 @@ function buildInterestProfile(peerRoot, topics) {
|
|
|
43148
43586
|
return { terms, query: terms.join(" ") };
|
|
43149
43587
|
}
|
|
43150
43588
|
function activeTaskTerms(peerRoot) {
|
|
43151
|
-
const stateDir =
|
|
43152
|
-
if (!
|
|
43589
|
+
const stateDir = join61(peerRoot, "state");
|
|
43590
|
+
if (!existsSync65(stateDir)) return [];
|
|
43153
43591
|
let files;
|
|
43154
43592
|
try {
|
|
43155
43593
|
files = import_fast_glob17.default.sync("*.md", { cwd: stateDir, absolute: true });
|
|
@@ -43250,7 +43688,7 @@ var init_federation_digest = __esm({
|
|
|
43250
43688
|
});
|
|
43251
43689
|
|
|
43252
43690
|
// src/server/routes/federation.ts
|
|
43253
|
-
import { dirname as
|
|
43691
|
+
import { dirname as dirname33 } from "path";
|
|
43254
43692
|
async function handleFederationInboxGet(_req, res, _params, contextRoot) {
|
|
43255
43693
|
const { entries, quarantined } = drainInbox(contextRoot);
|
|
43256
43694
|
const pending = entries.map((e) => e.entry);
|
|
@@ -43262,7 +43700,7 @@ async function handleFederationInboxGet(_req, res, _params, contextRoot) {
|
|
|
43262
43700
|
});
|
|
43263
43701
|
}
|
|
43264
43702
|
async function handleFederationSyncPost(_req, res, _params, contextRoot) {
|
|
43265
|
-
const senderName = currentVaultTarget(
|
|
43703
|
+
const senderName = currentVaultTarget(dirname33(contextRoot)).name;
|
|
43266
43704
|
const outbound = listConnections(contextRoot).filter(
|
|
43267
43705
|
(c) => (c.direction === "out" || c.direction === "both") && c.status !== "stale"
|
|
43268
43706
|
);
|
|
@@ -43310,14 +43748,14 @@ var init_federation = __esm({
|
|
|
43310
43748
|
});
|
|
43311
43749
|
|
|
43312
43750
|
// src/server/routes/packs.ts
|
|
43313
|
-
import { dirname as
|
|
43751
|
+
import { dirname as dirname34 } from "path";
|
|
43314
43752
|
async function handlePacksGet(_req, res, _params, contextRoot) {
|
|
43315
43753
|
const loaded = loadCatalog();
|
|
43316
43754
|
if (!loaded) {
|
|
43317
43755
|
sendJson(res, 200, { packs: [], standalone: [] });
|
|
43318
43756
|
return;
|
|
43319
43757
|
}
|
|
43320
|
-
const projectRoot =
|
|
43758
|
+
const projectRoot = dirname34(contextRoot);
|
|
43321
43759
|
const packs = loaded.catalog.packs.map((p) => ({ ...p, installed: isSkillInstalled(projectRoot, p.name) }));
|
|
43322
43760
|
const standalone = loaded.catalog.standalone.map((s) => ({ ...s, installed: isSkillInstalled(projectRoot, s.name) }));
|
|
43323
43761
|
sendJson(res, 200, { packs, standalone });
|
|
@@ -43331,7 +43769,7 @@ var init_packs = __esm({
|
|
|
43331
43769
|
});
|
|
43332
43770
|
|
|
43333
43771
|
// src/server/routes/packs-install.ts
|
|
43334
|
-
import { dirname as
|
|
43772
|
+
import { dirname as dirname35 } from "path";
|
|
43335
43773
|
function validatePackName(name, contextRoot) {
|
|
43336
43774
|
if (name.includes("/") || name.includes("\0") || safeChildPath2("/x", name) === null) {
|
|
43337
43775
|
return { ok: false, status: 400, code: "invalid_name", message: "Invalid pack name." };
|
|
@@ -43344,7 +43782,7 @@ function validatePackName(name, contextRoot) {
|
|
|
43344
43782
|
if (!known) {
|
|
43345
43783
|
return { ok: false, status: 404, code: "unknown_pack", message: `Pack "${name}" not found.` };
|
|
43346
43784
|
}
|
|
43347
|
-
const projectRoot =
|
|
43785
|
+
const projectRoot = dirname35(contextRoot);
|
|
43348
43786
|
const config = readSetupConfig(projectRoot);
|
|
43349
43787
|
const platforms = normalizePlatforms(config?.platforms ?? []);
|
|
43350
43788
|
const resolved = platforms.length > 0 ? platforms : [...DEFAULT_PLATFORMS];
|
|
@@ -43417,10 +43855,10 @@ var init_packs_install = __esm({
|
|
|
43417
43855
|
});
|
|
43418
43856
|
|
|
43419
43857
|
// src/server/routes/version-check.ts
|
|
43420
|
-
import { dirname as
|
|
43858
|
+
import { dirname as dirname36 } from "path";
|
|
43421
43859
|
async function handleVersionCheckGet(_req, res, _params, contextRoot) {
|
|
43422
43860
|
try {
|
|
43423
|
-
const projectRoot =
|
|
43861
|
+
const projectRoot = dirname36(contextRoot);
|
|
43424
43862
|
const cache = readVersionCache(projectRoot);
|
|
43425
43863
|
const fresh = isCacheFresh(cache);
|
|
43426
43864
|
const installedCli = dreamcontextVersion();
|
|
@@ -43475,7 +43913,7 @@ var init_taxonomy2 = __esm({
|
|
|
43475
43913
|
|
|
43476
43914
|
// src/server/index.ts
|
|
43477
43915
|
import { createServer } from "http";
|
|
43478
|
-
import { join as
|
|
43916
|
+
import { join as join62, resolve as resolve16 } from "path";
|
|
43479
43917
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
43480
43918
|
import { exec } from "child_process";
|
|
43481
43919
|
function buildRouter() {
|
|
@@ -43521,6 +43959,13 @@ function buildRouter() {
|
|
|
43521
43959
|
router.get("/api/launcher/capture/status", handleLauncherCaptureStatus);
|
|
43522
43960
|
router.get("/api/launcher/sleepy-config", handleSleepyConfigGet);
|
|
43523
43961
|
router.post("/api/launcher/sleepy-config", handleSleepyConfigSet);
|
|
43962
|
+
router.get("/api/launcher/status", handleLauncherStatus);
|
|
43963
|
+
router.post("/api/launcher/unregister", handleLauncherUnregister);
|
|
43964
|
+
router.post("/api/launcher/update", handleLauncherUpdate);
|
|
43965
|
+
router.get("/api/launcher/federation-graph", handleLauncherFederationGraph);
|
|
43966
|
+
router.post("/api/launcher/connection", handleLauncherConnectionCreate);
|
|
43967
|
+
router.post("/api/launcher/connection/remove", handleLauncherConnectionRemove);
|
|
43968
|
+
router.post("/api/launcher/shareable", handleLauncherShareable);
|
|
43524
43969
|
router.get("/api/sleepy/video", handleSleepyVideo);
|
|
43525
43970
|
router.get("/api/sleepy/anim", handleSleepyAnim);
|
|
43526
43971
|
router.get("/api/vaults", handleVaultsGet);
|
|
@@ -43532,6 +43977,8 @@ function buildRouter() {
|
|
|
43532
43977
|
router.get("/api/packs", handlePacksGet);
|
|
43533
43978
|
router.post("/api/packs/:name/install", handlePackInstall);
|
|
43534
43979
|
router.delete("/api/packs/:name", handlePackUninstall);
|
|
43980
|
+
router.get("/api/brain-settings", handleBrainSettingsGet);
|
|
43981
|
+
router.put("/api/brain-settings", handleBrainSettingsPut);
|
|
43535
43982
|
router.get("/api/version-check", handleVersionCheckGet);
|
|
43536
43983
|
router.get("/api/taxonomy", handleTaxonomyGet);
|
|
43537
43984
|
router.get("/api/changelog", handleChangelogGet);
|
|
@@ -43553,7 +44000,7 @@ function resolveRequestVault(req) {
|
|
|
43553
44000
|
if (/[/\\:.\x00]/.test(h)) return "INVALID";
|
|
43554
44001
|
const v = listVaults().find((x) => x.name === h);
|
|
43555
44002
|
if (!v) return "INVALID";
|
|
43556
|
-
return
|
|
44003
|
+
return join62(v.path, "_dream_context");
|
|
43557
44004
|
}
|
|
43558
44005
|
function getDashboardDir() {
|
|
43559
44006
|
const __dirname8 = fileURLToPath7(new URL(".", import.meta.url));
|
|
@@ -43653,6 +44100,7 @@ var init_server = __esm({
|
|
|
43653
44100
|
init_config();
|
|
43654
44101
|
init_vaults2();
|
|
43655
44102
|
init_launcher();
|
|
44103
|
+
init_ui_settings();
|
|
43656
44104
|
init_connections2();
|
|
43657
44105
|
init_federation();
|
|
43658
44106
|
init_packs();
|
|
@@ -43844,8 +44292,8 @@ var init_trigger = __esm({
|
|
|
43844
44292
|
});
|
|
43845
44293
|
|
|
43846
44294
|
// src/lib/reflection.ts
|
|
43847
|
-
import { existsSync as
|
|
43848
|
-
import { join as
|
|
44295
|
+
import { existsSync as existsSync66, mkdirSync as mkdirSync27, writeFileSync as writeFileSync34 } from "fs";
|
|
44296
|
+
import { join as join63, dirname as dirname37 } from "path";
|
|
43849
44297
|
function buildExclusionSet(corpus, excludedExtra) {
|
|
43850
44298
|
const excluded = new Set(excludedExtra);
|
|
43851
44299
|
for (const doc of corpus) {
|
|
@@ -44021,13 +44469,13 @@ function formatReflection(result) {
|
|
|
44021
44469
|
return capToBytes(lines, MAX_REFLECTION_BYTES);
|
|
44022
44470
|
}
|
|
44023
44471
|
function reflectionPath(root) {
|
|
44024
|
-
return
|
|
44472
|
+
return join63(root, "state", ".reflection.md");
|
|
44025
44473
|
}
|
|
44026
44474
|
function writeReflection(root, md) {
|
|
44027
44475
|
const outPath = reflectionPath(root);
|
|
44028
|
-
const dir =
|
|
44029
|
-
if (!
|
|
44030
|
-
|
|
44476
|
+
const dir = dirname37(outPath);
|
|
44477
|
+
if (!existsSync66(dir)) {
|
|
44478
|
+
mkdirSync27(dir, { recursive: true });
|
|
44031
44479
|
}
|
|
44032
44480
|
const tsMatch = md.match(/Generated: ([^\n]+)/);
|
|
44033
44481
|
const generatedAt = tsMatch ? tsMatch[1].trim() : (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -44038,7 +44486,7 @@ function writeReflection(root, md) {
|
|
|
44038
44486
|
"---",
|
|
44039
44487
|
""
|
|
44040
44488
|
].join("\n");
|
|
44041
|
-
|
|
44489
|
+
writeFileSync34(outPath, frontmatter + md, "utf-8");
|
|
44042
44490
|
return outPath;
|
|
44043
44491
|
}
|
|
44044
44492
|
var MAX_REFLECTION_BYTES, DEFAULT_MIN_SESSIONS, DEFAULT_MAX_CANDIDATES, REFLECTION_NOISE;
|
|
@@ -44202,14 +44650,14 @@ var init_reflection = __esm({
|
|
|
44202
44650
|
});
|
|
44203
44651
|
|
|
44204
44652
|
// src/cli/commands/reflect.ts
|
|
44205
|
-
import { existsSync as
|
|
44206
|
-
import { join as
|
|
44653
|
+
import { existsSync as existsSync67, readFileSync as readFileSync49 } from "fs";
|
|
44654
|
+
import { join as join64 } from "path";
|
|
44207
44655
|
function buildBookmarkSessions(root) {
|
|
44208
|
-
const sleepPath =
|
|
44656
|
+
const sleepPath = join64(root, "state", ".sleep.json");
|
|
44209
44657
|
const result = /* @__PURE__ */ new Map();
|
|
44210
|
-
if (!
|
|
44658
|
+
if (!existsSync67(sleepPath)) return result;
|
|
44211
44659
|
try {
|
|
44212
|
-
const parsed = JSON.parse(
|
|
44660
|
+
const parsed = JSON.parse(readFileSync49(sleepPath, "utf-8"));
|
|
44213
44661
|
const bookmarks = parsed.bookmarks ?? [];
|
|
44214
44662
|
for (const b of bookmarks) {
|
|
44215
44663
|
if (b.id && b.session_id) {
|
|
@@ -44223,13 +44671,13 @@ function buildBookmarkSessions(root) {
|
|
|
44223
44671
|
function buildExcludedExtra(root) {
|
|
44224
44672
|
const excluded = /* @__PURE__ */ new Set();
|
|
44225
44673
|
const coreFiles = [
|
|
44226
|
-
|
|
44227
|
-
|
|
44674
|
+
join64(root, "core", "0.soul.md"),
|
|
44675
|
+
join64(root, "core", "1.user.md")
|
|
44228
44676
|
];
|
|
44229
44677
|
for (const filePath of coreFiles) {
|
|
44230
|
-
if (!
|
|
44678
|
+
if (!existsSync67(filePath)) continue;
|
|
44231
44679
|
try {
|
|
44232
|
-
const content =
|
|
44680
|
+
const content = readFileSync49(filePath, "utf-8");
|
|
44233
44681
|
for (const tok of tokenize(content)) {
|
|
44234
44682
|
excluded.add(tok);
|
|
44235
44683
|
}
|
|
@@ -44280,8 +44728,8 @@ var init_reflect = __esm({
|
|
|
44280
44728
|
});
|
|
44281
44729
|
|
|
44282
44730
|
// src/cli/commands/council.ts
|
|
44283
|
-
import { existsSync as
|
|
44284
|
-
import { join as
|
|
44731
|
+
import { existsSync as existsSync68, mkdirSync as mkdirSync28, readFileSync as readFileSync50, writeFileSync as writeFileSync35 } from "fs";
|
|
44732
|
+
import { join as join65 } from "path";
|
|
44285
44733
|
function roundRunningStatus(n) {
|
|
44286
44734
|
return `round_${n}_running`;
|
|
44287
44735
|
}
|
|
@@ -44323,12 +44771,12 @@ function registerCreate(council) {
|
|
|
44323
44771
|
}
|
|
44324
44772
|
const id = generateId("council");
|
|
44325
44773
|
const dir = getDebateDir(id);
|
|
44326
|
-
|
|
44774
|
+
mkdirSync28(dir, { recursive: true });
|
|
44327
44775
|
const template = loadTemplate("council-debate.md");
|
|
44328
44776
|
const content = template.replaceAll("{{ID}}", id).replaceAll("{{TOPIC}}", topic.replace(/"/g, '\\"')).replaceAll("{{ROUNDS}}", String(rounds)).replaceAll("{{INTERRUPT}}", opts.interrupt ? "true" : "false").replaceAll("{{DATE}}", today());
|
|
44329
|
-
|
|
44330
|
-
|
|
44331
|
-
|
|
44777
|
+
writeFileSync35(join65(dir, "debate.md"), content, "utf-8");
|
|
44778
|
+
writeFileSync35(
|
|
44779
|
+
join65(dir, "round-log.md"),
|
|
44332
44780
|
`# Round log \u2014 ${id}
|
|
44333
44781
|
|
|
44334
44782
|
(Main agent appends timeline entries here.)
|
|
@@ -44370,8 +44818,8 @@ function registerAgent(council) {
|
|
|
44370
44818
|
process.exit(1);
|
|
44371
44819
|
}
|
|
44372
44820
|
const personaDir = getPersonaDir(debateId, slug);
|
|
44373
|
-
const personaFile =
|
|
44374
|
-
if (
|
|
44821
|
+
const personaFile = join65(personaDir, "context-and-persona.md");
|
|
44822
|
+
if (existsSync68(personaFile) && !opts.force) {
|
|
44375
44823
|
error(`Persona already exists: ${slug}`, "Use --force to overwrite.");
|
|
44376
44824
|
process.exit(1);
|
|
44377
44825
|
}
|
|
@@ -44381,14 +44829,14 @@ function registerAgent(council) {
|
|
|
44381
44829
|
process.exit(1);
|
|
44382
44830
|
}
|
|
44383
44831
|
const aspects = opts.aspects ? opts.aspects.split(",").map((a) => a.trim()).filter(Boolean) : [];
|
|
44384
|
-
|
|
44832
|
+
mkdirSync28(personaDir, { recursive: true });
|
|
44385
44833
|
const template = loadTemplate("council-persona.md");
|
|
44386
44834
|
const personaContent = template.replaceAll("{{SLUG}}", slug).replaceAll("{{MODEL}}", opts.model).replaceAll("{{ASPECTS}}", JSON.stringify(aspects)).replaceAll("{{PERSONA_BODY}}", body.trim());
|
|
44387
|
-
|
|
44835
|
+
writeFileSync35(personaFile, personaContent, "utf-8");
|
|
44388
44836
|
const reportTemplate = loadTemplate("council-report.md");
|
|
44389
44837
|
const reportContent = reportTemplate.replaceAll("{{SLUG}}", slug);
|
|
44390
|
-
|
|
44391
|
-
const debateFile =
|
|
44838
|
+
writeFileSync35(join65(personaDir, "report.md"), reportContent, "utf-8");
|
|
44839
|
+
const debateFile = join65(getDebateDir(debateId), "debate.md");
|
|
44392
44840
|
const { data } = readFrontmatter(debateFile);
|
|
44393
44841
|
const personas = Array.isArray(data.personas) ? data.personas.slice() : [];
|
|
44394
44842
|
if (!personas.includes(slug)) personas.push(slug);
|
|
@@ -44417,7 +44865,7 @@ function registerRound(council) {
|
|
|
44417
44865
|
error(`Round ${n} exceeds planned rounds (${data.rounds_planned}).`);
|
|
44418
44866
|
process.exit(1);
|
|
44419
44867
|
}
|
|
44420
|
-
const debateFile =
|
|
44868
|
+
const debateFile = join65(getDebateDir(debateId), "debate.md");
|
|
44421
44869
|
const personas = data.personas ?? [];
|
|
44422
44870
|
if (personas.length === 0) {
|
|
44423
44871
|
error("No personas registered. Run `council agent create` first.");
|
|
@@ -44426,9 +44874,9 @@ function registerRound(council) {
|
|
|
44426
44874
|
const crossContextHeader = `## Round ${n} \u2014 Cross-context loaded`;
|
|
44427
44875
|
if (n >= 2) {
|
|
44428
44876
|
for (const persona of personas) {
|
|
44429
|
-
const personaFile =
|
|
44430
|
-
if (!
|
|
44431
|
-
const existing =
|
|
44877
|
+
const personaFile = join65(getPersonaDir(debateId, persona), "context-and-persona.md");
|
|
44878
|
+
if (!existsSync68(personaFile)) continue;
|
|
44879
|
+
const existing = readFileSync50(personaFile, "utf-8");
|
|
44432
44880
|
if (existing.includes(crossContextHeader)) {
|
|
44433
44881
|
continue;
|
|
44434
44882
|
}
|
|
@@ -44450,7 +44898,7 @@ _(no round ${n - 1} report submitted)_`);
|
|
|
44450
44898
|
|
|
44451
44899
|
${peerLines.join("\n\n")}`;
|
|
44452
44900
|
const updated = existing.trimEnd() + "\n\n" + newSection + "\n";
|
|
44453
|
-
|
|
44901
|
+
writeFileSync35(personaFile, updated, "utf-8");
|
|
44454
44902
|
}
|
|
44455
44903
|
}
|
|
44456
44904
|
updateFrontmatterFields(debateFile, {
|
|
@@ -44458,13 +44906,13 @@ ${peerLines.join("\n\n")}`;
|
|
|
44458
44906
|
current_round: n,
|
|
44459
44907
|
updated_at: today()
|
|
44460
44908
|
});
|
|
44461
|
-
const logFile =
|
|
44462
|
-
const logExisting =
|
|
44909
|
+
const logFile = join65(getDebateDir(debateId), "round-log.md");
|
|
44910
|
+
const logExisting = existsSync68(logFile) ? readFileSync50(logFile, "utf-8") : "";
|
|
44463
44911
|
const logEntry = `
|
|
44464
44912
|
## Round ${n} started \u2014 ${today()}
|
|
44465
44913
|
- Personas: ${formatPersonaList(personas)}
|
|
44466
44914
|
`;
|
|
44467
|
-
|
|
44915
|
+
writeFileSync35(logFile, logExisting.trimEnd() + "\n" + logEntry + "\n", "utf-8");
|
|
44468
44916
|
upsertCouncilIndex({
|
|
44469
44917
|
id: debateId,
|
|
44470
44918
|
topic: data.topic,
|
|
@@ -44498,18 +44946,18 @@ ${peerLines.join("\n\n")}`;
|
|
|
44498
44946
|
error(`Round ${n} incomplete. Missing reports from: ${missing.join(", ")}`);
|
|
44499
44947
|
process.exit(1);
|
|
44500
44948
|
}
|
|
44501
|
-
const debateFile =
|
|
44949
|
+
const debateFile = join65(getDebateDir(debateId), "debate.md");
|
|
44502
44950
|
updateFrontmatterFields(debateFile, {
|
|
44503
44951
|
status: roundCompleteStatus(n),
|
|
44504
44952
|
updated_at: today()
|
|
44505
44953
|
});
|
|
44506
|
-
const logFile =
|
|
44507
|
-
const logExisting =
|
|
44954
|
+
const logFile = join65(getDebateDir(debateId), "round-log.md");
|
|
44955
|
+
const logExisting = existsSync68(logFile) ? readFileSync50(logFile, "utf-8") : "";
|
|
44508
44956
|
const logEntry = `
|
|
44509
44957
|
## Round ${n} complete \u2014 ${today()}
|
|
44510
44958
|
- All ${personas.length} personas submitted reports.
|
|
44511
44959
|
`;
|
|
44512
|
-
|
|
44960
|
+
writeFileSync35(logFile, logExisting.trimEnd() + "\n" + logEntry + "\n", "utf-8");
|
|
44513
44961
|
upsertCouncilIndex({
|
|
44514
44962
|
id: debateId,
|
|
44515
44963
|
topic: data.topic,
|
|
@@ -44532,8 +44980,8 @@ function registerRoundContext(council) {
|
|
|
44532
44980
|
try {
|
|
44533
44981
|
const data = readDebateFrontmatter(debateId);
|
|
44534
44982
|
ensurePersonaExists(debateId, personaSlug);
|
|
44535
|
-
const personaFile =
|
|
44536
|
-
const personaContent =
|
|
44983
|
+
const personaFile = join65(getPersonaDir(debateId, personaSlug), "context-and-persona.md");
|
|
44984
|
+
const personaContent = readFileSync50(personaFile, "utf-8");
|
|
44537
44985
|
console.log(`# Council debate: ${data.topic}`);
|
|
44538
44986
|
console.log(`Debate ID: ${debateId}`);
|
|
44539
44987
|
console.log(`Current round: ${data.current_round}/${data.rounds_planned}`);
|
|
@@ -44542,8 +44990,8 @@ function registerRoundContext(council) {
|
|
|
44542
44990
|
console.log("---");
|
|
44543
44991
|
console.log("");
|
|
44544
44992
|
console.log(personaContent);
|
|
44545
|
-
const debateFile =
|
|
44546
|
-
const debateRaw =
|
|
44993
|
+
const debateFile = join65(getDebateDir(debateId), "debate.md");
|
|
44994
|
+
const debateRaw = readFileSync50(debateFile, "utf-8");
|
|
44547
44995
|
const questionMatch = debateRaw.match(/##\s+Question\s*\n([\s\S]*?)(?=\n##\s|\Z)/);
|
|
44548
44996
|
const constraintsMatch = debateRaw.match(/##\s+Constraints & Known Facts\s*\n([\s\S]*?)(?=\n##\s|\Z)/);
|
|
44549
44997
|
if (questionMatch) {
|
|
@@ -44586,7 +45034,7 @@ function registerReport(council) {
|
|
|
44586
45034
|
process.exit(1);
|
|
44587
45035
|
}
|
|
44588
45036
|
for (const w of validation.warnings) warn(w);
|
|
44589
|
-
const reportFile =
|
|
45037
|
+
const reportFile = join65(getPersonaDir(debateId, personaSlug), "report.md");
|
|
44590
45038
|
const { data: reportData, content } = readFrontmatter(reportFile);
|
|
44591
45039
|
const existingRounds = parseReportRounds(content);
|
|
44592
45040
|
if (existingRounds.find((r) => r.round === round)) {
|
|
@@ -44608,7 +45056,7 @@ ${otherSerialized}
|
|
|
44608
45056
|
persona: personaSlug,
|
|
44609
45057
|
rounds_completed: Math.max(reportData.rounds_completed ?? 0, round)
|
|
44610
45058
|
}, "\n" + merged);
|
|
44611
|
-
const personaFile =
|
|
45059
|
+
const personaFile = join65(getPersonaDir(debateId, personaSlug), "context-and-persona.md");
|
|
44612
45060
|
const { data: pData } = readFrontmatter(personaFile);
|
|
44613
45061
|
updateFrontmatterFields(personaFile, {
|
|
44614
45062
|
round_entries: Math.max(pData.round_entries ?? 0, round)
|
|
@@ -44651,13 +45099,13 @@ function registerResearch(council) {
|
|
|
44651
45099
|
error("Research topic is required.");
|
|
44652
45100
|
process.exit(1);
|
|
44653
45101
|
}
|
|
44654
|
-
const researchesDir =
|
|
44655
|
-
|
|
44656
|
-
const indexPath2 =
|
|
44657
|
-
if (!
|
|
45102
|
+
const researchesDir = join65(getPersonaDir(debateId, personaSlug), "researches");
|
|
45103
|
+
mkdirSync28(researchesDir, { recursive: true });
|
|
45104
|
+
const indexPath2 = join65(researchesDir, "index.json");
|
|
45105
|
+
if (!existsSync68(indexPath2)) writeJsonArray(indexPath2, []);
|
|
44658
45106
|
const slug = slugify(topic);
|
|
44659
|
-
const file =
|
|
44660
|
-
if (
|
|
45107
|
+
const file = join65(researchesDir, `${slug}.md`);
|
|
45108
|
+
if (existsSync68(file)) {
|
|
44661
45109
|
error(`Research note already exists: ${slug}.md`);
|
|
44662
45110
|
process.exit(1);
|
|
44663
45111
|
}
|
|
@@ -44672,7 +45120,7 @@ _Added ${today()} by ${personaSlug}_
|
|
|
44672
45120
|
|
|
44673
45121
|
${body.trim()}
|
|
44674
45122
|
`;
|
|
44675
|
-
|
|
45123
|
+
writeFileSync35(file, noteContent, "utf-8");
|
|
44676
45124
|
insertToJsonArray(indexPath2, {
|
|
44677
45125
|
slug,
|
|
44678
45126
|
topic,
|
|
@@ -44687,9 +45135,9 @@ ${body.trim()}
|
|
|
44687
45135
|
research.command("list").argument("<debate_id>").argument("<persona_slug>").description("List this persona's prior research notes.").action((debateId, personaSlug) => {
|
|
44688
45136
|
try {
|
|
44689
45137
|
ensurePersonaExists(debateId, personaSlug);
|
|
44690
|
-
const researchesDir =
|
|
44691
|
-
const indexPath2 =
|
|
44692
|
-
if (!
|
|
45138
|
+
const researchesDir = join65(getPersonaDir(debateId, personaSlug), "researches");
|
|
45139
|
+
const indexPath2 = join65(researchesDir, "index.json");
|
|
45140
|
+
if (!existsSync68(indexPath2)) {
|
|
44693
45141
|
console.log(source_default.dim("(no researches)"));
|
|
44694
45142
|
return;
|
|
44695
45143
|
}
|
|
@@ -44711,7 +45159,7 @@ function registerSynthesize(council) {
|
|
|
44711
45159
|
council.command("synthesize").argument("<debate_id>").description("Mark status=synthesizing; print manifest of files synthesizer should read.").action((debateId) => {
|
|
44712
45160
|
try {
|
|
44713
45161
|
const data = readDebateFrontmatter(debateId);
|
|
44714
|
-
const debateFile =
|
|
45162
|
+
const debateFile = join65(getDebateDir(debateId), "debate.md");
|
|
44715
45163
|
updateFrontmatterFields(debateFile, {
|
|
44716
45164
|
status: "synthesizing",
|
|
44717
45165
|
updated_at: today()
|
|
@@ -44733,8 +45181,8 @@ function registerSynthesize(council) {
|
|
|
44733
45181
|
const personaDir = getPersonaDir(debateId, persona);
|
|
44734
45182
|
manifest.push(`_dream_context/council/${debateId}/${persona}/context-and-persona.md`);
|
|
44735
45183
|
manifest.push(`_dream_context/council/${debateId}/${persona}/report.md`);
|
|
44736
|
-
const researchesIndex =
|
|
44737
|
-
if (
|
|
45184
|
+
const researchesIndex = join65(personaDir, "researches", "index.json");
|
|
45185
|
+
if (existsSync68(researchesIndex)) {
|
|
44738
45186
|
manifest.push(`_dream_context/council/${debateId}/${persona}/researches/`);
|
|
44739
45187
|
}
|
|
44740
45188
|
}
|
|
@@ -44752,12 +45200,12 @@ function registerComplete(council) {
|
|
|
44752
45200
|
council.command("complete").argument("<debate_id>").description("Mark status=complete after final-report.md is written.").action((debateId) => {
|
|
44753
45201
|
try {
|
|
44754
45202
|
const data = readDebateFrontmatter(debateId);
|
|
44755
|
-
const finalReport =
|
|
44756
|
-
if (!
|
|
45203
|
+
const finalReport = join65(getDebateDir(debateId), "final-report.md");
|
|
45204
|
+
if (!existsSync68(finalReport)) {
|
|
44757
45205
|
error("final-report.md not found.", "Synthesizer must write it before calling `council complete`.");
|
|
44758
45206
|
process.exit(1);
|
|
44759
45207
|
}
|
|
44760
|
-
const debateFile =
|
|
45208
|
+
const debateFile = join65(getDebateDir(debateId), "debate.md");
|
|
44761
45209
|
updateFrontmatterFields(debateFile, {
|
|
44762
45210
|
status: "complete",
|
|
44763
45211
|
updated_at: today()
|
|
@@ -44789,8 +45237,8 @@ function registerPromote(council) {
|
|
|
44789
45237
|
error(`Cannot promote: debate status is "${data.status}", expected "complete".`);
|
|
44790
45238
|
process.exit(1);
|
|
44791
45239
|
}
|
|
44792
|
-
const finalReport =
|
|
44793
|
-
if (!
|
|
45240
|
+
const finalReport = join65(getDebateDir(debateId), "final-report.md");
|
|
45241
|
+
if (!existsSync68(finalReport)) {
|
|
44794
45242
|
error("final-report.md not found.");
|
|
44795
45243
|
process.exit(1);
|
|
44796
45244
|
}
|
|
@@ -44803,12 +45251,12 @@ function registerPromote(council) {
|
|
|
44803
45251
|
|
|
44804
45252
|
${sec.body.trim()}` : null;
|
|
44805
45253
|
}).filter(Boolean).join("\n\n");
|
|
44806
|
-
const knowledgeDir =
|
|
44807
|
-
|
|
45254
|
+
const knowledgeDir = join65(root, "knowledge");
|
|
45255
|
+
mkdirSync28(knowledgeDir, { recursive: true });
|
|
44808
45256
|
const slug = slugify(data.topic).slice(0, 80) || debateId;
|
|
44809
45257
|
const filename = `decision-${slug}.md`;
|
|
44810
|
-
const target =
|
|
44811
|
-
if (
|
|
45258
|
+
const target = join65(knowledgeDir, filename);
|
|
45259
|
+
if (existsSync68(target) && !opts.force) {
|
|
44812
45260
|
error(`Knowledge file exists: ${filename}`, "Use --force to overwrite.");
|
|
44813
45261
|
process.exit(1);
|
|
44814
45262
|
}
|
|
@@ -44832,7 +45280,7 @@ ${kept}
|
|
|
44832
45280
|
_Promoted from council debate \`${debateId}\` on ${today()}. See \`_dream_context/council/${debateId}/final-report.md\` for the full record._
|
|
44833
45281
|
`;
|
|
44834
45282
|
writeFrontmatter(target, knowledgeFrontmatter, body);
|
|
44835
|
-
updateFrontmatterFields(
|
|
45283
|
+
updateFrontmatterFields(join65(getDebateDir(debateId), "debate.md"), {
|
|
44836
45284
|
promoted_to_knowledge: `knowledge/${filename}`,
|
|
44837
45285
|
updated_at: today()
|
|
44838
45286
|
});
|
|
@@ -44894,10 +45342,10 @@ function registerShow(council) {
|
|
|
44894
45342
|
console.log(` promoted: ${data.promoted_to_knowledge ?? source_default.dim("(no)")}`);
|
|
44895
45343
|
console.log(` created: ${data.created_at}`);
|
|
44896
45344
|
console.log(` updated: ${data.updated_at}`);
|
|
44897
|
-
const logFile =
|
|
44898
|
-
if (
|
|
45345
|
+
const logFile = join65(getDebateDir(debateId), "round-log.md");
|
|
45346
|
+
if (existsSync68(logFile)) {
|
|
44899
45347
|
console.log("\n" + source_default.dim("\u2500\u2500\u2500 Round log \u2500\u2500\u2500"));
|
|
44900
|
-
console.log(
|
|
45348
|
+
console.log(readFileSync50(logFile, "utf-8"));
|
|
44901
45349
|
}
|
|
44902
45350
|
} catch (err) {
|
|
44903
45351
|
error(err.message);
|
|
@@ -45089,12 +45537,12 @@ var init_env_loader = __esm({
|
|
|
45089
45537
|
});
|
|
45090
45538
|
|
|
45091
45539
|
// src/lib/marketing/config.ts
|
|
45092
|
-
import { existsSync as
|
|
45093
|
-
import { dirname as
|
|
45540
|
+
import { existsSync as existsSync69, readFileSync as readFileSync51, writeFileSync as writeFileSync36, mkdirSync as mkdirSync29 } from "fs";
|
|
45541
|
+
import { dirname as dirname38 } from "path";
|
|
45094
45542
|
function readEnvFile() {
|
|
45095
45543
|
const path2 = MARKETING_PATHS.envFile();
|
|
45096
|
-
if (!
|
|
45097
|
-
const raw =
|
|
45544
|
+
if (!existsSync69(path2)) return {};
|
|
45545
|
+
const raw = readFileSync51(path2, "utf8");
|
|
45098
45546
|
const parsed = parseEnv(raw);
|
|
45099
45547
|
if (parsed.errors.length > 0) {
|
|
45100
45548
|
for (const e of parsed.errors) {
|
|
@@ -45138,9 +45586,9 @@ function requireEnv(keys = REQUIRED_KEYS) {
|
|
|
45138
45586
|
}
|
|
45139
45587
|
function loadConfig() {
|
|
45140
45588
|
const path2 = MARKETING_PATHS.configFile();
|
|
45141
|
-
if (!
|
|
45589
|
+
if (!existsSync69(path2)) return { ...EMPTY_CONFIG, feature_flags: { ...EMPTY_CONFIG.feature_flags } };
|
|
45142
45590
|
try {
|
|
45143
|
-
const raw =
|
|
45591
|
+
const raw = readFileSync51(path2, "utf8");
|
|
45144
45592
|
const parsed = JSON.parse(raw);
|
|
45145
45593
|
return {
|
|
45146
45594
|
default_profile: parsed.default_profile ?? null,
|
|
@@ -45155,21 +45603,21 @@ function loadConfig() {
|
|
|
45155
45603
|
}
|
|
45156
45604
|
function writeConfig(cfg) {
|
|
45157
45605
|
const path2 = MARKETING_PATHS.configFile();
|
|
45158
|
-
|
|
45159
|
-
|
|
45606
|
+
mkdirSync29(dirname38(path2), { recursive: true });
|
|
45607
|
+
writeFileSync36(path2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
45160
45608
|
}
|
|
45161
45609
|
function ensureConfigFile() {
|
|
45162
45610
|
const path2 = MARKETING_PATHS.configFile();
|
|
45163
|
-
if (
|
|
45611
|
+
if (existsSync69(path2)) return loadConfig();
|
|
45164
45612
|
const cfg = { ...EMPTY_CONFIG, feature_flags: { ...EMPTY_CONFIG.feature_flags } };
|
|
45165
45613
|
writeConfig(cfg);
|
|
45166
45614
|
return cfg;
|
|
45167
45615
|
}
|
|
45168
45616
|
function ensureEnvFile() {
|
|
45169
45617
|
const path2 = MARKETING_PATHS.envFile();
|
|
45170
|
-
if (
|
|
45171
|
-
|
|
45172
|
-
|
|
45618
|
+
if (existsSync69(path2)) return;
|
|
45619
|
+
mkdirSync29(marketingRoot(), { recursive: true });
|
|
45620
|
+
writeFileSync36(path2, ENV_TEMPLATE, { encoding: "utf8", mode: 384 });
|
|
45173
45621
|
}
|
|
45174
45622
|
var DEFAULT_API_VERSION, EMPTY_CONFIG, REQUIRED_KEYS, OPTIONAL_KEYS, ENV_TEMPLATE;
|
|
45175
45623
|
var init_config2 = __esm({
|
|
@@ -45210,9 +45658,9 @@ REINFLUENCE_BIN= # optional override; default uses .venv
|
|
|
45210
45658
|
|
|
45211
45659
|
// src/lib/marketing/bootstrap.ts
|
|
45212
45660
|
import { spawn as spawn5, spawnSync as spawnSync2 } from "child_process";
|
|
45213
|
-
import { existsSync as
|
|
45661
|
+
import { existsSync as existsSync70, mkdirSync as mkdirSync30, cpSync as cpSync3 } from "fs";
|
|
45214
45662
|
import { fileURLToPath as fileURLToPath8 } from "url";
|
|
45215
|
-
import { dirname as
|
|
45663
|
+
import { dirname as dirname39, resolve as resolve17, join as join66 } from "path";
|
|
45216
45664
|
function findBundledReinfluence() {
|
|
45217
45665
|
const candidates = [
|
|
45218
45666
|
// Installed npm package: dist/<chunk>.js -> ../tools/reinfluence
|
|
@@ -45222,7 +45670,7 @@ function findBundledReinfluence() {
|
|
|
45222
45670
|
resolve17(__dirname7, "..", "..", "..", "tools", "reinfluence")
|
|
45223
45671
|
];
|
|
45224
45672
|
for (const c of candidates) {
|
|
45225
|
-
if (
|
|
45673
|
+
if (existsSync70(join66(c, "__main__.py"))) return c;
|
|
45226
45674
|
}
|
|
45227
45675
|
throw new Error(
|
|
45228
45676
|
"Bundled reinfluence not found. Reinstall dreamcontext or set REINFLUENCE_BIN."
|
|
@@ -45253,18 +45701,18 @@ async function bootstrapMarketing(opts = {}) {
|
|
|
45253
45701
|
if (verbose) process.stderr.write(`[mk init] ${msg}
|
|
45254
45702
|
`);
|
|
45255
45703
|
};
|
|
45256
|
-
|
|
45704
|
+
mkdirSync30(marketingRoot(), { recursive: true });
|
|
45257
45705
|
const bundled = findBundledReinfluence();
|
|
45258
45706
|
const target = MARKETING_PATHS.reinfluenceDir();
|
|
45259
45707
|
log(`copying tools \u2192 ${target}`);
|
|
45260
|
-
|
|
45708
|
+
mkdirSync30(MARKETING_PATHS.toolsDir(), { recursive: true });
|
|
45261
45709
|
cpSync3(bundled, target, { recursive: true });
|
|
45262
45710
|
const py = findPython3();
|
|
45263
45711
|
if (!py) {
|
|
45264
45712
|
throw new Error("python3 not found on PATH. Install Python 3.10+ and retry.");
|
|
45265
45713
|
}
|
|
45266
45714
|
const venv = MARKETING_PATHS.venvDir();
|
|
45267
|
-
if (!
|
|
45715
|
+
if (!existsSync70(MARKETING_PATHS.venvPython())) {
|
|
45268
45716
|
log(`creating venv \u2192 ${venv}`);
|
|
45269
45717
|
const r2 = runBlocking(py, ["-m", "venv", venv]);
|
|
45270
45718
|
if (r2.code !== 0) {
|
|
@@ -45277,7 +45725,7 @@ async function bootstrapMarketing(opts = {}) {
|
|
|
45277
45725
|
log("upgrading pip");
|
|
45278
45726
|
let r = runBlocking(venvPy, ["-m", "pip", "install", "--upgrade", "pip", "--quiet"]);
|
|
45279
45727
|
if (r.code !== 0) log(`pip upgrade warning: ${r.stderr.trim().slice(0, 200)}`);
|
|
45280
|
-
const reqs =
|
|
45728
|
+
const reqs = join66(target, "requirements.txt");
|
|
45281
45729
|
log("installing python deps (whisper / yt-dlp / instaloader) \u2014 first run can take several minutes");
|
|
45282
45730
|
r = runBlocking(venvPy, ["-m", "pip", "install", "-r", reqs, "--quiet"]);
|
|
45283
45731
|
if (r.code !== 0) {
|
|
@@ -45287,7 +45735,7 @@ ${r.stderr.trim() || r.stdout.trim()}`);
|
|
|
45287
45735
|
let whisperPrimed = false;
|
|
45288
45736
|
if (whisperModel) {
|
|
45289
45737
|
log(`pre-pulling whisper model "${whisperModel}" into ${MARKETING_PATHS.whisperCacheDir()}`);
|
|
45290
|
-
|
|
45738
|
+
mkdirSync30(MARKETING_PATHS.whisperCacheDir(), { recursive: true });
|
|
45291
45739
|
whisperPrimed = await primeWhisper(whisperModel);
|
|
45292
45740
|
if (!whisperPrimed) log("whisper pre-pull failed (will retry on first ingest)");
|
|
45293
45741
|
}
|
|
@@ -45327,15 +45775,15 @@ function subprocessEnv() {
|
|
|
45327
45775
|
return {
|
|
45328
45776
|
...process.env,
|
|
45329
45777
|
XDG_CACHE_HOME: cache,
|
|
45330
|
-
HF_HOME:
|
|
45331
|
-
TRANSFORMERS_CACHE:
|
|
45778
|
+
HF_HOME: join66(cache, "hf"),
|
|
45779
|
+
TRANSFORMERS_CACHE: join66(cache, "hf", "transformers"),
|
|
45332
45780
|
WHISPER_CACHE_DIR: MARKETING_PATHS.whisperCacheDir(),
|
|
45333
45781
|
PYTHONUNBUFFERED: "1",
|
|
45334
45782
|
PYTHONPATH: MARKETING_PATHS.toolsDir()
|
|
45335
45783
|
};
|
|
45336
45784
|
}
|
|
45337
45785
|
function isBootstrapped() {
|
|
45338
|
-
return
|
|
45786
|
+
return existsSync70(MARKETING_PATHS.venvPython()) && existsSync70(join66(MARKETING_PATHS.reinfluenceDir(), "__main__.py"));
|
|
45339
45787
|
}
|
|
45340
45788
|
var __filename, __dirname7;
|
|
45341
45789
|
var init_bootstrap = __esm({
|
|
@@ -45343,12 +45791,12 @@ var init_bootstrap = __esm({
|
|
|
45343
45791
|
"use strict";
|
|
45344
45792
|
init_paths2();
|
|
45345
45793
|
__filename = fileURLToPath8(import.meta.url);
|
|
45346
|
-
__dirname7 =
|
|
45794
|
+
__dirname7 = dirname39(__filename);
|
|
45347
45795
|
}
|
|
45348
45796
|
});
|
|
45349
45797
|
|
|
45350
45798
|
// src/cli/commands/marketing/init.ts
|
|
45351
|
-
import { mkdirSync as
|
|
45799
|
+
import { mkdirSync as mkdirSync31 } from "fs";
|
|
45352
45800
|
function registerMarketingInit(parent) {
|
|
45353
45801
|
parent.command("init").description("Bootstrap _dream_context/marketing/ (folders, .env, venv, reinfluence tools, whisper cache)").option("--skip-bootstrap", "Only create folders + .env template; skip venv + pip install", false).option("--whisper-model <model>", "Whisper model to pre-pull (default: medium)", "medium").option("--no-whisper", "Skip Whisper model pre-pull").action(async (opts) => {
|
|
45354
45802
|
try {
|
|
@@ -45359,7 +45807,7 @@ function registerMarketingInit(parent) {
|
|
|
45359
45807
|
}
|
|
45360
45808
|
console.log(header("Marketing init"));
|
|
45361
45809
|
const root = marketingRoot();
|
|
45362
|
-
|
|
45810
|
+
mkdirSync31(root, { recursive: true });
|
|
45363
45811
|
for (const dir of [
|
|
45364
45812
|
MARKETING_PATHS.cohortsDir(),
|
|
45365
45813
|
MARKETING_PATHS.campaignsDir(),
|
|
@@ -45372,7 +45820,7 @@ function registerMarketingInit(parent) {
|
|
|
45372
45820
|
MARKETING_PATHS.byIdemDir(),
|
|
45373
45821
|
MARKETING_PATHS.cacheDir()
|
|
45374
45822
|
]) {
|
|
45375
|
-
|
|
45823
|
+
mkdirSync31(dir, { recursive: true });
|
|
45376
45824
|
}
|
|
45377
45825
|
info(`folders ready under ${source_default.dim(root)}`);
|
|
45378
45826
|
ensureEnvFile();
|
|
@@ -45412,8 +45860,8 @@ var init_init2 = __esm({
|
|
|
45412
45860
|
});
|
|
45413
45861
|
|
|
45414
45862
|
// src/lib/marketing/vision.ts
|
|
45415
|
-
import { existsSync as
|
|
45416
|
-
import { dirname as
|
|
45863
|
+
import { existsSync as existsSync71, readFileSync as readFileSync52, writeFileSync as writeFileSync37 } from "fs";
|
|
45864
|
+
import { dirname as dirname40, join as join67 } from "path";
|
|
45417
45865
|
function pickVisionProvider(env2 = process.env) {
|
|
45418
45866
|
const oai = env2.OPENAI_VISION_API_KEY;
|
|
45419
45867
|
if (oai && oai.trim().length > 0) return { provider: "openai", apiKey: oai.trim() };
|
|
@@ -45452,11 +45900,11 @@ function parseLabelsFromText(text, allowlist = LABEL_ALLOWLIST) {
|
|
|
45452
45900
|
return out;
|
|
45453
45901
|
}
|
|
45454
45902
|
async function readImageAsBase64(framePath) {
|
|
45455
|
-
const buf =
|
|
45903
|
+
const buf = readFileSync52(framePath);
|
|
45456
45904
|
return buf.toString("base64");
|
|
45457
45905
|
}
|
|
45458
45906
|
async function labelHookFrame(framePath, opts) {
|
|
45459
|
-
if (!
|
|
45907
|
+
if (!existsSync71(framePath)) return [];
|
|
45460
45908
|
const fetcher = opts.fetcher ?? defaultFetcher;
|
|
45461
45909
|
const prompt = opts.promptOverride ?? PROMPT;
|
|
45462
45910
|
const b64 = await readImageAsBase64(framePath);
|
|
@@ -45506,7 +45954,7 @@ async function labelHookFrame(framePath, opts) {
|
|
|
45506
45954
|
return parseLabelsFromText(text);
|
|
45507
45955
|
}
|
|
45508
45956
|
async function runVisionPassOnPost(postJsonPath, opts = {}) {
|
|
45509
|
-
const raw =
|
|
45957
|
+
const raw = readFileSync52(postJsonPath, "utf-8");
|
|
45510
45958
|
const post = JSON.parse(raw);
|
|
45511
45959
|
const shortcode = post.shortcode ?? "?";
|
|
45512
45960
|
const provider = opts.provider && opts.apiKey ? { provider: opts.provider, apiKey: opts.apiKey } : pickVisionProvider();
|
|
@@ -45545,15 +45993,15 @@ async function runVisionPassOnPost(postJsonPath, opts = {}) {
|
|
|
45545
45993
|
post.pattern_tags = [...aggregated].sort();
|
|
45546
45994
|
post.vision_summary = post.pattern_tags.length > 0 ? `Vision-tagged ${framesLabeled}/${hookFrames.length} hook frames; patterns: ${post.pattern_tags.join(", ")}.` : `Vision pass found no allowlisted patterns across ${hookFrames.length} hook frames.`;
|
|
45547
45995
|
const tmp = postJsonPath + ".tmp";
|
|
45548
|
-
|
|
45996
|
+
writeFileSync37(tmp, JSON.stringify(post, null, 2) + "\n", "utf-8");
|
|
45549
45997
|
const fs = await import("fs");
|
|
45550
45998
|
fs.renameSync(tmp, postJsonPath);
|
|
45551
|
-
const mdPath =
|
|
45552
|
-
if (
|
|
45999
|
+
const mdPath = join67(dirname40(postJsonPath), `${shortcode}.md`);
|
|
46000
|
+
if (existsSync71(mdPath)) {
|
|
45553
46001
|
try {
|
|
45554
|
-
const md =
|
|
46002
|
+
const md = readFileSync52(mdPath, "utf-8");
|
|
45555
46003
|
const refreshed = updatePatternTagsInBridge(md, post.pattern_tags);
|
|
45556
|
-
|
|
46004
|
+
writeFileSync37(mdPath, refreshed, "utf-8");
|
|
45557
46005
|
} catch {
|
|
45558
46006
|
}
|
|
45559
46007
|
}
|
|
@@ -45628,8 +46076,8 @@ Example output: ["talking-head","prop-driven"]`;
|
|
|
45628
46076
|
// src/lib/marketing/competitors.ts
|
|
45629
46077
|
import { spawn as spawn6 } from "child_process";
|
|
45630
46078
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
45631
|
-
import { existsSync as
|
|
45632
|
-
import { dirname as
|
|
46079
|
+
import { existsSync as existsSync72, mkdirSync as mkdirSync32, statfsSync } from "fs";
|
|
46080
|
+
import { dirname as dirname41, join as join68, basename as basename20, extname as extname4 } from "path";
|
|
45633
46081
|
function which(cmd) {
|
|
45634
46082
|
const r = spawnSync3(process.platform === "win32" ? "where" : "which", [cmd], { encoding: "utf8" });
|
|
45635
46083
|
if (r.status === 0) return (r.stdout || "").trim().split("\n")[0] || null;
|
|
@@ -45706,8 +46154,8 @@ ${h.installHints.join("\n")}`);
|
|
|
45706
46154
|
skip_transcripts: !!opts.skipTranscripts,
|
|
45707
46155
|
skip_frames: !!opts.skipFrames
|
|
45708
46156
|
});
|
|
45709
|
-
const outDir =
|
|
45710
|
-
|
|
46157
|
+
const outDir = join68(MARKETING_PATHS.competitorsDir(), "_ingest-tmp", run2.id);
|
|
46158
|
+
mkdirSync32(outDir, { recursive: true });
|
|
45711
46159
|
const args = [
|
|
45712
46160
|
"-m",
|
|
45713
46161
|
"reinfluence",
|
|
@@ -45807,15 +46255,15 @@ stderr: ${stderrBuf.slice(0, 1e3)}`));
|
|
|
45807
46255
|
return { runId: run2.id, postsIngested, warnings, errors };
|
|
45808
46256
|
}
|
|
45809
46257
|
function persistPost(evt) {
|
|
45810
|
-
const handleDir =
|
|
45811
|
-
const postsDir =
|
|
45812
|
-
const mediaDir =
|
|
45813
|
-
|
|
45814
|
-
|
|
45815
|
-
const finalVideoPath = evt.video_path ? moveAsset(evt.video_path,
|
|
46258
|
+
const handleDir = join68(MARKETING_PATHS.competitorsDir(), evt.handle);
|
|
46259
|
+
const postsDir = join68(handleDir, "posts");
|
|
46260
|
+
const mediaDir = join68(handleDir, "_media", evt.shortcode);
|
|
46261
|
+
mkdirSync32(postsDir, { recursive: true });
|
|
46262
|
+
mkdirSync32(mediaDir, { recursive: true });
|
|
46263
|
+
const finalVideoPath = evt.video_path ? moveAsset(evt.video_path, join68(mediaDir, basename20(evt.video_path))) : null;
|
|
45816
46264
|
const finalFramePaths = [];
|
|
45817
46265
|
for (const fr of evt.frames) {
|
|
45818
|
-
const finalP = moveAsset(fr.path,
|
|
46266
|
+
const finalP = moveAsset(fr.path, join68(mediaDir, "frames", basename20(fr.path)));
|
|
45819
46267
|
finalFramePaths.push(finalP);
|
|
45820
46268
|
}
|
|
45821
46269
|
const id = `${evt.handle}__${evt.shortcode}`;
|
|
@@ -45835,14 +46283,14 @@ function persistPost(evt) {
|
|
|
45835
46283
|
ingested_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
45836
46284
|
asset_paths: { video: finalVideoPath, frames: finalFramePaths }
|
|
45837
46285
|
};
|
|
45838
|
-
const jsonPath =
|
|
45839
|
-
const bridgePath =
|
|
46286
|
+
const jsonPath = join68(postsDir, `${evt.shortcode}.json`);
|
|
46287
|
+
const bridgePath = join68(postsDir, `${evt.shortcode}.md`);
|
|
45840
46288
|
writeJsonWithBridge(jsonPath, bridgePath, json, renderPostBridge(json));
|
|
45841
|
-
const metaPath =
|
|
45842
|
-
if (!
|
|
46289
|
+
const metaPath = join68(handleDir, "meta.json");
|
|
46290
|
+
if (!existsSync72(metaPath)) {
|
|
45843
46291
|
writeJsonWithBridge(
|
|
45844
46292
|
metaPath,
|
|
45845
|
-
|
|
46293
|
+
join68(handleDir, "meta.md"),
|
|
45846
46294
|
{ handle: evt.handle, first_seen_at: (/* @__PURE__ */ new Date()).toISOString() },
|
|
45847
46295
|
`---
|
|
45848
46296
|
id: competitor_${evt.handle}
|
|
@@ -45859,8 +46307,8 @@ First seen: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
|
45859
46307
|
return jsonPath;
|
|
45860
46308
|
}
|
|
45861
46309
|
function moveAsset(src, dest) {
|
|
45862
|
-
if (!
|
|
45863
|
-
|
|
46310
|
+
if (!existsSync72(src)) return dest;
|
|
46311
|
+
mkdirSync32(dirname41(dest), { recursive: true });
|
|
45864
46312
|
const fs = __require("fs");
|
|
45865
46313
|
try {
|
|
45866
46314
|
fs.renameSync(src, dest);
|
|
@@ -45921,8 +46369,8 @@ var init_competitors = __esm({
|
|
|
45921
46369
|
});
|
|
45922
46370
|
|
|
45923
46371
|
// src/cli/commands/marketing/competitor.ts
|
|
45924
|
-
import { existsSync as
|
|
45925
|
-
import { join as
|
|
46372
|
+
import { existsSync as existsSync73, readdirSync as readdirSync16, statSync as statSync11 } from "fs";
|
|
46373
|
+
import { join as join69 } from "path";
|
|
45926
46374
|
function registerMarketingCompetitor(parent) {
|
|
45927
46375
|
const cmd = parent.command("competitor").description("Ingest competitor IG / YouTube content (Reinfluence pipeline).");
|
|
45928
46376
|
cmd.command("ingest <target>").description("Ingest a single URL or an IG handle. Outputs land under _dream_context/marketing/competitors/<handle>/.").option("--model <name>", "Whisper model size (tiny|base|small|medium|large)", "medium").option("--max <n>", "Max reels for IG handle ingest (0 = all)", "0").option("--skip-transcripts", "Skip Whisper transcription", false).option("--skip-frames", "Skip frame extraction", false).option("--timeout <seconds>", "Wall-clock kill", "600").action(async (target, opts) => {
|
|
@@ -45972,13 +46420,13 @@ function registerMarketingCompetitor(parent) {
|
|
|
45972
46420
|
});
|
|
45973
46421
|
cmd.command("list").description("List ingested competitor handles.").action(() => {
|
|
45974
46422
|
const dir = MARKETING_PATHS.competitorsDir();
|
|
45975
|
-
if (!
|
|
46423
|
+
if (!existsSync73(dir)) {
|
|
45976
46424
|
info("No competitors ingested yet.");
|
|
45977
46425
|
return;
|
|
45978
46426
|
}
|
|
45979
46427
|
const handles = readdirSync16(dir).filter((name) => {
|
|
45980
46428
|
if (name.startsWith("_") || name.startsWith(".")) return false;
|
|
45981
|
-
const full =
|
|
46429
|
+
const full = join69(dir, name);
|
|
45982
46430
|
try {
|
|
45983
46431
|
return statSync11(full).isDirectory();
|
|
45984
46432
|
} catch {
|
|
@@ -45991,8 +46439,8 @@ function registerMarketingCompetitor(parent) {
|
|
|
45991
46439
|
}
|
|
45992
46440
|
console.log(header("Competitors"));
|
|
45993
46441
|
for (const handle of handles) {
|
|
45994
|
-
const postsDir =
|
|
45995
|
-
const postCount =
|
|
46442
|
+
const postsDir = join69(dir, handle, "posts");
|
|
46443
|
+
const postCount = existsSync73(postsDir) ? readdirSync16(postsDir).filter((f) => f.endsWith(".json")).length : 0;
|
|
45996
46444
|
console.log(` ${source_default.cyan("@" + handle)} ${source_default.dim(`${postCount} post(s)`)}`);
|
|
45997
46445
|
}
|
|
45998
46446
|
});
|
|
@@ -46005,11 +46453,11 @@ function registerMarketingCompetitor(parent) {
|
|
|
46005
46453
|
}
|
|
46006
46454
|
info(`Provider: ${provider.provider}`);
|
|
46007
46455
|
const competitorsDir = MARKETING_PATHS.competitorsDir();
|
|
46008
|
-
const handles = opts.handle ? [opts.handle] :
|
|
46456
|
+
const handles = opts.handle ? [opts.handle] : existsSync73(competitorsDir) ? readdirSync16(competitorsDir).filter((h) => !h.startsWith("_") && statSync11(join69(competitorsDir, h)).isDirectory()) : [];
|
|
46009
46457
|
const matches = [];
|
|
46010
46458
|
for (const h of handles) {
|
|
46011
|
-
const candidate =
|
|
46012
|
-
if (
|
|
46459
|
+
const candidate = join69(competitorsDir, h, "posts", `${shortcode}.json`);
|
|
46460
|
+
if (existsSync73(candidate)) matches.push(candidate);
|
|
46013
46461
|
}
|
|
46014
46462
|
if (matches.length === 0) {
|
|
46015
46463
|
error(`No post JSON found for shortcode "${shortcode}".`);
|
|
@@ -46044,18 +46492,18 @@ function registerMarketingCompetitor(parent) {
|
|
|
46044
46492
|
process.exit(1);
|
|
46045
46493
|
}
|
|
46046
46494
|
const competitorsDir = MARKETING_PATHS.competitorsDir();
|
|
46047
|
-
if (!
|
|
46495
|
+
if (!existsSync73(competitorsDir)) {
|
|
46048
46496
|
warn("No competitors directory yet \u2014 nothing to relabel.");
|
|
46049
46497
|
return;
|
|
46050
46498
|
}
|
|
46051
|
-
const handles = readdirSync16(competitorsDir).filter((h) => !h.startsWith("_") && statSync11(
|
|
46499
|
+
const handles = readdirSync16(competitorsDir).filter((h) => !h.startsWith("_") && statSync11(join69(competitorsDir, h)).isDirectory());
|
|
46052
46500
|
let labeled = 0;
|
|
46053
46501
|
let skipped = 0;
|
|
46054
46502
|
for (const h of handles) {
|
|
46055
|
-
const postsDir =
|
|
46056
|
-
if (!
|
|
46503
|
+
const postsDir = join69(competitorsDir, h, "posts");
|
|
46504
|
+
if (!existsSync73(postsDir)) continue;
|
|
46057
46505
|
for (const f of readdirSync16(postsDir).filter((n) => n.endsWith(".json"))) {
|
|
46058
|
-
const path2 =
|
|
46506
|
+
const path2 = join69(postsDir, f);
|
|
46059
46507
|
if (opts.dryRun) {
|
|
46060
46508
|
info(`would relabel: ${path2}`);
|
|
46061
46509
|
continue;
|
|
@@ -46102,8 +46550,8 @@ var init_competitor = __esm({
|
|
|
46102
46550
|
});
|
|
46103
46551
|
|
|
46104
46552
|
// src/lib/marketing/meta-fetch.ts
|
|
46105
|
-
import { existsSync as
|
|
46106
|
-
import { dirname as
|
|
46553
|
+
import { existsSync as existsSync74, mkdirSync as mkdirSync33, readFileSync as readFileSync53, writeFileSync as writeFileSync38, statSync as statSync12, openSync as openSync2, readSync, closeSync as closeSync2 } from "fs";
|
|
46554
|
+
import { dirname as dirname42, basename as basename21 } from "path";
|
|
46107
46555
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
46108
46556
|
function getQueue(accountId) {
|
|
46109
46557
|
let q = writeQueues.get(accountId);
|
|
@@ -46153,17 +46601,17 @@ function idemCachePath(key) {
|
|
|
46153
46601
|
}
|
|
46154
46602
|
function readIdem(key) {
|
|
46155
46603
|
const p = idemCachePath(key);
|
|
46156
|
-
if (!
|
|
46604
|
+
if (!existsSync74(p)) return null;
|
|
46157
46605
|
try {
|
|
46158
|
-
return JSON.parse(
|
|
46606
|
+
return JSON.parse(readFileSync53(p, "utf8"));
|
|
46159
46607
|
} catch {
|
|
46160
46608
|
return null;
|
|
46161
46609
|
}
|
|
46162
46610
|
}
|
|
46163
46611
|
function writeIdem(rec) {
|
|
46164
46612
|
const p = idemCachePath(rec.key);
|
|
46165
|
-
|
|
46166
|
-
|
|
46613
|
+
mkdirSync33(dirname42(p), { recursive: true });
|
|
46614
|
+
writeFileSync38(p, JSON.stringify(rec, null, 2) + "\n", "utf8");
|
|
46167
46615
|
}
|
|
46168
46616
|
function backoffMs(attempt, hintSec) {
|
|
46169
46617
|
if (hintSec != null && Number.isFinite(hintSec) && hintSec > 0) {
|
|
@@ -46431,7 +46879,7 @@ async function singleShotVideoUpload(ctx, filepath, fields) {
|
|
|
46431
46879
|
if (fields.name) form.set("name", fields.name);
|
|
46432
46880
|
if (fields.title) form.set("title", fields.title);
|
|
46433
46881
|
if (fields.description) form.set("description", fields.description);
|
|
46434
|
-
const buffer =
|
|
46882
|
+
const buffer = readFileSync53(filepath);
|
|
46435
46883
|
const blob = new Blob([new Uint8Array(buffer)], { type: "video/mp4" });
|
|
46436
46884
|
form.set("source", blob, basename21(filepath));
|
|
46437
46885
|
const resp = await fetch(url, {
|
|
@@ -46480,7 +46928,7 @@ async function uploadImageFile(ctx, filepath) {
|
|
|
46480
46928
|
return withWriteSlot(ctx.adAccountId, async () => {
|
|
46481
46929
|
const url = buildUrl(ctx, { method: "POST", path: `${ctx.adAccountId}/adimages` });
|
|
46482
46930
|
const form = new FormData();
|
|
46483
|
-
const buffer =
|
|
46931
|
+
const buffer = readFileSync53(filepath);
|
|
46484
46932
|
const blob = new Blob([new Uint8Array(buffer)], { type: "image/png" });
|
|
46485
46933
|
form.set("filename", blob, basename21(filepath));
|
|
46486
46934
|
const resp = await fetch(url, {
|
|
@@ -46899,7 +47347,7 @@ var init_account = __esm({
|
|
|
46899
47347
|
});
|
|
46900
47348
|
|
|
46901
47349
|
// src/lib/marketing/hypothesis.ts
|
|
46902
|
-
import { existsSync as
|
|
47350
|
+
import { existsSync as existsSync75, readFileSync as readFileSync54 } from "fs";
|
|
46903
47351
|
function validateHypothesis(raw, options2 = {}) {
|
|
46904
47352
|
const errors = [];
|
|
46905
47353
|
const fieldErrors = {};
|
|
@@ -46966,12 +47414,12 @@ function validateHypothesis(raw, options2 = {}) {
|
|
|
46966
47414
|
};
|
|
46967
47415
|
}
|
|
46968
47416
|
function loadHypothesisFile(path2, options2 = {}) {
|
|
46969
|
-
if (!
|
|
47417
|
+
if (!existsSync75(path2)) {
|
|
46970
47418
|
return { ok: false, errors: [`Hypothesis file not found: ${path2}`] };
|
|
46971
47419
|
}
|
|
46972
47420
|
let parsed;
|
|
46973
47421
|
try {
|
|
46974
|
-
parsed = JSON.parse(
|
|
47422
|
+
parsed = JSON.parse(readFileSync54(path2, "utf8"));
|
|
46975
47423
|
} catch (e) {
|
|
46976
47424
|
return { ok: false, errors: [`Failed to parse JSON at ${path2}: ${e.message}`] };
|
|
46977
47425
|
}
|
|
@@ -47159,8 +47607,8 @@ var init_cohort2 = __esm({
|
|
|
47159
47607
|
});
|
|
47160
47608
|
|
|
47161
47609
|
// src/lib/marketing/insights-cache.ts
|
|
47162
|
-
import { existsSync as
|
|
47163
|
-
import { join as
|
|
47610
|
+
import { existsSync as existsSync76, readFileSync as readFileSync55, mkdirSync as mkdirSync34, writeFileSync as writeFileSync39, readdirSync as readdirSync17, statSync as statSync13 } from "fs";
|
|
47611
|
+
import { join as join70 } from "path";
|
|
47164
47612
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
47165
47613
|
function snapshotFilename(entityId, pulledAt) {
|
|
47166
47614
|
const yyyy = pulledAt.getUTCFullYear();
|
|
@@ -47171,30 +47619,30 @@ function snapshotFilename(entityId, pulledAt) {
|
|
|
47171
47619
|
return `${safe}__${yyyy}-${mm}-${dd}-${hh}.json`;
|
|
47172
47620
|
}
|
|
47173
47621
|
function indexPath() {
|
|
47174
|
-
return
|
|
47622
|
+
return join70(MARKETING_PATHS.insightsDir(), "_index.json");
|
|
47175
47623
|
}
|
|
47176
47624
|
function readIndex() {
|
|
47177
47625
|
const p = indexPath();
|
|
47178
|
-
if (!
|
|
47626
|
+
if (!existsSync76(p)) return { latest: {}, updated_at: "1970-01-01T00:00:00Z" };
|
|
47179
47627
|
try {
|
|
47180
|
-
return JSON.parse(
|
|
47628
|
+
return JSON.parse(readFileSync55(p, "utf8"));
|
|
47181
47629
|
} catch {
|
|
47182
47630
|
return { latest: {}, updated_at: "1970-01-01T00:00:00Z" };
|
|
47183
47631
|
}
|
|
47184
47632
|
}
|
|
47185
47633
|
function writeIndex(idx) {
|
|
47186
47634
|
const p = indexPath();
|
|
47187
|
-
|
|
47635
|
+
mkdirSync34(MARKETING_PATHS.insightsDir(), { recursive: true });
|
|
47188
47636
|
const tmp = `${p}.tmp.${process.pid}.${randomBytes3(4).toString("hex")}`;
|
|
47189
|
-
|
|
47637
|
+
writeFileSync39(tmp, JSON.stringify(idx, null, 2) + "\n", "utf8");
|
|
47190
47638
|
__require("fs").renameSync(tmp, p);
|
|
47191
47639
|
}
|
|
47192
47640
|
function saveInsightsSnapshot(snap) {
|
|
47193
|
-
|
|
47641
|
+
mkdirSync34(MARKETING_PATHS.insightsDir(), { recursive: true });
|
|
47194
47642
|
const filename = snapshotFilename(snap.entity_id, new Date(snap.pulled_at));
|
|
47195
|
-
const fullPath =
|
|
47643
|
+
const fullPath = join70(MARKETING_PATHS.insightsDir(), filename);
|
|
47196
47644
|
const tmp = `${fullPath}.tmp.${process.pid}.${randomBytes3(4).toString("hex")}`;
|
|
47197
|
-
|
|
47645
|
+
writeFileSync39(tmp, JSON.stringify(snap, null, 2) + "\n", "utf8");
|
|
47198
47646
|
__require("fs").renameSync(tmp, fullPath);
|
|
47199
47647
|
const idx = readIndex();
|
|
47200
47648
|
idx.latest[snap.entity_id] = filename;
|
|
@@ -47206,10 +47654,10 @@ function getCachedInsights(entityId) {
|
|
|
47206
47654
|
const idx = readIndex();
|
|
47207
47655
|
const filename = idx.latest[entityId];
|
|
47208
47656
|
if (!filename) return null;
|
|
47209
|
-
const fullPath =
|
|
47210
|
-
if (!
|
|
47657
|
+
const fullPath = join70(MARKETING_PATHS.insightsDir(), filename);
|
|
47658
|
+
if (!existsSync76(fullPath)) return null;
|
|
47211
47659
|
try {
|
|
47212
|
-
const snap = JSON.parse(
|
|
47660
|
+
const snap = JSON.parse(readFileSync55(fullPath, "utf8"));
|
|
47213
47661
|
const ageMs = Date.now() - new Date(snap.pulled_at).getTime();
|
|
47214
47662
|
if (ageMs > INSIGHTS_TTL_MS) return null;
|
|
47215
47663
|
return snap;
|
|
@@ -47221,20 +47669,20 @@ function getLatestSnapshot(entityId) {
|
|
|
47221
47669
|
const idx = readIndex();
|
|
47222
47670
|
const filename = idx.latest[entityId];
|
|
47223
47671
|
if (!filename) return null;
|
|
47224
|
-
const fullPath =
|
|
47225
|
-
if (!
|
|
47672
|
+
const fullPath = join70(MARKETING_PATHS.insightsDir(), filename);
|
|
47673
|
+
if (!existsSync76(fullPath)) return null;
|
|
47226
47674
|
try {
|
|
47227
|
-
return JSON.parse(
|
|
47675
|
+
return JSON.parse(readFileSync55(fullPath, "utf8"));
|
|
47228
47676
|
} catch {
|
|
47229
47677
|
return null;
|
|
47230
47678
|
}
|
|
47231
47679
|
}
|
|
47232
47680
|
function getPriorSnapshot(entityId, beforeMs) {
|
|
47233
47681
|
const dir = MARKETING_PATHS.insightsDir();
|
|
47234
|
-
if (!
|
|
47682
|
+
if (!existsSync76(dir)) return null;
|
|
47235
47683
|
const safe = entityId.replace(/[^A-Za-z0-9_-]/g, "_");
|
|
47236
47684
|
const candidates = readdirSync17(dir).filter((f) => f.startsWith(`${safe}__`) && f.endsWith(".json")).map((f) => {
|
|
47237
|
-
const p =
|
|
47685
|
+
const p = join70(dir, f);
|
|
47238
47686
|
const stat = statSync13(p);
|
|
47239
47687
|
return { f, p, mtimeMs: stat.mtimeMs };
|
|
47240
47688
|
}).sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
@@ -47242,7 +47690,7 @@ function getPriorSnapshot(entityId, beforeMs) {
|
|
|
47242
47690
|
for (const c of candidates) {
|
|
47243
47691
|
if (c.mtimeMs <= cutoff) {
|
|
47244
47692
|
try {
|
|
47245
|
-
return JSON.parse(
|
|
47693
|
+
return JSON.parse(readFileSync55(c.p, "utf8"));
|
|
47246
47694
|
} catch {
|
|
47247
47695
|
continue;
|
|
47248
47696
|
}
|
|
@@ -47878,8 +48326,8 @@ var init_kill = __esm({
|
|
|
47878
48326
|
});
|
|
47879
48327
|
|
|
47880
48328
|
// src/cli/commands/marketing/doctor.ts
|
|
47881
|
-
import { readFileSync as
|
|
47882
|
-
import { join as
|
|
48329
|
+
import { readFileSync as readFileSync56, readdirSync as readdirSync18, statSync as statSync14 } from "fs";
|
|
48330
|
+
import { join as join71 } from "path";
|
|
47883
48331
|
function registerMarketingDoctor(parent) {
|
|
47884
48332
|
parent.command("doctor").description("Run diagnostics: env, FK integrity, retroactive secret scan, Reinfluence health.").option("--scan", "Run retroactive secret scan over the entire _dream_context/ tree", false).action(async (opts) => {
|
|
47885
48333
|
console.log(header("Marketing doctor"));
|
|
@@ -47960,7 +48408,7 @@ function scanForSecrets(root) {
|
|
|
47960
48408
|
for (const file of walkText(root)) {
|
|
47961
48409
|
let txt;
|
|
47962
48410
|
try {
|
|
47963
|
-
txt =
|
|
48411
|
+
txt = readFileSync56(file, "utf8");
|
|
47964
48412
|
} catch {
|
|
47965
48413
|
continue;
|
|
47966
48414
|
}
|
|
@@ -47987,7 +48435,7 @@ function* walkText(dir) {
|
|
|
47987
48435
|
}
|
|
47988
48436
|
for (const e of entries) {
|
|
47989
48437
|
if (e.startsWith(".") && (e === ".env" || e === ".env.local")) continue;
|
|
47990
|
-
const full =
|
|
48438
|
+
const full = join71(dir, e);
|
|
47991
48439
|
let stat;
|
|
47992
48440
|
try {
|
|
47993
48441
|
stat = statSync14(full);
|
|
@@ -48025,8 +48473,8 @@ var init_doctor2 = __esm({
|
|
|
48025
48473
|
});
|
|
48026
48474
|
|
|
48027
48475
|
// src/lib/marketing/entity-store.ts
|
|
48028
|
-
import { existsSync as
|
|
48029
|
-
import { join as
|
|
48476
|
+
import { existsSync as existsSync78, readFileSync as readFileSync57, readdirSync as readdirSync19 } from "fs";
|
|
48477
|
+
import { join as join72 } from "path";
|
|
48030
48478
|
function dirFor(kind) {
|
|
48031
48479
|
switch (kind) {
|
|
48032
48480
|
case "campaign":
|
|
@@ -48045,24 +48493,24 @@ function newEntityId(kind) {
|
|
|
48045
48493
|
}
|
|
48046
48494
|
function entityPaths(kind, id) {
|
|
48047
48495
|
const d = dirFor(kind);
|
|
48048
|
-
return { json:
|
|
48496
|
+
return { json: join72(d, `${id}.json`), md: join72(d, `${id}.md`) };
|
|
48049
48497
|
}
|
|
48050
48498
|
function loadEntity(kind, id) {
|
|
48051
48499
|
const { json } = entityPaths(kind, id);
|
|
48052
|
-
if (!
|
|
48500
|
+
if (!existsSync78(json)) return null;
|
|
48053
48501
|
try {
|
|
48054
|
-
return JSON.parse(
|
|
48502
|
+
return JSON.parse(readFileSync57(json, "utf8"));
|
|
48055
48503
|
} catch {
|
|
48056
48504
|
return null;
|
|
48057
48505
|
}
|
|
48058
48506
|
}
|
|
48059
48507
|
function listEntities(kind) {
|
|
48060
48508
|
const d = dirFor(kind);
|
|
48061
|
-
if (!
|
|
48509
|
+
if (!existsSync78(d)) return [];
|
|
48062
48510
|
const out = [];
|
|
48063
48511
|
for (const f of readdirSync19(d).filter((x) => x.endsWith(".json"))) {
|
|
48064
48512
|
try {
|
|
48065
|
-
out.push(JSON.parse(
|
|
48513
|
+
out.push(JSON.parse(readFileSync57(join72(d, f), "utf8")));
|
|
48066
48514
|
} catch {
|
|
48067
48515
|
}
|
|
48068
48516
|
}
|
|
@@ -48256,7 +48704,7 @@ var init_campaign = __esm({
|
|
|
48256
48704
|
});
|
|
48257
48705
|
|
|
48258
48706
|
// src/cli/commands/marketing/adset.ts
|
|
48259
|
-
import { existsSync as
|
|
48707
|
+
import { existsSync as existsSync79, readFileSync as readFileSync58 } from "fs";
|
|
48260
48708
|
function registerMarketingAdSet(parent) {
|
|
48261
48709
|
const cmd = parent.command("adset").description("Manage adsets.");
|
|
48262
48710
|
cmd.command("create").description("Create an adset (PAUSED). --daily-budget required (no fallback).").requiredOption("--campaign <id>", "parent campaign local id").requiredOption("--name <name>", "adset name").requiredOption("--daily-budget <amount>", "daily budget (major-currency units)").requiredOption("--targeting <file>", "JSON file with Meta targeting spec").option("--currency <code>", "currency code", "TRY").option("--optimization-goal <goal>", "OFFSITE_CONVERSIONS|LINK_CLICKS|...", "OFFSITE_CONVERSIONS").option("--billing-event <event>", "IMPRESSIONS|LINK_CLICKS|THRUPLAY", "IMPRESSIONS").option("--custom-event-type <evt>", "e.g. PURCHASE, COMPLETE_REGISTRATION (for OFFSITE_CONVERSIONS)").option("--no-dry-run", "Actually create on Meta").action(async (opts) => {
|
|
@@ -48276,13 +48724,13 @@ function registerMarketingAdSet(parent) {
|
|
|
48276
48724
|
}
|
|
48277
48725
|
throw e;
|
|
48278
48726
|
}
|
|
48279
|
-
if (!
|
|
48727
|
+
if (!existsSync79(opts.targeting)) {
|
|
48280
48728
|
error(`Targeting file not found: ${opts.targeting}`);
|
|
48281
48729
|
process.exit(1);
|
|
48282
48730
|
}
|
|
48283
48731
|
let targeting;
|
|
48284
48732
|
try {
|
|
48285
|
-
targeting = JSON.parse(
|
|
48733
|
+
targeting = JSON.parse(readFileSync58(opts.targeting, "utf8"));
|
|
48286
48734
|
} catch (e) {
|
|
48287
48735
|
error(`Failed to parse targeting JSON: ${e.message}`);
|
|
48288
48736
|
process.exit(1);
|
|
@@ -48539,12 +48987,12 @@ var init_creative = __esm({
|
|
|
48539
48987
|
});
|
|
48540
48988
|
|
|
48541
48989
|
// src/cli/commands/marketing/asset.ts
|
|
48542
|
-
import { existsSync as
|
|
48990
|
+
import { existsSync as existsSync80, statSync as statSync15 } from "fs";
|
|
48543
48991
|
import { extname as extname5 } from "path";
|
|
48544
48992
|
function registerMarketingAsset(parent) {
|
|
48545
48993
|
const cmd = parent.command("asset").description("Upload creative assets to Meta.");
|
|
48546
48994
|
cmd.command("upload <path>").description("Upload a video (>50MB \u2192 chunked) or image to Meta. Returns id/hash.").option("--type <type>", "override auto-detection (video|image)").option("--name <name>", "asset name (videos)").option("--no-dry-run", "Actually upload to Meta").action(async (path2, opts) => {
|
|
48547
|
-
if (!
|
|
48995
|
+
if (!existsSync80(path2)) {
|
|
48548
48996
|
error(`File not found: ${path2}`);
|
|
48549
48997
|
process.exit(1);
|
|
48550
48998
|
}
|
|
@@ -48712,8 +49160,8 @@ var init_ad = __esm({
|
|
|
48712
49160
|
});
|
|
48713
49161
|
|
|
48714
49162
|
// src/lib/marketing/launch.ts
|
|
48715
|
-
import { existsSync as
|
|
48716
|
-
import { dirname as
|
|
49163
|
+
import { existsSync as existsSync81, readFileSync as readFileSync59, writeFileSync as writeFileSync40, mkdirSync as mkdirSync35, renameSync as renameSync8, readdirSync as readdirSync20 } from "fs";
|
|
49164
|
+
import { dirname as dirname43, join as join73, basename as basename22 } from "path";
|
|
48717
49165
|
import { randomBytes as randomBytes4 } from "crypto";
|
|
48718
49166
|
function buildLaunchSummary(cohortId) {
|
|
48719
49167
|
const cohort = loadCohort(cohortId);
|
|
@@ -48757,15 +49205,15 @@ function isoTs2() {
|
|
|
48757
49205
|
return (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
48758
49206
|
}
|
|
48759
49207
|
function atomicWriteFile3(path2, data) {
|
|
48760
|
-
|
|
49208
|
+
mkdirSync35(dirname43(path2), { recursive: true });
|
|
48761
49209
|
const tmp = `${path2}.tmp.${process.pid}.${randomBytes4(4).toString("hex")}`;
|
|
48762
|
-
|
|
49210
|
+
writeFileSync40(tmp, data, "utf8");
|
|
48763
49211
|
renameSync8(tmp, path2);
|
|
48764
49212
|
}
|
|
48765
49213
|
function readWal(path2) {
|
|
48766
|
-
if (!
|
|
49214
|
+
if (!existsSync81(path2)) return null;
|
|
48767
49215
|
try {
|
|
48768
|
-
return JSON.parse(
|
|
49216
|
+
return JSON.parse(readFileSync59(path2, "utf8"));
|
|
48769
49217
|
} catch {
|
|
48770
49218
|
return null;
|
|
48771
49219
|
}
|
|
@@ -48775,13 +49223,13 @@ function writeWal(path2, wal) {
|
|
|
48775
49223
|
}
|
|
48776
49224
|
function findWalByRunId(runId) {
|
|
48777
49225
|
const dir = MARKETING_PATHS.runsDir();
|
|
48778
|
-
if (!
|
|
49226
|
+
if (!existsSync81(dir)) return null;
|
|
48779
49227
|
for (const f of readdirSync20(dir)) {
|
|
48780
49228
|
if (!f.endsWith(".json")) continue;
|
|
48781
49229
|
if (f.startsWith("by-idem")) continue;
|
|
48782
49230
|
const stem = f.replace(/\.json$/, "");
|
|
48783
49231
|
if (stem === runId || f === runId || basename22(f, ".json") === runId) {
|
|
48784
|
-
return
|
|
49232
|
+
return join73(dir, f);
|
|
48785
49233
|
}
|
|
48786
49234
|
}
|
|
48787
49235
|
return null;
|
|
@@ -48821,7 +49269,7 @@ function createLaunchWal(args) {
|
|
|
48821
49269
|
flipped_count: 0,
|
|
48822
49270
|
error: null
|
|
48823
49271
|
};
|
|
48824
|
-
const walPath =
|
|
49272
|
+
const walPath = join73(MARKETING_PATHS.runsDir(), `${id}.json`);
|
|
48825
49273
|
writeWal(walPath, wal);
|
|
48826
49274
|
return { walPath, wal };
|
|
48827
49275
|
}
|
|
@@ -49052,7 +49500,7 @@ var init_launch2 = __esm({
|
|
|
49052
49500
|
});
|
|
49053
49501
|
|
|
49054
49502
|
// src/cli/commands/marketing/learnings.ts
|
|
49055
|
-
import { existsSync as
|
|
49503
|
+
import { existsSync as existsSync82, readFileSync as readFileSync60 } from "fs";
|
|
49056
49504
|
function registerMarketingLearnings(parent) {
|
|
49057
49505
|
const cmd = parent.command("learnings").description("Performance Monitor learnings ledger (per-day .md + index).");
|
|
49058
49506
|
cmd.command("show").description("Show today's (or specified day's) learnings file.").option("--date <YYYY-MM-DD>", "Day to show (default: today UTC)").option("--id <id>", "Show a single entry by id").action((opts) => {
|
|
@@ -49195,8 +49643,8 @@ async function resolveBody(body, bodyFile) {
|
|
|
49195
49643
|
if (body) return body;
|
|
49196
49644
|
if (bodyFile === "-") return readStdin3();
|
|
49197
49645
|
if (bodyFile) {
|
|
49198
|
-
if (!
|
|
49199
|
-
return
|
|
49646
|
+
if (!existsSync82(bodyFile)) throw new Error(`Body file not found: ${bodyFile}`);
|
|
49647
|
+
return readFileSync60(bodyFile, "utf8");
|
|
49200
49648
|
}
|
|
49201
49649
|
return null;
|
|
49202
49650
|
}
|
|
@@ -49226,29 +49674,29 @@ var init_learnings2 = __esm({
|
|
|
49226
49674
|
|
|
49227
49675
|
// src/lib/marketing/rem-sleep.ts
|
|
49228
49676
|
import {
|
|
49229
|
-
existsSync as
|
|
49230
|
-
mkdirSync as
|
|
49231
|
-
readFileSync as
|
|
49232
|
-
writeFileSync as
|
|
49677
|
+
existsSync as existsSync83,
|
|
49678
|
+
mkdirSync as mkdirSync36,
|
|
49679
|
+
readFileSync as readFileSync61,
|
|
49680
|
+
writeFileSync as writeFileSync41,
|
|
49233
49681
|
readdirSync as readdirSync21,
|
|
49234
49682
|
statSync as statSync16,
|
|
49235
49683
|
unlinkSync as unlinkSync3,
|
|
49236
49684
|
renameSync as renameSync9
|
|
49237
49685
|
} from "fs";
|
|
49238
|
-
import { dirname as
|
|
49686
|
+
import { dirname as dirname44, join as join74 } from "path";
|
|
49239
49687
|
import { randomBytes as randomBytes5 } from "crypto";
|
|
49240
49688
|
function atomicWriteFile4(path2, data) {
|
|
49241
|
-
|
|
49689
|
+
mkdirSync36(dirname44(path2), { recursive: true });
|
|
49242
49690
|
const tmp = `${path2}.tmp.${process.pid}.${randomBytes5(4).toString("hex")}`;
|
|
49243
|
-
|
|
49691
|
+
writeFileSync41(tmp, data, "utf8");
|
|
49244
49692
|
renameSync9(tmp, path2);
|
|
49245
49693
|
}
|
|
49246
49694
|
function pruneRuns(opts = {}) {
|
|
49247
49695
|
const keepLast = opts.keepLast ?? 100;
|
|
49248
49696
|
const dir = MARKETING_PATHS.runsDir();
|
|
49249
|
-
if (!
|
|
49697
|
+
if (!existsSync83(dir)) return { scanned: 0, kept: 0, deleted: 0, deletedFiles: [] };
|
|
49250
49698
|
const files = readdirSync21(dir).filter((f) => f.endsWith(".json")).map((f) => {
|
|
49251
|
-
const p =
|
|
49699
|
+
const p = join74(dir, f);
|
|
49252
49700
|
try {
|
|
49253
49701
|
return { f, p, mtimeMs: statSync16(p).mtimeMs };
|
|
49254
49702
|
} catch {
|
|
@@ -49282,13 +49730,13 @@ function compactInsights(opts = {}) {
|
|
|
49282
49730
|
const weeklyAfterDays = opts.weeklyAfterDays ?? 14;
|
|
49283
49731
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
49284
49732
|
const dir = MARKETING_PATHS.insightsDir();
|
|
49285
|
-
if (!
|
|
49733
|
+
if (!existsSync83(dir)) return { scanned: 0, kept: 0, deleted: 0, deletedFiles: [] };
|
|
49286
49734
|
const files = [];
|
|
49287
49735
|
for (const f of readdirSync21(dir)) {
|
|
49288
49736
|
if (!f.endsWith(".json") || f.startsWith("_")) continue;
|
|
49289
49737
|
const m = f.match(SNAP_RE);
|
|
49290
49738
|
if (!m) continue;
|
|
49291
|
-
const p =
|
|
49739
|
+
const p = join74(dir, f);
|
|
49292
49740
|
try {
|
|
49293
49741
|
const stat = statSync16(p);
|
|
49294
49742
|
files.push({ f, p, mtimeMs: stat.mtimeMs, entityId: m[1], bucket: m[2] });
|
|
@@ -49354,7 +49802,7 @@ function mergeDailyLearnings(opts = {}) {
|
|
|
49354
49802
|
const retainDays = opts.retainDays ?? 7;
|
|
49355
49803
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
49356
49804
|
const dir = MARKETING_PATHS.learningsDir();
|
|
49357
|
-
if (!
|
|
49805
|
+
if (!existsSync83(dir)) {
|
|
49358
49806
|
return { scanned: 0, merged: 0, archivePath: null, droppedRejected: 0, mergedFiles: [] };
|
|
49359
49807
|
}
|
|
49360
49808
|
const dayMs = 24 * 60 * 60 * 1e3;
|
|
@@ -49365,7 +49813,7 @@ function mergeDailyLearnings(opts = {}) {
|
|
|
49365
49813
|
if (!m) continue;
|
|
49366
49814
|
const date = m[1];
|
|
49367
49815
|
const dateMs = (/* @__PURE__ */ new Date(`${date}T00:00:00Z`)).getTime();
|
|
49368
|
-
if (dateMs < cutoff) candidates.push({ f, p:
|
|
49816
|
+
if (dateMs < cutoff) candidates.push({ f, p: join74(dir, f), date });
|
|
49369
49817
|
}
|
|
49370
49818
|
if (candidates.length === 0) {
|
|
49371
49819
|
return { scanned: 0, merged: 0, archivePath: null, droppedRejected: 0, mergedFiles: [] };
|
|
@@ -49379,10 +49827,10 @@ function mergeDailyLearnings(opts = {}) {
|
|
|
49379
49827
|
const mergedFiles = [];
|
|
49380
49828
|
let lastArchivePath = null;
|
|
49381
49829
|
for (const [q, list] of byQuarter) {
|
|
49382
|
-
const archivePath =
|
|
49830
|
+
const archivePath = join74(dir, `_archive-${q}.md`);
|
|
49383
49831
|
list.sort((a, b) => a.date.localeCompare(b.date));
|
|
49384
49832
|
for (const c of list) {
|
|
49385
|
-
const existingArchive =
|
|
49833
|
+
const existingArchive = existsSync83(archivePath) ? readFileSync61(archivePath, "utf8") : `# Marketing learnings archive \u2014 ${q}
|
|
49386
49834
|
`;
|
|
49387
49835
|
const dateMarker = `# Marketing learnings \u2014 ${c.date}`;
|
|
49388
49836
|
const alreadyMerged = existingArchive.includes(dateMarker);
|
|
@@ -49391,7 +49839,7 @@ function mergeDailyLearnings(opts = {}) {
|
|
|
49391
49839
|
continue;
|
|
49392
49840
|
}
|
|
49393
49841
|
if (!alreadyMerged) {
|
|
49394
|
-
const body =
|
|
49842
|
+
const body = readFileSync61(c.p, "utf8").trimEnd();
|
|
49395
49843
|
const next2 = existingArchive.trimEnd() + "\n\n" + body + "\n";
|
|
49396
49844
|
atomicWriteFile4(archivePath, next2);
|
|
49397
49845
|
}
|
|
@@ -49434,14 +49882,14 @@ function quarterKey(yyyymmdd) {
|
|
|
49434
49882
|
}
|
|
49435
49883
|
function redactRunsSweep(opts = {}) {
|
|
49436
49884
|
const dir = MARKETING_PATHS.runsDir();
|
|
49437
|
-
if (!
|
|
49885
|
+
if (!existsSync83(dir)) return { scanned: 0, rewritten: 0, rewrittenFiles: [] };
|
|
49438
49886
|
const files = readdirSync21(dir).filter((f) => f.endsWith(".json"));
|
|
49439
49887
|
const rewrittenFiles = [];
|
|
49440
49888
|
for (const f of files) {
|
|
49441
|
-
const p =
|
|
49889
|
+
const p = join74(dir, f);
|
|
49442
49890
|
let raw;
|
|
49443
49891
|
try {
|
|
49444
|
-
raw =
|
|
49892
|
+
raw = readFileSync61(p, "utf8");
|
|
49445
49893
|
} catch {
|
|
49446
49894
|
continue;
|
|
49447
49895
|
}
|
|
@@ -49463,7 +49911,7 @@ function redactRunsSweep(opts = {}) {
|
|
|
49463
49911
|
function runRemSleep(opts = {}) {
|
|
49464
49912
|
const ranAt = (opts.now ?? /* @__PURE__ */ new Date()).toISOString();
|
|
49465
49913
|
const root = marketingRootIfExists();
|
|
49466
|
-
if (!root || !
|
|
49914
|
+
if (!root || !existsSync83(root)) {
|
|
49467
49915
|
return {
|
|
49468
49916
|
ranAt,
|
|
49469
49917
|
marketingPresent: false,
|
|
@@ -49485,7 +49933,7 @@ function runRemSleep(opts = {}) {
|
|
|
49485
49933
|
now: opts.now
|
|
49486
49934
|
});
|
|
49487
49935
|
const redaction = redactRunsSweep({ dryRun: opts.dryRun });
|
|
49488
|
-
void
|
|
49936
|
+
void mkdirSync36;
|
|
49489
49937
|
return { ranAt, marketingPresent: true, runs, insights, learnings, redaction };
|
|
49490
49938
|
}
|
|
49491
49939
|
var SNAP_RE;
|
|
@@ -49582,9 +50030,9 @@ var init_git_guard = __esm({
|
|
|
49582
50030
|
});
|
|
49583
50031
|
|
|
49584
50032
|
// src/cli/commands/marketing/hooks.ts
|
|
49585
|
-
import { existsSync as
|
|
50033
|
+
import { existsSync as existsSync84, readFileSync as readFileSync62, writeFileSync as writeFileSync42, chmodSync as chmodSync3, mkdirSync as mkdirSync37, statSync as statSync17 } from "fs";
|
|
49586
50034
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
49587
|
-
import { join as
|
|
50035
|
+
import { join as join75 } from "path";
|
|
49588
50036
|
function findGitDir(cwd = process.cwd()) {
|
|
49589
50037
|
try {
|
|
49590
50038
|
const out = execFileSync6("git", ["rev-parse", "--git-dir"], {
|
|
@@ -49593,7 +50041,7 @@ function findGitDir(cwd = process.cwd()) {
|
|
|
49593
50041
|
stdio: ["ignore", "pipe", "ignore"]
|
|
49594
50042
|
}).trim();
|
|
49595
50043
|
if (!out) return null;
|
|
49596
|
-
return out.startsWith("/") ? out :
|
|
50044
|
+
return out.startsWith("/") ? out : join75(cwd, out);
|
|
49597
50045
|
} catch {
|
|
49598
50046
|
return null;
|
|
49599
50047
|
}
|
|
@@ -49624,11 +50072,11 @@ function registerMarketingHooks(parent) {
|
|
|
49624
50072
|
error("Not inside a git repository (or `git` is not on PATH).");
|
|
49625
50073
|
process.exit(1);
|
|
49626
50074
|
}
|
|
49627
|
-
const hooksDir =
|
|
49628
|
-
|
|
49629
|
-
const target =
|
|
49630
|
-
if (
|
|
49631
|
-
const existing =
|
|
50075
|
+
const hooksDir = join75(gitDir, "hooks");
|
|
50076
|
+
mkdirSync37(hooksDir, { recursive: true });
|
|
50077
|
+
const target = join75(hooksDir, "pre-commit");
|
|
50078
|
+
if (existsSync84(target)) {
|
|
50079
|
+
const existing = readFileSync62(target, "utf-8");
|
|
49632
50080
|
if (existing.includes(MANAGED_MARKER)) {
|
|
49633
50081
|
info("pre-commit hook already managed by dreamcontext \u2014 refreshing.");
|
|
49634
50082
|
} else if (!opts.force) {
|
|
@@ -49640,7 +50088,7 @@ function registerMarketingHooks(parent) {
|
|
|
49640
50088
|
warn("Overwriting existing pre-commit hook (--force).");
|
|
49641
50089
|
}
|
|
49642
50090
|
}
|
|
49643
|
-
|
|
50091
|
+
writeFileSync42(target, HOOK_LAUNCHER, "utf-8");
|
|
49644
50092
|
try {
|
|
49645
50093
|
chmodSync3(target, 493);
|
|
49646
50094
|
} catch {
|
|
@@ -49679,26 +50127,26 @@ exec dreamcontext mk hooks check-staged
|
|
|
49679
50127
|
});
|
|
49680
50128
|
|
|
49681
50129
|
// src/lib/marketing/council-personas.ts
|
|
49682
|
-
import { existsSync as
|
|
50130
|
+
import { existsSync as existsSync85, readFileSync as readFileSync63, readdirSync as readdirSync22 } from "fs";
|
|
49683
50131
|
import { fileURLToPath as fileURLToPath9 } from "url";
|
|
49684
|
-
import { join as
|
|
50132
|
+
import { join as join76, dirname as dirname45 } from "path";
|
|
49685
50133
|
function findPersonasDir() {
|
|
49686
50134
|
const candidates = [
|
|
49687
50135
|
// dev: src/lib/marketing/council-personas.ts → ../../../skill-packs/...
|
|
49688
|
-
|
|
50136
|
+
join76(__dirname_local, "..", "..", "..", PERSONA_SUBPATH),
|
|
49689
50137
|
// built: dist/index.js → ./skill-packs/...
|
|
49690
|
-
|
|
50138
|
+
join76(__dirname_local, PERSONA_SUBPATH),
|
|
49691
50139
|
// tsup-bundled (deeper nesting if ever): ../skill-packs/...
|
|
49692
|
-
|
|
49693
|
-
|
|
50140
|
+
join76(__dirname_local, "..", PERSONA_SUBPATH),
|
|
50141
|
+
join76(__dirname_local, "..", "..", PERSONA_SUBPATH)
|
|
49694
50142
|
];
|
|
49695
50143
|
for (const candidate of candidates) {
|
|
49696
|
-
if (
|
|
50144
|
+
if (existsSync85(candidate)) return candidate;
|
|
49697
50145
|
}
|
|
49698
50146
|
return null;
|
|
49699
50147
|
}
|
|
49700
50148
|
function parsePersonaFile(filePath) {
|
|
49701
|
-
const raw =
|
|
50149
|
+
const raw = readFileSync63(filePath, "utf-8");
|
|
49702
50150
|
const parsed = (0, import_gray_matter5.default)(raw);
|
|
49703
50151
|
const data = parsed.data;
|
|
49704
50152
|
const slug = typeof data.slug === "string" ? data.slug.trim() : "";
|
|
@@ -49718,9 +50166,9 @@ function parsePersonaFile(filePath) {
|
|
|
49718
50166
|
}
|
|
49719
50167
|
function loadAllPersonas(personasDir) {
|
|
49720
50168
|
const dir = personasDir ?? findPersonasDir();
|
|
49721
|
-
if (!dir || !
|
|
50169
|
+
if (!dir || !existsSync85(dir)) return [];
|
|
49722
50170
|
const files = readdirSync22(dir).filter((n) => n.endsWith(".md")).sort();
|
|
49723
|
-
return files.map((name) => parsePersonaFile(
|
|
50171
|
+
return files.map((name) => parsePersonaFile(join76(dir, name)));
|
|
49724
50172
|
}
|
|
49725
50173
|
function selectPersonas(all, requested) {
|
|
49726
50174
|
if (requested.length === 0) return [...all];
|
|
@@ -49739,23 +50187,23 @@ var init_council_personas = __esm({
|
|
|
49739
50187
|
import_gray_matter5 = __toESM(require_gray_matter(), 1);
|
|
49740
50188
|
__dirname_local = (() => {
|
|
49741
50189
|
try {
|
|
49742
|
-
return
|
|
50190
|
+
return dirname45(fileURLToPath9(import.meta.url));
|
|
49743
50191
|
} catch {
|
|
49744
50192
|
return process.cwd();
|
|
49745
50193
|
}
|
|
49746
50194
|
})();
|
|
49747
50195
|
VALID_MODELS2 = /* @__PURE__ */ new Set(["opus", "sonnet", "haiku"]);
|
|
49748
|
-
PERSONA_SUBPATH =
|
|
50196
|
+
PERSONA_SUBPATH = join76("skill-packs", "meta-marketing", "council-personas");
|
|
49749
50197
|
}
|
|
49750
50198
|
});
|
|
49751
50199
|
|
|
49752
50200
|
// src/cli/commands/marketing/council.ts
|
|
49753
50201
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
49754
|
-
import { existsSync as
|
|
50202
|
+
import { existsSync as existsSync86 } from "fs";
|
|
49755
50203
|
function resolveDreamcontextEntry() {
|
|
49756
50204
|
const node = process.argv[0];
|
|
49757
50205
|
const script = process.argv[1];
|
|
49758
|
-
if (script &&
|
|
50206
|
+
if (script && existsSync86(script)) {
|
|
49759
50207
|
return { node, script };
|
|
49760
50208
|
}
|
|
49761
50209
|
return { node, script: null };
|
|
@@ -49927,8 +50375,8 @@ var init_marketing = __esm({
|
|
|
49927
50375
|
});
|
|
49928
50376
|
|
|
49929
50377
|
// src/cli/commands/memory.ts
|
|
49930
|
-
import { existsSync as
|
|
49931
|
-
import { join as
|
|
50378
|
+
import { existsSync as existsSync87, unlinkSync as unlinkSync4 } from "fs";
|
|
50379
|
+
import { join as join77, dirname as dirname46 } from "path";
|
|
49932
50380
|
function collectVault(value, previous) {
|
|
49933
50381
|
return [...previous, value];
|
|
49934
50382
|
}
|
|
@@ -49940,7 +50388,7 @@ function parseTypes(value) {
|
|
|
49940
50388
|
return filtered.length > 0 ? filtered : void 0;
|
|
49941
50389
|
}
|
|
49942
50390
|
function recallFederated(contextRoot, query, topK, types, opts) {
|
|
49943
|
-
const projectRoot =
|
|
50391
|
+
const projectRoot = dirname46(contextRoot);
|
|
49944
50392
|
const { target: currentTarget } = currentVaultTarget(projectRoot);
|
|
49945
50393
|
const byName = /* @__PURE__ */ new Map();
|
|
49946
50394
|
const add = (t) => {
|
|
@@ -50093,7 +50541,7 @@ function registerMemoryCommand(program2) {
|
|
|
50093
50541
|
const summary = opts.summary ?? (text.length > 200 ? text.slice(0, 197) + "..." : text);
|
|
50094
50542
|
const references = opts.references ? opts.references.split(",").map((s) => s.trim()).filter(Boolean) : void 0;
|
|
50095
50543
|
const authors = opts.person ? opts.person.split(",").map((s) => s.trim()).filter(Boolean) : void 0;
|
|
50096
|
-
const changelogPath =
|
|
50544
|
+
const changelogPath = join77(root, "core", "CHANGELOG.json");
|
|
50097
50545
|
const entry = {
|
|
50098
50546
|
date: today(),
|
|
50099
50547
|
type: opts.type ?? "note",
|
|
@@ -50111,8 +50559,8 @@ function registerMemoryCommand(program2) {
|
|
|
50111
50559
|
memory.command("update").argument("<slug>", "Knowledge file slug (without .md)").option("-d, --description <desc>", "New description (replaces existing)").option("-t, --tags <tags>", "New tags (comma-separated, replaces existing)").option("-c, --content <content>", "New body content (replaces existing)").option("--append <text>", "Append text to body (preserves existing content)").option("--pin", "Set pinned: true").option("--unpin", "Set pinned: false").description("Update a knowledge file (frontmatter and/or body)").action(
|
|
50112
50560
|
async (slug, opts) => {
|
|
50113
50561
|
const root = ensureContextRoot();
|
|
50114
|
-
const filePath =
|
|
50115
|
-
if (!
|
|
50562
|
+
const filePath = join77(root, "knowledge", `${slug}.md`);
|
|
50563
|
+
if (!existsSync87(filePath)) {
|
|
50116
50564
|
error(`Knowledge file not found: ${slug}.md`);
|
|
50117
50565
|
return;
|
|
50118
50566
|
}
|
|
@@ -50159,8 +50607,8 @@ ${opts.append}
|
|
|
50159
50607
|
);
|
|
50160
50608
|
memory.command("delete").argument("<slug>", "Knowledge file slug to delete (without .md)").option("-f, --force", "Skip confirmation prompt").description("Delete a knowledge file (irreversible; use git to recover)").action(async (slug, opts) => {
|
|
50161
50609
|
const root = ensureContextRoot();
|
|
50162
|
-
const filePath =
|
|
50163
|
-
if (!
|
|
50610
|
+
const filePath = join77(root, "knowledge", `${slug}.md`);
|
|
50611
|
+
if (!existsSync87(filePath)) {
|
|
50164
50612
|
error(`Knowledge file not found: ${slug}.md`);
|
|
50165
50613
|
return;
|
|
50166
50614
|
}
|
|
@@ -50268,13 +50716,13 @@ var init_memory = __esm({
|
|
|
50268
50716
|
|
|
50269
50717
|
// src/cli/commands/upgrade.ts
|
|
50270
50718
|
import { execFileSync as execFileSync8 } from "child_process";
|
|
50271
|
-
import { dirname as
|
|
50719
|
+
import { dirname as dirname47 } from "path";
|
|
50272
50720
|
function defaultInstaller(args) {
|
|
50273
50721
|
execFileSync8("npm", args, { stdio: "inherit" });
|
|
50274
50722
|
}
|
|
50275
50723
|
function projectRootForCache() {
|
|
50276
50724
|
const contextDir = resolveContextRoot();
|
|
50277
|
-
return contextDir ?
|
|
50725
|
+
return contextDir ? dirname47(contextDir) : process.cwd();
|
|
50278
50726
|
}
|
|
50279
50727
|
function defaultLiveLatest() {
|
|
50280
50728
|
let latest = null;
|
|
@@ -50597,9 +51045,9 @@ var init_vaults3 = __esm({
|
|
|
50597
51045
|
});
|
|
50598
51046
|
|
|
50599
51047
|
// src/cli/commands/connections.ts
|
|
50600
|
-
import { dirname as
|
|
51048
|
+
import { dirname as dirname48 } from "path";
|
|
50601
51049
|
function currentVaultName2(contextRoot) {
|
|
50602
|
-
return currentVaultTarget(
|
|
51050
|
+
return currentVaultTarget(dirname48(contextRoot)).name;
|
|
50603
51051
|
}
|
|
50604
51052
|
function registerConnectionsCommand(program2) {
|
|
50605
51053
|
program2.command("connect <vault>").description("Connect this vault to a peer for federation (out|in|both)").option("-d, --direction <direction>", "Connection direction: out | in | both", "both").option("--topics <list>", "Comma-separated topic filter (default: all topics)").action((vault, opts) => {
|
|
@@ -50681,17 +51129,17 @@ var init_connections3 = __esm({
|
|
|
50681
51129
|
});
|
|
50682
51130
|
|
|
50683
51131
|
// src/lib/federation-ingest.ts
|
|
50684
|
-
import { existsSync as
|
|
50685
|
-
import { join as
|
|
51132
|
+
import { existsSync as existsSync88, mkdirSync as mkdirSync38 } from "fs";
|
|
51133
|
+
import { join as join78 } from "path";
|
|
50686
51134
|
function ingestEntry(contextRoot, entry) {
|
|
50687
|
-
const knowledgeDir =
|
|
50688
|
-
|
|
51135
|
+
const knowledgeDir = join78(contextRoot, "knowledge");
|
|
51136
|
+
mkdirSync38(knowledgeDir, { recursive: true });
|
|
50689
51137
|
const baseSlug = slugFromTitle(entry.title);
|
|
50690
|
-
const canonicalPath =
|
|
50691
|
-
const collided =
|
|
51138
|
+
const canonicalPath = join78(knowledgeDir, `${baseSlug}.md`);
|
|
51139
|
+
const collided = existsSync88(canonicalPath);
|
|
50692
51140
|
const slug = collided ? `${baseSlug}--from-${sanitizeVault(entry.origin.vault)}` : baseSlug;
|
|
50693
|
-
const targetPath =
|
|
50694
|
-
if (!
|
|
51141
|
+
const targetPath = join78(knowledgeDir, `${slug}.md`);
|
|
51142
|
+
if (!existsSync88(targetPath)) {
|
|
50695
51143
|
writeFrontmatter(
|
|
50696
51144
|
targetPath,
|
|
50697
51145
|
{
|
|
@@ -50767,9 +51215,9 @@ var init_federation_ingest = __esm({
|
|
|
50767
51215
|
});
|
|
50768
51216
|
|
|
50769
51217
|
// src/cli/commands/federation.ts
|
|
50770
|
-
import { dirname as
|
|
51218
|
+
import { dirname as dirname49 } from "path";
|
|
50771
51219
|
function currentVaultName3(contextRoot) {
|
|
50772
|
-
return currentVaultTarget(
|
|
51220
|
+
return currentVaultTarget(dirname49(contextRoot)).name;
|
|
50773
51221
|
}
|
|
50774
51222
|
function outboundConnections(contextRoot) {
|
|
50775
51223
|
return listConnections(contextRoot).filter(
|
|
@@ -50982,12 +51430,12 @@ var init_people = __esm({
|
|
|
50982
51430
|
});
|
|
50983
51431
|
|
|
50984
51432
|
// src/cli/commands/config.ts
|
|
50985
|
-
import { dirname as
|
|
50986
|
-
import { existsSync as
|
|
50987
|
-
import { join as
|
|
51433
|
+
import { dirname as dirname50 } from "path";
|
|
51434
|
+
import { existsSync as existsSync89, readFileSync as readFileSync65, writeFileSync as writeFileSync44 } from "fs";
|
|
51435
|
+
import { join as join79 } from "path";
|
|
50988
51436
|
function resolveProjectRoot() {
|
|
50989
51437
|
const contextRoot = resolveContextRoot();
|
|
50990
|
-
return contextRoot ?
|
|
51438
|
+
return contextRoot ? dirname50(contextRoot) : null;
|
|
50991
51439
|
}
|
|
50992
51440
|
function requireProjectRoot() {
|
|
50993
51441
|
const projectRoot = resolveProjectRoot();
|
|
@@ -51146,7 +51594,7 @@ function registerConfigCommand(program2) {
|
|
|
51146
51594
|
const liveToken = resolveClickUpToken(projectRoot);
|
|
51147
51595
|
let connected = false;
|
|
51148
51596
|
if (liveToken) {
|
|
51149
|
-
const contextRoot =
|
|
51597
|
+
const contextRoot = join79(projectRoot, "_dream_context");
|
|
51150
51598
|
const probe = createClickUpBackend(contextRoot, readSetupConfig(projectRoot));
|
|
51151
51599
|
const test = await probe.testConnection();
|
|
51152
51600
|
if (test.ok) {
|
|
@@ -51189,7 +51637,7 @@ function registerConfigCommand(program2) {
|
|
|
51189
51637
|
cfgNow = readSetupConfig(projectRoot);
|
|
51190
51638
|
}
|
|
51191
51639
|
if (connected && cfgNow?.clickup?.listId) {
|
|
51192
|
-
const contextRoot =
|
|
51640
|
+
const contextRoot = join79(projectRoot, "_dream_context");
|
|
51193
51641
|
const backend2 = createClickUpBackend(contextRoot, cfgNow);
|
|
51194
51642
|
if (await esm_default4({ message: "Create the recommended custom fields on the list (urgency, summary, RICE, \u2026)?", default: true })) {
|
|
51195
51643
|
const result = await backend2.provisionRemote();
|
|
@@ -51244,13 +51692,13 @@ function registerConfigCommand(program2) {
|
|
|
51244
51692
|
const contextRoot = resolveContextRoot();
|
|
51245
51693
|
let userMdSynced = false;
|
|
51246
51694
|
if (contextRoot) {
|
|
51247
|
-
const userMdPath =
|
|
51248
|
-
if (
|
|
51695
|
+
const userMdPath = join79(contextRoot, "core", "1.user.md");
|
|
51696
|
+
if (existsSync89(userMdPath)) {
|
|
51249
51697
|
try {
|
|
51250
|
-
const before =
|
|
51698
|
+
const before = readFileSync65(userMdPath, "utf-8");
|
|
51251
51699
|
const after = ensurePeopleSection(before, roster);
|
|
51252
51700
|
if (after !== before) {
|
|
51253
|
-
|
|
51701
|
+
writeFileSync44(userMdPath, after, "utf-8");
|
|
51254
51702
|
userMdSynced = true;
|
|
51255
51703
|
}
|
|
51256
51704
|
} catch (err) {
|
|
@@ -51294,7 +51742,7 @@ function registerConfigCommand(program2) {
|
|
|
51294
51742
|
config.command("clickup-list <teamId> <spaceId> <listId>").description("Set the ClickUp team/space/list the tasks sync against").option("--migrate", "When changing lists: reset the sync ledger so the next sync recreates every local task in the NEW list").option("--keep", "When changing lists: keep existing task mappings (tasks were moved in ClickUp itself)").action(async (teamId, spaceId, listId, opts) => {
|
|
51295
51743
|
const projectRoot = requireProjectRoot();
|
|
51296
51744
|
if (!projectRoot) return;
|
|
51297
|
-
const contextRoot =
|
|
51745
|
+
const contextRoot = join79(projectRoot, "_dream_context");
|
|
51298
51746
|
const existing = readSetupConfig(projectRoot)?.clickup ?? {};
|
|
51299
51747
|
const ledger = new SyncLedger(contextRoot);
|
|
51300
51748
|
const changingList = !!existing.listId && existing.listId !== listId && ledger.readMap().length > 0;
|
|
@@ -51335,8 +51783,8 @@ function registerConfigCommand(program2) {
|
|
|
51335
51783
|
if (!value) {
|
|
51336
51784
|
if (!process.stdin.isTTY) {
|
|
51337
51785
|
try {
|
|
51338
|
-
const { readFileSync:
|
|
51339
|
-
value =
|
|
51786
|
+
const { readFileSync: readFileSync66 } = await import("fs");
|
|
51787
|
+
value = readFileSync66(0, "utf-8").trim();
|
|
51340
51788
|
} catch {
|
|
51341
51789
|
value = "";
|
|
51342
51790
|
}
|
|
@@ -51695,12 +52143,12 @@ var init_feedback2 = __esm({
|
|
|
51695
52143
|
});
|
|
51696
52144
|
|
|
51697
52145
|
// src/cli/commands/migrations.ts
|
|
51698
|
-
import { dirname as
|
|
52146
|
+
import { dirname as dirname51 } from "path";
|
|
51699
52147
|
function registerMigrationsCommand(program2) {
|
|
51700
52148
|
const migrations = program2.command("migrations").description("Inspect and record brain structure migrations");
|
|
51701
52149
|
migrations.command("pending").description("Print pending agent task instructions for any unfinished migrations").action(() => {
|
|
51702
52150
|
const root = ensureContextRoot();
|
|
51703
|
-
const projectRoot =
|
|
52151
|
+
const projectRoot = dirname51(root);
|
|
51704
52152
|
const config = readSetupConfig(projectRoot);
|
|
51705
52153
|
const fromVersion = config?.setupVersion ?? "0.0.0";
|
|
51706
52154
|
const toVersion = dreamcontextVersion();
|