@guuey/config 0.6.1 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/agent.d.ts CHANGED
@@ -134,9 +134,33 @@ export declare const McpServerEntrySchema: z.ZodUnion<readonly [z.ZodDiscriminat
134
134
  }, z.core.$strict>], "kind">, z.ZodLiteral<false>]>;
135
135
  export type DeclaredMcpServers = Record<string, GuueyAgentMcpServer | false>;
136
136
  /**
137
- * Tool-gate block — allowlist applied first (intersect with what the MCP
138
- * server advertises), then denylist subtracts. Tool names are MCP-namespaced
139
- * (`"<server>.<tool>"`). Bare names match across all connected servers.
137
+ * Tool-gate block — `allowlist` first (the model may call ONLY these), then
138
+ * `denylist` subtracts (removed from the model's catalog outright). Both
139
+ * optional; both empty/absent every tool of every connected server.
140
+ *
141
+ * Entry shapes (guuey#234 — the ONE grammar, parsed by
142
+ * {@link parseToolGateEntry}, validated at deploy time by
143
+ * {@link validateToolGates}, and translated to the framework's own tool
144
+ * names by the host at turn time):
145
+ *
146
+ * - `"<server>.<tool>"` — one tool of one declared MCP server
147
+ * (`"todoist.create_task"`).
148
+ * - `"<server>.*"` — every tool of one declared server (`"ggui.*"`).
149
+ * - `"<tool>"` — a bare name: that tool on EVERY connected server
150
+ * (`"search"`), and — for a Claude agent on a GuueyFS-armed pod — the
151
+ * built-in file tool of that name (`"Bash"`, `"Write"`, …).
152
+ *
153
+ * `<server>` must name a server this agent connects: a declared
154
+ * `mcpServers` key, the platform default `ggui` (unless opted out with
155
+ * `ggui: false`), or a platform-injected reserved server
156
+ * ({@link RESERVED_MCP_SERVER_NAMES}). The framework-internal spellings
157
+ * (`mcp__server__tool`) are NOT accepted — write the config grammar and
158
+ * let the host translate.
159
+ *
160
+ * Runtime posture (Claude): a tool the model picks that is NOT in an explicit
161
+ * allowlist is DENIED with a message the model can read — never routed to an
162
+ * interactive prompt (a headless pod has no one to answer one). Deny-listed
163
+ * tools never reach the model's catalog at all.
140
164
  */
141
165
  declare const ToolGatesSchema: z.ZodObject<{
142
166
  allowlist: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -409,6 +433,51 @@ export declare const RESERVED_MCP_SERVER_NAMES: readonly string[];
409
433
  * {@link validateNoProxiedServers}'s shape.
410
434
  */
411
435
  export declare function validateReservedServerNames(agent: GuueyAgent | undefined): string[];
436
+ /** One parsed `tools.allowlist` / `tools.denylist` entry. */
437
+ export type ToolGateEntry =
438
+ /** `"<server>.<tool>"` — one tool of one server. */
439
+ {
440
+ kind: 'server-tool';
441
+ server: string;
442
+ tool: string;
443
+ }
444
+ /** `"<server>.*"` — every tool of one server. */
445
+ | {
446
+ kind: 'server-all';
447
+ server: string;
448
+ }
449
+ /** `"<tool>"` — that tool on every connected server (and the built-in of that name). */
450
+ | {
451
+ kind: 'bare';
452
+ tool: string;
453
+ };
454
+ /**
455
+ * Parse one tool-gate entry per the {@link ToolGatesSchema} grammar. Returns
456
+ * the parsed shape, or a human-readable reason string when the entry is
457
+ * malformed (never throws — callers decide whether to reject or report).
458
+ */
459
+ export declare function parseToolGateEntry(raw: string): ToolGateEntry | {
460
+ error: string;
461
+ };
462
+ /**
463
+ * The server names a tool-gate entry may qualify with: every EFFECTIVE server
464
+ * (declared map with the platform default seeded and `ggui: false` honoured —
465
+ * {@link effectiveMcpServers}) plus the platform-injected reserved servers
466
+ * ({@link RESERVED_MCP_SERVER_NAMES}: memory / profile, spliced at invoke time
467
+ * for authenticated callers).
468
+ */
469
+ export declare function toolGateServerNames(agent: GuueyAgent | undefined): string[];
470
+ /**
471
+ * Validate `agent.tools.allowlist` / `agent.tools.denylist` at deploy time
472
+ * (guuey#234). Every entry must parse per {@link parseToolGateEntry}, and a
473
+ * server-qualified entry must name a server this agent connects
474
+ * ({@link toolGateServerNames}). Returns a list of human-readable violation
475
+ * messages (empty = clean). Tool-level existence against a server's live
476
+ * manifest is NOT checked here (a hosted server's tool set is only known once
477
+ * it is connected) — that is why the host DENIES an unlisted pick at turn time
478
+ * instead of prompting.
479
+ */
480
+ export declare function validateToolGates(agent: GuueyAgent | undefined): string[];
412
481
  /**
413
482
  * Platform default MCP server map. Seeded under every declared map by
414
483
  * {@link effectiveMcpServers} (opt out with `ggui: false`). Exposed here so
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,6EAKnB,CAAC;AACX,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAS/D;;;;GAIG;AACH,eAAO,MAAM,mBAAmB;;;EAAiC,CAAC;AAClE,uEAAuE;AACvE,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AA+GhE;;;;;;;;GAQG;AACH,QAAA,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BAKnB,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;mDAA+C,CAAC;AACjF,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,mBAAmB,GAAG,KAAK,CAAC,CAAC;AAE7E;;;;GAIG;AACH,QAAA,MAAM,eAAe;;;kBAGnB,CAAC;AAEH;;;;;;;;GAQG;AACH,QAAA,MAAM,mBAAmB;;;kBAGvB,CAAC;AAcH;;;;GAIG;AACH,QAAA,MAAM,kBAAkB;;oBAGtB,CAAC;AAEH;;;;;;GAMG;AACH,QAAA,MAAM,oBAAoB;;;kBAGxB,CAAC;AAEH;;;;;;;;;;GAUG;AACH,QAAA,MAAM,YAAY;;;;;;;;;kBAKhB,CAAC;AA0BH;;;;;GAKG;AACH;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;oDAAoD,CAAC;AAEnF,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA4FzB,CAAC;AAEH,kEAAkE;AAClE,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAExD,oCAAoC;AACpC,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAElE,4BAA4B;AAC5B,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAElE,iCAAiC;AACjC,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEpE,kDAAkD;AAClD,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAExE,4BAA4B;AAC5B,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAEtE,0BAA0B;AAC1B,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAuE5D;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,UAAU,GAAG,SAAS,GAC5B,MAAM,EAAE,CAiCV;AAeD;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,UAAU,GAAG,SAAS,GAC5B,MAAM,EAAE,CAaV;AAaD;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,UAAU,GAAG,SAAS,GAC5B,MAAM,EAAE,CAaV;AAgBD;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,iBAAiB,CAAC;AAE1D;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,kBAAkB,CAAC;AAE5D;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,EAAE,SAAS,MAAM,EAGtD,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,UAAU,GAAG,SAAS,GAC5B,MAAM,EAAE,CAaV;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAEzE,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,kBAAkB,GAAG,SAAS,GACvC,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAOrC;AAED,kJAAkJ;AAClJ,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,kBAAkB,GAAG,SAAS,GACtC,KAAK,CAAC,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAItC"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
package/dist/agent.js CHANGED
@@ -193,9 +193,33 @@ const McpServerSchema = z.discriminatedUnion('kind', [
193
193
  */
194
194
  export const McpServerEntrySchema = z.union([McpServerSchema, z.literal(false)]);
195
195
  /**
196
- * Tool-gate block — allowlist applied first (intersect with what the MCP
197
- * server advertises), then denylist subtracts. Tool names are MCP-namespaced
198
- * (`"<server>.<tool>"`). Bare names match across all connected servers.
196
+ * Tool-gate block — `allowlist` first (the model may call ONLY these), then
197
+ * `denylist` subtracts (removed from the model's catalog outright). Both
198
+ * optional; both empty/absent every tool of every connected server.
199
+ *
200
+ * Entry shapes (guuey#234 — the ONE grammar, parsed by
201
+ * {@link parseToolGateEntry}, validated at deploy time by
202
+ * {@link validateToolGates}, and translated to the framework's own tool
203
+ * names by the host at turn time):
204
+ *
205
+ * - `"<server>.<tool>"` — one tool of one declared MCP server
206
+ * (`"todoist.create_task"`).
207
+ * - `"<server>.*"` — every tool of one declared server (`"ggui.*"`).
208
+ * - `"<tool>"` — a bare name: that tool on EVERY connected server
209
+ * (`"search"`), and — for a Claude agent on a GuueyFS-armed pod — the
210
+ * built-in file tool of that name (`"Bash"`, `"Write"`, …).
211
+ *
212
+ * `<server>` must name a server this agent connects: a declared
213
+ * `mcpServers` key, the platform default `ggui` (unless opted out with
214
+ * `ggui: false`), or a platform-injected reserved server
215
+ * ({@link RESERVED_MCP_SERVER_NAMES}). The framework-internal spellings
216
+ * (`mcp__server__tool`) are NOT accepted — write the config grammar and
217
+ * let the host translate.
218
+ *
219
+ * Runtime posture (Claude): a tool the model picks that is NOT in an explicit
220
+ * allowlist is DENIED with a message the model can read — never routed to an
221
+ * interactive prompt (a headless pod has no one to answer one). Deny-listed
222
+ * tools never reach the model's catalog at all.
199
223
  */
200
224
  const ToolGatesSchema = z.strictObject({
201
225
  allowlist: z.array(z.string().min(1)).optional(),
@@ -607,6 +631,85 @@ export function validateReservedServerNames(agent) {
607
631
  }
608
632
  return violations;
609
633
  }
634
+ /**
635
+ * The framework-internal MCP tool-name prefix (Claude Agent SDK:
636
+ * `mcp__<server>__<tool>`). Rejected in config — builders write the
637
+ * `<server>.<tool>` grammar; the host translates.
638
+ */
639
+ const SDK_INTERNAL_TOOL_PREFIX = /^mcp__/;
640
+ /**
641
+ * Parse one tool-gate entry per the {@link ToolGatesSchema} grammar. Returns
642
+ * the parsed shape, or a human-readable reason string when the entry is
643
+ * malformed (never throws — callers decide whether to reject or report).
644
+ */
645
+ export function parseToolGateEntry(raw) {
646
+ const entry = raw.trim();
647
+ if (entry.length === 0)
648
+ return { error: 'empty entry' };
649
+ if (SDK_INTERNAL_TOOL_PREFIX.test(entry)) {
650
+ return {
651
+ error: `"${entry}" uses the framework-internal spelling — write "<server>.<tool>" (or "<server>.*", or a bare tool name) instead`,
652
+ };
653
+ }
654
+ const dot = entry.indexOf('.');
655
+ if (dot === -1)
656
+ return { kind: 'bare', tool: entry };
657
+ const server = entry.slice(0, dot);
658
+ const tool = entry.slice(dot + 1);
659
+ if (server.length === 0)
660
+ return { error: `"${entry}" has an empty server name before the dot` };
661
+ if (tool.length === 0)
662
+ return { error: `"${entry}" has an empty tool name after the dot` };
663
+ if (tool === '*')
664
+ return { kind: 'server-all', server };
665
+ if (tool.includes('*')) {
666
+ return { error: `"${entry}": wildcards are only valid as the whole tool part ("${server}.*")` };
667
+ }
668
+ return { kind: 'server-tool', server, tool };
669
+ }
670
+ /**
671
+ * The server names a tool-gate entry may qualify with: every EFFECTIVE server
672
+ * (declared map with the platform default seeded and `ggui: false` honoured —
673
+ * {@link effectiveMcpServers}) plus the platform-injected reserved servers
674
+ * ({@link RESERVED_MCP_SERVER_NAMES}: memory / profile, spliced at invoke time
675
+ * for authenticated callers).
676
+ */
677
+ export function toolGateServerNames(agent) {
678
+ return [
679
+ ...Object.keys(effectiveMcpServers(agent?.mcpServers)),
680
+ ...RESERVED_MCP_SERVER_NAMES,
681
+ ];
682
+ }
683
+ /**
684
+ * Validate `agent.tools.allowlist` / `agent.tools.denylist` at deploy time
685
+ * (guuey#234). Every entry must parse per {@link parseToolGateEntry}, and a
686
+ * server-qualified entry must name a server this agent connects
687
+ * ({@link toolGateServerNames}). Returns a list of human-readable violation
688
+ * messages (empty = clean). Tool-level existence against a server's live
689
+ * manifest is NOT checked here (a hosted server's tool set is only known once
690
+ * it is connected) — that is why the host DENIES an unlisted pick at turn time
691
+ * instead of prompting.
692
+ */
693
+ export function validateToolGates(agent) {
694
+ const violations = [];
695
+ const gates = agent?.tools;
696
+ if (!gates)
697
+ return violations;
698
+ const known = new Set(toolGateServerNames(agent));
699
+ for (const list of ['allowlist', 'denylist']) {
700
+ for (const raw of gates[list] ?? []) {
701
+ const parsed = parseToolGateEntry(raw);
702
+ if ('error' in parsed) {
703
+ violations.push(`tools.${list}: ${parsed.error}`);
704
+ continue;
705
+ }
706
+ if (parsed.kind !== 'bare' && !known.has(parsed.server)) {
707
+ violations.push(`tools.${list}: "${raw}" names MCP server "${parsed.server}", which this agent does not connect — declare it under mcpServers or use one of: ${[...known].join(', ')}`);
708
+ }
709
+ }
710
+ }
711
+ return violations;
712
+ }
610
713
  /**
611
714
  * Platform default MCP server map. Seeded under every declared map by
612
715
  * {@link effectiveMcpServers} (opt out with `ggui: false`). Exposed here so
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guuey/config",
3
- "version": "0.6.1",
3
+ "version": "0.7.1",
4
4
  "description": "Open-source schemas + loaders for the three guuey config files: agent.json (declarative agent definition), guuey.json (hosted-deploy overlay), and the helper types around them. Consumed by @guuey/cli, the guuey backend, and devs writing their own agent or MCP server.",
5
5
  "license": "MIT",
6
6
  "type": "module",