@ghostpaw/questlog 0.9.0 → 0.9.2
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 +66 -18
- package/SKILL.md +136 -29
- package/dist/{questlog_skill_spec-JLZH3JL2.js → chunk-6KTQK3ZE.js} +1 -52
- package/dist/chunk-DKH623HU.js +17 -0
- package/dist/chunk-QYSIJ2YN.js +47 -0
- package/dist/{chunk-3Y5F3SMB.js → chunk-UTUQPSGO.js} +179 -77
- package/dist/cli.js +2 -2
- package/dist/{cli_main-ED5BJPSR.js → cli_main-XNZP4TY2.js} +68 -14
- package/dist/index.cjs +147 -2
- package/dist/index.js +147 -2
- package/dist/mcp-server.js +149 -10
- package/dist/mcp.cjs +158 -46
- package/dist/mcp.js +158 -46
- package/dist/questlog_skill_spec-EM6DGGVN.js +74 -0
- package/dist/{serve_questlog_mcp-J4ZHNEOT.js → serve_questlog_mcp-KFUYJB2P.js} +12 -3
- package/dist/{skill_markdown-7HCMSJYR.js → skill_markdown-HXYQ3K6U.js} +34 -6
- package/package.json +6 -3
- package/skills/questlog/SKILL.md +136 -29
- package/dist/chunk-RUSE7ZFF.js +0 -58
package/dist/index.js
CHANGED
|
@@ -3181,8 +3181,153 @@ function translateToolError(error, options = {}) {
|
|
|
3181
3181
|
);
|
|
3182
3182
|
}
|
|
3183
3183
|
|
|
3184
|
+
// src/surfaces/schema_actions.ts
|
|
3185
|
+
var requirements = /* @__PURE__ */ new WeakMap();
|
|
3186
|
+
function registerSchemaActions(schema, actions) {
|
|
3187
|
+
requirements.set(schema, actions);
|
|
3188
|
+
}
|
|
3189
|
+
function requiredForAction(schema, action) {
|
|
3190
|
+
return requirements.get(schema)?.[String(action)] ?? [];
|
|
3191
|
+
}
|
|
3192
|
+
|
|
3193
|
+
// src/surfaces/schema_examples.ts
|
|
3194
|
+
function minimalInput(schema, action, name = "") {
|
|
3195
|
+
const constant = "const" in schema ? schema.const : void 0;
|
|
3196
|
+
if (constant !== void 0) return constant;
|
|
3197
|
+
if (schema.enum)
|
|
3198
|
+
return action !== void 0 && schema.enum.includes(action) ? action : schema.enum[0];
|
|
3199
|
+
const branch = schema.oneOf?.[0];
|
|
3200
|
+
if (schema.type === "object" || schema.properties) {
|
|
3201
|
+
action ??= schema.properties?.action?.enum?.[0];
|
|
3202
|
+
const properties = { ...schema.properties, ...branch?.properties };
|
|
3203
|
+
return Object.fromEntries(
|
|
3204
|
+
[
|
|
3205
|
+
.../* @__PURE__ */ new Set([
|
|
3206
|
+
...schema.required ?? [],
|
|
3207
|
+
...requiredForAction(schema, action),
|
|
3208
|
+
...schema.properties?.outcome && ["finish", "abandon", "abandon_and_spawn_followups"].includes(String(action)) ? ["outcome"] : [],
|
|
3209
|
+
...branch?.required ?? []
|
|
3210
|
+
])
|
|
3211
|
+
].map((key) => [
|
|
3212
|
+
key,
|
|
3213
|
+
minimalInput(properties[key] ?? {}, key === "action" ? action : void 0, key)
|
|
3214
|
+
])
|
|
3215
|
+
);
|
|
3216
|
+
}
|
|
3217
|
+
if (branch) return minimalInput(branch, action, name);
|
|
3218
|
+
if (schema.type === "array") return [minimalInput(schema.items ?? {}, void 0, name)];
|
|
3219
|
+
if (schema.type === "integer" || schema.type === "number")
|
|
3220
|
+
return name === "anchorAt" ? 18e11 : name === "toQuestId" ? 2 : 1;
|
|
3221
|
+
if (schema.type === "boolean") return false;
|
|
3222
|
+
if (schema.type === "null") return null;
|
|
3223
|
+
if (name === "rrule") return "FREQ=WEEKLY";
|
|
3224
|
+
if (name === "title") return "Review release notes";
|
|
3225
|
+
if (name === "objective") return "Check changes against the release";
|
|
3226
|
+
return "release";
|
|
3227
|
+
}
|
|
3228
|
+
|
|
3229
|
+
// src/surfaces/validate_input.ts
|
|
3230
|
+
function validateInput(schema, input, path = "$") {
|
|
3231
|
+
const errors = [];
|
|
3232
|
+
const matchesType = (type) => {
|
|
3233
|
+
switch (type) {
|
|
3234
|
+
case "object":
|
|
3235
|
+
return typeof input === "object" && input !== null && !Array.isArray(input);
|
|
3236
|
+
case "array":
|
|
3237
|
+
return Array.isArray(input);
|
|
3238
|
+
case "integer":
|
|
3239
|
+
return typeof input === "number" && Number.isInteger(input);
|
|
3240
|
+
case "number":
|
|
3241
|
+
return typeof input === "number" && Number.isFinite(input);
|
|
3242
|
+
case "null":
|
|
3243
|
+
return input === null;
|
|
3244
|
+
default:
|
|
3245
|
+
return typeof input === type;
|
|
3246
|
+
}
|
|
3247
|
+
};
|
|
3248
|
+
if (schema.type && !(Array.isArray(schema.type) ? schema.type : [schema.type]).some(matchesType)) {
|
|
3249
|
+
return [`${path}: expected ${String(schema.type)}`];
|
|
3250
|
+
}
|
|
3251
|
+
if (schema.enum && !schema.enum.some((value) => JSON.stringify(value) === JSON.stringify(input)))
|
|
3252
|
+
errors.push(`${path}: expected one of ${JSON.stringify(schema.enum)}`);
|
|
3253
|
+
const constant = "const" in schema ? schema.const : void 0;
|
|
3254
|
+
if (constant !== void 0 && constant !== input)
|
|
3255
|
+
errors.push(`${path}: expected ${JSON.stringify(constant)}`);
|
|
3256
|
+
if (schema.oneOf) {
|
|
3257
|
+
const branches = schema.oneOf.map((branch) => validateInput(branch, input, path));
|
|
3258
|
+
if (!branches.some((errors2) => errors2.length === 0)) {
|
|
3259
|
+
errors.push(
|
|
3260
|
+
...branches.sort((a, b) => a.length - b.length)[0] ?? [
|
|
3261
|
+
`${path}: must match at least one schema branch`
|
|
3262
|
+
]
|
|
3263
|
+
);
|
|
3264
|
+
}
|
|
3265
|
+
}
|
|
3266
|
+
if (typeof input === "object" && input !== null && !Array.isArray(input)) {
|
|
3267
|
+
const record = input;
|
|
3268
|
+
for (const name of [...schema.required ?? [], ...requiredForAction(schema, record.action)])
|
|
3269
|
+
if (!Object.hasOwn(record, name)) errors.push(`${path}.${name}: required`);
|
|
3270
|
+
for (const [name, property] of Object.entries(schema.properties ?? {}))
|
|
3271
|
+
if (Object.hasOwn(record, name))
|
|
3272
|
+
errors.push(...validateInput(property, record[name], `${path}.${name}`));
|
|
3273
|
+
}
|
|
3274
|
+
if (Array.isArray(input) && schema.items)
|
|
3275
|
+
input.forEach((value, index) => {
|
|
3276
|
+
errors.push(...validateInput(schema.items, value, `${path}[${index}]`));
|
|
3277
|
+
});
|
|
3278
|
+
return errors;
|
|
3279
|
+
}
|
|
3280
|
+
|
|
3281
|
+
// src/tools/action_requirements.ts
|
|
3282
|
+
var actionRequirements = {
|
|
3283
|
+
shape_work: {
|
|
3284
|
+
create_quest: ["quest"],
|
|
3285
|
+
create_questline: ["questline"],
|
|
3286
|
+
attach_quest_to_questline: ["questId", "questlineId"],
|
|
3287
|
+
detach_quest_from_questline: ["questId"],
|
|
3288
|
+
dismiss_rumor: ["rumorId"],
|
|
3289
|
+
reopen_rumor: ["rumorId"],
|
|
3290
|
+
settle_rumor: ["rumorId"],
|
|
3291
|
+
update_rumor: ["rumorId"]
|
|
3292
|
+
},
|
|
3293
|
+
manage_repeatable: {
|
|
3294
|
+
create: ["repeatableQuest"],
|
|
3295
|
+
archive: ["repeatableQuestId"],
|
|
3296
|
+
update: ["repeatableQuestId"],
|
|
3297
|
+
spawn_due: ["now"]
|
|
3298
|
+
},
|
|
3299
|
+
organize_work: {
|
|
3300
|
+
add_unlock: ["fromQuestId", "toQuestId"],
|
|
3301
|
+
remove_unlock: ["fromQuestId", "toQuestId"],
|
|
3302
|
+
replace_unlocks: ["fromQuestIds", "toQuestId"],
|
|
3303
|
+
archive_questline: ["questlineId"],
|
|
3304
|
+
set_questline_fields: ["questlineId"]
|
|
3305
|
+
},
|
|
3306
|
+
plan_quest: { revise_objective: ["objective"] },
|
|
3307
|
+
run_quest: {
|
|
3308
|
+
abandon_and_spawn_followups: ["followups"],
|
|
3309
|
+
log_effort: ["effortSeconds"]
|
|
3310
|
+
},
|
|
3311
|
+
reward_work: { add: ["reward"], update: ["reward"], replace_repeatable_template: ["rewards"] }
|
|
3312
|
+
};
|
|
3313
|
+
|
|
3184
3314
|
// src/tools/tool_metadata.ts
|
|
3185
3315
|
function defineQuestlogTool(definition) {
|
|
3316
|
+
const requirements2 = actionRequirements[definition.name];
|
|
3317
|
+
if (requirements2) registerSchemaActions(definition.inputSchema, requirements2);
|
|
3318
|
+
const handler = definition.handler;
|
|
3319
|
+
definition.handler = (db, input) => {
|
|
3320
|
+
const errors = validateInput(definition.inputSchema, input);
|
|
3321
|
+
if (errors.length) {
|
|
3322
|
+
const action = input?.action;
|
|
3323
|
+
const example = minimalInput(definition.inputSchema, action);
|
|
3324
|
+
const message = errors.join("; ");
|
|
3325
|
+
return toolFailure("protocol", "invalid_input", message, message, {
|
|
3326
|
+
recovery: `${message}; pass ${JSON.stringify(example)}`
|
|
3327
|
+
});
|
|
3328
|
+
}
|
|
3329
|
+
return handler(db, input);
|
|
3330
|
+
};
|
|
3186
3331
|
return definition;
|
|
3187
3332
|
}
|
|
3188
3333
|
function stringSchema(description, options = {}) {
|
|
@@ -4725,7 +4870,7 @@ var rewardWorkTool = defineQuestlogTool({
|
|
|
4725
4870
|
name: stringSchema("Reward name."),
|
|
4726
4871
|
now: integerSchema("Optional update timestamp for the update action.")
|
|
4727
4872
|
},
|
|
4728
|
-
[]
|
|
4873
|
+
["kind", "name"]
|
|
4729
4874
|
),
|
|
4730
4875
|
rewards: arraySchema(
|
|
4731
4876
|
objectSchema(
|
|
@@ -5391,7 +5536,7 @@ var shapeWorkTool = defineQuestlogTool({
|
|
|
5391
5536
|
title: stringSchema("Questline title."),
|
|
5392
5537
|
description: stringSchema("Optional questline description.")
|
|
5393
5538
|
},
|
|
5394
|
-
[]
|
|
5539
|
+
["title"]
|
|
5395
5540
|
),
|
|
5396
5541
|
rumorId: integerSchema("Rumor to settle, dismiss, or reopen."),
|
|
5397
5542
|
dismissedAt: integerSchema("Optional dismissal timestamp."),
|
package/dist/mcp-server.js
CHANGED
|
@@ -5,14 +5,74 @@ import { homedir } from 'node:os';
|
|
|
5
5
|
|
|
6
6
|
var __defProp = Object.defineProperty;
|
|
7
7
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
8
|
-
var __esm = (fn, res) => function __init() {
|
|
9
|
-
|
|
8
|
+
var __esm = (fn, res, err) => function __init() {
|
|
9
|
+
if (err) throw err[0];
|
|
10
|
+
try {
|
|
11
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
12
|
+
} catch (e) {
|
|
13
|
+
throw err = [e], e;
|
|
14
|
+
}
|
|
10
15
|
};
|
|
11
16
|
var __export = (target, all) => {
|
|
12
17
|
for (var name in all)
|
|
13
18
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
14
19
|
};
|
|
15
20
|
|
|
21
|
+
// src/surfaces/schema_actions.ts
|
|
22
|
+
function registerSchemaActions(schema, actions) {
|
|
23
|
+
requirements.set(schema, actions);
|
|
24
|
+
}
|
|
25
|
+
function requiredForAction(schema, action) {
|
|
26
|
+
return requirements.get(schema)?.[String(action)] ?? [];
|
|
27
|
+
}
|
|
28
|
+
var requirements;
|
|
29
|
+
var init_schema_actions = __esm({
|
|
30
|
+
"src/surfaces/schema_actions.ts"() {
|
|
31
|
+
requirements = /* @__PURE__ */ new WeakMap();
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// src/surfaces/schema_examples.ts
|
|
36
|
+
function minimalInput(schema, action, name = "") {
|
|
37
|
+
const constant = "const" in schema ? schema.const : void 0;
|
|
38
|
+
if (constant !== void 0) return constant;
|
|
39
|
+
if (schema.enum)
|
|
40
|
+
return action !== void 0 && schema.enum.includes(action) ? action : schema.enum[0];
|
|
41
|
+
const branch = schema.oneOf?.[0];
|
|
42
|
+
if (schema.type === "object" || schema.properties) {
|
|
43
|
+
action ??= schema.properties?.action?.enum?.[0];
|
|
44
|
+
const properties = { ...schema.properties, ...branch?.properties };
|
|
45
|
+
return Object.fromEntries(
|
|
46
|
+
[
|
|
47
|
+
.../* @__PURE__ */ new Set([
|
|
48
|
+
...schema.required ?? [],
|
|
49
|
+
...requiredForAction(schema, action),
|
|
50
|
+
...schema.properties?.outcome && ["finish", "abandon", "abandon_and_spawn_followups"].includes(String(action)) ? ["outcome"] : [],
|
|
51
|
+
...branch?.required ?? []
|
|
52
|
+
])
|
|
53
|
+
].map((key) => [
|
|
54
|
+
key,
|
|
55
|
+
minimalInput(properties[key] ?? {}, key === "action" ? action : void 0, key)
|
|
56
|
+
])
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
if (branch) return minimalInput(branch, action, name);
|
|
60
|
+
if (schema.type === "array") return [minimalInput(schema.items ?? {}, void 0, name)];
|
|
61
|
+
if (schema.type === "integer" || schema.type === "number")
|
|
62
|
+
return name === "anchorAt" ? 18e11 : name === "toQuestId" ? 2 : 1;
|
|
63
|
+
if (schema.type === "boolean") return false;
|
|
64
|
+
if (schema.type === "null") return null;
|
|
65
|
+
if (name === "rrule") return "FREQ=WEEKLY";
|
|
66
|
+
if (name === "title") return "Review release notes";
|
|
67
|
+
if (name === "objective") return "Check changes against the release";
|
|
68
|
+
return "release";
|
|
69
|
+
}
|
|
70
|
+
var init_schema_examples = __esm({
|
|
71
|
+
"src/surfaces/schema_examples.ts"() {
|
|
72
|
+
init_schema_actions();
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
16
76
|
// src/surfaces/surface_types.ts
|
|
17
77
|
function isErrorResult(result) {
|
|
18
78
|
return typeof result === "object" && result !== null && "ok" in result && result.ok === false;
|
|
@@ -46,11 +106,22 @@ function validateInput(schema, input, path = "$") {
|
|
|
46
106
|
}
|
|
47
107
|
if (schema.enum && !schema.enum.some((value) => JSON.stringify(value) === JSON.stringify(input)))
|
|
48
108
|
errors.push(`${path}: expected one of ${JSON.stringify(schema.enum)}`);
|
|
49
|
-
|
|
50
|
-
|
|
109
|
+
const constant = "const" in schema ? schema.const : void 0;
|
|
110
|
+
if (constant !== void 0 && constant !== input)
|
|
111
|
+
errors.push(`${path}: expected ${JSON.stringify(constant)}`);
|
|
112
|
+
if (schema.oneOf) {
|
|
113
|
+
const branches = schema.oneOf.map((branch) => validateInput(branch, input, path));
|
|
114
|
+
if (!branches.some((errors2) => errors2.length === 0)) {
|
|
115
|
+
errors.push(
|
|
116
|
+
...branches.sort((a, b) => a.length - b.length)[0] ?? [
|
|
117
|
+
`${path}: must match at least one schema branch`
|
|
118
|
+
]
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
51
122
|
if (typeof input === "object" && input !== null && !Array.isArray(input)) {
|
|
52
123
|
const record = input;
|
|
53
|
-
for (const name of schema.required ?? [])
|
|
124
|
+
for (const name of [...schema.required ?? [], ...requiredForAction(schema, record.action)])
|
|
54
125
|
if (!Object.hasOwn(record, name)) errors.push(`${path}.${name}: required`);
|
|
55
126
|
for (const [name, property] of Object.entries(schema.properties ?? {}))
|
|
56
127
|
if (Object.hasOwn(record, name))
|
|
@@ -64,6 +135,7 @@ function validateInput(schema, input, path = "$") {
|
|
|
64
135
|
}
|
|
65
136
|
var init_validate_input = __esm({
|
|
66
137
|
"src/surfaces/validate_input.ts"() {
|
|
138
|
+
init_schema_actions();
|
|
67
139
|
}
|
|
68
140
|
});
|
|
69
141
|
|
|
@@ -158,7 +230,15 @@ Not for: ${tool.whenNotToUse}` : ""),
|
|
|
158
230
|
const input = params.arguments === void 0 ? {} : params.arguments;
|
|
159
231
|
const errors = validateInput(tool.inputSchema, input);
|
|
160
232
|
if (errors.length)
|
|
161
|
-
return result({
|
|
233
|
+
return result({
|
|
234
|
+
content: [
|
|
235
|
+
{
|
|
236
|
+
type: "text",
|
|
237
|
+
text: `${errors.join("\n")}; pass ${JSON.stringify(minimalInput(tool.inputSchema, input?.action))}`
|
|
238
|
+
}
|
|
239
|
+
],
|
|
240
|
+
isError: true
|
|
241
|
+
});
|
|
162
242
|
try {
|
|
163
243
|
context ??= Promise.resolve().then(options.context);
|
|
164
244
|
const value = await tool.handler(await context, input);
|
|
@@ -197,6 +277,7 @@ Not for: ${tool.whenNotToUse}` : ""),
|
|
|
197
277
|
var MCP_LATEST_PROTOCOL_VERSION, MCP_SUPPORTED_PROTOCOL_VERSIONS;
|
|
198
278
|
var init_mcp_server = __esm({
|
|
199
279
|
"src/surfaces/mcp_server.ts"() {
|
|
280
|
+
init_schema_examples();
|
|
200
281
|
init_surface_types();
|
|
201
282
|
init_validate_input();
|
|
202
283
|
MCP_LATEST_PROTOCOL_VERSION = "2026-07-28";
|
|
@@ -677,7 +758,7 @@ var init_open_questlog_db = __esm({
|
|
|
677
758
|
var questlogVersion;
|
|
678
759
|
var init_version = __esm({
|
|
679
760
|
"src/version.ts"() {
|
|
680
|
-
questlogVersion = "0.9.
|
|
761
|
+
questlogVersion = "0.9.2";
|
|
681
762
|
}
|
|
682
763
|
});
|
|
683
764
|
|
|
@@ -979,8 +1060,61 @@ var init_tool_errors = __esm({
|
|
|
979
1060
|
}
|
|
980
1061
|
});
|
|
981
1062
|
|
|
1063
|
+
// src/tools/action_requirements.ts
|
|
1064
|
+
var actionRequirements;
|
|
1065
|
+
var init_action_requirements = __esm({
|
|
1066
|
+
"src/tools/action_requirements.ts"() {
|
|
1067
|
+
actionRequirements = {
|
|
1068
|
+
shape_work: {
|
|
1069
|
+
create_quest: ["quest"],
|
|
1070
|
+
create_questline: ["questline"],
|
|
1071
|
+
attach_quest_to_questline: ["questId", "questlineId"],
|
|
1072
|
+
detach_quest_from_questline: ["questId"],
|
|
1073
|
+
dismiss_rumor: ["rumorId"],
|
|
1074
|
+
reopen_rumor: ["rumorId"],
|
|
1075
|
+
settle_rumor: ["rumorId"],
|
|
1076
|
+
update_rumor: ["rumorId"]
|
|
1077
|
+
},
|
|
1078
|
+
manage_repeatable: {
|
|
1079
|
+
create: ["repeatableQuest"],
|
|
1080
|
+
archive: ["repeatableQuestId"],
|
|
1081
|
+
update: ["repeatableQuestId"],
|
|
1082
|
+
spawn_due: ["now"]
|
|
1083
|
+
},
|
|
1084
|
+
organize_work: {
|
|
1085
|
+
add_unlock: ["fromQuestId", "toQuestId"],
|
|
1086
|
+
remove_unlock: ["fromQuestId", "toQuestId"],
|
|
1087
|
+
replace_unlocks: ["fromQuestIds", "toQuestId"],
|
|
1088
|
+
archive_questline: ["questlineId"],
|
|
1089
|
+
set_questline_fields: ["questlineId"]
|
|
1090
|
+
},
|
|
1091
|
+
plan_quest: { revise_objective: ["objective"] },
|
|
1092
|
+
run_quest: {
|
|
1093
|
+
abandon_and_spawn_followups: ["followups"],
|
|
1094
|
+
log_effort: ["effortSeconds"]
|
|
1095
|
+
},
|
|
1096
|
+
reward_work: { add: ["reward"], update: ["reward"], replace_repeatable_template: ["rewards"] }
|
|
1097
|
+
};
|
|
1098
|
+
}
|
|
1099
|
+
});
|
|
1100
|
+
|
|
982
1101
|
// src/tools/tool_metadata.ts
|
|
983
1102
|
function defineQuestlogTool(definition) {
|
|
1103
|
+
const requirements2 = actionRequirements[definition.name];
|
|
1104
|
+
if (requirements2) registerSchemaActions(definition.inputSchema, requirements2);
|
|
1105
|
+
const handler = definition.handler;
|
|
1106
|
+
definition.handler = (db, input) => {
|
|
1107
|
+
const errors = validateInput(definition.inputSchema, input);
|
|
1108
|
+
if (errors.length) {
|
|
1109
|
+
const action = input?.action;
|
|
1110
|
+
const example = minimalInput(definition.inputSchema, action);
|
|
1111
|
+
const message = errors.join("; ");
|
|
1112
|
+
return toolFailure("protocol", "invalid_input", message, message, {
|
|
1113
|
+
recovery: `${message}; pass ${JSON.stringify(example)}`
|
|
1114
|
+
});
|
|
1115
|
+
}
|
|
1116
|
+
return handler(db, input);
|
|
1117
|
+
};
|
|
984
1118
|
return definition;
|
|
985
1119
|
}
|
|
986
1120
|
function stringSchema(description, options = {}) {
|
|
@@ -1023,6 +1157,11 @@ function objectSchema(properties, required, description) {
|
|
|
1023
1157
|
}
|
|
1024
1158
|
var init_tool_metadata = __esm({
|
|
1025
1159
|
"src/tools/tool_metadata.ts"() {
|
|
1160
|
+
init_schema_actions();
|
|
1161
|
+
init_schema_examples();
|
|
1162
|
+
init_validate_input();
|
|
1163
|
+
init_action_requirements();
|
|
1164
|
+
init_tool_types();
|
|
1026
1165
|
}
|
|
1027
1166
|
});
|
|
1028
1167
|
|
|
@@ -4599,7 +4738,7 @@ var init_reward_work_tool = __esm({
|
|
|
4599
4738
|
name: stringSchema("Reward name."),
|
|
4600
4739
|
now: integerSchema("Optional update timestamp for the update action.")
|
|
4601
4740
|
},
|
|
4602
|
-
[]
|
|
4741
|
+
["kind", "name"]
|
|
4603
4742
|
),
|
|
4604
4743
|
rewards: arraySchema(
|
|
4605
4744
|
objectSchema(
|
|
@@ -5513,7 +5652,7 @@ var init_shape_work_tool = __esm({
|
|
|
5513
5652
|
title: stringSchema("Questline title."),
|
|
5514
5653
|
description: stringSchema("Optional questline description.")
|
|
5515
5654
|
},
|
|
5516
|
-
[]
|
|
5655
|
+
["title"]
|
|
5517
5656
|
),
|
|
5518
5657
|
rumorId: integerSchema("Rumor to settle, dismiss, or reopen."),
|
|
5519
5658
|
dismissedAt: integerSchema("Optional dismissal timestamp."),
|
|
@@ -5867,7 +6006,7 @@ var init_questlog_surface_tools = __esm({
|
|
|
5867
6006
|
whenNotToUse: tool.whenNotToUse ?? "",
|
|
5868
6007
|
readOnly: tool.readOnly,
|
|
5869
6008
|
sideEffects: tool.sideEffects,
|
|
5870
|
-
inputSchema:
|
|
6009
|
+
inputSchema: tool.inputSchema,
|
|
5871
6010
|
handler: tool.handler
|
|
5872
6011
|
})
|
|
5873
6012
|
);
|
package/dist/mcp.cjs
CHANGED
|
@@ -386,7 +386,7 @@ async function openQuestlogDb(path) {
|
|
|
386
386
|
}
|
|
387
387
|
|
|
388
388
|
// src/version.ts
|
|
389
|
-
var questlogVersion = "0.9.
|
|
389
|
+
var questlogVersion = "0.9.2";
|
|
390
390
|
|
|
391
391
|
// src/surface/questlog_mcp_instructions.ts
|
|
392
392
|
var questlogMcpInstructions = "Questlog manages local tasks, calendar commitments, and recurring work. Search before creating work, inspect before changing it, and keep uncertain work as rumors. Use unlock prerequisites to sequence work. run_quest refuses blocked starts unless force is true. Review commitments and resolve work with an honest outcome.";
|
|
@@ -632,8 +632,153 @@ function translateToolError(error, options = {}) {
|
|
|
632
632
|
);
|
|
633
633
|
}
|
|
634
634
|
|
|
635
|
+
// src/surfaces/schema_actions.ts
|
|
636
|
+
var requirements = /* @__PURE__ */ new WeakMap();
|
|
637
|
+
function registerSchemaActions(schema, actions) {
|
|
638
|
+
requirements.set(schema, actions);
|
|
639
|
+
}
|
|
640
|
+
function requiredForAction(schema, action) {
|
|
641
|
+
return requirements.get(schema)?.[String(action)] ?? [];
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
// src/surfaces/schema_examples.ts
|
|
645
|
+
function minimalInput(schema, action, name = "") {
|
|
646
|
+
const constant = "const" in schema ? schema.const : void 0;
|
|
647
|
+
if (constant !== void 0) return constant;
|
|
648
|
+
if (schema.enum)
|
|
649
|
+
return action !== void 0 && schema.enum.includes(action) ? action : schema.enum[0];
|
|
650
|
+
const branch = schema.oneOf?.[0];
|
|
651
|
+
if (schema.type === "object" || schema.properties) {
|
|
652
|
+
action ??= schema.properties?.action?.enum?.[0];
|
|
653
|
+
const properties = { ...schema.properties, ...branch?.properties };
|
|
654
|
+
return Object.fromEntries(
|
|
655
|
+
[
|
|
656
|
+
.../* @__PURE__ */ new Set([
|
|
657
|
+
...schema.required ?? [],
|
|
658
|
+
...requiredForAction(schema, action),
|
|
659
|
+
...schema.properties?.outcome && ["finish", "abandon", "abandon_and_spawn_followups"].includes(String(action)) ? ["outcome"] : [],
|
|
660
|
+
...branch?.required ?? []
|
|
661
|
+
])
|
|
662
|
+
].map((key) => [
|
|
663
|
+
key,
|
|
664
|
+
minimalInput(properties[key] ?? {}, key === "action" ? action : void 0, key)
|
|
665
|
+
])
|
|
666
|
+
);
|
|
667
|
+
}
|
|
668
|
+
if (branch) return minimalInput(branch, action, name);
|
|
669
|
+
if (schema.type === "array") return [minimalInput(schema.items ?? {}, void 0, name)];
|
|
670
|
+
if (schema.type === "integer" || schema.type === "number")
|
|
671
|
+
return name === "anchorAt" ? 18e11 : name === "toQuestId" ? 2 : 1;
|
|
672
|
+
if (schema.type === "boolean") return false;
|
|
673
|
+
if (schema.type === "null") return null;
|
|
674
|
+
if (name === "rrule") return "FREQ=WEEKLY";
|
|
675
|
+
if (name === "title") return "Review release notes";
|
|
676
|
+
if (name === "objective") return "Check changes against the release";
|
|
677
|
+
return "release";
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
// src/surfaces/validate_input.ts
|
|
681
|
+
function validateInput(schema, input, path = "$") {
|
|
682
|
+
const errors = [];
|
|
683
|
+
const matchesType = (type) => {
|
|
684
|
+
switch (type) {
|
|
685
|
+
case "object":
|
|
686
|
+
return typeof input === "object" && input !== null && !Array.isArray(input);
|
|
687
|
+
case "array":
|
|
688
|
+
return Array.isArray(input);
|
|
689
|
+
case "integer":
|
|
690
|
+
return typeof input === "number" && Number.isInteger(input);
|
|
691
|
+
case "number":
|
|
692
|
+
return typeof input === "number" && Number.isFinite(input);
|
|
693
|
+
case "null":
|
|
694
|
+
return input === null;
|
|
695
|
+
default:
|
|
696
|
+
return typeof input === type;
|
|
697
|
+
}
|
|
698
|
+
};
|
|
699
|
+
if (schema.type && !(Array.isArray(schema.type) ? schema.type : [schema.type]).some(matchesType)) {
|
|
700
|
+
return [`${path}: expected ${String(schema.type)}`];
|
|
701
|
+
}
|
|
702
|
+
if (schema.enum && !schema.enum.some((value) => JSON.stringify(value) === JSON.stringify(input)))
|
|
703
|
+
errors.push(`${path}: expected one of ${JSON.stringify(schema.enum)}`);
|
|
704
|
+
const constant = "const" in schema ? schema.const : void 0;
|
|
705
|
+
if (constant !== void 0 && constant !== input)
|
|
706
|
+
errors.push(`${path}: expected ${JSON.stringify(constant)}`);
|
|
707
|
+
if (schema.oneOf) {
|
|
708
|
+
const branches = schema.oneOf.map((branch) => validateInput(branch, input, path));
|
|
709
|
+
if (!branches.some((errors2) => errors2.length === 0)) {
|
|
710
|
+
errors.push(
|
|
711
|
+
...branches.sort((a, b) => a.length - b.length)[0] ?? [
|
|
712
|
+
`${path}: must match at least one schema branch`
|
|
713
|
+
]
|
|
714
|
+
);
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
if (typeof input === "object" && input !== null && !Array.isArray(input)) {
|
|
718
|
+
const record = input;
|
|
719
|
+
for (const name of [...schema.required ?? [], ...requiredForAction(schema, record.action)])
|
|
720
|
+
if (!Object.hasOwn(record, name)) errors.push(`${path}.${name}: required`);
|
|
721
|
+
for (const [name, property] of Object.entries(schema.properties ?? {}))
|
|
722
|
+
if (Object.hasOwn(record, name))
|
|
723
|
+
errors.push(...validateInput(property, record[name], `${path}.${name}`));
|
|
724
|
+
}
|
|
725
|
+
if (Array.isArray(input) && schema.items)
|
|
726
|
+
input.forEach((value, index) => {
|
|
727
|
+
errors.push(...validateInput(schema.items, value, `${path}[${index}]`));
|
|
728
|
+
});
|
|
729
|
+
return errors;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
// src/tools/action_requirements.ts
|
|
733
|
+
var actionRequirements = {
|
|
734
|
+
shape_work: {
|
|
735
|
+
create_quest: ["quest"],
|
|
736
|
+
create_questline: ["questline"],
|
|
737
|
+
attach_quest_to_questline: ["questId", "questlineId"],
|
|
738
|
+
detach_quest_from_questline: ["questId"],
|
|
739
|
+
dismiss_rumor: ["rumorId"],
|
|
740
|
+
reopen_rumor: ["rumorId"],
|
|
741
|
+
settle_rumor: ["rumorId"],
|
|
742
|
+
update_rumor: ["rumorId"]
|
|
743
|
+
},
|
|
744
|
+
manage_repeatable: {
|
|
745
|
+
create: ["repeatableQuest"],
|
|
746
|
+
archive: ["repeatableQuestId"],
|
|
747
|
+
update: ["repeatableQuestId"],
|
|
748
|
+
spawn_due: ["now"]
|
|
749
|
+
},
|
|
750
|
+
organize_work: {
|
|
751
|
+
add_unlock: ["fromQuestId", "toQuestId"],
|
|
752
|
+
remove_unlock: ["fromQuestId", "toQuestId"],
|
|
753
|
+
replace_unlocks: ["fromQuestIds", "toQuestId"],
|
|
754
|
+
archive_questline: ["questlineId"],
|
|
755
|
+
set_questline_fields: ["questlineId"]
|
|
756
|
+
},
|
|
757
|
+
plan_quest: { revise_objective: ["objective"] },
|
|
758
|
+
run_quest: {
|
|
759
|
+
abandon_and_spawn_followups: ["followups"],
|
|
760
|
+
log_effort: ["effortSeconds"]
|
|
761
|
+
},
|
|
762
|
+
reward_work: { add: ["reward"], update: ["reward"], replace_repeatable_template: ["rewards"] }
|
|
763
|
+
};
|
|
764
|
+
|
|
635
765
|
// src/tools/tool_metadata.ts
|
|
636
766
|
function defineQuestlogTool(definition) {
|
|
767
|
+
const requirements2 = actionRequirements[definition.name];
|
|
768
|
+
if (requirements2) registerSchemaActions(definition.inputSchema, requirements2);
|
|
769
|
+
const handler = definition.handler;
|
|
770
|
+
definition.handler = (db, input) => {
|
|
771
|
+
const errors = validateInput(definition.inputSchema, input);
|
|
772
|
+
if (errors.length) {
|
|
773
|
+
const action = input?.action;
|
|
774
|
+
const example = minimalInput(definition.inputSchema, action);
|
|
775
|
+
const message = errors.join("; ");
|
|
776
|
+
return toolFailure("protocol", "invalid_input", message, message, {
|
|
777
|
+
recovery: `${message}; pass ${JSON.stringify(example)}`
|
|
778
|
+
});
|
|
779
|
+
}
|
|
780
|
+
return handler(db, input);
|
|
781
|
+
};
|
|
637
782
|
return definition;
|
|
638
783
|
}
|
|
639
784
|
function stringSchema(description, options = {}) {
|
|
@@ -3583,7 +3728,7 @@ var rewardWorkTool = defineQuestlogTool({
|
|
|
3583
3728
|
name: stringSchema("Reward name."),
|
|
3584
3729
|
now: integerSchema("Optional update timestamp for the update action.")
|
|
3585
3730
|
},
|
|
3586
|
-
[]
|
|
3731
|
+
["kind", "name"]
|
|
3587
3732
|
),
|
|
3588
3733
|
rewards: arraySchema(
|
|
3589
3734
|
objectSchema(
|
|
@@ -4410,7 +4555,7 @@ var shapeWorkTool = defineQuestlogTool({
|
|
|
4410
4555
|
title: stringSchema("Questline title."),
|
|
4411
4556
|
description: stringSchema("Optional questline description.")
|
|
4412
4557
|
},
|
|
4413
|
-
[]
|
|
4558
|
+
["title"]
|
|
4414
4559
|
),
|
|
4415
4560
|
rumorId: integerSchema("Rumor to settle, dismiss, or reopen."),
|
|
4416
4561
|
dismissedAt: integerSchema("Optional dismissal timestamp."),
|
|
@@ -4692,7 +4837,7 @@ var questlogSurfaceTools = questlogTools.map(
|
|
|
4692
4837
|
whenNotToUse: tool.whenNotToUse ?? "",
|
|
4693
4838
|
readOnly: tool.readOnly,
|
|
4694
4839
|
sideEffects: tool.sideEffects,
|
|
4695
|
-
inputSchema:
|
|
4840
|
+
inputSchema: tool.inputSchema,
|
|
4696
4841
|
handler: tool.handler
|
|
4697
4842
|
})
|
|
4698
4843
|
);
|
|
@@ -4727,47 +4872,6 @@ function isErrorResult(result) {
|
|
|
4727
4872
|
return typeof result === "object" && result !== null && "ok" in result && result.ok === false;
|
|
4728
4873
|
}
|
|
4729
4874
|
|
|
4730
|
-
// src/surfaces/validate_input.ts
|
|
4731
|
-
function validateInput(schema, input, path = "$") {
|
|
4732
|
-
const errors = [];
|
|
4733
|
-
const matchesType = (type) => {
|
|
4734
|
-
switch (type) {
|
|
4735
|
-
case "object":
|
|
4736
|
-
return typeof input === "object" && input !== null && !Array.isArray(input);
|
|
4737
|
-
case "array":
|
|
4738
|
-
return Array.isArray(input);
|
|
4739
|
-
case "integer":
|
|
4740
|
-
return typeof input === "number" && Number.isInteger(input);
|
|
4741
|
-
case "number":
|
|
4742
|
-
return typeof input === "number" && Number.isFinite(input);
|
|
4743
|
-
case "null":
|
|
4744
|
-
return input === null;
|
|
4745
|
-
default:
|
|
4746
|
-
return typeof input === type;
|
|
4747
|
-
}
|
|
4748
|
-
};
|
|
4749
|
-
if (schema.type && !(Array.isArray(schema.type) ? schema.type : [schema.type]).some(matchesType)) {
|
|
4750
|
-
return [`${path}: expected ${String(schema.type)}`];
|
|
4751
|
-
}
|
|
4752
|
-
if (schema.enum && !schema.enum.some((value) => JSON.stringify(value) === JSON.stringify(input)))
|
|
4753
|
-
errors.push(`${path}: expected one of ${JSON.stringify(schema.enum)}`);
|
|
4754
|
-
if (schema.oneOf && !schema.oneOf.some((branch) => validateInput(branch, input, path).length === 0))
|
|
4755
|
-
errors.push(`${path}: must match at least one schema branch`);
|
|
4756
|
-
if (typeof input === "object" && input !== null && !Array.isArray(input)) {
|
|
4757
|
-
const record = input;
|
|
4758
|
-
for (const name of schema.required ?? [])
|
|
4759
|
-
if (!Object.hasOwn(record, name)) errors.push(`${path}.${name}: required`);
|
|
4760
|
-
for (const [name, property] of Object.entries(schema.properties ?? {}))
|
|
4761
|
-
if (Object.hasOwn(record, name))
|
|
4762
|
-
errors.push(...validateInput(property, record[name], `${path}.${name}`));
|
|
4763
|
-
}
|
|
4764
|
-
if (Array.isArray(input) && schema.items)
|
|
4765
|
-
input.forEach((value, index) => {
|
|
4766
|
-
errors.push(...validateInput(schema.items, value, `${path}[${index}]`));
|
|
4767
|
-
});
|
|
4768
|
-
return errors;
|
|
4769
|
-
}
|
|
4770
|
-
|
|
4771
4875
|
// src/surfaces/mcp_server.ts
|
|
4772
4876
|
var MCP_LATEST_PROTOCOL_VERSION = "2026-07-28";
|
|
4773
4877
|
var MCP_SUPPORTED_PROTOCOL_VERSIONS = [
|
|
@@ -4867,7 +4971,15 @@ Not for: ${tool.whenNotToUse}` : ""),
|
|
|
4867
4971
|
const input = params.arguments === void 0 ? {} : params.arguments;
|
|
4868
4972
|
const errors = validateInput(tool.inputSchema, input);
|
|
4869
4973
|
if (errors.length)
|
|
4870
|
-
return result({
|
|
4974
|
+
return result({
|
|
4975
|
+
content: [
|
|
4976
|
+
{
|
|
4977
|
+
type: "text",
|
|
4978
|
+
text: `${errors.join("\n")}; pass ${JSON.stringify(minimalInput(tool.inputSchema, input?.action))}`
|
|
4979
|
+
}
|
|
4980
|
+
],
|
|
4981
|
+
isError: true
|
|
4982
|
+
});
|
|
4871
4983
|
try {
|
|
4872
4984
|
context ??= Promise.resolve().then(options.context);
|
|
4873
4985
|
const value = await tool.handler(await context, input);
|