@creator-notes/cnotes 0.16.11

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.
Files changed (158) hide show
  1. package/.claude-plugin/plugin.json +14 -0
  2. package/.mcp.json +12 -0
  3. package/LICENSE +21 -0
  4. package/README.md +303 -0
  5. package/dist/cn.d.ts +3 -0
  6. package/dist/cn.d.ts.map +1 -0
  7. package/dist/cn.js +124 -0
  8. package/dist/cn.js.map +1 -0
  9. package/dist/commands/auth.d.ts +10 -0
  10. package/dist/commands/auth.d.ts.map +1 -0
  11. package/dist/commands/auth.js +188 -0
  12. package/dist/commands/auth.js.map +1 -0
  13. package/dist/commands/canvas.d.ts +3 -0
  14. package/dist/commands/canvas.d.ts.map +1 -0
  15. package/dist/commands/canvas.js +1383 -0
  16. package/dist/commands/canvas.js.map +1 -0
  17. package/dist/commands/claude-hook.d.ts +28 -0
  18. package/dist/commands/claude-hook.d.ts.map +1 -0
  19. package/dist/commands/claude-hook.js +59 -0
  20. package/dist/commands/claude-hook.js.map +1 -0
  21. package/dist/commands/config.d.ts +3 -0
  22. package/dist/commands/config.d.ts.map +1 -0
  23. package/dist/commands/config.js +47 -0
  24. package/dist/commands/config.js.map +1 -0
  25. package/dist/commands/files.d.ts +3 -0
  26. package/dist/commands/files.d.ts.map +1 -0
  27. package/dist/commands/files.js +119 -0
  28. package/dist/commands/files.js.map +1 -0
  29. package/dist/commands/init.d.ts +3 -0
  30. package/dist/commands/init.d.ts.map +1 -0
  31. package/dist/commands/init.js +473 -0
  32. package/dist/commands/init.js.map +1 -0
  33. package/dist/commands/mcp.d.ts +15 -0
  34. package/dist/commands/mcp.d.ts.map +1 -0
  35. package/dist/commands/mcp.js +118 -0
  36. package/dist/commands/mcp.js.map +1 -0
  37. package/dist/commands/memory.d.ts +3 -0
  38. package/dist/commands/memory.d.ts.map +1 -0
  39. package/dist/commands/memory.js +150 -0
  40. package/dist/commands/memory.js.map +1 -0
  41. package/dist/commands/notes.d.ts +3 -0
  42. package/dist/commands/notes.d.ts.map +1 -0
  43. package/dist/commands/notes.js +706 -0
  44. package/dist/commands/notes.js.map +1 -0
  45. package/dist/commands/operations.d.ts +18 -0
  46. package/dist/commands/operations.d.ts.map +1 -0
  47. package/dist/commands/operations.js +231 -0
  48. package/dist/commands/operations.js.map +1 -0
  49. package/dist/commands/relationships.d.ts +3 -0
  50. package/dist/commands/relationships.d.ts.map +1 -0
  51. package/dist/commands/relationships.js +94 -0
  52. package/dist/commands/relationships.js.map +1 -0
  53. package/dist/commands/schema.d.ts +12 -0
  54. package/dist/commands/schema.d.ts.map +1 -0
  55. package/dist/commands/schema.js +85 -0
  56. package/dist/commands/schema.js.map +1 -0
  57. package/dist/commands/search.d.ts +3 -0
  58. package/dist/commands/search.d.ts.map +1 -0
  59. package/dist/commands/search.js +57 -0
  60. package/dist/commands/search.js.map +1 -0
  61. package/dist/commands/theme.d.ts +3 -0
  62. package/dist/commands/theme.d.ts.map +1 -0
  63. package/dist/commands/theme.js +184 -0
  64. package/dist/commands/theme.js.map +1 -0
  65. package/dist/commands/timeline.d.ts +3 -0
  66. package/dist/commands/timeline.d.ts.map +1 -0
  67. package/dist/commands/timeline.js +97 -0
  68. package/dist/commands/timeline.js.map +1 -0
  69. package/dist/commands/types.d.ts +3 -0
  70. package/dist/commands/types.d.ts.map +1 -0
  71. package/dist/commands/types.js +139 -0
  72. package/dist/commands/types.js.map +1 -0
  73. package/dist/commands/versions.d.ts +3 -0
  74. package/dist/commands/versions.d.ts.map +1 -0
  75. package/dist/commands/versions.js +120 -0
  76. package/dist/commands/versions.js.map +1 -0
  77. package/dist/commands/workspace.d.ts +13 -0
  78. package/dist/commands/workspace.d.ts.map +1 -0
  79. package/dist/commands/workspace.js +176 -0
  80. package/dist/commands/workspace.js.map +1 -0
  81. package/dist/lib/api-client.d.ts +45 -0
  82. package/dist/lib/api-client.d.ts.map +1 -0
  83. package/dist/lib/api-client.js +198 -0
  84. package/dist/lib/api-client.js.map +1 -0
  85. package/dist/lib/auth-store.d.ts +47 -0
  86. package/dist/lib/auth-store.d.ts.map +1 -0
  87. package/dist/lib/auth-store.js +116 -0
  88. package/dist/lib/auth-store.js.map +1 -0
  89. package/dist/lib/brand.d.ts +32 -0
  90. package/dist/lib/brand.d.ts.map +1 -0
  91. package/dist/lib/brand.js +32 -0
  92. package/dist/lib/brand.js.map +1 -0
  93. package/dist/lib/build-schema.d.ts +97 -0
  94. package/dist/lib/build-schema.d.ts.map +1 -0
  95. package/dist/lib/build-schema.js +139 -0
  96. package/dist/lib/build-schema.js.map +1 -0
  97. package/dist/lib/canvas-read.d.ts +54 -0
  98. package/dist/lib/canvas-read.d.ts.map +1 -0
  99. package/dist/lib/canvas-read.js +145 -0
  100. package/dist/lib/canvas-read.js.map +1 -0
  101. package/dist/lib/claude-session.d.ts +73 -0
  102. package/dist/lib/claude-session.d.ts.map +1 -0
  103. package/dist/lib/claude-session.js +104 -0
  104. package/dist/lib/claude-session.js.map +1 -0
  105. package/dist/lib/config.d.ts +28 -0
  106. package/dist/lib/config.d.ts.map +1 -0
  107. package/dist/lib/config.js +66 -0
  108. package/dist/lib/config.js.map +1 -0
  109. package/dist/lib/env.d.ts +14 -0
  110. package/dist/lib/env.d.ts.map +1 -0
  111. package/dist/lib/env.js +16 -0
  112. package/dist/lib/env.js.map +1 -0
  113. package/dist/lib/errors.d.ts +47 -0
  114. package/dist/lib/errors.d.ts.map +1 -0
  115. package/dist/lib/errors.js +194 -0
  116. package/dist/lib/errors.js.map +1 -0
  117. package/dist/lib/fs-utils.d.ts +2 -0
  118. package/dist/lib/fs-utils.d.ts.map +1 -0
  119. package/dist/lib/fs-utils.js +16 -0
  120. package/dist/lib/fs-utils.js.map +1 -0
  121. package/dist/lib/install-hook.d.ts +86 -0
  122. package/dist/lib/install-hook.d.ts.map +1 -0
  123. package/dist/lib/install-hook.js +168 -0
  124. package/dist/lib/install-hook.js.map +1 -0
  125. package/dist/lib/install-mcp.d.ts +21 -0
  126. package/dist/lib/install-mcp.d.ts.map +1 -0
  127. package/dist/lib/install-mcp.js +133 -0
  128. package/dist/lib/install-mcp.js.map +1 -0
  129. package/dist/lib/install-skill.d.ts +49 -0
  130. package/dist/lib/install-skill.d.ts.map +1 -0
  131. package/dist/lib/install-skill.js +113 -0
  132. package/dist/lib/install-skill.js.map +1 -0
  133. package/dist/lib/output.d.ts +29 -0
  134. package/dist/lib/output.d.ts.map +1 -0
  135. package/dist/lib/output.js +78 -0
  136. package/dist/lib/output.js.map +1 -0
  137. package/dist/lib/resolve-note.d.ts +7 -0
  138. package/dist/lib/resolve-note.d.ts.map +1 -0
  139. package/dist/lib/resolve-note.js +23 -0
  140. package/dist/lib/resolve-note.js.map +1 -0
  141. package/dist/lib/stdin.d.ts +5 -0
  142. package/dist/lib/stdin.d.ts.map +1 -0
  143. package/dist/lib/stdin.js +11 -0
  144. package/dist/lib/stdin.js.map +1 -0
  145. package/dist/lib/style.d.ts +10 -0
  146. package/dist/lib/style.d.ts.map +1 -0
  147. package/dist/lib/style.js +17 -0
  148. package/dist/lib/style.js.map +1 -0
  149. package/dist/lib/themes.d.ts +44 -0
  150. package/dist/lib/themes.d.ts.map +1 -0
  151. package/dist/lib/themes.js +168 -0
  152. package/dist/lib/themes.js.map +1 -0
  153. package/dist/mcp-server.d.ts +3 -0
  154. package/dist/mcp-server.d.ts.map +1 -0
  155. package/dist/mcp-server.js +782 -0
  156. package/dist/mcp-server.js.map +1 -0
  157. package/package.json +66 -0
  158. package/skills/cnotes/SKILL.md +680 -0
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Brand single source of truth for the CLI.
3
+ *
4
+ * This is the CLI-side MIRROR of the app's `lib/brand.ts`. The CLI ships as a
5
+ * separate npm package and cannot import from the Next.js app, so the shared
6
+ * identity is duplicated here. A drift guard in the app
7
+ * (`__tests__/brand.test.ts`) asserts the shared fields below stay in sync with
8
+ * `lib/brand.ts` — update both together.
9
+ *
10
+ * On a rename, changing `configDir` orphans existing logins and changing
11
+ * `packageName` breaks `npx`/global-install updates — so when either moves, ship
12
+ * a migration. `configDir` carries a one-time rename of the old directory on
13
+ * load (see `auth-store.ts`); the old npm package should be deprecated to point
14
+ * at the new one.
15
+ */
16
+ export const BRAND = {
17
+ /** Display name, used in CLI help/banner text. */
18
+ name: "Creator Notes",
19
+ /** Canonical production origin (the published default server). */
20
+ url: "https://creatornotes.app",
21
+ /** Bare domain. */
22
+ domain: "creatornotes.app",
23
+ /** The installed command. */
24
+ command: "cnotes",
25
+ /** Published package name. */
26
+ packageName: "@creator-notes/cnotes",
27
+ /** Config dir under $HOME (holds login tokens). Migrated from the old name on load. */
28
+ configDir: ".cnotes",
29
+ /** Source repo, owner/name form. */
30
+ repo: "creatornotes/pm-notes",
31
+ };
32
+ //# sourceMappingURL=brand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brand.js","sourceRoot":"","sources":["../../src/lib/brand.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,kDAAkD;IAClD,IAAI,EAAE,eAAe;IACrB,kEAAkE;IAClE,GAAG,EAAE,0BAA0B;IAC/B,mBAAmB;IACnB,MAAM,EAAE,kBAAkB;IAC1B,6BAA6B;IAC7B,OAAO,EAAE,QAAQ;IACjB,8BAA8B;IAC9B,WAAW,EAAE,uBAAuB;IACpC,uFAAuF;IACvF,SAAS,EAAE,SAAS;IACpB,oCAAoC;IACpC,IAAI,EAAE,uBAAuB;CACrB,CAAC"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Shared schema builder for `cnotes schema` and the `cn_schema` MCP tool.
3
+ *
4
+ * Returns the things an agent would otherwise have to read SKILL.md or guess
5
+ * at: valid note types (from the current workspace), common relationship
6
+ * slugs, resource field shapes, exit codes, and env vars. One source of truth
7
+ * so the CLI and MCP surfaces never drift.
8
+ */
9
+ import { ApiClient } from "./api-client.js";
10
+ export declare const STATIC_SCHEMA: {
11
+ readonly relationships: {
12
+ readonly note: "Relationship slugs are free-form strings. The values below are common conventions, not an enum — the server accepts any string.";
13
+ readonly common: readonly ["references", "supports", "blocks", "derives_from", "contradicts", "triggers", "related"];
14
+ };
15
+ readonly syntax: {
16
+ readonly noteMention: "[NOTE-12: Title](relationship:references)";
17
+ readonly batchPlaceholder: "[@key: Title](relationship:references) — '@key' is replaced with the new display ID after batch create";
18
+ readonly rules: readonly ["Always include `: Title` after the ID. The title-less form renders as 'Untitled' in the UI.", "Pick a relationship slug that fits; `references` is the safe default."];
19
+ };
20
+ readonly resources: {
21
+ readonly note: {
22
+ readonly fields: {
23
+ readonly id: "Convex ID (string)";
24
+ readonly displayId: "Human-readable ID (e.g. MEETING-12, PRD-3)";
25
+ readonly title: "string";
26
+ readonly type: "string (must match a supertag name from `types`)";
27
+ readonly tags: "string[]";
28
+ readonly isPinned: "boolean";
29
+ readonly isArchived: "boolean";
30
+ readonly updatedAt: "number (unix ms)";
31
+ };
32
+ };
33
+ readonly canvasNode: {
34
+ readonly kinds: readonly ["note", "text", "list", "canvas", "richtext", "link"];
35
+ readonly note: "Use `cnotes canvas place` with the declarative layout DSL whenever you can — it packs items without overlaps so you avoid x/y math.";
36
+ };
37
+ readonly canvasEdge: {
38
+ readonly fields: {
39
+ readonly sourceNodeId: "string";
40
+ readonly targetNodeId: "string";
41
+ readonly label: "string (optional, free-form)";
42
+ readonly lineStyle: "solid | dashed";
43
+ readonly arrow: "end | start | both | none";
44
+ };
45
+ };
46
+ };
47
+ readonly exitCodes: {
48
+ readonly "0": "ok";
49
+ readonly "1": "generic error";
50
+ readonly "2": "auth required (run `cnotes auth login`)";
51
+ readonly "3": "validation (bad input)";
52
+ readonly "4": "not found";
53
+ readonly "5": "conflict (state collision)";
54
+ readonly "6": "rate-limited";
55
+ readonly "7": "permission denied";
56
+ };
57
+ readonly env: {
58
+ readonly CN_SERVER: "Override server URL";
59
+ readonly CN_TOKEN: "Auth token (alternative to `cnotes auth login`)";
60
+ readonly CN_WORKSPACE: "Override workspace ID for this invocation";
61
+ readonly CN_JSON: "Set to 1 to force JSON output";
62
+ readonly CN_AGENT_RUN_ID: "Active agent-run bracket (set by `cnotes canvas agent-run begin/wrap`)";
63
+ readonly CN_AGENT_BEFORE_SNAPSHOT_ID: "Begin-snapshot ID carried with the agent-run";
64
+ };
65
+ readonly agentRun: {
66
+ readonly note: "Wrap multi-step canvas mutations in an agent-run so they show up as one revertable unit in the UI history.";
67
+ readonly wrap: "cnotes canvas agent-run wrap --canvas <id> --prompt \"<intent>\" -- <command>";
68
+ };
69
+ };
70
+ export interface SchemaType {
71
+ name: string;
72
+ prefix: string;
73
+ displayName: string;
74
+ color: string | null;
75
+ isBuiltIn: boolean;
76
+ }
77
+ export interface SchemaFetchError {
78
+ resource: "workspace" | "types";
79
+ error: string;
80
+ }
81
+ export interface BuiltSchema {
82
+ workspace: {
83
+ id: string;
84
+ name: string | null;
85
+ verified: boolean;
86
+ };
87
+ types: SchemaType[];
88
+ dynamicFetchErrors?: SchemaFetchError[];
89
+ }
90
+ /**
91
+ * Build the full schema document. The static metadata (exit codes, syntax,
92
+ * resource shapes) is always present; the dynamic bits (workspace + types)
93
+ * are fetched and any failures are reported in `dynamicFetchErrors` so callers
94
+ * never treat a partial schema as authoritative.
95
+ */
96
+ export declare function buildSchema(api: ApiClient, workspaceId: string): Promise<BuiltSchema & typeof STATIC_SCHEMA>;
97
+ //# sourceMappingURL=build-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-schema.d.ts","sourceRoot":"","sources":["../../src/lib/build-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsEhB,CAAC;AAgBX,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;IAClE,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,kBAAkB,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACzC;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,SAAS,EACd,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,WAAW,GAAG,OAAO,aAAa,CAAC,CAyD7C"}
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Shared schema builder for `cnotes schema` and the `cn_schema` MCP tool.
3
+ *
4
+ * Returns the things an agent would otherwise have to read SKILL.md or guess
5
+ * at: valid note types (from the current workspace), common relationship
6
+ * slugs, resource field shapes, exit codes, and env vars. One source of truth
7
+ * so the CLI and MCP surfaces never drift.
8
+ */
9
+ export const STATIC_SCHEMA = {
10
+ relationships: {
11
+ note: "Relationship slugs are free-form strings. The values below are common conventions, not an enum — the server accepts any string.",
12
+ common: [
13
+ "references",
14
+ "supports",
15
+ "blocks",
16
+ "derives_from",
17
+ "contradicts",
18
+ "triggers",
19
+ "related",
20
+ ],
21
+ },
22
+ syntax: {
23
+ noteMention: "[NOTE-12: Title](relationship:references)",
24
+ batchPlaceholder: "[@key: Title](relationship:references) — '@key' is replaced with the new display ID after batch create",
25
+ rules: [
26
+ "Always include `: Title` after the ID. The title-less form renders as 'Untitled' in the UI.",
27
+ "Pick a relationship slug that fits; `references` is the safe default.",
28
+ ],
29
+ },
30
+ resources: {
31
+ note: {
32
+ fields: {
33
+ id: "Convex ID (string)",
34
+ displayId: "Human-readable ID (e.g. MEETING-12, PRD-3)",
35
+ title: "string",
36
+ type: "string (must match a supertag name from `types`)",
37
+ tags: "string[]",
38
+ isPinned: "boolean",
39
+ isArchived: "boolean",
40
+ updatedAt: "number (unix ms)",
41
+ },
42
+ },
43
+ canvasNode: {
44
+ kinds: ["note", "text", "list", "canvas", "richtext", "link"],
45
+ note: "Use `cnotes canvas place` with the declarative layout DSL whenever you can — it packs items without overlaps so you avoid x/y math.",
46
+ },
47
+ canvasEdge: {
48
+ fields: {
49
+ sourceNodeId: "string",
50
+ targetNodeId: "string",
51
+ label: "string (optional, free-form)",
52
+ lineStyle: "solid | dashed",
53
+ arrow: "end | start | both | none",
54
+ },
55
+ },
56
+ },
57
+ exitCodes: {
58
+ "0": "ok",
59
+ "1": "generic error",
60
+ "2": "auth required (run `cnotes auth login`)",
61
+ "3": "validation (bad input)",
62
+ "4": "not found",
63
+ "5": "conflict (state collision)",
64
+ "6": "rate-limited",
65
+ "7": "permission denied",
66
+ },
67
+ env: {
68
+ CN_SERVER: "Override server URL",
69
+ CN_TOKEN: "Auth token (alternative to `cnotes auth login`)",
70
+ CN_WORKSPACE: "Override workspace ID for this invocation",
71
+ CN_JSON: "Set to 1 to force JSON output",
72
+ CN_AGENT_RUN_ID: "Active agent-run bracket (set by `cnotes canvas agent-run begin/wrap`)",
73
+ CN_AGENT_BEFORE_SNAPSHOT_ID: "Begin-snapshot ID carried with the agent-run",
74
+ },
75
+ agentRun: {
76
+ note: "Wrap multi-step canvas mutations in an agent-run so they show up as one revertable unit in the UI history.",
77
+ wrap: "cnotes canvas agent-run wrap --canvas <id> --prompt \"<intent>\" -- <command>",
78
+ },
79
+ };
80
+ /**
81
+ * Build the full schema document. The static metadata (exit codes, syntax,
82
+ * resource shapes) is always present; the dynamic bits (workspace + types)
83
+ * are fetched and any failures are reported in `dynamicFetchErrors` so callers
84
+ * never treat a partial schema as authoritative.
85
+ */
86
+ export async function buildSchema(api, workspaceId) {
87
+ const dynamicFetchErrors = [];
88
+ const [workspaceData, supertags] = await Promise.all([
89
+ api
90
+ .get(`/api/workspaces/${workspaceId}`)
91
+ .catch((err) => {
92
+ dynamicFetchErrors.push({
93
+ resource: "workspace",
94
+ error: err instanceof Error ? err.message : String(err),
95
+ });
96
+ return null;
97
+ }),
98
+ api
99
+ .get("/api/supertags", { workspaceId })
100
+ .catch((err) => {
101
+ dynamicFetchErrors.push({
102
+ resource: "types",
103
+ error: err instanceof Error ? err.message : String(err),
104
+ });
105
+ return [];
106
+ }),
107
+ ]);
108
+ const workspaceRecord = workspaceData
109
+ ? (workspaceData.workspace ??
110
+ workspaceData)
111
+ : null;
112
+ const types = (Array.isArray(supertags) ? supertags : []).map((s) => ({
113
+ name: s.name ?? "",
114
+ prefix: s.prefix ?? "",
115
+ displayName: s.displayName ?? s.name ?? "",
116
+ color: s.color ?? null,
117
+ isBuiltIn: !!s.isBuiltIn,
118
+ }));
119
+ const workspaceFailed = dynamicFetchErrors.some((e) => e.resource === "workspace");
120
+ return {
121
+ workspace: workspaceRecord
122
+ ? {
123
+ id: String(workspaceRecord._id ?? workspaceRecord.id ?? workspaceId),
124
+ name: workspaceRecord.name ?? null,
125
+ verified: true,
126
+ }
127
+ : {
128
+ id: workspaceId,
129
+ name: null,
130
+ // Surface that we couldn't confirm this ID with the server, so an
131
+ // agent doesn't trust it for downstream lookups.
132
+ verified: !workspaceFailed,
133
+ },
134
+ types,
135
+ ...(dynamicFetchErrors.length > 0 ? { dynamicFetchErrors } : {}),
136
+ ...STATIC_SCHEMA,
137
+ };
138
+ }
139
+ //# sourceMappingURL=build-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-schema.js","sourceRoot":"","sources":["../../src/lib/build-schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Shared helper for `cnotes canvas read` and the `cn_canvas_read` MCP tool.
3
+ *
4
+ * Fetches a canvas + its referenced notes (one bulk call, never N+1) and
5
+ * returns a list of "renderable" elements ordered top-to-bottom,
6
+ * left-to-right with a small Y tolerance so visually-aligned rows stay
7
+ * together. Heuristic, not a layout-aware sort — fine for a "thinking
8
+ * aid" but not authoritative.
9
+ */
10
+ import type { ApiClient } from "./api-client.js";
11
+ export type CanvasPos = {
12
+ positionX?: number;
13
+ positionY?: number;
14
+ };
15
+ export type CanvasElement = {
16
+ kind: "note";
17
+ pos: CanvasPos;
18
+ displayId: string;
19
+ title: string;
20
+ type: string;
21
+ markdown: string;
22
+ } | {
23
+ kind: "text";
24
+ pos: CanvasPos;
25
+ text: string;
26
+ headingSize?: string;
27
+ } | {
28
+ kind: "richtext";
29
+ pos: CanvasPos;
30
+ markdown: string;
31
+ } | {
32
+ kind: "list";
33
+ pos: CanvasPos;
34
+ title: string;
35
+ items: Array<{
36
+ displayId?: string;
37
+ title?: string;
38
+ type?: string;
39
+ }>;
40
+ };
41
+ export interface CanvasReadResult {
42
+ canvas: Record<string, unknown> | {
43
+ id: string;
44
+ };
45
+ elements: CanvasElement[];
46
+ }
47
+ export declare function readCanvasMarkdown(api: ApiClient, workspaceId: string | undefined, canvasId: string): Promise<CanvasReadResult>;
48
+ /**
49
+ * Render a CanvasReadResult as a single concatenated markdown document.
50
+ * Used by the CLI's text output mode; the MCP tool returns the structured
51
+ * form directly so the model can do its own rendering if needed.
52
+ */
53
+ export declare function renderCanvasMarkdown(result: CanvasReadResult): string;
54
+ //# sourceMappingURL=canvas-read.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvas-read.d.ts","sourceRoot":"","sources":["../../src/lib/canvas-read.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,MAAM,MAAM,SAAS,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnE,MAAM,MAAM,aAAa,GACrB;IACE,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,SAAS,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB,GACD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACpE;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACtD;IACE,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,SAAS,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACrE,CAAC;AAEN,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AAID,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,SAAS,EACd,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,gBAAgB,CAAC,CA0G3B;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CA6BrE"}
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Shared helper for `cnotes canvas read` and the `cn_canvas_read` MCP tool.
3
+ *
4
+ * Fetches a canvas + its referenced notes (one bulk call, never N+1) and
5
+ * returns a list of "renderable" elements ordered top-to-bottom,
6
+ * left-to-right with a small Y tolerance so visually-aligned rows stay
7
+ * together. Heuristic, not a layout-aware sort — fine for a "thinking
8
+ * aid" but not authoritative.
9
+ */
10
+ const ROW_TOLERANCE = 80;
11
+ export async function readCanvasMarkdown(api, workspaceId, canvasId) {
12
+ const data = await api.get(`/api/canvas/${encodeURIComponent(canvasId)}`, { workspaceId, format: "markdown" });
13
+ const nodes = data.nodes || [];
14
+ const textNodes = data.textNodes || [];
15
+ const richtextNodes = data.richtextNodes || [];
16
+ const listNodes = data.listNodes || [];
17
+ const wantedDisplayIds = new Set();
18
+ for (const n of nodes) {
19
+ const note = n.note;
20
+ const id = note?.displayId;
21
+ if (typeof id === "string")
22
+ wantedDisplayIds.add(id);
23
+ }
24
+ const idsArr = Array.from(wantedDisplayIds);
25
+ const bulk = idsArr.length === 0
26
+ ? []
27
+ : await api.get("/api/notes", {
28
+ workspaceId,
29
+ exact_ids: idsArr.join(","),
30
+ format: "markdown",
31
+ });
32
+ const markdownByDisplayId = new Map();
33
+ for (const n of bulk) {
34
+ const id = n.displayId;
35
+ const md = n.latestVersion?.content ?? n.content;
36
+ if (typeof id === "string" && typeof md === "string") {
37
+ markdownByDisplayId.set(id, md);
38
+ }
39
+ }
40
+ const elements = [];
41
+ for (const n of nodes) {
42
+ const note = n.note;
43
+ const displayId = note?.displayId;
44
+ if (!displayId)
45
+ continue;
46
+ elements.push({
47
+ kind: "note",
48
+ pos: {
49
+ positionX: n.positionX,
50
+ positionY: n.positionY,
51
+ },
52
+ displayId,
53
+ title: note?.title || "(untitled)",
54
+ type: note?.type || "Note",
55
+ markdown: markdownByDisplayId.get(displayId) ?? "",
56
+ });
57
+ }
58
+ for (const t of textNodes) {
59
+ elements.push({
60
+ kind: "text",
61
+ pos: {
62
+ positionX: t.positionX,
63
+ positionY: t.positionY,
64
+ },
65
+ text: String(t.text || ""),
66
+ headingSize: t.headingSize,
67
+ });
68
+ }
69
+ for (const r of richtextNodes) {
70
+ elements.push({
71
+ kind: "richtext",
72
+ pos: {
73
+ positionX: r.positionX,
74
+ positionY: r.positionY,
75
+ },
76
+ markdown: typeof r.content === "string" ? r.content : "",
77
+ });
78
+ }
79
+ for (const l of listNodes) {
80
+ const items = l.items || [];
81
+ elements.push({
82
+ kind: "list",
83
+ pos: {
84
+ positionX: l.positionX,
85
+ positionY: l.positionY,
86
+ },
87
+ title: String(l.title || "List"),
88
+ items: items.map((it) => {
89
+ const note = it.note;
90
+ return {
91
+ displayId: note?.displayId,
92
+ title: note?.title,
93
+ type: note?.type,
94
+ };
95
+ }),
96
+ });
97
+ }
98
+ elements.sort((a, b) => {
99
+ const ay = a.pos.positionY ?? 0;
100
+ const by = b.pos.positionY ?? 0;
101
+ if (Math.abs(ay - by) > ROW_TOLERANCE)
102
+ return ay - by;
103
+ return (a.pos.positionX ?? 0) - (b.pos.positionX ?? 0);
104
+ });
105
+ return {
106
+ canvas: data.canvas ?? { id: canvasId },
107
+ elements,
108
+ };
109
+ }
110
+ /**
111
+ * Render a CanvasReadResult as a single concatenated markdown document.
112
+ * Used by the CLI's text output mode; the MCP tool returns the structured
113
+ * form directly so the model can do its own rendering if needed.
114
+ */
115
+ export function renderCanvasMarkdown(result) {
116
+ const canvas = result.canvas;
117
+ const canvasName = canvas?.title || canvas?.name || "(unnamed)";
118
+ const lines = [`# Canvas: ${canvasName}`, ""];
119
+ for (const r of result.elements) {
120
+ if (r.kind === "note") {
121
+ lines.push(`## ${r.displayId}: ${r.title}`, `*${r.type}*`, "");
122
+ if (r.markdown)
123
+ lines.push(r.markdown.trim(), "");
124
+ }
125
+ else if (r.kind === "text") {
126
+ const prefix = r.headingSize === "h1" ? "# " : r.headingSize === "h2" ? "## " : "### ";
127
+ lines.push(`${prefix}${r.text}`, "");
128
+ }
129
+ else if (r.kind === "richtext") {
130
+ if (r.markdown)
131
+ lines.push(r.markdown.trim(), "");
132
+ }
133
+ else if (r.kind === "list") {
134
+ lines.push(`## List: ${r.title}`, "");
135
+ for (const it of r.items) {
136
+ if (it.displayId) {
137
+ lines.push(`- [${it.displayId}: ${it.title ?? ""}](relationship:references)`);
138
+ }
139
+ }
140
+ lines.push("");
141
+ }
142
+ }
143
+ return lines.join("\n");
144
+ }
145
+ //# sourceMappingURL=canvas-read.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvas-read.js","sourceRoot":"","sources":["../../src/lib/canvas-read.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ export interface AgentSession {
2
+ /** Namespaces `id`. Today only "claude-code" (resumable via
3
+ * `claude --resume <id>`); other agent runtimes can opt in later. */
4
+ kind: string;
5
+ /** The conversation/session id to resume. */
6
+ id: string;
7
+ }
8
+ /**
9
+ * Where `cnotes claude-hook` (a Claude Code SessionStart hook) persists the
10
+ * current session id. A single "latest" file — simple and correct for the
11
+ * common one-session-per-machine case. Concurrent Claude Code sessions on the
12
+ * same machine would clobber it; set CNOTES_AGENT_SESSION_ID to disambiguate.
13
+ */
14
+ export declare const CLAUDE_SESSION_FILE: string;
15
+ /**
16
+ * How long a hook-captured session stays trustworthy as "the agent driving
17
+ * this cnotes run". The SessionStart hook stamps `updatedAt` when the session is
18
+ * (re)opened, but there's no heartbeat — so this is age-since-opened, not
19
+ * since-last-activity. A generous window keeps long-running sessions valid
20
+ * while stopping a file left behind by a session that ended days ago from
21
+ * stamping a later, unrelated run.
22
+ */
23
+ export declare const SESSION_FILE_MAX_AGE_MS: number;
24
+ interface StoredSession {
25
+ id: string;
26
+ kind?: string;
27
+ cwd?: string;
28
+ updatedAt?: number;
29
+ }
30
+ /**
31
+ * Decide whether a stored hook session is still a trustworthy stand-in for
32
+ * "the agent driving THIS cnotes run". Pure (takes `now` + `cwd` rather than
33
+ * reading them) so the rules stay easy to reason about:
34
+ *
35
+ * - Must carry an `id` — the only thing we can actually resume.
36
+ * - Not older than {@link SESSION_FILE_MAX_AGE_MS} — a stale file left after
37
+ * a session ended must not stamp a later run as if that chat drove it.
38
+ * - If the file recorded the session's `cwd`, the current directory must sit
39
+ * inside that subtree — a cnotes run in a *different* project isn't this
40
+ * session's work. (No recorded cwd → can't scope, so we don't reject on
41
+ * that basis.)
42
+ *
43
+ * Erring toward rejection is the safe bias here: a false negative just drops
44
+ * the (optional) resume affordance, whereas a false positive mislabels the
45
+ * run's provenance and offers a resume to the wrong chat.
46
+ */
47
+ export declare function isStoredSessionUsable(stored: StoredSession, ctx: {
48
+ now: number;
49
+ cwd: string;
50
+ }): boolean;
51
+ /**
52
+ * Resolve the agent conversation/session driving the current cnotes run, so
53
+ * `cnotes operations begin` can stamp it on the operation row (making the run
54
+ * traceable + resumable from the timeline). Resolution order, most explicit
55
+ * first:
56
+ *
57
+ * 1. CN_AGENT_SESSION_ID (+ optional CN_AGENT_SESSION_KIND) — explicit
58
+ * override, wins everything. Lets any agent runtime opt in by hand.
59
+ * 2. The SessionStart-hook file written by `cnotes claude-hook`, when it's still
60
+ * fresh + scoped to this directory (see {@link isStoredSessionUsable}).
61
+ * This is the Claude Code TOP-LEVEL session id, captured once when the
62
+ * session starts — the most correct value to resume (a subagent's own
63
+ * bash would otherwise report the subagent's id via the env var below).
64
+ * 3. CLAUDE_CODE_SESSION_ID — Claude Code's per-process env var. Zero-config
65
+ * but undocumented; best-effort fallback when no hook is installed. It's
66
+ * the live process's own env, so no staleness check applies.
67
+ *
68
+ * Returns null when nothing is known (e.g. cnotes run outside any agent), in which
69
+ * case the run simply isn't session-stamped — no error.
70
+ */
71
+ export declare function resolveAgentSession(): AgentSession | null;
72
+ export {};
73
+ //# sourceMappingURL=claude-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-session.d.ts","sourceRoot":"","sources":["../../src/lib/claude-session.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,YAAY;IAC3B;0EACsE;IACtE,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,QAI/B,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,QAAsB,CAAC;AAE3D,UAAU,aAAa;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,aAAa,EACrB,GAAG,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAChC,OAAO,CAUT;AAQD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,mBAAmB,IAAI,YAAY,GAAG,IAAI,CAgBzD"}