agent-first-data 0.16.0 → 0.16.1
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.
|
@@ -47,13 +47,7 @@
|
|
|
47
47
|
"type": "object",
|
|
48
48
|
"properties": {
|
|
49
49
|
"kind": {"const": "progress"},
|
|
50
|
-
"progress":
|
|
51
|
-
"type": "object",
|
|
52
|
-
"properties": {
|
|
53
|
-
"message": {"type": "string", "minLength": 1}
|
|
54
|
-
},
|
|
55
|
-
"additionalProperties": true
|
|
56
|
-
},
|
|
50
|
+
"progress": true,
|
|
57
51
|
"trace": {"$ref": "#/$defs/trace"}
|
|
58
52
|
},
|
|
59
53
|
"required": ["kind", "progress"],
|
|
@@ -63,18 +57,7 @@
|
|
|
63
57
|
"type": "object",
|
|
64
58
|
"properties": {
|
|
65
59
|
"kind": {"const": "log"},
|
|
66
|
-
"log":
|
|
67
|
-
"type": "object",
|
|
68
|
-
"properties": {
|
|
69
|
-
"message": {"type": "string", "minLength": 1},
|
|
70
|
-
"level": {"enum": ["debug", "info", "warn", "error"]},
|
|
71
|
-
"code": false
|
|
72
|
-
},
|
|
73
|
-
"not": {
|
|
74
|
-
"required": ["code"]
|
|
75
|
-
},
|
|
76
|
-
"additionalProperties": true
|
|
77
|
-
},
|
|
60
|
+
"log": true,
|
|
78
61
|
"trace": {"$ref": "#/$defs/trace"}
|
|
79
62
|
},
|
|
80
63
|
"required": ["kind", "log"],
|
|
@@ -258,7 +258,7 @@ Startup payload fields are tool-defined; `config` is recommended, while `version
|
|
|
258
258
|
|
|
259
259
|
All use `kind` plus the same-named payload and optional `trace`. Do not split protocol events across `stdout` and `stderr`.
|
|
260
260
|
|
|
261
|
-
Base validators enforce mandatory envelope/error/lifecycle rules. Strict validators additionally require object-valued `trace` on every event
|
|
261
|
+
Base validators enforce mandatory envelope/error/lifecycle rules. Strict validators additionally require object-valued `trace` on every event and `retryable` on every error. Log and progress payloads remain tool-defined in both profiles. Use strict validation before claiming compliance with all recommendations.
|
|
262
262
|
|
|
263
263
|
---
|
|
264
264
|
|
|
@@ -298,11 +298,11 @@ let span = info_span!("request", request_id = %uuid);
|
|
|
298
298
|
let _guard = span.enter();
|
|
299
299
|
```
|
|
300
300
|
|
|
301
|
-
For Go, Python, and TypeScript: emit span fields explicitly in each log
|
|
301
|
+
For Go, Python, and TypeScript: emit span fields explicitly in each tool-defined log payload.
|
|
302
302
|
|
|
303
303
|
### Output fields
|
|
304
304
|
|
|
305
|
-
|
|
305
|
+
Log payloads have no required or reserved fields. Traditional logging adapters commonly add `message` and `level` (debug/info/warn/error), plus span and event fields, but those names and meanings are adapter conventions rather than AFDATA protocol requirements. Projects that need timestamps add `timestamp_epoch_ms` explicitly.
|
|
306
306
|
|
|
307
307
|
Log redaction is **by field name** (the same `_secret`/`_url` rule as all output), applied when the line is emitted. Name the secret field — `info!(api_key_secret = %key)` — rather than logging a whole object by its `Debug`/string rendering, which hides the inner field names from redaction. For structured/nested secret-bearing data, build a value, apply redaction through output formatters or redacted_value(), then emit via the standard formatting helpers — do not pass the struct to a `?`/`%`-rendered log field.
|
|
308
308
|
|
package/dist/format.d.ts
CHANGED
|
@@ -54,30 +54,19 @@ export declare class JsonErrorBuilder {
|
|
|
54
54
|
build(): Event;
|
|
55
55
|
}
|
|
56
56
|
export declare class JsonProgressBuilder {
|
|
57
|
-
private readonly
|
|
58
|
-
private extensionFields;
|
|
57
|
+
private readonly payload;
|
|
59
58
|
private traceValue;
|
|
60
59
|
private issues;
|
|
61
|
-
constructor(
|
|
62
|
-
field(name: string, value: JsonValue): this;
|
|
63
|
-
fields(obj: unknown): this;
|
|
64
|
-
extend(obj: unknown): this;
|
|
60
|
+
constructor(payload: JsonValue);
|
|
65
61
|
trace(value: Record<string, JsonValue> | undefined): this;
|
|
66
|
-
private isReservedProgressField;
|
|
67
62
|
build(): Event;
|
|
68
63
|
}
|
|
69
64
|
export declare class JsonLogBuilder {
|
|
70
|
-
private readonly
|
|
71
|
-
private readonly message;
|
|
72
|
-
private extensionFields;
|
|
65
|
+
private readonly payload;
|
|
73
66
|
private traceValue;
|
|
74
67
|
private issues;
|
|
75
|
-
constructor(
|
|
76
|
-
field(name: string, value: JsonValue): this;
|
|
77
|
-
fields(obj: unknown): this;
|
|
78
|
-
extend(obj: unknown): this;
|
|
68
|
+
constructor(payload: JsonValue);
|
|
79
69
|
trace(value: Record<string, JsonValue> | undefined): this;
|
|
80
|
-
private isReservedLogField;
|
|
81
70
|
build(): Event;
|
|
82
71
|
}
|
|
83
72
|
/** Fluent builder for result events. */
|
|
@@ -85,9 +74,9 @@ export declare function jsonResult(payload: JsonValue): JsonResultBuilder;
|
|
|
85
74
|
/** Fluent builder for error events. */
|
|
86
75
|
export declare function jsonError(code: string, message: string): JsonErrorBuilder;
|
|
87
76
|
/** Fluent builder for progress events. */
|
|
88
|
-
export declare function jsonProgress(
|
|
77
|
+
export declare function jsonProgress(payload: JsonValue): JsonProgressBuilder;
|
|
89
78
|
/** Fluent builder for log events. */
|
|
90
|
-
export declare function jsonLog(
|
|
79
|
+
export declare function jsonLog(payload: JsonValue): JsonLogBuilder;
|
|
91
80
|
/** Validate one protocol event envelope. `strict` also enforces the recommended strict protocol profile (default true). */
|
|
92
81
|
export declare function validateProtocolEvent(event: unknown, strict?: boolean): void;
|
|
93
82
|
/** Validate finite CLI lifecycle: (log | progress)* -> exactly one terminal. `strict` also enforces the recommended strict protocol profile (default true). */
|
|
@@ -108,15 +97,12 @@ export type DecodedError = {
|
|
|
108
97
|
};
|
|
109
98
|
export type DecodedProgress = {
|
|
110
99
|
kind: "progress";
|
|
111
|
-
|
|
112
|
-
fields: Record<string, JsonValue>;
|
|
100
|
+
progress: JsonValue;
|
|
113
101
|
trace?: Record<string, JsonValue>;
|
|
114
102
|
};
|
|
115
103
|
export type DecodedLog = {
|
|
116
104
|
kind: "log";
|
|
117
|
-
|
|
118
|
-
message: string;
|
|
119
|
-
fields: Record<string, JsonValue>;
|
|
105
|
+
log: JsonValue;
|
|
120
106
|
trace?: Record<string, JsonValue>;
|
|
121
107
|
};
|
|
122
108
|
/** Discriminated union of decoded protocol events, narrow on `kind`. */
|
|
@@ -127,8 +113,7 @@ export declare class EventDecodeError extends Error {
|
|
|
127
113
|
}
|
|
128
114
|
/**
|
|
129
115
|
* Parse one protocol line (a single JSON text value), strict-validate it, and
|
|
130
|
-
* return a typed decoded event.
|
|
131
|
-
* the required ones, collected into `fields`.
|
|
116
|
+
* return a typed decoded event.
|
|
132
117
|
*/
|
|
133
118
|
export declare function decodeProtocolEvent(text: string): DecodedEvent;
|
|
134
119
|
export declare enum RedactionPolicy {
|
package/dist/format.js
CHANGED
|
@@ -176,53 +176,11 @@ export class JsonErrorBuilder {
|
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
178
|
export class JsonProgressBuilder {
|
|
179
|
-
|
|
180
|
-
extensionFields = {};
|
|
179
|
+
payload;
|
|
181
180
|
traceValue = {};
|
|
182
181
|
issues = [];
|
|
183
|
-
constructor(
|
|
184
|
-
this.
|
|
185
|
-
if (!message || message === "")
|
|
186
|
-
this.issues.push("message must be a non-empty string");
|
|
187
|
-
}
|
|
188
|
-
field(name, value) {
|
|
189
|
-
if (this.isReservedProgressField(name)) {
|
|
190
|
-
this.issues.push(`cannot write reserved progress field ${JSON.stringify(name)}`);
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
this.extensionFields[name] = value;
|
|
194
|
-
}
|
|
195
|
-
return this;
|
|
196
|
-
}
|
|
197
|
-
fields(obj) {
|
|
198
|
-
if (!isObject(obj)) {
|
|
199
|
-
this.issues.push("fields must be a JSON object");
|
|
200
|
-
return this;
|
|
201
|
-
}
|
|
202
|
-
for (const [key, val] of Object.entries(obj)) {
|
|
203
|
-
if (this.isReservedProgressField(key)) {
|
|
204
|
-
this.issues.push(`cannot write reserved progress field ${JSON.stringify(key)}`);
|
|
205
|
-
}
|
|
206
|
-
else {
|
|
207
|
-
this.extensionFields[key] = val;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
return this;
|
|
211
|
-
}
|
|
212
|
-
extend(obj) {
|
|
213
|
-
if (!isObject(obj)) {
|
|
214
|
-
this.issues.push("extend must be a JSON object");
|
|
215
|
-
return this;
|
|
216
|
-
}
|
|
217
|
-
for (const [key, val] of Object.entries(obj)) {
|
|
218
|
-
if (this.isReservedProgressField(key)) {
|
|
219
|
-
this.issues.push(`cannot write reserved progress field ${JSON.stringify(key)}`);
|
|
220
|
-
}
|
|
221
|
-
else {
|
|
222
|
-
this.extensionFields[key] = val;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
return this;
|
|
182
|
+
constructor(payload) {
|
|
183
|
+
this.payload = payload;
|
|
226
184
|
}
|
|
227
185
|
trace(value) {
|
|
228
186
|
if (value !== undefined) {
|
|
@@ -235,71 +193,20 @@ export class JsonProgressBuilder {
|
|
|
235
193
|
}
|
|
236
194
|
return this;
|
|
237
195
|
}
|
|
238
|
-
isReservedProgressField(name) {
|
|
239
|
-
return name === "message";
|
|
240
|
-
}
|
|
241
196
|
build() {
|
|
242
197
|
if (this.issues.length > 0) {
|
|
243
198
|
throw new EventBuildError(`Failed to build progress event: ${this.issues.join("; ")}`, this.issues);
|
|
244
199
|
}
|
|
245
|
-
const
|
|
246
|
-
progress.message = this.message;
|
|
247
|
-
const m = { kind: "progress", progress, trace: this.traceValue };
|
|
200
|
+
const m = { kind: "progress", progress: this.payload, trace: this.traceValue };
|
|
248
201
|
return new Event(m);
|
|
249
202
|
}
|
|
250
203
|
}
|
|
251
204
|
export class JsonLogBuilder {
|
|
252
|
-
|
|
253
|
-
message;
|
|
254
|
-
extensionFields = {};
|
|
205
|
+
payload;
|
|
255
206
|
traceValue = {};
|
|
256
207
|
issues = [];
|
|
257
|
-
constructor(
|
|
258
|
-
this.
|
|
259
|
-
this.message = message;
|
|
260
|
-
if (!message || message === "")
|
|
261
|
-
this.issues.push("message must be a non-empty string");
|
|
262
|
-
if (!isValidLogLevel(level))
|
|
263
|
-
this.issues.push(`level must be one of debug, info, warn, error`);
|
|
264
|
-
}
|
|
265
|
-
field(name, value) {
|
|
266
|
-
if (this.isReservedLogField(name)) {
|
|
267
|
-
this.issues.push(`cannot write reserved log field ${JSON.stringify(name)}`);
|
|
268
|
-
}
|
|
269
|
-
else {
|
|
270
|
-
this.extensionFields[name] = value;
|
|
271
|
-
}
|
|
272
|
-
return this;
|
|
273
|
-
}
|
|
274
|
-
fields(obj) {
|
|
275
|
-
if (!isObject(obj)) {
|
|
276
|
-
this.issues.push("fields must be a JSON object");
|
|
277
|
-
return this;
|
|
278
|
-
}
|
|
279
|
-
for (const [key, val] of Object.entries(obj)) {
|
|
280
|
-
if (this.isReservedLogField(key)) {
|
|
281
|
-
this.issues.push(`cannot write reserved log field ${JSON.stringify(key)}`);
|
|
282
|
-
}
|
|
283
|
-
else {
|
|
284
|
-
this.extensionFields[key] = val;
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
return this;
|
|
288
|
-
}
|
|
289
|
-
extend(obj) {
|
|
290
|
-
if (!isObject(obj)) {
|
|
291
|
-
this.issues.push("extend must be a JSON object");
|
|
292
|
-
return this;
|
|
293
|
-
}
|
|
294
|
-
for (const [key, val] of Object.entries(obj)) {
|
|
295
|
-
if (this.isReservedLogField(key)) {
|
|
296
|
-
this.issues.push(`cannot write reserved log field ${JSON.stringify(key)}`);
|
|
297
|
-
}
|
|
298
|
-
else {
|
|
299
|
-
this.extensionFields[key] = val;
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
return this;
|
|
208
|
+
constructor(payload) {
|
|
209
|
+
this.payload = payload;
|
|
303
210
|
}
|
|
304
211
|
trace(value) {
|
|
305
212
|
if (value !== undefined) {
|
|
@@ -312,17 +219,11 @@ export class JsonLogBuilder {
|
|
|
312
219
|
}
|
|
313
220
|
return this;
|
|
314
221
|
}
|
|
315
|
-
isReservedLogField(name) {
|
|
316
|
-
return name === "message" || name === "level" || name === "code";
|
|
317
|
-
}
|
|
318
222
|
build() {
|
|
319
223
|
if (this.issues.length > 0) {
|
|
320
224
|
throw new EventBuildError(`Failed to build log event: ${this.issues.join("; ")}`, this.issues);
|
|
321
225
|
}
|
|
322
|
-
const
|
|
323
|
-
log.level = this.level;
|
|
324
|
-
log.message = this.message;
|
|
325
|
-
const m = { kind: "log", log, trace: this.traceValue };
|
|
226
|
+
const m = { kind: "log", log: this.payload, trace: this.traceValue };
|
|
326
227
|
return new Event(m);
|
|
327
228
|
}
|
|
328
229
|
}
|
|
@@ -335,15 +236,12 @@ export function jsonError(code, message) {
|
|
|
335
236
|
return new JsonErrorBuilder(code, message);
|
|
336
237
|
}
|
|
337
238
|
/** Fluent builder for progress events. */
|
|
338
|
-
export function jsonProgress(
|
|
339
|
-
return new JsonProgressBuilder(
|
|
239
|
+
export function jsonProgress(payload) {
|
|
240
|
+
return new JsonProgressBuilder(payload);
|
|
340
241
|
}
|
|
341
242
|
/** Fluent builder for log events. */
|
|
342
|
-
export function jsonLog(
|
|
343
|
-
return new JsonLogBuilder(
|
|
344
|
-
}
|
|
345
|
-
function isValidLogLevel(level) {
|
|
346
|
-
return level === "debug" || level === "info" || level === "warn" || level === "error";
|
|
243
|
+
export function jsonLog(payload) {
|
|
244
|
+
return new JsonLogBuilder(payload);
|
|
347
245
|
}
|
|
348
246
|
/** Validate one protocol event envelope. `strict` also enforces the recommended strict protocol profile (default true). */
|
|
349
247
|
export function validateProtocolEvent(event, strict = true) {
|
|
@@ -372,10 +270,6 @@ export function validateProtocolEvent(event, strict = true) {
|
|
|
372
270
|
return;
|
|
373
271
|
if (!isObject(event.trace))
|
|
374
272
|
throw new Error("event.trace is required in strict mode");
|
|
375
|
-
if (kind === "log")
|
|
376
|
-
validateStrictLog(event.log);
|
|
377
|
-
if (kind === "progress")
|
|
378
|
-
validateStrictProgress(event.progress);
|
|
379
273
|
if (kind === "error")
|
|
380
274
|
validateStrictError(event.error);
|
|
381
275
|
}
|
|
@@ -418,25 +312,6 @@ export function validateProtocolStream(events, strict = true) {
|
|
|
418
312
|
throw new Error("event stream must contain exactly one terminal result or error");
|
|
419
313
|
}
|
|
420
314
|
}
|
|
421
|
-
function validateStrictLog(payload) {
|
|
422
|
-
if (!isObject(payload))
|
|
423
|
-
throw new Error("event.log must be a JSON object in strict mode");
|
|
424
|
-
// 0.16: log payload MUST NOT contain code field
|
|
425
|
-
if ("code" in payload) {
|
|
426
|
-
throw new Error("event.log.code is not allowed in strict mode");
|
|
427
|
-
}
|
|
428
|
-
if (typeof payload.message !== "string" || payload.message === "") {
|
|
429
|
-
throw new Error("event.log.message must be a non-empty string in strict mode");
|
|
430
|
-
}
|
|
431
|
-
if (!['debug', 'info', 'warn', 'error'].includes(payload.level)) {
|
|
432
|
-
throw new Error("event.log.level must be one of debug, info, warn, error in strict mode");
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
function validateStrictProgress(payload) {
|
|
436
|
-
if (!isObject(payload) || typeof payload.message !== "string" || payload.message === "") {
|
|
437
|
-
throw new Error("event.progress.message must be a non-empty string in strict mode");
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
315
|
function validateStrictError(error) {
|
|
441
316
|
if (!isObject(error))
|
|
442
317
|
throw new Error("event.error must be a JSON object in strict mode");
|
|
@@ -461,12 +336,9 @@ export class EventDecodeError extends Error {
|
|
|
461
336
|
}
|
|
462
337
|
}
|
|
463
338
|
const ERROR_RESERVED_FIELDS = new Set(["code", "message", "hint", "retryable"]);
|
|
464
|
-
const PROGRESS_RESERVED_FIELDS = new Set(["message"]);
|
|
465
|
-
const LOG_RESERVED_FIELDS = new Set(["level", "message"]);
|
|
466
339
|
/**
|
|
467
340
|
* Parse one protocol line (a single JSON text value), strict-validate it, and
|
|
468
|
-
* return a typed decoded event.
|
|
469
|
-
* the required ones, collected into `fields`.
|
|
341
|
+
* return a typed decoded event.
|
|
470
342
|
*/
|
|
471
343
|
export function decodeProtocolEvent(text) {
|
|
472
344
|
let parsed;
|
|
@@ -506,24 +378,10 @@ export function decodeProtocolEvent(text) {
|
|
|
506
378
|
decoded.hint = error.hint;
|
|
507
379
|
return decoded;
|
|
508
380
|
}
|
|
509
|
-
case "progress":
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
if (!PROGRESS_RESERVED_FIELDS.has(k))
|
|
514
|
-
fields[k] = v;
|
|
515
|
-
}
|
|
516
|
-
return { kind: "progress", message: progress.message, fields, trace };
|
|
517
|
-
}
|
|
518
|
-
case "log": {
|
|
519
|
-
const log = event.log;
|
|
520
|
-
const fields = {};
|
|
521
|
-
for (const [k, v] of Object.entries(log)) {
|
|
522
|
-
if (!LOG_RESERVED_FIELDS.has(k))
|
|
523
|
-
fields[k] = v;
|
|
524
|
-
}
|
|
525
|
-
return { kind: "log", level: log.level, message: log.message, fields, trace };
|
|
526
|
-
}
|
|
381
|
+
case "progress":
|
|
382
|
+
return { kind: "progress", progress: event.progress, trace };
|
|
383
|
+
case "log":
|
|
384
|
+
return { kind: "log", log: event.log, trace };
|
|
527
385
|
default:
|
|
528
386
|
// Unreachable: validateProtocolEvent already constrains event.kind.
|
|
529
387
|
throw new EventDecodeError(`unsupported event kind ${JSON.stringify(event.kind)}`);
|