@nestr/mcp 0.1.90 → 0.1.92

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 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAmC,KAAK,WAAW,EAA6C,MAAM,kBAAkB,CAAC;AAIhI,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAO5D,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAIhD,CAAC;AAKH,eAAO,MAAM,eAAe;;;;;CAKlB,CAAC;AAQX,KAAK,iBAAiB,GAAG,OAAO,GAAG,YAAY,GAAG,UAAU,GAAG,UAAU,GAAG,QAAQ,CAAC;AAGrF,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,iBAAiB,EACzB,KAAK,EAAE,MAAM,GACZ;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,iBAAiB,CAAC;IAAC,KAAK,EAAE,OAAO,EAAE,CAAA;CAAE,CAWhE;AAeD,wBAAgB,eAAe,CAAC,CAAC,EAC/B,IAAI,EAAE,CAAC,EAAE,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,CAAC,EAAE,CAAA;CAAE,GAAG,CAAC,EAC7D,IAAI,GAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAgB,GAChD,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAA;CAAE,GAAG,CAAC,CA+B3E;AA+CD;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACxC;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAwGD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,eAAe,GAAG,gBAAgB,GAAG,IAAI,CA2CpF;AAID,wBAAgB,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,CA6DzC;AA6BD,wBAAgB,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,CAqBzC;AAyCD,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+cnB,CAAC;AAQF,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAilC3B,CAAC;AAGF,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE,KAAK,CACV;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAC9B;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CACpD,CAAC;IACF,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAGF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAiB7D;AAgBD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAgB7F;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAuBxF;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,WAAW,CAAC,EAAE,MAAM,gBAAgB,CAAC;IACrC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAsB,cAAc,CAClC,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,UAAU,CAAC,CAkBrB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmhBnB,CAAC;AAQF,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAyvC3B,CAAC;AAGF,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE,KAAK,CACV;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAC9B;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CACpD,CAAC;IACF,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAGF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAiB7D;AAgBD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAgB7F;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAuBxF;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,WAAW,CAAC,EAAE,MAAM,gBAAgB,CAAC;IACrC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAsB,cAAc,CAClC,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,UAAU,CAAC,CAkBrB"}
@@ -123,11 +123,31 @@ const HINT_URL_PATTERNS = [
123
123
  },
124
124
  // /nests/{id}/posts → nestr_get_comments
125
125
  { pattern: /^\/nests\/([^/]+)\/posts$/, tool: "nestr_get_comments", params: (m) => ({ nestId: m[1] }) },
126
+ // /nests/{id}/files → nestr_get_nest_files
127
+ { pattern: /^\/nests\/([^/]+)\/files$/, tool: "nestr_get_nest_files", params: (m) => ({ nestId: m[1] }) },
126
128
  // /nests/{id}/tensions → nestr_list_tensions
127
129
  { pattern: /^\/nests\/([^/]+)\/tensions$/, tool: "nestr_list_tensions", params: (m) => ({ nestId: m[1] }) },
128
130
  // /nests/{id} → nestr_get_nest (must be last — catches all /nests/{id} patterns)
129
131
  { pattern: /^\/nests\/([^/]+)$/, tool: "nestr_get_nest", params: (m) => ({ nestId: m[1] }) },
130
132
  ];
133
+ const HINT_TYPE_TOOL_CALLS = {
134
+ no_strategy(nest) {
135
+ const nestId = nest._id;
136
+ if (!nestId)
137
+ return null;
138
+ const labels = nest.labels || [];
139
+ const isAnchorCircle = labels.includes("circleplus-anchor-circle")
140
+ || labels.includes("anchor-circle");
141
+ const fieldKey = isAnchorCircle ? "anchor-circle.strategy" : "circle.strategy";
142
+ return {
143
+ tool: "nestr_update_nest",
144
+ params: {
145
+ nestId,
146
+ fields: { [fieldKey]: "<strategy statement — what this circle prioritises now vs. defers>" },
147
+ },
148
+ };
149
+ },
150
+ };
131
151
  const HINT_ENDPOINT_TOOL_MAPPINGS = [
132
152
  {
133
153
  method: "POST",
@@ -262,9 +282,17 @@ export function enrichHints(data) {
262
282
  const workspaceId = ancestors?.length ? ancestors[ancestors.length - 1] : undefined;
263
283
  record.hints = record.hints.map((hint) => {
264
284
  const enriched = { ...hint };
265
- // Legacy: single URL toolCall. Kept for backwards compatibility with
266
- // hints that pre-date the endpoints[] payload.
267
- if (hint.url) {
285
+ // Type-based overrides win over URL matching for hints whose URL is
286
+ // just the nest itself (`/nests/{id}` → nestr_get_nest) and doesn't
287
+ // point at the actionable follow-up. Registered in HINT_TYPE_TOOL_CALLS.
288
+ const typeOverride = HINT_TYPE_TOOL_CALLS[hint.type];
289
+ const overrideCall = typeOverride ? typeOverride(record) : null;
290
+ if (overrideCall) {
291
+ enriched.toolCall = overrideCall;
292
+ }
293
+ else if (hint.url) {
294
+ // Legacy: single URL → toolCall. Kept for backwards compatibility with
295
+ // hints that pre-date the endpoints[] payload.
268
296
  let rawUrl = hint.url;
269
297
  const apiPrefixMatch = rawUrl.match(/^https?:\/\/[^/]+\/api(\/.*)/);
270
298
  if (apiPrefixMatch)
@@ -421,6 +449,15 @@ export const schemas = {
421
449
  nestId: z.string().describe("Nest ID. Supports comma-separated IDs to fetch multiple nests in one call (e.g., 'id1,id2,id3') — returns an array instead of a single object. Keep total URL under 2000 chars to avoid HTTP limits."),
422
450
  fieldsMetaData: z.boolean().optional().describe("Set to true to include field schema metadata (e.g., available options for project.status)"),
423
451
  hints: z.boolean().optional().describe("Include contextual hints on each nest (default: true). Hints surface actionable signals like unassigned roles, stale projects, or unread comments. Set to false for bulk lookups where you only need structural data, not contextual guidance."),
452
+ provenance: z.boolean().optional().describe("Single-nest only. Include field/property provenance: which label (and circle context) defines each field and property."),
453
+ rights: z.boolean().optional().describe("Single-nest only. Include the caller's composed rights on the nest plus a deny trace naming the profiles that block each op."),
454
+ forUser: z.string().optional().describe("Single-nest only, with rights=true. Report rights for this user id instead of the caller. Requires the caller to be an admin of the nest."),
455
+ whoCan: z.string().optional().describe("Single-nest only. Comma-separated ops (read,update,delete,create) to list who can perform each on this nest."),
456
+ }),
457
+ explainNest: z.object({
458
+ nestId: z.string().describe("The nest to diagnose (a single id)."),
459
+ forUser: z.string().optional().describe("Diagnose rights for this user id instead of the caller. Requires the caller to be an admin of the nest."),
460
+ whoCan: z.string().optional().describe("Comma-separated ops (read,update,delete,create) to also list who can perform each on this nest."),
424
461
  }),
425
462
  getNestChildren: z.object({
426
463
  nestId: z.string().describe("Parent nest ID"),
@@ -620,6 +657,16 @@ export const schemas = {
620
657
  getMe: z.object({
621
658
  fullWorkspaces: z.boolean().optional().describe("Set true to include full workspace details (purpose, labels, governance type, user access roles). Recommended on first call to establish workspace context."),
622
659
  }),
660
+ // Current user's cross-workspace activity (requires OAuth token)
661
+ myActivity: z.object({
662
+ limit: z.number().optional().describe("Max activity items to return (default 50, max 200)."),
663
+ withUser: z.string().optional().describe("Scope DM considerations to the conversation with this user id. Agent internal considerations from direct-message runs are redacted to an anonymous marker unless you name that conversation's counterpart here."),
664
+ }),
665
+ // Another user's cross-workspace activity (requires OAuth token)
666
+ userActivity: z.object({
667
+ userId: z.string().describe("The user whose activity to fetch."),
668
+ limit: z.number().optional().describe("Max activity items to return (default 50, max 200)."),
669
+ }),
623
670
  // User tension tools (requires OAuth token)
624
671
  listMyTensions: z.object({
625
672
  context: z.string().optional().describe("Optional context filter (e.g., workspace ID or circle ID)"),
@@ -772,6 +819,46 @@ export const schemas = {
772
819
  maxImages: coerceFromJson(z.number().int().positive().optional()).describe("Help-article mode only. Cap on how many screenshots the default selection attaches (the first N content images in document order). Default 3, max 6. Ignored when imageIndexes is provided."),
773
820
  }).refine((v) => Boolean(v.topic) || Boolean(v.search), { message: "Provide either `topic` or `search`." }),
774
821
  diagnose: z.object({}).describe("No arguments — diagnose reads session state from the server."),
822
+ // Connector tools (registration is workspace-admin only)
823
+ listConnectors: z.object({
824
+ workspaceId: z.string().describe("Workspace ID whose connector catalog to list"),
825
+ }),
826
+ registerConnector: z.object({
827
+ workspaceId: z.string().describe("Workspace ID to register the connector in"),
828
+ type: z.enum(["mcp", "cli", "api"]).describe("Transport: 'mcp' (MCP server over a url), 'api' (REST endpoint over a url), or 'cli' (a command)"),
829
+ name: z.string().describe("Unique connector name within the workspace catalog"),
830
+ config: coerceFromJson(z.record(z.unknown())).optional().describe("Per-type transport config, no secret. mcp/api need a url (e.g., { url: 'https://...' }); cli needs a command (e.g., { command: 'some-cli' }). Optional non-secret headers go under headers."),
831
+ capabilities: coerceFromJson(z.record(z.unknown())).optional().describe("Capability descriptor: { discover: boolean, tools: [{ name, description, inputSchema }] }. discover:true lets the connector self-describe its tools at runtime."),
832
+ exposure: coerceFromJson(z.record(z.unknown())).optional().describe("Exposure policy deciding which owners may bind: { userAgent: boolean, domainGated: boolean }. Set domainGated:true to allow binding to a role's domain."),
833
+ authStrategy: z.enum(["secret", "oauth2"]).optional().describe("How a principal connects: 'secret' (a one-time secret captured via the Connect button) or 'oauth2'. The agent never sees the secret."),
834
+ }),
835
+ bindConnector: z.object({
836
+ workspaceId: z.string().describe("Workspace ID the connector and owner belong to"),
837
+ connectorId: z.string().describe("ID of an enabled connector from nestr_list_connectors"),
838
+ ownerType: z.enum(["user", "agent", "workspace", "role-domain"]).describe("Owner type. 'role-domain' binds the connector to a role's domain so the role can use it and a credentials field is materialised on the domain."),
839
+ ownerId: z.string().describe("Owner ID. user/agent: the user ID. workspace: the workspace ID. role-domain: the domain nest ID."),
840
+ }),
841
+ // File attachments (a comment id works as the nestId — files are keyed by nestId)
842
+ getNestFiles: z.object({
843
+ nestId: z.string().describe("Nest or comment ID whose file attachments to list"),
844
+ }),
845
+ readFile: z.object({
846
+ nestId: z.string().describe("Nest or comment ID the file is attached to"),
847
+ fileId: z.string().describe("File ID from nestr_get_nest_files"),
848
+ }),
849
+ uploadFile: z.object({
850
+ nestId: z.string().describe("Nest or comment ID to attach the file to"),
851
+ name: z.string().describe('File name including extension (e.g. "notes.md", "data.csv")'),
852
+ contentType: z.string().describe('MIME type of the file (e.g. "text/markdown", "text/csv", "image/png")'),
853
+ content: z.string().optional().describe("File content as UTF-8 text. Use for text-native files you author directly (.md, .txt, .csv, .json, .html, .svg, code). Stored verbatim. Provide this OR dataBase64, not both."),
854
+ dataBase64: z.string().optional().describe("File bytes, base64-encoded. Use for binary content you already hold as base64. Provide this OR content, not both."),
855
+ }).refine((v) => (v.content !== undefined) !== (v.dataBase64 !== undefined), {
856
+ message: "Provide exactly one of content (UTF-8 text) or dataBase64 (base64 bytes).",
857
+ }),
858
+ deleteFile: z.object({
859
+ nestId: z.string().describe("Nest or comment ID the file is attached to"),
860
+ fileId: z.string().describe("File ID from nestr_get_nest_files"),
861
+ }),
775
862
  };
776
863
  // Tool annotations for MCP - hints for clients on tool behavior
777
864
  const readOnly = { annotations: { readOnlyHint: true, destructiveHint: false } };
@@ -891,7 +978,7 @@ export const toolDefinitions = [
891
978
  },
892
979
  {
893
980
  name: "nestr_get_nest",
894
- description: "Get nest details. Supports comma-separated IDs for batch fetch. Add hints=true for contextual signals, fieldsMetaData=true for field schemas.",
981
+ description: "Get nest details. Supports comma-separated IDs for batch fetch. Add hints=true for contextual signals, fieldsMetaData=true for field schemas. For a single nest you can also diagnose it: provenance, rights, and whoCan (see explain_nest for a one-shot diagnosis).",
895
982
  inputSchema: {
896
983
  type: "object",
897
984
  properties: {
@@ -899,6 +986,24 @@ export const toolDefinitions = [
899
986
  fieldsMetaData: { type: "boolean", description: "Set to true to include field schema metadata (available options, field types)" },
900
987
  hints: { type: "boolean", description: "Include contextual hints (default: true). Set to false for bulk lookups where you only need structural data." },
901
988
  stripDescription: { type: "boolean", description: "Set true to strip description fields from response, significantly reducing size." },
989
+ provenance: { type: "boolean", description: "Single-nest only. Include field/property provenance: which label (and circle context) defines each field and property, e.g. why a role has a given icon." },
990
+ rights: { type: "boolean", description: "Single-nest only. Include the caller's composed rights on the nest (self read/update/delete) plus a deny trace naming the profiles that block each op, and why." },
991
+ forUser: { type: "string", description: "Single-nest only, with rights=true. Report rights for this user id instead of the caller. Requires the caller to be an admin of the nest." },
992
+ whoCan: { type: "string", description: "Single-nest only. Comma-separated ops (read,update,delete,create): list the users who can perform each op on this nest (admins + role-holders), with contact for admin callers." },
993
+ },
994
+ required: ["nestId"],
995
+ },
996
+ ...readOnly,
997
+ },
998
+ {
999
+ name: "nestr_explain_nest",
1000
+ description: "Diagnose a single nest: WHY it looks and behaves as it does. Returns field/property provenance (which label and circle defines each field, value, and property such as the icon), the caller's composed rights with a deny trace (why a field is read-only, why you cannot edit), and — when whoCan is given — who can perform an op and who to contact. Use this when a user asks 'why can't I ...', 'why is this read-only', 'where does this field come from', 'why does this role have a different icon', or 'who can change this'. For connection/auth errors use nestr_diagnose instead.",
1001
+ inputSchema: {
1002
+ type: "object",
1003
+ properties: {
1004
+ nestId: { type: "string", description: "The nest to diagnose (a single id)." },
1005
+ forUser: { type: "string", description: "Diagnose rights for this user id instead of the caller. Requires the caller to be an admin of the nest." },
1006
+ whoCan: { type: "string", description: "Comma-separated ops (read,update,delete,create) to also list who can perform each on this nest." },
902
1007
  },
903
1008
  required: ["nestId"],
904
1009
  },
@@ -1464,6 +1569,33 @@ export const toolDefinitions = [
1464
1569
  _meta: completableListUi,
1465
1570
  ...readOnly,
1466
1571
  },
1572
+ // Current user's cross-workspace activity (requires OAuth token)
1573
+ {
1574
+ name: "nestr_my_activity",
1575
+ description: "The caller's own activity across ALL their workspaces, newest first (gated by workspace membership and the token's scope). Not scoped to a project or a single nest — it's everything you've done. For an agent, this is how it sees what it has done: past considerations (with the tools used and the outcome), comments, governance changes, and other actions. Agent internal considerations from direct-message runs are redacted to an anonymous marker unless you pass withUser with that conversation's counterpart. Auth: OAuth only (user-scoped — workspace API keys lack user identity). On auth failure call nestr_diagnose.",
1576
+ inputSchema: {
1577
+ type: "object",
1578
+ properties: {
1579
+ limit: { type: "number", description: "Max activity items to return (default 50, max 200)." },
1580
+ withUser: { type: "string", description: "Scope DM considerations to the conversation with this user id. Agent internal considerations from direct-message runs are redacted to an anonymous marker unless you name that conversation's counterpart here." },
1581
+ },
1582
+ },
1583
+ ...readOnly,
1584
+ },
1585
+ // Another user's cross-workspace activity (requires OAuth token)
1586
+ {
1587
+ name: "nestr_user_activity",
1588
+ description: "Another user's activity across the workspaces you share with them, newest first. Lets an agent see what a colleague or another agent has done: their past considerations (with the tools used and the outcome), comments, governance changes, and other actions. Agent internal considerations from direct-message runs show their substance only when you are a participant of that conversation, otherwise an anonymous marker. Auth: OAuth only (user-scoped — workspace API keys lack user identity). On auth failure call nestr_diagnose.",
1589
+ inputSchema: {
1590
+ type: "object",
1591
+ properties: {
1592
+ userId: { type: "string", description: "The user whose activity to fetch." },
1593
+ limit: { type: "number", description: "Max activity items to return (default 50, max 200)." },
1594
+ },
1595
+ required: ["userId"],
1596
+ },
1597
+ ...readOnly,
1598
+ },
1467
1599
  // Label management
1468
1600
  {
1469
1601
  name: "nestr_add_label",
@@ -1880,6 +2012,129 @@ export const toolDefinitions = [
1880
2012
  },
1881
2013
  ...destructive,
1882
2014
  },
2015
+ {
2016
+ name: "nestr_list_connectors",
2017
+ description: "List the workspace's connector catalog: the mcp / cli / api templates an admin has registered. Each entry holds no secret and shows its type, name, authStrategy, config, capabilities, exposure ({ userAgent, domainGated }) and whether it is enabled. Typical flow: register a connector, then bind it to a role's domain with nestr_bind_connector, then a human or agent connects the account via the credentials field's Connect button (the secret is captured out-of-band, never by the agent). Auth: any valid token can list.",
2018
+ inputSchema: {
2019
+ type: "object",
2020
+ properties: {
2021
+ workspaceId: { type: "string", description: "Workspace ID whose connector catalog to list" },
2022
+ },
2023
+ required: ["workspaceId"],
2024
+ },
2025
+ ...readOnly,
2026
+ },
2027
+ {
2028
+ name: "nestr_register_connector",
2029
+ description: "Register a connector in the workspace catalog: a reusable mcp / cli / api template that holds no secret. Workspace-admin only. A non-admin caller gets AUTH_SCOPE_INSUFFICIENT (call nestr_diagnose on any auth error). Provide type ('mcp' or 'api' need a url in config; 'cli' needs a command) and a unique name; optionally capabilities, exposure ({ userAgent, domainGated }), and authStrategy ('secret' or 'oauth2'). This only creates the template. Typical flow: register here, then bind it to a role's domain with nestr_bind_connector, then a human or agent connects the account via the credentials field's Connect button. The secret is captured out-of-band through that button, never by the agent.",
2030
+ inputSchema: {
2031
+ type: "object",
2032
+ properties: {
2033
+ workspaceId: { type: "string", description: "Workspace ID to register the connector in" },
2034
+ type: {
2035
+ type: "string",
2036
+ enum: ["mcp", "cli", "api"],
2037
+ description: "Transport: 'mcp' (MCP server over a url), 'api' (REST endpoint over a url), or 'cli' (a command)",
2038
+ },
2039
+ name: { type: "string", description: "Unique connector name within the workspace catalog" },
2040
+ config: {
2041
+ type: "object",
2042
+ description: "Per-type transport config, no secret. mcp/api need a url (e.g., { url: 'https://...' }); cli needs a command (e.g., { command: 'some-cli' }). Optional non-secret headers go under headers.",
2043
+ },
2044
+ capabilities: {
2045
+ type: "object",
2046
+ description: "Capability descriptor: { discover: boolean, tools: [{ name, description, inputSchema }] }. discover:true lets the connector self-describe its tools at runtime.",
2047
+ },
2048
+ exposure: {
2049
+ type: "object",
2050
+ description: "Exposure policy deciding which owners may bind: { userAgent: boolean, domainGated: boolean }. Set domainGated:true to allow binding to a role's domain.",
2051
+ },
2052
+ authStrategy: {
2053
+ type: "string",
2054
+ enum: ["secret", "oauth2"],
2055
+ description: "How a principal connects: 'secret' (a one-time secret captured via the Connect button) or 'oauth2'. The agent never sees the secret.",
2056
+ },
2057
+ },
2058
+ required: ["workspaceId", "type", "name"],
2059
+ },
2060
+ ...mutating,
2061
+ },
2062
+ {
2063
+ name: "nestr_bind_connector",
2064
+ description: "Bind a registered connector to an owner so that owner can use it. Owner types: 'user' or 'agent' (ownerId is the user ID), 'workspace' (ownerId is the workspace ID), or 'role-domain' (ownerId is the domain nest ID). A 'role-domain' owner also materialises a credentials field on the domain nest, so the role can use the connector and the Connect button renders there; the response then includes credentialsField { domainId, fieldId, fieldCode }. After binding, a human or agent connects the account via that Connect button. The secret is captured out-of-band and is never seen by the agent. Workspace-admin only: a non-admin caller gets AUTH_SCOPE_INSUFFICIENT. The connector must already be registered (nestr_register_connector) and enabled.",
2065
+ inputSchema: {
2066
+ type: "object",
2067
+ properties: {
2068
+ workspaceId: { type: "string", description: "Workspace ID the connector and owner belong to" },
2069
+ connectorId: { type: "string", description: "ID of an enabled connector from nestr_list_connectors" },
2070
+ ownerType: {
2071
+ type: "string",
2072
+ enum: ["user", "agent", "workspace", "role-domain"],
2073
+ description: "Owner type. 'role-domain' binds the connector to a role's domain so the role can use it and a credentials field is materialised on the domain.",
2074
+ },
2075
+ ownerId: {
2076
+ type: "string",
2077
+ description: "Owner ID. user/agent: the user ID. workspace: the workspace ID. role-domain: the domain nest ID.",
2078
+ },
2079
+ },
2080
+ required: ["workspaceId", "connectorId", "ownerType", "ownerId"],
2081
+ },
2082
+ ...mutating,
2083
+ },
2084
+ {
2085
+ name: "nestr_get_nest_files",
2086
+ description: "List a nest's file attachments. A comment ID works too — files are keyed by nestId, so pass a comment ID to see files attached to that comment. Returns each file's id, name, contentType and size. Use nestr_read_file with a returned id to read one (images come back as viewable image content). Auth: any valid token with access to the nest.",
2087
+ inputSchema: {
2088
+ type: "object",
2089
+ properties: {
2090
+ nestId: { type: "string", description: "Nest or comment ID whose file attachments to list" },
2091
+ },
2092
+ required: ["nestId"],
2093
+ },
2094
+ ...readOnly,
2095
+ },
2096
+ {
2097
+ name: "nestr_read_file",
2098
+ description: "Read a single file attachment on a nest (or comment). Branches on contentType: images (image/*) return as viewable image content so you can see them (very large images return metadata only); JSON and text (application/json, text/*) return as decoded UTF-8 text (large text is truncated); PDFs and other types return their metadata only (cannot be inlined yet). Get file ids from nestr_get_nest_files. A comment ID works as the nestId. Auth: any valid token with access to the nest.",
2099
+ inputSchema: {
2100
+ type: "object",
2101
+ properties: {
2102
+ nestId: { type: "string", description: "Nest or comment ID the file is attached to" },
2103
+ fileId: { type: "string", description: "File ID from nestr_get_nest_files" },
2104
+ },
2105
+ required: ["nestId", "fileId"],
2106
+ },
2107
+ ...readOnly,
2108
+ },
2109
+ {
2110
+ name: "nestr_upload_file",
2111
+ description: "Upload a file and attach it to a nest (or comment; files are keyed by nestId, so a comment ID attaches the file to that comment). Provide the file one of two ways: content (UTF-8 text, for text-native files you author directly such as .md, .csv, .json, .html, .svg, or code) or dataBase64 (base64-encoded bytes you already have). Any content type is accepted; the upload is rejected if it exceeds the server's maximum size (default 10MB). Returns the new file's descriptor (id, name, contentType, size). Auth: a token with write access to the nest.",
2112
+ inputSchema: {
2113
+ type: "object",
2114
+ properties: {
2115
+ nestId: { type: "string", description: "Nest or comment ID to attach the file to" },
2116
+ name: { type: "string", description: 'File name including extension (e.g. "notes.md", "data.csv")' },
2117
+ contentType: { type: "string", description: 'MIME type (e.g. "text/markdown", "text/csv", "image/png")' },
2118
+ content: { type: "string", description: "File content as UTF-8 text (for text-native files: .md, .txt, .csv, .json, .html, .svg, code). Stored verbatim. Provide this OR dataBase64." },
2119
+ dataBase64: { type: "string", description: "File bytes, base64-encoded. Provide this OR content." },
2120
+ },
2121
+ required: ["nestId", "name", "contentType"],
2122
+ },
2123
+ ...mutating,
2124
+ },
2125
+ {
2126
+ name: "nestr_delete_file",
2127
+ description: "Delete a file attachment from a nest (or comment). Get the file id from nestr_get_nest_files. A comment ID works as the nestId. This permanently removes the file. Auth: a token with delete access to the nest.",
2128
+ inputSchema: {
2129
+ type: "object",
2130
+ properties: {
2131
+ nestId: { type: "string", description: "Nest or comment ID the file is attached to" },
2132
+ fileId: { type: "string", description: "File ID from nestr_get_nest_files" },
2133
+ },
2134
+ required: ["nestId", "fileId"],
2135
+ },
2136
+ ...destructive,
2137
+ },
1883
2138
  ];
1884
2139
  // Strip description fields from nest objects in response data
1885
2140
  export function stripDescriptionFields(data) {
@@ -2218,6 +2473,23 @@ async function _handleToolCall(client, name, args, context) {
2218
2473
  cleanText: true,
2219
2474
  fieldsMetaData: parsed.fieldsMetaData,
2220
2475
  hints: parsed.hints !== false,
2476
+ provenance: parsed.provenance,
2477
+ rights: parsed.rights,
2478
+ forUser: parsed.forUser,
2479
+ whoCan: parsed.whoCan,
2480
+ });
2481
+ return formatResult(enrichHints(nest));
2482
+ }
2483
+ case "nestr_explain_nest": {
2484
+ const parsed = schemas.explainNest.parse(args);
2485
+ const nest = await client.getNest(parsed.nestId, {
2486
+ cleanText: true,
2487
+ fieldsMetaData: true,
2488
+ hints: false,
2489
+ provenance: true,
2490
+ rights: true,
2491
+ forUser: parsed.forUser,
2492
+ whoCan: parsed.whoCan,
2221
2493
  });
2222
2494
  return formatResult(enrichHints(nest));
2223
2495
  }
@@ -2561,6 +2833,21 @@ async function _handleToolCall(client, name, args, context) {
2561
2833
  const items = await client.getDailyPlan();
2562
2834
  return formatResult(completableResponse(compactResponse(items), "daily-plan", "Daily Plan"));
2563
2835
  }
2836
+ case "nestr_my_activity": {
2837
+ const parsed = schemas.myActivity.parse(args);
2838
+ const activity = await client.getMyActivity({
2839
+ limit: parsed.limit,
2840
+ withUser: parsed.withUser,
2841
+ });
2842
+ return formatResult({ count: activity.length, activity });
2843
+ }
2844
+ case "nestr_user_activity": {
2845
+ const parsed = schemas.userActivity.parse(args);
2846
+ const activity = await client.getUserActivity(parsed.userId, {
2847
+ limit: parsed.limit,
2848
+ });
2849
+ return formatResult({ count: activity.length, activity });
2850
+ }
2564
2851
  // Current user identity and workspace context
2565
2852
  case "nestr_get_me": {
2566
2853
  const parsed = schemas.getMe.parse(args);
@@ -2811,6 +3098,127 @@ async function _handleToolCall(client, name, args, context) {
2811
3098
  const result = await client.removeGraphLink(parsed.nestId, parsed.relation, parsed.targetId);
2812
3099
  return formatResult({ message: "Graph link removed" });
2813
3100
  }
3101
+ // Connector tools
3102
+ case "nestr_list_connectors": {
3103
+ const parsed = schemas.listConnectors.parse(args);
3104
+ const connectors = await client.listConnectors(parsed.workspaceId);
3105
+ return formatResult(connectors);
3106
+ }
3107
+ case "nestr_register_connector": {
3108
+ const parsed = schemas.registerConnector.parse(args);
3109
+ const connector = await client.registerConnector(parsed.workspaceId, {
3110
+ type: parsed.type,
3111
+ name: parsed.name,
3112
+ config: parsed.config,
3113
+ capabilities: parsed.capabilities,
3114
+ exposure: parsed.exposure,
3115
+ authStrategy: parsed.authStrategy,
3116
+ });
3117
+ return formatResult({
3118
+ message: "Connector registered. Next, bind it to an owner with nestr_bind_connector (e.g. a role's domain), then a human or agent connects the account via the credentials field's Connect button.",
3119
+ connector,
3120
+ });
3121
+ }
3122
+ case "nestr_bind_connector": {
3123
+ const parsed = schemas.bindConnector.parse(args);
3124
+ const connection = await client.bindConnector(parsed.workspaceId, {
3125
+ connectorId: parsed.connectorId,
3126
+ owner: { type: parsed.ownerType, id: parsed.ownerId },
3127
+ });
3128
+ // For a role-domain binding the API materialises a credentials field on
3129
+ // the domain; surface that explicitly so the caller knows the Connect
3130
+ // button now renders there and the secret is captured out-of-band.
3131
+ const message = parsed.ownerType === "role-domain"
3132
+ ? "Connector bound to the role's domain. A credentials field was materialised on the domain (see credentialsField) so the role can use the connector and the Connect button renders. A human or agent now connects the account via that button; the secret is captured out-of-band and never by the agent."
3133
+ : "Connector bound to the owner. The owner now connects the account out-of-band; the secret is never seen by the agent.";
3134
+ return formatResult({ message, connection });
3135
+ }
3136
+ case "nestr_get_nest_files": {
3137
+ const parsed = schemas.getNestFiles.parse(args);
3138
+ const files = await client.getNestFiles(parsed.nestId);
3139
+ if (files.length === 0) {
3140
+ return { content: [{ type: "text", text: `No file attachments on ${parsed.nestId}.` }] };
3141
+ }
3142
+ const lines = files.map((f) => `- ${f.id} — ${f.name} (${f.contentType}, ${formatBytes(f.size)})`);
3143
+ const text = `${files.length} file${files.length === 1 ? "" : "s"} attached to ${parsed.nestId}. Read one with nestr_read_file({ nestId: "${parsed.nestId}", fileId: "<id>" }).\n\n${lines.join("\n")}`;
3144
+ return { content: [{ type: "text", text }] };
3145
+ }
3146
+ case "nestr_read_file": {
3147
+ const parsed = schemas.readFile.parse(args);
3148
+ const file = await client.getNestFile(parsed.nestId, parsed.fileId);
3149
+ const contentType = file.contentType || "application/octet-stream";
3150
+ // Images: return as a viewable image content item (mirrors nestr_help).
3151
+ // Guard the size first — an image over MAX_IMAGE_INLINE_BYTES exceeds the
3152
+ // per-image limit of the model API the agent forwards it to, so inlining
3153
+ // the base64 would just make that call fail. Degrade to a metadata note.
3154
+ if (contentType.startsWith("image/")) {
3155
+ // Not `??`: size can legitimately be 0 when a legacy file's metadata was
3156
+ // lost (the API descriptor falls back to 0), and there we want the real
3157
+ // byte length so the cap still applies. `> 0` recomputes on a zero/missing
3158
+ // size; trusting a 0 would skip the guard on a large legacy image.
3159
+ const imageBytes = file.size > 0 ? file.size : Buffer.byteLength(file.dataBase64, "base64");
3160
+ if (imageBytes > MAX_IMAGE_INLINE_BYTES) {
3161
+ return {
3162
+ content: [
3163
+ {
3164
+ type: "text",
3165
+ text: `File: ${file.name}\nContent type: ${contentType}\nSize: ${formatBytes(imageBytes)}\n\nThis image is too large to inline (limit ${formatBytes(MAX_IMAGE_INLINE_BYTES)}). Download it directly to view the content.`,
3166
+ },
3167
+ ],
3168
+ };
3169
+ }
3170
+ return {
3171
+ content: [
3172
+ { type: "text", text: `File: ${file.name} (${contentType}, ${formatBytes(file.size)})` },
3173
+ { type: "image", data: file.dataBase64, mimeType: contentType },
3174
+ ],
3175
+ };
3176
+ }
3177
+ // JSON / text / CSV: decode to UTF-8 and return as a text block.
3178
+ if (contentType.startsWith("text/") ||
3179
+ contentType.startsWith("application/json")) {
3180
+ const decoded = Buffer.from(file.dataBase64, "base64").toString("utf-8");
3181
+ const { text: body, truncated } = capText(decoded);
3182
+ const note = truncated
3183
+ ? `\n\n_(truncated — file is ${formatBytes(file.size)}; showing the first ${MAX_TEXT_FILE_CHARS} characters)_`
3184
+ : "";
3185
+ return {
3186
+ content: [
3187
+ { type: "text", text: `File: ${file.name} (${contentType}, ${formatBytes(file.size)})\n\n${body}${note}` },
3188
+ ],
3189
+ };
3190
+ }
3191
+ // PDFs and everything else: metadata only. The ToolResult content type
3192
+ // supports text + image blocks, so a non-image binary can't be inlined yet.
3193
+ return {
3194
+ content: [
3195
+ {
3196
+ type: "text",
3197
+ text: `File: ${file.name}\nContent type: ${contentType}\nSize: ${formatBytes(file.size)}\n\nThis file type can't be inlined yet — only images (returned as viewable image content) and text/JSON (returned as decoded text) are supported.`,
3198
+ },
3199
+ ],
3200
+ };
3201
+ }
3202
+ case "nestr_upload_file": {
3203
+ const parsed = schemas.uploadFile.parse(args);
3204
+ // The REST API takes base64 bytes; base64-encode the text convenience here
3205
+ // so the model can hand over content it authored without encoding it itself.
3206
+ const dataBase64 = parsed.dataBase64 ?? Buffer.from(parsed.content ?? "", "utf-8").toString("base64");
3207
+ const file = await client.createNestFile(parsed.nestId, {
3208
+ name: parsed.name,
3209
+ contentType: parsed.contentType,
3210
+ dataBase64,
3211
+ });
3212
+ return formatResult({
3213
+ message: `Uploaded ${file.name} (${formatBytes(file.size)}) to ${parsed.nestId}.`,
3214
+ file,
3215
+ });
3216
+ }
3217
+ case "nestr_delete_file": {
3218
+ const parsed = schemas.deleteFile.parse(args);
3219
+ await client.deleteNestFile(parsed.nestId, parsed.fileId);
3220
+ return formatResult({ message: `Deleted file ${parsed.fileId} from ${parsed.nestId}.` });
3221
+ }
2814
3222
  default:
2815
3223
  return formatError({
2816
3224
  error: true,
@@ -2879,6 +3287,34 @@ function buildDiagnoseHint(snapshot) {
2879
3287
  }
2880
3288
  return "Server-side state looks healthy. If a tool is failing, include sessionCorrelationId in the bug report.";
2881
3289
  }
3290
+ // Cap on decoded text-file content returned by nestr_read_file, to bound token
3291
+ // cost on large files. ~200 KB of characters.
3292
+ const MAX_TEXT_FILE_CHARS = 200_000;
3293
+ /** Truncate decoded text to MAX_TEXT_FILE_CHARS, flagging whether it was cut. */
3294
+ function capText(text) {
3295
+ if (text.length <= MAX_TEXT_FILE_CHARS)
3296
+ return { text, truncated: false };
3297
+ return { text: text.slice(0, MAX_TEXT_FILE_CHARS), truncated: true };
3298
+ }
3299
+ // Cap on an image returned inline by nestr_read_file. Above this the base64 blob
3300
+ // exceeds the ~5MB-per-image limit of the model API the agent forwards it to, so
3301
+ // we return metadata instead of an image block that call would reject.
3302
+ const MAX_IMAGE_INLINE_BYTES = 5 * 1024 * 1024;
3303
+ /** Human-readable byte size (e.g. "12.3 KB"). */
3304
+ function formatBytes(bytes) {
3305
+ if (!Number.isFinite(bytes) || bytes < 0)
3306
+ return "unknown size";
3307
+ if (bytes < 1024)
3308
+ return `${bytes} B`;
3309
+ const units = ["KB", "MB", "GB"];
3310
+ let size = bytes / 1024;
3311
+ let unit = 0;
3312
+ while (size >= 1024 && unit < units.length - 1) {
3313
+ size /= 1024;
3314
+ unit++;
3315
+ }
3316
+ return `${size.toFixed(1)} ${units[unit]}`;
3317
+ }
2882
3318
  function formatResult(data) {
2883
3319
  return {
2884
3320
  content: [