@sponsio/sdk 0.2.0-alpha.4 → 0.2.0-alpha.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/contracts/capability/destructive.yaml +213 -0
  2. package/contracts/capability/factual-claims.yaml +79 -0
  3. package/contracts/capability/host-config-integrity.yaml +42 -9
  4. package/contracts/capability/self-modify.yaml +32 -1
  5. package/contracts/capability/shell.yaml +19 -10
  6. package/contracts/incident/claude-code-secret-bypass.yaml +46 -14
  7. package/contracts/incident/cursor-railway-wipe.yaml +60 -4
  8. package/contracts/incident/openclaw.yaml +9 -63
  9. package/dist/cli/cli.js +32 -0
  10. package/dist/cli/cli.js.map +1 -1
  11. package/dist/cli/packs.d.ts.map +1 -1
  12. package/dist/cli/packs.js +13 -7
  13. package/dist/cli/packs.js.map +1 -1
  14. package/dist/cloud/client.d.ts +76 -0
  15. package/dist/cloud/client.d.ts.map +1 -0
  16. package/dist/cloud/client.js +198 -0
  17. package/dist/cloud/client.js.map +1 -0
  18. package/dist/cloud/evidence.d.ts +108 -0
  19. package/dist/cloud/evidence.d.ts.map +1 -0
  20. package/dist/cloud/evidence.js +184 -0
  21. package/dist/cloud/evidence.js.map +1 -0
  22. package/dist/cloud/privacy.d.ts +67 -0
  23. package/dist/cloud/privacy.d.ts.map +1 -0
  24. package/dist/cloud/privacy.js +170 -0
  25. package/dist/cloud/privacy.js.map +1 -0
  26. package/dist/cloud/view-model.d.ts +49 -0
  27. package/dist/cloud/view-model.d.ts.map +1 -0
  28. package/dist/cloud/view-model.js +172 -0
  29. package/dist/cloud/view-model.js.map +1 -0
  30. package/dist/core/config-loader.js +16 -0
  31. package/dist/core/config-loader.js.map +1 -1
  32. package/dist/core/evaluator.d.ts +2 -0
  33. package/dist/core/evaluator.d.ts.map +1 -1
  34. package/dist/core/evaluator.js +90 -4
  35. package/dist/core/evaluator.js.map +1 -1
  36. package/dist/core/grounding.d.ts +43 -7
  37. package/dist/core/grounding.d.ts.map +1 -1
  38. package/dist/core/grounding.js +180 -25
  39. package/dist/core/grounding.js.map +1 -1
  40. package/dist/core/nl-parser.d.ts +1 -1
  41. package/dist/core/nl-parser.d.ts.map +1 -1
  42. package/dist/core/nl-parser.js +616 -40
  43. package/dist/core/nl-parser.js.map +1 -1
  44. package/dist/core/pattern-factory.d.ts.map +1 -1
  45. package/dist/core/pattern-factory.js +7 -1
  46. package/dist/core/pattern-factory.js.map +1 -1
  47. package/dist/core/patterns.d.ts +69 -0
  48. package/dist/core/patterns.d.ts.map +1 -1
  49. package/dist/core/patterns.js +133 -10
  50. package/dist/core/patterns.js.map +1 -1
  51. package/dist/core/tool-names.d.ts +59 -0
  52. package/dist/core/tool-names.d.ts.map +1 -0
  53. package/dist/core/tool-names.js +128 -0
  54. package/dist/core/tool-names.js.map +1 -0
  55. package/dist/index.d.ts +144 -0
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +367 -32
  58. package/dist/index.js.map +1 -1
  59. package/dist/integrations/claude-agent.d.ts +5 -0
  60. package/dist/integrations/claude-agent.d.ts.map +1 -1
  61. package/dist/integrations/claude-agent.js +42 -13
  62. package/dist/integrations/claude-agent.js.map +1 -1
  63. package/dist/integrations/google-adk.d.ts +5 -3
  64. package/dist/integrations/google-adk.d.ts.map +1 -1
  65. package/dist/integrations/google-adk.js +9 -5
  66. package/dist/integrations/google-adk.js.map +1 -1
  67. package/dist/integrations/langchain.d.ts +7 -0
  68. package/dist/integrations/langchain.d.ts.map +1 -1
  69. package/dist/integrations/langchain.js +21 -3
  70. package/dist/integrations/langchain.js.map +1 -1
  71. package/dist/integrations/openai-agents.d.ts +22 -10
  72. package/dist/integrations/openai-agents.d.ts.map +1 -1
  73. package/dist/integrations/openai-agents.js +51 -12
  74. package/dist/integrations/openai-agents.js.map +1 -1
  75. package/dist/integrations/openai.d.ts +11 -0
  76. package/dist/integrations/openai.d.ts.map +1 -1
  77. package/dist/integrations/openai.js +130 -48
  78. package/dist/integrations/openai.js.map +1 -1
  79. package/dist/integrations/vercel-ai.d.ts +20 -9
  80. package/dist/integrations/vercel-ai.d.ts.map +1 -1
  81. package/dist/integrations/vercel-ai.js +131 -50
  82. package/dist/integrations/vercel-ai.js.map +1 -1
  83. package/package.json +12 -8
  84. package/prompts/onboard.md +17 -4
  85. package/contracts/core/llm_safety.yaml +0 -138
@@ -8,64 +8,146 @@
8
8
  * const guard = new Sponsio({ contracts: [...] })
9
9
  * const client = wrapOpenAI(new OpenAI(), guard)
10
10
  *
11
+ * Covers ``chat.completions.create`` / ``parse`` and, when the client has
12
+ * it, ``responses.create`` / ``parse``. Every tool call the model emits
13
+ * is checked before the caller's tool loop can run it; refused calls are
14
+ * removed from the response and a ``[BLOCKED] <tool>: <reason>`` line is
15
+ * added to the assistant text so the model learns why.
16
+ *
17
+ * ``stream: true`` throws at call time on every wrapped method: tool
18
+ * calls arrive as deltas and could only be checked after the caller has
19
+ * already assembled and run them. Call without ``stream``, or run your
20
+ * own executor through ``guard.guardBefore()`` before each tool call.
21
+ *
11
22
  * ``patchOpenAI`` is an alias matching Python's ``patch_openai``
12
23
  * factory (same monkey-patch semantics — no wrapped return value
13
24
  * required; the client passed in is mutated in place).
14
25
  */
26
+ const STREAM_UNSUPPORTED = "sponsio: the OpenAI guard does not support stream: true. Tool calls " +
27
+ "arrive as deltas and could only be checked after the caller has already " +
28
+ "assembled and run them. Call without stream, or run your own executor " +
29
+ "through guard.guardBefore() before each tool call.";
15
30
  export function wrapOpenAI(client, guard) {
16
31
  const c = client;
17
- const original = c.chat.completions.create.bind(c.chat.completions);
18
- c.chat.completions.create = async function (...args) {
19
- const response = await original(...args);
20
- for (const choice of response.choices ?? []) {
21
- const msg = choice.message;
22
- if (!msg?.tool_calls)
32
+ const completions = c?.chat?.completions;
33
+ if (!completions || typeof completions.create !== "function") {
34
+ throw new TypeError("wrapOpenAI: expected an OpenAI client with chat.completions.create");
35
+ }
36
+ patchMethod(completions, "create", guard, "chat");
37
+ patchMethod(completions, "parse", guard, "chat");
38
+ if (c.responses) {
39
+ patchMethod(c.responses, "create", guard, "responses");
40
+ patchMethod(c.responses, "parse", guard, "responses");
41
+ }
42
+ return client;
43
+ }
44
+ function patchMethod(target, name, guard, kind) {
45
+ const original = target[name];
46
+ if (typeof original !== "function")
47
+ return;
48
+ const bound = original.bind(target);
49
+ target[name] = async function (...args) {
50
+ const params = args[0];
51
+ if (params && typeof params === "object" && params.stream) {
52
+ throw new Error(STREAM_UNSUPPORTED);
53
+ }
54
+ const response = await bound(...args);
55
+ return kind === "chat"
56
+ ? guardChatResponse(response, guard)
57
+ : guardResponsesOutput(response, guard);
58
+ };
59
+ }
60
+ /**
61
+ * Decide one emitted call. Malformed JSON arguments are refused in
62
+ * enforce mode without touching the trace (a call that never runs must
63
+ * not count as a call); in observe mode they pass through and are
64
+ * recorded with a sentinel so the session log shows what arrived.
65
+ */
66
+ function decide(guard, toolName, rawArgs) {
67
+ let args;
68
+ try {
69
+ const parsed = JSON.parse(rawArgs || "{}");
70
+ args =
71
+ parsed && typeof parsed === "object" && !Array.isArray(parsed)
72
+ ? parsed
73
+ : { input: parsed };
74
+ }
75
+ catch {
76
+ if (guard.mode === "enforce") {
77
+ return {
78
+ blocked: true,
79
+ note: `[BLOCKED] ${toolName}: malformed JSON arguments — refusing to forward to the tool loop`,
80
+ };
81
+ }
82
+ args = { _sponsio_malformed_args: rawArgs ?? "" };
83
+ }
84
+ const result = guard.guardBefore(toolName, args);
85
+ // ``stopOriginal`` covers a redirect verdict as well as a block: the
86
+ // wrapper has no substitution path, so a redirect strips the call.
87
+ if (result.stopOriginal) {
88
+ return { blocked: true, note: `[BLOCKED] ${toolName}: ${result.message}` };
89
+ }
90
+ return { blocked: false };
91
+ }
92
+ function guardChatResponse(response, guard) {
93
+ for (const choice of response?.choices ?? []) {
94
+ const msg = choice.message;
95
+ if (!msg?.tool_calls)
96
+ continue;
97
+ const kept = [];
98
+ const blocked = [];
99
+ for (const tc of msg.tool_calls) {
100
+ const d = decide(guard, tc.function.name, tc.function.arguments);
101
+ if (d.blocked)
102
+ blocked.push(d.note);
103
+ else
104
+ kept.push(tc);
105
+ }
106
+ msg.tool_calls = kept.length > 0 ? kept : null;
107
+ if (blocked.length > 0 && !msg.tool_calls) {
108
+ // Match Python's ``_filter_blocked_calls``: join with a newline
109
+ // separator but no leading newline before the first message.
110
+ msg.content = (msg.content ?? "") + blocked.join("\n");
111
+ }
112
+ }
113
+ return response;
114
+ }
115
+ function guardResponsesOutput(response, guard) {
116
+ const output = response?.output;
117
+ if (!Array.isArray(output))
118
+ return response;
119
+ const kept = [];
120
+ const blocked = [];
121
+ for (const item of output) {
122
+ if (item?.type === "function_call") {
123
+ const d = decide(guard, item.name ?? "", item.arguments);
124
+ if (d.blocked) {
125
+ blocked.push(d.note);
23
126
  continue;
24
- const kept = [];
25
- const blocked = [];
26
- for (const tc of msg.tool_calls) {
27
- let tcArgs = {};
28
- let parseFailed = false;
29
- try {
30
- tcArgs = JSON.parse(tc.function.arguments || "{}");
31
- }
32
- catch {
33
- parseFailed = true;
34
- }
35
- // Malformed arguments bypass any arg-based contract
36
- // (``arg_blacklist``, ``arg_length_limit``, ``scope_limit``,
37
- // ``dangerous_sql_verbs``, ``arg_value_range``) if we treat
38
- // them as empty. Feed a sentinel so the guard still sees
39
- // *something* distinctive, and block-by-default so a
40
- // malformed payload doesn't silently slip through.
41
- if (parseFailed) {
42
- guard.guardBefore(tc.function.name, {
43
- _sponsio_malformed_args: tc.function.arguments ?? "",
44
- });
45
- blocked.push(`[BLOCKED] ${tc.function.name}: malformed JSON arguments — ` +
46
- `refusing to forward to tool loop (set ` +
47
- `SPONSIO_OPENAI_STRICT_TOOL_ARGS=0 to downgrade once the ` +
48
- `parity flag ships in TS)`);
49
- continue;
50
- }
51
- const result = guard.guardBefore(tc.function.name, tcArgs);
52
- if (result.blocked) {
53
- blocked.push(`[BLOCKED] ${tc.function.name}: ${result.message}`);
54
- }
55
- else {
56
- kept.push(tc);
57
- }
58
- }
59
- msg.tool_calls = kept.length > 0 ? kept : null;
60
- if (blocked.length > 0 && !msg.tool_calls) {
61
- // Match Python's ``_filter_blocked_calls``: join with a newline
62
- // separator but no leading newline before the first message.
63
- msg.content = (msg.content ?? "") + blocked.join("\n");
64
127
  }
65
128
  }
129
+ kept.push(item);
130
+ }
131
+ if (blocked.length === 0)
66
132
  return response;
67
- };
68
- return client;
133
+ response.output = kept;
134
+ const note = blocked.join("\n");
135
+ const lastMessage = [...kept].reverse().find((i) => i?.type === "message");
136
+ const textPart = lastMessage?.content
137
+ ? [...lastMessage.content].reverse().find((p) => typeof p?.text === "string")
138
+ : undefined;
139
+ if (textPart) {
140
+ textPart.text = `${textPart.text}\n${note}`;
141
+ }
142
+ else {
143
+ kept.push({
144
+ type: "message",
145
+ role: "assistant",
146
+ status: "completed",
147
+ content: [{ type: "output_text", text: note, annotations: [] }],
148
+ });
149
+ }
150
+ return response;
69
151
  }
70
152
  /**
71
153
  * Alias for ``wrapOpenAI`` — matches Python's
@@ -1 +1 @@
1
- {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/integrations/openai.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,MAAM,UAAU,UAAU,CAAC,MAAe,EAAE,KAAc;IACxD,MAAM,CAAC,GAAG,MAeT,CAAC;IAEF,MAAM,QAAQ,GAAG,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAEpE,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,KAAK,WAAW,GAAG,IAAe;QAC5D,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC;QAEzC,KAAK,MAAM,MAAM,IAAI,QAAQ,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;YAC5C,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC;YAC3B,IAAI,CAAC,GAAG,EAAE,UAAU;gBAAE,SAAS;YAE/B,MAAM,IAAI,GAA0B,EAAE,CAAC;YACvC,MAAM,OAAO,GAAa,EAAE,CAAC;YAE7B,KAAK,MAAM,EAAE,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;gBAChC,IAAI,MAAM,GAA4B,EAAE,CAAC;gBACzC,IAAI,WAAW,GAAG,KAAK,CAAC;gBACxB,IAAI,CAAC;oBACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC;gBACrD,CAAC;gBAAC,MAAM,CAAC;oBACP,WAAW,GAAG,IAAI,CAAC;gBACrB,CAAC;gBAED,oDAAoD;gBACpD,6DAA6D;gBAC7D,4DAA4D;gBAC5D,yDAAyD;gBACzD,qDAAqD;gBACrD,mDAAmD;gBACnD,IAAI,WAAW,EAAE,CAAC;oBAChB,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE;wBAClC,uBAAuB,EAAE,EAAE,CAAC,QAAQ,CAAC,SAAS,IAAI,EAAE;qBACrD,CAAC,CAAC;oBACH,OAAO,CAAC,IAAI,CACV,aAAa,EAAE,CAAC,QAAQ,CAAC,IAAI,+BAA+B;wBAC1D,wCAAwC;wBACxC,0DAA0D;wBAC1D,0BAA0B,CAC7B,CAAC;oBACF,SAAS;gBACX,CAAC;gBAED,MAAM,MAAM,GAAG,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBAC3D,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;oBACnB,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,QAAQ,CAAC,IAAI,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;gBACnE,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAChB,CAAC;YACH,CAAC;YAED,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;YAC/C,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC;gBAC1C,gEAAgE;gBAChE,6DAA6D;gBAC7D,GAAG,CAAC,OAAO,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACzD,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAoB,CAAC;IAErB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,UAAU,CAAC"}
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/integrations/openai.ts"],"names":[],"mappings":"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"}
@@ -10,19 +10,30 @@
10
10
  * const model = wrapLanguageModel({ model, middleware: sponsioMiddleware(guard) })
11
11
  *
12
12
  * Behaviour:
13
- * - guardBefore is called for every tool call the model emits.
13
+ * - guardBefore runs for every tool call the model emits, on both
14
+ * ``generateText`` (``wrapGenerate``) and ``streamText``
15
+ * (``wrapStream``), before the AI SDK executes the tool.
14
16
  * - Allowed calls pass through untouched.
15
- * - Blocked calls are *dropped* from ``result.toolCalls`` (so the AI
16
- * SDK's parseToolCall doesn't reject the response with NoSuchToolError),
17
- * and a `[Sponsio blocked: <reason>]` line is appended to the
18
- * model's text output. If every emitted call was blocked, the
19
- * finishReason is forced to ``stop`` so the agent loop terminates
20
- * instead of spinning on an empty turn.
21
- * - The model's args are JSON-stringified at the language-model layer;
22
- * the middleware parses defensively before handing them to the
17
+ * - Blocked calls are *dropped* (so the AI SDK never executes them and
18
+ * ``parseToolCall`` doesn't reject the response), and a
19
+ * ``[Sponsio blocked: <reason>]`` note is added to the model's text.
20
+ * If every emitted call was blocked, the finishReason is forced to
21
+ * ``stop`` so the agent loop terminates instead of spinning.
22
+ * - Both provider result shapes are handled: ``ai`` v4
23
+ * (``LanguageModelV1``: ``result.toolCalls[]`` with ``args``) and
24
+ * ``ai`` v5 and later (``LanguageModelV2`` / ``V3``:
25
+ * ``result.content[]`` with ``{ type: "tool-call", input }`` parts).
26
+ * - The model's args arrive JSON-stringified at the language-model
27
+ * layer; the middleware parses defensively before handing them to the
23
28
  * guard so the contract evaluator sees a real object.
24
29
  */
25
30
  import type { Sponsio } from "../index.js";
31
+ /**
32
+ * The model's arguments as an object. A string that is not JSON is kept
33
+ * under ``_sponsio_malformed_args`` so coarse regex contracts still see
34
+ * it instead of an empty object that passes every argument rule.
35
+ */
36
+ export declare function parseArgs(raw: unknown): Record<string, unknown>;
26
37
  export declare function sponsioMiddleware(guard: Sponsio): {
27
38
  transformParams: ({ params }: {
28
39
  params: any;
@@ -1 +1 @@
1
- {"version":3,"file":"vercel-ai.d.ts","sourceRoot":"","sources":["../../src/integrations/vercel-ai.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAgD3C,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO;kCAER;QAAE,MAAM,EAAE,GAAG,CAAA;KAAE,KAAG,OAAO,CAAC,GAAG,CAAC;oCAI/D;QACD,UAAU,EAAE,MAAM,GAAG,CAAC;QACtB,MAAM,EAAE,GAAG,CAAC;KACb,KAAG,OAAO,CAAC,GAAG,CAAC;+BAsDiB;QAAE,QAAQ,EAAE,MAAM,GAAG,CAAA;KAAE,KAAG,OAAO,CAAC,GAAG,CAAC;EAQ1E"}
1
+ {"version":3,"file":"vercel-ai.d.ts","sourceRoot":"","sources":["../../src/integrations/vercel-ai.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAsC3C;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAc/D;AA0CD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO;kCAER;QAAE,MAAM,EAAE,GAAG,CAAA;KAAE,KAAG,OAAO,CAAC,GAAG,CAAC;oCAI/D;QACD,UAAU,EAAE,MAAM,GAAG,CAAC;QACtB,MAAM,EAAE,GAAG,CAAC;KACb,KAAG,OAAO,CAAC,GAAG,CAAC;+BAuDiB;QAAE,QAAQ,EAAE,MAAM,GAAG,CAAA;KAAE,KAAG,OAAO,CAAC,GAAG,CAAC;EA4C1E"}
@@ -10,16 +10,21 @@
10
10
  * const model = wrapLanguageModel({ model, middleware: sponsioMiddleware(guard) })
11
11
  *
12
12
  * Behaviour:
13
- * - guardBefore is called for every tool call the model emits.
13
+ * - guardBefore runs for every tool call the model emits, on both
14
+ * ``generateText`` (``wrapGenerate``) and ``streamText``
15
+ * (``wrapStream``), before the AI SDK executes the tool.
14
16
  * - Allowed calls pass through untouched.
15
- * - Blocked calls are *dropped* from ``result.toolCalls`` (so the AI
16
- * SDK's parseToolCall doesn't reject the response with NoSuchToolError),
17
- * and a `[Sponsio blocked: <reason>]` line is appended to the
18
- * model's text output. If every emitted call was blocked, the
19
- * finishReason is forced to ``stop`` so the agent loop terminates
20
- * instead of spinning on an empty turn.
21
- * - The model's args are JSON-stringified at the language-model layer;
22
- * the middleware parses defensively before handing them to the
17
+ * - Blocked calls are *dropped* (so the AI SDK never executes them and
18
+ * ``parseToolCall`` doesn't reject the response), and a
19
+ * ``[Sponsio blocked: <reason>]`` note is added to the model's text.
20
+ * If every emitted call was blocked, the finishReason is forced to
21
+ * ``stop`` so the agent loop terminates instead of spinning.
22
+ * - Both provider result shapes are handled: ``ai`` v4
23
+ * (``LanguageModelV1``: ``result.toolCalls[]`` with ``args``) and
24
+ * ``ai`` v5 and later (``LanguageModelV2`` / ``V3``:
25
+ * ``result.content[]`` with ``{ type: "tool-call", input }`` parts).
26
+ * - The model's args arrive JSON-stringified at the language-model
27
+ * layer; the middleware parses defensively before handing them to the
23
28
  * guard so the contract evaluator sees a real object.
24
29
  */
25
30
  function emitBanner(toolName, reason, agentId) {
@@ -38,7 +43,12 @@ function emitBanner(toolName, reason, agentId) {
38
43
  ];
39
44
  process.stderr.write(lines.join("\n"));
40
45
  }
41
- function parseArgs(raw) {
46
+ /**
47
+ * The model's arguments as an object. A string that is not JSON is kept
48
+ * under ``_sponsio_malformed_args`` so coarse regex contracts still see
49
+ * it instead of an empty object that passes every argument rule.
50
+ */
51
+ export function parseArgs(raw) {
42
52
  if (raw == null)
43
53
  return {};
44
54
  if (typeof raw === "object" && !Array.isArray(raw))
@@ -48,55 +58,91 @@ function parseArgs(raw) {
48
58
  const parsed = JSON.parse(raw);
49
59
  return parsed && typeof parsed === "object" && !Array.isArray(parsed)
50
60
  ? parsed
51
- : {};
61
+ : { input: parsed };
52
62
  }
53
63
  catch {
54
- return {};
64
+ return { _sponsio_malformed_args: raw };
65
+ }
66
+ }
67
+ return { input: raw };
68
+ }
69
+ /** Compact one-line reason for the appended note; full message stays in the session log. */
70
+ function trimReason(msg) {
71
+ // Strip prefix via indexOf rather than regex — every regex form that
72
+ // matched the pattern ``^[A-Z-]*BLOCKED:\s*[^—]+—\s*`` kept tripping
73
+ // CodeQL js/polynomial-redos (the ``\s*`` and ``[^—]+`` overlap on
74
+ // spaces). indexOf is O(n) with no backtracking.
75
+ let trimmed = msg;
76
+ const blockedIdx = trimmed.indexOf("BLOCKED:");
77
+ if (blockedIdx >= 0 && blockedIdx <= 64) {
78
+ const dashIdx = trimmed.indexOf("—", blockedIdx + "BLOCKED:".length);
79
+ if (dashIdx >= 0) {
80
+ trimmed = trimmed.slice(dashIdx + "—".length).trimStart();
55
81
  }
56
82
  }
57
- return {};
83
+ const head = trimmed.toLowerCase();
84
+ if (head.startsWith("det constraint violated:")) {
85
+ trimmed = trimmed.slice("det constraint violated:".length).trimStart();
86
+ }
87
+ else if (head.startsWith("violated:")) {
88
+ trimmed = trimmed.slice("violated:".length).trimStart();
89
+ }
90
+ return trimmed.split("\n")[0];
91
+ }
92
+ /** Run one emitted tool call through the guard, before anything executes it. */
93
+ function decide(guard, tc) {
94
+ const check = guard.guardBefore(tc.toolName, parseArgs(tc.input ?? tc.args));
95
+ // ``stopOriginal`` covers a redirect verdict as well as a block: the
96
+ // middleware has no substitution path, so a redirect drops the call.
97
+ if (!check.stopOriginal)
98
+ return { blocked: false };
99
+ const reason = trimReason(check.message ?? `${tc.toolName} blocked by Sponsio`);
100
+ emitBanner(tc.toolName, reason, guard.agentId);
101
+ return { blocked: true, reason };
102
+ }
103
+ function blockNote(reasons) {
104
+ return `[Sponsio blocked: ${reasons.join("; ")}]`;
58
105
  }
59
106
  export function sponsioMiddleware(guard) {
60
107
  return {
61
108
  transformParams: async ({ params }) => params,
62
109
  wrapGenerate: async ({ doGenerate, }) => {
63
110
  const result = await doGenerate();
111
+ // ai v5+: tool calls are ``tool-call`` parts inside ``content``.
112
+ if (Array.isArray(result.content)) {
113
+ const content = [];
114
+ const blockedReasons = [];
115
+ let survivingCalls = 0;
116
+ for (const part of result.content) {
117
+ if (part?.type === "tool-call") {
118
+ const d = decide(guard, part);
119
+ if (d.blocked) {
120
+ blockedReasons.push(`${String(part.toolName)}: ${d.reason}`);
121
+ continue;
122
+ }
123
+ survivingCalls++;
124
+ }
125
+ content.push(part);
126
+ }
127
+ if (blockedReasons.length === 0)
128
+ return result;
129
+ content.push({ type: "text", text: blockNote(blockedReasons) });
130
+ return {
131
+ ...result,
132
+ content,
133
+ finishReason: survivingCalls === 0 ? "stop" : result.finishReason,
134
+ };
135
+ }
136
+ // ai v4: tool calls are ``result.toolCalls``.
64
137
  const calls = result.toolCalls ?? [];
65
138
  if (calls.length === 0)
66
139
  return result;
67
140
  const surviving = [];
68
141
  const blockedReasons = [];
69
142
  for (const tc of calls) {
70
- const check = guard.guardBefore(tc.toolName, parseArgs(tc.args));
71
- if (check.blocked) {
72
- // Strip the leading "BLOCKED: agent.tool — det constraint violated: "
73
- // prefix and any "det constraint violated:" / "violated:" boilerplate
74
- // so the appended text is concise; full message stays in the session log.
75
- const msg = check.message ?? `${tc.toolName} blocked by Sponsio`;
76
- // Strip prefix via indexOf rather than regex — every regex
77
- // form that matched the pattern
78
- // ``^[A-Z-]*BLOCKED:\s*[^—]+—\s*`` kept tripping CodeQL
79
- // js/polynomial-redos (the ``\s*`` and ``[^—]+`` overlap on
80
- // spaces). indexOf is O(n) with no backtracking.
81
- let trimmed = msg;
82
- const blockedIdx = trimmed.indexOf("BLOCKED:");
83
- if (blockedIdx >= 0 && blockedIdx <= 64) {
84
- const dashIdx = trimmed.indexOf("—", blockedIdx + "BLOCKED:".length);
85
- if (dashIdx >= 0) {
86
- trimmed = trimmed.slice(dashIdx + "—".length).trimStart();
87
- }
88
- }
89
- // Strip optional "(det constraint )?violated:" boilerplate.
90
- const head = trimmed.toLowerCase();
91
- if (head.startsWith("det constraint violated:")) {
92
- trimmed = trimmed.slice("det constraint violated:".length).trimStart();
93
- }
94
- else if (head.startsWith("violated:")) {
95
- trimmed = trimmed.slice("violated:".length).trimStart();
96
- }
97
- const reason = trimmed.split("\n")[0];
98
- emitBanner(tc.toolName, reason, guard.agentId);
99
- blockedReasons.push(`${tc.toolName}: ${reason}`);
143
+ const d = decide(guard, tc);
144
+ if (d.blocked) {
145
+ blockedReasons.push(`${tc.toolName}: ${d.reason}`);
100
146
  }
101
147
  else {
102
148
  surviving.push(tc);
@@ -104,8 +150,8 @@ export function sponsioMiddleware(guard) {
104
150
  }
105
151
  if (blockedReasons.length === 0)
106
152
  return result;
107
- const blockNote = `[Sponsio blocked: ${blockedReasons.join("; ")}]`;
108
- const newText = result.text ? `${result.text}\n\n${blockNote}` : blockNote;
153
+ const note = blockNote(blockedReasons);
154
+ const newText = result.text ? `${result.text}\n\n${note}` : note;
109
155
  return {
110
156
  ...result,
111
157
  toolCalls: surviving,
@@ -114,11 +160,46 @@ export function sponsioMiddleware(guard) {
114
160
  };
115
161
  },
116
162
  wrapStream: async ({ doStream }) => {
117
- // Stream support is intentionally pass-through for now; the
118
- // stream parts API is more involved and the demo / OSS hot
119
- // path uses generateText. We can add full stream filtering in
120
- // a follow-up without changing the wrapGenerate contract.
121
- return doStream();
163
+ const streamed = await doStream();
164
+ const source = streamed?.stream;
165
+ if (!source || typeof source.pipeThrough !== "function")
166
+ return streamed;
167
+ // ``streamText`` executes a tool when the ``tool-call`` part arrives,
168
+ // so that part is the gate. Earlier ``tool-input-*`` /
169
+ // ``tool-call-delta`` parts only render partial arguments and pass
170
+ // through; nothing runs on them.
171
+ let survivingCalls = 0;
172
+ let blockedAny = false;
173
+ let noteId = 0;
174
+ const gated = source.pipeThrough(new TransformStream({
175
+ transform(part, controller) {
176
+ if (part?.type === "tool-call") {
177
+ const d = decide(guard, part);
178
+ if (d.blocked) {
179
+ blockedAny = true;
180
+ const note = blockNote([`${String(part.toolName)}: ${d.reason}`]);
181
+ if ("input" in part) {
182
+ // v5+ text streams are start / delta / end triples.
183
+ const id = `sponsio-block-${++noteId}`;
184
+ controller.enqueue({ type: "text-start", id });
185
+ controller.enqueue({ type: "text-delta", id, delta: note });
186
+ controller.enqueue({ type: "text-end", id });
187
+ }
188
+ else {
189
+ controller.enqueue({ type: "text-delta", textDelta: note });
190
+ }
191
+ return;
192
+ }
193
+ survivingCalls++;
194
+ }
195
+ if (part?.type === "finish" && blockedAny && survivingCalls === 0) {
196
+ controller.enqueue({ ...part, finishReason: "stop" });
197
+ return;
198
+ }
199
+ controller.enqueue(part);
200
+ },
201
+ }));
202
+ return { ...streamed, stream: gated };
122
203
  },
123
204
  };
124
205
  }
@@ -1 +1 @@
1
- {"version":3,"file":"vercel-ai.js","sourceRoot":"","sources":["../../src/integrations/vercel-ai.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vercel-ai.js","sourceRoot":"","sources":["../../src/integrations/vercel-ai.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sponsio/sdk",
3
- "version": "0.2.0-alpha.4",
4
- "description": "Runtime contract enforcement for LLM agents — native TypeScript",
3
+ "version": "0.2.0-alpha.8",
4
+ "description": "Runtime contract enforcement for LLM agents \u2014 native TypeScript",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",
@@ -46,6 +46,10 @@
46
46
  "./langchain": {
47
47
  "types": "./dist/integrations/langchain.d.ts",
48
48
  "default": "./dist/integrations/langchain.js"
49
+ },
50
+ "./cloud/evidence": {
51
+ "types": "./dist/cloud/evidence.d.ts",
52
+ "import": "./dist/cloud/evidence.js"
49
53
  }
50
54
  },
51
55
  "bin": {
@@ -63,22 +67,22 @@
63
67
  ],
64
68
  "scripts": {
65
69
  "build": "tsc && tsc -p tsconfig.cli.json && node -e \"require('fs').writeFileSync('dist/cli/package.json', '{\\\"type\\\":\\\"commonjs\\\"}\\n')\"",
66
- "test": "node --test dist/__tests__/*.test.js",
70
+ "test": "node --test dist/",
67
71
  "test:cli": "node --test dist/cli/__tests__/*.test.js",
68
72
  "test:src": "npx tsx src/__tests__/core.test.ts",
69
73
  "test:parity": "npx tsx src/__tests__/parity.test.ts && npx tsx src/__tests__/parity.scenarios.test.ts"
70
74
  },
71
75
  "dependencies": {
72
76
  "fast-glob": "^3.3.0",
73
- "js-yaml": "^5.2.3",
77
+ "js-yaml": "^5.4.2",
74
78
  "ts-morph": "^28.0.0",
75
- "yaml": "^2.9.0"
79
+ "yaml": "^2.9.1"
76
80
  },
77
81
  "devDependencies": {
78
82
  "@types/js-yaml": "^4.0.5",
79
- "@types/node": "^26.1.2",
80
- "esbuild": "^0.28.1",
81
- "tsx": "^4.23.5",
83
+ "@types/node": "^26.6.2",
84
+ "esbuild": "^0.28.2",
85
+ "tsx": "^4.23.15",
82
86
  "typescript": "^5.5.0"
83
87
  },
84
88
  "peerDependencies": {
@@ -175,10 +175,23 @@ agents:
175
175
 
176
176
  ## Pattern vocabulary
177
177
 
178
- (Same as plugin scan — `arg_blacklist`, `arg_value_range`,
179
- `arg_length_limit`, `rate_limit`, `loop_detection`,
180
- `irreversible_once`, `must_precede`. See
181
- ``sponsio plugin prompt mcp-bare`` for full signatures.)
178
+ Run ``sponsio patterns`` and use the FULL list it prints — do not
179
+ rely on a memorized subset. The library spans temporal ordering
180
+ (`must_precede`, `no_reversal`, `always_followed_by`, …), argument &
181
+ path constraints (`arg_blacklist`, `arg_allowlist`, `scope_limit`,
182
+ `arg_value_range`, `arg_length_limit`, …), OWASP presets
183
+ (`dangerous_sql_verbs`, `dangerous_bash_commands`,
184
+ `destructive_action_gate`, `tool_allowlist`, …), rate / resource
185
+ caps (`rate_limit`, `idempotent`, `loop_detection`, …), and data
186
+ flow (`no_data_leak`). Policy docs about SQL safety, data
187
+ isolation, taint, or approval gates almost always need patterns
188
+ outside the arg-constraint family — check the full list before
189
+ concluding a rule can't be expressed.
190
+
191
+ If no pattern fits, two fallbacks (in order): a plain NL rule that
192
+ ``sponsio validate`` accepts, or a raw formula over the atomic
193
+ propositions in ``sponsio/tracer/grounding.py`` (`called`,
194
+ `called_with`, `arg_has`, `arg_field_has`, `contains`, `flow`).
182
195
 
183
196
  ## Source tagging
184
197