@sponsio/sdk 0.2.0-alpha.4 → 0.2.0-alpha.9
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/contracts/capability/destructive.yaml +213 -0
- package/contracts/capability/factual-claims.yaml +79 -0
- package/contracts/capability/host-config-integrity.yaml +42 -9
- package/contracts/capability/self-modify.yaml +32 -1
- package/contracts/capability/shell.yaml +19 -10
- package/contracts/incident/claude-code-secret-bypass.yaml +46 -14
- package/contracts/incident/cursor-railway-wipe.yaml +60 -4
- package/contracts/incident/openclaw.yaml +9 -63
- package/dist/cli/cli.js +32 -0
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/packs.d.ts.map +1 -1
- package/dist/cli/packs.js +13 -7
- package/dist/cli/packs.js.map +1 -1
- package/dist/cloud/client.d.ts +76 -0
- package/dist/cloud/client.d.ts.map +1 -0
- package/dist/cloud/client.js +198 -0
- package/dist/cloud/client.js.map +1 -0
- package/dist/cloud/evidence.d.ts +108 -0
- package/dist/cloud/evidence.d.ts.map +1 -0
- package/dist/cloud/evidence.js +184 -0
- package/dist/cloud/evidence.js.map +1 -0
- package/dist/cloud/privacy.d.ts +67 -0
- package/dist/cloud/privacy.d.ts.map +1 -0
- package/dist/cloud/privacy.js +170 -0
- package/dist/cloud/privacy.js.map +1 -0
- package/dist/cloud/view-model.d.ts +49 -0
- package/dist/cloud/view-model.d.ts.map +1 -0
- package/dist/cloud/view-model.js +172 -0
- package/dist/cloud/view-model.js.map +1 -0
- package/dist/core/config-loader.js +16 -0
- package/dist/core/config-loader.js.map +1 -1
- package/dist/core/evaluator.d.ts +2 -0
- package/dist/core/evaluator.d.ts.map +1 -1
- package/dist/core/evaluator.js +90 -4
- package/dist/core/evaluator.js.map +1 -1
- package/dist/core/formula.d.ts.map +1 -1
- package/dist/core/formula.js +12 -0
- package/dist/core/formula.js.map +1 -1
- package/dist/core/grounding.d.ts +43 -7
- package/dist/core/grounding.d.ts.map +1 -1
- package/dist/core/grounding.js +192 -26
- package/dist/core/grounding.js.map +1 -1
- package/dist/core/nl-parser.d.ts +1 -1
- package/dist/core/nl-parser.d.ts.map +1 -1
- package/dist/core/nl-parser.js +616 -40
- package/dist/core/nl-parser.js.map +1 -1
- package/dist/core/pattern-factory.d.ts.map +1 -1
- package/dist/core/pattern-factory.js +7 -1
- package/dist/core/pattern-factory.js.map +1 -1
- package/dist/core/patterns.d.ts +69 -0
- package/dist/core/patterns.d.ts.map +1 -1
- package/dist/core/patterns.js +133 -10
- package/dist/core/patterns.js.map +1 -1
- package/dist/core/tool-names.d.ts +59 -0
- package/dist/core/tool-names.d.ts.map +1 -0
- package/dist/core/tool-names.js +128 -0
- package/dist/core/tool-names.js.map +1 -0
- package/dist/index.d.ts +144 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +367 -32
- package/dist/index.js.map +1 -1
- package/dist/integrations/claude-agent.d.ts +5 -0
- package/dist/integrations/claude-agent.d.ts.map +1 -1
- package/dist/integrations/claude-agent.js +42 -13
- package/dist/integrations/claude-agent.js.map +1 -1
- package/dist/integrations/google-adk.d.ts +5 -3
- package/dist/integrations/google-adk.d.ts.map +1 -1
- package/dist/integrations/google-adk.js +9 -5
- package/dist/integrations/google-adk.js.map +1 -1
- package/dist/integrations/langchain.d.ts +7 -0
- package/dist/integrations/langchain.d.ts.map +1 -1
- package/dist/integrations/langchain.js +21 -3
- package/dist/integrations/langchain.js.map +1 -1
- package/dist/integrations/openai-agents.d.ts +22 -10
- package/dist/integrations/openai-agents.d.ts.map +1 -1
- package/dist/integrations/openai-agents.js +51 -12
- package/dist/integrations/openai-agents.js.map +1 -1
- package/dist/integrations/openai.d.ts +11 -0
- package/dist/integrations/openai.d.ts.map +1 -1
- package/dist/integrations/openai.js +130 -48
- package/dist/integrations/openai.js.map +1 -1
- package/dist/integrations/vercel-ai.d.ts +20 -9
- package/dist/integrations/vercel-ai.d.ts.map +1 -1
- package/dist/integrations/vercel-ai.js +131 -50
- package/dist/integrations/vercel-ai.js.map +1 -1
- package/package.json +12 -8
- package/prompts/onboard.md +17 -4
- package/contracts/core/llm_safety.yaml +0 -138
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The evidence lane, from TypeScript.
|
|
3
|
+
*
|
|
4
|
+
* Rules check what an agent *does*; evidence checks what it *says*. A
|
|
5
|
+
* model that reports "the three line items total $100" is making a claim
|
|
6
|
+
* that is either true of the numbers it was given or is not, and no
|
|
7
|
+
* amount of prompting settles it. This sends the claim to
|
|
8
|
+
* `/v1/evidence/verify`, which resolves it against the declared inputs
|
|
9
|
+
* and answers PASS, MISMATCH, or a verdict meaning it could not tell.
|
|
10
|
+
*
|
|
11
|
+
* Parity with `sponsio/cloud/evidence.py`: same endpoint, same wire
|
|
12
|
+
* shape, same verdict vocabulary. One service, one meter — the server
|
|
13
|
+
* records usage per tenant and cannot see which SDK called it.
|
|
14
|
+
*
|
|
15
|
+
* The judgement is entirely server-side. This file normalises inputs,
|
|
16
|
+
* makes one request, and classifies the answer.
|
|
17
|
+
*
|
|
18
|
+
* @module @sponsio/sdk/cloud/evidence
|
|
19
|
+
*/
|
|
20
|
+
/** A verdict the server can return. Anything else is treated as unknown. */
|
|
21
|
+
export type EvidenceVerdict = "PASS" | "MISMATCH" | "NO_EVIDENCE" | "SOURCE_UNAVAILABLE" | "UNDERDETERMINED";
|
|
22
|
+
/** What the server says to do about a verdict. */
|
|
23
|
+
export type EvidenceAction = "release" | "block" | "clarify";
|
|
24
|
+
/**
|
|
25
|
+
* One input, tagged with where its value came from.
|
|
26
|
+
*
|
|
27
|
+
* The tag is not decoration. Each predicate declares which sources it
|
|
28
|
+
* will accept, and the server refuses a value that arrived from anywhere
|
|
29
|
+
* else: a total the model made up must not be checked against itself.
|
|
30
|
+
* `GET /v1/evidence/predicates` lists the allowlist per predicate.
|
|
31
|
+
*/
|
|
32
|
+
export interface TaggedInput {
|
|
33
|
+
value: unknown;
|
|
34
|
+
source: string;
|
|
35
|
+
}
|
|
36
|
+
/** Ergonomic forms accepted per input: a tagged object or a `[value, source]` pair. */
|
|
37
|
+
export type InputSpec = TaggedInput | [unknown, string];
|
|
38
|
+
export interface EvidenceResult {
|
|
39
|
+
predicate: string;
|
|
40
|
+
verdict: EvidenceVerdict | string;
|
|
41
|
+
action: EvidenceAction | string;
|
|
42
|
+
/** The resolved values the verdict was reached from. */
|
|
43
|
+
values: unknown[];
|
|
44
|
+
evidenceTs?: number;
|
|
45
|
+
source?: string;
|
|
46
|
+
tableVersion?: string;
|
|
47
|
+
/** The right value, when the server knows it. Never invented. */
|
|
48
|
+
correction?: unknown;
|
|
49
|
+
/** What to ask about, on a clarify action. */
|
|
50
|
+
clarifyOn: unknown[];
|
|
51
|
+
/** Server-side record of this check, for an audit trail. */
|
|
52
|
+
attestationId?: string;
|
|
53
|
+
}
|
|
54
|
+
/** The check did not reach a verdict. The caller decides open or closed. */
|
|
55
|
+
export declare class EvidenceError extends Error {
|
|
56
|
+
readonly status?: number;
|
|
57
|
+
constructor(message: string, status?: number);
|
|
58
|
+
}
|
|
59
|
+
/** True when this verdict must stop the response. */
|
|
60
|
+
export declare function isBlocking(result: EvidenceResult): boolean;
|
|
61
|
+
/** True when this verdict asks the agent to clarify rather than stop. */
|
|
62
|
+
export declare function needsClarification(result: EvidenceResult): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Ergonomic input forms to the wire's tagged shape.
|
|
65
|
+
*
|
|
66
|
+
* An untagged input is rejected here rather than sent. The server would
|
|
67
|
+
* refuse it anyway under the taint rule, and failing locally names the
|
|
68
|
+
* input that is missing its tag.
|
|
69
|
+
*
|
|
70
|
+
* The pair form needs a string source. Without that check a two-element
|
|
71
|
+
* array of data read as a pair: `{ items: [40, 60] }` became
|
|
72
|
+
* `value: 40, source: "60"`, and the server then refused source `"60"`
|
|
73
|
+
* as untrusted, an error naming nothing the caller had written. A list
|
|
74
|
+
* value takes the explicit form, `[[40, 60], "submitted_output"]`.
|
|
75
|
+
*/
|
|
76
|
+
export declare function normalizeInputs(inputs?: Record<string, InputSpec>): Record<string, TaggedInput>;
|
|
77
|
+
export interface EvidenceClientOptions {
|
|
78
|
+
/** Defaults to `SPONSIO_API_KEY`. */
|
|
79
|
+
apiKey?: string;
|
|
80
|
+
/** Defaults to `SPONSIO_API_URL`, then `https://app.sponsio.dev`. */
|
|
81
|
+
url?: string;
|
|
82
|
+
/** Per-request timeout in milliseconds. */
|
|
83
|
+
timeoutMs?: number;
|
|
84
|
+
}
|
|
85
|
+
export declare class EvidenceClient {
|
|
86
|
+
readonly url: string;
|
|
87
|
+
private readonly apiKey;
|
|
88
|
+
private readonly timeoutMs;
|
|
89
|
+
constructor(opts?: EvidenceClientOptions);
|
|
90
|
+
get configured(): boolean;
|
|
91
|
+
private post;
|
|
92
|
+
/**
|
|
93
|
+
* Verify one claim against fresh evidence, server-side.
|
|
94
|
+
*
|
|
95
|
+
* Throws `EvidenceError` when the check did not run to a verdict.
|
|
96
|
+
* Decide open or closed at the call site; closed means treating the
|
|
97
|
+
* throw as a block.
|
|
98
|
+
*/
|
|
99
|
+
verify(predicate: string, opts?: {
|
|
100
|
+
value?: unknown;
|
|
101
|
+
text?: string;
|
|
102
|
+
inputs?: Record<string, InputSpec>;
|
|
103
|
+
sessionId?: string;
|
|
104
|
+
}): Promise<EvidenceResult>;
|
|
105
|
+
/** The predicate catalog this key can reach. */
|
|
106
|
+
predicates(): Promise<Record<string, unknown>[]>;
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=evidence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evidence.d.ts","sourceRoot":"","sources":["../../src/cloud/evidence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,4EAA4E;AAC5E,MAAM,MAAM,eAAe,GACvB,MAAM,GACN,UAAU,GACV,aAAa,GACb,oBAAoB,GACpB,iBAAiB,CAAC;AAEtB,kDAAkD;AAClD,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;AAE7D;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,uFAAuF;AACvF,MAAM,MAAM,SAAS,GAAG,WAAW,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;AAExD,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,eAAe,GAAG,MAAM,CAAC;IAClC,MAAM,EAAE,cAAc,GAAG,MAAM,CAAC;IAChC,wDAAwD;IACxD,MAAM,EAAE,OAAO,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iEAAiE;IACjE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,8CAA8C;IAC9C,SAAS,EAAE,OAAO,EAAE,CAAC;IACrB,4DAA4D;IAC5D,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,4EAA4E;AAC5E,qBAAa,aAAc,SAAQ,KAAK;IACtC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;gBACb,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;CAK7C;AAED,qDAAqD;AACrD,wBAAgB,UAAU,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAE1D;AAED,yEAAyE;AACzE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAElE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAC7B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GACjC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAkB7B;AA0BD,MAAM,WAAW,qBAAqB;IACpC,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,cAAc;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,IAAI,GAAE,qBAA0B;IAa5C,IAAI,UAAU,IAAI,OAAO,CAExB;YAEa,IAAI;IAmDlB;;;;;;OAMG;IACG,MAAM,CACV,SAAS,EAAE,MAAM,EACjB,IAAI,GAAE;QACJ,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QACnC,SAAS,CAAC,EAAE,MAAM,CAAC;KACf,GACL,OAAO,CAAC,cAAc,CAAC;IAU1B,gDAAgD;IAC1C,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;CAoBvD"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The evidence lane, from TypeScript.
|
|
3
|
+
*
|
|
4
|
+
* Rules check what an agent *does*; evidence checks what it *says*. A
|
|
5
|
+
* model that reports "the three line items total $100" is making a claim
|
|
6
|
+
* that is either true of the numbers it was given or is not, and no
|
|
7
|
+
* amount of prompting settles it. This sends the claim to
|
|
8
|
+
* `/v1/evidence/verify`, which resolves it against the declared inputs
|
|
9
|
+
* and answers PASS, MISMATCH, or a verdict meaning it could not tell.
|
|
10
|
+
*
|
|
11
|
+
* Parity with `sponsio/cloud/evidence.py`: same endpoint, same wire
|
|
12
|
+
* shape, same verdict vocabulary. One service, one meter — the server
|
|
13
|
+
* records usage per tenant and cannot see which SDK called it.
|
|
14
|
+
*
|
|
15
|
+
* The judgement is entirely server-side. This file normalises inputs,
|
|
16
|
+
* makes one request, and classifies the answer.
|
|
17
|
+
*
|
|
18
|
+
* @module @sponsio/sdk/cloud/evidence
|
|
19
|
+
*/
|
|
20
|
+
/** The check did not reach a verdict. The caller decides open or closed. */
|
|
21
|
+
export class EvidenceError extends Error {
|
|
22
|
+
status;
|
|
23
|
+
constructor(message, status) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.name = "EvidenceError";
|
|
26
|
+
this.status = status;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/** True when this verdict must stop the response. */
|
|
30
|
+
export function isBlocking(result) {
|
|
31
|
+
return result.action === "block";
|
|
32
|
+
}
|
|
33
|
+
/** True when this verdict asks the agent to clarify rather than stop. */
|
|
34
|
+
export function needsClarification(result) {
|
|
35
|
+
return result.action === "clarify";
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Ergonomic input forms to the wire's tagged shape.
|
|
39
|
+
*
|
|
40
|
+
* An untagged input is rejected here rather than sent. The server would
|
|
41
|
+
* refuse it anyway under the taint rule, and failing locally names the
|
|
42
|
+
* input that is missing its tag.
|
|
43
|
+
*
|
|
44
|
+
* The pair form needs a string source. Without that check a two-element
|
|
45
|
+
* array of data read as a pair: `{ items: [40, 60] }` became
|
|
46
|
+
* `value: 40, source: "60"`, and the server then refused source `"60"`
|
|
47
|
+
* as untrusted, an error naming nothing the caller had written. A list
|
|
48
|
+
* value takes the explicit form, `[[40, 60], "submitted_output"]`.
|
|
49
|
+
*/
|
|
50
|
+
export function normalizeInputs(inputs) {
|
|
51
|
+
const wire = {};
|
|
52
|
+
for (const [name, spec] of Object.entries(inputs ?? {})) {
|
|
53
|
+
if (Array.isArray(spec) && spec.length === 2 && typeof spec[1] === "string") {
|
|
54
|
+
wire[name] = { value: spec[0], source: spec[1] };
|
|
55
|
+
}
|
|
56
|
+
else if (spec && typeof spec === "object" && "source" in spec) {
|
|
57
|
+
wire[name] = {
|
|
58
|
+
value: spec.value,
|
|
59
|
+
source: String(spec.source),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
throw new Error(`input '${name}' needs a source tag: pass [value, source] or ` +
|
|
64
|
+
`{ value, source } — the server rejects untagged inputs (taint rule)`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return wire;
|
|
68
|
+
}
|
|
69
|
+
function parseResult(payload) {
|
|
70
|
+
const evidence = (payload.evidence ?? {});
|
|
71
|
+
const rawValues = evidence.values;
|
|
72
|
+
const clarify = payload.clarify_on;
|
|
73
|
+
return {
|
|
74
|
+
predicate: String(payload.predicate ?? ""),
|
|
75
|
+
verdict: String(payload.verdict ?? ""),
|
|
76
|
+
action: String(payload.action ?? ""),
|
|
77
|
+
values: Array.isArray(rawValues) ? rawValues : [],
|
|
78
|
+
...(typeof evidence.ts === "number" ? { evidenceTs: evidence.ts } : {}),
|
|
79
|
+
...(typeof evidence.source === "string" ? { source: evidence.source } : {}),
|
|
80
|
+
...(typeof evidence.table_version === "string"
|
|
81
|
+
? { tableVersion: evidence.table_version }
|
|
82
|
+
: {}),
|
|
83
|
+
...(payload.correction !== null && payload.correction !== undefined
|
|
84
|
+
? { correction: payload.correction }
|
|
85
|
+
: {}),
|
|
86
|
+
clarifyOn: Array.isArray(clarify) ? clarify : [],
|
|
87
|
+
...(typeof payload.attestation_id === "string"
|
|
88
|
+
? { attestationId: payload.attestation_id }
|
|
89
|
+
: {}),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
export class EvidenceClient {
|
|
93
|
+
url;
|
|
94
|
+
apiKey;
|
|
95
|
+
timeoutMs;
|
|
96
|
+
constructor(opts = {}) {
|
|
97
|
+
this.apiKey = opts.apiKey ?? process.env.SPONSIO_API_KEY ?? undefined;
|
|
98
|
+
// Trailing slashes stripped without a regex. `/\/+$/` backtracks
|
|
99
|
+
// polynomially on a string of many slashes, and the URL comes from
|
|
100
|
+
// an env var, so it is not ours to trust about its own shape.
|
|
101
|
+
let base = opts.url ?? process.env.SPONSIO_API_URL ?? "https://app.sponsio.dev";
|
|
102
|
+
let end = base.length;
|
|
103
|
+
while (end > 0 && base.charCodeAt(end - 1) === 47)
|
|
104
|
+
end -= 1;
|
|
105
|
+
this.url = base.slice(0, end);
|
|
106
|
+
this.timeoutMs = opts.timeoutMs ?? 10_000;
|
|
107
|
+
}
|
|
108
|
+
get configured() {
|
|
109
|
+
return Boolean(this.apiKey);
|
|
110
|
+
}
|
|
111
|
+
async post(path, body) {
|
|
112
|
+
if (!this.apiKey) {
|
|
113
|
+
throw new EvidenceError("no API key: set SPONSIO_API_KEY or pass apiKey to EvidenceClient");
|
|
114
|
+
}
|
|
115
|
+
const controller = new AbortController();
|
|
116
|
+
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
117
|
+
let response;
|
|
118
|
+
try {
|
|
119
|
+
response = await fetch(`${this.url}${path}`, {
|
|
120
|
+
method: "POST",
|
|
121
|
+
headers: {
|
|
122
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
123
|
+
"Content-Type": "application/json",
|
|
124
|
+
"User-Agent": "sponsio-sdk-ts",
|
|
125
|
+
},
|
|
126
|
+
body: JSON.stringify(body),
|
|
127
|
+
signal: controller.signal,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
throw new EvidenceError(`cannot reach ${this.url}: ${err instanceof Error ? err.message : err}`);
|
|
132
|
+
}
|
|
133
|
+
finally {
|
|
134
|
+
clearTimeout(timer);
|
|
135
|
+
}
|
|
136
|
+
const text = await response.text();
|
|
137
|
+
let payload;
|
|
138
|
+
try {
|
|
139
|
+
payload = text ? JSON.parse(text) : {};
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
throw new EvidenceError(`${this.url} answered ${response.status} with non-JSON`, response.status);
|
|
143
|
+
}
|
|
144
|
+
if (!response.ok) {
|
|
145
|
+
const detail = payload?.detail;
|
|
146
|
+
throw new EvidenceError(typeof detail === "string" ? detail : `verify failed (${response.status})`, response.status);
|
|
147
|
+
}
|
|
148
|
+
return payload;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Verify one claim against fresh evidence, server-side.
|
|
152
|
+
*
|
|
153
|
+
* Throws `EvidenceError` when the check did not run to a verdict.
|
|
154
|
+
* Decide open or closed at the call site; closed means treating the
|
|
155
|
+
* throw as a block.
|
|
156
|
+
*/
|
|
157
|
+
async verify(predicate, opts = {}) {
|
|
158
|
+
const body = {
|
|
159
|
+
predicate,
|
|
160
|
+
claim: { value: opts.value ?? null, text: opts.text ?? null },
|
|
161
|
+
inputs: normalizeInputs(opts.inputs),
|
|
162
|
+
};
|
|
163
|
+
if (opts.sessionId)
|
|
164
|
+
body.session_id = opts.sessionId;
|
|
165
|
+
return parseResult(await this.post("/v1/evidence/verify", body));
|
|
166
|
+
}
|
|
167
|
+
/** The predicate catalog this key can reach. */
|
|
168
|
+
async predicates() {
|
|
169
|
+
if (!this.apiKey) {
|
|
170
|
+
throw new EvidenceError("no API key: set SPONSIO_API_KEY or pass apiKey to EvidenceClient");
|
|
171
|
+
}
|
|
172
|
+
const response = await fetch(`${this.url}/v1/evidence/predicates`, {
|
|
173
|
+
headers: {
|
|
174
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
175
|
+
"User-Agent": "sponsio-sdk-ts",
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
if (!response.ok) {
|
|
179
|
+
throw new EvidenceError(`predicates failed (${response.status})`, response.status);
|
|
180
|
+
}
|
|
181
|
+
return (await response.json());
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=evidence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evidence.js","sourceRoot":"","sources":["../../src/cloud/evidence.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What may leave this machine.
|
|
3
|
+
*
|
|
4
|
+
* Port of ``sponsio/bridge/privacy.py``. Enforcement already happened
|
|
5
|
+
* here — the det checks are pure and local — so nothing in this file can
|
|
6
|
+
* change a verdict. It only narrows what the console is shown, which is
|
|
7
|
+
* what makes it cheap: the run's shape is all the cloud needs to render
|
|
8
|
+
* a dashboard, count a finding, or meter usage.
|
|
9
|
+
*/
|
|
10
|
+
export declare const LEVELS: readonly ["full", "shape", "hashed", "metadata", "tool_calls"];
|
|
11
|
+
export type PrivacyLevel = (typeof LEVELS)[number];
|
|
12
|
+
/**
|
|
13
|
+
* The level in force. The environment beats the argument, deliberately:
|
|
14
|
+
* the person who decides what may leave a machine is the operator of
|
|
15
|
+
* that machine, not the author of the agent running on it.
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolve(explicit?: string): PrivacyLevel;
|
|
18
|
+
/**
|
|
19
|
+
* The structure of an argument set, with every value replaced.
|
|
20
|
+
*
|
|
21
|
+
* Lengths survive for strings and lists because "the model passed a
|
|
22
|
+
* 40 000-character path" is a debugging fact and not content, and it is
|
|
23
|
+
* the one an oversize-argument rule fires on.
|
|
24
|
+
*/
|
|
25
|
+
export declare function shape(args: unknown): string;
|
|
26
|
+
/**
|
|
27
|
+
* ``json.dumps`` as Python writes it, which is what the other runtime
|
|
28
|
+
* hashes and displays.
|
|
29
|
+
*
|
|
30
|
+
* ``JSON.stringify`` omits the spaces Python puts after ``,`` and
|
|
31
|
+
* ``:``. That is invisible in a console and decisive in a digest: the
|
|
32
|
+
* same arguments hashed to different values on the two sides, so
|
|
33
|
+
* duplicate and loop detection disagreed about whether two calls were
|
|
34
|
+
* the same call. ``sortKeys`` additionally makes two calls that differ
|
|
35
|
+
* only in key order agree, which is what the digest is for.
|
|
36
|
+
*/
|
|
37
|
+
export declare function pyJson(value: unknown, sortKeys?: boolean): string;
|
|
38
|
+
/**
|
|
39
|
+
* A stable short hash of an argument set. An equality token, not a
|
|
40
|
+
* signature, which is why twelve hex characters is enough: it is what
|
|
41
|
+
* lets duplicate and loop detection keep working with no content.
|
|
42
|
+
*/
|
|
43
|
+
export declare function digest(args: unknown): string;
|
|
44
|
+
/** What ``argsPreview`` carries at this level. */
|
|
45
|
+
export declare function preview(args: unknown, level: PrivacyLevel, fullPreview: string): string;
|
|
46
|
+
/**
|
|
47
|
+
* What a model turn may quote of itself. A response is the most
|
|
48
|
+
* content-bearing field in the payload, so it goes one level earlier
|
|
49
|
+
* than arguments do.
|
|
50
|
+
*/
|
|
51
|
+
export declare function say(text: string, level: PrivacyLevel): string;
|
|
52
|
+
/**
|
|
53
|
+
* Whether a step of this type is recorded at all.
|
|
54
|
+
*
|
|
55
|
+
* Only ``tool_calls`` drops whole steps. Every other level keeps the
|
|
56
|
+
* shape of the run and empties fields; this one keeps the action lane
|
|
57
|
+
* alone, because that is what the customer asked for by name.
|
|
58
|
+
*/
|
|
59
|
+
export declare function keepsStep(stepType: string, level: PrivacyLevel): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* A stamp for the run, so a reader knows what they are not seeing.
|
|
62
|
+
*
|
|
63
|
+
* A dashboard showing empty arguments has to be able to say whether the
|
|
64
|
+
* agent passed none or the deployment declined to send them.
|
|
65
|
+
*/
|
|
66
|
+
export declare function describe(level: PrivacyLevel): Record<string, unknown>;
|
|
67
|
+
//# sourceMappingURL=privacy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"privacy.d.ts","sourceRoot":"","sources":["../../src/cloud/privacy.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,eAAO,MAAM,MAAM,gEAAiE,CAAC;AACrF,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;AASnD;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,YAAY,CAWvD;AA0BD;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAS3C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,UAAQ,GAAG,MAAM,CAmB/D;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAM5C;AAED,kDAAkD;AAClD,wBAAgB,OAAO,CACrB,IAAI,EAAE,OAAO,EACb,KAAK,EAAE,YAAY,EACnB,WAAW,EAAE,MAAM,GAClB,MAAM,CAKR;AAED;;;;GAIG;AACH,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,MAAM,CAE7D;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAExE;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASrE"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What may leave this machine.
|
|
3
|
+
*
|
|
4
|
+
* Port of ``sponsio/bridge/privacy.py``. Enforcement already happened
|
|
5
|
+
* here — the det checks are pure and local — so nothing in this file can
|
|
6
|
+
* change a verdict. It only narrows what the console is shown, which is
|
|
7
|
+
* what makes it cheap: the run's shape is all the cloud needs to render
|
|
8
|
+
* a dashboard, count a finding, or meter usage.
|
|
9
|
+
*/
|
|
10
|
+
import { createHash } from "node:crypto";
|
|
11
|
+
export const LEVELS = ["full", "shape", "hashed", "metadata", "tool_calls"];
|
|
12
|
+
const DEFAULT = "full";
|
|
13
|
+
const STRICTEST = "tool_calls";
|
|
14
|
+
function isLevel(v) {
|
|
15
|
+
return LEVELS.includes(v);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The level in force. The environment beats the argument, deliberately:
|
|
19
|
+
* the person who decides what may leave a machine is the operator of
|
|
20
|
+
* that machine, not the author of the agent running on it.
|
|
21
|
+
*/
|
|
22
|
+
export function resolve(explicit) {
|
|
23
|
+
const env = (process.env.SPONSIO_PRIVACY ?? "").trim().toLowerCase();
|
|
24
|
+
if (isLevel(env))
|
|
25
|
+
return env;
|
|
26
|
+
if (env) {
|
|
27
|
+
// An unrecognised value is far more likely to be a typo in a
|
|
28
|
+
// deployment that meant to tighten than a request to loosen, so it
|
|
29
|
+
// fails closed, to the strictest level there is.
|
|
30
|
+
return STRICTEST;
|
|
31
|
+
}
|
|
32
|
+
if (explicit && isLevel(explicit))
|
|
33
|
+
return explicit;
|
|
34
|
+
return DEFAULT;
|
|
35
|
+
}
|
|
36
|
+
function typeOf(value) {
|
|
37
|
+
if (value === null || value === undefined)
|
|
38
|
+
return "<null>";
|
|
39
|
+
if (typeof value === "boolean")
|
|
40
|
+
return "<bool>";
|
|
41
|
+
if (typeof value === "number") {
|
|
42
|
+
// The one place the two runtimes cannot agree. JavaScript has a
|
|
43
|
+
// single number type, so a value Python reports as ``<float>``
|
|
44
|
+
// because it was written 250.0 arrives here indistinguishable from
|
|
45
|
+
// 250 and is reported ``<int>``. Reporting every number as a float
|
|
46
|
+
// to match would misdescribe every integer, which is worse: a shape
|
|
47
|
+
// is read to answer "what did the agent pass", and the answer for
|
|
48
|
+
// this runtime is that it passed a number JavaScript calls integral.
|
|
49
|
+
return Number.isInteger(value) ? "<int>" : "<float>";
|
|
50
|
+
}
|
|
51
|
+
if (typeof value === "string")
|
|
52
|
+
return `<str:${value.length}>`;
|
|
53
|
+
if (Array.isArray(value))
|
|
54
|
+
return `<list:${value.length}>`;
|
|
55
|
+
if (typeof value === "object") {
|
|
56
|
+
const parts = Object.entries(value).map(([k, v]) => `${k}: ${typeOf(v)}`);
|
|
57
|
+
return `{${parts.join(", ")}}`;
|
|
58
|
+
}
|
|
59
|
+
return `<${typeof value}>`;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The structure of an argument set, with every value replaced.
|
|
63
|
+
*
|
|
64
|
+
* Lengths survive for strings and lists because "the model passed a
|
|
65
|
+
* 40 000-character path" is a debugging fact and not content, and it is
|
|
66
|
+
* the one an oversize-argument rule fires on.
|
|
67
|
+
*/
|
|
68
|
+
export function shape(args) {
|
|
69
|
+
if (args === null || args === undefined)
|
|
70
|
+
return "";
|
|
71
|
+
if (typeof args === "object" && !Array.isArray(args)) {
|
|
72
|
+
const parts = Object.entries(args).map(([k, v]) => `"${k}": ${typeOf(v)}`);
|
|
73
|
+
return `{${parts.join(", ")}}`;
|
|
74
|
+
}
|
|
75
|
+
return typeOf(args);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* ``json.dumps`` as Python writes it, which is what the other runtime
|
|
79
|
+
* hashes and displays.
|
|
80
|
+
*
|
|
81
|
+
* ``JSON.stringify`` omits the spaces Python puts after ``,`` and
|
|
82
|
+
* ``:``. That is invisible in a console and decisive in a digest: the
|
|
83
|
+
* same arguments hashed to different values on the two sides, so
|
|
84
|
+
* duplicate and loop detection disagreed about whether two calls were
|
|
85
|
+
* the same call. ``sortKeys`` additionally makes two calls that differ
|
|
86
|
+
* only in key order agree, which is what the digest is for.
|
|
87
|
+
*/
|
|
88
|
+
export function pyJson(value, sortKeys = false) {
|
|
89
|
+
const seen = new WeakSet();
|
|
90
|
+
const walk = (v) => {
|
|
91
|
+
if (v === null || v === undefined)
|
|
92
|
+
return "null";
|
|
93
|
+
if (typeof v === "string")
|
|
94
|
+
return JSON.stringify(v);
|
|
95
|
+
if (typeof v === "number" || typeof v === "boolean")
|
|
96
|
+
return JSON.stringify(v);
|
|
97
|
+
if (typeof v !== "object")
|
|
98
|
+
return JSON.stringify(String(v));
|
|
99
|
+
if (seen.has(v))
|
|
100
|
+
return JSON.stringify("[circular]");
|
|
101
|
+
seen.add(v);
|
|
102
|
+
if (Array.isArray(v))
|
|
103
|
+
return "[" + v.map(walk).join(", ") + "]";
|
|
104
|
+
const o = v;
|
|
105
|
+
const keys = sortKeys ? Object.keys(o).sort() : Object.keys(o);
|
|
106
|
+
return "{" + keys.map((k) => `${JSON.stringify(k)}: ${walk(o[k])}`).join(", ") + "}";
|
|
107
|
+
};
|
|
108
|
+
try {
|
|
109
|
+
return walk(value);
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return String(value);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* A stable short hash of an argument set. An equality token, not a
|
|
117
|
+
* signature, which is why twelve hex characters is enough: it is what
|
|
118
|
+
* lets duplicate and loop detection keep working with no content.
|
|
119
|
+
*/
|
|
120
|
+
export function digest(args) {
|
|
121
|
+
if (args === null || args === undefined)
|
|
122
|
+
return "";
|
|
123
|
+
return ("sha256:" +
|
|
124
|
+
createHash("sha256").update(pyJson(args, true)).digest("hex").slice(0, 12));
|
|
125
|
+
}
|
|
126
|
+
/** What ``argsPreview`` carries at this level. */
|
|
127
|
+
export function preview(args, level, fullPreview) {
|
|
128
|
+
if (level === "full")
|
|
129
|
+
return fullPreview;
|
|
130
|
+
if (level === "shape")
|
|
131
|
+
return shape(args);
|
|
132
|
+
if (level === "hashed")
|
|
133
|
+
return digest(args);
|
|
134
|
+
return "";
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* What a model turn may quote of itself. A response is the most
|
|
138
|
+
* content-bearing field in the payload, so it goes one level earlier
|
|
139
|
+
* than arguments do.
|
|
140
|
+
*/
|
|
141
|
+
export function say(text, level) {
|
|
142
|
+
return level === "metadata" || level === "tool_calls" ? "" : text;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Whether a step of this type is recorded at all.
|
|
146
|
+
*
|
|
147
|
+
* Only ``tool_calls`` drops whole steps. Every other level keeps the
|
|
148
|
+
* shape of the run and empties fields; this one keeps the action lane
|
|
149
|
+
* alone, because that is what the customer asked for by name.
|
|
150
|
+
*/
|
|
151
|
+
export function keepsStep(stepType, level) {
|
|
152
|
+
return level === "tool_calls" ? stepType === "tool_call" : true;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* A stamp for the run, so a reader knows what they are not seeing.
|
|
156
|
+
*
|
|
157
|
+
* A dashboard showing empty arguments has to be able to say whether the
|
|
158
|
+
* agent passed none or the deployment declined to send them.
|
|
159
|
+
*/
|
|
160
|
+
export function describe(level) {
|
|
161
|
+
return {
|
|
162
|
+
level,
|
|
163
|
+
sendsArguments: level === "full",
|
|
164
|
+
sendsArgumentShapes: level === "full" || level === "shape",
|
|
165
|
+
sendsOutputText: level === "full" || level === "shape" || level === "hashed",
|
|
166
|
+
sendsClaimValues: level === "full" || level === "shape" || level === "hashed",
|
|
167
|
+
sendsOutputLane: level !== "tool_calls",
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=privacy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"privacy.js","sourceRoot":"","sources":["../../src/cloud/privacy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One finished run, in the shape the cloud stores.
|
|
3
|
+
*
|
|
4
|
+
* Port of the projection in ``sponsio/bridge/session.py``. Field names
|
|
5
|
+
* are Python's, not new ones: the server, the console and the findings
|
|
6
|
+
* pipeline all read this object, and a TypeScript run that spelled
|
|
7
|
+
* ``argsPreview`` differently would upload successfully and then appear
|
|
8
|
+
* as a run with no arguments and no rules.
|
|
9
|
+
*/
|
|
10
|
+
import type { DetFormula } from "../core/patterns.js";
|
|
11
|
+
import type { AgentTurnSpan } from "../core/spans.js";
|
|
12
|
+
import type { DetViolation } from "../index.js";
|
|
13
|
+
import * as privacy from "./privacy.js";
|
|
14
|
+
/** Parity with ``bridge.spans.slug``. */
|
|
15
|
+
export declare function slug(text: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* One line, truncated. Truncation happens before the value leaves the
|
|
18
|
+
* machine, so an argument that should never have been sent cannot be
|
|
19
|
+
* reconstructed from what was.
|
|
20
|
+
*/
|
|
21
|
+
export declare function argsPreview(args: unknown, limit?: number): string;
|
|
22
|
+
/** A run id with enough entropy that two runs cannot silently become one. */
|
|
23
|
+
export declare function newSessionId(): string;
|
|
24
|
+
export interface RunSpan {
|
|
25
|
+
span: AgentTurnSpan;
|
|
26
|
+
/** The violations the check produced, in the order it produced them. */
|
|
27
|
+
violations: DetViolation[];
|
|
28
|
+
/** What kind of step this was; only ``tool_call`` survives `tool_calls`. */
|
|
29
|
+
type?: string;
|
|
30
|
+
}
|
|
31
|
+
export interface ViewModelInput {
|
|
32
|
+
agentId: string;
|
|
33
|
+
mode: string;
|
|
34
|
+
sessionId: string;
|
|
35
|
+
startedAt: number;
|
|
36
|
+
contracts: DetFormula[];
|
|
37
|
+
spans: RunSpan[];
|
|
38
|
+
privacyLevel: privacy.PrivacyLevel;
|
|
39
|
+
/** Which book this run enforced, when it came from the cloud. */
|
|
40
|
+
rulebookStamp?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Build the run object.
|
|
44
|
+
*
|
|
45
|
+
* The privacy level is applied here rather than at the transport, so
|
|
46
|
+
* there is one place that decides what leaves and no path around it.
|
|
47
|
+
*/
|
|
48
|
+
export declare function buildViewModel(input: ViewModelInput): Record<string, unknown>;
|
|
49
|
+
//# sourceMappingURL=view-model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view-model.d.ts","sourceRoot":"","sources":["../../src/cloud/view-model.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAY,MAAM,kBAAkB,CAAC;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AAKxC,yCAAyC;AACzC,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzC;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,SAAM,GAAG,MAAM,CAO9D;AA4BD,6EAA6E;AAC7E,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,aAAa,CAAC;IACpB,wEAAwE;IACxE,UAAU,EAAE,YAAY,EAAE,CAAC;IAC3B,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,UAAU,EAAE,CAAC;IACxB,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC,YAAY,CAAC;IACnC,iEAAiE;IACjE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAUD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAuG7E"}
|