@tangle-network/agent-interface 0.35.0 → 0.37.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/README.md +2 -2
- package/dist/agent-candidate-artifact-schema.d.ts +504 -0
- package/dist/agent-candidate-artifact-schema.js +16 -1
- package/dist/agent-candidate-outcome-schema.d.ts +26 -0
- package/dist/agent-candidate-outcome-schema.js +8 -1
- package/dist/agent-candidate-profile-schema.d.ts +336 -0
- package/dist/agent-candidate-promotion-schema.d.ts +2199 -20
- package/dist/agent-candidate-promotion-schema.js +24 -1
- package/dist/agent-candidate-receipt-schema.d.ts +6 -0
- package/dist/agent-candidate-schema-common.js +1 -1
- package/dist/agent-candidate-schema.d.ts +336 -0
- package/dist/agent-candidate.d.ts +40 -11
- package/dist/agent-execution-limits.d.ts +4 -0
- package/dist/agent-improvement-measurement-schema.d.ts +40 -7
- package/dist/agent-improvement-measurement-schema.js +55 -14
- package/dist/agent-improvement-source.d.ts +61 -3
- package/dist/agent-improvement-source.js +122 -8
- package/dist/agent-profile-improvement-schema.d.ts +133 -10
- package/dist/agent-profile-improvement-schema.js +33 -1
- package/dist/agent-profile-improvement.d.ts +6 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +3 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AgentProfile, AgentProfileFileMount, AgentProfileHookCommand, AgentProfileMode, AgentProfileModelHints, AgentProfileResources, AgentSubagentProfile, ReasoningEffort } from "./agent-profile.js";
|
|
2
2
|
import type { HarnessType } from "./harness.js";
|
|
3
|
-
import type { AgentProfileImprovementMeasuredComparison } from "./agent-profile-improvement.js";
|
|
3
|
+
import type { AgentProfileImprovementExecutionRef, AgentProfileImprovementMeasuredComparison } from "./agent-profile-improvement.js";
|
|
4
|
+
import type { AgentImprovementSource } from "./agent-improvement-source.js";
|
|
4
5
|
/** Full SHA-256 digest with an explicit algorithm prefix. */
|
|
5
6
|
export type Sha256Digest = `sha256:${string}`;
|
|
6
7
|
/** RFC 8785 JSON Canonicalization Scheme followed by SHA-256. */
|
|
@@ -55,6 +56,8 @@ export interface AgentCandidateInlineResource {
|
|
|
55
56
|
content: string;
|
|
56
57
|
sha256: Sha256Digest;
|
|
57
58
|
byteLength: number;
|
|
59
|
+
/** Optional immutable origin, license obligations, and import history. */
|
|
60
|
+
source?: AgentImprovementSource;
|
|
58
61
|
}
|
|
59
62
|
/** GitHub content pinned to a full Git object id and expected content digest. */
|
|
60
63
|
export interface AgentCandidateGitHubResource {
|
|
@@ -65,6 +68,8 @@ export interface AgentCandidateGitHubResource {
|
|
|
65
68
|
name?: string;
|
|
66
69
|
sha256: Sha256Digest;
|
|
67
70
|
byteLength: number;
|
|
71
|
+
/** Optional immutable origin, license obligations, and import history. */
|
|
72
|
+
source?: AgentImprovementSource;
|
|
68
73
|
}
|
|
69
74
|
export type AgentCandidateResourceRef = AgentCandidateInlineResource | AgentCandidateGitHubResource;
|
|
70
75
|
export interface AgentCandidateFileMount extends Omit<AgentProfileFileMount, "resource"> {
|
|
@@ -235,6 +240,33 @@ export type AgentCandidateMemoryPolicy = {
|
|
|
235
240
|
scope: "task";
|
|
236
241
|
seed?: AgentCandidateArtifactRef;
|
|
237
242
|
};
|
|
243
|
+
/** Whether a settled cost came from provider billing or a reproducible estimate. */
|
|
244
|
+
export type AgentCandidateCostProvenance = "observed" | "estimated";
|
|
245
|
+
/** One known dollar amount carried with its source. */
|
|
246
|
+
export interface AgentImprovementCost {
|
|
247
|
+
usd: number;
|
|
248
|
+
provenance: AgentCandidateCostProvenance;
|
|
249
|
+
}
|
|
250
|
+
/** Complete accounting for a measured improvement proposal. */
|
|
251
|
+
export interface AgentImprovementEvaluationAccounting {
|
|
252
|
+
generationsExplored: number;
|
|
253
|
+
/** Trace analysis and candidate search before held-out execution. */
|
|
254
|
+
preparation: {
|
|
255
|
+
wallDurationMs: number;
|
|
256
|
+
cost: AgentImprovementCost;
|
|
257
|
+
};
|
|
258
|
+
/** Held-out baseline/candidate execution. Work time sums parallel calls. */
|
|
259
|
+
measurement: {
|
|
260
|
+
wallDurationMs: number;
|
|
261
|
+
workDurationMs: number;
|
|
262
|
+
cost: AgentImprovementCost;
|
|
263
|
+
};
|
|
264
|
+
/** Wall time is preparation plus held-out measurement. */
|
|
265
|
+
total: {
|
|
266
|
+
wallDurationMs: number;
|
|
267
|
+
cost: AgentImprovementCost;
|
|
268
|
+
};
|
|
269
|
+
}
|
|
238
270
|
/** Lossless evaluator-owned usage totals for one candidate execution. */
|
|
239
271
|
export interface AgentCandidateFixedSpend {
|
|
240
272
|
inputTokens: number;
|
|
@@ -244,6 +276,7 @@ export interface AgentCandidateFixedSpend {
|
|
|
244
276
|
modelCalls: number;
|
|
245
277
|
/** Integer billionths of one US dollar. */
|
|
246
278
|
costUsdNanos: number;
|
|
279
|
+
costProvenance: AgentCandidateCostProvenance;
|
|
247
280
|
}
|
|
248
281
|
/** Evidence and ancestry that produced the immutable candidate. */
|
|
249
282
|
export interface AgentCandidateLineage {
|
|
@@ -350,13 +383,14 @@ export type AgentCandidateEffectiveMemory = {
|
|
|
350
383
|
beforeState: AgentCandidateWorkspaceSnapshotEvidence;
|
|
351
384
|
seedDigest?: Sha256Digest;
|
|
352
385
|
};
|
|
353
|
-
/** The exact evaluator-owned limits applied to every candidate arm. */
|
|
386
|
+
/** The exact evaluator-owned limits applied to every complete candidate arm. */
|
|
354
387
|
export interface AgentCandidateExecutionLimits {
|
|
355
388
|
timeoutMs: number;
|
|
356
389
|
maxSteps: number;
|
|
357
390
|
maxModelCalls: number;
|
|
358
391
|
maxInputTokens: number;
|
|
359
392
|
maxOutputTokens: number;
|
|
393
|
+
/** Total agent plus grading spend for one complete arm. */
|
|
360
394
|
maxCostUsd: number;
|
|
361
395
|
}
|
|
362
396
|
/** Counted attempt identity and the only retry class allowed by the evaluator. */
|
|
@@ -765,15 +799,7 @@ export interface AgentImprovementMeasuredComparisonBase<TExperiment, TMeasuremen
|
|
|
765
799
|
candidateContentHash: string;
|
|
766
800
|
};
|
|
767
801
|
diff: string;
|
|
768
|
-
evaluation:
|
|
769
|
-
generationsExplored: number;
|
|
770
|
-
searchDurationMs: number;
|
|
771
|
-
executionDurationMs: number;
|
|
772
|
-
durationMs: number;
|
|
773
|
-
searchCostUsd: number;
|
|
774
|
-
executionCostUsd: number;
|
|
775
|
-
totalCostUsd: number;
|
|
776
|
-
};
|
|
802
|
+
evaluation: AgentImprovementEvaluationAccounting;
|
|
777
803
|
metadata?: {
|
|
778
804
|
[key: string]: AgentCandidateJsonValue;
|
|
779
805
|
};
|
|
@@ -822,6 +848,8 @@ export interface AgentImprovementActivation {
|
|
|
822
848
|
experimentDigest: Sha256Digest;
|
|
823
849
|
/** Exact proposed state, whether it is a sealed bundle or a normal profile. */
|
|
824
850
|
candidateDigest: Sha256Digest;
|
|
851
|
+
/** Required when a target uses `agent-profile`; the schema enforces this condition. */
|
|
852
|
+
executionRef?: AgentProfileImprovementExecutionRef;
|
|
825
853
|
intent: AgentImprovementActivationIntent;
|
|
826
854
|
targets: [AgentImprovementActivationTarget, ...AgentImprovementActivationTarget[]];
|
|
827
855
|
fundingOwner: string;
|
|
@@ -895,6 +923,7 @@ export interface AgentCandidateModelSettlementCall {
|
|
|
895
923
|
cachedInputTokens: number;
|
|
896
924
|
reasoningTokens: number;
|
|
897
925
|
costUsdNanos: number;
|
|
926
|
+
costProvenance: AgentCandidateCostProvenance;
|
|
898
927
|
}
|
|
899
928
|
/** Canonical model-access ledger after the evaluator has revoked access. */
|
|
900
929
|
export interface AgentCandidateModelSettlementMaterial {
|
|
@@ -16,6 +16,10 @@ export declare const agentExecutionLimitObservationSchema: z.ZodObject<{
|
|
|
16
16
|
reasoningTokens: z.ZodNumber;
|
|
17
17
|
modelCalls: z.ZodNumber;
|
|
18
18
|
costUsdNanos: z.ZodNumber;
|
|
19
|
+
costProvenance: z.ZodEnum<{
|
|
20
|
+
observed: "observed";
|
|
21
|
+
estimated: "estimated";
|
|
22
|
+
}>;
|
|
19
23
|
}, z.core.$strict>;
|
|
20
24
|
}, z.core.$strict>;
|
|
21
25
|
export interface RefineAgentExecutionWithinLimitsOptions {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import type { AgentCandidateEvaluationPolicy, AgentCandidateJsonValue, AgentImprovementMeasuredComparisonBase } from "./agent-candidate.js";
|
|
2
|
+
import type { AgentCandidateCostProvenance, AgentCandidateEvaluationPolicy, AgentCandidateJsonValue, AgentImprovementMeasuredComparisonBase } from "./agent-candidate.js";
|
|
3
3
|
export declare const canonicalJsonSchema: z.ZodCustom<AgentCandidateJsonValue, AgentCandidateJsonValue>;
|
|
4
4
|
export declare const canonicalJsonObjectSchema: z.ZodRecord<z.ZodString, z.ZodCustom<AgentCandidateJsonValue, AgentCandidateJsonValue>>;
|
|
5
5
|
export declare const agentCandidateEvaluationPolicySchema: z.ZodObject<{
|
|
@@ -12,6 +12,13 @@ export declare const agentCandidateEvaluationPolicySchema: z.ZodObject<{
|
|
|
12
12
|
criticalDimensions: z.ZodArray<z.ZodString>;
|
|
13
13
|
regressionTolerance: z.ZodNumber;
|
|
14
14
|
}, z.core.$strict>;
|
|
15
|
+
export declare const agentImprovementCostSchema: z.ZodObject<{
|
|
16
|
+
usd: z.ZodNumber;
|
|
17
|
+
provenance: z.ZodEnum<{
|
|
18
|
+
observed: "observed";
|
|
19
|
+
estimated: "estimated";
|
|
20
|
+
}>;
|
|
21
|
+
}, z.core.$strict>;
|
|
15
22
|
export declare const measuredComparisonCommonShape: {
|
|
16
23
|
overall: z.ZodObject<{
|
|
17
24
|
direction: z.ZodLiteral<"higher-is-better">;
|
|
@@ -157,12 +164,37 @@ export declare const measuredComparisonCommonShape: {
|
|
|
157
164
|
diff: z.ZodString;
|
|
158
165
|
evaluation: z.ZodObject<{
|
|
159
166
|
generationsExplored: z.ZodNumber;
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
167
|
+
preparation: z.ZodObject<{
|
|
168
|
+
wallDurationMs: z.ZodNumber;
|
|
169
|
+
cost: z.ZodObject<{
|
|
170
|
+
usd: z.ZodNumber;
|
|
171
|
+
provenance: z.ZodEnum<{
|
|
172
|
+
observed: "observed";
|
|
173
|
+
estimated: "estimated";
|
|
174
|
+
}>;
|
|
175
|
+
}, z.core.$strict>;
|
|
176
|
+
}, z.core.$strict>;
|
|
177
|
+
measurement: z.ZodObject<{
|
|
178
|
+
wallDurationMs: z.ZodNumber;
|
|
179
|
+
workDurationMs: z.ZodNumber;
|
|
180
|
+
cost: z.ZodObject<{
|
|
181
|
+
usd: z.ZodNumber;
|
|
182
|
+
provenance: z.ZodEnum<{
|
|
183
|
+
observed: "observed";
|
|
184
|
+
estimated: "estimated";
|
|
185
|
+
}>;
|
|
186
|
+
}, z.core.$strict>;
|
|
187
|
+
}, z.core.$strict>;
|
|
188
|
+
total: z.ZodObject<{
|
|
189
|
+
wallDurationMs: z.ZodNumber;
|
|
190
|
+
cost: z.ZodObject<{
|
|
191
|
+
usd: z.ZodNumber;
|
|
192
|
+
provenance: z.ZodEnum<{
|
|
193
|
+
observed: "observed";
|
|
194
|
+
estimated: "estimated";
|
|
195
|
+
}>;
|
|
196
|
+
}, z.core.$strict>;
|
|
197
|
+
}, z.core.$strict>;
|
|
166
198
|
}, z.core.$strict>;
|
|
167
199
|
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodCustom<AgentCandidateJsonValue, AgentCandidateJsonValue>>>;
|
|
168
200
|
};
|
|
@@ -184,6 +216,7 @@ export declare function refineMeasuredComparisonSummary<TReceipt>(comparison: Me
|
|
|
184
216
|
score(receipt: TReceipt): number;
|
|
185
217
|
dimension(receipt: TReceipt, name: string): number | undefined;
|
|
186
218
|
cost(receipt: TReceipt): number;
|
|
219
|
+
costProvenance(receipt: TReceipt): AgentCandidateCostProvenance;
|
|
187
220
|
latency(receipt: TReceipt): number;
|
|
188
221
|
}, ctx: z.RefinementCtx): void;
|
|
189
222
|
export declare function refineEstimate(estimate: {
|
|
@@ -95,6 +95,36 @@ export const agentCandidateEvaluationPolicySchema = z
|
|
|
95
95
|
});
|
|
96
96
|
}
|
|
97
97
|
});
|
|
98
|
+
export const agentImprovementCostSchema = z
|
|
99
|
+
.object({
|
|
100
|
+
usd: z.number().finite().nonnegative(),
|
|
101
|
+
provenance: z.enum(["observed", "estimated"]),
|
|
102
|
+
})
|
|
103
|
+
.strict();
|
|
104
|
+
const agentImprovementEvaluationSchema = z
|
|
105
|
+
.object({
|
|
106
|
+
generationsExplored: z.number().int().nonnegative(),
|
|
107
|
+
preparation: z
|
|
108
|
+
.object({
|
|
109
|
+
wallDurationMs: z.number().finite().nonnegative(),
|
|
110
|
+
cost: agentImprovementCostSchema,
|
|
111
|
+
})
|
|
112
|
+
.strict(),
|
|
113
|
+
measurement: z
|
|
114
|
+
.object({
|
|
115
|
+
wallDurationMs: z.number().finite().nonnegative(),
|
|
116
|
+
workDurationMs: z.number().finite().nonnegative(),
|
|
117
|
+
cost: agentImprovementCostSchema,
|
|
118
|
+
})
|
|
119
|
+
.strict(),
|
|
120
|
+
total: z
|
|
121
|
+
.object({
|
|
122
|
+
wallDurationMs: z.number().finite().nonnegative(),
|
|
123
|
+
cost: agentImprovementCostSchema,
|
|
124
|
+
})
|
|
125
|
+
.strict(),
|
|
126
|
+
})
|
|
127
|
+
.strict();
|
|
98
128
|
export const measuredComparisonCommonShape = {
|
|
99
129
|
overall: z
|
|
100
130
|
.object({
|
|
@@ -148,17 +178,7 @@ export const measuredComparisonCommonShape = {
|
|
|
148
178
|
})
|
|
149
179
|
.strict(),
|
|
150
180
|
diff: z.string(),
|
|
151
|
-
evaluation:
|
|
152
|
-
.object({
|
|
153
|
-
generationsExplored: z.number().int().nonnegative(),
|
|
154
|
-
searchDurationMs: z.number().finite().nonnegative(),
|
|
155
|
-
executionDurationMs: z.number().finite().nonnegative(),
|
|
156
|
-
durationMs: z.number().finite().nonnegative(),
|
|
157
|
-
searchCostUsd: z.number().finite().nonnegative(),
|
|
158
|
-
executionCostUsd: z.number().finite().nonnegative(),
|
|
159
|
-
totalCostUsd: z.number().finite().nonnegative(),
|
|
160
|
-
})
|
|
161
|
-
.strict(),
|
|
181
|
+
evaluation: agentImprovementEvaluationSchema,
|
|
162
182
|
metadata: canonicalJsonObjectSchema.optional(),
|
|
163
183
|
};
|
|
164
184
|
/** Keep receipt identity reuse rules identical across measured source formats. */
|
|
@@ -181,12 +201,18 @@ export function createMeasuredComparisonIdentityRegistry(options) {
|
|
|
181
201
|
}
|
|
182
202
|
export function refineMeasuredComparisonSummary(comparison, policy, expectedN, measurements, values, ctx) {
|
|
183
203
|
refineEstimate(comparison.overall, ["overall"], ctx);
|
|
184
|
-
|
|
185
|
-
|
|
204
|
+
const totalCostProvenance = comparison.evaluation.preparation.cost.provenance === "observed" &&
|
|
205
|
+
comparison.evaluation.measurement.cost.provenance === "observed"
|
|
206
|
+
? "observed"
|
|
207
|
+
: "estimated";
|
|
208
|
+
if (!numbersApproximatelyEqual(comparison.evaluation.total.wallDurationMs, comparison.evaluation.preparation.wallDurationMs +
|
|
209
|
+
comparison.evaluation.measurement.wallDurationMs) ||
|
|
210
|
+
!numbersApproximatelyEqual(comparison.evaluation.total.cost.usd, comparison.evaluation.preparation.cost.usd + comparison.evaluation.measurement.cost.usd) ||
|
|
211
|
+
comparison.evaluation.total.cost.provenance !== totalCostProvenance) {
|
|
186
212
|
ctx.addIssue({
|
|
187
213
|
code: "custom",
|
|
188
214
|
path: ["evaluation"],
|
|
189
|
-
message: "evaluation totals must equal
|
|
215
|
+
message: "evaluation totals must equal preparation and measurement accounting",
|
|
190
216
|
});
|
|
191
217
|
}
|
|
192
218
|
if (comparison.overall.n !== expectedN) {
|
|
@@ -265,6 +291,21 @@ export function refineMeasuredComparisonSummary(comparison, policy, expectedN, m
|
|
|
265
291
|
latencyCount += 1;
|
|
266
292
|
}
|
|
267
293
|
}
|
|
294
|
+
const measurementCostUsd = measurements.reduce((sum, measurement) => sum + values.cost(measurement.baseline) + values.cost(measurement.candidate), 0);
|
|
295
|
+
const measurementWorkDurationMs = measurements.reduce((sum, measurement) => sum + values.latency(measurement.baseline) + values.latency(measurement.candidate), 0);
|
|
296
|
+
const measurementCostProvenance = measurements.every((measurement) => values.costProvenance(measurement.baseline) === "observed" &&
|
|
297
|
+
values.costProvenance(measurement.candidate) === "observed")
|
|
298
|
+
? "observed"
|
|
299
|
+
: "estimated";
|
|
300
|
+
if (!numbersApproximatelyEqual(comparison.evaluation.measurement.cost.usd, measurementCostUsd) ||
|
|
301
|
+
comparison.evaluation.measurement.cost.provenance !== measurementCostProvenance ||
|
|
302
|
+
!numbersApproximatelyEqual(comparison.evaluation.measurement.workDurationMs, measurementWorkDurationMs)) {
|
|
303
|
+
ctx.addIssue({
|
|
304
|
+
code: "custom",
|
|
305
|
+
path: ["evaluation", "measurement"],
|
|
306
|
+
message: "measurement accounting must equal the complete signed receipts",
|
|
307
|
+
});
|
|
308
|
+
}
|
|
268
309
|
if (costCount !== 1 || latencyCount !== 1) {
|
|
269
310
|
ctx.addIssue({
|
|
270
311
|
code: "custom",
|
|
@@ -2,19 +2,77 @@ import { z } from "zod";
|
|
|
2
2
|
import type { AgentCandidateJsonValue } from "./agent-candidate.js";
|
|
3
3
|
/** Metadata key that binds a measured improvement to its exact external source. */
|
|
4
4
|
export declare const AGENT_IMPROVEMENT_SOURCE_METADATA_KEY = "agentImprovementSource";
|
|
5
|
+
/** License terms retained with an imported source. */
|
|
6
|
+
export declare const agentSourceLicenseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
7
|
+
kind: z.ZodLiteral<"spdx">;
|
|
8
|
+
expression: z.ZodString;
|
|
9
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
10
|
+
kind: z.ZodLiteral<"custom">;
|
|
11
|
+
name: z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>, z.ZodString>;
|
|
12
|
+
reference: z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>, z.ZodString>;
|
|
13
|
+
termsDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
14
|
+
}, z.core.$strict>], "kind">;
|
|
15
|
+
export type AgentSourceLicense = z.infer<typeof agentSourceLicenseSchema>;
|
|
16
|
+
/**
|
|
17
|
+
* One content transition applied while importing a source.
|
|
18
|
+
*
|
|
19
|
+
* `identity` and `revision` pin the transformer. Input/output digests make the
|
|
20
|
+
* ordered chain auditable without embedding executable transformation code.
|
|
21
|
+
* `procedureDigest` pins the implementation and non-secret configuration used
|
|
22
|
+
* for that step.
|
|
23
|
+
*/
|
|
24
|
+
export declare const agentSourceTransformationSchema: z.ZodObject<{
|
|
25
|
+
kind: z.ZodEnum<{
|
|
26
|
+
normalization: "normalization";
|
|
27
|
+
transformation: "transformation";
|
|
28
|
+
}>;
|
|
29
|
+
identity: z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>, z.ZodString>;
|
|
30
|
+
revision: z.ZodUnion<readonly [z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>, z.ZodString>, z.ZodNumber]>;
|
|
31
|
+
procedureDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
32
|
+
inputDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
33
|
+
outputDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
34
|
+
}, z.core.$strict>;
|
|
35
|
+
export type AgentSourceTransformation = z.infer<typeof agentSourceTransformationSchema>;
|
|
5
36
|
/**
|
|
6
37
|
* Stable reference for the state from which an improvement candidate was made.
|
|
7
38
|
* `sourceIdentity` identifies the provider object; `sourceDigest` is the exact
|
|
8
|
-
* measured source state; `sourceRevision` is an
|
|
39
|
+
* measured source state consumed by the candidate; `sourceRevision` is an
|
|
9
40
|
* opaque provider version retained to make stale-source errors intelligible to
|
|
10
41
|
* callers. A revision may be numeric or textual because providers use both
|
|
11
42
|
* counters and immutable revision identifiers.
|
|
43
|
+
*
|
|
44
|
+
* Optional license, attribution, and notice fields preserve obligations when a
|
|
45
|
+
* public source becomes an improvement input. When transformations are
|
|
46
|
+
* present, their first input pins the fetched source bytes, every adjacent
|
|
47
|
+
* digest must join, and the final output must equal `sourceDigest`.
|
|
12
48
|
*/
|
|
13
49
|
export declare const agentImprovementSourceSchema: z.ZodObject<{
|
|
14
50
|
kind: z.ZodString;
|
|
15
|
-
sourceIdentity: z.ZodString
|
|
51
|
+
sourceIdentity: z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>, z.ZodString>;
|
|
16
52
|
sourceDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
17
|
-
sourceRevision: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
|
|
53
|
+
sourceRevision: z.ZodUnion<readonly [z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>, z.ZodString>, z.ZodNumber]>;
|
|
54
|
+
license: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
55
|
+
kind: z.ZodLiteral<"spdx">;
|
|
56
|
+
expression: z.ZodString;
|
|
57
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
58
|
+
kind: z.ZodLiteral<"custom">;
|
|
59
|
+
name: z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>, z.ZodString>;
|
|
60
|
+
reference: z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>, z.ZodString>;
|
|
61
|
+
termsDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
62
|
+
}, z.core.$strict>], "kind">>;
|
|
63
|
+
attribution: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
64
|
+
notices: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
65
|
+
transformations: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
66
|
+
kind: z.ZodEnum<{
|
|
67
|
+
normalization: "normalization";
|
|
68
|
+
transformation: "transformation";
|
|
69
|
+
}>;
|
|
70
|
+
identity: z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>, z.ZodString>;
|
|
71
|
+
revision: z.ZodUnion<readonly [z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>, z.ZodString>, z.ZodNumber]>;
|
|
72
|
+
procedureDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
73
|
+
inputDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
74
|
+
outputDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
75
|
+
}, z.core.$strict>>>;
|
|
18
76
|
}, z.core.$strict>;
|
|
19
77
|
export type AgentImprovementSource = z.infer<typeof agentImprovementSourceSchema>;
|
|
20
78
|
/** Attach one validated source reference to signed improvement metadata. */
|
|
@@ -1,26 +1,140 @@
|
|
|
1
|
+
import parseSpdxExpression from "spdx-expression-parse";
|
|
1
2
|
import { z } from "zod";
|
|
2
|
-
import { sha256DigestSchema } from "./agent-candidate-schema-common.js";
|
|
3
|
+
import { isWellFormedUnicode, looksLikeCredential, sha256DigestSchema, } from "./agent-candidate-schema-common.js";
|
|
3
4
|
/** Metadata key that binds a measured improvement to its exact external source. */
|
|
4
5
|
export const AGENT_IMPROVEMENT_SOURCE_METADATA_KEY = "agentImprovementSource";
|
|
6
|
+
function publicSourceTextSchema(maxLength, label) {
|
|
7
|
+
return z
|
|
8
|
+
.string()
|
|
9
|
+
.max(maxLength)
|
|
10
|
+
.refine(isWellFormedUnicode, `${label} must be well-formed Unicode`)
|
|
11
|
+
.refine((value) => !looksLikeCredential(value), `${label} cannot carry credentials`);
|
|
12
|
+
}
|
|
13
|
+
const sourceIdentitySchema = publicSourceTextSchema(256, "source identity")
|
|
14
|
+
.transform((value) => value.trim())
|
|
15
|
+
.pipe(z.string().min(1, "source identity cannot be blank"));
|
|
16
|
+
const sourceRevisionSchema = z.union([
|
|
17
|
+
publicSourceTextSchema(256, "source revision")
|
|
18
|
+
.transform((value) => value.trim())
|
|
19
|
+
.pipe(z.string().min(1, "source revision cannot be blank")),
|
|
20
|
+
z.number().int().nonnegative(),
|
|
21
|
+
]);
|
|
22
|
+
const sourceStatementSchema = publicSourceTextSchema(16_384, "source statement").refine((value) => value.trim().length > 0, "statement cannot be blank");
|
|
23
|
+
const sourceStatementListSchema = z
|
|
24
|
+
.array(sourceStatementSchema)
|
|
25
|
+
.min(1)
|
|
26
|
+
.max(128)
|
|
27
|
+
.refine((values) => new Set(values).size === values.length, "statements must be unique");
|
|
28
|
+
function containsCustomLicenseReference(expression) {
|
|
29
|
+
if ("license" in expression) {
|
|
30
|
+
return (expression.license.startsWith("LicenseRef-") ||
|
|
31
|
+
expression.license.includes(":LicenseRef-"));
|
|
32
|
+
}
|
|
33
|
+
return (containsCustomLicenseReference(expression.left) ||
|
|
34
|
+
containsCustomLicenseReference(expression.right));
|
|
35
|
+
}
|
|
36
|
+
/** License terms retained with an imported source. */
|
|
37
|
+
export const agentSourceLicenseSchema = z.discriminatedUnion("kind", [
|
|
38
|
+
z
|
|
39
|
+
.object({
|
|
40
|
+
kind: z.literal("spdx"),
|
|
41
|
+
expression: z
|
|
42
|
+
.string()
|
|
43
|
+
.trim()
|
|
44
|
+
.min(1)
|
|
45
|
+
.max(1_024)
|
|
46
|
+
.refine((expression) => {
|
|
47
|
+
try {
|
|
48
|
+
return !containsCustomLicenseReference(parseSpdxExpression(expression));
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}, "license expression must use standard SPDX identifiers; content-pin custom terms with kind=custom"),
|
|
54
|
+
})
|
|
55
|
+
.strict(),
|
|
56
|
+
z
|
|
57
|
+
.object({
|
|
58
|
+
kind: z.literal("custom"),
|
|
59
|
+
name: sourceIdentitySchema,
|
|
60
|
+
/** URL or repository-relative path from which the exact terms can be recovered. */
|
|
61
|
+
reference: publicSourceTextSchema(2_048, "license reference")
|
|
62
|
+
.transform((value) => value.trim())
|
|
63
|
+
.pipe(z.string().min(1, "license reference cannot be blank")),
|
|
64
|
+
/** Digest of the custom license text, not of its URL or file name. */
|
|
65
|
+
termsDigest: sha256DigestSchema,
|
|
66
|
+
})
|
|
67
|
+
.strict(),
|
|
68
|
+
]);
|
|
69
|
+
/**
|
|
70
|
+
* One content transition applied while importing a source.
|
|
71
|
+
*
|
|
72
|
+
* `identity` and `revision` pin the transformer. Input/output digests make the
|
|
73
|
+
* ordered chain auditable without embedding executable transformation code.
|
|
74
|
+
* `procedureDigest` pins the implementation and non-secret configuration used
|
|
75
|
+
* for that step.
|
|
76
|
+
*/
|
|
77
|
+
export const agentSourceTransformationSchema = z
|
|
78
|
+
.object({
|
|
79
|
+
kind: z.enum(["normalization", "transformation"]),
|
|
80
|
+
identity: sourceIdentitySchema,
|
|
81
|
+
revision: sourceRevisionSchema,
|
|
82
|
+
procedureDigest: sha256DigestSchema,
|
|
83
|
+
inputDigest: sha256DigestSchema,
|
|
84
|
+
outputDigest: sha256DigestSchema,
|
|
85
|
+
})
|
|
86
|
+
.strict();
|
|
5
87
|
/**
|
|
6
88
|
* Stable reference for the state from which an improvement candidate was made.
|
|
7
89
|
* `sourceIdentity` identifies the provider object; `sourceDigest` is the exact
|
|
8
|
-
* measured source state; `sourceRevision` is an
|
|
90
|
+
* measured source state consumed by the candidate; `sourceRevision` is an
|
|
9
91
|
* opaque provider version retained to make stale-source errors intelligible to
|
|
10
92
|
* callers. A revision may be numeric or textual because providers use both
|
|
11
93
|
* counters and immutable revision identifiers.
|
|
94
|
+
*
|
|
95
|
+
* Optional license, attribution, and notice fields preserve obligations when a
|
|
96
|
+
* public source becomes an improvement input. When transformations are
|
|
97
|
+
* present, their first input pins the fetched source bytes, every adjacent
|
|
98
|
+
* digest must join, and the final output must equal `sourceDigest`.
|
|
12
99
|
*/
|
|
13
100
|
export const agentImprovementSourceSchema = z
|
|
14
101
|
.object({
|
|
15
102
|
kind: z.string().trim().min(1).max(100).regex(/^[a-z][a-z0-9-]*$/),
|
|
16
|
-
sourceIdentity:
|
|
103
|
+
sourceIdentity: sourceIdentitySchema,
|
|
17
104
|
sourceDigest: sha256DigestSchema,
|
|
18
|
-
sourceRevision:
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
105
|
+
sourceRevision: sourceRevisionSchema,
|
|
106
|
+
license: agentSourceLicenseSchema.optional(),
|
|
107
|
+
attribution: sourceStatementListSchema.optional(),
|
|
108
|
+
notices: sourceStatementListSchema.optional(),
|
|
109
|
+
transformations: z
|
|
110
|
+
.array(agentSourceTransformationSchema)
|
|
111
|
+
.min(1)
|
|
112
|
+
.max(128)
|
|
113
|
+
.optional(),
|
|
22
114
|
})
|
|
23
|
-
.strict()
|
|
115
|
+
.strict()
|
|
116
|
+
.superRefine((source, ctx) => {
|
|
117
|
+
const transformations = source.transformations;
|
|
118
|
+
if (transformations === undefined)
|
|
119
|
+
return;
|
|
120
|
+
for (let index = 1; index < transformations.length; index++) {
|
|
121
|
+
if (transformations[index]?.inputDigest !==
|
|
122
|
+
transformations[index - 1]?.outputDigest) {
|
|
123
|
+
ctx.addIssue({
|
|
124
|
+
code: "custom",
|
|
125
|
+
path: ["transformations", index, "inputDigest"],
|
|
126
|
+
message: "transformation input must equal the previous output",
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (transformations.at(-1)?.outputDigest !== source.sourceDigest) {
|
|
131
|
+
ctx.addIssue({
|
|
132
|
+
code: "custom",
|
|
133
|
+
path: ["sourceDigest"],
|
|
134
|
+
message: "source digest must equal the final transformation output",
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
});
|
|
24
138
|
/** Attach one validated source reference to signed improvement metadata. */
|
|
25
139
|
export function agentImprovementSourceMetadata(source) {
|
|
26
140
|
return {
|