nexus-ai-pro 2.3.0 → 2.5.0
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/API_STABILITY.md +271 -0
- package/CHANGELOG.md +330 -1
- package/README.md +18 -4
- package/SECURITY.md +209 -0
- package/dist/adapter-kit/contracts.d.ts +87 -0
- package/dist/adapter-kit/contracts.js +237 -0
- package/dist/adapter-kit/errors.d.ts +39 -0
- package/dist/adapter-kit/errors.js +52 -0
- package/dist/adapter-kit/index.d.ts +144 -0
- package/dist/adapter-kit/index.js +178 -0
- package/dist/adapter-kit/semver.d.ts +12 -0
- package/dist/adapter-kit/semver.js +55 -0
- package/dist/agent/middleware/pii.js +2 -33
- package/dist/context-hub/hub.d.ts +53 -0
- package/dist/context-hub/hub.js +108 -3
- package/dist/context-hub/index.d.ts +2 -1
- package/dist/context-hub/index.js +2 -1
- package/dist/context-hub/signing.d.ts +95 -0
- package/dist/context-hub/signing.js +88 -0
- package/dist/core/secure-stream.js +4 -3
- package/dist/doctor/index.d.ts +4 -2
- package/dist/doctor/index.js +29 -0
- package/dist/embeddings/adapters.js +2 -1
- package/dist/evals/judge.js +2 -5
- package/dist/evaluate/cache.d.ts +0 -14
- package/dist/evaluate/cache.js +0 -30
- package/dist/evaluate/file-cache.d.ts +15 -0
- package/dist/evaluate/file-cache.js +30 -0
- package/dist/evaluate/index.d.ts +2 -1
- package/dist/evaluate/index.js +2 -1
- package/dist/evaluate/review.js +2 -2
- package/dist/evaluate/run.js +2 -2
- package/dist/evaluate/threads.d.ts +187 -0
- package/dist/evaluate/threads.js +187 -0
- package/dist/evaluate/version.js +3 -3
- package/dist/graph/graph.js +2 -2
- package/dist/graph/node-cache.js +3 -3
- package/dist/hallucination/rag.d.ts +4 -1
- package/dist/hallucination/rag.js +6 -1
- package/dist/images/asset-stores.js +2 -3
- package/dist/images/asset-support.js +2 -2
- package/dist/images/assets.js +1 -2
- package/dist/images/evals.js +4 -4
- package/dist/insights/proposals.js +1 -2
- package/dist/insights/regressions.d.ts +26 -2
- package/dist/insights/regressions.js +129 -3
- package/dist/loaders/git.js +8 -1
- package/dist/loaders/web.js +7 -1
- package/dist/mcp/client.d.ts +14 -0
- package/dist/mcp/client.js +59 -1
- package/dist/mcp/registry.d.ts +6 -0
- package/dist/mcp/registry.js +7 -0
- package/dist/operations/adapters.d.ts +2 -1
- package/dist/operations/runner.js +2 -0
- package/dist/operations/stats.js +11 -4
- package/dist/postgres/index.d.ts +2 -1
- package/dist/postgres/index.js +4 -0
- package/dist/postgres/operations.js +11 -4
- package/dist/postgres/store.d.ts +7 -0
- package/dist/postgres/store.js +21 -0
- package/dist/postgres/tenancy.d.ts +43 -0
- package/dist/postgres/tenancy.js +71 -0
- package/dist/prompts/file.js +28 -11
- package/dist/protocols/a2a.d.ts +235 -0
- package/dist/protocols/a2a.js +386 -0
- package/dist/protocols/acp.d.ts +87 -0
- package/dist/protocols/acp.js +322 -0
- package/dist/protocols/ag-ui.d.ts +120 -0
- package/dist/protocols/ag-ui.js +180 -0
- package/dist/protocols/shared.d.ts +80 -0
- package/dist/protocols/shared.js +49 -0
- package/dist/providers/anthropic.js +1 -0
- package/dist/providers/cohere.js +2 -2
- package/dist/providers/google.js +2 -11
- package/dist/providers/openai.js +1 -0
- package/dist/rag/file-ingestion.js +15 -9
- package/dist/runtime/detect.d.ts +17 -0
- package/dist/runtime/detect.js +16 -0
- package/dist/runtime/index.d.ts +19 -0
- package/dist/runtime/index.js +7 -0
- package/dist/security/injection-detector.d.ts +2 -0
- package/dist/security/injection-detector.js +7 -1
- package/dist/security/input-guard.js +5 -2
- package/dist/security/output-guard.js +8 -4
- package/dist/security/pii-detector.js +22 -6
- package/dist/security/prompt-hardening.js +6 -2
- package/dist/security/semantic-injection-classifier.d.ts +2 -1
- package/dist/security/semantic-injection-classifier.js +31 -35
- package/dist/security/upload-scanner.d.ts +8 -0
- package/dist/security/upload-scanner.js +51 -9
- package/dist/server/deployments.d.ts +188 -11
- package/dist/server/deployments.js +474 -36
- package/dist/server/metrics.d.ts +2 -0
- package/dist/server/metrics.js +7 -0
- package/dist/server/runs.d.ts +18 -1
- package/dist/server/runs.js +66 -7
- package/dist/server/server.js +9 -1
- package/dist/server/state.d.ts +12 -2
- package/dist/server/state.js +15 -0
- package/dist/sqlite/operations.js +15 -4
- package/dist/sqlite/store.d.ts +7 -0
- package/dist/sqlite/store.js +28 -0
- package/dist/store/memory.d.ts +8 -0
- package/dist/store/memory.js +12 -1
- package/dist/store/redis.d.ts +13 -0
- package/dist/store/redis.js +38 -0
- package/dist/testing/record.js +2 -2
- package/dist/tracing/instrument.js +1 -0
- package/dist/tracing/stores.js +2 -1
- package/dist/tracing/tracer.d.ts +4 -0
- package/dist/tracing/tracer.js +8 -2
- package/dist/types/config.d.ts +20 -0
- package/dist/types/operations.d.ts +7 -0
- package/dist/types/server.d.ts +67 -2
- package/dist/types/store.d.ts +9 -0
- package/dist/utils/base64.d.ts +4 -0
- package/dist/utils/base64.js +21 -0
- package/dist/utils/checksums.d.ts +22 -0
- package/dist/utils/checksums.js +39 -0
- package/dist/utils/ids.d.ts +8 -0
- package/dist/utils/ids.js +26 -2
- package/dist/utils/sha256.d.ts +22 -0
- package/dist/utils/sha256.js +120 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist-cjs/adapter-kit/contracts.d.ts +87 -0
- package/dist-cjs/adapter-kit/contracts.js +243 -0
- package/dist-cjs/adapter-kit/errors.d.ts +39 -0
- package/dist-cjs/adapter-kit/errors.js +57 -0
- package/dist-cjs/adapter-kit/index.d.ts +144 -0
- package/dist-cjs/adapter-kit/index.js +194 -0
- package/dist-cjs/adapter-kit/semver.d.ts +12 -0
- package/dist-cjs/adapter-kit/semver.js +59 -0
- package/dist-cjs/agent/middleware/pii.js +4 -35
- package/dist-cjs/context-hub/hub.d.ts +53 -0
- package/dist-cjs/context-hub/hub.js +110 -4
- package/dist-cjs/context-hub/index.d.ts +2 -1
- package/dist-cjs/context-hub/index.js +7 -1
- package/dist-cjs/context-hub/signing.d.ts +95 -0
- package/dist-cjs/context-hub/signing.js +96 -0
- package/dist-cjs/core/secure-stream.js +4 -3
- package/dist-cjs/doctor/index.d.ts +4 -2
- package/dist-cjs/doctor/index.js +29 -0
- package/dist-cjs/embeddings/adapters.js +2 -1
- package/dist-cjs/evals/judge.js +2 -5
- package/dist-cjs/evaluate/cache.d.ts +0 -14
- package/dist-cjs/evaluate/cache.js +1 -65
- package/dist-cjs/evaluate/file-cache.d.ts +15 -0
- package/dist-cjs/evaluate/file-cache.js +67 -0
- package/dist-cjs/evaluate/index.d.ts +2 -1
- package/dist-cjs/evaluate/index.js +3 -2
- package/dist-cjs/evaluate/review.js +2 -2
- package/dist-cjs/evaluate/run.js +2 -2
- package/dist-cjs/evaluate/threads.d.ts +187 -0
- package/dist-cjs/evaluate/threads.js +198 -0
- package/dist-cjs/evaluate/version.js +3 -3
- package/dist-cjs/graph/graph.js +2 -2
- package/dist-cjs/graph/node-cache.js +3 -3
- package/dist-cjs/hallucination/rag.d.ts +4 -1
- package/dist-cjs/hallucination/rag.js +6 -1
- package/dist-cjs/images/asset-stores.js +2 -3
- package/dist-cjs/images/asset-support.js +2 -2
- package/dist-cjs/images/assets.js +1 -2
- package/dist-cjs/images/evals.js +4 -4
- package/dist-cjs/insights/proposals.js +1 -2
- package/dist-cjs/insights/regressions.d.ts +26 -2
- package/dist-cjs/insights/regressions.js +129 -3
- package/dist-cjs/loaders/git.js +8 -1
- package/dist-cjs/loaders/web.js +7 -1
- package/dist-cjs/mcp/client.d.ts +14 -0
- package/dist-cjs/mcp/client.js +60 -1
- package/dist-cjs/mcp/registry.d.ts +6 -0
- package/dist-cjs/mcp/registry.js +7 -0
- package/dist-cjs/operations/adapters.d.ts +2 -1
- package/dist-cjs/operations/runner.js +2 -0
- package/dist-cjs/operations/stats.js +11 -4
- package/dist-cjs/postgres/index.d.ts +2 -1
- package/dist-cjs/postgres/index.js +8 -1
- package/dist-cjs/postgres/operations.js +11 -4
- package/dist-cjs/postgres/store.d.ts +7 -0
- package/dist-cjs/postgres/store.js +21 -0
- package/dist-cjs/postgres/tenancy.d.ts +43 -0
- package/dist-cjs/postgres/tenancy.js +110 -0
- package/dist-cjs/prompts/file.js +28 -11
- package/dist-cjs/protocols/a2a.d.ts +235 -0
- package/dist-cjs/protocols/a2a.js +393 -0
- package/dist-cjs/protocols/acp.d.ts +87 -0
- package/dist-cjs/protocols/acp.js +326 -0
- package/dist-cjs/protocols/ag-ui.d.ts +120 -0
- package/dist-cjs/protocols/ag-ui.js +186 -0
- package/dist-cjs/protocols/shared.d.ts +80 -0
- package/dist-cjs/protocols/shared.js +59 -0
- package/dist-cjs/providers/anthropic.js +1 -0
- package/dist-cjs/providers/cohere.js +2 -2
- package/dist-cjs/providers/google.js +3 -12
- package/dist-cjs/providers/openai.js +1 -0
- package/dist-cjs/rag/file-ingestion.js +14 -8
- package/dist-cjs/runtime/detect.d.ts +17 -0
- package/dist-cjs/runtime/detect.js +19 -0
- package/dist-cjs/runtime/index.d.ts +19 -0
- package/dist-cjs/runtime/index.js +31 -0
- package/dist-cjs/security/injection-detector.d.ts +2 -0
- package/dist-cjs/security/injection-detector.js +7 -1
- package/dist-cjs/security/input-guard.js +5 -2
- package/dist-cjs/security/output-guard.js +8 -4
- package/dist-cjs/security/pii-detector.js +22 -6
- package/dist-cjs/security/prompt-hardening.js +6 -2
- package/dist-cjs/security/semantic-injection-classifier.d.ts +2 -1
- package/dist-cjs/security/semantic-injection-classifier.js +31 -35
- package/dist-cjs/security/upload-scanner.d.ts +8 -0
- package/dist-cjs/security/upload-scanner.js +53 -9
- package/dist-cjs/server/deployments.d.ts +188 -11
- package/dist-cjs/server/deployments.js +474 -36
- package/dist-cjs/server/metrics.d.ts +2 -0
- package/dist-cjs/server/metrics.js +8 -0
- package/dist-cjs/server/runs.d.ts +18 -1
- package/dist-cjs/server/runs.js +65 -6
- package/dist-cjs/server/server.js +9 -1
- package/dist-cjs/server/state.d.ts +12 -2
- package/dist-cjs/server/state.js +15 -0
- package/dist-cjs/sqlite/operations.js +15 -4
- package/dist-cjs/sqlite/store.d.ts +7 -0
- package/dist-cjs/sqlite/store.js +28 -0
- package/dist-cjs/store/memory.d.ts +8 -0
- package/dist-cjs/store/memory.js +12 -1
- package/dist-cjs/store/redis.d.ts +13 -0
- package/dist-cjs/store/redis.js +38 -0
- package/dist-cjs/testing/record.js +2 -2
- package/dist-cjs/tracing/instrument.js +1 -0
- package/dist-cjs/tracing/stores.js +2 -1
- package/dist-cjs/tracing/tracer.d.ts +4 -0
- package/dist-cjs/tracing/tracer.js +8 -2
- package/dist-cjs/types/config.d.ts +20 -0
- package/dist-cjs/types/operations.d.ts +7 -0
- package/dist-cjs/types/server.d.ts +67 -2
- package/dist-cjs/types/store.d.ts +9 -0
- package/dist-cjs/utils/base64.d.ts +4 -0
- package/dist-cjs/utils/base64.js +25 -0
- package/dist-cjs/utils/checksums.d.ts +22 -0
- package/dist-cjs/utils/checksums.js +46 -0
- package/dist-cjs/utils/ids.d.ts +8 -0
- package/dist-cjs/utils/ids.js +28 -2
- package/dist-cjs/utils/sha256.d.ts +22 -0
- package/dist-cjs/utils/sha256.js +125 -0
- package/dist-cjs/version.d.ts +1 -1
- package/dist-cjs/version.js +1 -1
- package/llms.txt +5 -2
- package/package.json +102 -6
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { runEmbeddingProviderConformance, } from '../testing/embedding-provider-conformance.js';
|
|
2
|
+
import { runProviderConformance } from '../testing/provider-conformance.js';
|
|
3
|
+
import { NEXUS_VERSION } from '../version.js';
|
|
4
|
+
import { runRetrieverContract, runStoreContract, runVectorStoreContract, } from './contracts.js';
|
|
5
|
+
import { AdapterError, classifyAdapterError } from './errors.js';
|
|
6
|
+
import { satisfiesRange } from './semver.js';
|
|
7
|
+
export { ADAPTER_FIXTURE_PASSAGES, runRetrieverContract, runStoreContract, runVectorStoreContract, } from './contracts.js';
|
|
8
|
+
export { AdapterError, classifyAdapterError } from './errors.js';
|
|
9
|
+
export { parseVersion, satisfiesRange } from './semver.js';
|
|
10
|
+
const OPERATIONS = {
|
|
11
|
+
provider: ['complete', 'healthCheck'],
|
|
12
|
+
embeddings: ['embed'],
|
|
13
|
+
'vector-store': ['add', 'search', 'searchVector', 'delete'],
|
|
14
|
+
retriever: ['retrieve', 'add', 'delete'],
|
|
15
|
+
store: ['put', 'get', 'delete', 'search', 'listNamespaces'],
|
|
16
|
+
};
|
|
17
|
+
function build(kind, definition, contract) {
|
|
18
|
+
for (const field of ['name', 'version', 'nexus']) {
|
|
19
|
+
if (typeof definition[field] !== 'string' || !definition[field])
|
|
20
|
+
throw new TypeError(`An adapter needs a ${field}`);
|
|
21
|
+
}
|
|
22
|
+
satisfiesRange(NEXUS_VERSION, definition.nexus);
|
|
23
|
+
const create = async (config, options = {}) => instrument(kind, definition, await definition.create(config), options);
|
|
24
|
+
return {
|
|
25
|
+
kind,
|
|
26
|
+
name: definition.name,
|
|
27
|
+
version: definition.version,
|
|
28
|
+
nexus: definition.nexus,
|
|
29
|
+
capabilities: definition.capabilities,
|
|
30
|
+
...(definition.normalizeError ? { normalizeError: definition.normalizeError } : {}),
|
|
31
|
+
...(definition.budgets ? { budgets: definition.budgets } : {}),
|
|
32
|
+
create,
|
|
33
|
+
compatible: (nexusVersion = NEXUS_VERSION) => satisfiesRange(nexusVersion, definition.nexus),
|
|
34
|
+
async verify(config, options) {
|
|
35
|
+
const durations = new Map();
|
|
36
|
+
const instance = await create(config, {
|
|
37
|
+
onCall: (event) => {
|
|
38
|
+
if (event.ok)
|
|
39
|
+
durations.set(event.operation, [...(durations.get(event.operation) ?? []), event.durationMs]);
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
const compatible = satisfiesRange(NEXUS_VERSION, definition.nexus);
|
|
43
|
+
const checks = [
|
|
44
|
+
{
|
|
45
|
+
name: `declares support for nexus-ai-pro ${NEXUS_VERSION}`,
|
|
46
|
+
ok: compatible,
|
|
47
|
+
...(compatible ? {} : { detail: `the declared range is ${definition.nexus}` }),
|
|
48
|
+
},
|
|
49
|
+
...(await contract(instance, options, definition.capabilities)),
|
|
50
|
+
];
|
|
51
|
+
const benchmark = {};
|
|
52
|
+
for (const [operation, values] of durations) {
|
|
53
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
54
|
+
const at = (q) => round(sorted[Math.min(sorted.length - 1, Math.ceil(q * sorted.length) - 1)] ?? 0);
|
|
55
|
+
benchmark[operation] = { calls: sorted.length, p50Ms: at(0.5), p95Ms: at(0.95) };
|
|
56
|
+
}
|
|
57
|
+
for (const [operation, budget] of Object.entries(definition.budgets ?? {})) {
|
|
58
|
+
const measured = benchmark[operation]?.p95Ms;
|
|
59
|
+
checks.push(measured === undefined
|
|
60
|
+
? {
|
|
61
|
+
name: `${operation} stays within ${budget} ms at p95`,
|
|
62
|
+
ok: true,
|
|
63
|
+
skipped: true,
|
|
64
|
+
detail: 'not called by the contract',
|
|
65
|
+
}
|
|
66
|
+
: {
|
|
67
|
+
name: `${operation} stays within ${budget} ms at p95`,
|
|
68
|
+
ok: measured <= budget,
|
|
69
|
+
...(measured <= budget ? {} : { detail: `measured ${measured} ms` }),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
adapter: definition.name,
|
|
74
|
+
version: definition.version,
|
|
75
|
+
kind,
|
|
76
|
+
nexusVersion: NEXUS_VERSION,
|
|
77
|
+
compatible,
|
|
78
|
+
passed: checks.every((check) => check.ok),
|
|
79
|
+
checks,
|
|
80
|
+
benchmark,
|
|
81
|
+
};
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function instrument(kind, definition, instance, options) {
|
|
86
|
+
const operations = new Set(OPERATIONS[kind]);
|
|
87
|
+
return new Proxy(instance, {
|
|
88
|
+
get(target, property, receiver) {
|
|
89
|
+
const value = Reflect.get(target, property, receiver);
|
|
90
|
+
if (typeof property !== 'string' || !operations.has(property) || typeof value !== 'function') {
|
|
91
|
+
return typeof value === 'function' ? value.bind(target) : value;
|
|
92
|
+
}
|
|
93
|
+
return async (...args) => {
|
|
94
|
+
const started = performance.now();
|
|
95
|
+
try {
|
|
96
|
+
const result = await value.apply(target, args);
|
|
97
|
+
options.onCall?.({
|
|
98
|
+
adapter: definition.name,
|
|
99
|
+
kind,
|
|
100
|
+
operation: property,
|
|
101
|
+
durationMs: performance.now() - started,
|
|
102
|
+
ok: true,
|
|
103
|
+
});
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
const failure = error instanceof AdapterError
|
|
108
|
+
? {
|
|
109
|
+
code: error.code,
|
|
110
|
+
retryable: error.retryable,
|
|
111
|
+
...(error.status === undefined ? {} : { status: error.status }),
|
|
112
|
+
}
|
|
113
|
+
: (definition.normalizeError?.(error, property) ?? classifyAdapterError(error));
|
|
114
|
+
options.onCall?.({
|
|
115
|
+
adapter: definition.name,
|
|
116
|
+
kind,
|
|
117
|
+
operation: property,
|
|
118
|
+
durationMs: performance.now() - started,
|
|
119
|
+
ok: false,
|
|
120
|
+
error: failure,
|
|
121
|
+
});
|
|
122
|
+
throw error instanceof AdapterError ? error : new AdapterError(definition.name, property, failure, error);
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
export function defineProviderAdapter(definition) {
|
|
129
|
+
return build('provider', definition, async (provider, options, capabilities) => {
|
|
130
|
+
const results = await runProviderConformance(definition.name, provider, {
|
|
131
|
+
...options,
|
|
132
|
+
testStream: capabilities.streaming,
|
|
133
|
+
testJson: capabilities.json,
|
|
134
|
+
testTools: capabilities.tools,
|
|
135
|
+
testHealth: capabilities.health,
|
|
136
|
+
});
|
|
137
|
+
return results.flatMap((result) => [
|
|
138
|
+
{
|
|
139
|
+
name: `completes the ${result.caseName} case`,
|
|
140
|
+
ok: result.completeOk,
|
|
141
|
+
...(result.completeOk ? {} : { detail: result.error ?? 'the response was not accepted' }),
|
|
142
|
+
},
|
|
143
|
+
...(result.streamOk === undefined ? [] : [{ name: `streams the ${result.caseName} case`, ok: result.streamOk }]),
|
|
144
|
+
...(result.healthOk === undefined ? [] : [{ name: 'answers its health check', ok: result.healthOk }]),
|
|
145
|
+
]);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
export function defineEmbeddingsAdapter(definition) {
|
|
149
|
+
return build('embeddings', definition, async (provider, options, capabilities) => {
|
|
150
|
+
const results = await runEmbeddingProviderConformance(definition.name, provider, {
|
|
151
|
+
...options,
|
|
152
|
+
testAbort: capabilities.abort,
|
|
153
|
+
testDeterminism: capabilities.deterministic,
|
|
154
|
+
});
|
|
155
|
+
return results.flatMap((result) => [
|
|
156
|
+
{
|
|
157
|
+
name: `embeds the ${result.caseName} case`,
|
|
158
|
+
ok: result.ok,
|
|
159
|
+
...(result.ok ? {} : { detail: result.error ?? 'not accepted' }),
|
|
160
|
+
},
|
|
161
|
+
...(result.abortOk === undefined
|
|
162
|
+
? []
|
|
163
|
+
: [{ name: `stops the ${result.caseName} case when aborted`, ok: result.abortOk }]),
|
|
164
|
+
]);
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
export function defineVectorStoreAdapter(definition) {
|
|
168
|
+
return build('vector-store', definition, (store, options, capabilities) => runVectorStoreContract(store, { ...options, capabilities }));
|
|
169
|
+
}
|
|
170
|
+
export function defineRetrieverAdapter(definition) {
|
|
171
|
+
return build('retriever', definition, (retriever, options, capabilities) => runRetrieverContract(retriever, { ...options, capabilities }));
|
|
172
|
+
}
|
|
173
|
+
export function defineStoreAdapter(definition) {
|
|
174
|
+
return build('store', definition, (store, _options, capabilities) => runStoreContract(store, { capabilities }));
|
|
175
|
+
}
|
|
176
|
+
function round(value) {
|
|
177
|
+
return Math.round(value * 100) / 100;
|
|
178
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Version ranges, as an adapter declares the releases of `nexus-ai-pro` it works with. A small,
|
|
3
|
+
* dependency-free subset of npm's ranges: comparators joined by spaces must all hold, alternatives
|
|
4
|
+
* joined by `||` need one to hold, and `>=`, `>`, `<=`, `<`, `=`, `^`, `~`, `x`, and `*` mean what
|
|
5
|
+
* they mean in npm.
|
|
6
|
+
*/
|
|
7
|
+
type Version = [number, number, number];
|
|
8
|
+
/** A version as three numbers. A prerelease or build tag is ignored. `undefined` for anything else. */
|
|
9
|
+
export declare function parseVersion(version: string): Version | undefined;
|
|
10
|
+
/** Whether `version` satisfies `range`, such as `>=2.4.0 <3` or `^2.4.0 || ^3.0.0`. */
|
|
11
|
+
export declare function satisfiesRange(version: string, range: string): boolean;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export function parseVersion(version) {
|
|
2
|
+
const match = /^\s*v?(\d+)\.(\d+)\.(\d+)/.exec(version);
|
|
3
|
+
return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : undefined;
|
|
4
|
+
}
|
|
5
|
+
export function satisfiesRange(version, range) {
|
|
6
|
+
const parsed = parseVersion(version);
|
|
7
|
+
if (!parsed)
|
|
8
|
+
return false;
|
|
9
|
+
return range.split('||').some((alternative) => {
|
|
10
|
+
const comparators = alternative.trim().split(/\s+/).filter(Boolean);
|
|
11
|
+
return comparators.length === 0 || comparators.every((comparator) => holds(parsed, comparator));
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
function holds(version, comparator) {
|
|
15
|
+
const match = /^(>=|<=|>|<|=|\^|~)?v?(\d+|x|X|\*)(?:\.(\d+|x|X|\*))?(?:\.(\d+|x|X|\*))?/.exec(comparator);
|
|
16
|
+
if (!match)
|
|
17
|
+
throw new RangeError(`"${comparator}" is not a version range`);
|
|
18
|
+
const operator = match[1] ?? '';
|
|
19
|
+
const parts = [match[2], match[3], match[4]];
|
|
20
|
+
const fixed = parts.findIndex((part) => part === undefined || /^[xX*]$/.test(part));
|
|
21
|
+
const known = fixed === -1 ? 3 : fixed;
|
|
22
|
+
const base = parts.map((part, index) => (index < known ? Number(part) : 0));
|
|
23
|
+
if (known === 0)
|
|
24
|
+
return operator === '' || operator === '=' || operator === '>=' || operator === '<=';
|
|
25
|
+
switch (operator) {
|
|
26
|
+
case '>=':
|
|
27
|
+
return compare(version, base) >= 0;
|
|
28
|
+
case '>':
|
|
29
|
+
return known === 3 ? compare(version, base) > 0 : compare(version, bump(base, known - 1)) >= 0;
|
|
30
|
+
case '<=':
|
|
31
|
+
return known === 3 ? compare(version, base) <= 0 : compare(version, bump(base, known - 1)) < 0;
|
|
32
|
+
case '<':
|
|
33
|
+
return compare(version, base) < 0;
|
|
34
|
+
case '^': {
|
|
35
|
+
const pinned = base[0] > 0 || known === 1 ? 0 : base[1] > 0 || known === 2 ? 1 : 2;
|
|
36
|
+
return compare(version, base) >= 0 && compare(version, bump(base, pinned)) < 0;
|
|
37
|
+
}
|
|
38
|
+
case '~':
|
|
39
|
+
return compare(version, base) >= 0 && compare(version, bump(base, known >= 2 ? 1 : 0)) < 0;
|
|
40
|
+
default:
|
|
41
|
+
return known === 3
|
|
42
|
+
? compare(version, base) === 0
|
|
43
|
+
: compare(version, base) >= 0 && compare(version, bump(base, known - 1)) < 0;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function bump(version, part) {
|
|
47
|
+
return version.map((value, index) => (index < part ? value : index === part ? value + 1 : 0));
|
|
48
|
+
}
|
|
49
|
+
function compare(left, right) {
|
|
50
|
+
for (let index = 0; index < 3; index += 1) {
|
|
51
|
+
if (left[index] !== right[index])
|
|
52
|
+
return left[index] - right[index];
|
|
53
|
+
}
|
|
54
|
+
return 0;
|
|
55
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ibanChecksum, luhn, phoneNumber } from '../../utils/checksums.js';
|
|
1
2
|
import { shortHash } from './shared.js';
|
|
2
3
|
export class PiiBlockedError extends Error {
|
|
3
4
|
kind;
|
|
@@ -21,10 +22,7 @@ const DETECTORS = {
|
|
|
21
22
|
'ip-address': { pattern: /\b(?:(?:25[0-5]|2[0-4]\d|1?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|1?\d?\d)\b/g },
|
|
22
23
|
phone: {
|
|
23
24
|
pattern: /(?<![\w+])\+?(?:\(\d{1,4}\)|\d{1,4})(?:[ .-]?(?:\(\d{1,4}\)|\d{2,4})){2,4}(?!\w)/g,
|
|
24
|
-
valid:
|
|
25
|
-
const digits = match.replace(/\D/g, '').length;
|
|
26
|
-
return digits >= 10 && digits <= 15 && (/^\+/.test(match) || /[ .()-]/.test(match));
|
|
27
|
-
},
|
|
25
|
+
valid: phoneNumber,
|
|
28
26
|
},
|
|
29
27
|
};
|
|
30
28
|
const ORDER = ['secret', 'email', 'credit-card', 'iban', 'ssn', 'ip-address', 'phone'];
|
|
@@ -142,32 +140,3 @@ function replace(match, kind, strategy) {
|
|
|
142
140
|
function isToolOutput(value) {
|
|
143
141
|
return value?.type === 'tool_output' && Array.isArray(value.content);
|
|
144
142
|
}
|
|
145
|
-
function luhn(match) {
|
|
146
|
-
const digits = match.replace(/\D/g, '');
|
|
147
|
-
if (digits.length < 13 || digits.length > 19)
|
|
148
|
-
return false;
|
|
149
|
-
let sum = 0;
|
|
150
|
-
for (let index = 0; index < digits.length; index += 1) {
|
|
151
|
-
let digit = Number(digits[digits.length - 1 - index]);
|
|
152
|
-
if (index % 2 === 1) {
|
|
153
|
-
digit *= 2;
|
|
154
|
-
if (digit > 9)
|
|
155
|
-
digit -= 9;
|
|
156
|
-
}
|
|
157
|
-
sum += digit;
|
|
158
|
-
}
|
|
159
|
-
return sum % 10 === 0;
|
|
160
|
-
}
|
|
161
|
-
function ibanChecksum(match) {
|
|
162
|
-
const iban = match.replace(/ /g, '');
|
|
163
|
-
if (iban.length < 15 || iban.length > 34)
|
|
164
|
-
return false;
|
|
165
|
-
const rearranged = `${iban.slice(4)}${iban.slice(0, 4)}`;
|
|
166
|
-
let remainder = 0;
|
|
167
|
-
for (const char of rearranged) {
|
|
168
|
-
const value = /\d/.test(char) ? char : String(char.charCodeAt(0) - 55);
|
|
169
|
-
for (const digit of value)
|
|
170
|
-
remainder = (remainder * 10 + Number(digit)) % 97;
|
|
171
|
-
}
|
|
172
|
-
return remainder === 1;
|
|
173
|
-
}
|
|
@@ -2,6 +2,7 @@ import type { GateResult } from '../prompts/errors.js';
|
|
|
2
2
|
import type { PromptRegistry } from '../prompts/registry.js';
|
|
3
3
|
import type { PromptHistoryEntry, PromptLabel, PromptStore, PromptVersion, RenderedPrompt, RenderOptions } from '../types/prompts.js';
|
|
4
4
|
import { type ContextDiff } from './diff.js';
|
|
5
|
+
import { type ContextKeyring, type ContextSignature, type ContextSigner } from './signing.js';
|
|
5
6
|
/** A prompt a bundle uses, pinned to one content version of the prompt registry. */
|
|
6
7
|
export interface ContextPromptPin {
|
|
7
8
|
/** The prompt's name in the registry. */
|
|
@@ -61,6 +62,8 @@ export interface ContextBundle extends ContextBundleDefinition {
|
|
|
61
62
|
author?: string;
|
|
62
63
|
/** The version that was newest before it. */
|
|
63
64
|
parent?: string;
|
|
65
|
+
/** Signatures over its content and its pinned prompts' content. Not part of the version. */
|
|
66
|
+
signatures?: ContextSignature[];
|
|
64
67
|
}
|
|
65
68
|
/** Which bundle version is being used, as experiments and traces record it. */
|
|
66
69
|
export interface ContextReference {
|
|
@@ -125,9 +128,33 @@ export interface ContextHubOptions {
|
|
|
125
128
|
gates?: Record<string, readonly ContextPromotionGate[]>;
|
|
126
129
|
/** Called after every recorded change. */
|
|
127
130
|
onChange?: (entry: ContextHistoryEntry) => void | Promise<void>;
|
|
131
|
+
/**
|
|
132
|
+
* Signs every new version, over its content and its pinned prompts' content, so another hub can
|
|
133
|
+
* check where it came from. Signing a bundle that pins prompts needs `prompts`.
|
|
134
|
+
*/
|
|
135
|
+
signer?: ContextSigner;
|
|
136
|
+
/**
|
|
137
|
+
* The keys whose signatures this hub trusts, for `verify()`, and for `requireSignature`. A signature
|
|
138
|
+
* by a key the keyring does not hold is kept, but never trusted.
|
|
139
|
+
*/
|
|
140
|
+
keyring?: ContextKeyring;
|
|
141
|
+
/**
|
|
142
|
+
* Refuses any bundle without a valid signature by a key in `keyring`: on import, and whenever a
|
|
143
|
+
* version is served through `resolve()` or `renderPrompt()`.
|
|
144
|
+
*/
|
|
145
|
+
requireSignature?: boolean;
|
|
128
146
|
/** Replaces the system clock, for tests. */
|
|
129
147
|
now?: () => Date;
|
|
130
148
|
}
|
|
149
|
+
/** What `ContextHub.verify()` found. */
|
|
150
|
+
export interface ContextVerification {
|
|
151
|
+
/** Whether a key in the keyring signed exactly this content. */
|
|
152
|
+
trusted: boolean;
|
|
153
|
+
/** The digest the content has now. */
|
|
154
|
+
digest: string;
|
|
155
|
+
/** The signature that verified, when one did. */
|
|
156
|
+
signature?: ContextSignature;
|
|
157
|
+
}
|
|
131
158
|
/** Base class for context hub errors, each with a stable `code`. */
|
|
132
159
|
export declare class ContextHubError extends Error {
|
|
133
160
|
/** Stable code, such as `CONTEXT_NOT_FOUND`. */
|
|
@@ -160,6 +187,18 @@ export declare class ContextPromotionError extends ContextHubError {
|
|
|
160
187
|
/** Every gate's verdict. */
|
|
161
188
|
results: GateResult[]);
|
|
162
189
|
}
|
|
190
|
+
/** Raised when a bundle has no signature the hub trusts, or its signatures do not match its content. */
|
|
191
|
+
export declare class ContextSignatureError extends ContextHubError {
|
|
192
|
+
/** The bundle. */
|
|
193
|
+
readonly bundle: string;
|
|
194
|
+
/** The version. */
|
|
195
|
+
readonly version: string;
|
|
196
|
+
constructor(
|
|
197
|
+
/** The bundle. */
|
|
198
|
+
bundle: string,
|
|
199
|
+
/** The version. */
|
|
200
|
+
version: string, reason: string);
|
|
201
|
+
}
|
|
163
202
|
/** Raised when a bundle definition, a pin, or an import is invalid. */
|
|
164
203
|
export declare class ContextDefinitionError extends ContextHubError {
|
|
165
204
|
constructor(message: string);
|
|
@@ -182,6 +221,8 @@ export declare class ContextHub {
|
|
|
182
221
|
/** Where versions, labels, and history live. */
|
|
183
222
|
readonly store: PromptStore;
|
|
184
223
|
private readonly now;
|
|
224
|
+
/** Versions already verified as trusted, which never change. */
|
|
225
|
+
private readonly trusted;
|
|
185
226
|
constructor(options?: ContextHubOptions);
|
|
186
227
|
/**
|
|
187
228
|
* Commits a bundle and returns its version. Unchanged content returns the existing version and
|
|
@@ -193,8 +234,15 @@ export declare class ContextHub {
|
|
|
193
234
|
author?: string;
|
|
194
235
|
label?: string | readonly string[];
|
|
195
236
|
}): Promise<ContextBundle>;
|
|
237
|
+
private commitSigned;
|
|
196
238
|
/** A version by content version, label, or `latest`, the default. Throws `ContextNotFoundError` when there is none. */
|
|
197
239
|
get(name: string, ref?: string): Promise<ContextBundle>;
|
|
240
|
+
/**
|
|
241
|
+
* Whether a key in the hub's keyring signed exactly this bundle's content, and its pinned prompts'
|
|
242
|
+
* content as the prompt registry holds them. A version's answer never changes, so it is checked
|
|
243
|
+
* once.
|
|
244
|
+
*/
|
|
245
|
+
verify(bundle: ContextBundle): Promise<ContextVerification>;
|
|
198
246
|
/** A version with the reference experiments and traces record for it. */
|
|
199
247
|
resolve(name: string, ref?: string): Promise<{
|
|
200
248
|
bundle: ContextBundle;
|
|
@@ -262,6 +310,11 @@ export declare class ContextHub {
|
|
|
262
310
|
label?: string | readonly string[];
|
|
263
311
|
by?: string;
|
|
264
312
|
}): Promise<ContextBundle>;
|
|
313
|
+
/** Refuses a bundle without a trusted signature, when the hub requires one. */
|
|
314
|
+
private assertTrusted;
|
|
315
|
+
private check;
|
|
316
|
+
/** What a signature over this bundle covers, with its pinned prompts read from the registry. */
|
|
317
|
+
private signedContent;
|
|
265
318
|
private read;
|
|
266
319
|
private pointer;
|
|
267
320
|
private record;
|
package/dist/context-hub/hub.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { MemoryPromptStore } from '../prompts/memory.js';
|
|
2
2
|
import { canonicalJson } from '../prompts/version.js';
|
|
3
3
|
import { diffContexts } from './diff.js';
|
|
4
|
+
import { contextDigest, signDigest, verifiedBy, } from './signing.js';
|
|
4
5
|
export class ContextHubError extends Error {
|
|
5
6
|
code;
|
|
6
7
|
constructor(message, code) {
|
|
@@ -36,6 +37,16 @@ export class ContextPromotionError extends ContextHubError {
|
|
|
36
37
|
this.name = 'ContextPromotionError';
|
|
37
38
|
}
|
|
38
39
|
}
|
|
40
|
+
export class ContextSignatureError extends ContextHubError {
|
|
41
|
+
bundle;
|
|
42
|
+
version;
|
|
43
|
+
constructor(bundle, version, reason) {
|
|
44
|
+
super(`Context bundle "${bundle}" ${version}: ${reason}`, 'CONTEXT_SIGNATURE');
|
|
45
|
+
this.bundle = bundle;
|
|
46
|
+
this.version = version;
|
|
47
|
+
this.name = 'ContextSignatureError';
|
|
48
|
+
}
|
|
49
|
+
}
|
|
39
50
|
export class ContextDefinitionError extends ContextHubError {
|
|
40
51
|
constructor(message) {
|
|
41
52
|
super(message, 'CONTEXT_DEFINITION_ERROR');
|
|
@@ -63,12 +74,19 @@ export class ContextHub {
|
|
|
63
74
|
options;
|
|
64
75
|
store;
|
|
65
76
|
now;
|
|
77
|
+
trusted = new Map();
|
|
66
78
|
constructor(options = {}) {
|
|
67
79
|
this.options = options;
|
|
80
|
+
if (options.requireSignature && !options.keyring) {
|
|
81
|
+
throw new TypeError('requireSignature needs a keyring of the keys the hub trusts');
|
|
82
|
+
}
|
|
68
83
|
this.store = options.store ?? new MemoryPromptStore();
|
|
69
84
|
this.now = options.now ?? (() => new Date());
|
|
70
85
|
}
|
|
71
86
|
async commit(definition, options = {}) {
|
|
87
|
+
return this.commitSigned(definition, options, []);
|
|
88
|
+
}
|
|
89
|
+
async commitSigned(definition, options, inherited) {
|
|
72
90
|
validate(definition);
|
|
73
91
|
if (this.options.prompts) {
|
|
74
92
|
for (const [role, pin] of Object.entries(definition.prompts ?? {})) {
|
|
@@ -92,6 +110,13 @@ export class ContextHub {
|
|
|
92
110
|
...(options.author === undefined ? {} : { author: options.author }),
|
|
93
111
|
...(newest ? { parent: newest.version } : {}),
|
|
94
112
|
};
|
|
113
|
+
const signatures = [...inherited];
|
|
114
|
+
if (this.options.signer) {
|
|
115
|
+
const digest = await contextDigest(await this.signedContent(definition));
|
|
116
|
+
signatures.push(await signDigest(this.options.signer, digest, this.now()));
|
|
117
|
+
}
|
|
118
|
+
if (signatures.length > 0)
|
|
119
|
+
stored.signatures = signatures;
|
|
95
120
|
await this.store.saveVersion(toStored(stored));
|
|
96
121
|
await this.record({ name: definition.name, action: 'commit', version: id, by: options.author });
|
|
97
122
|
}
|
|
@@ -118,8 +143,19 @@ export class ContextHub {
|
|
|
118
143
|
throw new ContextNotFoundError(name, ref);
|
|
119
144
|
return found;
|
|
120
145
|
}
|
|
146
|
+
async verify(bundle) {
|
|
147
|
+
const key = `${bundle.name}@${bundle.version}`;
|
|
148
|
+
let pending = this.trusted.get(key);
|
|
149
|
+
if (!pending) {
|
|
150
|
+
pending = this.check(bundle, await this.signedContent(bundle));
|
|
151
|
+
this.trusted.set(key, pending);
|
|
152
|
+
pending.catch(() => this.trusted.delete(key));
|
|
153
|
+
}
|
|
154
|
+
return pending;
|
|
155
|
+
}
|
|
121
156
|
async resolve(name, ref = 'latest') {
|
|
122
157
|
const bundle = await this.get(name, ref);
|
|
158
|
+
await this.assertTrusted(bundle);
|
|
123
159
|
return {
|
|
124
160
|
bundle,
|
|
125
161
|
reference: {
|
|
@@ -133,6 +169,7 @@ export class ContextHub {
|
|
|
133
169
|
const registry = this.options.prompts;
|
|
134
170
|
if (!registry)
|
|
135
171
|
throw new ContextDefinitionError('Rendering a pinned prompt needs the hub to have a prompt registry');
|
|
172
|
+
await this.assertTrusted(bundle);
|
|
136
173
|
const pin = bundle.prompts?.[role];
|
|
137
174
|
if (!pin)
|
|
138
175
|
throw new ContextNotFoundError(bundle.name, `prompt role "${role}"`);
|
|
@@ -259,15 +296,52 @@ export class ContextHub {
|
|
|
259
296
|
throw new ContextDefinitionError(`Prompt ${prompt.name} was exported as ${version} but its content is ${committed.version}`);
|
|
260
297
|
}
|
|
261
298
|
}
|
|
262
|
-
const { version, createdAt: _createdAt, parent: _parent, message, author, ...definition } = exported.bundle;
|
|
299
|
+
const { version, createdAt: _createdAt, parent: _parent, message, author, signatures = [], ...definition } = exported.bundle;
|
|
263
300
|
if ((await contextVersion(definition)) !== version) {
|
|
264
301
|
throw new ContextDefinitionError(`Bundle ${definition.name} was exported as ${version} but its content has changed`);
|
|
265
302
|
}
|
|
266
|
-
|
|
303
|
+
const digest = await contextDigest(signedContentOf(definition, exportedPrompts(exported)));
|
|
304
|
+
const claims = signatures.filter((signature) => signature?.digest === digest);
|
|
305
|
+
if (this.options.requireSignature && this.options.keyring) {
|
|
306
|
+
const signed = await verifiedBy(this.options.keyring, digest, claims);
|
|
307
|
+
if (!signed) {
|
|
308
|
+
throw new ContextSignatureError(definition.name, version, signatures.length > 0
|
|
309
|
+
? 'no signature verifies against its content with a trusted key'
|
|
310
|
+
: 'it is not signed, and this hub requires a signature');
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return this.commitSigned(definition, {
|
|
267
314
|
message: message ?? 'imported',
|
|
268
315
|
...((options.by ?? author) === undefined ? {} : { author: options.by ?? author }),
|
|
269
316
|
...(options.label === undefined ? {} : { label: options.label }),
|
|
270
|
-
});
|
|
317
|
+
}, claims);
|
|
318
|
+
}
|
|
319
|
+
async assertTrusted(bundle) {
|
|
320
|
+
if (!this.options.requireSignature)
|
|
321
|
+
return;
|
|
322
|
+
const verification = await this.verify(bundle);
|
|
323
|
+
if (!verification.trusted) {
|
|
324
|
+
throw new ContextSignatureError(bundle.name, bundle.version, bundle.signatures?.length
|
|
325
|
+
? 'no signature verifies against its content with a trusted key'
|
|
326
|
+
: 'it is not signed, and this hub requires a signature');
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
async check(bundle, content) {
|
|
330
|
+
const digest = await contextDigest(content);
|
|
331
|
+
const signature = this.options.keyring
|
|
332
|
+
? await verifiedBy(this.options.keyring, digest, bundle.signatures)
|
|
333
|
+
: undefined;
|
|
334
|
+
return { trusted: signature !== undefined, digest, ...(signature ? { signature } : {}) };
|
|
335
|
+
}
|
|
336
|
+
async signedContent(definition) {
|
|
337
|
+
const pins = Object.entries(definition.prompts ?? {});
|
|
338
|
+
if (pins.length > 0 && !this.options.prompts) {
|
|
339
|
+
throw new ContextDefinitionError(`Bundle "${definition.name}" pins prompts; signing or verifying it needs the hub to have a prompt registry`);
|
|
340
|
+
}
|
|
341
|
+
const prompts = [];
|
|
342
|
+
for (const [, pin] of pins)
|
|
343
|
+
prompts.push(await this.options.prompts.get(pin.name, pin.version));
|
|
344
|
+
return signedContentOf(definition, prompts);
|
|
271
345
|
}
|
|
272
346
|
async read(name, version) {
|
|
273
347
|
const stored = await this.store.getVersion(name, version);
|
|
@@ -304,6 +378,37 @@ function validate(definition) {
|
|
|
304
378
|
}
|
|
305
379
|
}
|
|
306
380
|
}
|
|
381
|
+
function signedContentOf(definition, prompts) {
|
|
382
|
+
const byPin = new Map(prompts.map((prompt) => [`${prompt.name}@${prompt.version}`, prompt]));
|
|
383
|
+
const pinned = {};
|
|
384
|
+
for (const [role, pin] of Object.entries(definition.prompts ?? {})) {
|
|
385
|
+
const prompt = byPin.get(`${pin.name}@${pin.version}`);
|
|
386
|
+
if (!prompt)
|
|
387
|
+
throw new ContextDefinitionError(`Bundle "${definition.name}" pins ${role} to ${pin.name}@${pin.version}, which is not at hand`);
|
|
388
|
+
pinned[role] = {
|
|
389
|
+
name: prompt.name,
|
|
390
|
+
messages: prompt.messages,
|
|
391
|
+
partials: prompt.partials,
|
|
392
|
+
config: prompt.config,
|
|
393
|
+
defaults: prompt.defaults,
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
return {
|
|
397
|
+
bundle: {
|
|
398
|
+
name: definition.name,
|
|
399
|
+
description: definition.description,
|
|
400
|
+
prompts: definition.prompts,
|
|
401
|
+
instructions: definition.instructions,
|
|
402
|
+
tools: definition.tools,
|
|
403
|
+
skills: definition.skills,
|
|
404
|
+
config: definition.config,
|
|
405
|
+
},
|
|
406
|
+
prompts: pinned,
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
function exportedPrompts(exported) {
|
|
410
|
+
return exported.prompts;
|
|
411
|
+
}
|
|
307
412
|
function toStored(bundle) {
|
|
308
413
|
return { ...bundle, messages: [], variables: [] };
|
|
309
414
|
}
|
|
@@ -4,8 +4,9 @@ import type { Dataset, DatasetExample, Evaluator, Experiment } from '../types/ev
|
|
|
4
4
|
import type { ToolDefinition } from '../types/messages.js';
|
|
5
5
|
import type { ContextBundle, ContextPromotionGate } from './hub.js';
|
|
6
6
|
export { type ContextChange, type ContextDiff, diffContexts, formatContextDiff } from './diff.js';
|
|
7
|
-
export { type ContextBundle, type ContextBundleDefinition, type ContextBundleExport, ContextConflictError, ContextDefinitionError, type ContextHistoryEntry, ContextHub, ContextHubError, type ContextHubOptions, type ContextLabel, ContextNotFoundError, type ContextPromotionContext, ContextPromotionError, type ContextPromotionGate, type ContextPromotionResult, type ContextPromptPin, type ContextReference, type ContextSkill, type ContextTool, contextVersion, } from './hub.js';
|
|
7
|
+
export { type ContextBundle, type ContextBundleDefinition, type ContextBundleExport, ContextConflictError, ContextDefinitionError, type ContextHistoryEntry, ContextHub, ContextHubError, type ContextHubOptions, type ContextLabel, ContextNotFoundError, type ContextPromotionContext, ContextPromotionError, type ContextPromotionGate, ContextSignatureError, type ContextVerification, type ContextPromotionResult, type ContextPromptPin, type ContextReference, type ContextSkill, type ContextTool, contextVersion, } from './hub.js';
|
|
8
8
|
export type { ExperimentGateOptions } from '../prompts/gates.js';
|
|
9
|
+
export { type ContextCryptoKey, type ContextJsonWebKey, type ContextKeyring, type ContextSignature, type ContextSignedContent, type ContextSigner, type ContextSigningKey, contextDigest, ed25519Keyring, ed25519Signer, generateContextKey, } from './signing.js';
|
|
9
10
|
/**
|
|
10
11
|
* A bundle's instructions joined into one system text, in the order the bundle lists them, or only
|
|
11
12
|
* the ones named in `include`, in that order.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { fingerprintOf } from '../evaluate/cache.js';
|
|
2
2
|
import { experimentVerdict } from '../prompts/gates.js';
|
|
3
3
|
export { diffContexts, formatContextDiff } from './diff.js';
|
|
4
|
-
export { ContextConflictError, ContextDefinitionError, ContextHub, ContextHubError, ContextNotFoundError, ContextPromotionError, contextVersion, } from './hub.js';
|
|
4
|
+
export { ContextConflictError, ContextDefinitionError, ContextHub, ContextHubError, ContextNotFoundError, ContextPromotionError, ContextSignatureError, contextVersion, } from './hub.js';
|
|
5
|
+
export { contextDigest, ed25519Keyring, ed25519Signer, generateContextKey, } from './signing.js';
|
|
5
6
|
export function contextInstructions(bundle, options = {}) {
|
|
6
7
|
const names = options.include ?? Object.keys(bundle.instructions ?? {});
|
|
7
8
|
return names
|