rootr-cli 0.4.0 → 0.5.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.
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
2
 
3
- import { jsonResult, errorResult, makeClient, requireWorkspace } from './shared.js';
3
+ import { jsonResult, errorResult, makeClient, requireWorkspace, resolveNodeId, NODE_TARGET_HINT, resolveOptionalNodeId } from './shared.js';
4
4
 
5
5
  const CELL_VALUE = z
6
6
  .union([z.string(), z.number(), z.boolean(), z.null()])
@@ -32,7 +32,7 @@ export function registerSpreadsheetTools(server) {
32
32
  annotations: { readOnlyHint: false, destructiveHint: false },
33
33
  inputSchema: {
34
34
  name: z.string().optional().describe('Spreadsheet name/title'),
35
- parentId: z.string().optional().describe('Parent folder/node id to create it under'),
35
+ parentId: z.string().optional().describe(`Parent folder/node id${NODE_TARGET_HINT}`),
36
36
  icon: z.string().optional().describe('Emoji icon for the node'),
37
37
  data: z
38
38
  .object({ sheets: z.array(z.record(z.unknown())).optional() })
@@ -46,6 +46,7 @@ export function registerSpreadsheetTools(server) {
46
46
  try {
47
47
  const ws = requireWorkspace(workspace);
48
48
  const client = makeClient(ws);
49
+ parentId = await resolveOptionalNodeId(client, parentId);
49
50
  const result = await client.createSpreadsheet(ws, { name, parentId, icon, data, config });
50
51
  return jsonResult(result);
51
52
  } catch (err) {
@@ -64,12 +65,13 @@ export function registerSpreadsheetTools(server) {
64
65
  'and cell contents.',
65
66
  annotations: { readOnlyHint: true, destructiveHint: false },
66
67
  inputSchema: {
67
- spreadsheetId: z.string().describe('SPREADSHEET node id'),
68
+ spreadsheetId: z.string().describe(`SPREADSHEET node id${NODE_TARGET_HINT}`),
68
69
  },
69
70
  },
70
71
  async ({ spreadsheetId }) => {
71
72
  try {
72
73
  const client = makeClient();
74
+ spreadsheetId = await resolveNodeId(client, spreadsheetId);
73
75
  const result = await client.getSpreadsheet(spreadsheetId);
74
76
  return jsonResult(result);
75
77
  } catch (err) {
@@ -88,7 +90,7 @@ export function registerSpreadsheetTools(server) {
88
90
  'you want to keep, or prefer rootr_create_sheet / rootr_patch_spreadsheet_cells for incremental changes).',
89
91
  annotations: { readOnlyHint: false, destructiveHint: false },
90
92
  inputSchema: {
91
- spreadsheetId: z.string().describe('SPREADSHEET node id'),
93
+ spreadsheetId: z.string().describe(`SPREADSHEET node id${NODE_TARGET_HINT}`),
92
94
  sheets: z
93
95
  .array(z.record(z.unknown()))
94
96
  .optional()
@@ -100,6 +102,7 @@ export function registerSpreadsheetTools(server) {
100
102
  async ({ spreadsheetId, sheets, config, icon }) => {
101
103
  try {
102
104
  const client = makeClient();
105
+ spreadsheetId = await resolveNodeId(client, spreadsheetId);
103
106
  const result = await client.updateSpreadsheet(spreadsheetId, { sheets, config, icon });
104
107
  return jsonResult(result);
105
108
  } catch (err) {
@@ -115,7 +118,7 @@ export function registerSpreadsheetTools(server) {
115
118
  description: 'Add a new empty sheet (tab) to an existing Rootr (루터) SPREADSHEET, without touching other sheets.',
116
119
  annotations: { readOnlyHint: false, destructiveHint: false },
117
120
  inputSchema: {
118
- spreadsheetId: z.string().describe('SPREADSHEET node id'),
121
+ spreadsheetId: z.string().describe(`SPREADSHEET node id${NODE_TARGET_HINT}`),
119
122
  name: z.string().optional().describe('Sheet name, e.g. "Q1 Budget"'),
120
123
  rowCount: z.number().int().min(1).max(10_000).optional().describe('Row count (default 1000)'),
121
124
  colCount: z.number().int().min(1).max(500).optional().describe('Column count (default 52)'),
@@ -124,6 +127,7 @@ export function registerSpreadsheetTools(server) {
124
127
  async ({ spreadsheetId, name, rowCount, colCount }) => {
125
128
  try {
126
129
  const client = makeClient();
130
+ spreadsheetId = await resolveNodeId(client, spreadsheetId);
127
131
  const result = await client.createSheet(spreadsheetId, { name, rowCount, colCount });
128
132
  return jsonResult(result);
129
133
  } catch (err) {
@@ -141,7 +145,7 @@ export function registerSpreadsheetTools(server) {
141
145
  'Call rootr_read_spreadsheet first to get the exact sheetId.',
142
146
  annotations: { readOnlyHint: false, destructiveHint: false },
143
147
  inputSchema: {
144
- spreadsheetId: z.string().describe('SPREADSHEET node id'),
148
+ spreadsheetId: z.string().describe(`SPREADSHEET node id${NODE_TARGET_HINT}`),
145
149
  sheetId: z.string().describe('Sheet id to update'),
146
150
  name: z.string().optional().describe('New sheet name'),
147
151
  rowCount: z.number().int().min(1).max(10_000).optional(),
@@ -157,6 +161,7 @@ export function registerSpreadsheetTools(server) {
157
161
  async ({ spreadsheetId, sheetId, name, rowCount, colCount, rowSizes, colSizes, merges }) => {
158
162
  try {
159
163
  const client = makeClient();
164
+ spreadsheetId = await resolveNodeId(client, spreadsheetId);
160
165
  const result = await client.patchSheet(spreadsheetId, sheetId, {
161
166
  name,
162
167
  rowCount,
@@ -179,13 +184,14 @@ export function registerSpreadsheetTools(server) {
179
184
  description: 'Delete one sheet (tab) from a Rootr (루터) SPREADSHEET by sheetId. Not recoverable — read first to confirm.',
180
185
  annotations: { readOnlyHint: false, destructiveHint: true },
181
186
  inputSchema: {
182
- spreadsheetId: z.string().describe('SPREADSHEET node id'),
187
+ spreadsheetId: z.string().describe(`SPREADSHEET node id${NODE_TARGET_HINT}`),
183
188
  sheetId: z.string().describe('Sheet id to delete'),
184
189
  },
185
190
  },
186
191
  async ({ spreadsheetId, sheetId }) => {
187
192
  try {
188
193
  const client = makeClient();
194
+ spreadsheetId = await resolveNodeId(client, spreadsheetId);
189
195
  await client.deleteSheet(spreadsheetId, sheetId);
190
196
  return jsonResult({ deleted: sheetId });
191
197
  } catch (err) {
@@ -204,7 +210,7 @@ export function registerSpreadsheetTools(server) {
204
210
  CELLS_GUIDE,
205
211
  annotations: { readOnlyHint: false, destructiveHint: false },
206
212
  inputSchema: {
207
- spreadsheetId: z.string().describe('SPREADSHEET node id'),
213
+ spreadsheetId: z.string().describe(`SPREADSHEET node id${NODE_TARGET_HINT}`),
208
214
  sheetId: z.string().describe('Sheet id to patch'),
209
215
  cells: z
210
216
  .record(cellShape.nullable())
@@ -214,6 +220,7 @@ export function registerSpreadsheetTools(server) {
214
220
  async ({ spreadsheetId, sheetId, cells }) => {
215
221
  try {
216
222
  const client = makeClient();
223
+ spreadsheetId = await resolveNodeId(client, spreadsheetId);
217
224
  const result = await client.patchCells(spreadsheetId, sheetId, cells);
218
225
  return jsonResult(result);
219
226
  } catch (err) {
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
2
 
3
- import { jsonResult, errorResult, makeClient, requireWorkspace } from './shared.js';
3
+ import { jsonResult, errorResult, makeClient, requireWorkspace, resolveOptionalNodeId, NODE_TARGET_HINT } from './shared.js';
4
4
 
5
5
  const VALID_EVENTS = [
6
6
  'document.created',
@@ -60,7 +60,7 @@ export function registerWebhookTools(server) {
60
60
  url: z.string().describe('HTTPS endpoint to receive webhook POSTs'),
61
61
  events: z.array(z.string()).describe(`Event names to subscribe to, from: ${VALID_EVENTS.join(', ')}`),
62
62
  name: z.string().optional().describe('Human-readable name for the webhook'),
63
- scopeNodeId: z.string().optional().describe('Restrict to this node and its descendants'),
63
+ scopeNodeId: z.string().optional().describe(`Node id${NODE_TARGET_HINT} — restrict to this node and its descendants`),
64
64
  filterTags: z.array(z.string()).optional().describe('Only fire for nodes carrying one of these tags'),
65
65
  debounceSeconds: z.number().optional().describe('Trailing debounce window in seconds (server-capped)'),
66
66
  workspace: z
@@ -73,6 +73,7 @@ export function registerWebhookTools(server) {
73
73
  try {
74
74
  const ws = requireWorkspace(workspace);
75
75
  const client = makeClient(ws);
76
+ scopeNodeId = await resolveOptionalNodeId(client, scopeNodeId);
76
77
  const result = await client.createWebhook(ws, {
77
78
  name,
78
79
  url,
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
2
 
3
- import { jsonResult, errorResult, makeClient, requireWorkspace } from './shared.js';
3
+ import { jsonResult, errorResult, makeClient, requireWorkspace, resolveNodeId, NODE_TARGET_HINT, resolveOptionalNodeId } from './shared.js';
4
4
 
5
5
  const shapeShape = z
6
6
  .object({
@@ -67,7 +67,7 @@ export function registerWhiteboardTools(server) {
67
67
  annotations: { readOnlyHint: false, destructiveHint: false },
68
68
  inputSchema: {
69
69
  name: z.string().optional().describe('Whiteboard name/title'),
70
- parentId: z.string().optional().describe('Parent folder/node id to create it under'),
70
+ parentId: z.string().optional().describe(`Parent folder/node id${NODE_TARGET_HINT}`),
71
71
  icon: z.string().optional().describe('Emoji icon for the node'),
72
72
  scene: z
73
73
  .union([sceneShape, excalidrawSceneShape])
@@ -81,6 +81,7 @@ export function registerWhiteboardTools(server) {
81
81
  try {
82
82
  const ws = requireWorkspace(workspace);
83
83
  const client = makeClient(ws);
84
+ parentId = await resolveOptionalNodeId(client, parentId);
84
85
  const result = await client.createWhiteboard(ws, { name, parentId, icon, scene, config });
85
86
  return jsonResult(result);
86
87
  } catch (err) {
@@ -101,13 +102,14 @@ export function registerWhiteboardTools(server) {
101
102
  'the current ids.',
102
103
  annotations: { readOnlyHint: true, destructiveHint: false },
103
104
  inputSchema: {
104
- whiteboardId: z.string().describe('WHITEBOARD node id'),
105
+ whiteboardId: z.string().describe(`WHITEBOARD node id${NODE_TARGET_HINT}`),
105
106
  mode: z.enum(['summary', 'full']).optional().describe('"summary" (default) or "full" (raw elements too)'),
106
107
  },
107
108
  },
108
109
  async ({ whiteboardId, mode }) => {
109
110
  try {
110
111
  const client = makeClient();
112
+ whiteboardId = await resolveNodeId(client, whiteboardId);
111
113
  const result = await client.getWhiteboard(whiteboardId);
112
114
  const { scene, ...rest } = result ?? {};
113
115
  if (mode !== 'full') return jsonResult(rest);
@@ -139,7 +141,7 @@ export function registerWhiteboardTools(server) {
139
141
  AUTHORING_GUIDE,
140
142
  annotations: { readOnlyHint: false, destructiveHint: false },
141
143
  inputSchema: {
142
- whiteboardId: z.string().describe('WHITEBOARD node id'),
144
+ whiteboardId: z.string().describe(`WHITEBOARD node id${NODE_TARGET_HINT}`),
143
145
  scene: z
144
146
  .union([sceneShape, excalidrawSceneShape])
145
147
  .optional()
@@ -155,6 +157,7 @@ export function registerWhiteboardTools(server) {
155
157
  async ({ whiteboardId, scene, merge, config, icon }) => {
156
158
  try {
157
159
  const client = makeClient();
160
+ whiteboardId = await resolveNodeId(client, whiteboardId);
158
161
  const result = await client.updateWhiteboard(whiteboardId, { scene, merge, config, icon });
159
162
  const { scene: _scene, ...rest } = result ?? {};
160
163
  return jsonResult(rest);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rootr-cli",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Official Rootr CLI + MCP server — read, write, edit and search Rootr documents from the shell or from an AI agent.",
5
5
  "type": "module",
6
6
  "bin": {