@blackwell-systems/gcf 0.4.0 → 0.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/README.md CHANGED
@@ -44,33 +44,21 @@ Or install globally: `npm install -g @blackwell-systems/gcf` then use `gcf` dire
44
44
  ### Quick Start
45
45
 
46
46
  ```typescript
47
- import { encode, type Payload } from '@blackwell-systems/gcf';
47
+ import { encodeGeneric } from '@blackwell-systems/gcf';
48
48
 
49
- const p: Payload = {
50
- tool: 'context_for_task',
51
- tokenBudget: 5000,
52
- tokensUsed: 1847,
53
- symbols: [
54
- { qualifiedName: 'pkg.AuthMiddleware', kind: 'function', score: 0.78, provenance: 'lsp_resolved', distance: 0 },
55
- { qualifiedName: 'pkg.NewServer', kind: 'function', score: 0.54, provenance: 'lsp_resolved', distance: 1 },
56
- ],
57
- edges: [
58
- { source: 'pkg.NewServer', target: 'pkg.AuthMiddleware', edgeType: 'calls' },
49
+ const output = encodeGeneric({
50
+ employees: [
51
+ { id: 1, name: 'Alice', department: 'Engineering', salary: 95000 },
52
+ { id: 2, name: 'Bob', department: 'Sales', salary: 72000 },
59
53
  ],
60
- };
61
-
62
- const output = encode(p);
54
+ });
63
55
  ```
64
56
 
65
57
  Output:
66
58
  ```
67
- GCF tool=context_for_task budget=5000 tokens=1847 symbols=2 edges=1
68
- ## targets
69
- @0 fn pkg.AuthMiddleware 0.78 lsp_resolved
70
- ## related
71
- @1 fn pkg.NewServer 0.54 lsp_resolved
72
- ## edges [1]
73
- @0<@1 calls
59
+ ## employees [2]{id,name,department,salary}
60
+ 1|Alice|Engineering|95000
61
+ 2|Bob|Sales|72000
74
62
  ```
75
63
 
76
64
  ## Decode
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Decode any GCF text (tabular or graph profile) back into a JS value.
3
+ * Returns objects, arrays, and primitives matching the original structure.
4
+ *
5
+ * If the input starts with "GCF " (graph profile), falls back to decode()
6
+ * and returns the Payload as a plain object.
7
+ */
8
+ export declare function decodeGeneric(input: string): any;
9
+ //# sourceMappingURL=decode_generic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decode_generic.d.ts","sourceRoot":"","sources":["../src/decode_generic.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAiChD"}
@@ -0,0 +1,236 @@
1
+ import { decode } from './decode.js';
2
+ /**
3
+ * Decode any GCF text (tabular or graph profile) back into a JS value.
4
+ * Returns objects, arrays, and primitives matching the original structure.
5
+ *
6
+ * If the input starts with "GCF " (graph profile), falls back to decode()
7
+ * and returns the Payload as a plain object.
8
+ */
9
+ export function decodeGeneric(input) {
10
+ input = input.trimEnd();
11
+ if (!input)
12
+ return null;
13
+ const lines = input.split('\n');
14
+ // Graph profile fallback.
15
+ if (lines[0].startsWith('GCF ')) {
16
+ const p = decode(input);
17
+ return {
18
+ tool: p.tool,
19
+ tokenBudget: p.tokenBudget,
20
+ tokensUsed: p.tokensUsed,
21
+ packRoot: p.packRoot ?? '',
22
+ symbols: p.symbols.map(s => ({
23
+ qualifiedName: s.qualifiedName,
24
+ kind: s.kind,
25
+ score: s.score,
26
+ provenance: s.provenance,
27
+ distance: s.distance,
28
+ })),
29
+ edges: p.edges.map(e => ({
30
+ source: e.source,
31
+ target: e.target,
32
+ edgeType: e.edgeType,
33
+ ...(e.status ? { status: e.status } : {}),
34
+ })),
35
+ };
36
+ }
37
+ const result = {};
38
+ parseObject(lines, 0, 0, result);
39
+ return result;
40
+ }
41
+ function parseObject(lines, start, depth, out) {
42
+ const indent = ' '.repeat(depth);
43
+ let i = start;
44
+ while (i < lines.length) {
45
+ const raw = lines[i].replace(/\r$/, '');
46
+ if (raw === '' || raw.startsWith('# ')) {
47
+ i++;
48
+ continue;
49
+ }
50
+ if (depth > 0 && !raw.startsWith(indent))
51
+ break;
52
+ const content = depth > 0 ? raw.slice(indent.length) : raw;
53
+ // Skip _summary.
54
+ if (content.startsWith('## _summary')) {
55
+ i++;
56
+ continue;
57
+ }
58
+ // Tabular array or section header.
59
+ if (content.startsWith('## ')) {
60
+ const header = content.slice(3);
61
+ const bracketIdx = header.indexOf(' [');
62
+ if (bracketIdx >= 0) {
63
+ const name = header.slice(0, bracketIdx);
64
+ const rest = header.slice(bracketIdx + 2);
65
+ const closeBracket = rest.indexOf(']');
66
+ if (closeBracket >= 0) {
67
+ const afterBracket = rest.slice(closeBracket + 1);
68
+ if (afterBracket.startsWith('{')) {
69
+ // Tabular with fields.
70
+ const fieldEnd = afterBracket.indexOf('}');
71
+ if (fieldEnd >= 0) {
72
+ const fields = afterBracket.slice(1, fieldEnd).split(',');
73
+ i++;
74
+ const [rows, consumed] = parseTabularRows(lines, i, depth, fields);
75
+ out[name] = rows;
76
+ i += consumed;
77
+ continue;
78
+ }
79
+ }
80
+ else {
81
+ const countStr = rest.slice(0, closeBracket);
82
+ if (countStr === '0') {
83
+ out[name] = [];
84
+ i++;
85
+ continue;
86
+ }
87
+ // Non-uniform array.
88
+ i++;
89
+ const [items, consumed] = parseNonUniformArray(lines, i, depth);
90
+ out[name] = items;
91
+ i += consumed;
92
+ continue;
93
+ }
94
+ }
95
+ }
96
+ // Plain section header.
97
+ let name = header;
98
+ const bi = name.indexOf(' [');
99
+ if (bi >= 0)
100
+ name = name.slice(0, bi);
101
+ i++;
102
+ const nested = {};
103
+ const consumed = parseObject(lines, i, depth + 1, nested);
104
+ out[name] = nested;
105
+ i += consumed;
106
+ continue;
107
+ }
108
+ // Inline primitive array: name[N]: val1,val2,...
109
+ const bracketIdx = content.indexOf('[');
110
+ if (bracketIdx > 0) {
111
+ const colonIdx = content.indexOf(']: ');
112
+ if (colonIdx > bracketIdx) {
113
+ const name = content.slice(0, bracketIdx);
114
+ const valsStr = content.slice(colonIdx + 3);
115
+ out[name] = valsStr.split(',').map(v => parseValue(v.trim()));
116
+ i++;
117
+ continue;
118
+ }
119
+ }
120
+ // Key=value.
121
+ const eqIdx = content.indexOf('=');
122
+ if (eqIdx > 0) {
123
+ const key = content.slice(0, eqIdx);
124
+ const val = content.slice(eqIdx + 1);
125
+ out[key] = parseValue(val);
126
+ i++;
127
+ continue;
128
+ }
129
+ i++;
130
+ }
131
+ return i - start;
132
+ }
133
+ function parseTabularRows(lines, start, depth, fields) {
134
+ const indent = ' '.repeat(depth);
135
+ const rows = [];
136
+ let i = start;
137
+ while (i < lines.length) {
138
+ const raw = lines[i].replace(/\r$/, '');
139
+ if (raw === '') {
140
+ i++;
141
+ continue;
142
+ }
143
+ const content = depth > 0 ? (raw.startsWith(indent) ? raw.slice(indent.length) : null) : raw;
144
+ if (content === null)
145
+ break;
146
+ if (content.startsWith('## '))
147
+ break;
148
+ if (content.startsWith('# ')) {
149
+ i++;
150
+ continue;
151
+ }
152
+ let rowData = content;
153
+ let hasNested = false;
154
+ if (rowData.startsWith('@')) {
155
+ const sp = rowData.indexOf(' ');
156
+ if (sp > 0) {
157
+ rowData = rowData.slice(sp + 1);
158
+ hasNested = true;
159
+ }
160
+ }
161
+ const vals = rowData.split('|');
162
+ const row = {};
163
+ for (let j = 0; j < fields.length; j++) {
164
+ row[fields[j]] = j < vals.length ? parseValue(vals[j]) : null;
165
+ }
166
+ i++;
167
+ if (hasNested) {
168
+ const nestedIndent = indent + ' ';
169
+ while (i < lines.length) {
170
+ const nl = lines[i].replace(/\r$/, '');
171
+ if (!nl.startsWith(nestedIndent))
172
+ break;
173
+ const nc = nl.slice(nestedIndent.length);
174
+ if (nc.startsWith('.')) {
175
+ const fieldName = nc.slice(1);
176
+ i++;
177
+ const nested = {};
178
+ const consumed = parseObject(lines, i, depth + 2, nested);
179
+ row[fieldName] = nested;
180
+ i += consumed;
181
+ }
182
+ else {
183
+ break;
184
+ }
185
+ }
186
+ }
187
+ rows.push(row);
188
+ }
189
+ return [rows, i - start];
190
+ }
191
+ function parseNonUniformArray(lines, start, depth) {
192
+ const indent = ' '.repeat(depth);
193
+ const items = [];
194
+ let i = start;
195
+ while (i < lines.length) {
196
+ const raw = lines[i].replace(/\r$/, '');
197
+ if (raw === '') {
198
+ i++;
199
+ continue;
200
+ }
201
+ const content = depth > 0 ? (raw.startsWith(indent) ? raw.slice(indent.length) : null) : raw;
202
+ if (content === null)
203
+ break;
204
+ if (content.startsWith('## '))
205
+ break;
206
+ if (content.startsWith('@')) {
207
+ const sp = content.indexOf(' ');
208
+ if (sp > 0) {
209
+ items.push(parseValue(content.slice(sp + 1)));
210
+ }
211
+ i++;
212
+ }
213
+ else {
214
+ break;
215
+ }
216
+ }
217
+ return [items, i - start];
218
+ }
219
+ function parseValue(s) {
220
+ if (s === '-')
221
+ return null;
222
+ if (s === 'true')
223
+ return true;
224
+ if (s === 'false')
225
+ return false;
226
+ if (s === '""')
227
+ return '';
228
+ if (s.length >= 2 && s[0] === '"' && s[s.length - 1] === '"') {
229
+ return s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
230
+ }
231
+ const n = Number(s);
232
+ if (!isNaN(n) && s !== '')
233
+ return n;
234
+ return s;
235
+ }
236
+ //# sourceMappingURL=decode_generic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decode_generic.js","sourceRoot":"","sources":["../src/decode_generic.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -5,5 +5,6 @@ export { decode } from './decode.js';
5
5
  export { Session, encodeWithSession } from './session.js';
6
6
  export { encodeDelta } from './delta.js';
7
7
  export { encodeGeneric } from './generic.js';
8
+ export { decodeGeneric } from './decode_generic.js';
8
9
  export { StreamEncoder, type StreamWriter, type StreamOptions } from './stream.js';
9
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAClF,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,KAAK,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAClF,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,KAAK,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -4,5 +4,6 @@ export { decode } from './decode.js';
4
4
  export { Session, encodeWithSession } from './session.js';
5
5
  export { encodeDelta } from './delta.js';
6
6
  export { encodeGeneric } from './generic.js';
7
+ export { decodeGeneric } from './decode_generic.js';
7
8
  export { StreamEncoder } from './stream.js';
8
9
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAyC,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAyC,MAAM,aAAa,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blackwell-systems/gcf",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "TypeScript implementation of GCF (Graph Compact Format) - token-optimized wire format for LLM tool responses",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -0,0 +1,237 @@
1
+ import { decode } from './decode.js';
2
+
3
+ /**
4
+ * Decode any GCF text (tabular or graph profile) back into a JS value.
5
+ * Returns objects, arrays, and primitives matching the original structure.
6
+ *
7
+ * If the input starts with "GCF " (graph profile), falls back to decode()
8
+ * and returns the Payload as a plain object.
9
+ */
10
+ export function decodeGeneric(input: string): any {
11
+ input = input.trimEnd();
12
+ if (!input) return null;
13
+
14
+ const lines = input.split('\n');
15
+
16
+ // Graph profile fallback.
17
+ if (lines[0].startsWith('GCF ')) {
18
+ const p = decode(input);
19
+ return {
20
+ tool: p.tool,
21
+ tokenBudget: p.tokenBudget,
22
+ tokensUsed: p.tokensUsed,
23
+ packRoot: p.packRoot ?? '',
24
+ symbols: p.symbols.map(s => ({
25
+ qualifiedName: s.qualifiedName,
26
+ kind: s.kind,
27
+ score: s.score,
28
+ provenance: s.provenance,
29
+ distance: s.distance,
30
+ })),
31
+ edges: p.edges.map(e => ({
32
+ source: e.source,
33
+ target: e.target,
34
+ edgeType: e.edgeType,
35
+ ...(e.status ? { status: e.status } : {}),
36
+ })),
37
+ };
38
+ }
39
+
40
+ const result: Record<string, any> = {};
41
+ parseObject(lines, 0, 0, result);
42
+ return result;
43
+ }
44
+
45
+ function parseObject(lines: string[], start: number, depth: number, out: Record<string, any>): number {
46
+ const indent = ' '.repeat(depth);
47
+ let i = start;
48
+
49
+ while (i < lines.length) {
50
+ const raw = lines[i].replace(/\r$/, '');
51
+ if (raw === '' || raw.startsWith('# ')) { i++; continue; }
52
+
53
+ if (depth > 0 && !raw.startsWith(indent)) break;
54
+
55
+ const content = depth > 0 ? raw.slice(indent.length) : raw;
56
+
57
+ // Skip _summary.
58
+ if (content.startsWith('## _summary')) { i++; continue; }
59
+
60
+ // Tabular array or section header.
61
+ if (content.startsWith('## ')) {
62
+ const header = content.slice(3);
63
+ const bracketIdx = header.indexOf(' [');
64
+
65
+ if (bracketIdx >= 0) {
66
+ const name = header.slice(0, bracketIdx);
67
+ const rest = header.slice(bracketIdx + 2);
68
+ const closeBracket = rest.indexOf(']');
69
+
70
+ if (closeBracket >= 0) {
71
+ const afterBracket = rest.slice(closeBracket + 1);
72
+
73
+ if (afterBracket.startsWith('{')) {
74
+ // Tabular with fields.
75
+ const fieldEnd = afterBracket.indexOf('}');
76
+ if (fieldEnd >= 0) {
77
+ const fields = afterBracket.slice(1, fieldEnd).split(',');
78
+ i++;
79
+ const [rows, consumed] = parseTabularRows(lines, i, depth, fields);
80
+ out[name] = rows;
81
+ i += consumed;
82
+ continue;
83
+ }
84
+ } else {
85
+ const countStr = rest.slice(0, closeBracket);
86
+ if (countStr === '0') {
87
+ out[name] = [];
88
+ i++;
89
+ continue;
90
+ }
91
+ // Non-uniform array.
92
+ i++;
93
+ const [items, consumed] = parseNonUniformArray(lines, i, depth);
94
+ out[name] = items;
95
+ i += consumed;
96
+ continue;
97
+ }
98
+ }
99
+ }
100
+
101
+ // Plain section header.
102
+ let name = header;
103
+ const bi = name.indexOf(' [');
104
+ if (bi >= 0) name = name.slice(0, bi);
105
+ i++;
106
+ const nested: Record<string, any> = {};
107
+ const consumed = parseObject(lines, i, depth + 1, nested);
108
+ out[name] = nested;
109
+ i += consumed;
110
+ continue;
111
+ }
112
+
113
+ // Inline primitive array: name[N]: val1,val2,...
114
+ const bracketIdx = content.indexOf('[');
115
+ if (bracketIdx > 0) {
116
+ const colonIdx = content.indexOf(']: ');
117
+ if (colonIdx > bracketIdx) {
118
+ const name = content.slice(0, bracketIdx);
119
+ const valsStr = content.slice(colonIdx + 3);
120
+ out[name] = valsStr.split(',').map(v => parseValue(v.trim()));
121
+ i++;
122
+ continue;
123
+ }
124
+ }
125
+
126
+ // Key=value.
127
+ const eqIdx = content.indexOf('=');
128
+ if (eqIdx > 0) {
129
+ const key = content.slice(0, eqIdx);
130
+ const val = content.slice(eqIdx + 1);
131
+ out[key] = parseValue(val);
132
+ i++;
133
+ continue;
134
+ }
135
+
136
+ i++;
137
+ }
138
+
139
+ return i - start;
140
+ }
141
+
142
+ function parseTabularRows(lines: string[], start: number, depth: number, fields: string[]): [any[], number] {
143
+ const indent = ' '.repeat(depth);
144
+ const rows: any[] = [];
145
+ let i = start;
146
+
147
+ while (i < lines.length) {
148
+ const raw = lines[i].replace(/\r$/, '');
149
+ if (raw === '') { i++; continue; }
150
+
151
+ const content = depth > 0 ? (raw.startsWith(indent) ? raw.slice(indent.length) : null) : raw;
152
+ if (content === null) break;
153
+ if (content.startsWith('## ')) break;
154
+ if (content.startsWith('# ')) { i++; continue; }
155
+
156
+ let rowData = content;
157
+ let hasNested = false;
158
+ if (rowData.startsWith('@')) {
159
+ const sp = rowData.indexOf(' ');
160
+ if (sp > 0) {
161
+ rowData = rowData.slice(sp + 1);
162
+ hasNested = true;
163
+ }
164
+ }
165
+
166
+ const vals = rowData.split('|');
167
+ const row: Record<string, any> = {};
168
+ for (let j = 0; j < fields.length; j++) {
169
+ row[fields[j]] = j < vals.length ? parseValue(vals[j]) : null;
170
+ }
171
+
172
+ i++;
173
+
174
+ if (hasNested) {
175
+ const nestedIndent = indent + ' ';
176
+ while (i < lines.length) {
177
+ const nl = lines[i].replace(/\r$/, '');
178
+ if (!nl.startsWith(nestedIndent)) break;
179
+ const nc = nl.slice(nestedIndent.length);
180
+
181
+ if (nc.startsWith('.')) {
182
+ const fieldName = nc.slice(1);
183
+ i++;
184
+ const nested: Record<string, any> = {};
185
+ const consumed = parseObject(lines, i, depth + 2, nested);
186
+ row[fieldName] = nested;
187
+ i += consumed;
188
+ } else {
189
+ break;
190
+ }
191
+ }
192
+ }
193
+
194
+ rows.push(row);
195
+ }
196
+
197
+ return [rows, i - start];
198
+ }
199
+
200
+ function parseNonUniformArray(lines: string[], start: number, depth: number): [any[], number] {
201
+ const indent = ' '.repeat(depth);
202
+ const items: any[] = [];
203
+ let i = start;
204
+
205
+ while (i < lines.length) {
206
+ const raw = lines[i].replace(/\r$/, '');
207
+ if (raw === '') { i++; continue; }
208
+ const content = depth > 0 ? (raw.startsWith(indent) ? raw.slice(indent.length) : null) : raw;
209
+ if (content === null) break;
210
+ if (content.startsWith('## ')) break;
211
+
212
+ if (content.startsWith('@')) {
213
+ const sp = content.indexOf(' ');
214
+ if (sp > 0) {
215
+ items.push(parseValue(content.slice(sp + 1)));
216
+ }
217
+ i++;
218
+ } else {
219
+ break;
220
+ }
221
+ }
222
+
223
+ return [items, i - start];
224
+ }
225
+
226
+ function parseValue(s: string): any {
227
+ if (s === '-') return null;
228
+ if (s === 'true') return true;
229
+ if (s === 'false') return false;
230
+ if (s === '""') return '';
231
+ if (s.length >= 2 && s[0] === '"' && s[s.length - 1] === '"') {
232
+ return s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
233
+ }
234
+ const n = Number(s);
235
+ if (!isNaN(n) && s !== '') return n;
236
+ return s;
237
+ }
package/src/index.ts CHANGED
@@ -5,4 +5,5 @@ export { decode } from './decode.js';
5
5
  export { Session, encodeWithSession } from './session.js';
6
6
  export { encodeDelta } from './delta.js';
7
7
  export { encodeGeneric } from './generic.js';
8
+ export { decodeGeneric } from './decode_generic.js';
8
9
  export { StreamEncoder, type StreamWriter, type StreamOptions } from './stream.js';