@agentwares/agentguard 0.1.9 → 0.1.10
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/CHANGELOG.md +33 -0
- package/dist/audit-5LUDXZLG.js +18 -0
- package/dist/chunk-2QDPPTPY.js +179 -0
- package/dist/chunk-2QDPPTPY.js.map +1 -0
- package/dist/{chunk-SUXQTT3X.js → chunk-4WTFMFRY.js} +18 -16
- package/dist/chunk-4WTFMFRY.js.map +1 -0
- package/dist/{chunk-VQWQ5TOM.js → chunk-DEVXG3IB.js} +4 -4
- package/dist/chunk-DEVXG3IB.js.map +1 -0
- package/dist/chunk-F73VDY3W.js +202 -0
- package/dist/chunk-F73VDY3W.js.map +1 -0
- package/dist/{chunk-X4M7YWQA.js → chunk-IEJK7N3B.js} +32 -27
- package/dist/chunk-IEJK7N3B.js.map +1 -0
- package/dist/{chunk-ZSLWPKXI.js → chunk-IS3DAHZI.js} +562 -8
- package/dist/chunk-IS3DAHZI.js.map +1 -0
- package/dist/{chunk-KRKZGAJ3.js → chunk-JSELR4SG.js} +66 -55
- package/dist/chunk-JSELR4SG.js.map +1 -0
- package/dist/{chunk-TW5KJREH.js → chunk-OM5L7A32.js} +20 -11
- package/dist/chunk-OM5L7A32.js.map +1 -0
- package/dist/{chunk-HPYZ3JDX.js → chunk-SWZQMPDG.js} +3 -3
- package/dist/{chunk-HPYZ3JDX.js.map → chunk-SWZQMPDG.js.map} +1 -1
- package/dist/{chunk-D66U3PVB.js → chunk-TJXZBOHL.js} +6 -6
- package/dist/chunk-TJXZBOHL.js.map +1 -0
- package/dist/{chunk-BKXXTWIS.js → chunk-XOBFANL4.js} +5 -5
- package/dist/chunk-XOBFANL4.js.map +1 -0
- package/dist/chunk-XPNBYSIN.js +23 -0
- package/dist/chunk-XPNBYSIN.js.map +1 -0
- package/dist/{chunk-6S7LYVOC.js → chunk-YBVD6HTT.js} +27 -24
- package/dist/chunk-YBVD6HTT.js.map +1 -0
- package/dist/{chunk-6TUQD666.js → chunk-ZG4LGUJE.js} +100 -81
- package/dist/chunk-ZG4LGUJE.js.map +1 -0
- package/dist/cli.js +6 -4
- package/dist/fixtures/crm-server.js +2 -2
- package/dist/fixtures/demo-agent.js +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +23 -21
- package/dist/index.js.map +1 -1
- package/dist/init-MKPQU2JG.js +17 -0
- package/dist/{proxy-3Z5YEZ4R.js → proxy-6GP63TLD.js} +21 -29
- package/dist/proxy-6GP63TLD.js.map +1 -0
- package/dist/tools-XS7PMTLT.js +15 -0
- package/llms.txt +8 -6
- package/package.json +10 -4
- package/server.json +9 -9
- package/dist/audit-2YCMHMCP.js +0 -17
- package/dist/chunk-3O6KWT3E.js +0 -345
- package/dist/chunk-3O6KWT3E.js.map +0 -1
- package/dist/chunk-6S7LYVOC.js.map +0 -1
- package/dist/chunk-6TUQD666.js.map +0 -1
- package/dist/chunk-BKXXTWIS.js.map +0 -1
- package/dist/chunk-D66U3PVB.js.map +0 -1
- package/dist/chunk-KRKZGAJ3.js.map +0 -1
- package/dist/chunk-SUXQTT3X.js.map +0 -1
- package/dist/chunk-TW5KJREH.js.map +0 -1
- package/dist/chunk-VQWQ5TOM.js.map +0 -1
- package/dist/chunk-X4M7YWQA.js.map +0 -1
- package/dist/chunk-ZSLWPKXI.js.map +0 -1
- package/dist/init-CWROGV5I.js +0 -15
- package/dist/proxy-3Z5YEZ4R.js.map +0 -1
- package/dist/tools-3LLDG3XQ.js +0 -15
- /package/dist/{audit-2YCMHMCP.js.map → audit-5LUDXZLG.js.map} +0 -0
- /package/dist/{init-CWROGV5I.js.map → init-MKPQU2JG.js.map} +0 -0
- /package/dist/{tools-3LLDG3XQ.js.map → tools-XS7PMTLT.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/fixtures/crm-server.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * Fake CRM MCP server used by the tests, the demo agent and the README walkthrough. In-memory\n * contacts; every mutation is recorded so tests can assert what really happened upstream.\n *\n * node dist/fixtures/crm-server.js # stdio\n * node dist/fixtures/crm-server.js --http # Streamable HTTP on 127.0.0.1:<port> (prints the URL)\n */\nimport {\n createHttpHandler,\n createMcpServer,\n defineTool,\n handleHealth,\n localhostHosts,\n serveNodeHttp,\n serveStdio,\n toolError,\n type ToolDef,\n} from \"@agentwares/mcp-kit\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n\nexport interface Contact {\n id: string;\n name: string;\n email: string;\n updated_at: string;\n}\n\nexport interface CrmState {\n contacts: Map<string, Contact>;\n mutations: { tool: string; args: unknown }[];\n emails: { to: string; subject: string }[];\n charges: { customer_id: string; amount_usd: number }[];\n}\n\nexport function seedState(): CrmState {\n const contacts = new Map<string, Contact>();\n for (const [id, name, email] of [\n [\"c_1\", \"Ada Lovelace\", \"ada@example.com\"],\n [\"c_2\", \"Grace Hopper\", \"grace@example.com\"],\n [\"c_3\", \"Linus Torvalds\", \"linus@example.com\"],\n ] as const) {\n contacts.set(id, { id, name, email, updated_at: \"2026-01-01T00:00:00.000Z\" });\n }\n return { contacts, mutations: [], emails: [], charges: [] };\n}\n\nlet counter = 0;\nconst nextId = (prefix: string): string => `${prefix}_${(++counter).toString(36).padStart(4, \"0\")}`;\n\nexport function crmTools(state: CrmState): ToolDef[] {\n const contactSchema = z.object({\n id: z.string(),\n name: z.string(),\n email: z.string(),\n updated_at: z.string(),\n });\n return [\n defineTool({\n name: \"crm_list_contacts\",\n description:\n \"List every contact in the CRM. Read-only; returns id, name, email and updated_at.\",\n input: z.object({ limit: z.number().int().min(1).max(500).default(100) }),\n output: z.object({ contacts: z.array(contactSchema), total: z.number() }),\n annotations: { readOnlyHint: true },\n handler: ({ limit }) => ({\n contacts: [...state.contacts.values()].slice(0, limit),\n total: state.contacts.size,\n }),\n }),\n defineTool({\n name: \"crm_get_contact\",\n description: \"Fetch one contact by id. Read-only; NOT_FOUND when the id does not exist.\",\n input: z.object({ id: z.string() }),\n output: contactSchema,\n annotations: { readOnlyHint: true },\n handler: ({ id }) => {\n const c = state.contacts.get(id);\n if (!c)\n throw toolError(\n \"NOT_FOUND\",\n `no contact ${id}`,\n \"call crm_list_contacts and use an existing id\",\n );\n return c;\n },\n }),\n defineTool({\n name: \"crm_search\",\n description:\n \"Search contacts by name or email substring. Returns matching contacts (no annotations on purpose).\",\n input: z.object({ query: z.string() }),\n handler: ({ query }) => ({\n contacts: [...state.contacts.values()].filter((c) =>\n `${c.name} ${c.email}`.toLowerCase().includes(query.toLowerCase()),\n ),\n }),\n }),\n defineTool({\n name: \"crm_create_contact\",\n description: \"Create a contact. Returns the new id and created_at timestamp.\",\n input: z.object({ name: z.string(), email: z.string() }),\n output: z.object({ id: z.string(), created_at: z.string() }),\n annotations: { readOnlyHint: false, destructiveHint: false },\n handler: ({ name, email }) => {\n const id = nextId(\"c\");\n const now = new Date().toISOString();\n state.contacts.set(id, { id, name, email, updated_at: now });\n state.mutations.push({ tool: \"crm_create_contact\", args: { name, email } });\n return { id, created_at: now };\n },\n }),\n defineTool({\n name: \"crm_update_contact\",\n description:\n \"Update fields on a contact. Returns the id and updated_at; NOT_FOUND for unknown ids.\",\n input: z.object({\n id: z.string(),\n fields: z.object({ name: z.string().optional(), email: z.string().optional() }),\n }),\n output: z.object({ id: z.string(), updated_at: z.string() }),\n annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },\n handler: ({ id, fields }) => {\n const c = state.contacts.get(id);\n if (!c)\n throw toolError(\n \"NOT_FOUND\",\n `no contact ${id}`,\n \"call crm_list_contacts and use an existing id\",\n );\n Object.assign(c, fields, { updated_at: new Date().toISOString() });\n state.mutations.push({ tool: \"crm_update_contact\", args: { id, fields } });\n return { id, updated_at: c.updated_at };\n },\n }),\n defineTool({\n name: \"crm_delete_contact\",\n description: \"Permanently delete a contact. Irreversible. Returns { deleted, id }.\",\n input: z.object({ id: z.string() }),\n output: z.object({ deleted: z.boolean(), id: z.string() }),\n annotations: { readOnlyHint: false, destructiveHint: true },\n handler: ({ id }) => {\n const existed = state.contacts.delete(id);\n state.mutations.push({ tool: \"crm_delete_contact\", args: { id } });\n return { deleted: existed, id };\n },\n }),\n defineTool({\n name: \"crm_send_email\",\n description:\n \"Send an email to a contact through the CRM. Returns the message id and sent_at.\",\n input: z.object({ to: z.string(), subject: z.string(), body: z.string() }),\n output: z.object({ message_id: z.string(), sent_at: z.string() }),\n handler: ({ to, subject }) => {\n state.emails.push({ to, subject });\n state.mutations.push({ tool: \"crm_send_email\", args: { to, subject } });\n return { message_id: nextId(\"msg\"), sent_at: new Date().toISOString() };\n },\n }),\n defineTool({\n name: \"crm_charge_card\",\n description:\n \"Charge a customer's card on file (amount in cents). Returns the charge id and amount_usd.\",\n input: z.object({\n customer_id: z.string(),\n amount_cents: z.number().int().positive(),\n currency: z.string().default(\"usd\"),\n }),\n output: z.object({ charge_id: z.string(), amount_usd: z.number() }),\n handler: ({ customer_id, amount_cents }) => {\n const amount_usd = amount_cents / 100;\n state.charges.push({ customer_id, amount_usd });\n state.mutations.push({ tool: \"crm_charge_card\", args: { customer_id, amount_usd } });\n return { charge_id: nextId(\"ch\"), amount_usd };\n },\n }),\n defineTool({\n name: \"crm_frobnicate\",\n description:\n \"A tool with no annotations and no recognizable verb — exists to test `unknown` handling.\",\n input: z.object({}),\n handler: () => {\n state.mutations.push({ tool: \"crm_frobnicate\", args: {} });\n return { frobnicated: true };\n },\n }),\n defineTool({\n name: \"crm_fail\",\n description: \"Always returns a structured UPSTREAM_ERROR result, for error-path tests.\",\n input: z.object({}),\n annotations: { readOnlyHint: true },\n handler: () => {\n throw toolError(\"UPSTREAM_ERROR\", \"the CRM is having a bad day\", \"retry in a minute\", {\n retryable: true,\n });\n },\n }),\n ];\n}\n\nexport function createCrmMcpServer(state: CrmState = seedState()): McpServer {\n return createMcpServer({\n name: \"fake-crm\",\n version: \"0.1.0\",\n instructions: \"A fake CRM for agentguard tests. Nothing here is real.\",\n tools: crmTools(state),\n });\n}\n\nconst isMain = process.argv[1] !== undefined && /crm-server\\.[cm]?[jt]s$/.test(process.argv[1]);\nif (isMain) {\n const state = seedState();\n if (process.argv.includes(\"--http\")) {\n const portArg = process.argv.find((a) => a.startsWith(\"--port=\"));\n const port = portArg ? Number(portArg.slice(\"--port=\".length)) : 0;\n const handler = createHttpHandler(() => createCrmMcpServer(state), {\n sessions: true,\n jsonResponse: false,\n allowedHosts: port ? localhostHosts(port) : undefined,\n });\n const server = await serveNodeHttp({\n handler,\n port,\n health: () =>\n handleHealth({ name: \"fake-crm\", version: \"0.1.0\", tools: crmTools(state).length }),\n });\n console.log(`fake-crm listening at ${server.url}`);\n } else {\n // The proxy stops us with SIGTERM; exit on it so Node does not warn about the unsettled\n // top-level await into the parent's stderr at the end of the demo.\n for (const signal of [\"SIGTERM\", \"SIGINT\"] as const) process.on(signal, () => process.exit(0));\n await serveStdio(createCrmMcpServer(state));\n }\n}\n"],"mappings":";;;;;;;;;;;;AAoBA,SAAS,SAAS;AAgBX,SAAS,YAAsB;AACpC,QAAM,WAAW,oBAAI,IAAqB;AAC1C,aAAW,CAAC,IAAI,MAAM,KAAK,KAAK;AAAA,IAC9B,CAAC,OAAO,gBAAgB,iBAAiB;AAAA,IACzC,CAAC,OAAO,gBAAgB,mBAAmB;AAAA,IAC3C,CAAC,OAAO,kBAAkB,mBAAmB;AAAA,EAC/C,GAAY;AACV,aAAS,IAAI,IAAI,EAAE,IAAI,MAAM,OAAO,YAAY,2BAA2B,CAAC;AAAA,EAC9E;AACA,SAAO,EAAE,UAAU,WAAW,CAAC,GAAG,QAAQ,CAAC,GAAG,SAAS,CAAC,EAAE;AAC5D;AAEA,IAAI,UAAU;AACd,IAAM,SAAS,CAAC,WAA2B,GAAG,MAAM,KAAK,EAAE,SAAS,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC;AAE1F,SAAS,SAAS,OAA4B;AACnD,QAAM,gBAAgB,EAAE,OAAO;AAAA,IAC7B,IAAI,EAAE,OAAO;AAAA,IACb,MAAM,EAAE,OAAO;AAAA,IACf,OAAO,EAAE,OAAO;AAAA,IAChB,YAAY,EAAE,OAAO;AAAA,EACvB,CAAC;AACD,SAAO;AAAA,IACL,WAAW;AAAA,MACT,MAAM;AAAA,MACN,aACE;AAAA,MACF,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,GAAG,EAAE,CAAC;AAAA,MACxE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC;AAAA,MACxE,aAAa,EAAE,cAAc,KAAK;AAAA,MAClC,SAAS,CAAC,EAAE,MAAM,OAAO;AAAA,QACvB,UAAU,CAAC,GAAG,MAAM,SAAS,OAAO,CAAC,EAAE,MAAM,GAAG,KAAK;AAAA,QACrD,OAAO,MAAM,SAAS;AAAA,MACxB;AAAA,IACF,CAAC;AAAA,IACD,WAAW;AAAA,MACT,MAAM;AAAA,MACN,aAAa;AAAA,MACb,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAAA,MAClC,QAAQ;AAAA,MACR,aAAa,EAAE,cAAc,KAAK;AAAA,MAClC,SAAS,CAAC,EAAE,GAAG,MAAM;AACnB,cAAM,IAAI,MAAM,SAAS,IAAI,EAAE;AAC/B,YAAI,CAAC;AACH,gBAAM;AAAA,YACJ;AAAA,YACA,cAAc,EAAE;AAAA,YAChB;AAAA,UACF;AACF,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAAA,IACD,WAAW;AAAA,MACT,MAAM;AAAA,MACN,aACE;AAAA,MACF,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAAA,MACrC,SAAS,CAAC,EAAE,MAAM,OAAO;AAAA,QACvB,UAAU,CAAC,GAAG,MAAM,SAAS,OAAO,CAAC,EAAE;AAAA,UAAO,CAAC,MAC7C,GAAG,EAAE,IAAI,IAAI,EAAE,KAAK,GAAG,YAAY,EAAE,SAAS,MAAM,YAAY,CAAC;AAAA,QACnE;AAAA,MACF;AAAA,IACF,CAAC;AAAA,IACD,WAAW;AAAA,MACT,MAAM;AAAA,MACN,aAAa;AAAA,MACb,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC;AAAA,MACvD,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,YAAY,EAAE,OAAO,EAAE,CAAC;AAAA,MAC3D,aAAa,EAAE,cAAc,OAAO,iBAAiB,MAAM;AAAA,MAC3D,SAAS,CAAC,EAAE,MAAM,MAAM,MAAM;AAC5B,cAAM,KAAK,OAAO,GAAG;AACrB,cAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,cAAM,SAAS,IAAI,IAAI,EAAE,IAAI,MAAM,OAAO,YAAY,IAAI,CAAC;AAC3D,cAAM,UAAU,KAAK,EAAE,MAAM,sBAAsB,MAAM,EAAE,MAAM,MAAM,EAAE,CAAC;AAC1E,eAAO,EAAE,IAAI,YAAY,IAAI;AAAA,MAC/B;AAAA,IACF,CAAC;AAAA,IACD,WAAW;AAAA,MACT,MAAM;AAAA,MACN,aACE;AAAA,MACF,OAAO,EAAE,OAAO;AAAA,QACd,IAAI,EAAE,OAAO;AAAA,QACb,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,GAAG,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AAAA,MAChF,CAAC;AAAA,MACD,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,YAAY,EAAE,OAAO,EAAE,CAAC;AAAA,MAC3D,aAAa,EAAE,cAAc,OAAO,iBAAiB,OAAO,gBAAgB,KAAK;AAAA,MACjF,SAAS,CAAC,EAAE,IAAI,OAAO,MAAM;AAC3B,cAAM,IAAI,MAAM,SAAS,IAAI,EAAE;AAC/B,YAAI,CAAC;AACH,gBAAM;AAAA,YACJ;AAAA,YACA,cAAc,EAAE;AAAA,YAChB;AAAA,UACF;AACF,eAAO,OAAO,GAAG,QAAQ,EAAE,aAAY,oBAAI,KAAK,GAAE,YAAY,EAAE,CAAC;AACjE,cAAM,UAAU,KAAK,EAAE,MAAM,sBAAsB,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;AACzE,eAAO,EAAE,IAAI,YAAY,EAAE,WAAW;AAAA,MACxC;AAAA,IACF,CAAC;AAAA,IACD,WAAW;AAAA,MACT,MAAM;AAAA,MACN,aAAa;AAAA,MACb,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAAA,MAClC,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,GAAG,IAAI,EAAE,OAAO,EAAE,CAAC;AAAA,MACzD,aAAa,EAAE,cAAc,OAAO,iBAAiB,KAAK;AAAA,MAC1D,SAAS,CAAC,EAAE,GAAG,MAAM;AACnB,cAAM,UAAU,MAAM,SAAS,OAAO,EAAE;AACxC,cAAM,UAAU,KAAK,EAAE,MAAM,sBAAsB,MAAM,EAAE,GAAG,EAAE,CAAC;AACjE,eAAO,EAAE,SAAS,SAAS,GAAG;AAAA,MAChC;AAAA,IACF,CAAC;AAAA,IACD,WAAW;AAAA,MACT,MAAM;AAAA,MACN,aACE;AAAA,MACF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,SAAS,EAAE,OAAO,GAAG,MAAM,EAAE,OAAO,EAAE,CAAC;AAAA,MACzE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,GAAG,SAAS,EAAE,OAAO,EAAE,CAAC;AAAA,MAChE,SAAS,CAAC,EAAE,IAAI,QAAQ,MAAM;AAC5B,cAAM,OAAO,KAAK,EAAE,IAAI,QAAQ,CAAC;AACjC,cAAM,UAAU,KAAK,EAAE,MAAM,kBAAkB,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;AACtE,eAAO,EAAE,YAAY,OAAO,KAAK,GAAG,UAAS,oBAAI,KAAK,GAAE,YAAY,EAAE;AAAA,MACxE;AAAA,IACF,CAAC;AAAA,IACD,WAAW;AAAA,MACT,MAAM;AAAA,MACN,aACE;AAAA,MACF,OAAO,EAAE,OAAO;AAAA,QACd,aAAa,EAAE,OAAO;AAAA,QACtB,cAAc,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,QACxC,UAAU,EAAE,OAAO,EAAE,QAAQ,KAAK;AAAA,MACpC,CAAC;AAAA,MACD,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,GAAG,YAAY,EAAE,OAAO,EAAE,CAAC;AAAA,MAClE,SAAS,CAAC,EAAE,aAAa,aAAa,MAAM;AAC1C,cAAM,aAAa,eAAe;AAClC,cAAM,QAAQ,KAAK,EAAE,aAAa,WAAW,CAAC;AAC9C,cAAM,UAAU,KAAK,EAAE,MAAM,mBAAmB,MAAM,EAAE,aAAa,WAAW,EAAE,CAAC;AACnF,eAAO,EAAE,WAAW,OAAO,IAAI,GAAG,WAAW;AAAA,MAC/C;AAAA,IACF,CAAC;AAAA,IACD,WAAW;AAAA,MACT,MAAM;AAAA,MACN,aACE;AAAA,MACF,OAAO,EAAE,OAAO,CAAC,CAAC;AAAA,MAClB,SAAS,MAAM;AACb,cAAM,UAAU,KAAK,EAAE,MAAM,kBAAkB,MAAM,CAAC,EAAE,CAAC;AACzD,eAAO,EAAE,aAAa,KAAK;AAAA,MAC7B;AAAA,IACF,CAAC;AAAA,IACD,WAAW;AAAA,MACT,MAAM;AAAA,MACN,aAAa;AAAA,MACb,OAAO,EAAE,OAAO,CAAC,CAAC;AAAA,MAClB,aAAa,EAAE,cAAc,KAAK;AAAA,MAClC,SAAS,MAAM;AACb,cAAM,UAAU,kBAAkB,+BAA+B,qBAAqB;AAAA,UACpF,WAAW;AAAA,QACb,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEO,SAAS,mBAAmB,QAAkB,UAAU,GAAc;AAC3E,SAAO,gBAAgB;AAAA,IACrB,MAAM;AAAA,IACN,SAAS;AAAA,IACT,cAAc;AAAA,IACd,OAAO,SAAS,KAAK;AAAA,EACvB,CAAC;AACH;AAEA,IAAM,SAAS,QAAQ,KAAK,CAAC,MAAM,UAAa,0BAA0B,KAAK,QAAQ,KAAK,CAAC,CAAC;AAC9F,IAAI,QAAQ;AACV,QAAM,QAAQ,UAAU;AACxB,MAAI,QAAQ,KAAK,SAAS,QAAQ,GAAG;AACnC,UAAM,UAAU,QAAQ,KAAK,KAAK,CAAC,MAAM,EAAE,WAAW,SAAS,CAAC;AAChE,UAAM,OAAO,UAAU,OAAO,QAAQ,MAAM,UAAU,MAAM,CAAC,IAAI;AACjE,UAAM,UAAU,kBAAkB,MAAM,mBAAmB,KAAK,GAAG;AAAA,MACjE,UAAU;AAAA,MACV,cAAc;AAAA,MACd,cAAc,OAAO,eAAe,IAAI,IAAI;AAAA,IAC9C,CAAC;AACD,UAAM,SAAS,MAAM,cAAc;AAAA,MACjC;AAAA,MACA;AAAA,MACA,QAAQ,MACN,aAAa,EAAE,MAAM,YAAY,SAAS,SAAS,OAAO,SAAS,KAAK,EAAE,OAAO,CAAC;AAAA,IACtF,CAAC;AACD,YAAQ,IAAI,yBAAyB,OAAO,GAAG,EAAE;AAAA,EACnD,OAAO;AAGL,eAAW,UAAU,CAAC,WAAW,QAAQ,EAAY,SAAQ,GAAG,QAAQ,MAAM,QAAQ,KAAK,CAAC,CAAC;AAC7F,UAAM,WAAW,mBAAmB,KAAK,CAAC;AAAA,EAC5C;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/fixtures/crm-server.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * Fake CRM MCP server used by the tests, the demo agent and the README walkthrough. In-memory\n * contacts; every mutation is recorded so tests can assert what really happened upstream.\n *\n * node dist/fixtures/crm-server.js # stdio\n * node dist/fixtures/crm-server.js --http # Streamable HTTP on 127.0.0.1:<port> (prints the URL)\n */\nimport {\n createHttpHandler,\n createMcpServer,\n defineTool,\n handleHealth,\n localhostHosts,\n serveNodeHttp,\n serveStdio,\n toolError,\n type ToolDef,\n} from \"@agentwares/mcp-kit\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n\nexport interface Contact {\n id: string;\n name: string;\n email: string;\n updated_at: string;\n}\n\nexport interface CrmState {\n contacts: Map<string, Contact>;\n mutations: { tool: string; args: unknown }[];\n emails: { to: string; subject: string }[];\n charges: { customer_id: string; amount_usd: number }[];\n}\n\nexport function seedState(): CrmState {\n const contacts = new Map<string, Contact>();\n for (const [id, name, email] of [\n [\"c_1\", \"Ada Lovelace\", \"ada@example.com\"],\n [\"c_2\", \"Grace Hopper\", \"grace@example.com\"],\n [\"c_3\", \"Linus Torvalds\", \"linus@example.com\"],\n ] as const) {\n contacts.set(id, { id, name, email, updated_at: \"2026-01-01T00:00:00.000Z\" });\n }\n return { contacts, mutations: [], emails: [], charges: [] };\n}\n\nlet counter = 0;\nconst nextId = (prefix: string): string => `${prefix}_${(++counter).toString(36).padStart(4, \"0\")}`;\n\nexport function crmTools(state: CrmState): ToolDef[] {\n const contactSchema = z.object({\n id: z.string(),\n name: z.string(),\n email: z.string(),\n updated_at: z.string(),\n });\n return [\n defineTool({\n name: \"crm_list_contacts\",\n description:\n \"List every contact in the CRM. Read-only; returns id, name, email and updated_at.\",\n input: z.object({ limit: z.number().int().min(1).max(500).default(100) }),\n output: z.object({ contacts: z.array(contactSchema), total: z.number() }),\n annotations: { readOnlyHint: true },\n handler: ({ limit }) => ({\n contacts: [...state.contacts.values()].slice(0, limit),\n total: state.contacts.size,\n }),\n }),\n defineTool({\n name: \"crm_get_contact\",\n description: \"Fetch one contact by id. Read-only; NOT_FOUND when the id does not exist.\",\n input: z.object({ id: z.string() }),\n output: contactSchema,\n annotations: { readOnlyHint: true },\n handler: ({ id }) => {\n const c = state.contacts.get(id);\n if (!c)\n throw toolError(\n \"NOT_FOUND\",\n `no contact ${id}`,\n \"call crm_list_contacts and use an existing id\",\n );\n return c;\n },\n }),\n defineTool({\n name: \"crm_search\",\n description:\n \"Search contacts by name or email substring. Returns matching contacts (no annotations on purpose).\",\n input: z.object({ query: z.string() }),\n handler: ({ query }) => ({\n contacts: [...state.contacts.values()].filter((c) =>\n `${c.name} ${c.email}`.toLowerCase().includes(query.toLowerCase()),\n ),\n }),\n }),\n defineTool({\n name: \"crm_create_contact\",\n description: \"Create a contact. Returns the new id and created_at timestamp.\",\n input: z.object({ name: z.string(), email: z.string() }),\n output: z.object({ id: z.string(), created_at: z.string() }),\n annotations: { readOnlyHint: false, destructiveHint: false },\n handler: ({ name, email }) => {\n const id = nextId(\"c\");\n const now = new Date().toISOString();\n state.contacts.set(id, { id, name, email, updated_at: now });\n state.mutations.push({ tool: \"crm_create_contact\", args: { name, email } });\n return { id, created_at: now };\n },\n }),\n defineTool({\n name: \"crm_update_contact\",\n description:\n \"Update fields on a contact. Returns the id and updated_at; NOT_FOUND for unknown ids.\",\n input: z.object({\n id: z.string(),\n fields: z.object({ name: z.string().optional(), email: z.string().optional() }),\n }),\n output: z.object({ id: z.string(), updated_at: z.string() }),\n annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true },\n handler: ({ id, fields }) => {\n const c = state.contacts.get(id);\n if (!c)\n throw toolError(\n \"NOT_FOUND\",\n `no contact ${id}`,\n \"call crm_list_contacts and use an existing id\",\n );\n Object.assign(c, fields, { updated_at: new Date().toISOString() });\n state.mutations.push({ tool: \"crm_update_contact\", args: { id, fields } });\n return { id, updated_at: c.updated_at };\n },\n }),\n defineTool({\n name: \"crm_delete_contact\",\n description: \"Permanently delete a contact. Irreversible. Returns { deleted, id }.\",\n input: z.object({ id: z.string() }),\n output: z.object({ deleted: z.boolean(), id: z.string() }),\n annotations: { readOnlyHint: false, destructiveHint: true },\n handler: ({ id }) => {\n const existed = state.contacts.delete(id);\n state.mutations.push({ tool: \"crm_delete_contact\", args: { id } });\n return { deleted: existed, id };\n },\n }),\n defineTool({\n name: \"crm_send_email\",\n description:\n \"Send an email to a contact through the CRM. Returns the message id and sent_at.\",\n input: z.object({ to: z.string(), subject: z.string(), body: z.string() }),\n output: z.object({ message_id: z.string(), sent_at: z.string() }),\n handler: ({ to, subject }) => {\n state.emails.push({ to, subject });\n state.mutations.push({ tool: \"crm_send_email\", args: { to, subject } });\n return { message_id: nextId(\"msg\"), sent_at: new Date().toISOString() };\n },\n }),\n defineTool({\n name: \"crm_charge_card\",\n description:\n \"Charge a customer's card on file (amount in cents). Returns the charge id and amount_usd.\",\n input: z.object({\n customer_id: z.string(),\n amount_cents: z.number().int().positive(),\n currency: z.string().default(\"usd\"),\n }),\n output: z.object({ charge_id: z.string(), amount_usd: z.number() }),\n handler: ({ customer_id, amount_cents }) => {\n const amount_usd = amount_cents / 100;\n state.charges.push({ customer_id, amount_usd });\n state.mutations.push({ tool: \"crm_charge_card\", args: { customer_id, amount_usd } });\n return { charge_id: nextId(\"ch\"), amount_usd };\n },\n }),\n defineTool({\n name: \"crm_frobnicate\",\n description:\n \"A tool with no annotations and no recognizable verb — exists to test `unknown` handling.\",\n input: z.object({}),\n handler: () => {\n state.mutations.push({ tool: \"crm_frobnicate\", args: {} });\n return { frobnicated: true };\n },\n }),\n defineTool({\n name: \"crm_fail\",\n description: \"Always returns a structured UPSTREAM_ERROR result, for error-path tests.\",\n input: z.object({}),\n annotations: { readOnlyHint: true },\n handler: () => {\n throw toolError(\"UPSTREAM_ERROR\", \"the CRM is having a bad day\", \"retry in a minute\", {\n retryable: true,\n });\n },\n }),\n ];\n}\n\nexport function createCrmMcpServer(state: CrmState = seedState()): McpServer {\n return createMcpServer({\n name: \"fake-crm\",\n version: \"0.1.0\",\n instructions: \"A fake CRM for okgate tests. Nothing here is real.\",\n tools: crmTools(state),\n });\n}\n\nconst isMain = process.argv[1] !== undefined && /crm-server\\.[cm]?[jt]s$/.test(process.argv[1]);\nif (isMain) {\n const state = seedState();\n if (process.argv.includes(\"--http\")) {\n const portArg = process.argv.find((a) => a.startsWith(\"--port=\"));\n const port = portArg ? Number(portArg.slice(\"--port=\".length)) : 0;\n const handler = createHttpHandler(() => createCrmMcpServer(state), {\n sessions: true,\n jsonResponse: false,\n allowedHosts: port ? localhostHosts(port) : undefined,\n });\n const server = await serveNodeHttp({\n handler,\n port,\n health: () =>\n handleHealth({ name: \"fake-crm\", version: \"0.1.0\", tools: crmTools(state).length }),\n });\n console.log(`fake-crm listening at ${server.url}`);\n } else {\n // The proxy stops us with SIGTERM; exit on it so Node does not warn about the unsettled\n // top-level await into the parent's stderr at the end of the demo.\n for (const signal of [\"SIGTERM\", \"SIGINT\"] as const) process.on(signal, () => process.exit(0));\n await serveStdio(createCrmMcpServer(state));\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
readAllPages
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-IS3DAHZI.js";
|
|
4
4
|
import {
|
|
5
5
|
version
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-4WTFMFRY.js";
|
|
7
7
|
|
|
8
8
|
// src/proxy/runtime.ts
|
|
9
9
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
@@ -49,7 +49,7 @@ var ProxyRuntime = class {
|
|
|
49
49
|
this.agent = opts.agent;
|
|
50
50
|
this.defaultRunId = opts.defaultRunId;
|
|
51
51
|
this.configured = opts.configured ?? true;
|
|
52
|
-
this.log = opts.log ?? ((line) => process.stderr.write(`[
|
|
52
|
+
this.log = opts.log ?? ((line) => process.stderr.write(`[okgate] ${line}
|
|
53
53
|
`));
|
|
54
54
|
this.connectTimeoutMs = opts.connectTimeoutMs ?? 15e3;
|
|
55
55
|
this.testClients = opts.clients ?? {};
|
|
@@ -89,7 +89,7 @@ var ProxyRuntime = class {
|
|
|
89
89
|
}
|
|
90
90
|
async connect(upstream) {
|
|
91
91
|
const client = new Client(
|
|
92
|
-
{ name: "
|
|
92
|
+
{ name: "okgate", version: version() },
|
|
93
93
|
{ capabilities: { sampling: {}, elicitation: {} } }
|
|
94
94
|
);
|
|
95
95
|
const conn = {
|
|
@@ -335,7 +335,7 @@ var ProxyRuntime = class {
|
|
|
335
335
|
throw new GuardError({
|
|
336
336
|
code: "UPSTREAM_ERROR",
|
|
337
337
|
cause: `upstream "${tool.upstream}" is not connected${conn?.error ? ` (${conn.error})` : ""}`,
|
|
338
|
-
fix: "check the upstream command/url in
|
|
338
|
+
fix: "check the upstream command/url in okgate.yaml and restart the proxy",
|
|
339
339
|
retryable: true
|
|
340
340
|
});
|
|
341
341
|
}
|
|
@@ -526,4 +526,4 @@ async function withTimeout(promise, ms, what) {
|
|
|
526
526
|
export {
|
|
527
527
|
ProxyRuntime
|
|
528
528
|
};
|
|
529
|
-
//# sourceMappingURL=chunk-
|
|
529
|
+
//# sourceMappingURL=chunk-TJXZBOHL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/proxy/runtime.ts"],"sourcesContent":["/**\n * Upstream side of the proxy: one MCP client per upstream (stdio or Streamable HTTP), the merged\n * tool table, resource/prompt routing, notification fan-out to downstream sessions, and\n * `callTool` through the policy engine.\n */\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { version as cliVersion } from \"../version.js\";\nimport {\n getDefaultEnvironment,\n StdioClientTransport,\n} from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport {\n CreateMessageRequestSchema,\n ElicitRequestSchema,\n LoggingMessageNotificationSchema,\n PromptListChangedNotificationSchema,\n ResourceListChangedNotificationSchema,\n ResourceUpdatedNotificationSchema,\n ToolListChangedNotificationSchema,\n type CallToolResult,\n type CompleteRequest,\n type CompleteResult,\n type GetPromptResult,\n type ListPromptsResult,\n type ListResourceTemplatesResult,\n type ListResourcesResult,\n type LoggingLevel,\n type Prompt,\n type ReadResourceResult,\n type Resource,\n type ResourceTemplate,\n type Tool,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { RequestId } from \"@modelcontextprotocol/sdk/types.js\";\nimport {\n GuardError,\n classifyTool,\n upstreamHeaders,\n type AgentScope,\n type Classification,\n type Guard,\n type GuardResult,\n type Upstream,\n} from \"@agentwares/agentguard-core\";\nimport type { LoadedPolicy } from \"@agentwares/agentguard-core/node\";\n// The root export, not `@agentwares/mcp-kit/paging`: tsup bundles mcp-kit into the published CLI\n// by an exact-name match, and a subpath would be left as an undeclared runtime dependency.\nimport { readAllPages } from \"@agentwares/mcp-kit\";\n\nexport interface ExposedTool {\n /** the name the agent sees */\n name: string;\n upstream: string;\n /** the name the upstream knows */\n original: string;\n tool: Tool;\n classification: Classification;\n}\n\nexport interface DownstreamSession {\n id: string;\n server: McpServer;\n lastActive: number;\n /** upstream name → downstream request ids currently waiting on it (newest last) */\n inflight: Map<string, RequestId[]>;\n}\n\nexport interface UpstreamStatus {\n name: string;\n connected: boolean;\n tools: number;\n transport: \"stdio\" | \"http\";\n error?: string;\n}\n\ninterface Connection {\n upstream: Upstream;\n client: Client;\n tools: Tool[];\n capabilities: ReturnType<Client[\"getServerCapabilities\"]>;\n connected: boolean;\n error?: string;\n}\n\nexport interface RuntimeOptions {\n loaded: LoadedPolicy;\n guard: Guard;\n /** fixed agent scope for stdio (`--agent`) */\n agent?: AgentScope | null;\n /** run id when neither `X-Run-Id` nor `_meta.runId` is present */\n defaultRunId: string;\n log?: (line: string) => void;\n /** connect timeout per upstream (ms) */\n connectTimeoutMs?: number;\n /** in-process upstreams for tests: name → already-connected client */\n clients?: Record<string, Client>;\n /**\n * false when no policy file was found and the proxy runs on the default policy with no\n * upstreams, serving only its own read-only tools (default true)\n */\n configured?: boolean;\n}\n\nexport interface CallContext {\n runId: string;\n agent?: AgentScope | null;\n sessionId?: string;\n onprogress?: (progress: { progress: number; total?: number; message?: string }) => void;\n /** downstream session + request id, so upstream notifications can be related to this call */\n session?: DownstreamSession;\n requestId?: RequestId;\n}\n\nexport class ProxyRuntime {\n readonly loaded: LoadedPolicy;\n readonly guard: Guard;\n readonly agent: AgentScope | null | undefined;\n readonly defaultRunId: string;\n readonly configured: boolean;\n readonly sessions = new Set<DownstreamSession>();\n private readonly connections = new Map<string, Connection>();\n private exposed: ExposedTool[] = [];\n private readonly resourceOwner = new Map<string, string>();\n private readonly templateOwner = new Map<string, string>();\n private readonly promptOwner = new Map<string, { upstream: string; original: string }>();\n private readonly log: (line: string) => void;\n private readonly connectTimeoutMs: number;\n private readonly testClients: Record<string, Client>;\n /** stop relaying upstream stderr once we are tearing down — shutdown noise is not the user's problem */\n private closing = false;\n\n constructor(opts: RuntimeOptions) {\n this.loaded = opts.loaded;\n this.guard = opts.guard;\n this.agent = opts.agent;\n this.defaultRunId = opts.defaultRunId;\n this.configured = opts.configured ?? true;\n this.log = opts.log ?? ((line) => process.stderr.write(`[okgate] ${line}\\n`));\n this.connectTimeoutMs = opts.connectTimeoutMs ?? 15_000;\n this.testClients = opts.clients ?? {};\n }\n\n get policy() {\n return this.loaded.policy;\n }\n\n async start(): Promise<void> {\n await Promise.all(this.policy.upstreams.map((u) => this.connect(u)));\n for (const [name, client] of Object.entries(this.testClients)) {\n if (this.connections.has(name)) continue;\n const upstream: Upstream = {\n name,\n command: \"in-memory\",\n args: [],\n env: {},\n headers: {},\n prefix: false,\n timeout_ms: 60_000,\n };\n const conn: Connection = {\n upstream,\n client,\n tools: [],\n capabilities: client.getServerCapabilities(),\n connected: true,\n };\n this.connections.set(name, conn);\n this.wire(conn);\n await this.refreshTools(name);\n }\n this.rebuildExposed();\n const status = this.upstreamStatus();\n this.log(\n `connected ${status.filter((s) => s.connected).length}/${status.length} upstreams, ${this.exposed.length} tools, mode ${this.policy.mode}`,\n );\n }\n\n private async connect(upstream: Upstream): Promise<void> {\n const client = new Client(\n { name: \"okgate\", version: cliVersion() },\n { capabilities: { sampling: {}, elicitation: {} } },\n );\n const conn: Connection = {\n upstream,\n client,\n tools: [],\n capabilities: undefined,\n connected: false,\n };\n this.connections.set(upstream.name, conn);\n try {\n const transport = upstream.url\n ? new StreamableHTTPClientTransport(new URL(upstream.url), {\n requestInit: { headers: upstreamHeaders(upstream) },\n })\n : new StdioClientTransport({\n command: upstream.command!,\n args: upstream.args,\n env: { ...getDefaultEnvironment(), ...upstream.env },\n cwd: upstream.cwd,\n stderr: \"pipe\",\n });\n if (transport instanceof StdioClientTransport) {\n transport.stderr?.on(\"data\", (chunk: Buffer) => {\n if (this.closing) return;\n for (const line of chunk.toString(\"utf8\").split(\"\\n\"))\n if (line.trim()) this.log(`${upstream.name}: ${line}`);\n });\n }\n await withTimeout(\n client.connect(transport),\n this.connectTimeoutMs,\n `connect to upstream \"${upstream.name}\"`,\n );\n conn.capabilities = client.getServerCapabilities();\n conn.connected = true;\n this.wire(conn);\n await this.refreshTools(upstream.name);\n } catch (err) {\n conn.connected = false;\n conn.error = err instanceof Error ? err.message : String(err);\n this.log(`upstream \"${upstream.name}\" unavailable: ${conn.error}`);\n }\n }\n\n private wire(conn: Connection): void {\n const { client, upstream } = conn;\n client.onclose = () => {\n conn.connected = false;\n conn.error = \"connection closed\";\n if (!this.closing) this.log(`upstream \"${upstream.name}\" closed`);\n };\n client.setNotificationHandler(LoggingMessageNotificationSchema, async (n) => {\n await this.broadcast(upstream.name, n.method, n.params);\n });\n client.setNotificationHandler(ResourceUpdatedNotificationSchema, async (n) => {\n await this.broadcast(upstream.name, n.method, n.params);\n });\n client.setNotificationHandler(ResourceListChangedNotificationSchema, async () => {\n this.resourceOwner.clear();\n await this.broadcast(upstream.name, \"notifications/resources/list_changed\", undefined);\n });\n client.setNotificationHandler(PromptListChangedNotificationSchema, async () => {\n this.promptOwner.clear();\n await this.broadcast(upstream.name, \"notifications/prompts/list_changed\", undefined);\n });\n client.setNotificationHandler(ToolListChangedNotificationSchema, async () => {\n await this.refreshTools(upstream.name);\n this.rebuildExposed();\n for (const s of this.sessions) s.server.server.sendToolListChanged().catch(() => undefined);\n });\n // Relay server→client requests (sampling, elicitation) to the downstream session that is\n // waiting on this upstream. Clients created without those capabilities (tests) skip this.\n try {\n client.setRequestHandler(CreateMessageRequestSchema, async (req) => {\n const session = this.pickSession(upstream.name);\n if (!session) throw new Error(\"no downstream client is connected to relay sampling to\");\n const related = session.inflight.get(upstream.name)?.at(-1);\n return session.server.server.createMessage(req.params, { relatedRequestId: related });\n });\n client.setRequestHandler(ElicitRequestSchema, async (req) => {\n const session = this.pickSession(upstream.name);\n if (!session) throw new Error(\"no downstream client is connected to relay elicitation to\");\n const related = session.inflight.get(upstream.name)?.at(-1);\n return session.server.server.elicitInput(req.params, { relatedRequestId: related });\n });\n } catch {\n // client declared no sampling/elicitation capability\n }\n }\n\n private pickSession(upstream: string): DownstreamSession | undefined {\n let best: DownstreamSession | undefined;\n for (const s of this.sessions) {\n if ((s.inflight.get(upstream)?.length ?? 0) > 0) return s;\n if (!best || s.lastActive > best.lastActive) best = s;\n }\n return best;\n }\n\n private async broadcast(upstream: string, method: string, params: unknown): Promise<void> {\n for (const s of this.sessions) {\n const related = s.inflight.get(upstream)?.at(-1);\n try {\n await s.server.server.notification(\n { method, params: params as Record<string, unknown> | undefined },\n related !== undefined ? { relatedRequestId: related } : undefined,\n );\n } catch {\n // session gone\n }\n }\n }\n\n /**\n * Re-read an upstream's tools, every page (mcp-kit's `readAllPages`): at most 20 requests, each\n * under the upstream's `timeout_ms`, ending at a cursor already followed. It used to follow\n * `nextCursor` with no bound, so an upstream that echoed its cursor kept the proxy asking for\n * the same page forever. A refresh that fails, or stops at the 20-page / 2,000-tool ceiling,\n * changes nothing: the agent keeps the last good list, and the log says why.\n */\n private async refreshTools(name: string): Promise<void> {\n const conn = this.connections.get(name);\n if (!conn?.connected) return;\n if (conn.capabilities && !conn.capabilities.tools) {\n conn.tools = [];\n return;\n }\n const kept = () =>\n `keeping the last good list (${conn.tools.length} tool${conn.tools.length === 1 ? \"\" : \"s\"})`;\n try {\n const read = await readAllPages<Tool>(async (cursor) => {\n const page = await conn.client.listTools(cursor ? { cursor } : undefined, {\n timeout: conn.upstream.timeout_ms,\n });\n return { items: page.tools, nextCursor: page.nextCursor };\n });\n if (read.truncated) {\n this.log(`tools/list for \"${name}\" not applied: ${read.truncated.reason}; ${kept()}`);\n return;\n }\n conn.tools = read.items;\n } catch (err) {\n this.log(\n `tools/list failed for \"${name}\": ${err instanceof Error ? err.message : String(err)}; ${kept()}`,\n );\n }\n }\n\n private rebuildExposed(): void {\n const taken = new Set<string>();\n const out: ExposedTool[] = [];\n const order = [...this.policy.upstreams.map((u) => u.name), ...Object.keys(this.testClients)];\n for (const name of order) {\n const conn = this.connections.get(name);\n if (!conn) continue;\n const prefix =\n conn.upstream.prefix === true\n ? name\n : typeof conn.upstream.prefix === \"string\"\n ? conn.upstream.prefix\n : undefined;\n for (const tool of conn.tools) {\n let exposedName = prefix ? `${prefix}__${tool.name}` : tool.name;\n if (taken.has(exposedName)) exposedName = `${name}__${tool.name}`;\n if (taken.has(exposedName)) {\n this.log(`skipping duplicate tool ${exposedName} from ${name}`);\n continue;\n }\n taken.add(exposedName);\n out.push({\n name: exposedName,\n upstream: name,\n original: tool.name,\n tool,\n classification: classifyTool(\n {\n name: exposedName,\n description: tool.description,\n annotations: tool.annotations,\n inputSchema: tool.inputSchema,\n outputSchema: tool.outputSchema,\n },\n this.policy,\n ),\n });\n }\n }\n this.exposed = out;\n }\n\n listTools(agent?: AgentScope | null): ExposedTool[] {\n if (agent?.upstreams) return this.exposed.filter((t) => agent.upstreams!.includes(t.upstream));\n return this.exposed;\n }\n\n findTool(name: string): ExposedTool | undefined {\n return this.exposed.find((t) => t.name === name);\n }\n\n upstreamStatus(): UpstreamStatus[] {\n return [...this.connections.values()].map((c) => ({\n name: c.upstream.name,\n connected: c.connected,\n tools: c.tools.length,\n transport: c.upstream.url ? \"http\" : \"stdio\",\n error: c.error,\n }));\n }\n\n attach(session: DownstreamSession): void {\n this.sessions.add(session);\n }\n detach(session: DownstreamSession): void {\n this.sessions.delete(session);\n }\n\n /** Run a tool call through the policy engine and, if allowed, the upstream. */\n async callTool(\n name: string,\n args: unknown,\n ctx: CallContext,\n ): Promise<{ result: GuardResult; tool?: ExposedTool }> {\n const tool = this.findTool(name);\n const agent = ctx.agent === undefined ? this.agent : ctx.agent;\n if (!tool) {\n const result = await this.guard.run(\n { tool: { name }, args, runId: ctx.runId, agent, sessionId: ctx.sessionId },\n async () => {\n throw new GuardError({\n code: \"UNKNOWN_TOOL\",\n cause: `no upstream exposes a tool named \"${name}\"`,\n fix: \"call tools/list and use one of the listed names\",\n retryable: false,\n });\n },\n );\n return { result };\n }\n const conn = this.connections.get(tool.upstream);\n const track = (): (() => void) => {\n if (!ctx.session || ctx.requestId === undefined) return () => undefined;\n const list = ctx.session.inflight.get(tool.upstream) ?? [];\n list.push(ctx.requestId);\n ctx.session.inflight.set(tool.upstream, list);\n return () => {\n const l = ctx.session!.inflight.get(tool.upstream) ?? [];\n const i = l.indexOf(ctx.requestId!);\n if (i >= 0) l.splice(i, 1);\n };\n };\n const result = await this.guard.run(\n {\n tool: {\n name: tool.name,\n description: tool.tool.description,\n annotations: tool.tool.annotations,\n inputSchema: tool.tool.inputSchema,\n outputSchema: tool.tool.outputSchema,\n },\n args,\n runId: ctx.runId,\n agent,\n sessionId: ctx.sessionId,\n upstream: tool.upstream,\n },\n async (finalArgs) => {\n if (!conn?.connected) {\n throw new GuardError({\n code: \"UPSTREAM_ERROR\",\n cause: `upstream \"${tool.upstream}\" is not connected${conn?.error ? ` (${conn.error})` : \"\"}`,\n fix: \"check the upstream command/url in okgate.yaml and restart the proxy\",\n retryable: true,\n });\n }\n const untrack = track();\n try {\n return (await conn.client.callTool(\n { name: tool.original, arguments: (finalArgs ?? {}) as Record<string, unknown> },\n undefined,\n {\n timeout: conn.upstream.timeout_ms,\n resetTimeoutOnProgress: true,\n onprogress: ctx.onprogress,\n },\n )) as CallToolResult;\n } finally {\n untrack();\n }\n },\n );\n return { result, tool };\n }\n\n private connectedWith(\n capability: \"resources\" | \"prompts\" | \"completions\" | \"logging\",\n ): Connection[] {\n return [...this.connections.values()].filter(\n (c) => c.connected && (c.capabilities?.[capability] || c.capabilities === undefined),\n );\n }\n\n async listResources(): Promise<ListResourcesResult> {\n const resources: Resource[] = [];\n for (const conn of this.connectedWith(\"resources\")) {\n try {\n const page = await conn.client.listResources(undefined, {\n timeout: conn.upstream.timeout_ms,\n });\n for (const r of page.resources) {\n this.resourceOwner.set(r.uri, conn.upstream.name);\n resources.push(r);\n }\n } catch {\n // upstream has no resources\n }\n }\n return { resources };\n }\n\n async listResourceTemplates(): Promise<ListResourceTemplatesResult> {\n const resourceTemplates: ResourceTemplate[] = [];\n for (const conn of this.connectedWith(\"resources\")) {\n try {\n const page = await conn.client.listResourceTemplates(undefined, {\n timeout: conn.upstream.timeout_ms,\n });\n for (const t of page.resourceTemplates) {\n this.templateOwner.set(t.uriTemplate, conn.upstream.name);\n resourceTemplates.push(t);\n }\n } catch {\n // none\n }\n }\n return { resourceTemplates };\n }\n\n private ownerForUri(uri: string): Connection[] {\n const owner = this.resourceOwner.get(uri);\n if (owner && this.connections.get(owner)?.connected) return [this.connections.get(owner)!];\n for (const [template, name] of this.templateOwner) {\n if (templateMatches(template, uri) && this.connections.get(name)?.connected)\n return [this.connections.get(name)!];\n }\n return this.connectedWith(\"resources\");\n }\n\n async readResource(uri: string): Promise<ReadResourceResult> {\n let lastError: unknown;\n for (const conn of this.ownerForUri(uri)) {\n try {\n const result = await conn.client.readResource(\n { uri },\n { timeout: conn.upstream.timeout_ms },\n );\n this.resourceOwner.set(uri, conn.upstream.name);\n return result;\n } catch (err) {\n lastError = err;\n }\n }\n throw lastError ?? new Error(`no upstream serves resource ${uri}`);\n }\n\n async subscribe(uri: string, on: boolean): Promise<void> {\n for (const conn of this.ownerForUri(uri)) {\n try {\n if (on) await conn.client.subscribeResource({ uri });\n else await conn.client.unsubscribeResource({ uri });\n return;\n } catch {\n // try next\n }\n }\n }\n\n async listPrompts(): Promise<ListPromptsResult> {\n const prompts: Prompt[] = [];\n const taken = new Set<string>();\n this.promptOwner.clear();\n for (const conn of this.connectedWith(\"prompts\")) {\n try {\n const page = await conn.client.listPrompts(undefined, {\n timeout: conn.upstream.timeout_ms,\n });\n for (const p of page.prompts) {\n const name = taken.has(p.name) ? `${conn.upstream.name}__${p.name}` : p.name;\n taken.add(name);\n this.promptOwner.set(name, { upstream: conn.upstream.name, original: p.name });\n prompts.push({ ...p, name });\n }\n } catch {\n // none\n }\n }\n return { prompts };\n }\n\n async getPrompt(\n name: string,\n args: Record<string, string> | undefined,\n ): Promise<GetPromptResult> {\n if (this.promptOwner.size === 0) await this.listPrompts();\n const owner = this.promptOwner.get(name);\n const conns = owner ? [this.connections.get(owner.upstream)!] : this.connectedWith(\"prompts\");\n let lastError: unknown;\n for (const conn of conns) {\n try {\n return await conn.client.getPrompt(\n { name: owner?.original ?? name, arguments: args },\n { timeout: conn.upstream.timeout_ms },\n );\n } catch (err) {\n lastError = err;\n }\n }\n throw lastError ?? new Error(`no upstream serves prompt ${name}`);\n }\n\n async complete(params: CompleteRequest[\"params\"]): Promise<CompleteResult> {\n let conns: Connection[];\n if (params.ref.type === \"ref/prompt\") {\n if (this.promptOwner.size === 0) await this.listPrompts();\n const owner = this.promptOwner.get(params.ref.name);\n conns = owner ? [this.connections.get(owner.upstream)!] : this.connectedWith(\"completions\");\n if (owner) params = { ...params, ref: { ...params.ref, name: owner.original } };\n } else {\n if (this.templateOwner.size === 0) await this.listResourceTemplates();\n conns = this.ownerForUri(params.ref.uri);\n }\n let lastError: unknown;\n for (const conn of conns) {\n try {\n return await conn.client.complete(params, { timeout: conn.upstream.timeout_ms });\n } catch (err) {\n lastError = err;\n }\n }\n throw lastError ?? new Error(\"no upstream supports completions\");\n }\n\n async setLevel(level: LoggingLevel): Promise<void> {\n await Promise.all(\n this.connectedWith(\"logging\").map((c) =>\n c.client.setLoggingLevel(level).catch(() => undefined),\n ),\n );\n }\n\n async close(): Promise<void> {\n this.closing = true;\n for (const conn of this.connections.values()) {\n try {\n await conn.client.close();\n } catch {\n // already closed\n }\n }\n this.connections.clear();\n }\n}\n\nfunction templateMatches(template: string, uri: string): boolean {\n const re = new RegExp(\n \"^\" + template.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\").replace(/\\\\\\{[^}]+\\\\\\}/g, \"[^/]+\") + \"$\",\n );\n return re.test(uri);\n}\n\nexport async function withTimeout<T>(promise: Promise<T>, ms: number, what: string): Promise<T> {\n let timer: NodeJS.Timeout | undefined;\n const timeout = new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(new Error(`${what} timed out after ${ms}ms`)), ms);\n });\n try {\n return await Promise.race([promise, timeout]);\n } finally {\n if (timer) clearTimeout(timer);\n }\n}\n"],"mappings":"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","names":["result"]}
|
|
@@ -6,7 +6,7 @@ import { fileURLToPath } from "url";
|
|
|
6
6
|
import path from "path";
|
|
7
7
|
function summarize(result) {
|
|
8
8
|
const text = result.content.find((c) => c.type === "text")?.text;
|
|
9
|
-
const meta = result._meta?.
|
|
9
|
+
const meta = result._meta?.okgate;
|
|
10
10
|
if (result.isError) {
|
|
11
11
|
let code;
|
|
12
12
|
try {
|
|
@@ -78,8 +78,8 @@ if (isMain) {
|
|
|
78
78
|
return i >= 0 ? argv[i + 1] : void 0;
|
|
79
79
|
};
|
|
80
80
|
const url = arg("--url");
|
|
81
|
-
const config = arg("--config") ?? "
|
|
82
|
-
const client = new Client({ name: "
|
|
81
|
+
const config = arg("--config") ?? "okgate.yaml";
|
|
82
|
+
const client = new Client({ name: "okgate-demo-agent", version: "0.1.0" });
|
|
83
83
|
if (url) {
|
|
84
84
|
await client.connect(
|
|
85
85
|
new StreamableHTTPClientTransport(new URL(url), {
|
|
@@ -106,7 +106,7 @@ if (isMain) {
|
|
|
106
106
|
const halts = steps.filter((s) => !s.ok).map((s) => s.code);
|
|
107
107
|
console.log(
|
|
108
108
|
`
|
|
109
|
-
${steps.length} calls; halts: ${halts.join(", ") || "none"}. Now run:
|
|
109
|
+
${steps.length} calls; halts: ${halts.join(", ") || "none"}. Now run: okgate report`
|
|
110
110
|
);
|
|
111
111
|
} finally {
|
|
112
112
|
await client.close();
|
|
@@ -116,4 +116,4 @@ ${steps.length} calls; halts: ${halts.join(", ") || "none"}. Now run: agentguard
|
|
|
116
116
|
export {
|
|
117
117
|
runDemoAgent
|
|
118
118
|
};
|
|
119
|
-
//# sourceMappingURL=chunk-
|
|
119
|
+
//# sourceMappingURL=chunk-XOBFANL4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/fixtures/demo-agent.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * A scripted \"agent\" that misbehaves on purpose: reads, then writes, then loops, then bursts\n * writes past the cap. Run it against the proxy to see dry-run diffs, LOOP_DETECTED and\n * CAP_EXCEEDED in `okgate report`.\n *\n * node dist/fixtures/demo-agent.js --config okgate.yaml # spawns `okgate proxy` over stdio\n */\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport type { CallToolResult } from \"@modelcontextprotocol/sdk/types.js\";\nimport { fileURLToPath } from \"node:url\";\nimport path from \"node:path\";\n\nexport interface DemoStep {\n step: string;\n tool: string;\n ok: boolean;\n code?: string;\n dryRun?: boolean;\n text?: string;\n}\n\nexport interface DemoOptions {\n /** how many writes to burst at the end (default 60 — past a `writes: 50` cap) */\n burst?: number;\n /** how many times to repeat the identical update (default 5 — past `max_repeats: 3`) */\n loop?: number;\n runId?: string;\n log?: (line: string) => void;\n}\n\nfunction summarize(result: CallToolResult): {\n ok: boolean;\n code?: string;\n dryRun?: boolean;\n text?: string;\n} {\n const text = result.content.find((c) => c.type === \"text\")?.text;\n const meta = (result._meta as { okgate?: { dryRun?: boolean } } | undefined)?.okgate;\n if (result.isError) {\n let code: string | undefined;\n try {\n code = (JSON.parse(text ?? \"{}\") as { code?: string }).code;\n } catch {\n // not JSON\n }\n return { ok: false, code, text };\n }\n return { ok: true, dryRun: meta?.dryRun, text };\n}\n\n/** Drive a connected client through the scripted scenario. Returns every step's outcome. */\nexport async function runDemoAgent(client: Client, opts: DemoOptions = {}): Promise<DemoStep[]> {\n const steps: DemoStep[] = [];\n const log = opts.log ?? (() => undefined);\n const meta = opts.runId ? { runId: opts.runId } : undefined;\n const call = async (\n step: string,\n tool: string,\n args: Record<string, unknown>,\n ): Promise<DemoStep> => {\n const result = (await client.callTool({\n name: tool,\n arguments: args,\n _meta: meta,\n })) as CallToolResult;\n const s = { step, tool, ...summarize(result) };\n steps.push(s);\n log(\n `${s.ok ? (s.dryRun ? \"faked \" : \"ok \") : `${s.code ?? \"error\"}`.padEnd(6)} ${step}: ${tool}`,\n );\n return s;\n };\n\n await call(\"read: list contacts\", \"crm_list_contacts\", { limit: 10 });\n await call(\"read: get one\", \"crm_get_contact\", { id: \"c_1\" });\n await call(\"write: create\", \"crm_create_contact\", {\n name: \"Demo Person\",\n email: \"demo@example.com\",\n });\n await call(\"write: update\", \"crm_update_contact\", { id: \"c_1\", fields: { name: \"Ada L.\" } });\n await call(\"write: delete (destructive)\", \"crm_delete_contact\", { id: \"c_2\" });\n await call(\"write: send email\", \"crm_send_email\", {\n to: \"ada@example.com\",\n subject: \"Hi\",\n body: \"Hello from the demo agent\",\n });\n await call(\"spend: charge $12\", \"crm_charge_card\", {\n customer_id: \"c_1\",\n amount_cents: 1200,\n currency: \"usd\",\n });\n\n const loops = opts.loop ?? 5;\n for (let i = 0; i < loops; i += 1) {\n const s = await call(`loop ${i + 1}/${loops}: identical update`, \"crm_update_contact\", {\n id: \"c_3\",\n fields: { name: \"Same Thing\" },\n });\n if (s.code === \"LOOP_DETECTED\") break;\n }\n\n const burst = opts.burst ?? 60;\n for (let i = 0; i < burst; i += 1) {\n const s = await call(`burst ${i + 1}/${burst}: create`, \"crm_create_contact\", {\n name: `Bulk ${i}`,\n email: `bulk${i}@example.com`,\n });\n if (s.code === \"CAP_EXCEEDED\") break;\n }\n return steps;\n}\n\nconst isMain = process.argv[1] !== undefined && /demo-agent\\.[cm]?[jt]s$/.test(process.argv[1]);\nif (isMain) {\n const argv = process.argv.slice(2);\n const arg = (name: string): string | undefined => {\n const i = argv.indexOf(name);\n return i >= 0 ? argv[i + 1] : undefined;\n };\n const url = arg(\"--url\");\n const config = arg(\"--config\") ?? \"okgate.yaml\";\n const client = new Client({ name: \"okgate-demo-agent\", version: \"0.1.0\" });\n if (url) {\n await client.connect(\n new StreamableHTTPClientTransport(new URL(url), {\n requestInit: {\n headers: { \"X-Run-Id\": arg(\"--run-id\") ?? `demo_${Date.now().toString(36)}` },\n },\n }),\n );\n } else {\n const cli = path.resolve(path.dirname(fileURLToPath(import.meta.url)), \"../cli.js\");\n await client.connect(\n new StdioClientTransport({\n command: process.execPath,\n args: [cli, \"proxy\", \"--config\", config],\n stderr: \"inherit\",\n }),\n );\n }\n try {\n const steps = await runDemoAgent(client, {\n log: (l) => console.log(l),\n runId: arg(\"--run-id\"),\n });\n const halts = steps.filter((s) => !s.ok).map((s) => s.code);\n console.log(\n `\\n${steps.length} calls; halts: ${halts.join(\", \") || \"none\"}. Now run: okgate report`,\n );\n } finally {\n await client.close();\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// src/install.ts
|
|
2
|
+
var NEW_NPM_NAMES = false;
|
|
3
|
+
var FROM_GITHUB = false;
|
|
4
|
+
var BIN = "okgate";
|
|
5
|
+
var PACKAGE = NEW_NPM_NAMES ? "@agentwares/okgate" : "@agentwares/agentguard";
|
|
6
|
+
var GITHUB = "--allow-git=root github:agentwares/okgate";
|
|
7
|
+
function npxArgs(opts = {}) {
|
|
8
|
+
const pkg = `${PACKAGE}${opts.version ? `@${opts.version}` : ""}`;
|
|
9
|
+
return [...opts.yes ? ["-y"] : [], ...NEW_NPM_NAMES ? [pkg] : ["-p", pkg, BIN]];
|
|
10
|
+
}
|
|
11
|
+
var INSTALL = FROM_GITHUB ? `npx ${GITHUB}` : ["npx", ...npxArgs()].join(" ");
|
|
12
|
+
var RUN = FROM_GITHUB ? `npx -y ${GITHUB}` : ["npx", ...npxArgs({ yes: true })].join(" ");
|
|
13
|
+
function npxCommand(version) {
|
|
14
|
+
return ["npx", ...npxArgs({ yes: true, version })].join(" ");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export {
|
|
18
|
+
npxArgs,
|
|
19
|
+
INSTALL,
|
|
20
|
+
RUN,
|
|
21
|
+
npxCommand
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=chunk-XPNBYSIN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/install.ts"],"sourcesContent":["/**\n * How to run okgate: the one constant behind every place the command is shown, printed or\n * written into someone's config: `--help` and the CLI's own hints, the hook command `hooks\n * install` writes, the MCP server entry `init` writes, the README, llms.txt, server.json and the\n * plugin files. src/distribution.test.ts fails while any of them names a form that does not run.\n *\n * agentguard was renamed okgate on 8 Oct 2026 (brief REN-1). The new npm names need the owner's\n * security key for their first publish, so until then npm serves okgate as a second bin of the\n * package it always was: `npx -p @agentwares/agentguard okgate`.\n *\n * - NEW_NPM_NAMES: flip when `@agentwares/okgate`, `-core` and `-sdk` 0.2.0 are on npm (and the\n * old names have become shims). Hook commands and MCP entries then name `@agentwares/okgate`.\n * The rest of the flip is listed in docs/handoff/briefs/REN-1.md's PR and in shims/README.md.\n * - FROM_GITHUB: the npm-free form REL-1 uses for the doors,\n * `npx --allow-git=root github:agentwares/okgate` (npm 12 refuses a git spec unless\n * `--allow-git` permits it; `root` permits only the one named; npm 10 and 11 accept the flag).\n * It needs the public repo renamed AND a runnable package at its root, which it does not have\n * today: scripts/sync-oss-repos.sh generates agentguard as a private pnpm workspace. Leave it\n * off until `npx --allow-git=root github:agentwares/okgate --version` prints a version.\n */\nexport const NEW_NPM_NAMES: boolean = false;\nexport const FROM_GITHUB: boolean = false;\n\nexport const BIN = \"okgate\";\n/** The npm package that serves the CLI. */\nexport const PACKAGE = NEW_NPM_NAMES ? \"@agentwares/okgate\" : \"@agentwares/agentguard\";\n/** The npm package the policy engine is published as. */\nexport const CORE_PACKAGE = NEW_NPM_NAMES\n ? \"@agentwares/okgate-core\"\n : \"@agentwares/agentguard-core\";\n/** The npm package the SDK is published as. */\nexport const SDK_PACKAGE = NEW_NPM_NAMES ? \"@agentwares/okgate-sdk\" : \"@agentwares/agentguard-sdk\";\n\nconst GITHUB = \"--allow-git=root github:agentwares/okgate\";\n\n/** `npx` arguments that run the CLI from npm; `version` pins it. */\nexport function npxArgs(opts: { yes?: boolean; version?: string } = {}): string[] {\n const pkg = `${PACKAGE}${opts.version ? `@${opts.version}` : \"\"}`;\n return [...(opts.yes ? [\"-y\"] : []), ...(NEW_NPM_NAMES ? [pkg] : [\"-p\", pkg, BIN])];\n}\n\n/** What a person types. */\nexport const INSTALL = FROM_GITHUB ? `npx ${GITHUB}` : [\"npx\", ...npxArgs()].join(\" \");\n\n/** What an agent runs unattended: no install prompt. */\nexport const RUN = FROM_GITHUB ? `npx -y ${GITHUB}` : [\"npx\", ...npxArgs({ yes: true })].join(\" \");\n\n/**\n * The command a hook or an MCP client config runs: always from npm, pinned when `version` is\n * given, so a committed settings file keeps running the build that wrote it.\n */\nexport function npxCommand(version?: string): string {\n return [\"npx\", ...npxArgs({ yes: true, version })].join(\" \");\n}\n"],"mappings":";AAoBO,IAAM,gBAAyB;AAC/B,IAAM,cAAuB;AAE7B,IAAM,MAAM;AAEZ,IAAM,UAAU,gBAAgB,uBAAuB;AAQ9D,IAAM,SAAS;AAGR,SAAS,QAAQ,OAA4C,CAAC,GAAa;AAChF,QAAM,MAAM,GAAG,OAAO,GAAG,KAAK,UAAU,IAAI,KAAK,OAAO,KAAK,EAAE;AAC/D,SAAO,CAAC,GAAI,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,GAAI,GAAI,gBAAgB,CAAC,GAAG,IAAI,CAAC,MAAM,KAAK,GAAG,CAAE;AACpF;AAGO,IAAM,UAAU,cAAc,OAAO,MAAM,KAAK,CAAC,OAAO,GAAG,QAAQ,CAAC,EAAE,KAAK,GAAG;AAG9E,IAAM,MAAM,cAAc,UAAU,MAAM,KAAK,CAAC,OAAO,GAAG,QAAQ,EAAE,KAAK,KAAK,CAAC,CAAC,EAAE,KAAK,GAAG;AAM1F,SAAS,WAAW,SAA0B;AACnD,SAAO,CAAC,OAAO,GAAG,QAAQ,EAAE,KAAK,MAAM,QAAQ,CAAC,CAAC,EAAE,KAAK,GAAG;AAC7D;","names":[]}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
HOOKS_POLICY_BLOCK,
|
|
3
|
-
hookTarget,
|
|
4
3
|
hooksCommand,
|
|
5
|
-
installedHandlers,
|
|
6
4
|
renderHooksStarterPolicy
|
|
7
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-F73VDY3W.js";
|
|
6
|
+
import {
|
|
7
|
+
hookTarget,
|
|
8
|
+
installedHandlers
|
|
9
|
+
} from "./chunk-2QDPPTPY.js";
|
|
8
10
|
import {
|
|
9
11
|
flagBool,
|
|
10
12
|
flagList,
|
|
@@ -12,12 +14,13 @@ import {
|
|
|
12
14
|
homeFrom,
|
|
13
15
|
parseArgs,
|
|
14
16
|
version
|
|
15
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-4WTFMFRY.js";
|
|
16
18
|
|
|
17
19
|
// src/commands/audit.ts
|
|
18
20
|
import { writeFileSync as writeFileSync2 } from "fs";
|
|
19
21
|
import { tmpdir } from "os";
|
|
20
|
-
import { join as join4, resolve as resolve3 } from "path";
|
|
22
|
+
import { basename as basename2, join as join4, resolve as resolve3 } from "path";
|
|
23
|
+
import { findPolicyFile } from "@agentwares/agentguard-core/node";
|
|
21
24
|
import {
|
|
22
25
|
NOT_CHECKABLE_HINT,
|
|
23
26
|
applicableNoun,
|
|
@@ -26,7 +29,9 @@ import {
|
|
|
26
29
|
extractRules,
|
|
27
30
|
planEnforcement,
|
|
28
31
|
stableHash as stableHash2,
|
|
29
|
-
summarizeAudit
|
|
32
|
+
summarizeAudit,
|
|
33
|
+
STATE_DIR,
|
|
34
|
+
envTwin
|
|
30
35
|
} from "@agentwares/agentguard-core";
|
|
31
36
|
|
|
32
37
|
// src/audit/cache.ts
|
|
@@ -631,13 +636,11 @@ async function auditCommand(args, io) {
|
|
|
631
636
|
const clients = clientsFrom(args);
|
|
632
637
|
const home = homeFrom(io);
|
|
633
638
|
const repo = findRepo(resolve3(io.cwd, flagString(args, "repo") ?? "."));
|
|
634
|
-
const
|
|
635
|
-
|
|
636
|
-
flagString(args, "config") ?? io.env.AGENTGUARD_CONFIG ?? "agentguard.yaml"
|
|
637
|
-
);
|
|
639
|
+
const named = flagString(args, "config") ?? envTwin(io.env, "CONFIG");
|
|
640
|
+
const policyPath = named !== void 0 ? resolve3(repo.checkout, named) : findPolicyFile(repo.checkout);
|
|
638
641
|
const files = readRuleFiles(repo.checkout, flagList(args, "rules"));
|
|
639
642
|
const config = readConfigRules(policyPath);
|
|
640
|
-
const { rules, errors } = extractRules(files, config.rules,
|
|
643
|
+
const { rules, errors } = extractRules(files, config.rules, basename2(policyPath));
|
|
641
644
|
const warnings = [
|
|
642
645
|
...config.warning ? [config.warning] : [],
|
|
643
646
|
...errors.map((e) => `${e.file}:${e.line}: ${e.message}`)
|
|
@@ -654,7 +657,7 @@ async function auditCommand(args, io) {
|
|
|
654
657
|
...clients.includes("codex") ? codexGroups(dirs.codex) : []
|
|
655
658
|
];
|
|
656
659
|
const cache = new AuditCache(
|
|
657
|
-
resolve3(io.cwd, flagString(args, "cache-dir") ?? join4(home,
|
|
660
|
+
resolve3(io.cwd, flagString(args, "cache-dir") ?? join4(home, STATE_DIR)),
|
|
658
661
|
sha(repo.root),
|
|
659
662
|
flagBool(args, "cache") !== false
|
|
660
663
|
);
|
|
@@ -727,7 +730,7 @@ async function auditCommand(args, io) {
|
|
|
727
730
|
io.out(
|
|
728
731
|
JSON.stringify(
|
|
729
732
|
{
|
|
730
|
-
tool: "
|
|
733
|
+
tool: "okgate audit",
|
|
731
734
|
version: version(),
|
|
732
735
|
repo: repo.root,
|
|
733
736
|
checkout: repo.checkout,
|
|
@@ -771,9 +774,9 @@ async function auditCommand(args, io) {
|
|
|
771
774
|
},
|
|
772
775
|
warnings,
|
|
773
776
|
enforce: {
|
|
774
|
-
command: "
|
|
777
|
+
command: "okgate audit --enforce",
|
|
775
778
|
rules: enforceable.size,
|
|
776
|
-
note: "writes hook-mode rules into
|
|
779
|
+
note: "writes hook-mode rules into okgate.yaml in dry-run; nothing is blocked until hooks.mode is enforce"
|
|
777
780
|
},
|
|
778
781
|
team_history: { available: false, url: TEAM_HISTORY_URL },
|
|
779
782
|
privacy: "counts, rule ids and dates only: no command, path or prompt from a transcript is in this output, and nothing was sent anywhere"
|
|
@@ -830,7 +833,7 @@ function ruleHead(r) {
|
|
|
830
833
|
function renderHuman(io, v) {
|
|
831
834
|
const s = v.summary;
|
|
832
835
|
const window = v.since === void 0 ? "all history" : `since ${localDay(v.since)}`;
|
|
833
|
-
io.out(`
|
|
836
|
+
io.out(`okgate audit \u2014 ${v.root} \xB7 ${window}`);
|
|
834
837
|
const read = v.clients.map((c) => {
|
|
835
838
|
const n = v.counts[c];
|
|
836
839
|
const parts = [`${n.read} read`, `${n.cached} from cache`];
|
|
@@ -851,7 +854,7 @@ function renderHuman(io, v) {
|
|
|
851
854
|
io.out("");
|
|
852
855
|
if (v.files.length === 0 && s.rules.length === 0) {
|
|
853
856
|
io.out(
|
|
854
|
-
"No rule files here (CLAUDE.md, AGENTS.md, GEMINI.md, .cursor/rules, \u2026) and no audit.rules in
|
|
857
|
+
"No rule files here (CLAUDE.md, AGENTS.md, GEMINI.md, .cursor/rules, \u2026) and no audit.rules in okgate.yaml: nothing to audit."
|
|
855
858
|
);
|
|
856
859
|
io.out("");
|
|
857
860
|
io.out(TEAM_HISTORY_LINE);
|
|
@@ -932,7 +935,7 @@ function renderHuman(io, v) {
|
|
|
932
935
|
io.out("");
|
|
933
936
|
if (v.enforceable > 0)
|
|
934
937
|
io.out(
|
|
935
|
-
`Enforce:
|
|
938
|
+
`Enforce: okgate audit --enforce writes ${plural(v.enforceable, "rule")} into okgate.yaml as hook rules, in dry-run (nothing is blocked until hooks.mode: enforce)`
|
|
936
939
|
);
|
|
937
940
|
io.out(TEAM_HISTORY_LINE);
|
|
938
941
|
}
|
|
@@ -989,7 +992,7 @@ async function enforce(args, io, rules, policyPath, checkout, json) {
|
|
|
989
992
|
return blocked && changed ? 1 : 0;
|
|
990
993
|
}
|
|
991
994
|
if (!changed)
|
|
992
|
-
io.out(`
|
|
995
|
+
io.out(`okgate.yaml already has a hook rule for every enforceable rule (${policyPath}).`);
|
|
993
996
|
else {
|
|
994
997
|
io.out(
|
|
995
998
|
`${write ? edit.created ? "wrote" : "updated" : "would update"} ${policyPath} \u2014 ${plural(edit.added.length, "hook rule")}:`
|
|
@@ -1008,18 +1011,18 @@ async function enforce(args, io, rules, policyPath, checkout, json) {
|
|
|
1008
1011
|
io.out("");
|
|
1009
1012
|
if (blocked && changed) {
|
|
1010
1013
|
io.out(
|
|
1011
|
-
"hooks.mode is enforce in this
|
|
1014
|
+
"hooks.mode is enforce in this okgate.yaml, so these rules would block at once. Nothing was written. Rerun with --enforce --yes to add them anyway, or set hooks.mode: dry-run first."
|
|
1012
1015
|
);
|
|
1013
1016
|
return 1;
|
|
1014
1017
|
}
|
|
1015
1018
|
if (preview) {
|
|
1016
|
-
io.out("Preview only: nothing was written. Run
|
|
1019
|
+
io.out("Preview only: nothing was written. Run okgate audit --enforce to write it.");
|
|
1017
1020
|
return 0;
|
|
1018
1021
|
}
|
|
1019
1022
|
for (const l of hookOut) io.out(l);
|
|
1020
|
-
if (installed) io.out("The
|
|
1023
|
+
if (installed) io.out("The okgate hook is already installed (okgate hooks status).");
|
|
1021
1024
|
io.out(
|
|
1022
|
-
`hooks.mode is ${edit.mode}: ${edit.mode === "dry-run" ? "every decision is logged and nothing is blocked. Read
|
|
1025
|
+
`hooks.mode is ${edit.mode}: ${edit.mode === "dry-run" ? "every decision is logged and nothing is blocked. Read okgate report, then set hooks.mode: enforce yourself." : "the rules apply from the next session."}`
|
|
1023
1026
|
);
|
|
1024
1027
|
return 0;
|
|
1025
1028
|
}
|
|
@@ -1030,4 +1033,4 @@ export {
|
|
|
1030
1033
|
parseSince,
|
|
1031
1034
|
auditCommand
|
|
1032
1035
|
};
|
|
1033
|
-
//# sourceMappingURL=chunk-
|
|
1036
|
+
//# sourceMappingURL=chunk-YBVD6HTT.js.map
|