agent-first-data 0.8.0 → 0.9.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 CHANGED
@@ -63,7 +63,7 @@ Plain: args.input_path=/data/backup.tar.gz code=log event=startup config.max_fil
63
63
 
64
64
  ## API Reference
65
65
 
66
- Total: **15 public APIs and 2 types** + **AFDATA logging** (3 protocol builders + 2 redacted value helpers + 4 output functions + 1 internal + 1 utility + 4 CLI helpers + `OutputFormat` + `RedactionPolicy`)
66
+ Public APIs are grouped by role: protocol builders, redaction helpers, output formatters, internal redaction tools, utility/CLI helpers, types, and AFDATA logging integration.
67
67
 
68
68
  ### Protocol Builders (returns JsonValue)
69
69
 
@@ -82,13 +82,14 @@ buildJsonError(message: string, hint?: string, trace?: JsonValue): JsonValue
82
82
  buildJson(code: string, fields: JsonValue, trace?: JsonValue): JsonValue
83
83
  ```
84
84
 
85
- ### Redacted Values (returns JsonValue)
85
+ ### Redaction Helpers (returns JsonValue)
86
86
 
87
87
  Use these before raw HTTP/MCP/SSE serializers that do not call `outputJson`.
88
88
 
89
89
  ```typescript
90
90
  redactedValue(value: unknown): JsonValue
91
91
  redactedValueWith(value: unknown, redactionPolicy: RedactionPolicy): JsonValue
92
+ redactedValueWithOptions(value: unknown, redactionOptions: RedactionOptions): JsonValue
92
93
  ```
93
94
 
94
95
  **Use case:** structured protocol payloads (frameworks automatically serialize)
@@ -128,15 +129,18 @@ const notFound = buildJson(
128
129
  );
129
130
  ```
130
131
 
131
- ### CLI/Log Output (returns string)
132
+ ### Output Formatters (returns string)
132
133
 
133
- Format values for CLI output and logs. `outputJson` uses full `_secret` redaction by default. `outputJsonWith` supports explicit scoped policies. YAML and Plain always redact `_secret` and apply human-readable formatting.
134
+ Format values for CLI output and logs. `outputJson` uses full `_secret` redaction by default. `outputJsonWith` supports explicit scoped policies. Use `OutputOptions` to pass legacy secret names such as `api_key` or request schema-preserving YAML/plain rendering with `OutputStyle.Raw`.
134
135
 
135
136
  ```typescript
136
137
  outputJson(value: JsonValue): string // Single-line JSON, original keys, for programs/logs
137
138
  outputJsonWith(value: JsonValue, redactionPolicy: RedactionPolicy): string
139
+ outputJsonWithOptions(value: JsonValue, outputOptions: OutputOptions): string
138
140
  outputYaml(value: JsonValue): string // Multi-line YAML, keys stripped, values formatted
141
+ outputYamlWithOptions(value: JsonValue, outputOptions: OutputOptions): string
139
142
  outputPlain(value: JsonValue): string // Single-line logfmt, keys stripped, values formatted
143
+ outputPlainWithOptions(value: JsonValue, outputOptions: OutputOptions): string
140
144
  ```
141
145
 
142
146
  ```typescript
@@ -145,8 +149,25 @@ enum RedactionPolicy {
145
149
  RedactionNone = "RedactionNone",
146
150
  RedactionStrict = "RedactionStrict",
147
151
  }
152
+
153
+ type RedactionOptions = {
154
+ policy?: RedactionPolicy;
155
+ secretNames?: readonly string[]; // legacy names like "api_key" or "authorization"
156
+ }
157
+
158
+ enum OutputStyle {
159
+ Readable = "Readable",
160
+ Raw = "Raw",
161
+ }
162
+
163
+ type OutputOptions = {
164
+ redaction?: RedactionOptions;
165
+ style?: OutputStyle;
166
+ }
148
167
  ```
149
168
 
169
+ Secret names match exact field names at any nesting level; there is no trim, case folding, hyphen/underscore normalization, glob, regex, or substring matching. `OutputOptions` combines `RedactionOptions` with `OutputStyle.Readable` (default suffix stripping and value formatting) or `OutputStyle.Raw` (no suffix stripping or value formatting).
170
+
150
171
  **Example:**
151
172
  ```typescript
152
173
  import { outputJson, outputYaml, outputPlain } from "agent-first-data";
@@ -179,6 +200,7 @@ console.log(outputPlain(data));
179
200
 
180
201
  ```typescript
181
202
  internalRedactSecrets(value: JsonValue): void // Manually redact secrets in-place
203
+ internalRedactSecretsWithOptions(value: JsonValue, redactionOptions: RedactionOptions): void
182
204
  ```
183
205
 
184
206
  Most users don't need this. Output functions automatically protect secrets.
@@ -210,6 +232,7 @@ type OutputFormat = "json" | "yaml" | "plain"
210
232
  cliParseOutput(s: string): OutputFormat // Parse --output flag; throws on unknown
211
233
  cliParseLogFilters(entries: string[]): string[] // Normalize --log: trim, lowercase, dedup, remove empty
212
234
  cliOutput(value: JsonValue, format: OutputFormat): string // Dispatch to outputJson/Yaml/Plain
235
+ cliOutputWithOptions(value: JsonValue, format: OutputFormat, outputOptions: OutputOptions): string
213
236
  buildCliError(message: string, hint?: string): JsonValue // {code:"error", error_code:"invalid_request", hint?, retryable:false, trace:{duration_ms:0}}
214
237
  ```
215
238
 
package/dist/cli.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * AFDATA CLI helpers — output format parsing, log filter normalization, error building.
3
3
  */
4
- import { JsonValue } from "./format.js";
4
+ import { JsonValue, type OutputOptions } from "./format.js";
5
5
  /** Output format for CLI and pipe/MCP modes. */
6
6
  export type OutputFormat = "json" | "yaml" | "plain";
7
7
  /**
@@ -29,6 +29,11 @@ export declare function cliParseLogFilters(entries: string[]): string[];
29
29
  * cliOutput({ code: "ok" }, "plain") // → "code=ok"
30
30
  */
31
31
  export declare function cliOutput(value: JsonValue, format: OutputFormat): string;
32
+ /**
33
+ * Dispatch output formatting with explicit redaction and style.
34
+ * JSON ignores OutputStyle and preserves original keys and values after redaction.
35
+ */
36
+ export declare function cliOutputWithOptions(value: JsonValue, format: OutputFormat, outputOptions: OutputOptions): string;
32
37
  /**
33
38
  * Build a standard CLI parse error value.
34
39
  * Use when flag parsing fails or a flag value is invalid.
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * AFDATA CLI helpers — output format parsing, log filter normalization, error building.
3
3
  */
4
- import { outputJson, outputYaml, outputPlain } from "./format.js";
4
+ import { outputJson, outputJsonWithOptions, outputYaml, outputYamlWithOptions, outputPlain, outputPlainWithOptions, } from "./format.js";
5
5
  /**
6
6
  * Parse the --output flag value into an OutputFormat.
7
7
  * Throws on unknown values; catch and pass message to buildCliError.
@@ -47,6 +47,17 @@ export function cliOutput(value, format) {
47
47
  return outputPlain(value);
48
48
  return outputJson(value);
49
49
  }
50
+ /**
51
+ * Dispatch output formatting with explicit redaction and style.
52
+ * JSON ignores OutputStyle and preserves original keys and values after redaction.
53
+ */
54
+ export function cliOutputWithOptions(value, format, outputOptions) {
55
+ if (format === "yaml")
56
+ return outputYamlWithOptions(value, outputOptions);
57
+ if (format === "plain")
58
+ return outputPlainWithOptions(value, outputOptions);
59
+ return outputJsonWithOptions(value, outputOptions);
60
+ }
50
61
  /**
51
62
  * Build a standard CLI parse error value.
52
63
  * Use when flag parsing fails or a flag value is invalid.
package/dist/format.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * AFDATA output formatting and protocol templates.
3
3
  *
4
- * 11 public APIs and 1 type: protocol builders, redacted value helpers,
5
- * output formatters, redaction, parseSize, and RedactionPolicy.
4
+ * 16 public APIs and 4 types: protocol builders, redacted value helpers,
5
+ * output formatters, redaction, parseSize, RedactionPolicy, RedactionOptions,
6
+ * OutputStyle, and OutputOptions.
6
7
  */
7
8
  export type JsonValue = string | number | boolean | null | JsonValue[] | {
8
9
  [key: string]: JsonValue;
@@ -18,20 +19,49 @@ export declare enum RedactionPolicy {
18
19
  RedactionNone = "RedactionNone",
19
20
  RedactionStrict = "RedactionStrict"
20
21
  }
22
+ export type RedactionOptions = {
23
+ /** Optional scoped policy. Omitted means default full redaction. */
24
+ policy?: RedactionPolicy;
25
+ /**
26
+ * Field names to treat as secrets in addition to _secret suffixes.
27
+ * Matching is exact field-name equality at any nesting level.
28
+ */
29
+ secretNames?: readonly string[];
30
+ };
31
+ export declare enum OutputStyle {
32
+ Readable = "Readable",
33
+ Raw = "Raw"
34
+ }
35
+ export type OutputOptions = {
36
+ /** Redaction options applied before rendering. */
37
+ redaction?: RedactionOptions;
38
+ /** Rendering style for YAML/plain output. Omitted means readable. */
39
+ style?: OutputStyle;
40
+ };
21
41
  /** Format as single-line JSON. Secrets redacted, original keys, raw values. */
22
42
  export declare function outputJson(value: JsonValue): string;
23
43
  /** Format as single-line JSON with explicit redaction policy. */
24
44
  export declare function outputJsonWith(value: JsonValue, redactionPolicy: RedactionPolicy): string;
45
+ /** Format as single-line JSON with explicit output options. */
46
+ export declare function outputJsonWithOptions(value: JsonValue, outputOptions: OutputOptions): string;
25
47
  /** Format as multi-line YAML. Keys stripped, values formatted, secrets redacted. */
26
48
  export declare function outputYaml(value: JsonValue): string;
49
+ /** Format as multi-line YAML with explicit output options. */
50
+ export declare function outputYamlWithOptions(value: JsonValue, outputOptions: OutputOptions): string;
27
51
  /** Format as single-line logfmt. Keys stripped, values formatted, secrets redacted. */
28
52
  export declare function outputPlain(value: JsonValue): string;
53
+ /** Format as single-line logfmt with explicit output options. */
54
+ export declare function outputPlainWithOptions(value: JsonValue, outputOptions: OutputOptions): string;
29
55
  /** Redact _secret fields in-place. */
30
56
  export declare function internalRedactSecrets(value: JsonValue): void;
57
+ /** Redact secret fields in-place using explicit redaction options. */
58
+ export declare function internalRedactSecretsWithOptions(value: JsonValue, redactionOptions: RedactionOptions): void;
31
59
  /** Return a JSON-safe copy with default _secret redaction applied. */
32
60
  export declare function redactedValue(value: unknown): JsonValue;
33
61
  /** Return a JSON-safe copy with an explicit redaction policy applied. */
34
62
  export declare function redactedValueWith(value: unknown, redactionPolicy: RedactionPolicy): JsonValue;
63
+ /** Return a JSON-safe copy with explicit redaction options applied. */
64
+ export declare function redactedValueWithOptions(value: unknown, redactionOptions: RedactionOptions): JsonValue;
35
65
  /**
36
66
  * Parse a human-readable size string into bytes.
37
67
  * Accepts bare numbers or numbers followed by a unit letter (B/K/M/G/T).
package/dist/format.js CHANGED
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * AFDATA output formatting and protocol templates.
3
3
  *
4
- * 11 public APIs and 1 type: protocol builders, redacted value helpers,
5
- * output formatters, redaction, parseSize, and RedactionPolicy.
4
+ * 16 public APIs and 4 types: protocol builders, redacted value helpers,
5
+ * output formatters, redaction, parseSize, RedactionPolicy, RedactionOptions,
6
+ * OutputStyle, and OutputOptions.
6
7
  */
7
8
  // ═══════════════════════════════════════════
8
9
  // Public API: Protocol Builders
@@ -40,6 +41,11 @@ export var RedactionPolicy;
40
41
  RedactionPolicy["RedactionNone"] = "RedactionNone";
41
42
  RedactionPolicy["RedactionStrict"] = "RedactionStrict";
42
43
  })(RedactionPolicy || (RedactionPolicy = {}));
44
+ export var OutputStyle;
45
+ (function (OutputStyle) {
46
+ OutputStyle["Readable"] = "Readable";
47
+ OutputStyle["Raw"] = "Raw";
48
+ })(OutputStyle || (OutputStyle = {}));
43
49
  /** Format as single-line JSON. Secrets redacted, original keys, raw values. */
44
50
  export function outputJson(value) {
45
51
  return JSON.stringify(redactedValue(value));
@@ -48,18 +54,40 @@ export function outputJson(value) {
48
54
  export function outputJsonWith(value, redactionPolicy) {
49
55
  return JSON.stringify(redactedValueWith(value, redactionPolicy));
50
56
  }
57
+ /** Format as single-line JSON with explicit output options. */
58
+ export function outputJsonWithOptions(value, outputOptions) {
59
+ return JSON.stringify(redactedValueWithOptions(value, outputOptions.redaction ?? {}));
60
+ }
51
61
  /** Format as multi-line YAML. Keys stripped, values formatted, secrets redacted. */
52
62
  export function outputYaml(value) {
53
- value = redactedValue(value);
63
+ return outputYamlWithOptions(value, {});
64
+ }
65
+ /** Format as multi-line YAML with explicit output options. */
66
+ export function outputYamlWithOptions(value, outputOptions) {
67
+ value = redactedValueWithOptions(value, outputOptions.redaction ?? {});
54
68
  const lines = ["---"];
55
- renderYamlProcessed(value, 0, lines);
69
+ if (outputOptions.style === OutputStyle.Raw) {
70
+ renderYamlRaw(value, 0, lines);
71
+ }
72
+ else {
73
+ renderYamlProcessed(value, 0, lines);
74
+ }
56
75
  return lines.join("\n");
57
76
  }
58
77
  /** Format as single-line logfmt. Keys stripped, values formatted, secrets redacted. */
59
78
  export function outputPlain(value) {
60
- value = redactedValue(value);
79
+ return outputPlainWithOptions(value, {});
80
+ }
81
+ /** Format as single-line logfmt with explicit output options. */
82
+ export function outputPlainWithOptions(value, outputOptions) {
83
+ value = redactedValueWithOptions(value, outputOptions.redaction ?? {});
61
84
  const pairs = [];
62
- collectPlainPairs(value, "", pairs);
85
+ if (outputOptions.style === OutputStyle.Raw) {
86
+ collectPlainPairsRaw(value, "", pairs);
87
+ }
88
+ else {
89
+ collectPlainPairs(value, "", pairs);
90
+ }
63
91
  pairs.sort(([a], [b]) => jcsCompare(a, b));
64
92
  return pairs
65
93
  .map(([k, v]) => `${k}=${quoteLogfmtValue(v)}`)
@@ -72,6 +100,10 @@ export function outputPlain(value) {
72
100
  export function internalRedactSecrets(value) {
73
101
  redactSecrets(value);
74
102
  }
103
+ /** Redact secret fields in-place using explicit redaction options. */
104
+ export function internalRedactSecretsWithOptions(value, redactionOptions) {
105
+ applyRedactionOptions(value, redactionOptions);
106
+ }
75
107
  /** Return a JSON-safe copy with default _secret redaction applied. */
76
108
  export function redactedValue(value) {
77
109
  const v = sanitizeForJson(value);
@@ -84,6 +116,12 @@ export function redactedValueWith(value, redactionPolicy) {
84
116
  applyRedactionPolicy(v, redactionPolicy);
85
117
  return v;
86
118
  }
119
+ /** Return a JSON-safe copy with explicit redaction options applied. */
120
+ export function redactedValueWithOptions(value, redactionOptions) {
121
+ const v = sanitizeForJson(value);
122
+ applyRedactionOptions(v, redactionOptions);
123
+ return v;
124
+ }
87
125
  /**
88
126
  * Parse a human-readable size string into bytes.
89
127
  * Accepts bare numbers or numbers followed by a unit letter (B/K/M/G/T).
@@ -123,61 +161,77 @@ export function parseSize(s) {
123
161
  // ═══════════════════════════════════════════
124
162
  // Secret Redaction
125
163
  // ═══════════════════════════════════════════
126
- function redactSecrets(value) {
164
+ const EMPTY_SECRET_NAMES = new Set();
165
+ function secretNameSet(redactionOptions) {
166
+ return new Set(redactionOptions.secretNames ?? []);
167
+ }
168
+ function keyHasSecretSuffix(key) {
169
+ return key.endsWith("_secret") || key.endsWith("_SECRET");
170
+ }
171
+ function isSecretKey(key, secretNames) {
172
+ return keyHasSecretSuffix(key) || secretNames.has(key);
173
+ }
174
+ function redactSecrets(value, secretNames = EMPTY_SECRET_NAMES) {
127
175
  if (isObject(value)) {
128
176
  for (const k of Object.keys(value)) {
129
- if (k.endsWith("_secret") || k.endsWith("_SECRET")) {
177
+ if (isSecretKey(k, secretNames)) {
130
178
  const v = value[k];
131
179
  if (isObject(v) || Array.isArray(v)) {
132
- redactSecrets(v);
180
+ redactSecrets(v, secretNames);
133
181
  }
134
182
  else {
135
183
  value[k] = "***";
136
184
  }
137
185
  }
138
186
  else {
139
- redactSecrets(value[k]);
187
+ redactSecrets(value[k], secretNames);
140
188
  }
141
189
  }
142
190
  }
143
191
  else if (Array.isArray(value)) {
144
192
  for (const item of value) {
145
- redactSecrets(item);
193
+ redactSecrets(item, secretNames);
146
194
  }
147
195
  }
148
196
  }
149
- function redactSecretsStrict(value) {
197
+ function redactSecretsStrict(value, secretNames = EMPTY_SECRET_NAMES) {
150
198
  if (isObject(value)) {
151
199
  for (const k of Object.keys(value)) {
152
- if (k.endsWith("_secret") || k.endsWith("_SECRET")) {
200
+ if (isSecretKey(k, secretNames)) {
153
201
  value[k] = "***";
154
202
  }
155
203
  else {
156
- redactSecretsStrict(value[k]);
204
+ redactSecretsStrict(value[k], secretNames);
157
205
  }
158
206
  }
159
207
  }
160
208
  else if (Array.isArray(value)) {
161
209
  for (const item of value) {
162
- redactSecretsStrict(item);
210
+ redactSecretsStrict(item, secretNames);
163
211
  }
164
212
  }
165
213
  }
166
214
  function applyRedactionPolicy(value, redactionPolicy) {
215
+ applyRedactionPolicyWithNames(value, redactionPolicy, EMPTY_SECRET_NAMES);
216
+ }
217
+ function applyRedactionOptions(value, redactionOptions) {
218
+ applyRedactionPolicyWithNames(value, redactionOptions.policy, secretNameSet(redactionOptions));
219
+ }
220
+ function applyRedactionPolicyWithNames(value, redactionPolicy, secretNames) {
167
221
  switch (redactionPolicy) {
168
222
  case RedactionPolicy.RedactionTraceOnly:
169
223
  if (isObject(value) && value.trace !== undefined) {
170
- redactSecrets(value.trace);
224
+ redactSecrets(value.trace, secretNames);
171
225
  }
172
226
  break;
173
227
  case RedactionPolicy.RedactionNone:
174
228
  break;
175
229
  case RedactionPolicy.RedactionStrict:
176
- redactSecretsStrict(value);
230
+ redactSecretsStrict(value, secretNames);
177
231
  break;
178
232
  default:
179
- // Safety fallback for unknown values.
180
- redactSecrets(value);
233
+ // Empty/unknown policy falls back to default full redaction.
234
+ redactSecrets(value, secretNames);
181
235
  break;
182
236
  }
183
237
  }
@@ -483,6 +537,69 @@ function renderYamlProcessed(value, indent, lines) {
483
537
  }
484
538
  }
485
539
  }
540
+ function renderYamlRaw(value, indent, lines) {
541
+ const prefix = " ".repeat(indent);
542
+ if (isObject(value)) {
543
+ for (const key of sortedObjectKeys(value)) {
544
+ renderYamlFieldRaw(prefix, key, value[key], indent, lines);
545
+ }
546
+ }
547
+ else if (Array.isArray(value)) {
548
+ renderYamlArrayRaw(value, indent, lines);
549
+ }
550
+ else {
551
+ lines.push(`${prefix}${yamlScalar(value)}`);
552
+ }
553
+ }
554
+ function renderYamlFieldRaw(prefix, key, value, indent, lines) {
555
+ if (isObject(value)) {
556
+ if (Object.keys(value).length > 0) {
557
+ lines.push(`${prefix}${key}:`);
558
+ renderYamlRaw(value, indent + 1, lines);
559
+ }
560
+ else {
561
+ lines.push(`${prefix}${key}: {}`);
562
+ }
563
+ }
564
+ else if (Array.isArray(value)) {
565
+ if (value.length > 0) {
566
+ lines.push(`${prefix}${key}:`);
567
+ renderYamlArrayRaw(value, indent + 1, lines);
568
+ }
569
+ else {
570
+ lines.push(`${prefix}${key}: []`);
571
+ }
572
+ }
573
+ else {
574
+ lines.push(`${prefix}${key}: ${yamlScalar(value)}`);
575
+ }
576
+ }
577
+ function renderYamlArrayRaw(arr, indent, lines) {
578
+ const prefix = " ".repeat(indent);
579
+ for (const item of arr) {
580
+ if (isObject(item)) {
581
+ if (Object.keys(item).length > 0) {
582
+ lines.push(`${prefix}-`);
583
+ renderYamlRaw(item, indent + 1, lines);
584
+ }
585
+ else {
586
+ lines.push(`${prefix}- {}`);
587
+ }
588
+ }
589
+ else if (Array.isArray(item)) {
590
+ if (item.length > 0) {
591
+ lines.push(`${prefix}-`);
592
+ renderYamlArrayRaw(item, indent + 1, lines);
593
+ }
594
+ else {
595
+ lines.push(`${prefix}- []`);
596
+ }
597
+ }
598
+ else {
599
+ lines.push(`${prefix}- ${yamlScalar(item)}`);
600
+ }
601
+ }
602
+ }
486
603
  function escapeYamlStr(s) {
487
604
  return s.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
488
605
  }
@@ -522,6 +639,26 @@ function collectPlainPairs(value, prefix, pairs) {
522
639
  }
523
640
  }
524
641
  }
642
+ function collectPlainPairsRaw(value, prefix, pairs) {
643
+ if (!isObject(value))
644
+ return;
645
+ for (const key of sortedObjectKeys(value)) {
646
+ const v = value[key];
647
+ const fullKey = prefix ? `${prefix}.${key}` : key;
648
+ if (isObject(v)) {
649
+ collectPlainPairsRaw(v, fullKey, pairs);
650
+ }
651
+ else if (Array.isArray(v)) {
652
+ pairs.push([fullKey, v.map((i) => plainScalarRaw(i)).join(",")]);
653
+ }
654
+ else if (v === null) {
655
+ pairs.push([fullKey, ""]);
656
+ }
657
+ else {
658
+ pairs.push([fullKey, plainScalar(v)]);
659
+ }
660
+ }
661
+ }
525
662
  function plainScalar(value) {
526
663
  if (typeof value === "string")
527
664
  return value;
@@ -533,6 +670,12 @@ function plainScalar(value) {
533
670
  return value.toString();
534
671
  return String(value);
535
672
  }
673
+ function plainScalarRaw(value) {
674
+ if (isObject(value) || Array.isArray(value)) {
675
+ return JSON.stringify(sortJsonValue(value));
676
+ }
677
+ return plainScalar(value);
678
+ }
536
679
  function quoteLogfmtValue(value) {
537
680
  if (value === "")
538
681
  return "";
@@ -598,6 +741,21 @@ function sanitizeForJson(value, stack = new WeakSet()) {
598
741
  function isObject(value) {
599
742
  return typeof value === "object" && value !== null && !Array.isArray(value);
600
743
  }
744
+ function sortedObjectKeys(obj) {
745
+ return Object.keys(obj).sort(jcsCompare);
746
+ }
747
+ function sortJsonValue(value) {
748
+ if (Array.isArray(value))
749
+ return value.map(sortJsonValue);
750
+ if (isObject(value)) {
751
+ const out = {};
752
+ for (const key of sortedObjectKeys(value)) {
753
+ out[key] = sortJsonValue(value[key]);
754
+ }
755
+ return out;
756
+ }
757
+ return value;
758
+ }
601
759
  function jcsCompare(a, b) {
602
760
  const ua = Array.from(a).flatMap((c) => {
603
761
  const cp = c.codePointAt(0);
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Agent-First Data (AFDATA) — suffix-driven output formatting and protocol templates.
3
3
  */
4
- export { buildJsonOk, buildJsonError, buildJson, RedactionPolicy, outputJson, outputJsonWith, outputYaml, outputPlain, internalRedactSecrets, redactedValue, redactedValueWith, parseSize, } from "./format.js";
4
+ export { buildJsonOk, buildJsonError, buildJson, RedactionPolicy, type RedactionOptions, OutputStyle, type OutputOptions, outputJson, outputJsonWith, outputJsonWithOptions, outputYaml, outputYamlWithOptions, outputPlain, outputPlainWithOptions, internalRedactSecrets, internalRedactSecretsWithOptions, redactedValue, redactedValueWith, redactedValueWithOptions, parseSize, } from "./format.js";
5
5
  export { log, span, initJson, initPlain, initYaml } from "./afdata_logging.js";
6
- export { type OutputFormat, cliParseOutput, cliParseLogFilters, cliOutput, buildCliError } from "./cli.js";
6
+ export { type OutputFormat, cliParseOutput, cliParseLogFilters, cliOutput, cliOutputWithOptions, buildCliError, } from "./cli.js";
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Agent-First Data (AFDATA) — suffix-driven output formatting and protocol templates.
3
3
  */
4
- export { buildJsonOk, buildJsonError, buildJson, RedactionPolicy, outputJson, outputJsonWith, outputYaml, outputPlain, internalRedactSecrets, redactedValue, redactedValueWith, parseSize, } from "./format.js";
4
+ export { buildJsonOk, buildJsonError, buildJson, RedactionPolicy, OutputStyle, outputJson, outputJsonWith, outputJsonWithOptions, outputYaml, outputYamlWithOptions, outputPlain, outputPlainWithOptions, internalRedactSecrets, internalRedactSecretsWithOptions, redactedValue, redactedValueWith, redactedValueWithOptions, parseSize, } from "./format.js";
5
5
  export { log, span, initJson, initPlain, initYaml } from "./afdata_logging.js";
6
- export { cliParseOutput, cliParseLogFilters, cliOutput, buildCliError } from "./cli.js";
6
+ export { cliParseOutput, cliParseLogFilters, cliOutput, cliOutputWithOptions, buildCliError, } from "./cli.js";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agent-first-data",
3
- "version": "0.8.0",
4
- "description": "Agent-First Data (AFDATA) — suffix-driven output formatting and protocol templates for AI agents",
3
+ "version": "0.9.0",
4
+ "description": "A naming convention that lets AI agents understand your data without being told what it means.",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",