@ghostpaw/questlog 0.9.1 → 0.10.1
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 +180 -18
- package/SKILL.md +161 -32
- package/dist/{chunk-3Y5F3SMB.js → chunk-55JAQORX.js} +245 -665
- package/dist/{questlog_skill_spec-LOQ2FNOF.js → chunk-D2W5MYNO.js} +9 -54
- package/dist/chunk-GVD6A3RR.js +108 -0
- package/dist/chunk-IL2QRKZL.js +14 -0
- package/dist/chunk-N7V7VUI5.js +982 -0
- package/dist/chunk-QYSIJ2YN.js +47 -0
- package/dist/{chunk-3B6FMHZU.js → chunk-ZHTX64KD.js} +24 -0
- package/dist/cli.js +1 -1
- package/dist/{cli_main-ELAKW6KW.js → cli_main-7AIEZV75.js} +136 -120
- package/dist/index.cjs +2046 -1393
- package/dist/index.d.cts +142 -11
- package/dist/index.d.ts +142 -11
- package/dist/index.js +2046 -1394
- package/dist/mcp-server.js +959 -386
- package/dist/mcp.cjs +810 -328
- package/dist/mcp.js +811 -329
- package/dist/open_questlog_db-LAEH7UDM.js +2 -0
- package/dist/questlog_skill_spec-HEW2B6EB.js +76 -0
- package/dist/run_hook_command-C42BQC36.js +95 -0
- package/dist/{serve_questlog_mcp-QSHMNNFT.js → serve_questlog_mcp-W3R63HW4.js} +14 -4
- package/dist/{skill_markdown-7HCMSJYR.js → skill_markdown-HXYQ3K6U.js} +34 -6
- package/package.json +6 -3
- package/skills/questlog/SKILL.md +161 -32
- package/skills/questlog/references/webhooks.md +91 -0
- package/dist/chunk-KRQDV4KF.js +0 -58
- package/dist/open_questlog_db-SH3DAU4C.js +0 -2
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { questlogMcpInstructions } from './chunk-SVWAEAKC.js';
|
|
3
|
+
import { questlogSkills } from './chunk-D2W5MYNO.js';
|
|
4
|
+
import { reviewQuestlogTool, questlogSurfaceTools } from './chunk-55JAQORX.js';
|
|
5
|
+
import './chunk-N7V7VUI5.js';
|
|
6
|
+
import './chunk-QYSIJ2YN.js';
|
|
7
|
+
|
|
8
|
+
// src/soul.ts
|
|
9
|
+
var questlogSoulTraits = [
|
|
10
|
+
{
|
|
11
|
+
principle: "Store the least committed truth first.",
|
|
12
|
+
provenance: "The worst downstream errors usually start upstream: vague asks are turned into quests, soft ideas become fake deadlines, and half-understood work is treated as fully shaped. Using rumors and clarification before commitment keeps uncertainty where it belongs."
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
principle: "Read before you prescribe.",
|
|
16
|
+
provenance: "Many management mistakes are category mistakes: blocked work gets treated as available, missed schedule as overdue, or resolved work as fully closed when follow-through still remains. Reading the derived state first prevents confident but wrong interventions."
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
principle: "Protect history when reality changes.",
|
|
20
|
+
provenance: "Once execution starts, rewriting a quest into a different commitment destroys the meaning of the record. Honest finishes, abandonments, and follow-up quests preserve what actually happened and keep later review, planning, and reporting trustworthy."
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
principle: "Close the last mile, not just the main work.",
|
|
24
|
+
provenance: "Operational debt often hides in almost-done states: work finished but not claimed, reported, handed off, reviewed, or retired. Treating closure as a real phase prevents stale rewards, lingering initiatives, and misleading progress signals."
|
|
25
|
+
}
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
// src/surface/questlog_skill_spec.ts
|
|
29
|
+
var questlogSkillSpec = {
|
|
30
|
+
name: "questlog",
|
|
31
|
+
cheatSheet: [
|
|
32
|
+
"## Install",
|
|
33
|
+
"",
|
|
34
|
+
"Linux/macOS:",
|
|
35
|
+
"",
|
|
36
|
+
"```sh",
|
|
37
|
+
"curl -fsSL https://raw.githubusercontent.com/GhostPawJS/questlog/main/install.sh | sh",
|
|
38
|
+
"```",
|
|
39
|
+
"",
|
|
40
|
+
"Installs `~/.local/bin/ghostpaw-questlog` after checking SHA256SUMS.",
|
|
41
|
+
"",
|
|
42
|
+
"Windows x64 (PowerShell):",
|
|
43
|
+
"",
|
|
44
|
+
"```powershell",
|
|
45
|
+
"irm https://raw.githubusercontent.com/GhostPawJS/questlog/main/install.ps1 | iex",
|
|
46
|
+
"```",
|
|
47
|
+
"",
|
|
48
|
+
"Run tools as `ghostpaw-questlog ...`; use `~/.local/bin/ghostpaw-questlog` if it is not on PATH.",
|
|
49
|
+
"",
|
|
50
|
+
"`questlog` and `ghostpaw-questlog` are the same binary.",
|
|
51
|
+
"",
|
|
52
|
+
"- `questlog search <words>` before `add` to avoid duplicates.",
|
|
53
|
+
'- `ghostpaw-questlog add "..." --tag a,b --due tomorrow`',
|
|
54
|
+
`- \`questlog list [--view <view>]\`: ${reviewQuestlogTool.inputSchema.properties?.view?.enum?.join(", ")}.`,
|
|
55
|
+
'- `questlog done <id> --outcome "..."`',
|
|
56
|
+
"- `questlog search <words>`",
|
|
57
|
+
"- `questlog show <id>`",
|
|
58
|
+
"- Use `--json` on any plain command.",
|
|
59
|
+
"- Exit codes: 0 ok / 1 error / 2 usage / 3 needs input.",
|
|
60
|
+
"- Database: `~/.ghostpaw/questlog.db`; override with `--db` or `GHOSTPAW_QUESTLOG_DB`.",
|
|
61
|
+
"- Use one database per agent or project.",
|
|
62
|
+
"- Webhooks: `questlog hook add <url>`, `questlog tick --dry-run`, `questlog watch`. Read `questlog skill webhooks` for events, signing, verification, and cron setup."
|
|
63
|
+
].join("\n"),
|
|
64
|
+
description: "Use the release binary ghostpaw-questlog to manage local tasks, calendar commitments, and recurring work. Use when planning, executing, reviewing, or organizing work.",
|
|
65
|
+
license: "MIT",
|
|
66
|
+
compatibility: "Release binary ghostpaw-questlog (no runtime needed); MCP stdio via ghostpaw-questlog mcp.",
|
|
67
|
+
bin: "ghostpaw-questlog",
|
|
68
|
+
packageName: "@ghostpaw/questlog",
|
|
69
|
+
server: "ghostpaw-questlog",
|
|
70
|
+
about: questlogMcpInstructions,
|
|
71
|
+
tools: questlogSurfaceTools,
|
|
72
|
+
workflows: questlogSkills,
|
|
73
|
+
principles: questlogSoulTraits.map((trait) => trait.principle)
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export { questlogSkillSpec };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { parseCliArgs } from './chunk-GVD6A3RR.js';
|
|
3
|
+
import { watchQuestlog, testHook, removeHook, hookLabel, listHooks, addHook } from './chunk-N7V7VUI5.js';
|
|
4
|
+
|
|
5
|
+
// src/surface/run_hook_command.ts
|
|
6
|
+
async function runHookCommand(command, args, io, open) {
|
|
7
|
+
let db;
|
|
8
|
+
try {
|
|
9
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
10
|
+
io.stdout.write(
|
|
11
|
+
"questlog hook add <url> [--tag name] [--events types] [--min-gap seconds] [--secret-stdin] [--json]\nquestlog hook list|remove <id>|test <id>|label [name]\nquestlog watch [--interval seconds] [--json]\n"
|
|
12
|
+
);
|
|
13
|
+
return 0;
|
|
14
|
+
}
|
|
15
|
+
const action = command === "watch" ? "watch" : args.shift();
|
|
16
|
+
if (!["add", "list", "remove", "test", "label", "watch"].includes(action ?? ""))
|
|
17
|
+
throw new Error("Expected hook add, list, remove, test, or label");
|
|
18
|
+
const values = parseCliArgs(args, {
|
|
19
|
+
command,
|
|
20
|
+
flags: [
|
|
21
|
+
{ name: "json", type: "boolean" },
|
|
22
|
+
...action === "add" ? [
|
|
23
|
+
{ name: "tag", type: "string" },
|
|
24
|
+
{ name: "events", type: "string" },
|
|
25
|
+
{ name: "min-gap", type: "integer" },
|
|
26
|
+
{ name: "secret-stdin", type: "boolean" }
|
|
27
|
+
] : action === "watch" ? [{ name: "interval", type: "number" }] : []
|
|
28
|
+
],
|
|
29
|
+
positionals: action === "add" ? [{ name: "url", type: "string", required: true }] : ["remove", "test"].includes(action ?? "") ? [{ name: "id", type: "integer", required: true }] : action === "label" ? [{ name: "name", type: "string" }] : []
|
|
30
|
+
});
|
|
31
|
+
if (action === "watch" && values.interval !== void 0 && Number(values.interval) < 5)
|
|
32
|
+
throw new Error("Interval must be at least 5 seconds");
|
|
33
|
+
db = await open();
|
|
34
|
+
let result;
|
|
35
|
+
switch (action) {
|
|
36
|
+
case "add": {
|
|
37
|
+
let secret;
|
|
38
|
+
if (values.secretStdin) {
|
|
39
|
+
secret = "";
|
|
40
|
+
for await (const chunk of io.stdin) secret += String(chunk);
|
|
41
|
+
secret = secret.replace(/\r?\n$/, "");
|
|
42
|
+
}
|
|
43
|
+
result = addHook(db, {
|
|
44
|
+
url: String(values.url),
|
|
45
|
+
...values.tag === void 0 ? {} : { tag: String(values.tag) },
|
|
46
|
+
...values.events === void 0 ? {} : { events: String(values.events).split(",") },
|
|
47
|
+
...values.minGap === void 0 ? {} : { minGap: Number(values.minGap) },
|
|
48
|
+
...secret === void 0 ? {} : { secret }
|
|
49
|
+
});
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
case "list":
|
|
53
|
+
result = listHooks(db);
|
|
54
|
+
break;
|
|
55
|
+
case "label":
|
|
56
|
+
result = { label: hookLabel(db, values.name) };
|
|
57
|
+
break;
|
|
58
|
+
case "remove":
|
|
59
|
+
removeHook(db, Number(values.id));
|
|
60
|
+
result = { removed: Number(values.id) };
|
|
61
|
+
break;
|
|
62
|
+
case "test":
|
|
63
|
+
result = await testHook(db, Number(values.id));
|
|
64
|
+
break;
|
|
65
|
+
case "watch": {
|
|
66
|
+
const controller = new AbortController();
|
|
67
|
+
const stop = () => controller.abort();
|
|
68
|
+
process.on("SIGINT", stop);
|
|
69
|
+
process.on("SIGTERM", stop);
|
|
70
|
+
try {
|
|
71
|
+
await watchQuestlog(db, {
|
|
72
|
+
signal: controller.signal,
|
|
73
|
+
interval: Number(values.interval ?? 60),
|
|
74
|
+
onTick: (tick) => io.stdout.write(`${JSON.stringify(tick)}
|
|
75
|
+
`)
|
|
76
|
+
});
|
|
77
|
+
} finally {
|
|
78
|
+
process.off("SIGINT", stop);
|
|
79
|
+
process.off("SIGTERM", stop);
|
|
80
|
+
}
|
|
81
|
+
return 0;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
io.stdout.write(`${JSON.stringify(result, null, 2)}
|
|
85
|
+
`);
|
|
86
|
+
return 0;
|
|
87
|
+
} catch {
|
|
88
|
+
io.stderr.write("Invalid webhook command or unavailable target. Run questlog hook --help.\n");
|
|
89
|
+
return 2;
|
|
90
|
+
} finally {
|
|
91
|
+
db?.close();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export { runHookCommand };
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { openQuestlogDb } from './chunk-
|
|
2
|
+
import { openQuestlogDb } from './chunk-ZHTX64KD.js';
|
|
3
3
|
import { questlogMcpInstructions } from './chunk-SVWAEAKC.js';
|
|
4
|
-
import {
|
|
5
|
-
import { questlogSurfaceTools } from './chunk-
|
|
4
|
+
import { isErrorResult, resolveQuestlogDbPath } from './chunk-IL2QRKZL.js';
|
|
5
|
+
import { validateInput, questlogSurfaceTools } from './chunk-55JAQORX.js';
|
|
6
|
+
import { questlogVersion } from './chunk-N7V7VUI5.js';
|
|
7
|
+
import { minimalInput } from './chunk-QYSIJ2YN.js';
|
|
6
8
|
|
|
7
9
|
// src/surfaces/mcp_server.ts
|
|
8
10
|
var MCP_LATEST_PROTOCOL_VERSION = "2026-07-28";
|
|
@@ -103,7 +105,15 @@ Not for: ${tool.whenNotToUse}` : ""),
|
|
|
103
105
|
const input = params.arguments === void 0 ? {} : params.arguments;
|
|
104
106
|
const errors = validateInput(tool.inputSchema, input);
|
|
105
107
|
if (errors.length)
|
|
106
|
-
return result({
|
|
108
|
+
return result({
|
|
109
|
+
content: [
|
|
110
|
+
{
|
|
111
|
+
type: "text",
|
|
112
|
+
text: `${errors.join("\n")}; pass ${JSON.stringify(minimalInput(tool.inputSchema, input?.action))}`
|
|
113
|
+
}
|
|
114
|
+
],
|
|
115
|
+
isError: true
|
|
116
|
+
});
|
|
107
117
|
try {
|
|
108
118
|
context ??= Promise.resolve().then(options.context);
|
|
109
119
|
const value = await tool.handler(await context, input);
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { minimalInput } from './chunk-QYSIJ2YN.js';
|
|
3
|
+
|
|
2
4
|
// src/surfaces/skill_markdown.ts
|
|
3
5
|
function renderSkillMarkdown(spec, { referencesBase = "references" } = {}) {
|
|
4
6
|
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(spec.name) || spec.name.length > 64)
|
|
@@ -26,7 +28,7 @@ function renderSkillMarkdown(spec, { referencesBase = "references" } = {}) {
|
|
|
26
28
|
"",
|
|
27
29
|
`MCP: connect to ${spec.server}, then call a tool by name with its JSON arguments.`,
|
|
28
30
|
"",
|
|
29
|
-
`CLI: \`${spec.bin} call <tool> '<JSON object>'\` or \`${spec.bin} <tool> --parameter value
|
|
31
|
+
`CLI: \`${spec.bin} call <tool> '<JSON object>'\` or \`${spec.bin} <tool> --parameter value\`.`,
|
|
30
32
|
"",
|
|
31
33
|
`Inspect schemas with \`${spec.bin} describe <tool>\`. Use \`--db <path>\` to select a database.`,
|
|
32
34
|
""
|
|
@@ -46,17 +48,38 @@ function renderSkillMarkdown(spec, { referencesBase = "references" } = {}) {
|
|
|
46
48
|
"| Parameter | Type | Required | Values / description |",
|
|
47
49
|
"| --- | --- | --- | --- |"
|
|
48
50
|
);
|
|
49
|
-
|
|
51
|
+
const rows = (schema, prefix = "") => {
|
|
52
|
+
const properties = { ...schema.properties };
|
|
53
|
+
const required = new Set(schema.required);
|
|
54
|
+
for (const branch of schema.oneOf ?? []) {
|
|
55
|
+
for (const [key, value] of Object.entries(branch.properties ?? {}))
|
|
56
|
+
properties[key] ??= value;
|
|
57
|
+
for (const key of branch.required ?? []) required.add(key);
|
|
58
|
+
}
|
|
59
|
+
for (const [name, property] of Object.entries(properties)) {
|
|
60
|
+
if (prefix && Object.keys(properties).length > 8 && !required.has(name)) continue;
|
|
61
|
+
const path = `${prefix}${name}`;
|
|
62
|
+
lines.push(
|
|
63
|
+
`| ${path} | ${property.type ?? property.oneOf?.map((branch) => branch.type).join(" / ") ?? "any"} | ${required.has(name) ? "yes" : "no"} | ${((property.enum ? `${property.enum.join(", ")}. ` : "") + (property.description ?? "")).replaceAll("|", "\\|").replaceAll("\n", " ")} |`
|
|
64
|
+
);
|
|
65
|
+
if (property.properties || property.oneOf) rows(property, `${path}.`);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
rows(tool.inputSchema);
|
|
69
|
+
lines.push("", "```sh");
|
|
70
|
+
for (const action of tool.inputSchema.properties?.action?.enum?.slice(0, 3) ?? [void 0]) {
|
|
50
71
|
lines.push(
|
|
51
|
-
|
|
72
|
+
`${spec.bin} call ${tool.name} '${JSON.stringify(minimalInput(tool.inputSchema, action))}'`
|
|
52
73
|
);
|
|
74
|
+
}
|
|
75
|
+
lines.push("```");
|
|
53
76
|
lines.push("");
|
|
54
77
|
}
|
|
55
78
|
lines.push(
|
|
56
79
|
"## Workflow guides",
|
|
57
80
|
"",
|
|
58
81
|
...spec.workflows.map(
|
|
59
|
-
(workflow) => `- [${workflow.name}](${referencesBase}/${workflow.name}.md): ${workflow.description}`
|
|
82
|
+
(workflow) => `- \`${spec.bin} skill ${workflow.name}\` ([${workflow.name}](${referencesBase}/${workflow.name}.md)): ${workflow.description}`
|
|
60
83
|
),
|
|
61
84
|
"",
|
|
62
85
|
"## Principles",
|
|
@@ -65,7 +88,12 @@ function renderSkillMarkdown(spec, { referencesBase = "references" } = {}) {
|
|
|
65
88
|
""
|
|
66
89
|
);
|
|
67
90
|
const output = lines.join("\n");
|
|
68
|
-
|
|
91
|
+
const fallback = spec.packageName ? `
|
|
92
|
+
## Without the binary
|
|
93
|
+
|
|
94
|
+
Use \`npx -y ${spec.packageName} ...\` in npm-based environments (Node 24+). Harnesses that embed it in code can import \`${spec.packageName}\` as a library.
|
|
95
|
+
` : "";
|
|
96
|
+
if (!spec.cheatSheet) return output + fallback;
|
|
69
97
|
const title = `# ${spec.name}
|
|
70
98
|
|
|
71
99
|
`;
|
|
@@ -74,7 +102,7 @@ function renderSkillMarkdown(spec, { referencesBase = "references" } = {}) {
|
|
|
74
102
|
|
|
75
103
|
## Appendix: MCP and tool calls
|
|
76
104
|
|
|
77
|
-
${output.slice(start).replace(/^## /gm, "### ")}`;
|
|
105
|
+
${output.slice(start).replace(/^## /gm, "### ")}${fallback}`;
|
|
78
106
|
}
|
|
79
107
|
|
|
80
108
|
export { renderSkillMarkdown };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ghostpaw/questlog",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"description": "Unified task and calendar model for Node.js — SQLite, zero dependencies, with a built-in LLM tool facade",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -127,7 +127,7 @@
|
|
|
127
127
|
"devDependencies": {
|
|
128
128
|
"@biomejs/biome": "2.4.4",
|
|
129
129
|
"@types/node": "^25.3.0",
|
|
130
|
-
"esbuild": "^0.
|
|
130
|
+
"esbuild": "^0.28.2",
|
|
131
131
|
"fflate": "0.8.3",
|
|
132
132
|
"preact": "^10.29.0",
|
|
133
133
|
"sql.js-fts5": "^1.4.0",
|
|
@@ -138,5 +138,8 @@
|
|
|
138
138
|
"ghostpaw-questlog": "./dist/cli.js",
|
|
139
139
|
"questlog": "./dist/cli.js"
|
|
140
140
|
},
|
|
141
|
-
"mcpName": "io.github.GhostPawJS/questlog"
|
|
141
|
+
"mcpName": "io.github.GhostPawJS/questlog",
|
|
142
|
+
"overrides": {
|
|
143
|
+
"esbuild": "$esbuild"
|
|
144
|
+
}
|
|
142
145
|
}
|