@monnet/mcp 0.2.4 → 0.4.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 +20 -27
- package/dist/approval.d.ts +19 -11
- package/dist/approval.js +73 -52
- package/dist/approval.js.map +1 -1
- package/dist/client.js +1 -1
- package/dist/client.js.map +1 -1
- package/dist/index.js +10 -44
- package/dist/index.js.map +1 -1
- package/dist/instructions.d.ts +15 -0
- package/dist/instructions.js +31 -0
- package/dist/instructions.js.map +1 -0
- package/dist/registry.d.ts +95 -0
- package/dist/registry.js +50 -0
- package/dist/registry.js.map +1 -0
- package/dist/rendering/motion.d.ts +4 -12
- package/dist/rendering/motion.js +10 -26
- package/dist/rendering/motion.js.map +1 -1
- package/dist/test-env.d.ts +15 -0
- package/dist/test-env.js +17 -0
- package/dist/test-env.js.map +1 -0
- package/dist/tools/wiki/_common.d.ts +102 -0
- package/dist/tools/wiki/_common.js +132 -0
- package/dist/tools/wiki/_common.js.map +1 -0
- package/dist/tools/wiki/index.d.ts +21 -0
- package/dist/tools/wiki/index.js +48 -0
- package/dist/tools/wiki/index.js.map +1 -0
- package/dist/tools/wiki/read.d.ts +68 -0
- package/dist/tools/wiki/read.js +114 -0
- package/dist/tools/wiki/read.js.map +1 -0
- package/dist/tools/wiki/sources.d.ts +114 -0
- package/dist/tools/wiki/sources.js +288 -0
- package/dist/tools/wiki/sources.js.map +1 -0
- package/dist/tools/wiki/write.d.ts +174 -0
- package/dist/tools/wiki/write.js +280 -0
- package/dist/tools/wiki/write.js.map +1 -0
- package/package.json +3 -8
- package/LICENSE +0 -21
- package/dist/tools/get-workspace-memory.d.ts +0 -15
- package/dist/tools/get-workspace-memory.js +0 -35
- package/dist/tools/get-workspace-memory.js.map +0 -1
|
@@ -1,25 +1,17 @@
|
|
|
1
1
|
interface PlanStep {
|
|
2
|
-
kind?: "step";
|
|
3
2
|
content: string;
|
|
4
3
|
status: string;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
approved_by?: string
|
|
4
|
+
assignees?: string[];
|
|
5
|
+
approval?: boolean;
|
|
6
|
+
approved_by?: string[];
|
|
8
7
|
}
|
|
9
|
-
interface PlanGroup {
|
|
10
|
-
kind: "group";
|
|
11
|
-
title: string;
|
|
12
|
-
execution?: "parallel" | "sequential";
|
|
13
|
-
children: PlanItem[];
|
|
14
|
-
}
|
|
15
|
-
type PlanItem = PlanStep | PlanGroup;
|
|
16
8
|
interface MotionDetail {
|
|
17
9
|
id: string;
|
|
18
10
|
summary: string;
|
|
19
11
|
status: string;
|
|
20
12
|
priority: string | null;
|
|
21
13
|
body: string | null;
|
|
22
|
-
plan:
|
|
14
|
+
plan: PlanStep[] | null;
|
|
23
15
|
author: string;
|
|
24
16
|
created_at: string;
|
|
25
17
|
updated_at: string;
|
package/dist/rendering/motion.js
CHANGED
|
@@ -8,35 +8,10 @@ const PRIORITY_DOTS = {
|
|
|
8
8
|
normal: "●",
|
|
9
9
|
low: "○",
|
|
10
10
|
};
|
|
11
|
-
function isGroup(item) {
|
|
12
|
-
return item.kind === "group";
|
|
13
|
-
}
|
|
14
11
|
const DIVIDER = "━━━━━━━━━━━━━━━━━━━━━━━━━━━━";
|
|
15
12
|
function padRight(str, len) {
|
|
16
13
|
return str.length >= len ? str : str + " ".repeat(len - str.length);
|
|
17
14
|
}
|
|
18
|
-
// Render the plan tree recursively. Groups print their title + execution mode
|
|
19
|
-
// and recurse into their children; steps print status icon, content, assignee
|
|
20
|
-
// and an approval lock. Numbering is hierarchical (1, 2, 2.1, 2.2, …).
|
|
21
|
-
function renderPlanItems(items, nameMap, lines, depth, prefix) {
|
|
22
|
-
const indent = " ".repeat(depth + 1);
|
|
23
|
-
items.forEach((item, i) => {
|
|
24
|
-
const number = `${prefix}${i + 1}`;
|
|
25
|
-
if (isGroup(item)) {
|
|
26
|
-
const exec = item.execution ? ` (${item.execution})` : "";
|
|
27
|
-
lines.push(`${indent}${number}. 📂 ${item.title}${exec}`);
|
|
28
|
-
renderPlanItems(item.children || [], nameMap, lines, depth + 1, `${number}.`);
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
const icon = STATUS_ICONS[item.status] || "⏳";
|
|
32
|
-
const assigneeStr = item.assignee
|
|
33
|
-
? ` → ${nameMap.get(item.assignee) || item.assignee}`
|
|
34
|
-
: "";
|
|
35
|
-
const lock = item.step_type === "approval" ? " 🔒" : "";
|
|
36
|
-
lines.push(`${indent}${number}. ${icon} ${item.content}${assigneeStr}${lock}`);
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
15
|
export function renderMotionDetail(data) {
|
|
41
16
|
const priority = data.priority || "normal";
|
|
42
17
|
const dot = PRIORITY_DOTS[priority] || "●";
|
|
@@ -71,7 +46,16 @@ export function renderMotionDetail(data) {
|
|
|
71
46
|
if (data.plan && data.plan.length > 0) {
|
|
72
47
|
lines.push("");
|
|
73
48
|
lines.push("PLAN");
|
|
74
|
-
|
|
49
|
+
data.plan.forEach((step, i) => {
|
|
50
|
+
const icon = STATUS_ICONS[step.status] || "⏳";
|
|
51
|
+
let assigneeStr = "";
|
|
52
|
+
if (step.assignees && step.assignees.length > 0) {
|
|
53
|
+
const names = step.assignees.map((uid) => nameMap.get(uid) || uid);
|
|
54
|
+
assigneeStr = ` → ${names.join(", ")}`;
|
|
55
|
+
}
|
|
56
|
+
const lock = step.approval ? " 🔒" : "";
|
|
57
|
+
lines.push(` ${i + 1}. ${icon} ${step.content}${assigneeStr}${lock}`);
|
|
58
|
+
});
|
|
75
59
|
}
|
|
76
60
|
// Members — show motion-level roles (editor/commenter) when available,
|
|
77
61
|
// fall back to workspace role (owner/member) otherwise.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"motion.js","sourceRoot":"","sources":["../../src/rendering/motion.ts"],"names":[],"mappings":"AAAA,MAAM,YAAY,GAA2B;IAC3C,OAAO,EAAE,GAAG;IACZ,WAAW,EAAE,IAAI;IACjB,IAAI,EAAE,GAAG;CACV,CAAC;AAEF,MAAM,aAAa,GAA2B;IAC5C,QAAQ,EAAE,IAAI;IACd,MAAM,EAAE,GAAG;IACX,GAAG,EAAE,GAAG;CACT,CAAC;
|
|
1
|
+
{"version":3,"file":"motion.js","sourceRoot":"","sources":["../../src/rendering/motion.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Imported first by every test file.
|
|
3
|
+
*
|
|
4
|
+
* `client.ts` calls `process.exit(1)` at import time when MONNET_API_KEY is
|
|
5
|
+
* unset — right for a server a client just spawned with no config, fatal for a
|
|
6
|
+
* test suite. Without this the whole file dies before its first assertion, and
|
|
7
|
+
* it dies SILENTLY as far as a developer with a key exported is concerned: the
|
|
8
|
+
* suite passes on their machine and runs zero tests everywhere else. That is
|
|
9
|
+
* how the approval gate — the one thing standing between a model and an
|
|
10
|
+
* irreversible delete — came to have tests that never ran in CI.
|
|
11
|
+
*
|
|
12
|
+
* `??=` so a real key in the environment still wins; nothing here reaches the
|
|
13
|
+
* network anyway, since every test stubs `fetch`.
|
|
14
|
+
*/
|
|
15
|
+
export {};
|
package/dist/test-env.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Imported first by every test file.
|
|
3
|
+
*
|
|
4
|
+
* `client.ts` calls `process.exit(1)` at import time when MONNET_API_KEY is
|
|
5
|
+
* unset — right for a server a client just spawned with no config, fatal for a
|
|
6
|
+
* test suite. Without this the whole file dies before its first assertion, and
|
|
7
|
+
* it dies SILENTLY as far as a developer with a key exported is concerned: the
|
|
8
|
+
* suite passes on their machine and runs zero tests everywhere else. That is
|
|
9
|
+
* how the approval gate — the one thing standing between a model and an
|
|
10
|
+
* irreversible delete — came to have tests that never ran in CI.
|
|
11
|
+
*
|
|
12
|
+
* `??=` so a real key in the environment still wins; nothing here reaches the
|
|
13
|
+
* network anyway, since every test stubs `fetch`.
|
|
14
|
+
*/
|
|
15
|
+
process.env.MONNET_API_KEY ??= "mnk_test_not_a_real_key";
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=test-env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-env.js","sourceRoot":"","sources":["../src/test-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared plumbing for the company-brain tools.
|
|
3
|
+
*
|
|
4
|
+
* Grouped in one folder rather than thirteen sibling files, mirroring the
|
|
5
|
+
* backend's own `tool_handlers/wiki.py`: they share workspace resolution, the
|
|
6
|
+
* `?page=` link format and the same error vocabulary, and splitting them would
|
|
7
|
+
* mean repeating those thirteen times. The tool surface is unchanged — each is
|
|
8
|
+
* still registered by name in `index.ts`.
|
|
9
|
+
*
|
|
10
|
+
* These are deliberately the SAME names Monnet's own tools carry
|
|
11
|
+
* (`read_wiki_page`, `edit_wiki_page`, …). One vocabulary for the wiki,
|
|
12
|
+
* whether the agent writing is Monnet in the app or an agent on somebody's
|
|
13
|
+
* laptop; two sets of names for one surface would be two things to learn and
|
|
14
|
+
* two things to keep in step.
|
|
15
|
+
*/
|
|
16
|
+
import { z } from "zod";
|
|
17
|
+
/** Every wiki tool is scoped to one workspace, and says so the same way. */
|
|
18
|
+
export declare const WORKSPACE_SLUG_PROPERTY: {
|
|
19
|
+
type: "string";
|
|
20
|
+
description: string;
|
|
21
|
+
};
|
|
22
|
+
export declare const PAGE_ID_PROPERTY: {
|
|
23
|
+
type: "string";
|
|
24
|
+
description: string;
|
|
25
|
+
};
|
|
26
|
+
export declare function wikiBase(workspaceSlug: string): Promise<string>;
|
|
27
|
+
export interface WikiNode {
|
|
28
|
+
id: string;
|
|
29
|
+
type: "folder" | "page";
|
|
30
|
+
name: string;
|
|
31
|
+
path: string;
|
|
32
|
+
position: number;
|
|
33
|
+
children: WikiNode[];
|
|
34
|
+
}
|
|
35
|
+
export declare function fetchTree(workspaceSlug: string): Promise<WikiNode[]>;
|
|
36
|
+
/**
|
|
37
|
+
* The tree as indented lines, ids included.
|
|
38
|
+
*
|
|
39
|
+
* Ids are on every line because they are not decoration: a link is
|
|
40
|
+
* `[Label](?page=<id>)`, and the backend refuses a write whose links do not
|
|
41
|
+
* resolve. A listing without them would send the caller guessing at exactly
|
|
42
|
+
* the value it must copy.
|
|
43
|
+
*/
|
|
44
|
+
export declare function renderTree(nodes: WikiNode[], depth?: number): string;
|
|
45
|
+
/**
|
|
46
|
+
* Every node in the tree, flat, in render order.
|
|
47
|
+
*
|
|
48
|
+
* One walk that the folder lookups, the ambiguity check and the error listing
|
|
49
|
+
* all read, so they cannot disagree about what a folder's path is — they did,
|
|
50
|
+
* and the refusal could list the very path it had just rejected, written a
|
|
51
|
+
* different way.
|
|
52
|
+
*/
|
|
53
|
+
export declare function flatten(nodes: WikiNode[]): WikiNode[];
|
|
54
|
+
/**
|
|
55
|
+
* Normalise a folder path to the backend's shape: one leading slash, none
|
|
56
|
+
* trailing. "" and "/" both mean the wiki root, and so does `undefined`.
|
|
57
|
+
*/
|
|
58
|
+
export declare function normaliseFolderPath(path: string | undefined): string;
|
|
59
|
+
export type FolderLookup = {
|
|
60
|
+
id: string | null;
|
|
61
|
+
} | {
|
|
62
|
+
error: string;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Resolve a folder path to an id, agreeing with `resolve_folder_path` on the
|
|
66
|
+
* backend — the same comparison, and the same two refusals.
|
|
67
|
+
*
|
|
68
|
+
* Exact match, not case-insensitive: the backend compares exactly, and a
|
|
69
|
+
* client that accepted `product/design` where Monnet's own tool rejects it
|
|
70
|
+
* would make the wiki answer to two different vocabularies.
|
|
71
|
+
*
|
|
72
|
+
* Ambiguity is an error rather than a first match. Nothing stops two siblings
|
|
73
|
+
* sharing a name, so two folders can answer to one path — and silently taking
|
|
74
|
+
* either files a page into an arbitrary one of them, over and over, with
|
|
75
|
+
* nothing to notice.
|
|
76
|
+
*/
|
|
77
|
+
export declare function resolveFolderPath(nodes: WikiNode[], path: string | undefined): FolderLookup;
|
|
78
|
+
/**
|
|
79
|
+
* `resolveFolderPath` against the workspace's current tree, which every write
|
|
80
|
+
* tool needs before it can place anything. Returns the tree too: the caller
|
|
81
|
+
* that moves a node needs it again to append rather than prepend.
|
|
82
|
+
*/
|
|
83
|
+
export declare function lookUpFolder(workspaceSlug: string, path: string | undefined): Promise<{
|
|
84
|
+
tree: WikiNode[];
|
|
85
|
+
} & FolderLookup>;
|
|
86
|
+
/**
|
|
87
|
+
* The node a move should land AFTER: the destination's last child.
|
|
88
|
+
*
|
|
89
|
+
* Omitting it means "first" to the server's placement, which would take the top
|
|
90
|
+
* slot of the destination and push down an order the team set by hand. Monnet's
|
|
91
|
+
* own move tool computes the same value for the same reason (`_last_sibling_id`
|
|
92
|
+
* in the backend's wiki tool handlers) — an agent move appends.
|
|
93
|
+
*/
|
|
94
|
+
export declare function lastChildId(nodes: WikiNode[], destinationId: string | null, movingId: string): string | null;
|
|
95
|
+
/** Every wiki tool is scoped to one workspace, and validates it the same way. */
|
|
96
|
+
export declare const WorkspaceOnlyArgs: z.ZodObject<{
|
|
97
|
+
workspace_slug: z.ZodString;
|
|
98
|
+
}, "strip", z.ZodTypeAny, {
|
|
99
|
+
workspace_slug: string;
|
|
100
|
+
}, {
|
|
101
|
+
workspace_slug: string;
|
|
102
|
+
}>;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared plumbing for the company-brain tools.
|
|
3
|
+
*
|
|
4
|
+
* Grouped in one folder rather than thirteen sibling files, mirroring the
|
|
5
|
+
* backend's own `tool_handlers/wiki.py`: they share workspace resolution, the
|
|
6
|
+
* `?page=` link format and the same error vocabulary, and splitting them would
|
|
7
|
+
* mean repeating those thirteen times. The tool surface is unchanged — each is
|
|
8
|
+
* still registered by name in `index.ts`.
|
|
9
|
+
*
|
|
10
|
+
* These are deliberately the SAME names Monnet's own tools carry
|
|
11
|
+
* (`read_wiki_page`, `edit_wiki_page`, …). One vocabulary for the wiki,
|
|
12
|
+
* whether the agent writing is Monnet in the app or an agent on somebody's
|
|
13
|
+
* laptop; two sets of names for one surface would be two things to learn and
|
|
14
|
+
* two things to keep in step.
|
|
15
|
+
*/
|
|
16
|
+
import { z } from "zod";
|
|
17
|
+
import { apiFetch, resolveWorkspaceId } from "../../client.js";
|
|
18
|
+
/** Every wiki tool is scoped to one workspace, and says so the same way. */
|
|
19
|
+
export const WORKSPACE_SLUG_PROPERTY = {
|
|
20
|
+
type: "string",
|
|
21
|
+
description: "The workspace slug, from any Monnet URL (e.g. 'monnet-team-410b'). Call list_workspaces if you do not have it.",
|
|
22
|
+
};
|
|
23
|
+
export const PAGE_ID_PROPERTY = {
|
|
24
|
+
type: "string",
|
|
25
|
+
description: "The page's full id, as returned by get_wiki_tree, search_wiki or create_wiki_page. Not the 8-character short id — those address motions, not pages.",
|
|
26
|
+
};
|
|
27
|
+
export async function wikiBase(workspaceSlug) {
|
|
28
|
+
return `/workspaces/${await resolveWorkspaceId(workspaceSlug)}/wiki`;
|
|
29
|
+
}
|
|
30
|
+
export async function fetchTree(workspaceSlug) {
|
|
31
|
+
return apiFetch(`${await wikiBase(workspaceSlug)}/tree`);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The tree as indented lines, ids included.
|
|
35
|
+
*
|
|
36
|
+
* Ids are on every line because they are not decoration: a link is
|
|
37
|
+
* `[Label](?page=<id>)`, and the backend refuses a write whose links do not
|
|
38
|
+
* resolve. A listing without them would send the caller guessing at exactly
|
|
39
|
+
* the value it must copy.
|
|
40
|
+
*/
|
|
41
|
+
export function renderTree(nodes, depth = 0) {
|
|
42
|
+
return nodes
|
|
43
|
+
.flatMap((node) => {
|
|
44
|
+
const indent = " ".repeat(depth);
|
|
45
|
+
const line = node.type === "folder"
|
|
46
|
+
? `${indent}${node.name}/`
|
|
47
|
+
: `${indent}${node.name} (id: ${node.id})`;
|
|
48
|
+
return [line, ...(node.children.length ? [renderTree(node.children, depth + 1)] : [])];
|
|
49
|
+
})
|
|
50
|
+
.join("\n");
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Every node in the tree, flat, in render order.
|
|
54
|
+
*
|
|
55
|
+
* One walk that the folder lookups, the ambiguity check and the error listing
|
|
56
|
+
* all read, so they cannot disagree about what a folder's path is — they did,
|
|
57
|
+
* and the refusal could list the very path it had just rejected, written a
|
|
58
|
+
* different way.
|
|
59
|
+
*/
|
|
60
|
+
export function flatten(nodes) {
|
|
61
|
+
return nodes.flatMap((node) => [node, ...flatten(node.children)]);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Normalise a folder path to the backend's shape: one leading slash, none
|
|
65
|
+
* trailing. "" and "/" both mean the wiki root, and so does `undefined`.
|
|
66
|
+
*/
|
|
67
|
+
export function normaliseFolderPath(path) {
|
|
68
|
+
const trimmed = (path || "").trim().replace(/^\/+|\/+$/g, "");
|
|
69
|
+
return trimmed ? `/${trimmed}` : "";
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Resolve a folder path to an id, agreeing with `resolve_folder_path` on the
|
|
73
|
+
* backend — the same comparison, and the same two refusals.
|
|
74
|
+
*
|
|
75
|
+
* Exact match, not case-insensitive: the backend compares exactly, and a
|
|
76
|
+
* client that accepted `product/design` where Monnet's own tool rejects it
|
|
77
|
+
* would make the wiki answer to two different vocabularies.
|
|
78
|
+
*
|
|
79
|
+
* Ambiguity is an error rather than a first match. Nothing stops two siblings
|
|
80
|
+
* sharing a name, so two folders can answer to one path — and silently taking
|
|
81
|
+
* either files a page into an arbitrary one of them, over and over, with
|
|
82
|
+
* nothing to notice.
|
|
83
|
+
*/
|
|
84
|
+
export function resolveFolderPath(nodes, path) {
|
|
85
|
+
const wanted = normaliseFolderPath(path);
|
|
86
|
+
if (!wanted)
|
|
87
|
+
return { id: null };
|
|
88
|
+
const folders = flatten(nodes).filter((node) => node.type === "folder");
|
|
89
|
+
const matches = folders.filter((node) => normaliseFolderPath(node.path) === wanted);
|
|
90
|
+
if (matches.length > 1) {
|
|
91
|
+
return {
|
|
92
|
+
error: `Error: two folders answer to ${wanted}. Rename one of them, or move ` +
|
|
93
|
+
`the node by hand — this path cannot say which you mean.`,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
if (matches.length === 1)
|
|
97
|
+
return { id: matches[0].id };
|
|
98
|
+
const existing = folders.map((node) => normaliseFolderPath(node.path));
|
|
99
|
+
return {
|
|
100
|
+
error: `Error: no folder at "${wanted}". ` +
|
|
101
|
+
(existing.length
|
|
102
|
+
? `Existing folders: ${existing.join(", ")}. Create one with create_wiki_folder, or omit the path to work at the root.`
|
|
103
|
+
: "This wiki has no folders yet — omit the path to work at the root."),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* `resolveFolderPath` against the workspace's current tree, which every write
|
|
108
|
+
* tool needs before it can place anything. Returns the tree too: the caller
|
|
109
|
+
* that moves a node needs it again to append rather than prepend.
|
|
110
|
+
*/
|
|
111
|
+
export async function lookUpFolder(workspaceSlug, path) {
|
|
112
|
+
const tree = await fetchTree(workspaceSlug);
|
|
113
|
+
return { tree, ...resolveFolderPath(tree, path) };
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* The node a move should land AFTER: the destination's last child.
|
|
117
|
+
*
|
|
118
|
+
* Omitting it means "first" to the server's placement, which would take the top
|
|
119
|
+
* slot of the destination and push down an order the team set by hand. Monnet's
|
|
120
|
+
* own move tool computes the same value for the same reason (`_last_sibling_id`
|
|
121
|
+
* in the backend's wiki tool handlers) — an agent move appends.
|
|
122
|
+
*/
|
|
123
|
+
export function lastChildId(nodes, destinationId, movingId) {
|
|
124
|
+
const siblings = destinationId === null
|
|
125
|
+
? nodes
|
|
126
|
+
: flatten(nodes).find((node) => node.id === destinationId)?.children ?? [];
|
|
127
|
+
const candidates = siblings.filter((node) => node.id !== movingId);
|
|
128
|
+
return candidates.length ? candidates[candidates.length - 1].id : null;
|
|
129
|
+
}
|
|
130
|
+
/** Every wiki tool is scoped to one workspace, and validates it the same way. */
|
|
131
|
+
export const WorkspaceOnlyArgs = z.object({ workspace_slug: z.string().min(1) });
|
|
132
|
+
//# sourceMappingURL=_common.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_common.js","sourceRoot":"","sources":["../../../src/tools/wiki/_common.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The company-brain surface, as one registration list.
|
|
3
|
+
*
|
|
4
|
+
* `index.ts` spreads these rather than importing thirteen names, so adding a
|
|
5
|
+
* wiki tool is one entry here instead of three edits in the server file.
|
|
6
|
+
*/
|
|
7
|
+
export declare const WIKI_TOOLS: {
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
inputSchema: {
|
|
11
|
+
type: "object";
|
|
12
|
+
properties: {
|
|
13
|
+
workspace_slug: {
|
|
14
|
+
type: "string";
|
|
15
|
+
description: string;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
required: string[];
|
|
19
|
+
};
|
|
20
|
+
}[];
|
|
21
|
+
export declare const WIKI_HANDLERS: Record<string, (args: unknown) => Promise<string>>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The company-brain surface, as one registration list.
|
|
3
|
+
*
|
|
4
|
+
* `index.ts` spreads these rather than importing thirteen names, so adding a
|
|
5
|
+
* wiki tool is one entry here instead of three edits in the server file.
|
|
6
|
+
*/
|
|
7
|
+
import { GET_WIKI_SCHEMA_TOOL_DEFINITION, GET_WIKI_TREE_TOOL_DEFINITION, READ_WIKI_PAGE_TOOL_DEFINITION, SEARCH_WIKI_TOOL_DEFINITION, handleGetWikiSchema, handleGetWikiTree, handleReadWikiPage, handleSearchWiki, } from "./read.js";
|
|
8
|
+
import { CREATE_WIKI_FOLDER_TOOL_DEFINITION, CREATE_WIKI_PAGE_TOOL_DEFINITION, DELETE_WIKI_FOLDER_TOOL_DEFINITION, DELETE_WIKI_PAGE_TOOL_DEFINITION, EDIT_WIKI_PAGE_TOOL_DEFINITION, MOVE_WIKI_NODE_TOOL_DEFINITION, RENAME_WIKI_FOLDER_TOOL_DEFINITION, handleCreateWikiFolder, handleCreateWikiPage, handleDeleteWikiFolder, handleDeleteWikiPage, handleEditWikiPage, handleMoveWikiNode, handleRenameWikiFolder, } from "./write.js";
|
|
9
|
+
import { DELETE_WIKI_SOURCE_TOOL_DEFINITION, LIST_WIKI_SOURCES_TOOL_DEFINITION, MARK_WIKI_SOURCE_INGESTED_TOOL_DEFINITION, PUSH_WIKI_SOURCE_TOOL_DEFINITION, READ_WIKI_SOURCE_TOOL_DEFINITION, REQUEUE_WIKI_SOURCE_TOOL_DEFINITION, handleDeleteWikiSource, handleListWikiSources, handleMarkWikiSourceIngested, handlePushWikiSource, handleReadWikiSource, handleRequeueWikiSource, } from "./sources.js";
|
|
10
|
+
export const WIKI_TOOLS = [
|
|
11
|
+
GET_WIKI_SCHEMA_TOOL_DEFINITION,
|
|
12
|
+
GET_WIKI_TREE_TOOL_DEFINITION,
|
|
13
|
+
READ_WIKI_PAGE_TOOL_DEFINITION,
|
|
14
|
+
SEARCH_WIKI_TOOL_DEFINITION,
|
|
15
|
+
CREATE_WIKI_PAGE_TOOL_DEFINITION,
|
|
16
|
+
EDIT_WIKI_PAGE_TOOL_DEFINITION,
|
|
17
|
+
DELETE_WIKI_PAGE_TOOL_DEFINITION,
|
|
18
|
+
CREATE_WIKI_FOLDER_TOOL_DEFINITION,
|
|
19
|
+
RENAME_WIKI_FOLDER_TOOL_DEFINITION,
|
|
20
|
+
DELETE_WIKI_FOLDER_TOOL_DEFINITION,
|
|
21
|
+
MOVE_WIKI_NODE_TOOL_DEFINITION,
|
|
22
|
+
LIST_WIKI_SOURCES_TOOL_DEFINITION,
|
|
23
|
+
READ_WIKI_SOURCE_TOOL_DEFINITION,
|
|
24
|
+
PUSH_WIKI_SOURCE_TOOL_DEFINITION,
|
|
25
|
+
MARK_WIKI_SOURCE_INGESTED_TOOL_DEFINITION,
|
|
26
|
+
REQUEUE_WIKI_SOURCE_TOOL_DEFINITION,
|
|
27
|
+
DELETE_WIKI_SOURCE_TOOL_DEFINITION,
|
|
28
|
+
];
|
|
29
|
+
export const WIKI_HANDLERS = {
|
|
30
|
+
get_wiki_schema: handleGetWikiSchema,
|
|
31
|
+
get_wiki_tree: handleGetWikiTree,
|
|
32
|
+
read_wiki_page: handleReadWikiPage,
|
|
33
|
+
search_wiki: handleSearchWiki,
|
|
34
|
+
create_wiki_page: handleCreateWikiPage,
|
|
35
|
+
edit_wiki_page: handleEditWikiPage,
|
|
36
|
+
delete_wiki_page: handleDeleteWikiPage,
|
|
37
|
+
create_wiki_folder: handleCreateWikiFolder,
|
|
38
|
+
rename_wiki_folder: handleRenameWikiFolder,
|
|
39
|
+
delete_wiki_folder: handleDeleteWikiFolder,
|
|
40
|
+
move_wiki_node: handleMoveWikiNode,
|
|
41
|
+
list_wiki_sources: handleListWikiSources,
|
|
42
|
+
read_wiki_source: handleReadWikiSource,
|
|
43
|
+
push_wiki_source: handlePushWikiSource,
|
|
44
|
+
mark_wiki_source_ingested: handleMarkWikiSourceIngested,
|
|
45
|
+
requeue_wiki_source: handleRequeueWikiSource,
|
|
46
|
+
delete_wiki_source: handleDeleteWikiSource,
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/wiki/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,+BAA+B,EAC/B,6BAA6B,EAC7B,8BAA8B,EAC9B,2BAA2B,EAC3B,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,kCAAkC,EAClC,gCAAgC,EAChC,kCAAkC,EAClC,gCAAgC,EAChC,8BAA8B,EAC9B,8BAA8B,EAC9B,kCAAkC,EAClC,sBAAsB,EACtB,oBAAoB,EACpB,sBAAsB,EACtB,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,kCAAkC,EAClC,iCAAiC,EACjC,yCAAyC,EACzC,gCAAgC,EAChC,gCAAgC,EAChC,mCAAmC,EACnC,sBAAsB,EACtB,qBAAqB,EACrB,4BAA4B,EAC5B,oBAAoB,EACpB,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,cAAc,CAAC;AAEtB,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,+BAA+B;IAC/B,6BAA6B;IAC7B,8BAA8B;IAC9B,2BAA2B;IAC3B,gCAAgC;IAChC,8BAA8B;IAC9B,gCAAgC;IAChC,kCAAkC;IAClC,kCAAkC;IAClC,kCAAkC;IAClC,8BAA8B;IAC9B,iCAAiC;IACjC,gCAAgC;IAChC,gCAAgC;IAChC,yCAAyC;IACzC,mCAAmC;IACnC,kCAAkC;CACnC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAuD;IAC/E,eAAe,EAAE,mBAAmB;IACpC,aAAa,EAAE,iBAAiB;IAChC,cAAc,EAAE,kBAAkB;IAClC,WAAW,EAAE,gBAAgB;IAC7B,gBAAgB,EAAE,oBAAoB;IACtC,cAAc,EAAE,kBAAkB;IAClC,gBAAgB,EAAE,oBAAoB;IACtC,kBAAkB,EAAE,sBAAsB;IAC1C,kBAAkB,EAAE,sBAAsB;IAC1C,kBAAkB,EAAE,sBAAsB;IAC1C,cAAc,EAAE,kBAAkB;IAClC,iBAAiB,EAAE,qBAAqB;IACxC,gBAAgB,EAAE,oBAAoB;IACtC,gBAAgB,EAAE,oBAAoB;IACtC,yBAAyB,EAAE,4BAA4B;IACvD,mBAAmB,EAAE,uBAAuB;IAC5C,kBAAkB,EAAE,sBAAsB;CAC3C,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export declare function handleGetWikiSchema(args: unknown): Promise<string>;
|
|
2
|
+
export declare const GET_WIKI_SCHEMA_TOOL_DEFINITION: {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: "object";
|
|
7
|
+
properties: {
|
|
8
|
+
workspace_slug: {
|
|
9
|
+
type: "string";
|
|
10
|
+
description: string;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
required: string[];
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
export declare function handleGetWikiTree(args: unknown): Promise<string>;
|
|
17
|
+
export declare const GET_WIKI_TREE_TOOL_DEFINITION: {
|
|
18
|
+
name: string;
|
|
19
|
+
description: string;
|
|
20
|
+
inputSchema: {
|
|
21
|
+
type: "object";
|
|
22
|
+
properties: {
|
|
23
|
+
workspace_slug: {
|
|
24
|
+
type: "string";
|
|
25
|
+
description: string;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
required: string[];
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
export declare function handleReadWikiPage(args: unknown): Promise<string>;
|
|
32
|
+
export declare const READ_WIKI_PAGE_TOOL_DEFINITION: {
|
|
33
|
+
name: string;
|
|
34
|
+
description: string;
|
|
35
|
+
inputSchema: {
|
|
36
|
+
type: "object";
|
|
37
|
+
properties: {
|
|
38
|
+
workspace_slug: {
|
|
39
|
+
type: "string";
|
|
40
|
+
description: string;
|
|
41
|
+
};
|
|
42
|
+
page_id: {
|
|
43
|
+
type: "string";
|
|
44
|
+
description: string;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
required: string[];
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
export declare function handleSearchWiki(args: unknown): Promise<string>;
|
|
51
|
+
export declare const SEARCH_WIKI_TOOL_DEFINITION: {
|
|
52
|
+
name: string;
|
|
53
|
+
description: string;
|
|
54
|
+
inputSchema: {
|
|
55
|
+
type: "object";
|
|
56
|
+
properties: {
|
|
57
|
+
workspace_slug: {
|
|
58
|
+
type: "string";
|
|
59
|
+
description: string;
|
|
60
|
+
};
|
|
61
|
+
query: {
|
|
62
|
+
type: string;
|
|
63
|
+
description: string;
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
required: string[];
|
|
67
|
+
};
|
|
68
|
+
};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { apiFetch, resolveWorkspaceId } from "../../client.js";
|
|
3
|
+
import { PAGE_ID_PROPERTY, WORKSPACE_SLUG_PROPERTY, WorkspaceOnlyArgs, fetchTree, renderTree, wikiBase, } from "./_common.js";
|
|
4
|
+
/* ------------------------------------------------------------------ schema */
|
|
5
|
+
export async function handleGetWikiSchema(args) {
|
|
6
|
+
const { workspace_slug } = WorkspaceOnlyArgs.parse(args);
|
|
7
|
+
const { schema_markdown } = await apiFetch(`${await wikiBase(workspace_slug)}/schema`);
|
|
8
|
+
return schema_markdown;
|
|
9
|
+
}
|
|
10
|
+
export const GET_WIKI_SCHEMA_TOOL_DEFINITION = {
|
|
11
|
+
name: "get_wiki_schema",
|
|
12
|
+
description: "Read the rules this team's company brain is built on — how pages are typed and templated, when to create one versus extend one, and the link format. " +
|
|
13
|
+
"Read it BEFORE your first write to a workspace's wiki. It is the same text the nightly ingest job runs on, so a page you write matches the ones Monnet writes; " +
|
|
14
|
+
"a team that has rewritten it for their own brain is exactly the case where guessing goes wrong.",
|
|
15
|
+
inputSchema: {
|
|
16
|
+
type: "object",
|
|
17
|
+
properties: { workspace_slug: WORKSPACE_SLUG_PROPERTY },
|
|
18
|
+
required: ["workspace_slug"],
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
/* -------------------------------------------------------------------- tree */
|
|
22
|
+
export async function handleGetWikiTree(args) {
|
|
23
|
+
const { workspace_slug } = WorkspaceOnlyArgs.parse(args);
|
|
24
|
+
const tree = await fetchTree(workspace_slug);
|
|
25
|
+
if (!tree.length) {
|
|
26
|
+
return "This wiki is empty. Create its first page with create_wiki_page.";
|
|
27
|
+
}
|
|
28
|
+
return renderTree(tree);
|
|
29
|
+
}
|
|
30
|
+
export const GET_WIKI_TREE_TOOL_DEFINITION = {
|
|
31
|
+
name: "get_wiki_tree",
|
|
32
|
+
description: "List every folder and page in a workspace's company brain, nested, with each page's id. " +
|
|
33
|
+
"This is the wiki's table of contents and the only place page ids come from — read it before deciding a subject is missing, " +
|
|
34
|
+
"because most material belongs on a page that already exists. Names and paths only: use read_wiki_page for a page's contents.",
|
|
35
|
+
inputSchema: {
|
|
36
|
+
type: "object",
|
|
37
|
+
properties: { workspace_slug: WORKSPACE_SLUG_PROPERTY },
|
|
38
|
+
required: ["workspace_slug"],
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
/* -------------------------------------------------------------------- read */
|
|
42
|
+
const ReadPageArgs = z.object({
|
|
43
|
+
workspace_slug: z.string().min(1),
|
|
44
|
+
page_id: z.string().min(1),
|
|
45
|
+
});
|
|
46
|
+
export async function handleReadWikiPage(args) {
|
|
47
|
+
const { workspace_slug, page_id } = ReadPageArgs.parse(args);
|
|
48
|
+
const wsId = await resolveWorkspaceId(workspace_slug);
|
|
49
|
+
// The motion detail route: a page IS a motion row, and a full id passes
|
|
50
|
+
// straight through its short-id resolver. No wiki-specific read endpoint
|
|
51
|
+
// exists because there is nothing for it to do differently.
|
|
52
|
+
const detail = await apiFetch(`/workspaces/${wsId}/motions/${encodeURIComponent(page_id)}/detail`);
|
|
53
|
+
const { summary, body } = detail.motion;
|
|
54
|
+
return `# ${summary || "Untitled"}\n\n${body || "(this page is empty)"}`;
|
|
55
|
+
}
|
|
56
|
+
export const READ_WIKI_PAGE_TOOL_DEFINITION = {
|
|
57
|
+
name: "read_wiki_page",
|
|
58
|
+
description: "Read one company-brain page's full contents, as markdown. Read the page before editing it — edit_wiki_page replaces an exact string, and the ## Sources section at the bottom has to be kept current.",
|
|
59
|
+
inputSchema: {
|
|
60
|
+
type: "object",
|
|
61
|
+
properties: {
|
|
62
|
+
workspace_slug: WORKSPACE_SLUG_PROPERTY,
|
|
63
|
+
page_id: PAGE_ID_PROPERTY,
|
|
64
|
+
},
|
|
65
|
+
required: ["workspace_slug", "page_id"],
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
/* ------------------------------------------------------------------ search */
|
|
69
|
+
const SearchArgs = z.object({
|
|
70
|
+
workspace_slug: z.string().min(1),
|
|
71
|
+
query: z.string().min(1).max(200),
|
|
72
|
+
});
|
|
73
|
+
// The search route is capped server-side, across every workspace the caller
|
|
74
|
+
// belongs to and every kind of row. Since the wiki pages are filtered out of
|
|
75
|
+
// that page of results afterwards, the cap has to be wide enough that a busy
|
|
76
|
+
// workspace's motions cannot fill it and leave zero pages behind — answering
|
|
77
|
+
// "no page mentions this", which is exactly the signal the tool tells the
|
|
78
|
+
// model to read as "create one".
|
|
79
|
+
const SEARCH_FETCH_LIMIT = 50;
|
|
80
|
+
const SEARCH_SHOW_LIMIT = 10;
|
|
81
|
+
export async function handleSearchWiki(args) {
|
|
82
|
+
const { workspace_slug, query } = SearchArgs.parse(args);
|
|
83
|
+
// Resolving the slug first does two things: it gives an id to compare on,
|
|
84
|
+
// and it 404s an unknown slug — which otherwise came back as a cheerful
|
|
85
|
+
// "no wiki page mentions that", indistinguishable from a real empty result.
|
|
86
|
+
const wsId = await resolveWorkspaceId(workspace_slug);
|
|
87
|
+
const { motions } = await apiFetch(`/motions/search?q=${encodeURIComponent(query)}&limit=${SEARCH_FETCH_LIMIT}`);
|
|
88
|
+
// A page is a motion row carrying `kind`, so one index serves both.
|
|
89
|
+
const hits = motions.filter((m) => m.kind === "wiki_page" && m.workspace_id === wsId);
|
|
90
|
+
if (!hits.length) {
|
|
91
|
+
const capped = motions.length >= SEARCH_FETCH_LIMIT
|
|
92
|
+
? " (the search returned a full page of motions, so a matching wiki page may have been crowded out — try a narrower query, or get_wiki_tree)"
|
|
93
|
+
: "";
|
|
94
|
+
return `No wiki page in ${workspace_slug} mentions "${query}".${capped}`;
|
|
95
|
+
}
|
|
96
|
+
return hits
|
|
97
|
+
.slice(0, SEARCH_SHOW_LIMIT)
|
|
98
|
+
.map((h) => `- ${h.title || "Untitled"} (id: ${h.id})\n ${(h.snippet || "").replace(/\n/g, " ")}`)
|
|
99
|
+
.join("\n");
|
|
100
|
+
}
|
|
101
|
+
export const SEARCH_WIKI_TOOL_DEFINITION = {
|
|
102
|
+
name: "search_wiki",
|
|
103
|
+
description: "Search INSIDE company-brain pages — their titles and their bodies. Use it to find where a fact already lives before writing it somewhere new; " +
|
|
104
|
+
"get_wiki_tree gives you every title, so reach for this when what you are looking for is in a page's contents rather than its name.",
|
|
105
|
+
inputSchema: {
|
|
106
|
+
type: "object",
|
|
107
|
+
properties: {
|
|
108
|
+
workspace_slug: WORKSPACE_SLUG_PROPERTY,
|
|
109
|
+
query: { type: "string", description: "Words to look for. Words shorter than three characters are ignored." },
|
|
110
|
+
},
|
|
111
|
+
required: ["workspace_slug", "query"],
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
//# sourceMappingURL=read.js.map
|