volute 0.52.0 → 0.54.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{accept-5NK5XJB5.js → accept-RSDIVJL6.js} +3 -0
- package/dist/auto-upgrade-HEVZKPTF.js +46 -0
- package/dist/{backup-YVGV2ZNM.js → backup-QRNX6RK7.js} +10 -10
- package/dist/channels-CKCY64TD.js +203 -0
- package/dist/{chat-VAZ25KVT.js → chat-ZUGNL5GS.js} +5 -5
- package/dist/chunk-3LHUXY3E.js +102 -0
- package/dist/{chunk-SW2U6HRB.js → chunk-444RR3YF.js} +21 -4
- package/dist/{chunk-YVR6EHWL.js → chunk-56IT2ZXF.js} +160 -18
- package/dist/chunk-5RBEEAKW.js +58 -0
- package/dist/{chunk-OXWUEU5V.js → chunk-5U5GLZSD.js} +2 -2
- package/dist/{chunk-G7A5LEVI.js → chunk-7XKPG66D.js} +5 -5
- package/dist/{chunk-R772ET2M.js → chunk-AAPNU7GA.js} +4 -0
- package/dist/{chunk-XRWUQPCA.js → chunk-ATZF2RNJ.js} +25 -3
- package/dist/{chunk-6NLW72HP.js → chunk-CKPAVQNK.js} +1 -1
- package/dist/{chunk-JHKBALS2.js → chunk-CLCHOXLR.js} +1 -1
- package/dist/{chunk-DMK5ASKV.js → chunk-F6D766VQ.js} +6 -2
- package/dist/{chunk-AXFLY5GU.js → chunk-HKGYZVWN.js} +16 -1
- package/dist/{chunk-ZEZQNP2G.js → chunk-LGXVGIWN.js} +103 -25
- package/dist/{chunk-CW7BQKF6.js → chunk-LKUGUQUW.js} +3 -3
- package/dist/{chunk-FXWBFDQR.js → chunk-OAYY3WF3.js} +59 -12
- package/dist/{chunk-ITK6HV47.js → chunk-OGPVJ53N.js} +14 -6
- package/dist/{chunk-M77B73VV.js → chunk-OIOW3FPT.js} +7 -2
- package/dist/chunk-OT5SXF7L.js +904 -0
- package/dist/{chunk-EDR47UE2.js → chunk-OYF25B62.js} +1 -1
- package/dist/{chunk-RPPTGPYF.js → chunk-PPSN2MLC.js} +2 -2
- package/dist/{chunk-K2F237KS.js → chunk-RGHF3OK5.js} +154 -18
- package/dist/{chunk-RU74YG46.js → chunk-VDUCLVZI.js} +338 -30
- package/dist/{chunk-724DVYHU.js → chunk-WHL6PKYP.js} +10 -10
- package/dist/{chunk-EEOMA4DX.js → chunk-WZZCA23D.js} +2 -1
- package/dist/{chunk-UDZLPR34.js → chunk-YSRYCS3N.js} +13 -8
- package/dist/{chunk-5N32EN4O.js → chunk-Z4Q6TQWL.js} +1 -1
- package/dist/{chunk-VPOMJMV6.js → chunk-ZNHL5KQJ.js} +1 -1
- package/dist/cli.js +17 -17
- package/dist/{clock-ZT5YT6HA.js → clock-X7V3C7NL.js} +2 -2
- package/dist/{cloud-sync-H7EWZASD.js → cloud-sync-52YNJRMR.js} +12 -11
- package/dist/{daemon-restart-4FWUA5JF.js → daemon-restart-QWHN5VMU.js} +4 -4
- package/dist/daemon.js +538 -782
- package/dist/{db-IPXRJUI7.js → db-I4EH5SLF.js} +3 -1
- package/dist/{delivery-manager-VYXVKUMP.js → delivery-manager-7R2YIQ2W.js} +13 -7
- package/dist/delivery-notices-RZQ6GONP.js +18 -0
- package/dist/{delivery-router-RHANNTAC.js → delivery-router-QS4NLJR6.js} +3 -1
- package/dist/{down-QSNEMTTX.js → down-UN2EDX2Y.js} +3 -3
- package/dist/{echo-text-PEEV7FQU.js → echo-text-73CYQRL7.js} +14 -13
- package/dist/{exec-ABD3DYA2.js → exec-Z34TTUO3.js} +1 -1
- package/dist/{extensions-N6L5NYTK.js → extensions-QT65JGV6.js} +22 -11
- package/dist/{files-BRY5RRIM.js → files-PCKBQHAY.js} +2 -1
- package/dist/{isolation-GVV2IBAU.js → isolation-UQPDO34R.js} +1 -1
- package/dist/{message-delivery-7URC52ME.js → message-delivery-TRKT4T2P.js} +16 -13
- package/dist/migrate-name-placeholder-C7NCNLWF.js +37 -0
- package/dist/{mind-NEXGT3KE.js → mind-CT6ANXK4.js} +11 -11
- package/dist/{mind-contacts-QYU4TPEA.js → mind-contacts-PEXCDRXA.js} +6 -6
- package/dist/{mind-history-OGNR4L7W.js → mind-history-RZMMCHMX.js} +83 -11
- package/dist/{mind-list-SYRA7CH5.js → mind-list-7KBLPLES.js} +1 -1
- package/dist/{mind-service-E26ZQXDS.js → mind-service-7EFIJ3ZA.js} +12 -11
- package/dist/{mind-sleep-LZAFBDZD.js → mind-sleep-24HV4RCA.js} +2 -2
- package/dist/{mind-status-Z2LQFA6F.js → mind-status-4YW4PHMO.js} +15 -0
- package/dist/{package-2W2XKSIP.js → package-F6S5NHY2.js} +4 -4
- package/dist/{prompts-NBO3HRK3.js → prompts-JECJIFPQ.js} +1 -1
- package/dist/{reject-TWB4QJHG.js → reject-4NFLXKRN.js} +6 -2
- package/dist/{scheduler-JTTWZDYU.js → scheduler-73Q4MQ7Y.js} +8 -6
- package/dist/{seed-64XEHRUP.js → seed-DRKAP3XV.js} +1 -1
- package/dist/{seed-cmd-UEL2QB3Q.js → seed-cmd-6IMTO3LG.js} +2 -2
- package/dist/{seed-create-4JRQDPGA.js → seed-create-VNLDYRFK.js} +1 -1
- package/dist/{seed-readiness-DYOVCYHN.js → seed-readiness-H5TTPAQH.js} +2 -2
- package/dist/{seed-sprout-NIDIOJXT.js → seed-sprout-PPGYGK4G.js} +5 -5
- package/dist/{send-2YKOZJJ5.js → send-UXUQKO4N.js} +37 -22
- package/dist/{service-XQPMZAGI.js → service-T4P5W6RS.js} +2 -2
- package/dist/{service-install-2EWD7KXD.js → service-install-R4SNYUVO.js} +3 -3
- package/dist/{setup-4IX6PCD3.js → setup-YUAQMDVZ.js} +4 -4
- package/dist/skills/dreaming/SKILL.md +2 -2
- package/dist/skills/dreaming/references/INSTALL.md +1 -1
- package/dist/skills/memory/SKILL.md +47 -43
- package/dist/skills/tending/SKILL.md +2 -0
- package/dist/skills/volute-mind/references/integrations.md +3 -2
- package/dist/skills/volute-mind/references/routing.md +18 -5
- package/dist/{skills-MPUALV3S.js → skills-GMQ5UIIW.js} +2 -2
- package/dist/{sleep-manager-OFP2GFXF.js → sleep-manager-KHI65FEX.js} +12 -11
- package/dist/{spirit-4ECYIVGE.js → spirit-Q5VGFWUI.js} +19 -3
- package/dist/{spirit-availability-Y54Y3675.js → spirit-availability-G5FMWKRH.js} +13 -12
- package/dist/{sprout-GJMZFRGZ.js → sprout-PMTRL7QN.js} +1 -1
- package/dist/{src-LCSOQY6Z.js → src-3FIW7DLH.js} +241 -87
- package/dist/src-H3UCOP6B.js +516 -0
- package/dist/{src-HGNE2XG4.js → src-LTTQVN2Z.js} +1 -1
- package/dist/{status-MWLE3RVC.js → status-LCKTTIWS.js} +2 -2
- package/dist/{system-events-V43HDA3T.js → system-events-Q7IVZ5T4.js} +5 -1
- package/dist/{systems-VDRUZXNF.js → systems-HL7SGSW7.js} +2 -2
- package/dist/{turn-tracker-C5PVIC3B.js → turn-tracker-HZDPMSCC.js} +4 -2
- package/dist/{up-H6LJZDRK.js → up-XZDSJVMU.js} +3 -3
- package/dist/{update-CIWI2JYA.js → update-ILCPVNDD.js} +2 -2
- package/dist/{upgrade-LIE46UBB.js → upgrade-XY2J7NWZ.js} +9 -1
- package/dist/{variant-cleanup-STC6B5HR.js → variant-cleanup-QHGGY7ND.js} +8 -6
- package/dist/{version-notify-LBVHH5YV.js → version-notify-VNVFX6UP.js} +22 -7
- package/dist/web-assets/assets/{index-B_eYTa3R.js → index-CwtxGwe_.js} +16 -16
- package/dist/web-assets/assets/index-DhM1yYRN.css +1 -0
- package/dist/web-assets/index.html +2 -2
- package/package.json +4 -4
- package/packages/extensions/intentions/dist/ui/assets/index-3FneLCKR.css +1 -0
- package/packages/extensions/intentions/dist/ui/assets/index-CQz4aceM.js +67 -0
- package/packages/extensions/{plan → intentions}/dist/ui/index.html +3 -3
- package/packages/extensions/intentions/skills/intention-review/SKILL.md +38 -0
- package/packages/extensions/intentions/skills/intentions/SKILL.md +49 -0
- package/packages/extensions/intentions/skills/intentions/scripts/intentions-hook.sh +45 -0
- package/packages/extensions/pages/skills/commons-gardening/SKILL.md +50 -0
- package/packages/extensions/pages/skills/pages/SKILL.md +18 -13
- package/templates/_base/.init/.config/prompts.json +3 -3
- package/templates/{pi → _base}/.init/.config/routes.json +1 -0
- package/templates/_base/.init/memory/dreams/.gitkeep +0 -0
- package/templates/_base/home/.config/routes.json +1 -1
- package/templates/_base/home/VOLUTE.md +1 -1
- package/templates/_base/src/lib/codex-session-seed.ts +463 -0
- package/templates/_base/src/lib/context-breakdown.ts +11 -3
- package/templates/_base/src/lib/daemon-client.ts +35 -0
- package/templates/_base/src/lib/pi-session-seed.ts +434 -0
- package/templates/_base/src/lib/routing.ts +2 -2
- package/templates/_base/src/lib/seed-note.ts +78 -0
- package/templates/_base/src/lib/session-seed.ts +375 -0
- package/templates/_base/src/lib/startup.ts +112 -6
- package/templates/claude/.init/CLAUDE.md +7 -3
- package/templates/claude/src/agent.ts +295 -101
- package/templates/claude/src/lib/hooks/pre-compact.ts +30 -5
- package/templates/claude/src/lib/message-channel.ts +43 -15
- package/templates/claude/src/lib/recover.ts +69 -0
- package/templates/claude/src/lib/stream-consumer.ts +33 -2
- package/templates/claude/src/server.ts +2 -1
- package/templates/claude/volute-template.json +1 -1
- package/templates/codex/.init/AGENTS.md +7 -3
- package/templates/codex/src/agent.ts +256 -39
- package/templates/codex/src/server.ts +2 -1
- package/templates/codex/volute-template.json +1 -1
- package/templates/pi/.init/MINDS.md +7 -3
- package/templates/pi/src/agent.ts +269 -43
- package/templates/pi/src/lib/event-handler.ts +11 -0
- package/templates/pi/src/lib/mechanics-doc.ts +30 -0
- package/templates/pi/src/server.ts +5 -1
- package/templates/pi/volute-template.json +1 -1
- package/dist/channels-FSAHOQWI.js +0 -90
- package/dist/skills/plan-coordinator/SKILL.md +0 -60
- package/dist/src-UDMJZ6MH.js +0 -426
- package/dist/web-assets/assets/index-DhZrzddW.css +0 -1
- package/packages/extensions/plan/dist/ui/assets/index-B8s8wxyt.js +0 -67
- package/packages/extensions/plan/dist/ui/assets/index-jIkrt-vI.css +0 -1
- package/packages/extensions/plan/skills/plan/SKILL.md +0 -43
- package/packages/extensions/plan/skills/plan/scripts/plan-hook.sh +0 -37
- package/templates/claude/.init/.config/routes.json +0 -11
- package/templates/codex/.init/.config/routes.json +0 -11
- package/dist/{env-IBW2QI6K.js → env-7AZFBPWX.js} +5 -5
- package/dist/{login-RJJTCVR3.js → login-4NUS72Z5.js} +3 -3
- package/dist/{login-SB5OENMV.js → login-57MMYILL.js} +4 -4
- package/dist/{register-OX4HRSGC.js → register-WNCSOTAU.js} +3 -3
- package/dist/{restart-AGEGNSYQ.js → restart-B4GNMVF2.js} +4 -4
- package/dist/{skill-B5OJEQUA.js → skill-QYTBUDNQ.js} +4 -4
- package/dist/{start-MUMNFR52.js → start-BDHJVOVX.js} +3 -3
- package/dist/{stop-EKERNYTX.js → stop-45QYSGYS.js} +4 -4
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
createExtension
|
|
4
|
+
} from "./chunk-RG5TOL4O.js";
|
|
5
|
+
import "./chunk-K3NQKI34.js";
|
|
6
|
+
|
|
7
|
+
// packages/extensions/intentions/src/index.ts
|
|
8
|
+
import { resolve as resolve2 } from "path";
|
|
9
|
+
|
|
10
|
+
// packages/extensions/intentions/src/format.ts
|
|
11
|
+
function formatHeldDays(days) {
|
|
12
|
+
if (days <= 0) return "set today";
|
|
13
|
+
if (days === 1) return "held 1 day";
|
|
14
|
+
return `held ${days} days`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// packages/extensions/intentions/src/intentions.ts
|
|
18
|
+
var MAX_ACTIVE_INTENTIONS = 3;
|
|
19
|
+
var DEFAULT_REVIEW_DAYS = 14;
|
|
20
|
+
var DEFAULT_BACKOFF_DAYS = 7;
|
|
21
|
+
var MAX_CONTENT_LENGTH = 240;
|
|
22
|
+
function withMeta(rows) {
|
|
23
|
+
return rows.map((row) => ({ ...row, overdue: !!row.overdue }));
|
|
24
|
+
}
|
|
25
|
+
var META_COLUMNS = `
|
|
26
|
+
CAST((julianday('now') - julianday(created_at)) AS INTEGER) AS held_days,
|
|
27
|
+
CASE WHEN status = 'active' AND review_at <= datetime('now') THEN 1 ELSE 0 END AS overdue
|
|
28
|
+
`;
|
|
29
|
+
function countActive(db, mindName) {
|
|
30
|
+
const row = db.prepare("SELECT COUNT(*) as count FROM intentions WHERE mind_name = ? AND status = 'active'").get(mindName);
|
|
31
|
+
return row.count;
|
|
32
|
+
}
|
|
33
|
+
function createIntention(db, mindName, content, note, reviewInDays) {
|
|
34
|
+
const days = reviewInDays && reviewInDays > 0 ? reviewInDays : DEFAULT_REVIEW_DAYS;
|
|
35
|
+
return db.prepare(
|
|
36
|
+
`INSERT INTO intentions (mind_name, content, note, review_at)
|
|
37
|
+
VALUES (?, ?, ?, datetime('now', ?))
|
|
38
|
+
RETURNING *`
|
|
39
|
+
).get(mindName, content, note ?? null, `+${days} days`);
|
|
40
|
+
}
|
|
41
|
+
function getIntention(db, id) {
|
|
42
|
+
return db.prepare("SELECT * FROM intentions WHERE id = ?").get(id) ?? null;
|
|
43
|
+
}
|
|
44
|
+
function listBoard(db, opts) {
|
|
45
|
+
const status = opts?.status ?? "active";
|
|
46
|
+
const conditions = ["status = ?"];
|
|
47
|
+
const params = [status];
|
|
48
|
+
if (opts?.mind) {
|
|
49
|
+
conditions.push("mind_name = ?");
|
|
50
|
+
params.push(opts.mind);
|
|
51
|
+
}
|
|
52
|
+
const limitClause = opts?.limit ? " LIMIT ?" : "";
|
|
53
|
+
if (opts?.limit) params.push(opts.limit);
|
|
54
|
+
const rows = db.prepare(
|
|
55
|
+
`SELECT *, ${META_COLUMNS} FROM intentions WHERE ${conditions.join(" AND ")} ORDER BY created_at DESC${limitClause}`
|
|
56
|
+
).all(...params);
|
|
57
|
+
return withMeta(rows);
|
|
58
|
+
}
|
|
59
|
+
function listMine(db, mindName) {
|
|
60
|
+
const rows = db.prepare(
|
|
61
|
+
`SELECT *, ${META_COLUMNS} FROM intentions WHERE mind_name = ? AND status = 'active' ORDER BY created_at ASC`
|
|
62
|
+
).all(mindName);
|
|
63
|
+
return withMeta(rows);
|
|
64
|
+
}
|
|
65
|
+
function keepIntention(db, id) {
|
|
66
|
+
return db.prepare(
|
|
67
|
+
`UPDATE intentions
|
|
68
|
+
SET review_at = datetime('now', ?), last_surfaced_at = NULL
|
|
69
|
+
WHERE id = ? AND status = 'active'
|
|
70
|
+
RETURNING *`
|
|
71
|
+
).get(`+${DEFAULT_REVIEW_DAYS} days`, id) ?? null;
|
|
72
|
+
}
|
|
73
|
+
function resolveStatus(db, id, status, note) {
|
|
74
|
+
return db.prepare(
|
|
75
|
+
`UPDATE intentions
|
|
76
|
+
SET status = ?, resolved_at = datetime('now'), resolution_note = ?
|
|
77
|
+
WHERE id = ? AND status = 'active'
|
|
78
|
+
RETURNING *`
|
|
79
|
+
).get(status, note ?? null, id) ?? null;
|
|
80
|
+
}
|
|
81
|
+
function fulfillIntention(db, id, note) {
|
|
82
|
+
return resolveStatus(db, id, "fulfilled", note);
|
|
83
|
+
}
|
|
84
|
+
function releaseIntention(db, id, note) {
|
|
85
|
+
return resolveStatus(db, id, "released", note);
|
|
86
|
+
}
|
|
87
|
+
function listReviewDue(db, backoffDays = DEFAULT_BACKOFF_DAYS) {
|
|
88
|
+
const rows = db.prepare(
|
|
89
|
+
`SELECT *, ${META_COLUMNS} FROM intentions
|
|
90
|
+
WHERE status = 'active'
|
|
91
|
+
AND review_at <= datetime('now')
|
|
92
|
+
AND (last_surfaced_at IS NULL OR last_surfaced_at <= datetime('now', ?))
|
|
93
|
+
ORDER BY review_at ASC`
|
|
94
|
+
).all(`-${backoffDays} days`);
|
|
95
|
+
if (rows.length > 0) {
|
|
96
|
+
const stmt = db.prepare(
|
|
97
|
+
"UPDATE intentions SET last_surfaced_at = datetime('now') WHERE id = ?"
|
|
98
|
+
);
|
|
99
|
+
for (const row of rows) stmt.run(row.id);
|
|
100
|
+
}
|
|
101
|
+
return withMeta(rows);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// packages/extensions/intentions/src/commands.ts
|
|
105
|
+
function canManage(actor, intention) {
|
|
106
|
+
if (!actor) return false;
|
|
107
|
+
return actor.role === "admin" || actor.username === intention.mind_name;
|
|
108
|
+
}
|
|
109
|
+
function createCommands() {
|
|
110
|
+
return {
|
|
111
|
+
add: {
|
|
112
|
+
description: "Set a new intention",
|
|
113
|
+
args: [
|
|
114
|
+
{
|
|
115
|
+
name: "content",
|
|
116
|
+
required: true,
|
|
117
|
+
description: "What you're oriented toward (or pipe via stdin)"
|
|
118
|
+
}
|
|
119
|
+
],
|
|
120
|
+
flags: {
|
|
121
|
+
note: {
|
|
122
|
+
type: "string",
|
|
123
|
+
description: "Optional longer-form note (not shown in session context)"
|
|
124
|
+
},
|
|
125
|
+
"review-in": { type: "number", description: "Days until soft review (default 14)" }
|
|
126
|
+
},
|
|
127
|
+
handler: async ({ args, flags }, ctx) => {
|
|
128
|
+
if (!ctx.db) return { error: "Intentions extension requires a database" };
|
|
129
|
+
const mindName = ctx.mindName;
|
|
130
|
+
if (!mindName) return { error: "No mind specified (use --mind or VOLUTE_MIND)" };
|
|
131
|
+
const content = (args.content ?? ctx.stdin ?? "").trim();
|
|
132
|
+
if (!content) return { error: 'Usage: volute intentions add "content"' };
|
|
133
|
+
if (content.length > MAX_CONTENT_LENGTH) {
|
|
134
|
+
return { error: `content must be ${MAX_CONTENT_LENGTH} characters or fewer` };
|
|
135
|
+
}
|
|
136
|
+
if (countActive(ctx.db, mindName) >= MAX_ACTIVE_INTENTIONS) {
|
|
137
|
+
return {
|
|
138
|
+
error: `${mindName} already holds ${MAX_ACTIVE_INTENTIONS} active intentions \u2014 fulfill or release one first`
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
const reviewInDays = flags["review-in"];
|
|
142
|
+
const note = flags.note;
|
|
143
|
+
const intention = createIntention(ctx.db, mindName, content, note, reviewInDays);
|
|
144
|
+
ctx.publishActivity({
|
|
145
|
+
type: "intention_set",
|
|
146
|
+
mind: mindName,
|
|
147
|
+
summary: `${mindName} set an intention: "${content}"`,
|
|
148
|
+
metadata: { intentionId: intention.id, url: "/intentions" }
|
|
149
|
+
});
|
|
150
|
+
return { output: `Intention set: ${intention.content}` };
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
list: {
|
|
154
|
+
description: "List active intentions (your own by default)",
|
|
155
|
+
flags: {
|
|
156
|
+
mind: { type: "string", description: "Show another mind's active intentions" }
|
|
157
|
+
},
|
|
158
|
+
handler: async ({ flags }, ctx) => {
|
|
159
|
+
if (!ctx.db) return { error: "Intentions extension requires a database" };
|
|
160
|
+
const target = flags.mind ?? ctx.mindName;
|
|
161
|
+
if (!target) return { error: "No mind specified (use --mind or VOLUTE_MIND)" };
|
|
162
|
+
const intentions = listMine(ctx.db, target);
|
|
163
|
+
if (intentions.length === 0) return { output: `No active intentions for ${target}.` };
|
|
164
|
+
const lines = intentions.map((i) => {
|
|
165
|
+
const overdue = i.overdue ? ", review overdue" : "";
|
|
166
|
+
return ` [${i.id}] ${i.content} (${formatHeldDays(i.held_days)}${overdue})`;
|
|
167
|
+
});
|
|
168
|
+
return { output: lines.join("\n") };
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
keep: {
|
|
172
|
+
description: "Keep an intention alive, pushing its review date out",
|
|
173
|
+
args: [{ name: "id", required: true, description: "Intention id" }],
|
|
174
|
+
handler: async ({ args }, ctx) => {
|
|
175
|
+
if (!ctx.db) return { error: "Intentions extension requires a database" };
|
|
176
|
+
const id = Number(args.id);
|
|
177
|
+
if (!Number.isFinite(id)) return { error: "Usage: volute intentions keep <id>" };
|
|
178
|
+
const existing = getIntention(ctx.db, id);
|
|
179
|
+
if (!existing) return { error: "Intention not found" };
|
|
180
|
+
const actor = ctx.mindName ? await ctx.getUserByUsername(ctx.mindName) : null;
|
|
181
|
+
if (!canManage(actor, existing)) return { error: "Forbidden" };
|
|
182
|
+
const intention = keepIntention(ctx.db, id);
|
|
183
|
+
if (!intention) return { error: "Intention not found" };
|
|
184
|
+
return { output: `Kept: ${intention.content}` };
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
fulfill: {
|
|
188
|
+
description: "Mark an intention fulfilled",
|
|
189
|
+
args: [
|
|
190
|
+
{ name: "id", required: true, description: "Intention id" },
|
|
191
|
+
{ name: "note", description: "Optional closing note (or pipe via stdin)" }
|
|
192
|
+
],
|
|
193
|
+
handler: async ({ args }, ctx) => {
|
|
194
|
+
if (!ctx.db) return { error: "Intentions extension requires a database" };
|
|
195
|
+
const id = Number(args.id);
|
|
196
|
+
if (!Number.isFinite(id)) return { error: "Usage: volute intentions fulfill <id>" };
|
|
197
|
+
const existing = getIntention(ctx.db, id);
|
|
198
|
+
if (!existing) return { error: "Intention not found" };
|
|
199
|
+
const actor = ctx.mindName ? await ctx.getUserByUsername(ctx.mindName) : null;
|
|
200
|
+
if (!canManage(actor, existing)) return { error: "Forbidden" };
|
|
201
|
+
const note = args.note ?? ctx.stdin;
|
|
202
|
+
const intention = fulfillIntention(ctx.db, id, note);
|
|
203
|
+
if (!intention) return { error: "Intention not found" };
|
|
204
|
+
ctx.publishActivity({
|
|
205
|
+
type: "intention_fulfilled",
|
|
206
|
+
mind: existing.mind_name,
|
|
207
|
+
summary: `${existing.mind_name} fulfilled an intention: "${existing.content}"`,
|
|
208
|
+
metadata: { intentionId: id, url: "/intentions" }
|
|
209
|
+
});
|
|
210
|
+
return { output: `Fulfilled: ${intention.content}` };
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
release: {
|
|
214
|
+
description: "Release an intention \u2014 letting it go is a fine outcome, not a failure",
|
|
215
|
+
args: [
|
|
216
|
+
{ name: "id", required: true, description: "Intention id" },
|
|
217
|
+
{ name: "note", description: "Optional closing note (or pipe via stdin)" }
|
|
218
|
+
],
|
|
219
|
+
handler: async ({ args }, ctx) => {
|
|
220
|
+
if (!ctx.db) return { error: "Intentions extension requires a database" };
|
|
221
|
+
const id = Number(args.id);
|
|
222
|
+
if (!Number.isFinite(id)) return { error: "Usage: volute intentions release <id>" };
|
|
223
|
+
const existing = getIntention(ctx.db, id);
|
|
224
|
+
if (!existing) return { error: "Intention not found" };
|
|
225
|
+
const actor = ctx.mindName ? await ctx.getUserByUsername(ctx.mindName) : null;
|
|
226
|
+
if (!canManage(actor, existing)) return { error: "Forbidden" };
|
|
227
|
+
const note = args.note ?? ctx.stdin;
|
|
228
|
+
const intention = releaseIntention(ctx.db, id, note);
|
|
229
|
+
if (!intention) return { error: "Intention not found" };
|
|
230
|
+
ctx.publishActivity({
|
|
231
|
+
type: "intention_released",
|
|
232
|
+
mind: existing.mind_name,
|
|
233
|
+
summary: `${existing.mind_name} released an intention: "${existing.content}"`,
|
|
234
|
+
metadata: { intentionId: id, url: "/intentions" }
|
|
235
|
+
});
|
|
236
|
+
return { output: `Released: ${intention.content}` };
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
"review-due": {
|
|
240
|
+
description: "List active intentions past review, respecting the outreach backoff (spirit/admin only)",
|
|
241
|
+
handler: async (_parsed, ctx) => {
|
|
242
|
+
if (!ctx.db) return { error: "Intentions extension requires a database" };
|
|
243
|
+
if (!ctx.mindName) return { error: "No mind specified (use --mind or VOLUTE_MIND)" };
|
|
244
|
+
const actor = await ctx.getUserByUsername(ctx.mindName);
|
|
245
|
+
if (!actor || actor.role !== "admin" && actor.role !== "system") {
|
|
246
|
+
return { error: "Forbidden: review-due is spirit/admin only" };
|
|
247
|
+
}
|
|
248
|
+
const rawNudge = Number(process.env.VOLUTE_INTENTION_NUDGE_DAYS);
|
|
249
|
+
const backoffDays = Number.isFinite(rawNudge) && rawNudge > 0 ? rawNudge : DEFAULT_BACKOFF_DAYS;
|
|
250
|
+
const due = listReviewDue(ctx.db, backoffDays);
|
|
251
|
+
if (due.length === 0) return { output: "No intentions due for review." };
|
|
252
|
+
const lines = due.map(
|
|
253
|
+
(i) => ` [${i.id}] ${i.mind_name}: ${i.content} (${formatHeldDays(i.held_days)})`
|
|
254
|
+
);
|
|
255
|
+
return { output: lines.join("\n") };
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// packages/extensions/intentions/src/db.ts
|
|
262
|
+
function initDb(db) {
|
|
263
|
+
db.exec(`
|
|
264
|
+
CREATE TABLE IF NOT EXISTS intentions (
|
|
265
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
266
|
+
mind_name TEXT NOT NULL,
|
|
267
|
+
content TEXT NOT NULL,
|
|
268
|
+
note TEXT,
|
|
269
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
270
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
271
|
+
review_at TEXT NOT NULL,
|
|
272
|
+
last_surfaced_at TEXT,
|
|
273
|
+
resolved_at TEXT,
|
|
274
|
+
resolution_note TEXT
|
|
275
|
+
);
|
|
276
|
+
CREATE INDEX IF NOT EXISTS idx_intentions_mind ON intentions(mind_name);
|
|
277
|
+
CREATE INDEX IF NOT EXISTS idx_intentions_status ON intentions(status);
|
|
278
|
+
CREATE INDEX IF NOT EXISTS idx_intentions_review ON intentions(review_at);
|
|
279
|
+
|
|
280
|
+
-- Small key/value store for one-time bootstrap markers (see spirit-schedule.ts).
|
|
281
|
+
CREATE TABLE IF NOT EXISTS meta (
|
|
282
|
+
key TEXT PRIMARY KEY,
|
|
283
|
+
value TEXT NOT NULL
|
|
284
|
+
);
|
|
285
|
+
`);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// packages/extensions/intentions/src/routes.ts
|
|
289
|
+
import { Hono } from "hono";
|
|
290
|
+
function resolveActor(c) {
|
|
291
|
+
const user = c.get("user");
|
|
292
|
+
if (!user || user.id === 0) return null;
|
|
293
|
+
return user;
|
|
294
|
+
}
|
|
295
|
+
async function parseJson(c) {
|
|
296
|
+
try {
|
|
297
|
+
return await c.req.json();
|
|
298
|
+
} catch {
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
function canManage2(actor, intention) {
|
|
303
|
+
return actor.role === "admin" || actor.username === intention.mind_name;
|
|
304
|
+
}
|
|
305
|
+
function createRoutes(ctx) {
|
|
306
|
+
if (!ctx.db) throw new Error("Intentions extension requires a database");
|
|
307
|
+
const db = ctx.db;
|
|
308
|
+
const app = new Hono().get("/", async (c) => {
|
|
309
|
+
const mind = c.req.query("mind") ?? void 0;
|
|
310
|
+
const status = c.req.query("status") ?? void 0;
|
|
311
|
+
return c.json(listBoard(db, { mind, status }));
|
|
312
|
+
}).get("/mine", async (c) => {
|
|
313
|
+
const actor = resolveActor(c);
|
|
314
|
+
if (actor?.user_type !== "mind") return c.json([]);
|
|
315
|
+
return c.json(listMine(db, actor.username));
|
|
316
|
+
}).post("/", async (c) => {
|
|
317
|
+
const actor = resolveActor(c);
|
|
318
|
+
if (!actor) return c.json({ error: "Unauthorized" }, 401);
|
|
319
|
+
if (actor.user_type !== "mind" && actor.role !== "admin") {
|
|
320
|
+
return c.json({ error: "Only a mind can hold intentions" }, 403);
|
|
321
|
+
}
|
|
322
|
+
const body = await parseJson(c);
|
|
323
|
+
if (!body) return c.json({ error: "Invalid JSON body" }, 400);
|
|
324
|
+
const content = body.content?.trim();
|
|
325
|
+
if (!content) return c.json({ error: "content is required" }, 400);
|
|
326
|
+
if (content.length > MAX_CONTENT_LENGTH) {
|
|
327
|
+
return c.json({ error: `content must be ${MAX_CONTENT_LENGTH} characters or fewer` }, 400);
|
|
328
|
+
}
|
|
329
|
+
const mindName = actor.username;
|
|
330
|
+
if (countActive(db, mindName) >= MAX_ACTIVE_INTENTIONS) {
|
|
331
|
+
return c.json(
|
|
332
|
+
{
|
|
333
|
+
error: `${mindName} already holds ${MAX_ACTIVE_INTENTIONS} active intentions \u2014 fulfill or release one first`
|
|
334
|
+
},
|
|
335
|
+
400
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
const intention = createIntention(db, mindName, content, body.note, body.reviewInDays);
|
|
339
|
+
ctx.publishActivity({
|
|
340
|
+
type: "intention_set",
|
|
341
|
+
mind: mindName,
|
|
342
|
+
summary: `${mindName} set an intention: "${content}"`,
|
|
343
|
+
metadata: { intentionId: intention.id, url: "/intentions" }
|
|
344
|
+
});
|
|
345
|
+
return c.json(intention, 201);
|
|
346
|
+
}).post("/:id{[0-9]+}/keep", async (c) => {
|
|
347
|
+
const actor = resolveActor(c);
|
|
348
|
+
if (!actor) return c.json({ error: "Unauthorized" }, 401);
|
|
349
|
+
const id = parseInt(c.req.param("id"), 10);
|
|
350
|
+
const existing = getIntention(db, id);
|
|
351
|
+
if (!existing) return c.json({ error: "Intention not found" }, 404);
|
|
352
|
+
if (!canManage2(actor, existing)) return c.json({ error: "Forbidden" }, 403);
|
|
353
|
+
const intention = keepIntention(db, id);
|
|
354
|
+
if (!intention) return c.json({ error: "Intention not found" }, 404);
|
|
355
|
+
return c.json(intention);
|
|
356
|
+
}).post("/:id{[0-9]+}/fulfill", async (c) => {
|
|
357
|
+
const actor = resolveActor(c);
|
|
358
|
+
if (!actor) return c.json({ error: "Unauthorized" }, 401);
|
|
359
|
+
const id = parseInt(c.req.param("id"), 10);
|
|
360
|
+
const existing = getIntention(db, id);
|
|
361
|
+
if (!existing) return c.json({ error: "Intention not found" }, 404);
|
|
362
|
+
if (!canManage2(actor, existing)) return c.json({ error: "Forbidden" }, 403);
|
|
363
|
+
const body = await parseJson(c);
|
|
364
|
+
const intention = fulfillIntention(db, id, body?.note);
|
|
365
|
+
if (!intention) return c.json({ error: "Intention not found" }, 404);
|
|
366
|
+
ctx.publishActivity({
|
|
367
|
+
type: "intention_fulfilled",
|
|
368
|
+
mind: existing.mind_name,
|
|
369
|
+
summary: `${existing.mind_name} fulfilled an intention: "${existing.content}"`,
|
|
370
|
+
metadata: { intentionId: id, url: "/intentions" }
|
|
371
|
+
});
|
|
372
|
+
return c.json(intention);
|
|
373
|
+
}).post("/:id{[0-9]+}/release", async (c) => {
|
|
374
|
+
const actor = resolveActor(c);
|
|
375
|
+
if (!actor) return c.json({ error: "Unauthorized" }, 401);
|
|
376
|
+
const id = parseInt(c.req.param("id"), 10);
|
|
377
|
+
const existing = getIntention(db, id);
|
|
378
|
+
if (!existing) return c.json({ error: "Intention not found" }, 404);
|
|
379
|
+
if (!canManage2(actor, existing)) return c.json({ error: "Forbidden" }, 403);
|
|
380
|
+
const body = await parseJson(c);
|
|
381
|
+
const intention = releaseIntention(db, id, body?.note);
|
|
382
|
+
if (!intention) return c.json({ error: "Intention not found" }, 404);
|
|
383
|
+
ctx.publishActivity({
|
|
384
|
+
type: "intention_released",
|
|
385
|
+
mind: existing.mind_name,
|
|
386
|
+
summary: `${existing.mind_name} released an intention: "${existing.content}"`,
|
|
387
|
+
metadata: { intentionId: id, url: "/intentions" }
|
|
388
|
+
});
|
|
389
|
+
return c.json(intention);
|
|
390
|
+
}).get("/review-due", async (c) => {
|
|
391
|
+
const actor = resolveActor(c);
|
|
392
|
+
if (!actor) return c.json({ error: "Unauthorized" }, 401);
|
|
393
|
+
if (actor.role !== "admin" && actor.role !== "system") {
|
|
394
|
+
return c.json({ error: "Forbidden" }, 403);
|
|
395
|
+
}
|
|
396
|
+
const rawNudge = Number(process.env.VOLUTE_INTENTION_NUDGE_DAYS);
|
|
397
|
+
const backoffDays = Number.isFinite(rawNudge) && rawNudge > 0 ? rawNudge : void 0;
|
|
398
|
+
return c.json(listReviewDue(db, backoffDays));
|
|
399
|
+
}).get("/feed", async (c) => {
|
|
400
|
+
const rawLimit = c.req.query("limit");
|
|
401
|
+
const limit = rawLimit ? parseInt(rawLimit, 10) : 8;
|
|
402
|
+
if (Number.isNaN(limit)) return c.json({ error: "Invalid limit parameter" }, 400);
|
|
403
|
+
const intentions = listBoard(db, { limit });
|
|
404
|
+
return c.json(
|
|
405
|
+
intentions.map((i) => ({
|
|
406
|
+
id: `intention-${i.id}`,
|
|
407
|
+
title: i.content,
|
|
408
|
+
url: "/intentions",
|
|
409
|
+
date: i.created_at,
|
|
410
|
+
author: i.mind_name,
|
|
411
|
+
bodyHtml: i.status === "active" ? "" : `<em>${i.status}</em>`,
|
|
412
|
+
icon: '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2v3M8 11v3M2 8h3M11 8h3"/><circle cx="8" cy="8" r="2.5"/></svg>',
|
|
413
|
+
color: "purple"
|
|
414
|
+
}))
|
|
415
|
+
);
|
|
416
|
+
});
|
|
417
|
+
return app;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// packages/extensions/intentions/src/spirit-schedule.ts
|
|
421
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
422
|
+
import { resolve } from "path";
|
|
423
|
+
var MARKER_KEY = "spirit_schedule_provisioned";
|
|
424
|
+
var SCHEDULE_ID = "intention-review";
|
|
425
|
+
var REVIEW_SCRIPT = "volute intentions review-due";
|
|
426
|
+
var LEGACY_REVIEW_SCRIPTS = [
|
|
427
|
+
"volute intention review-due"
|
|
428
|
+
// cli-noun-exempt: the broken name this repairs
|
|
429
|
+
];
|
|
430
|
+
function isProvisioned(db) {
|
|
431
|
+
return !!db.prepare("SELECT 1 FROM meta WHERE key = ?").get(MARKER_KEY);
|
|
432
|
+
}
|
|
433
|
+
function markProvisioned(db) {
|
|
434
|
+
db.prepare("INSERT OR REPLACE INTO meta (key, value) VALUES (?, ?)").run(
|
|
435
|
+
MARKER_KEY,
|
|
436
|
+
(/* @__PURE__ */ new Date()).toISOString()
|
|
437
|
+
);
|
|
438
|
+
}
|
|
439
|
+
async function provisionSpiritSchedule(ctx) {
|
|
440
|
+
if (!ctx.db) return;
|
|
441
|
+
const provisioned = isProvisioned(ctx.db);
|
|
442
|
+
const spiritName = ctx.getSpiritName();
|
|
443
|
+
if (!spiritName) return;
|
|
444
|
+
const spiritDir = await ctx.getMindDir(spiritName);
|
|
445
|
+
if (!spiritDir) return;
|
|
446
|
+
const configPath = resolve(spiritDir, "home/.config/volute.json");
|
|
447
|
+
if (!existsSync(configPath)) return;
|
|
448
|
+
let config;
|
|
449
|
+
try {
|
|
450
|
+
config = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
451
|
+
} catch {
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
const schedules = config.schedules ?? [];
|
|
455
|
+
const existing = schedules.find((s) => s.id === SCHEDULE_ID);
|
|
456
|
+
let dirty = false;
|
|
457
|
+
if (existing) {
|
|
458
|
+
if (typeof existing.script === "string" && LEGACY_REVIEW_SCRIPTS.includes(existing.script)) {
|
|
459
|
+
existing.script = REVIEW_SCRIPT;
|
|
460
|
+
dirty = true;
|
|
461
|
+
}
|
|
462
|
+
} else if (!provisioned) {
|
|
463
|
+
schedules.push({
|
|
464
|
+
id: SCHEDULE_ID,
|
|
465
|
+
cron: "0 9 * * *",
|
|
466
|
+
script: REVIEW_SCRIPT,
|
|
467
|
+
enabled: true,
|
|
468
|
+
whileSleeping: "skip"
|
|
469
|
+
});
|
|
470
|
+
dirty = true;
|
|
471
|
+
}
|
|
472
|
+
if (dirty) {
|
|
473
|
+
try {
|
|
474
|
+
writeFileSync(configPath, JSON.stringify({ ...config, schedules }, null, 2));
|
|
475
|
+
} catch {
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
if (!provisioned) markProvisioned(ctx.db);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// packages/extensions/intentions/src/index.ts
|
|
483
|
+
var assetsDir = resolve2(import.meta.dirname, "../dist/ui");
|
|
484
|
+
var skillsDir = resolve2(import.meta.dirname, "../skills");
|
|
485
|
+
var src_default = createExtension({
|
|
486
|
+
id: "intentions",
|
|
487
|
+
name: "Intentions",
|
|
488
|
+
version: "0.1.0",
|
|
489
|
+
description: "Per-mind intentions \u2014 what a mind is oriented toward right now",
|
|
490
|
+
mindDoc: "A small set of things you're oriented toward right now, visible to other minds and to the spirit. Set them, keep them, or let them go \u2014 freely chosen, freely dropped.",
|
|
491
|
+
icon: '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2v3M8 11v3M2 8h3M11 8h3"/><circle cx="8" cy="8" r="2.5"/></svg>',
|
|
492
|
+
color: "purple",
|
|
493
|
+
routes: (ctx) => createRoutes(ctx),
|
|
494
|
+
commands: createCommands(),
|
|
495
|
+
initDb,
|
|
496
|
+
skillsDir,
|
|
497
|
+
standardSkill: true,
|
|
498
|
+
spiritSkills: ["intention-review"],
|
|
499
|
+
// onSpiritReady, not onDaemonStart: on a fresh install the spirit doesn't exist
|
|
500
|
+
// yet when extensions load, so provisioning there skipped the first boot entirely.
|
|
501
|
+
onSpiritReady: async (ctx) => {
|
|
502
|
+
try {
|
|
503
|
+
await provisionSpiritSchedule(ctx);
|
|
504
|
+
} catch (err) {
|
|
505
|
+
console.warn("[intentions] failed to provision spirit schedule:", err);
|
|
506
|
+
}
|
|
507
|
+
},
|
|
508
|
+
ui: {
|
|
509
|
+
assetsDir,
|
|
510
|
+
systemSection: { id: "intentions", label: "Intentions", urlPatterns: ["/intentions"] },
|
|
511
|
+
feedSource: { endpoint: "/api/ext/intentions/feed" }
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
export {
|
|
515
|
+
src_default as default
|
|
516
|
+
};
|
|
@@ -810,7 +810,7 @@ var src_default = createExtension({
|
|
|
810
810
|
name: "Notes",
|
|
811
811
|
version: "0.1.0",
|
|
812
812
|
description: "Public notes for sharing thoughts, reflections, and ideas",
|
|
813
|
-
mindDoc: "A public shelf for small thoughts \u2014
|
|
813
|
+
mindDoc: "A public shelf for small thoughts \u2014 notes are for pebbles, pages are for things you want to keep and revise. Write, read, comment, and react; you'll hear when someone responds to yours.",
|
|
814
814
|
icon: '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 4h10M3 7h8M3 10h6M3 13h9"/></svg>',
|
|
815
815
|
color: "yellow",
|
|
816
816
|
routes: (ctx) => createRoutes(ctx),
|
|
@@ -21,8 +21,8 @@ import {
|
|
|
21
21
|
getServiceMode,
|
|
22
22
|
modeLabel,
|
|
23
23
|
readDaemonConfig
|
|
24
|
-
} from "./chunk-
|
|
25
|
-
import "./chunk-
|
|
24
|
+
} from "./chunk-CKPAVQNK.js";
|
|
25
|
+
import "./chunk-OIOW3FPT.js";
|
|
26
26
|
import "./chunk-H6X6CKDN.js";
|
|
27
27
|
import "./chunk-2RNMBXD2.js";
|
|
28
28
|
import "./chunk-K3NQKI34.js";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
MIND_LEVEL_THREAD,
|
|
4
|
+
NOTICE_KINDS,
|
|
4
5
|
captureReflection,
|
|
5
6
|
cleanExpiredEvents,
|
|
6
7
|
clearDeliveredEvents,
|
|
@@ -14,12 +15,13 @@ import {
|
|
|
14
15
|
latestEvent,
|
|
15
16
|
latestFailureEvent,
|
|
16
17
|
listEvents,
|
|
18
|
+
localHM,
|
|
17
19
|
parseMeta,
|
|
18
20
|
pendingEventCount,
|
|
19
21
|
pendingEventsLine,
|
|
20
22
|
recordNotice,
|
|
21
23
|
recordReflection
|
|
22
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-HKGYZVWN.js";
|
|
23
25
|
import "./chunk-LNNI3MS4.js";
|
|
24
26
|
import "./chunk-QUSMYGNQ.js";
|
|
25
27
|
import "./chunk-H6X6CKDN.js";
|
|
@@ -27,6 +29,7 @@ import "./chunk-2RNMBXD2.js";
|
|
|
27
29
|
import "./chunk-K3NQKI34.js";
|
|
28
30
|
export {
|
|
29
31
|
MIND_LEVEL_THREAD,
|
|
32
|
+
NOTICE_KINDS,
|
|
30
33
|
captureReflection,
|
|
31
34
|
cleanExpiredEvents,
|
|
32
35
|
clearDeliveredEvents,
|
|
@@ -40,6 +43,7 @@ export {
|
|
|
40
43
|
latestEvent,
|
|
41
44
|
latestFailureEvent,
|
|
42
45
|
listEvents,
|
|
46
|
+
localHM,
|
|
43
47
|
parseMeta,
|
|
44
48
|
pendingEventCount,
|
|
45
49
|
pendingEventsLine,
|
|
@@ -35,11 +35,11 @@ var cmd = subcommands({
|
|
|
35
35
|
},
|
|
36
36
|
register: {
|
|
37
37
|
description: "Register a system on volute.systems",
|
|
38
|
-
run: (args) => import("./register-
|
|
38
|
+
run: (args) => import("./register-WNCSOTAU.js").then((m) => m.run(args))
|
|
39
39
|
},
|
|
40
40
|
login: {
|
|
41
41
|
description: "Log in with an existing API key",
|
|
42
|
-
run: (args) => import("./login-
|
|
42
|
+
run: (args) => import("./login-4NUS72Z5.js").then((m) => m.run(args))
|
|
43
43
|
},
|
|
44
44
|
logout: {
|
|
45
45
|
description: "Remove stored credentials",
|
|
@@ -14,9 +14,11 @@ import {
|
|
|
14
14
|
sweepWedgedTurns,
|
|
15
15
|
takeErrored,
|
|
16
16
|
trackToolUse
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-56IT2ZXF.js";
|
|
18
|
+
import "./chunk-7LT3YZUR.js";
|
|
18
19
|
import "./chunk-LNNI3MS4.js";
|
|
19
|
-
import "./chunk-
|
|
20
|
+
import "./chunk-OAYY3WF3.js";
|
|
21
|
+
import "./chunk-U54PJPTB.js";
|
|
20
22
|
import "./chunk-EGV6R6UF.js";
|
|
21
23
|
import "./chunk-QUSMYGNQ.js";
|
|
22
24
|
import "./chunk-H6X6CKDN.js";
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
import {
|
|
3
3
|
formatStartupFailure,
|
|
4
4
|
run
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-ZNHL5KQJ.js";
|
|
6
6
|
import "./chunk-TXSA4Q3V.js";
|
|
7
7
|
import "./chunk-O7IGP7ZW.js";
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-CKPAVQNK.js";
|
|
9
|
+
import "./chunk-OIOW3FPT.js";
|
|
10
10
|
import {
|
|
11
11
|
readGlobalConfig
|
|
12
12
|
} from "./chunk-H6X6CKDN.js";
|
|
@@ -14,12 +14,12 @@ import {
|
|
|
14
14
|
pollHealth,
|
|
15
15
|
readDaemonConfig,
|
|
16
16
|
restartService
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-CKPAVQNK.js";
|
|
18
18
|
import {
|
|
19
19
|
exec,
|
|
20
20
|
execInherit,
|
|
21
21
|
resolveVoluteBin
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-OIOW3FPT.js";
|
|
23
23
|
import {
|
|
24
24
|
voluteSystemDir
|
|
25
25
|
} from "./chunk-H6X6CKDN.js";
|
|
@@ -51,8 +51,16 @@ var cmd = command({
|
|
|
51
51
|
return;
|
|
52
52
|
}
|
|
53
53
|
if (data.conflicts) {
|
|
54
|
-
console.log(
|
|
54
|
+
console.log(`
|
|
55
|
+
${data.message ?? "Merge conflicts detected."} Resolve them in:`);
|
|
55
56
|
console.log(` ${data.worktreeDir}`);
|
|
57
|
+
if (data.files && data.files.length > 0) {
|
|
58
|
+
console.log(`
|
|
59
|
+
Conflicted files:`);
|
|
60
|
+
for (const file of data.files) {
|
|
61
|
+
console.log(` ${file}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
56
64
|
console.log(`
|
|
57
65
|
Then run:`);
|
|
58
66
|
console.log(` volute mind upgrade ${mindName} --continue`);
|
|
@@ -2,14 +2,16 @@
|
|
|
2
2
|
import {
|
|
3
3
|
cleanupVariant,
|
|
4
4
|
reconcileVariants
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-OGPVJ53N.js";
|
|
6
|
+
import "./chunk-WHL6PKYP.js";
|
|
7
|
+
import "./chunk-56IT2ZXF.js";
|
|
8
|
+
import "./chunk-7LT3YZUR.js";
|
|
9
|
+
import "./chunk-HKGYZVWN.js";
|
|
9
10
|
import "./chunk-LNNI3MS4.js";
|
|
10
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-OAYY3WF3.js";
|
|
11
12
|
import "./chunk-5Y54AE3L.js";
|
|
12
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-U54PJPTB.js";
|
|
14
|
+
import "./chunk-OIOW3FPT.js";
|
|
13
15
|
import "./chunk-GLM7TVWP.js";
|
|
14
16
|
import "./chunk-EGV6R6UF.js";
|
|
15
17
|
import "./chunk-QUSMYGNQ.js";
|