clawvault 3.1.0 → 3.2.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/README.md +422 -141
- package/bin/clawvault.js +10 -2
- package/bin/command-registration.test.js +3 -1
- package/bin/command-runtime.js +9 -1
- package/bin/register-core-commands.js +23 -28
- package/bin/register-maintenance-commands.js +39 -3
- package/bin/register-query-commands.js +58 -29
- package/bin/register-tailscale-commands.js +106 -0
- package/bin/register-task-commands.js +18 -1
- package/bin/register-task-commands.test.js +16 -0
- package/bin/register-vault-operations-commands.js +29 -1
- package/bin/register-workgraph-commands.js +1368 -0
- package/dashboard/lib/graph-diff.js +104 -0
- package/dashboard/lib/graph-diff.test.js +75 -0
- package/dashboard/lib/vault-parser.js +556 -0
- package/dashboard/lib/vault-parser.test.js +254 -0
- package/dashboard/public/app.js +796 -0
- package/dashboard/public/index.html +52 -0
- package/dashboard/public/styles.css +221 -0
- package/dashboard/server.js +374 -0
- package/dist/{chunk-F2JEUD4J.js → chunk-23YDQ3QU.js} +6 -8
- package/dist/{chunk-C7OK5WKP.js → chunk-2JQ3O2YL.js} +4 -4
- package/dist/{chunk-VR5NE7PZ.js → chunk-2RAZ4ZFE.js} +1 -1
- package/dist/chunk-2ZDO52B4.js +52 -0
- package/dist/{chunk-ZZA73MFY.js → chunk-33DOSHTA.js} +176 -36
- package/dist/chunk-33VSQP4J.js +37 -0
- package/dist/chunk-4BQTQMJP.js +93 -0
- package/dist/{chunk-GUKMRGM7.js → chunk-4OXMU5S2.js} +1 -1
- package/dist/{chunk-62YTUT6J.js → chunk-4PY655YM.js} +15 -3
- package/dist/chunk-6FH3IULF.js +352 -0
- package/dist/{chunk-3NSBOUT3.js → chunk-77Q5CSPJ.js} +404 -80
- package/dist/{chunk-4VQTUVH7.js → chunk-7YZWHM36.js} +52 -26
- package/dist/chunk-BSJ6RIT7.js +447 -0
- package/dist/chunk-BUEW6IIK.js +364 -0
- package/dist/{chunk-LI4O6NVK.js → chunk-CLJTREDS.js} +74 -14
- package/dist/chunk-EK6S23ZB.js +469 -0
- package/dist/{chunk-LNJA2UGL.js → chunk-ESFLMDRB.js} +9 -86
- package/dist/{chunk-H34S76MB.js → chunk-ESVS6K2B.js} +6 -6
- package/dist/{chunk-WAZ3NLWL.js → chunk-F55HGNU4.js} +0 -47
- package/dist/{chunk-QK3UCXWL.js → chunk-FHFUXL6G.js} +2 -2
- package/dist/{chunk-H62BP7RI.js → chunk-GAOWA7GR.js} +212 -46
- package/dist/chunk-GGA32J2R.js +784 -0
- package/dist/chunk-GNJL4YGR.js +79 -0
- package/dist/chunk-IVRIKYFE.js +520 -0
- package/dist/chunk-MDIH26GC.js +183 -0
- package/dist/{chunk-LYHGEHXG.js → chunk-MFAWT5O5.js} +0 -1
- package/dist/chunk-MM6QGW3P.js +207 -0
- package/dist/{chunk-P5EPF6MB.js → chunk-MW5C6ZQA.js} +110 -13
- package/dist/chunk-NCKFNBHJ.js +257 -0
- package/dist/{chunk-QBLMXKF2.js → chunk-OIWVQYQF.js} +1 -1
- package/dist/{chunk-42MXU7A6.js → chunk-P62WHA27.js} +58 -47
- package/dist/chunk-PBACDKKP.js +66 -0
- package/dist/{chunk-VGLOTGAS.js → chunk-QSHD36LH.js} +2 -2
- package/dist/{chunk-OZ7RIXTO.js → chunk-QSRRMEYM.js} +2 -2
- package/dist/chunk-QVEERJSP.js +152 -0
- package/dist/{chunk-N2AXRYLC.js → chunk-QWQ3TIKS.js} +1 -1
- package/dist/{chunk-3DHXQHYG.js → chunk-R2MIW5G7.js} +1 -1
- package/dist/{chunk-SJSFRIYS.js → chunk-SLXOR3CC.js} +2 -2
- package/dist/chunk-SS4B7P7V.js +99 -0
- package/dist/{chunk-JY6FYXIT.js → chunk-STCQGCEQ.js} +6 -11
- package/dist/chunk-TIGW564L.js +628 -0
- package/dist/chunk-U4O6C46S.js +154 -0
- package/dist/{chunk-ITPEXLHA.js → chunk-URXDAUVH.js} +24 -5
- package/dist/chunk-VSL7KY3M.js +189 -0
- package/dist/{chunk-U55BGUAU.js → chunk-W4SPAEE7.js} +6 -6
- package/dist/chunk-WMGIIABP.js +15 -0
- package/dist/{chunk-33UGEQRT.js → chunk-X3SPPUFG.js} +151 -64
- package/dist/chunk-Y6VJKXGL.js +373 -0
- package/dist/{chunk-3WRJEKN4.js → chunk-ZN54U2OZ.js} +123 -10
- package/dist/cli/index.js +34 -24
- package/dist/commands/archive.js +3 -3
- package/dist/commands/backlog.js +3 -3
- package/dist/commands/blocked.js +3 -3
- package/dist/commands/canvas.d.ts +15 -0
- package/dist/commands/canvas.js +200 -0
- package/dist/commands/checkpoint.js +2 -2
- package/dist/commands/compat.js +2 -2
- package/dist/commands/context.js +8 -6
- package/dist/commands/doctor.d.ts +11 -7
- package/dist/commands/doctor.js +18 -16
- package/dist/commands/embed.js +5 -6
- package/dist/commands/entities.js +2 -2
- package/dist/commands/graph.js +4 -4
- package/dist/commands/inject.d.ts +1 -1
- package/dist/commands/inject.js +5 -6
- package/dist/commands/kanban.js +4 -4
- package/dist/commands/link.js +5 -5
- package/dist/commands/migrate-observations.js +4 -4
- package/dist/commands/observe.d.ts +0 -1
- package/dist/commands/observe.js +14 -13
- package/dist/commands/project.js +5 -5
- package/dist/commands/rebuild-embeddings.d.ts +21 -0
- package/dist/commands/rebuild-embeddings.js +91 -0
- package/dist/commands/rebuild.js +12 -11
- package/dist/commands/recover.js +3 -3
- package/dist/commands/reflect.js +6 -7
- package/dist/commands/repair-session.js +1 -1
- package/dist/commands/replay.js +14 -14
- package/dist/commands/session-recap.js +1 -1
- package/dist/commands/setup.d.ts +2 -89
- package/dist/commands/setup.js +3 -21
- package/dist/commands/shell-init.js +1 -1
- package/dist/commands/sleep.d.ts +1 -1
- package/dist/commands/sleep.js +20 -19
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/status.js +57 -35
- package/dist/commands/sync-bd.d.ts +10 -0
- package/dist/commands/sync-bd.js +10 -0
- package/dist/commands/tailscale.d.ts +52 -0
- package/dist/commands/tailscale.js +26 -0
- package/dist/commands/task.js +4 -4
- package/dist/commands/template.js +2 -2
- package/dist/commands/wake.d.ts +1 -1
- package/dist/commands/wake.js +11 -10
- package/dist/commands/workgraph.d.ts +124 -0
- package/dist/commands/workgraph.js +38 -0
- package/dist/index.d.ts +341 -191
- package/dist/index.js +446 -116
- package/dist/{inject-Bzi5E-By.d.ts → inject-DYUrDqQO.d.ts} +3 -3
- package/dist/ledger-B7g7jhqG.d.ts +44 -0
- package/dist/lib/auto-linker.js +2 -2
- package/dist/lib/canvas-layout.d.ts +115 -0
- package/dist/lib/canvas-layout.js +35 -0
- package/dist/lib/config.d.ts +27 -3
- package/dist/lib/config.js +4 -2
- package/dist/lib/entity-index.js +1 -1
- package/dist/lib/project-utils.js +4 -4
- package/dist/lib/session-repair.js +1 -1
- package/dist/lib/session-utils.js +1 -1
- package/dist/lib/tailscale.d.ts +225 -0
- package/dist/lib/tailscale.js +50 -0
- package/dist/lib/task-utils.js +3 -3
- package/dist/lib/template-engine.js +1 -1
- package/dist/lib/webdav.d.ts +109 -0
- package/dist/lib/webdav.js +35 -0
- package/dist/onnxruntime_binding-5QEF3SUC.node +0 -0
- package/dist/onnxruntime_binding-BKPKNEGC.node +0 -0
- package/dist/onnxruntime_binding-FMOXGIUT.node +0 -0
- package/dist/onnxruntime_binding-OI2KMXC5.node +0 -0
- package/dist/onnxruntime_binding-UX44MLAZ.node +0 -0
- package/dist/onnxruntime_binding-Y2W7N7WY.node +0 -0
- package/dist/openclaw-plugin.d.ts +8 -0
- package/dist/openclaw-plugin.js +14 -0
- package/dist/registry-BR4326o0.d.ts +30 -0
- package/dist/store-CA-6sKCJ.d.ts +34 -0
- package/dist/thread-B9LhXNU0.d.ts +41 -0
- package/dist/transformers.node-A2ZRORSQ.js +46775 -0
- package/dist/{types-Y2_Um2Ls.d.ts → types-BbWJoC1c.d.ts} +1 -44
- package/dist/workgraph/index.d.ts +5 -0
- package/dist/workgraph/index.js +23 -0
- package/dist/workgraph/ledger.d.ts +2 -0
- package/dist/workgraph/ledger.js +25 -0
- package/dist/workgraph/registry.d.ts +2 -0
- package/dist/workgraph/registry.js +19 -0
- package/dist/workgraph/store.d.ts +2 -0
- package/dist/workgraph/store.js +25 -0
- package/dist/workgraph/thread.d.ts +2 -0
- package/dist/workgraph/thread.js +25 -0
- package/dist/workgraph/types.d.ts +54 -0
- package/dist/workgraph/types.js +7 -0
- package/hooks/clawvault/HOOK.md +113 -0
- package/hooks/clawvault/handler.js +1561 -0
- package/hooks/clawvault/handler.test.js +510 -0
- package/hooks/clawvault/openclaw.plugin.json +72 -0
- package/openclaw.plugin.json +65 -38
- package/package.json +25 -22
- package/dist/chunk-3RG5ZIWI.js +0 -10
- package/dist/chunk-3ZIH425O.js +0 -871
- package/dist/chunk-6U6MK36V.js +0 -205
- package/dist/chunk-CMB7UL7C.js +0 -327
- package/dist/chunk-D2H45LON.js +0 -1074
- package/dist/chunk-E7MFQB6D.js +0 -163
- package/dist/chunk-GQSLDZTS.js +0 -560
- package/dist/chunk-MFM6K7PU.js +0 -374
- package/dist/chunk-MXSSG3QU.js +0 -42
- package/dist/chunk-OCGVIN3L.js +0 -88
- package/dist/chunk-PAH27GSN.js +0 -108
- package/dist/chunk-YCUNCH2I.js +0 -78
- package/dist/cli/index.cjs +0 -8584
- package/dist/cli/index.d.cts +0 -5
- package/dist/commands/archive.cjs +0 -287
- package/dist/commands/archive.d.cts +0 -11
- package/dist/commands/backlog.cjs +0 -721
- package/dist/commands/backlog.d.cts +0 -53
- package/dist/commands/blocked.cjs +0 -204
- package/dist/commands/blocked.d.cts +0 -26
- package/dist/commands/checkpoint.cjs +0 -244
- package/dist/commands/checkpoint.d.cts +0 -41
- package/dist/commands/compat.cjs +0 -294
- package/dist/commands/compat.d.cts +0 -28
- package/dist/commands/context.cjs +0 -2990
- package/dist/commands/context.d.cts +0 -2
- package/dist/commands/doctor.cjs +0 -2986
- package/dist/commands/doctor.d.cts +0 -21
- package/dist/commands/embed.cjs +0 -232
- package/dist/commands/embed.d.cts +0 -17
- package/dist/commands/entities.cjs +0 -141
- package/dist/commands/entities.d.cts +0 -7
- package/dist/commands/graph.cjs +0 -501
- package/dist/commands/graph.d.cts +0 -21
- package/dist/commands/inject.cjs +0 -1636
- package/dist/commands/inject.d.cts +0 -2
- package/dist/commands/kanban.cjs +0 -884
- package/dist/commands/kanban.d.cts +0 -63
- package/dist/commands/link.cjs +0 -965
- package/dist/commands/link.d.cts +0 -11
- package/dist/commands/migrate-observations.cjs +0 -362
- package/dist/commands/migrate-observations.d.cts +0 -19
- package/dist/commands/observe.cjs +0 -4099
- package/dist/commands/observe.d.cts +0 -23
- package/dist/commands/project.cjs +0 -1341
- package/dist/commands/project.d.cts +0 -85
- package/dist/commands/rebuild.cjs +0 -3136
- package/dist/commands/rebuild.d.cts +0 -11
- package/dist/commands/recover.cjs +0 -361
- package/dist/commands/recover.d.cts +0 -38
- package/dist/commands/reflect.cjs +0 -1008
- package/dist/commands/reflect.d.cts +0 -11
- package/dist/commands/repair-session.cjs +0 -457
- package/dist/commands/repair-session.d.cts +0 -38
- package/dist/commands/replay.cjs +0 -4103
- package/dist/commands/replay.d.cts +0 -16
- package/dist/commands/session-recap.cjs +0 -353
- package/dist/commands/session-recap.d.cts +0 -27
- package/dist/commands/setup.cjs +0 -1278
- package/dist/commands/setup.d.cts +0 -99
- package/dist/commands/shell-init.cjs +0 -75
- package/dist/commands/shell-init.d.cts +0 -7
- package/dist/commands/sleep.cjs +0 -6029
- package/dist/commands/sleep.d.cts +0 -36
- package/dist/commands/status.cjs +0 -2737
- package/dist/commands/status.d.cts +0 -52
- package/dist/commands/task.cjs +0 -1236
- package/dist/commands/task.d.cts +0 -97
- package/dist/commands/template.cjs +0 -457
- package/dist/commands/template.d.cts +0 -36
- package/dist/commands/wake.cjs +0 -2627
- package/dist/commands/wake.d.cts +0 -22
- package/dist/context-BUGaWpyL.d.cts +0 -46
- package/dist/index.cjs +0 -12373
- package/dist/index.d.cts +0 -854
- package/dist/inject-Bzi5E-By.d.cts +0 -137
- package/dist/lib/auto-linker.cjs +0 -176
- package/dist/lib/auto-linker.d.cts +0 -26
- package/dist/lib/config.cjs +0 -78
- package/dist/lib/config.d.cts +0 -11
- package/dist/lib/entity-index.cjs +0 -84
- package/dist/lib/entity-index.d.cts +0 -26
- package/dist/lib/project-utils.cjs +0 -864
- package/dist/lib/project-utils.d.cts +0 -97
- package/dist/lib/session-repair.cjs +0 -239
- package/dist/lib/session-repair.d.cts +0 -110
- package/dist/lib/session-utils.cjs +0 -209
- package/dist/lib/session-utils.d.cts +0 -63
- package/dist/lib/task-utils.cjs +0 -1137
- package/dist/lib/task-utils.d.cts +0 -208
- package/dist/lib/template-engine.cjs +0 -47
- package/dist/lib/template-engine.d.cts +0 -11
- package/dist/plugin/index.cjs +0 -1907
- package/dist/plugin/index.d.cts +0 -36
- package/dist/plugin/index.d.ts +0 -36
- package/dist/plugin/index.js +0 -572
- package/dist/plugin/inject.cjs +0 -356
- package/dist/plugin/inject.d.cts +0 -54
- package/dist/plugin/inject.d.ts +0 -54
- package/dist/plugin/inject.js +0 -17
- package/dist/plugin/observe.cjs +0 -631
- package/dist/plugin/observe.d.cts +0 -39
- package/dist/plugin/observe.d.ts +0 -39
- package/dist/plugin/observe.js +0 -18
- package/dist/plugin/templates.cjs +0 -593
- package/dist/plugin/templates.d.cts +0 -52
- package/dist/plugin/templates.d.ts +0 -52
- package/dist/plugin/templates.js +0 -25
- package/dist/plugin/types.cjs +0 -18
- package/dist/plugin/types.d.cts +0 -209
- package/dist/plugin/types.d.ts +0 -209
- package/dist/plugin/types.js +0 -0
- package/dist/plugin/vault.cjs +0 -927
- package/dist/plugin/vault.d.cts +0 -68
- package/dist/plugin/vault.d.ts +0 -68
- package/dist/plugin/vault.js +0 -22
- package/dist/types-Y2_Um2Ls.d.cts +0 -205
- package/templates/memory-event.md +0 -67
- package/templates/party.md +0 -63
- package/templates/primitive-registry.yaml +0 -551
- package/templates/run.md +0 -68
- package/templates/trigger.md +0 -68
- package/templates/workspace.md +0 -50
package/dist/commands/task.cjs
DELETED
|
@@ -1,1236 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (let key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
-
}
|
|
18
|
-
return to;
|
|
19
|
-
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
|
|
30
|
-
// src/commands/task.ts
|
|
31
|
-
var task_exports = {};
|
|
32
|
-
__export(task_exports, {
|
|
33
|
-
formatTaskDetails: () => formatTaskDetails,
|
|
34
|
-
formatTaskList: () => formatTaskList,
|
|
35
|
-
taskAdd: () => taskAdd,
|
|
36
|
-
taskCommand: () => taskCommand,
|
|
37
|
-
taskDone: () => taskDone,
|
|
38
|
-
taskList: () => taskList,
|
|
39
|
-
taskShow: () => taskShow,
|
|
40
|
-
taskTransitions: () => taskTransitions,
|
|
41
|
-
taskUpdate: () => taskUpdate
|
|
42
|
-
});
|
|
43
|
-
module.exports = __toCommonJS(task_exports);
|
|
44
|
-
|
|
45
|
-
// src/lib/task-utils.ts
|
|
46
|
-
var fs3 = __toESM(require("fs"), 1);
|
|
47
|
-
var path3 = __toESM(require("path"), 1);
|
|
48
|
-
var import_gray_matter2 = __toESM(require("gray-matter"), 1);
|
|
49
|
-
|
|
50
|
-
// src/lib/transition-ledger.ts
|
|
51
|
-
var fs = __toESM(require("fs"), 1);
|
|
52
|
-
var path = __toESM(require("path"), 1);
|
|
53
|
-
var REGRESSION_PAIRS = [
|
|
54
|
-
["done", "open"],
|
|
55
|
-
["done", "blocked"],
|
|
56
|
-
["in-progress", "blocked"]
|
|
57
|
-
];
|
|
58
|
-
function isRegression(from, to) {
|
|
59
|
-
return REGRESSION_PAIRS.some(([f, t]) => f === from && t === to);
|
|
60
|
-
}
|
|
61
|
-
function getLedgerDir(vaultPath) {
|
|
62
|
-
return path.join(path.resolve(vaultPath), "ledger", "transitions");
|
|
63
|
-
}
|
|
64
|
-
function getTodayLedgerPath(vaultPath) {
|
|
65
|
-
const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
66
|
-
return path.join(getLedgerDir(vaultPath), `${date}.jsonl`);
|
|
67
|
-
}
|
|
68
|
-
var RETRYABLE_APPEND_CODES = /* @__PURE__ */ new Set(["ENOENT", "EAGAIN", "EBUSY"]);
|
|
69
|
-
var MAX_APPEND_RETRIES = 2;
|
|
70
|
-
function asErrno(error) {
|
|
71
|
-
if (!error || typeof error !== "object") {
|
|
72
|
-
return null;
|
|
73
|
-
}
|
|
74
|
-
return error;
|
|
75
|
-
}
|
|
76
|
-
function formatLedgerWriteError(filePath, error) {
|
|
77
|
-
const errno = asErrno(error);
|
|
78
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
79
|
-
if (errno?.code === "ENOSPC") {
|
|
80
|
-
return new Error(`Failed to write transition ledger at ${filePath}: no space left on device.`);
|
|
81
|
-
}
|
|
82
|
-
if (errno?.code === "EACCES" || errno?.code === "EPERM") {
|
|
83
|
-
return new Error(`Failed to write transition ledger at ${filePath}: permission denied.`);
|
|
84
|
-
}
|
|
85
|
-
return new Error(`Failed to write transition ledger at ${filePath}: ${message}`);
|
|
86
|
-
}
|
|
87
|
-
function appendTransition(vaultPath, event) {
|
|
88
|
-
const ledgerDir = getLedgerDir(vaultPath);
|
|
89
|
-
try {
|
|
90
|
-
fs.mkdirSync(ledgerDir, { recursive: true });
|
|
91
|
-
} catch (error) {
|
|
92
|
-
throw formatLedgerWriteError(ledgerDir, error);
|
|
93
|
-
}
|
|
94
|
-
const filePath = getTodayLedgerPath(vaultPath);
|
|
95
|
-
const payload = JSON.stringify(event) + "\n";
|
|
96
|
-
for (let attempt = 0; attempt <= MAX_APPEND_RETRIES; attempt += 1) {
|
|
97
|
-
try {
|
|
98
|
-
fs.appendFileSync(filePath, payload);
|
|
99
|
-
return;
|
|
100
|
-
} catch (error) {
|
|
101
|
-
const errno = asErrno(error);
|
|
102
|
-
const code = errno?.code;
|
|
103
|
-
if (code === "ENOENT") {
|
|
104
|
-
try {
|
|
105
|
-
fs.mkdirSync(ledgerDir, { recursive: true });
|
|
106
|
-
} catch (mkdirError) {
|
|
107
|
-
throw formatLedgerWriteError(filePath, mkdirError);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
if (code && RETRYABLE_APPEND_CODES.has(code) && attempt < MAX_APPEND_RETRIES) {
|
|
111
|
-
continue;
|
|
112
|
-
}
|
|
113
|
-
throw formatLedgerWriteError(filePath, error);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
function buildTransitionEvent(taskId, fromStatus, toStatus, options = {}) {
|
|
118
|
-
const agentId = process.env.OPENCLAW_AGENT_ID || "manual";
|
|
119
|
-
const costTokensRaw = process.env.OPENCLAW_TOKEN_ESTIMATE;
|
|
120
|
-
const costTokens = costTokensRaw ? parseInt(costTokensRaw, 10) : null;
|
|
121
|
-
return {
|
|
122
|
-
task_id: taskId,
|
|
123
|
-
agent_id: agentId,
|
|
124
|
-
from_status: fromStatus,
|
|
125
|
-
to_status: toStatus,
|
|
126
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
127
|
-
confidence: options.confidence ?? (agentId === "manual" ? 1 : 1),
|
|
128
|
-
cost_tokens: costTokens !== null && !isNaN(costTokens) ? costTokens : null,
|
|
129
|
-
reason: options.reason || null
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
function readAllTransitions(vaultPath) {
|
|
133
|
-
const ledgerDir = getLedgerDir(vaultPath);
|
|
134
|
-
if (!fs.existsSync(ledgerDir)) return [];
|
|
135
|
-
let files = [];
|
|
136
|
-
try {
|
|
137
|
-
files = fs.readdirSync(ledgerDir).filter((f) => f.endsWith(".jsonl")).sort();
|
|
138
|
-
} catch {
|
|
139
|
-
return [];
|
|
140
|
-
}
|
|
141
|
-
const events = [];
|
|
142
|
-
for (const file of files) {
|
|
143
|
-
let lines = [];
|
|
144
|
-
try {
|
|
145
|
-
lines = fs.readFileSync(path.join(ledgerDir, file), "utf-8").split("\n").filter((l) => l.trim());
|
|
146
|
-
} catch {
|
|
147
|
-
continue;
|
|
148
|
-
}
|
|
149
|
-
for (const line of lines) {
|
|
150
|
-
try {
|
|
151
|
-
events.push(JSON.parse(line));
|
|
152
|
-
} catch {
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
return events;
|
|
157
|
-
}
|
|
158
|
-
function queryTransitions(vaultPath, filters = {}) {
|
|
159
|
-
let events = readAllTransitions(vaultPath);
|
|
160
|
-
if (filters.taskId) {
|
|
161
|
-
events = events.filter((e) => e.task_id === filters.taskId);
|
|
162
|
-
}
|
|
163
|
-
if (filters.agent) {
|
|
164
|
-
events = events.filter((e) => e.agent_id === filters.agent);
|
|
165
|
-
}
|
|
166
|
-
if (filters.failed) {
|
|
167
|
-
events = events.filter((e) => isRegression(e.from_status, e.to_status));
|
|
168
|
-
}
|
|
169
|
-
return events;
|
|
170
|
-
}
|
|
171
|
-
function countBlockedTransitions(vaultPath, taskId) {
|
|
172
|
-
const events = readAllTransitions(vaultPath);
|
|
173
|
-
return events.filter((e) => e.task_id === taskId && e.to_status === "blocked").length;
|
|
174
|
-
}
|
|
175
|
-
function formatTransitionsTable(events) {
|
|
176
|
-
if (events.length === 0) return "No transitions found.\n";
|
|
177
|
-
const headers = ["TIMESTAMP", "TASK", "FROM\u2192TO", "AGENT", "REASON"];
|
|
178
|
-
const widths = [20, 20, 24, 16, 30];
|
|
179
|
-
let output = headers.map((h, i) => h.padEnd(widths[i])).join(" ") + "\n";
|
|
180
|
-
output += "-".repeat(widths.reduce((a, b) => a + b + 2, 0)) + "\n";
|
|
181
|
-
for (const e of events) {
|
|
182
|
-
const ts = e.timestamp.replace("T", " ").slice(0, 19);
|
|
183
|
-
const taskId = e.task_id.length > widths[1] ? e.task_id.slice(0, widths[1] - 3) + "..." : e.task_id;
|
|
184
|
-
const transition = `${e.from_status} \u2192 ${e.to_status}`;
|
|
185
|
-
const reason = e.reason ? e.reason.length > widths[4] ? e.reason.slice(0, widths[4] - 3) + "..." : e.reason : "-";
|
|
186
|
-
output += [
|
|
187
|
-
ts.padEnd(widths[0]),
|
|
188
|
-
taskId.padEnd(widths[1]),
|
|
189
|
-
transition.padEnd(widths[2]),
|
|
190
|
-
e.agent_id.padEnd(widths[3]),
|
|
191
|
-
reason
|
|
192
|
-
].join(" ") + "\n";
|
|
193
|
-
}
|
|
194
|
-
return output;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
// src/lib/primitive-templates.ts
|
|
198
|
-
var fs2 = __toESM(require("fs"), 1);
|
|
199
|
-
var path2 = __toESM(require("path"), 1);
|
|
200
|
-
var import_url = require("url");
|
|
201
|
-
var import_gray_matter = __toESM(require("gray-matter"), 1);
|
|
202
|
-
|
|
203
|
-
// src/lib/template-engine.ts
|
|
204
|
-
function buildTemplateVariables(input = {}, now = /* @__PURE__ */ new Date()) {
|
|
205
|
-
const datetime = input.datetime ?? now.toISOString();
|
|
206
|
-
const date = input.date ?? datetime.split("T")[0];
|
|
207
|
-
return {
|
|
208
|
-
title: input.title ?? "",
|
|
209
|
-
type: input.type ?? "",
|
|
210
|
-
date,
|
|
211
|
-
datetime
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
function renderTemplate(template, variables) {
|
|
215
|
-
return template.replace(/\{\{\s*([a-zA-Z0-9_-]+)\s*\}\}/g, (match, key) => {
|
|
216
|
-
const value = variables[key];
|
|
217
|
-
return value !== void 0 ? String(value) : match;
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// src/lib/primitive-templates.ts
|
|
222
|
-
var import_meta = {};
|
|
223
|
-
var TEMPLATE_EXTENSION = ".md";
|
|
224
|
-
function isRecord(value) {
|
|
225
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
226
|
-
}
|
|
227
|
-
function normalizeTemplateName(name) {
|
|
228
|
-
const base = path2.basename(name, path2.extname(name));
|
|
229
|
-
return base.trim();
|
|
230
|
-
}
|
|
231
|
-
function resolveBuiltinTemplatesDir(override) {
|
|
232
|
-
if (override) {
|
|
233
|
-
const resolved = path2.resolve(override);
|
|
234
|
-
return fs2.existsSync(resolved) && fs2.statSync(resolved).isDirectory() ? resolved : null;
|
|
235
|
-
}
|
|
236
|
-
const moduleDir = path2.dirname((0, import_url.fileURLToPath)(import_meta.url));
|
|
237
|
-
const candidates = [
|
|
238
|
-
path2.resolve(moduleDir, "../templates"),
|
|
239
|
-
path2.resolve(moduleDir, "../../templates")
|
|
240
|
-
];
|
|
241
|
-
for (const candidate of candidates) {
|
|
242
|
-
if (fs2.existsSync(candidate) && fs2.statSync(candidate).isDirectory()) {
|
|
243
|
-
return candidate;
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
return null;
|
|
247
|
-
}
|
|
248
|
-
function listTemplateFiles(dir, ignore) {
|
|
249
|
-
const entries = /* @__PURE__ */ new Map();
|
|
250
|
-
if (!fs2.existsSync(dir)) return entries;
|
|
251
|
-
for (const entry of fs2.readdirSync(dir, { withFileTypes: true })) {
|
|
252
|
-
if (!entry.isFile() || !entry.name.endsWith(TEMPLATE_EXTENSION)) continue;
|
|
253
|
-
const name = normalizeTemplateName(entry.name);
|
|
254
|
-
if (!name) continue;
|
|
255
|
-
if (ignore?.has(name)) continue;
|
|
256
|
-
entries.set(name, path2.join(dir, entry.name));
|
|
257
|
-
}
|
|
258
|
-
return entries;
|
|
259
|
-
}
|
|
260
|
-
function buildTemplateIndex(options = {}) {
|
|
261
|
-
const index = /* @__PURE__ */ new Map();
|
|
262
|
-
const builtinDir = resolveBuiltinTemplatesDir(options.builtinDir);
|
|
263
|
-
if (builtinDir) {
|
|
264
|
-
for (const [name, filePath] of listTemplateFiles(builtinDir, options.ignoreBuiltinNames)) {
|
|
265
|
-
index.set(name, filePath);
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
if (options.vaultPath) {
|
|
269
|
-
const vaultTemplatesDir = path2.join(path2.resolve(options.vaultPath), "templates");
|
|
270
|
-
for (const [name, filePath] of listTemplateFiles(vaultTemplatesDir)) {
|
|
271
|
-
index.set(name, filePath);
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
return index;
|
|
275
|
-
}
|
|
276
|
-
function inferFieldType(defaultValue) {
|
|
277
|
-
if (Array.isArray(defaultValue)) {
|
|
278
|
-
const uniqueItemTypes = [...new Set(defaultValue.map((value) => typeof value))];
|
|
279
|
-
if (uniqueItemTypes.length === 1 && uniqueItemTypes[0] === "string") {
|
|
280
|
-
return "string[]";
|
|
281
|
-
}
|
|
282
|
-
return "array";
|
|
283
|
-
}
|
|
284
|
-
switch (typeof defaultValue) {
|
|
285
|
-
case "string":
|
|
286
|
-
return "string";
|
|
287
|
-
case "number":
|
|
288
|
-
return "number";
|
|
289
|
-
case "boolean":
|
|
290
|
-
return "boolean";
|
|
291
|
-
case "object":
|
|
292
|
-
if (defaultValue === null) return "string";
|
|
293
|
-
return "object";
|
|
294
|
-
default:
|
|
295
|
-
return "string";
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
function normalizeFieldDefinition(rawField) {
|
|
299
|
-
if (!isRecord(rawField)) {
|
|
300
|
-
return {
|
|
301
|
-
type: inferFieldType(rawField),
|
|
302
|
-
default: rawField
|
|
303
|
-
};
|
|
304
|
-
}
|
|
305
|
-
const rawType = typeof rawField.type === "string" ? rawField.type.trim() : "";
|
|
306
|
-
const normalized = {
|
|
307
|
-
type: rawType || inferFieldType(rawField.default)
|
|
308
|
-
};
|
|
309
|
-
if (typeof rawField.description === "string" && rawField.description.trim()) {
|
|
310
|
-
normalized.description = rawField.description.trim();
|
|
311
|
-
}
|
|
312
|
-
if (typeof rawField.required === "boolean") {
|
|
313
|
-
normalized.required = rawField.required;
|
|
314
|
-
}
|
|
315
|
-
if (Object.prototype.hasOwnProperty.call(rawField, "default")) {
|
|
316
|
-
normalized.default = rawField.default;
|
|
317
|
-
}
|
|
318
|
-
if (Array.isArray(rawField.enum)) {
|
|
319
|
-
normalized.enum = rawField.enum;
|
|
320
|
-
}
|
|
321
|
-
return normalized;
|
|
322
|
-
}
|
|
323
|
-
function normalizeFieldDefinitions(rawFields) {
|
|
324
|
-
const normalized = {};
|
|
325
|
-
for (const [fieldName, rawField] of Object.entries(rawFields)) {
|
|
326
|
-
const normalizedName = String(fieldName).trim();
|
|
327
|
-
if (!normalizedName) continue;
|
|
328
|
-
normalized[normalizedName] = normalizeFieldDefinition(rawField);
|
|
329
|
-
}
|
|
330
|
-
return normalized;
|
|
331
|
-
}
|
|
332
|
-
function extractSchemaDefinition(frontmatter) {
|
|
333
|
-
const primitive = typeof frontmatter.primitive === "string" ? frontmatter.primitive.trim() : "";
|
|
334
|
-
const description = typeof frontmatter.description === "string" ? frontmatter.description.trim() : void 0;
|
|
335
|
-
if (primitive && isRecord(frontmatter.fields)) {
|
|
336
|
-
return {
|
|
337
|
-
primitive,
|
|
338
|
-
description,
|
|
339
|
-
fields: frontmatter.fields
|
|
340
|
-
};
|
|
341
|
-
}
|
|
342
|
-
const containerCandidates = [frontmatter.schema, frontmatter.template];
|
|
343
|
-
for (const candidate of containerCandidates) {
|
|
344
|
-
if (!isRecord(candidate)) continue;
|
|
345
|
-
const nestedPrimitive = typeof candidate.primitive === "string" ? candidate.primitive.trim() : primitive;
|
|
346
|
-
if (!nestedPrimitive || !isRecord(candidate.fields)) continue;
|
|
347
|
-
const nestedDescription = typeof candidate.description === "string" ? candidate.description.trim() : description;
|
|
348
|
-
return {
|
|
349
|
-
primitive: nestedPrimitive,
|
|
350
|
-
description: nestedDescription,
|
|
351
|
-
fields: candidate.fields
|
|
352
|
-
};
|
|
353
|
-
}
|
|
354
|
-
return null;
|
|
355
|
-
}
|
|
356
|
-
function inferLegacyFieldDefinitions(frontmatter) {
|
|
357
|
-
const normalized = {};
|
|
358
|
-
const ignoredKeys = /* @__PURE__ */ new Set(["primitive", "fields", "schema", "template"]);
|
|
359
|
-
for (const [key, value] of Object.entries(frontmatter)) {
|
|
360
|
-
if (ignoredKeys.has(key)) continue;
|
|
361
|
-
normalized[key] = {
|
|
362
|
-
type: inferFieldType(value),
|
|
363
|
-
default: value
|
|
364
|
-
};
|
|
365
|
-
}
|
|
366
|
-
return normalized;
|
|
367
|
-
}
|
|
368
|
-
function parseTemplateDefinition(rawTemplate, templateName, sourcePath) {
|
|
369
|
-
const normalizedName = normalizeTemplateName(templateName);
|
|
370
|
-
const { data, content } = (0, import_gray_matter.default)(rawTemplate);
|
|
371
|
-
const frontmatter = isRecord(data) ? data : {};
|
|
372
|
-
const extractedSchema = extractSchemaDefinition(frontmatter);
|
|
373
|
-
if (extractedSchema) {
|
|
374
|
-
return {
|
|
375
|
-
name: normalizedName,
|
|
376
|
-
primitive: extractedSchema.primitive,
|
|
377
|
-
description: extractedSchema.description,
|
|
378
|
-
fields: normalizeFieldDefinitions(extractedSchema.fields),
|
|
379
|
-
body: content,
|
|
380
|
-
format: "schema",
|
|
381
|
-
sourcePath
|
|
382
|
-
};
|
|
383
|
-
}
|
|
384
|
-
return {
|
|
385
|
-
name: normalizedName,
|
|
386
|
-
primitive: normalizedName,
|
|
387
|
-
description: typeof frontmatter.description === "string" ? frontmatter.description.trim() : void 0,
|
|
388
|
-
fields: inferLegacyFieldDefinitions(frontmatter),
|
|
389
|
-
body: content,
|
|
390
|
-
format: "legacy",
|
|
391
|
-
sourcePath
|
|
392
|
-
};
|
|
393
|
-
}
|
|
394
|
-
function readTemplateDefinitionFromPath(filePath, templateName) {
|
|
395
|
-
try {
|
|
396
|
-
const raw = fs2.readFileSync(filePath, "utf-8");
|
|
397
|
-
return parseTemplateDefinition(raw, templateName, filePath);
|
|
398
|
-
} catch {
|
|
399
|
-
return null;
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
function loadTemplateDefinition(templateName, options = {}) {
|
|
403
|
-
const normalizedName = normalizeTemplateName(templateName);
|
|
404
|
-
if (!normalizedName) return null;
|
|
405
|
-
const index = buildTemplateIndex(options);
|
|
406
|
-
const filePath = index.get(normalizedName);
|
|
407
|
-
if (!filePath) return null;
|
|
408
|
-
return readTemplateDefinitionFromPath(filePath, normalizedName);
|
|
409
|
-
}
|
|
410
|
-
function loadSchemaTemplateDefinition(templateName, options = {}) {
|
|
411
|
-
const definition = loadTemplateDefinition(templateName, options);
|
|
412
|
-
if (!definition || definition.format !== "schema") {
|
|
413
|
-
return null;
|
|
414
|
-
}
|
|
415
|
-
return definition;
|
|
416
|
-
}
|
|
417
|
-
function resolveInterpolatedValue(value, variables) {
|
|
418
|
-
if (typeof value === "string") {
|
|
419
|
-
return renderTemplate(value, variables);
|
|
420
|
-
}
|
|
421
|
-
if (Array.isArray(value)) {
|
|
422
|
-
return value.map((item) => resolveInterpolatedValue(item, variables));
|
|
423
|
-
}
|
|
424
|
-
if (isRecord(value)) {
|
|
425
|
-
const resolved = {};
|
|
426
|
-
for (const [key, nested] of Object.entries(value)) {
|
|
427
|
-
resolved[key] = resolveInterpolatedValue(nested, variables);
|
|
428
|
-
}
|
|
429
|
-
return resolved;
|
|
430
|
-
}
|
|
431
|
-
return value;
|
|
432
|
-
}
|
|
433
|
-
function pruneFrontmatter(frontmatter, options) {
|
|
434
|
-
const dropEmptyStrings = options.dropEmptyStrings ?? true;
|
|
435
|
-
const dropEmptyArrays = options.dropEmptyArrays ?? true;
|
|
436
|
-
const pruned = {};
|
|
437
|
-
for (const [key, value] of Object.entries(frontmatter)) {
|
|
438
|
-
if (value === void 0 || value === null) continue;
|
|
439
|
-
if (dropEmptyStrings && typeof value === "string" && value.trim() === "") continue;
|
|
440
|
-
if (dropEmptyArrays && Array.isArray(value) && value.length === 0) continue;
|
|
441
|
-
pruned[key] = value;
|
|
442
|
-
}
|
|
443
|
-
return pruned;
|
|
444
|
-
}
|
|
445
|
-
function buildFrontmatterFromTemplate(definition, variables, overrides = {}, options = {}) {
|
|
446
|
-
const frontmatter = {};
|
|
447
|
-
for (const [fieldName, schema] of Object.entries(definition.fields)) {
|
|
448
|
-
if (!Object.prototype.hasOwnProperty.call(schema, "default")) continue;
|
|
449
|
-
frontmatter[fieldName] = resolveInterpolatedValue(schema.default, variables);
|
|
450
|
-
}
|
|
451
|
-
for (const [fieldName, value] of Object.entries(overrides)) {
|
|
452
|
-
if (value === void 0) continue;
|
|
453
|
-
if (value === null) {
|
|
454
|
-
delete frontmatter[fieldName];
|
|
455
|
-
continue;
|
|
456
|
-
}
|
|
457
|
-
frontmatter[fieldName] = value;
|
|
458
|
-
}
|
|
459
|
-
if (!options.pruneEmpty) {
|
|
460
|
-
return frontmatter;
|
|
461
|
-
}
|
|
462
|
-
return pruneFrontmatter(frontmatter, options);
|
|
463
|
-
}
|
|
464
|
-
function renderDocumentFromTemplate(definition, options = {}) {
|
|
465
|
-
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
466
|
-
const variables = {
|
|
467
|
-
...buildTemplateVariables(
|
|
468
|
-
{
|
|
469
|
-
title: options.title ?? "",
|
|
470
|
-
type: options.type ?? definition.primitive
|
|
471
|
-
},
|
|
472
|
-
now
|
|
473
|
-
),
|
|
474
|
-
...options.variables ?? {}
|
|
475
|
-
};
|
|
476
|
-
const frontmatter = buildFrontmatterFromTemplate(
|
|
477
|
-
definition,
|
|
478
|
-
variables,
|
|
479
|
-
options.overrides,
|
|
480
|
-
options.frontmatter
|
|
481
|
-
);
|
|
482
|
-
const content = renderTemplate(definition.body, variables);
|
|
483
|
-
const markdown = import_gray_matter.default.stringify(content, frontmatter);
|
|
484
|
-
return {
|
|
485
|
-
frontmatter,
|
|
486
|
-
content,
|
|
487
|
-
markdown,
|
|
488
|
-
variables
|
|
489
|
-
};
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
// src/lib/task-utils.ts
|
|
493
|
-
function slugify(text) {
|
|
494
|
-
return text.toLowerCase().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "").trim();
|
|
495
|
-
}
|
|
496
|
-
function getTasksDir(vaultPath) {
|
|
497
|
-
return path3.join(path3.resolve(vaultPath), "tasks");
|
|
498
|
-
}
|
|
499
|
-
function ensureTasksDir(vaultPath) {
|
|
500
|
-
const tasksDir = getTasksDir(vaultPath);
|
|
501
|
-
if (!fs3.existsSync(tasksDir)) {
|
|
502
|
-
fs3.mkdirSync(tasksDir, { recursive: true });
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
function getTaskPath(vaultPath, slug) {
|
|
506
|
-
return path3.join(getTasksDir(vaultPath), `${slug}.md`);
|
|
507
|
-
}
|
|
508
|
-
function extractTitle(content) {
|
|
509
|
-
const match = content.match(/^#\s+(.+)$/m);
|
|
510
|
-
return match ? match[1].trim() : "";
|
|
511
|
-
}
|
|
512
|
-
function parseDueDate(value) {
|
|
513
|
-
if (!value) return null;
|
|
514
|
-
const timestamp = Date.parse(value);
|
|
515
|
-
if (Number.isNaN(timestamp)) return null;
|
|
516
|
-
return timestamp;
|
|
517
|
-
}
|
|
518
|
-
function startOfToday() {
|
|
519
|
-
const now = /* @__PURE__ */ new Date();
|
|
520
|
-
return new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();
|
|
521
|
-
}
|
|
522
|
-
function buildTaskFrontmatterFallback(now, options) {
|
|
523
|
-
const frontmatter = {
|
|
524
|
-
status: "open",
|
|
525
|
-
created: now,
|
|
526
|
-
updated: now
|
|
527
|
-
};
|
|
528
|
-
if (options.source) frontmatter.source = options.source;
|
|
529
|
-
if (options.owner) frontmatter.owner = options.owner;
|
|
530
|
-
if (options.project) frontmatter.project = options.project;
|
|
531
|
-
if (options.priority) frontmatter.priority = options.priority;
|
|
532
|
-
if (options.due) frontmatter.due = options.due;
|
|
533
|
-
if (options.tags && options.tags.length > 0) frontmatter.tags = options.tags;
|
|
534
|
-
if (options.description) frontmatter.description = options.description;
|
|
535
|
-
if (options.estimate) frontmatter.estimate = options.estimate;
|
|
536
|
-
if (options.parent) frontmatter.parent = options.parent;
|
|
537
|
-
if (options.depends_on && options.depends_on.length > 0) frontmatter.depends_on = options.depends_on;
|
|
538
|
-
return frontmatter;
|
|
539
|
-
}
|
|
540
|
-
function buildTaskContentFallback(title, options) {
|
|
541
|
-
let content = `# ${title}
|
|
542
|
-
`;
|
|
543
|
-
const links = [];
|
|
544
|
-
if (options.owner) links.push(`[[${options.owner}]]`);
|
|
545
|
-
if (options.project) links.push(`[[${options.project}]]`);
|
|
546
|
-
if (links.length > 0) {
|
|
547
|
-
content += `
|
|
548
|
-
${links.join(" | ")}
|
|
549
|
-
`;
|
|
550
|
-
}
|
|
551
|
-
if (options.content) {
|
|
552
|
-
content += `
|
|
553
|
-
${options.content}
|
|
554
|
-
`;
|
|
555
|
-
}
|
|
556
|
-
return content;
|
|
557
|
-
}
|
|
558
|
-
function buildTaskTemplateOverrides(options) {
|
|
559
|
-
const overrides = {};
|
|
560
|
-
if (options.source) overrides.source = options.source;
|
|
561
|
-
if (options.owner) overrides.owner = options.owner;
|
|
562
|
-
if (options.project) overrides.project = options.project;
|
|
563
|
-
if (options.priority) overrides.priority = options.priority;
|
|
564
|
-
if (options.due) overrides.due = options.due;
|
|
565
|
-
if (options.tags && options.tags.length > 0) overrides.tags = options.tags;
|
|
566
|
-
if (options.description) overrides.description = options.description;
|
|
567
|
-
if (options.estimate) overrides.estimate = options.estimate;
|
|
568
|
-
if (options.parent) overrides.parent = options.parent;
|
|
569
|
-
if (options.depends_on && options.depends_on.length > 0) overrides.depends_on = options.depends_on;
|
|
570
|
-
return overrides;
|
|
571
|
-
}
|
|
572
|
-
function buildTaskTemplateVariables(title, slug, options) {
|
|
573
|
-
const ownerLink = options.owner ? `[[${options.owner}]]` : "";
|
|
574
|
-
const projectLink = options.project ? `[[${options.project}]]` : "";
|
|
575
|
-
const linksLine = [ownerLink, projectLink].filter(Boolean).join(" | ");
|
|
576
|
-
return {
|
|
577
|
-
title,
|
|
578
|
-
slug,
|
|
579
|
-
source: options.source ?? "",
|
|
580
|
-
owner: options.owner ?? "",
|
|
581
|
-
project: options.project ?? "",
|
|
582
|
-
priority: options.priority ?? "",
|
|
583
|
-
due: options.due ?? "",
|
|
584
|
-
tags_csv: (options.tags || []).join(", "),
|
|
585
|
-
description: options.description ?? "",
|
|
586
|
-
estimate: options.estimate ?? "",
|
|
587
|
-
parent: options.parent ?? "",
|
|
588
|
-
depends_on_csv: (options.depends_on || []).join(", "),
|
|
589
|
-
content: options.content ?? "",
|
|
590
|
-
owner_link: ownerLink,
|
|
591
|
-
project_link: projectLink,
|
|
592
|
-
links_line: linksLine
|
|
593
|
-
};
|
|
594
|
-
}
|
|
595
|
-
var VALID_TASK_STATUSES = /* @__PURE__ */ new Set([
|
|
596
|
-
"open",
|
|
597
|
-
"in-progress",
|
|
598
|
-
"blocked",
|
|
599
|
-
"done"
|
|
600
|
-
]);
|
|
601
|
-
function isTaskStatus(value) {
|
|
602
|
-
return typeof value === "string" && VALID_TASK_STATUSES.has(value);
|
|
603
|
-
}
|
|
604
|
-
function persistTaskFrontmatter(task, frontmatter) {
|
|
605
|
-
fs3.writeFileSync(task.path, import_gray_matter2.default.stringify(task.content, frontmatter));
|
|
606
|
-
}
|
|
607
|
-
function resolveStatusTransition(previousStatus, nextStatus) {
|
|
608
|
-
if (!isTaskStatus(previousStatus) || !isTaskStatus(nextStatus)) {
|
|
609
|
-
return null;
|
|
610
|
-
}
|
|
611
|
-
if (previousStatus === nextStatus) {
|
|
612
|
-
return null;
|
|
613
|
-
}
|
|
614
|
-
return { fromStatus: previousStatus, toStatus: nextStatus };
|
|
615
|
-
}
|
|
616
|
-
function logStatusTransition({
|
|
617
|
-
vaultPath,
|
|
618
|
-
task,
|
|
619
|
-
fromStatus,
|
|
620
|
-
toStatus,
|
|
621
|
-
frontmatter,
|
|
622
|
-
options
|
|
623
|
-
}) {
|
|
624
|
-
const normalizedReason = typeof options.reason === "string" ? options.reason.trim() : "";
|
|
625
|
-
const reason = normalizedReason || (isRegression(fromStatus, toStatus) ? `regression: ${fromStatus} -> ${toStatus}` : void 0);
|
|
626
|
-
const event = buildTransitionEvent(task.slug, fromStatus, toStatus, {
|
|
627
|
-
confidence: options.confidence,
|
|
628
|
-
reason
|
|
629
|
-
});
|
|
630
|
-
try {
|
|
631
|
-
appendTransition(vaultPath, event);
|
|
632
|
-
} catch {
|
|
633
|
-
return frontmatter;
|
|
634
|
-
}
|
|
635
|
-
if (toStatus !== "blocked" || frontmatter.escalation) {
|
|
636
|
-
return frontmatter;
|
|
637
|
-
}
|
|
638
|
-
let blockedCount = 0;
|
|
639
|
-
try {
|
|
640
|
-
blockedCount = countBlockedTransitions(vaultPath, task.slug);
|
|
641
|
-
} catch {
|
|
642
|
-
return frontmatter;
|
|
643
|
-
}
|
|
644
|
-
if (blockedCount < 3) {
|
|
645
|
-
return frontmatter;
|
|
646
|
-
}
|
|
647
|
-
const escalatedFrontmatter = {
|
|
648
|
-
...frontmatter,
|
|
649
|
-
escalation: true
|
|
650
|
-
};
|
|
651
|
-
try {
|
|
652
|
-
persistTaskFrontmatter(task, escalatedFrontmatter);
|
|
653
|
-
return escalatedFrontmatter;
|
|
654
|
-
} catch {
|
|
655
|
-
return frontmatter;
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
function readTask(vaultPath, slug) {
|
|
659
|
-
const taskPath = getTaskPath(vaultPath, slug);
|
|
660
|
-
if (!fs3.existsSync(taskPath)) {
|
|
661
|
-
return null;
|
|
662
|
-
}
|
|
663
|
-
try {
|
|
664
|
-
const raw = fs3.readFileSync(taskPath, "utf-8");
|
|
665
|
-
const { data, content } = (0, import_gray_matter2.default)(raw);
|
|
666
|
-
const title = extractTitle(content) || slug;
|
|
667
|
-
return {
|
|
668
|
-
slug,
|
|
669
|
-
title,
|
|
670
|
-
content,
|
|
671
|
-
frontmatter: data,
|
|
672
|
-
path: taskPath
|
|
673
|
-
};
|
|
674
|
-
} catch {
|
|
675
|
-
return null;
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
function listTasks(vaultPath, filters) {
|
|
679
|
-
const tasksDir = getTasksDir(vaultPath);
|
|
680
|
-
if (!fs3.existsSync(tasksDir)) {
|
|
681
|
-
return [];
|
|
682
|
-
}
|
|
683
|
-
const tasks = [];
|
|
684
|
-
const entries = fs3.readdirSync(tasksDir, { withFileTypes: true });
|
|
685
|
-
const today = startOfToday();
|
|
686
|
-
for (const entry of entries) {
|
|
687
|
-
if (!entry.isFile() || !entry.name.endsWith(".md")) {
|
|
688
|
-
continue;
|
|
689
|
-
}
|
|
690
|
-
const slug = entry.name.replace(/\.md$/, "");
|
|
691
|
-
const task = readTask(vaultPath, slug);
|
|
692
|
-
if (!task) continue;
|
|
693
|
-
if (filters) {
|
|
694
|
-
if (filters.status && task.frontmatter.status !== filters.status) continue;
|
|
695
|
-
if (filters.owner && task.frontmatter.owner !== filters.owner) continue;
|
|
696
|
-
if (filters.project && task.frontmatter.project !== filters.project) continue;
|
|
697
|
-
if (filters.priority && task.frontmatter.priority !== filters.priority) continue;
|
|
698
|
-
if (filters.due && !task.frontmatter.due) continue;
|
|
699
|
-
if (filters.tag) {
|
|
700
|
-
const tags = task.frontmatter.tags || [];
|
|
701
|
-
const hasTag = tags.some((tag) => tag.toLowerCase() === filters.tag?.toLowerCase());
|
|
702
|
-
if (!hasTag) continue;
|
|
703
|
-
}
|
|
704
|
-
if (filters.overdue) {
|
|
705
|
-
const dueTime = parseDueDate(task.frontmatter.due);
|
|
706
|
-
if (task.frontmatter.status === "done" || dueTime === null || dueTime >= today) continue;
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
tasks.push(task);
|
|
710
|
-
}
|
|
711
|
-
const priorityOrder = {
|
|
712
|
-
critical: 0,
|
|
713
|
-
high: 1,
|
|
714
|
-
medium: 2,
|
|
715
|
-
low: 3
|
|
716
|
-
};
|
|
717
|
-
if (filters?.due || filters?.overdue) {
|
|
718
|
-
return tasks.sort((a, b) => {
|
|
719
|
-
const aDue = parseDueDate(a.frontmatter.due);
|
|
720
|
-
const bDue = parseDueDate(b.frontmatter.due);
|
|
721
|
-
if (aDue !== null && bDue !== null && aDue !== bDue) {
|
|
722
|
-
return aDue - bDue;
|
|
723
|
-
}
|
|
724
|
-
if (aDue !== null && bDue === null) return -1;
|
|
725
|
-
if (aDue === null && bDue !== null) return 1;
|
|
726
|
-
return new Date(b.frontmatter.created).getTime() - new Date(a.frontmatter.created).getTime();
|
|
727
|
-
});
|
|
728
|
-
}
|
|
729
|
-
return tasks.sort((a, b) => {
|
|
730
|
-
const aPriority = priorityOrder[a.frontmatter.priority || "low"];
|
|
731
|
-
const bPriority = priorityOrder[b.frontmatter.priority || "low"];
|
|
732
|
-
if (aPriority !== bPriority) {
|
|
733
|
-
return aPriority - bPriority;
|
|
734
|
-
}
|
|
735
|
-
return new Date(b.frontmatter.created).getTime() - new Date(a.frontmatter.created).getTime();
|
|
736
|
-
});
|
|
737
|
-
}
|
|
738
|
-
function createTask(vaultPath, title, options = {}) {
|
|
739
|
-
ensureTasksDir(vaultPath);
|
|
740
|
-
const slug = slugify(title);
|
|
741
|
-
const taskPath = getTaskPath(vaultPath, slug);
|
|
742
|
-
if (fs3.existsSync(taskPath)) {
|
|
743
|
-
throw new Error(`Task already exists: ${slug}`);
|
|
744
|
-
}
|
|
745
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
746
|
-
const template = loadSchemaTemplateDefinition("task", {
|
|
747
|
-
vaultPath: path3.resolve(vaultPath)
|
|
748
|
-
});
|
|
749
|
-
let frontmatter;
|
|
750
|
-
let content;
|
|
751
|
-
if (template) {
|
|
752
|
-
const rendered = renderDocumentFromTemplate(template, {
|
|
753
|
-
title,
|
|
754
|
-
type: "task",
|
|
755
|
-
now: new Date(now),
|
|
756
|
-
variables: buildTaskTemplateVariables(title, slug, options),
|
|
757
|
-
overrides: buildTaskTemplateOverrides(options),
|
|
758
|
-
frontmatter: { pruneEmpty: true }
|
|
759
|
-
});
|
|
760
|
-
const templateFrontmatter = rendered.frontmatter;
|
|
761
|
-
frontmatter = {
|
|
762
|
-
...templateFrontmatter,
|
|
763
|
-
status: isTaskStatus(templateFrontmatter.status) ? templateFrontmatter.status : "open",
|
|
764
|
-
created: typeof templateFrontmatter.created === "string" && templateFrontmatter.created ? templateFrontmatter.created : now,
|
|
765
|
-
updated: typeof templateFrontmatter.updated === "string" && templateFrontmatter.updated ? templateFrontmatter.updated : now
|
|
766
|
-
};
|
|
767
|
-
content = rendered.content;
|
|
768
|
-
} else {
|
|
769
|
-
frontmatter = buildTaskFrontmatterFallback(now, options);
|
|
770
|
-
content = buildTaskContentFallback(title, options);
|
|
771
|
-
}
|
|
772
|
-
const fileContent = import_gray_matter2.default.stringify(content, frontmatter);
|
|
773
|
-
fs3.writeFileSync(taskPath, fileContent);
|
|
774
|
-
return {
|
|
775
|
-
slug,
|
|
776
|
-
title,
|
|
777
|
-
content,
|
|
778
|
-
frontmatter,
|
|
779
|
-
path: taskPath
|
|
780
|
-
};
|
|
781
|
-
}
|
|
782
|
-
function updateTask(vaultPath, slug, updates, options = {}) {
|
|
783
|
-
const task = readTask(vaultPath, slug);
|
|
784
|
-
if (!task) {
|
|
785
|
-
throw new Error(`Task not found: ${slug}`);
|
|
786
|
-
}
|
|
787
|
-
if (updates.status !== void 0 && !isTaskStatus(updates.status)) {
|
|
788
|
-
throw new Error(`Invalid task status: ${String(updates.status)}`);
|
|
789
|
-
}
|
|
790
|
-
const previousStatus = task.frontmatter.status;
|
|
791
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
792
|
-
let newFrontmatter = {
|
|
793
|
-
...task.frontmatter,
|
|
794
|
-
updated: now
|
|
795
|
-
};
|
|
796
|
-
if (updates.status !== void 0) {
|
|
797
|
-
newFrontmatter.status = updates.status;
|
|
798
|
-
if (updates.status === "done" && !newFrontmatter.completed) {
|
|
799
|
-
newFrontmatter.completed = now;
|
|
800
|
-
}
|
|
801
|
-
if (updates.status !== "done") {
|
|
802
|
-
delete newFrontmatter.completed;
|
|
803
|
-
}
|
|
804
|
-
}
|
|
805
|
-
if (updates.source !== void 0) {
|
|
806
|
-
if (updates.source === null || updates.source.trim() === "") {
|
|
807
|
-
delete newFrontmatter.source;
|
|
808
|
-
} else {
|
|
809
|
-
newFrontmatter.source = updates.source;
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
|
-
if (updates.owner !== void 0) {
|
|
813
|
-
if (updates.owner === null || updates.owner.trim() === "") {
|
|
814
|
-
delete newFrontmatter.owner;
|
|
815
|
-
} else {
|
|
816
|
-
newFrontmatter.owner = updates.owner;
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
if (updates.project !== void 0) {
|
|
820
|
-
if (updates.project === null || updates.project.trim() === "") {
|
|
821
|
-
delete newFrontmatter.project;
|
|
822
|
-
} else {
|
|
823
|
-
newFrontmatter.project = updates.project;
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
if (updates.priority !== void 0) {
|
|
827
|
-
if (updates.priority === null) {
|
|
828
|
-
delete newFrontmatter.priority;
|
|
829
|
-
} else {
|
|
830
|
-
newFrontmatter.priority = updates.priority;
|
|
831
|
-
}
|
|
832
|
-
}
|
|
833
|
-
if (updates.due !== void 0) {
|
|
834
|
-
if (updates.due === null || updates.due.trim() === "") {
|
|
835
|
-
delete newFrontmatter.due;
|
|
836
|
-
} else {
|
|
837
|
-
newFrontmatter.due = updates.due;
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
|
-
if (updates.tags !== void 0) {
|
|
841
|
-
if (updates.tags === null) {
|
|
842
|
-
delete newFrontmatter.tags;
|
|
843
|
-
} else {
|
|
844
|
-
const normalizedTags = updates.tags.map((tag) => tag.trim()).filter(Boolean);
|
|
845
|
-
if (normalizedTags.length === 0) {
|
|
846
|
-
delete newFrontmatter.tags;
|
|
847
|
-
} else {
|
|
848
|
-
newFrontmatter.tags = normalizedTags;
|
|
849
|
-
}
|
|
850
|
-
}
|
|
851
|
-
}
|
|
852
|
-
if (updates.completed !== void 0) {
|
|
853
|
-
if (updates.completed === null || updates.completed.trim() === "") {
|
|
854
|
-
delete newFrontmatter.completed;
|
|
855
|
-
} else {
|
|
856
|
-
newFrontmatter.completed = updates.completed;
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
if (updates.escalation !== void 0) {
|
|
860
|
-
if (updates.escalation === null) {
|
|
861
|
-
delete newFrontmatter.escalation;
|
|
862
|
-
} else {
|
|
863
|
-
newFrontmatter.escalation = updates.escalation;
|
|
864
|
-
}
|
|
865
|
-
}
|
|
866
|
-
if (updates.confidence !== void 0) {
|
|
867
|
-
if (updates.confidence === null) {
|
|
868
|
-
delete newFrontmatter.confidence;
|
|
869
|
-
} else {
|
|
870
|
-
newFrontmatter.confidence = updates.confidence;
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
if (updates.reason !== void 0) {
|
|
874
|
-
if (updates.reason === null || updates.reason.trim() === "") {
|
|
875
|
-
delete newFrontmatter.reason;
|
|
876
|
-
} else {
|
|
877
|
-
newFrontmatter.reason = updates.reason;
|
|
878
|
-
}
|
|
879
|
-
}
|
|
880
|
-
if (updates.description !== void 0) {
|
|
881
|
-
if (updates.description === null || updates.description.trim() === "") {
|
|
882
|
-
delete newFrontmatter.description;
|
|
883
|
-
} else {
|
|
884
|
-
newFrontmatter.description = updates.description;
|
|
885
|
-
}
|
|
886
|
-
}
|
|
887
|
-
if (updates.estimate !== void 0) {
|
|
888
|
-
if (updates.estimate === null || updates.estimate.trim() === "") {
|
|
889
|
-
delete newFrontmatter.estimate;
|
|
890
|
-
} else {
|
|
891
|
-
newFrontmatter.estimate = updates.estimate;
|
|
892
|
-
}
|
|
893
|
-
}
|
|
894
|
-
if (updates.parent !== void 0) {
|
|
895
|
-
if (updates.parent === null || updates.parent.trim() === "") {
|
|
896
|
-
delete newFrontmatter.parent;
|
|
897
|
-
} else {
|
|
898
|
-
newFrontmatter.parent = updates.parent;
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
if (updates.depends_on !== void 0) {
|
|
902
|
-
if (updates.depends_on === null) {
|
|
903
|
-
delete newFrontmatter.depends_on;
|
|
904
|
-
} else {
|
|
905
|
-
const normalizedDeps = updates.depends_on.map((dep) => dep.trim()).filter(Boolean);
|
|
906
|
-
if (normalizedDeps.length === 0) {
|
|
907
|
-
delete newFrontmatter.depends_on;
|
|
908
|
-
} else {
|
|
909
|
-
newFrontmatter.depends_on = normalizedDeps;
|
|
910
|
-
}
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
if (updates.blocked_by !== void 0) {
|
|
914
|
-
if (updates.blocked_by === null || updates.blocked_by.trim() === "") {
|
|
915
|
-
delete newFrontmatter.blocked_by;
|
|
916
|
-
} else {
|
|
917
|
-
newFrontmatter.blocked_by = updates.blocked_by;
|
|
918
|
-
}
|
|
919
|
-
} else if (updates.status !== void 0 && updates.status !== "blocked") {
|
|
920
|
-
delete newFrontmatter.blocked_by;
|
|
921
|
-
}
|
|
922
|
-
persistTaskFrontmatter(task, newFrontmatter);
|
|
923
|
-
const transition = options.skipTransition ? null : resolveStatusTransition(previousStatus, newFrontmatter.status);
|
|
924
|
-
if (transition) {
|
|
925
|
-
const confidence = options.confidence ?? (typeof updates.confidence === "number" ? updates.confidence : void 0);
|
|
926
|
-
const reason = options.reason ?? updates.reason ?? null;
|
|
927
|
-
newFrontmatter = logStatusTransition({
|
|
928
|
-
vaultPath,
|
|
929
|
-
task,
|
|
930
|
-
fromStatus: transition.fromStatus,
|
|
931
|
-
toStatus: transition.toStatus,
|
|
932
|
-
frontmatter: newFrontmatter,
|
|
933
|
-
options: {
|
|
934
|
-
confidence,
|
|
935
|
-
reason
|
|
936
|
-
}
|
|
937
|
-
});
|
|
938
|
-
}
|
|
939
|
-
return {
|
|
940
|
-
...task,
|
|
941
|
-
frontmatter: newFrontmatter
|
|
942
|
-
};
|
|
943
|
-
}
|
|
944
|
-
function completeTask(vaultPath, slug, options = {}) {
|
|
945
|
-
return updateTask(vaultPath, slug, { status: "done" }, options);
|
|
946
|
-
}
|
|
947
|
-
function getStatusIcon(status) {
|
|
948
|
-
switch (status) {
|
|
949
|
-
case "in-progress":
|
|
950
|
-
return "\u25CF";
|
|
951
|
-
case "blocked":
|
|
952
|
-
return "\u25A0";
|
|
953
|
-
case "open":
|
|
954
|
-
return "\u25CB";
|
|
955
|
-
case "done":
|
|
956
|
-
return "\u2713";
|
|
957
|
-
default:
|
|
958
|
-
return "\u25CB";
|
|
959
|
-
}
|
|
960
|
-
}
|
|
961
|
-
function getStatusDisplay(status) {
|
|
962
|
-
switch (status) {
|
|
963
|
-
case "in-progress":
|
|
964
|
-
return "active";
|
|
965
|
-
case "blocked":
|
|
966
|
-
return "blocked";
|
|
967
|
-
case "open":
|
|
968
|
-
return "open";
|
|
969
|
-
case "done":
|
|
970
|
-
return "done";
|
|
971
|
-
default:
|
|
972
|
-
return status;
|
|
973
|
-
}
|
|
974
|
-
}
|
|
975
|
-
|
|
976
|
-
// src/commands/task.ts
|
|
977
|
-
function taskAdd(vaultPath, title, options = {}) {
|
|
978
|
-
return createTask(vaultPath, title, {
|
|
979
|
-
owner: options.owner,
|
|
980
|
-
project: options.project,
|
|
981
|
-
priority: options.priority,
|
|
982
|
-
due: options.due,
|
|
983
|
-
content: options.content,
|
|
984
|
-
tags: options.tags,
|
|
985
|
-
description: options.description,
|
|
986
|
-
estimate: options.estimate,
|
|
987
|
-
parent: options.parent,
|
|
988
|
-
depends_on: options.dependsOn
|
|
989
|
-
});
|
|
990
|
-
}
|
|
991
|
-
function taskList(vaultPath, options = {}) {
|
|
992
|
-
const filters = {};
|
|
993
|
-
if (options.status) filters.status = options.status;
|
|
994
|
-
if (options.owner) filters.owner = options.owner;
|
|
995
|
-
if (options.project) filters.project = options.project;
|
|
996
|
-
if (options.priority) filters.priority = options.priority;
|
|
997
|
-
if (options.due) filters.due = true;
|
|
998
|
-
if (options.tag) filters.tag = options.tag;
|
|
999
|
-
if (options.overdue) filters.overdue = true;
|
|
1000
|
-
const listed = listTasks(vaultPath, filters);
|
|
1001
|
-
if (!options.status && !options.overdue) {
|
|
1002
|
-
return listed.filter((t) => t.frontmatter.status !== "done");
|
|
1003
|
-
}
|
|
1004
|
-
return listed;
|
|
1005
|
-
}
|
|
1006
|
-
function taskUpdate(vaultPath, slug, options) {
|
|
1007
|
-
return updateTask(vaultPath, slug, {
|
|
1008
|
-
status: options.status,
|
|
1009
|
-
owner: options.owner,
|
|
1010
|
-
project: options.project,
|
|
1011
|
-
priority: options.priority,
|
|
1012
|
-
blocked_by: options.blockedBy,
|
|
1013
|
-
due: options.due,
|
|
1014
|
-
tags: options.tags,
|
|
1015
|
-
description: options.description,
|
|
1016
|
-
estimate: options.estimate,
|
|
1017
|
-
parent: options.parent,
|
|
1018
|
-
depends_on: options.dependsOn,
|
|
1019
|
-
confidence: options.confidence,
|
|
1020
|
-
reason: options.reason
|
|
1021
|
-
});
|
|
1022
|
-
}
|
|
1023
|
-
function taskDone(vaultPath, slug, options = {}) {
|
|
1024
|
-
return completeTask(vaultPath, slug, {
|
|
1025
|
-
confidence: options.confidence,
|
|
1026
|
-
reason: options.reason ?? void 0
|
|
1027
|
-
});
|
|
1028
|
-
}
|
|
1029
|
-
function taskTransitions(vaultPath, taskId, options = {}) {
|
|
1030
|
-
const events = queryTransitions(vaultPath, {
|
|
1031
|
-
taskId,
|
|
1032
|
-
agent: options.agent,
|
|
1033
|
-
failed: options.failed
|
|
1034
|
-
});
|
|
1035
|
-
if (options.json) {
|
|
1036
|
-
return JSON.stringify(events, null, 2);
|
|
1037
|
-
}
|
|
1038
|
-
return formatTransitionsTable(events);
|
|
1039
|
-
}
|
|
1040
|
-
function taskShow(vaultPath, slug) {
|
|
1041
|
-
return readTask(vaultPath, slug);
|
|
1042
|
-
}
|
|
1043
|
-
function formatTaskList(tasks) {
|
|
1044
|
-
if (tasks.length === 0) {
|
|
1045
|
-
return "No tasks found.\n";
|
|
1046
|
-
}
|
|
1047
|
-
const headers = ["STATUS", "OWNER", "PRIORITY", "PROJECT", "META", "TITLE"];
|
|
1048
|
-
const widths = [10, 12, 8, 14, 64, 32];
|
|
1049
|
-
const truncate = (value, width) => {
|
|
1050
|
-
if (value.length <= width) return value;
|
|
1051
|
-
return value.slice(0, width - 3) + "...";
|
|
1052
|
-
};
|
|
1053
|
-
let output = headers.map((h, i) => h.padEnd(widths[i])).join(" ") + "\n";
|
|
1054
|
-
for (const task of tasks) {
|
|
1055
|
-
const icon = getStatusIcon(task.frontmatter.status);
|
|
1056
|
-
const statusDisplay = getStatusDisplay(task.frontmatter.status);
|
|
1057
|
-
const status = `${icon} ${statusDisplay}`;
|
|
1058
|
-
const owner = task.frontmatter.owner || "-";
|
|
1059
|
-
const priority = task.frontmatter.priority || "low";
|
|
1060
|
-
const project = task.frontmatter.project || "-";
|
|
1061
|
-
const metaParts = [];
|
|
1062
|
-
if (task.frontmatter.due) metaParts.push(`due:${task.frontmatter.due.split("T")[0]}`);
|
|
1063
|
-
if (task.frontmatter.tags?.length) metaParts.push(task.frontmatter.tags.map((tag) => `#${tag}`).join(","));
|
|
1064
|
-
if (task.frontmatter.parent) metaParts.push(`parent:${task.frontmatter.parent}`);
|
|
1065
|
-
if (task.frontmatter.depends_on?.length) {
|
|
1066
|
-
metaParts.push(`deps:${task.frontmatter.depends_on.join("|")}`);
|
|
1067
|
-
}
|
|
1068
|
-
const meta = metaParts.length > 0 ? metaParts.join(" ") : "-";
|
|
1069
|
-
const title = truncate(task.title, widths[5]);
|
|
1070
|
-
const row = [
|
|
1071
|
-
status.padEnd(widths[0]),
|
|
1072
|
-
owner.padEnd(widths[1]),
|
|
1073
|
-
priority.padEnd(widths[2]),
|
|
1074
|
-
project.padEnd(widths[3]),
|
|
1075
|
-
truncate(meta, widths[4]).padEnd(widths[4]),
|
|
1076
|
-
title
|
|
1077
|
-
];
|
|
1078
|
-
output += row.join(" ") + "\n";
|
|
1079
|
-
}
|
|
1080
|
-
return output;
|
|
1081
|
-
}
|
|
1082
|
-
function formatTaskDetails(task) {
|
|
1083
|
-
let output = "";
|
|
1084
|
-
output += `# ${task.title}
|
|
1085
|
-
`;
|
|
1086
|
-
output += "-".repeat(40) + "\n";
|
|
1087
|
-
output += `Status: ${getStatusIcon(task.frontmatter.status)} ${getStatusDisplay(task.frontmatter.status)}
|
|
1088
|
-
`;
|
|
1089
|
-
if (task.frontmatter.owner) {
|
|
1090
|
-
output += `Owner: ${task.frontmatter.owner}
|
|
1091
|
-
`;
|
|
1092
|
-
}
|
|
1093
|
-
if (task.frontmatter.project) {
|
|
1094
|
-
output += `Project: ${task.frontmatter.project}
|
|
1095
|
-
`;
|
|
1096
|
-
}
|
|
1097
|
-
if (task.frontmatter.priority) {
|
|
1098
|
-
output += `Priority: ${task.frontmatter.priority}
|
|
1099
|
-
`;
|
|
1100
|
-
}
|
|
1101
|
-
if (task.frontmatter.description) {
|
|
1102
|
-
output += `Description: ${task.frontmatter.description}
|
|
1103
|
-
`;
|
|
1104
|
-
}
|
|
1105
|
-
if (task.frontmatter.estimate) {
|
|
1106
|
-
output += `Estimate: ${task.frontmatter.estimate}
|
|
1107
|
-
`;
|
|
1108
|
-
}
|
|
1109
|
-
if (task.frontmatter.parent) {
|
|
1110
|
-
output += `Parent: ${task.frontmatter.parent}
|
|
1111
|
-
`;
|
|
1112
|
-
}
|
|
1113
|
-
if (task.frontmatter.depends_on && task.frontmatter.depends_on.length > 0) {
|
|
1114
|
-
output += `Depends on: ${task.frontmatter.depends_on.join(", ")}
|
|
1115
|
-
`;
|
|
1116
|
-
}
|
|
1117
|
-
if (task.frontmatter.due) {
|
|
1118
|
-
output += `Due: ${task.frontmatter.due}
|
|
1119
|
-
`;
|
|
1120
|
-
}
|
|
1121
|
-
if (task.frontmatter.blocked_by) {
|
|
1122
|
-
output += `Blocked by: ${task.frontmatter.blocked_by}
|
|
1123
|
-
`;
|
|
1124
|
-
}
|
|
1125
|
-
if (task.frontmatter.tags && task.frontmatter.tags.length > 0) {
|
|
1126
|
-
output += `Tags: ${task.frontmatter.tags.join(", ")}
|
|
1127
|
-
`;
|
|
1128
|
-
}
|
|
1129
|
-
if (task.frontmatter.escalation) {
|
|
1130
|
-
output += "Escalation: true\n";
|
|
1131
|
-
}
|
|
1132
|
-
if (task.frontmatter.confidence !== void 0) {
|
|
1133
|
-
output += `Confidence: ${task.frontmatter.confidence}
|
|
1134
|
-
`;
|
|
1135
|
-
}
|
|
1136
|
-
if (task.frontmatter.reason) {
|
|
1137
|
-
output += `Reason: ${task.frontmatter.reason}
|
|
1138
|
-
`;
|
|
1139
|
-
}
|
|
1140
|
-
output += `Created: ${task.frontmatter.created}
|
|
1141
|
-
`;
|
|
1142
|
-
output += `Updated: ${task.frontmatter.updated}
|
|
1143
|
-
`;
|
|
1144
|
-
if (task.frontmatter.completed) {
|
|
1145
|
-
output += `Completed: ${task.frontmatter.completed}
|
|
1146
|
-
`;
|
|
1147
|
-
}
|
|
1148
|
-
output += `File: ${task.path}
|
|
1149
|
-
`;
|
|
1150
|
-
output += "-".repeat(40) + "\n";
|
|
1151
|
-
const contentWithoutTitle = task.content.replace(/^#\s+.+\n/, "").trim();
|
|
1152
|
-
if (contentWithoutTitle) {
|
|
1153
|
-
output += "\n" + contentWithoutTitle + "\n";
|
|
1154
|
-
}
|
|
1155
|
-
return output;
|
|
1156
|
-
}
|
|
1157
|
-
async function taskCommand(vaultPath, action, args) {
|
|
1158
|
-
const options = args.options || {};
|
|
1159
|
-
switch (action) {
|
|
1160
|
-
case "add": {
|
|
1161
|
-
if (!args.title) {
|
|
1162
|
-
throw new Error("Title is required for task add");
|
|
1163
|
-
}
|
|
1164
|
-
const task = taskAdd(vaultPath, args.title, options);
|
|
1165
|
-
console.log(`\u2713 Created task: ${task.slug}`);
|
|
1166
|
-
console.log(` Path: ${task.path}`);
|
|
1167
|
-
break;
|
|
1168
|
-
}
|
|
1169
|
-
case "list": {
|
|
1170
|
-
const tasks = taskList(vaultPath, options);
|
|
1171
|
-
if (options.json) {
|
|
1172
|
-
console.log(JSON.stringify(tasks, null, 2));
|
|
1173
|
-
} else {
|
|
1174
|
-
console.log(formatTaskList(tasks));
|
|
1175
|
-
}
|
|
1176
|
-
break;
|
|
1177
|
-
}
|
|
1178
|
-
case "update": {
|
|
1179
|
-
if (!args.slug) {
|
|
1180
|
-
throw new Error("Task slug is required for update");
|
|
1181
|
-
}
|
|
1182
|
-
const task = taskUpdate(vaultPath, args.slug, options);
|
|
1183
|
-
console.log(`\u2713 Updated task: ${task.slug}`);
|
|
1184
|
-
break;
|
|
1185
|
-
}
|
|
1186
|
-
case "done": {
|
|
1187
|
-
if (!args.slug) {
|
|
1188
|
-
throw new Error("Task slug is required for done");
|
|
1189
|
-
}
|
|
1190
|
-
const task = taskDone(vaultPath, args.slug, {
|
|
1191
|
-
confidence: options.confidence,
|
|
1192
|
-
reason: options.reason ?? void 0
|
|
1193
|
-
});
|
|
1194
|
-
console.log(`\u2713 Completed task: ${task.slug}`);
|
|
1195
|
-
break;
|
|
1196
|
-
}
|
|
1197
|
-
case "transitions": {
|
|
1198
|
-
const output = taskTransitions(vaultPath, args.slug, {
|
|
1199
|
-
agent: options.agent,
|
|
1200
|
-
failed: options.failed,
|
|
1201
|
-
json: options.json
|
|
1202
|
-
});
|
|
1203
|
-
console.log(output);
|
|
1204
|
-
break;
|
|
1205
|
-
}
|
|
1206
|
-
case "show": {
|
|
1207
|
-
if (!args.slug) {
|
|
1208
|
-
throw new Error("Task slug is required for show");
|
|
1209
|
-
}
|
|
1210
|
-
const task = taskShow(vaultPath, args.slug);
|
|
1211
|
-
if (!task) {
|
|
1212
|
-
throw new Error(`Task not found: ${args.slug}`);
|
|
1213
|
-
}
|
|
1214
|
-
if (options.json) {
|
|
1215
|
-
console.log(JSON.stringify(task, null, 2));
|
|
1216
|
-
} else {
|
|
1217
|
-
console.log(formatTaskDetails(task));
|
|
1218
|
-
}
|
|
1219
|
-
break;
|
|
1220
|
-
}
|
|
1221
|
-
default:
|
|
1222
|
-
throw new Error(`Unknown task action: ${action}`);
|
|
1223
|
-
}
|
|
1224
|
-
}
|
|
1225
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
1226
|
-
0 && (module.exports = {
|
|
1227
|
-
formatTaskDetails,
|
|
1228
|
-
formatTaskList,
|
|
1229
|
-
taskAdd,
|
|
1230
|
-
taskCommand,
|
|
1231
|
-
taskDone,
|
|
1232
|
-
taskList,
|
|
1233
|
-
taskShow,
|
|
1234
|
-
taskTransitions,
|
|
1235
|
-
taskUpdate
|
|
1236
|
-
});
|