@jinn-network/core 0.1.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.
Files changed (111) hide show
  1. package/dist/canonical-json.d.ts +1 -0
  2. package/dist/canonical-json.js +67 -0
  3. package/dist/captured-task.d.ts +140 -0
  4. package/dist/captured-task.js +122 -0
  5. package/dist/contribution-store.d.ts +97 -0
  6. package/dist/contribution-store.js +770 -0
  7. package/dist/corpus-read/acquire.d.ts +39 -0
  8. package/dist/corpus-read/acquire.js +212 -0
  9. package/dist/corpus-read/cache.d.ts +14 -0
  10. package/dist/corpus-read/cache.js +17 -0
  11. package/dist/corpus-read/capture-meta.d.ts +16 -0
  12. package/dist/corpus-read/capture-meta.js +18 -0
  13. package/dist/corpus-read/create-corpus.d.ts +2 -0
  14. package/dist/corpus-read/create-corpus.js +97 -0
  15. package/dist/corpus-read/fetch-artifact.d.ts +21 -0
  16. package/dist/corpus-read/fetch-artifact.js +32 -0
  17. package/dist/corpus-read/fetch.d.ts +12 -0
  18. package/dist/corpus-read/fetch.js +24 -0
  19. package/dist/corpus-read/http-discovery.d.ts +9 -0
  20. package/dist/corpus-read/http-discovery.js +128 -0
  21. package/dist/corpus-read/index.d.ts +10 -0
  22. package/dist/corpus-read/index.js +10 -0
  23. package/dist/corpus-read/ipfs.d.ts +5 -0
  24. package/dist/corpus-read/ipfs.js +72 -0
  25. package/dist/corpus-read/route-resolver.d.ts +16 -0
  26. package/dist/corpus-read/route-resolver.js +19 -0
  27. package/dist/corpus-read/types.d.ts +177 -0
  28. package/dist/corpus-read/types.js +42 -0
  29. package/dist/envelope.d.ts +134 -0
  30. package/dist/envelope.js +162 -0
  31. package/dist/evidence-adapter.d.ts +26 -0
  32. package/dist/evidence-adapter.js +321 -0
  33. package/dist/evidence-filesystem.d.ts +40 -0
  34. package/dist/evidence-filesystem.js +267 -0
  35. package/dist/evidence-index.d.ts +117 -0
  36. package/dist/evidence-index.js +1083 -0
  37. package/dist/evidence-store-lock.d.ts +2 -0
  38. package/dist/evidence-store-lock.js +208 -0
  39. package/dist/execution-envelope.d.ts +3142 -0
  40. package/dist/execution-envelope.js +203 -0
  41. package/dist/index.d.ts +12 -0
  42. package/dist/index.js +12 -0
  43. package/dist/manifest.d.ts +75 -0
  44. package/dist/manifest.js +184 -0
  45. package/dist/paired.d.ts +68 -0
  46. package/dist/paired.js +92 -0
  47. package/dist/scrub/build.d.ts +52 -0
  48. package/dist/scrub/build.js +84 -0
  49. package/dist/scrub/emit-scrub.d.ts +41 -0
  50. package/dist/scrub/emit-scrub.js +87 -0
  51. package/dist/scrub/index.d.ts +12 -0
  52. package/dist/scrub/index.js +12 -0
  53. package/dist/scrub/key-policy.d.ts +20 -0
  54. package/dist/scrub/key-policy.js +42 -0
  55. package/dist/scrub/layer2.d.ts +23 -0
  56. package/dist/scrub/layer2.js +32 -0
  57. package/dist/scrub/ml-pii-stage.d.ts +24 -0
  58. package/dist/scrub/ml-pii-stage.js +42 -0
  59. package/dist/scrub/openredaction-stage.d.ts +196 -0
  60. package/dist/scrub/openredaction-stage.js +270 -0
  61. package/dist/scrub/pii-build.d.ts +38 -0
  62. package/dist/scrub/pii-build.js +67 -0
  63. package/dist/scrub/pipeline.d.ts +38 -0
  64. package/dist/scrub/pipeline.js +83 -0
  65. package/dist/scrub/plain-patterns-stage.d.ts +31 -0
  66. package/dist/scrub/plain-patterns-stage.js +84 -0
  67. package/dist/scrub/secretlint-stage.d.ts +36 -0
  68. package/dist/scrub/secretlint-stage.js +249 -0
  69. package/dist/scrub/transformers-detector.d.ts +35 -0
  70. package/dist/scrub/transformers-detector.js +67 -0
  71. package/dist/scrub/types.d.ts +25 -0
  72. package/dist/scrub/types.js +1 -0
  73. package/dist/session-provenance.d.ts +75 -0
  74. package/dist/session-provenance.js +20 -0
  75. package/dist/skill-artifact.d.ts +442 -0
  76. package/dist/skill-artifact.js +136 -0
  77. package/dist/trajectory/hash-chain.d.ts +18 -0
  78. package/dist/trajectory/hash-chain.js +47 -0
  79. package/dist/trajectory/index.d.ts +4 -0
  80. package/dist/trajectory/index.js +4 -0
  81. package/dist/trajectory/schema.d.ts +606 -0
  82. package/dist/trajectory/schema.js +110 -0
  83. package/dist/trajectory/transcript-parsers/aider-history.d.ts +42 -0
  84. package/dist/trajectory/transcript-parsers/aider-history.js +181 -0
  85. package/dist/trajectory/transcript-parsers/claude-code-jsonl.d.ts +37 -0
  86. package/dist/trajectory/transcript-parsers/claude-code-jsonl.js +142 -0
  87. package/dist/trajectory/transcript-parsers/codex-session.d.ts +42 -0
  88. package/dist/trajectory/transcript-parsers/codex-session.js +235 -0
  89. package/dist/trajectory/transcript-parsers/continue-devdata.d.ts +41 -0
  90. package/dist/trajectory/transcript-parsers/continue-devdata.js +190 -0
  91. package/dist/trajectory/transcript-parsers/cursor-sqlite.d.ts +38 -0
  92. package/dist/trajectory/transcript-parsers/cursor-sqlite.js +118 -0
  93. package/dist/trajectory/transcript-parsers/gemini-session.d.ts +35 -0
  94. package/dist/trajectory/transcript-parsers/gemini-session.js +137 -0
  95. package/dist/trajectory/transcript-parsers/index.d.ts +7 -0
  96. package/dist/trajectory/transcript-parsers/index.js +7 -0
  97. package/dist/trajectory/transcript-parsers/types.d.ts +101 -0
  98. package/dist/trajectory/transcript-parsers/types.js +32 -0
  99. package/dist/trajectory/transcript-to-spans/attrs.d.ts +4 -0
  100. package/dist/trajectory/transcript-to-spans/attrs.js +30 -0
  101. package/dist/trajectory/transcript-to-spans/claude-code-stream-json.d.ts +8 -0
  102. package/dist/trajectory/transcript-to-spans/claude-code-stream-json.js +162 -0
  103. package/dist/trajectory/transcript-to-spans/codex-exec-json.d.ts +8 -0
  104. package/dist/trajectory/transcript-to-spans/codex-exec-json.js +253 -0
  105. package/dist/trajectory/transcript-to-spans/index.d.ts +4 -0
  106. package/dist/trajectory/transcript-to-spans/index.js +4 -0
  107. package/dist/trajectory/transcript-to-spans/types.d.ts +18 -0
  108. package/dist/trajectory/transcript-to-spans/types.js +1 -0
  109. package/dist/window.d.ts +12 -0
  110. package/dist/window.js +5 -0
  111. package/package.json +67 -0
@@ -0,0 +1,253 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { CodexSessionParser } from '../transcript-parsers/codex-session.js';
3
+ import { makeProvenanceAttrs, truncate, truncateLeaves } from './attrs.js';
4
+ const SOURCE_FORMAT = 'codex-exec-json';
5
+ const PARSER_NAME = 'codex-exec-json';
6
+ const PARSER_VERSION = '1.1.0';
7
+ class TimestampCursor {
8
+ lastGoodNs = 0n;
9
+ next(iso) {
10
+ const milliseconds = new Date(iso).getTime();
11
+ if (Number.isFinite(milliseconds)) {
12
+ const nanoseconds = BigInt(milliseconds) * 1000000n;
13
+ this.lastGoodNs = nanoseconds;
14
+ return String(nanoseconds);
15
+ }
16
+ this.lastGoodNs += 1n;
17
+ return String(this.lastGoodNs);
18
+ }
19
+ }
20
+ function provenanceAttrs() {
21
+ return makeProvenanceAttrs(SOURCE_FORMAT, PARSER_NAME, PARSER_VERSION);
22
+ }
23
+ /**
24
+ * `codex exec --json` stdout uses item lifecycle records, while Codex home
25
+ * sessions use timestamped `response_item` envelopes. Convert the direct
26
+ * stream to the same events consumed below; returning no events preserves the
27
+ * home-session compatibility fallback.
28
+ */
29
+ function parseDirectExecEvents(rawText) {
30
+ const events = [];
31
+ const pendingCommandIds = new Set();
32
+ let syntheticTimestampMs = 0;
33
+ const nextTimestamp = () => new Date(syntheticTimestampMs++).toISOString();
34
+ for (const line of rawText.split('\n')) {
35
+ const trimmed = line.trim();
36
+ if (!trimmed)
37
+ continue;
38
+ let record;
39
+ try {
40
+ record = JSON.parse(trimmed);
41
+ }
42
+ catch {
43
+ continue;
44
+ }
45
+ if (!record || (record.type !== 'item.started' && record.type !== 'item.completed')) {
46
+ continue;
47
+ }
48
+ if (!record.item || typeof record.item !== 'object' || Array.isArray(record.item)) {
49
+ continue;
50
+ }
51
+ const item = record.item;
52
+ if (record.type === 'item.completed' &&
53
+ item.type === 'agent_message' &&
54
+ typeof item.text === 'string' &&
55
+ item.text.length > 0) {
56
+ events.push({
57
+ kind: 'assistant-message',
58
+ timestamp: nextTimestamp(),
59
+ content: item.text,
60
+ });
61
+ continue;
62
+ }
63
+ if (item.type !== 'command_execution' || typeof item.command !== 'string') {
64
+ continue;
65
+ }
66
+ const itemId = typeof item.id === 'string' ? item.id : null;
67
+ const hasPendingCall = itemId !== null && pendingCommandIds.has(itemId);
68
+ if (record.type === 'item.started') {
69
+ events.push({
70
+ kind: 'tool-call',
71
+ timestamp: nextTimestamp(),
72
+ name: 'command_execution',
73
+ args: { command: item.command },
74
+ ...(itemId !== null ? { correlationId: itemId } : {}),
75
+ });
76
+ if (itemId !== null)
77
+ pendingCommandIds.add(itemId);
78
+ continue;
79
+ }
80
+ // A completed-only stream still carries enough evidence for a full call.
81
+ if (!hasPendingCall) {
82
+ events.push({
83
+ kind: 'tool-call',
84
+ timestamp: nextTimestamp(),
85
+ name: 'command_execution',
86
+ args: { command: item.command },
87
+ ...(itemId !== null ? { correlationId: itemId } : {}),
88
+ });
89
+ }
90
+ if (itemId !== null)
91
+ pendingCommandIds.delete(itemId);
92
+ const output = typeof item.aggregated_output === 'string' ? item.aggregated_output : '';
93
+ const isError = (typeof item.exit_code === 'number' && item.exit_code !== 0) ||
94
+ item.status === 'failed';
95
+ events.push({
96
+ kind: 'tool-result',
97
+ timestamp: nextTimestamp(),
98
+ name: 'command_execution',
99
+ content: output,
100
+ isError,
101
+ ...(itemId !== null ? { correlationId: itemId } : {}),
102
+ });
103
+ }
104
+ return events;
105
+ }
106
+ function findTerminalUsage(rawText) {
107
+ let result = null;
108
+ for (const line of rawText.split('\n')) {
109
+ const trimmed = line.trim();
110
+ if (!trimmed)
111
+ continue;
112
+ let object;
113
+ try {
114
+ object = JSON.parse(trimmed);
115
+ }
116
+ catch {
117
+ continue;
118
+ }
119
+ if ((object['type'] === 'turn.completed' || object['type'] === 'turn.failed') &&
120
+ object['usage']) {
121
+ const usage = object['usage'];
122
+ const inputTokens = usage['input_tokens'];
123
+ const outputTokens = usage['output_tokens'];
124
+ if (typeof inputTokens === 'number' && typeof outputTokens === 'number') {
125
+ result = { inputTokens, outputTokens };
126
+ }
127
+ }
128
+ }
129
+ return result;
130
+ }
131
+ export class CodexExecJsonParser {
132
+ sourceFormat = SOURCE_FORMAT;
133
+ parserName = PARSER_NAME;
134
+ parserVersion = PARSER_VERSION;
135
+ async parse(transcriptPath) {
136
+ let rawText;
137
+ try {
138
+ rawText = await readFile(transcriptPath, 'utf-8');
139
+ }
140
+ catch {
141
+ return [];
142
+ }
143
+ return this.parseText(rawText);
144
+ }
145
+ parseText(rawText) {
146
+ let events = parseDirectExecEvents(rawText);
147
+ if (events.length === 0) {
148
+ try {
149
+ const normalized = rawText.endsWith('\n') ? rawText : `${rawText}\n`;
150
+ events = new CodexSessionParser().parseChunk({
151
+ sessionId: 'engine-pack',
152
+ chunk: normalized,
153
+ });
154
+ }
155
+ catch {
156
+ return [];
157
+ }
158
+ }
159
+ const spans = [];
160
+ const pendingByName = new Map();
161
+ const pendingByCorrelationId = new Map();
162
+ const agentTurns = [];
163
+ const cursor = new TimestampCursor();
164
+ for (const event of events) {
165
+ switch (event.kind) {
166
+ case 'user-message':
167
+ case 'assistant-message': {
168
+ const timestamp = cursor.next(event.timestamp);
169
+ const turn = {
170
+ name: `agent_turn.${event.kind === 'user-message' ? 'user' : 'assistant'}`,
171
+ kind: 'INTERNAL',
172
+ startTimeUnixNano: timestamp,
173
+ endTimeUnixNano: timestamp,
174
+ attributes: {
175
+ 'jinn.span.kind': 'jinn.agent_turn',
176
+ 'jinn.turn.role': event.kind === 'user-message' ? 'user' : 'assistant',
177
+ 'message.content': truncate(event.content),
178
+ ...provenanceAttrs(),
179
+ },
180
+ events: [],
181
+ status: { code: 'OK' },
182
+ };
183
+ spans.push(turn);
184
+ agentTurns.push(turn);
185
+ break;
186
+ }
187
+ case 'tool-call': {
188
+ const timestamp = cursor.next(event.timestamp);
189
+ const call = {
190
+ name: `tool_call.${event.name}`,
191
+ kind: 'INTERNAL',
192
+ startTimeUnixNano: timestamp,
193
+ endTimeUnixNano: timestamp,
194
+ attributes: {
195
+ 'jinn.span.kind': 'jinn.tool_call',
196
+ 'tool.name': event.name,
197
+ 'tool.args': truncateLeaves(event.args),
198
+ ...provenanceAttrs(),
199
+ },
200
+ events: [],
201
+ status: { code: 'UNSET' },
202
+ };
203
+ spans.push(call);
204
+ if (event.correlationId) {
205
+ pendingByCorrelationId.set(event.correlationId, call);
206
+ }
207
+ else {
208
+ const queue = pendingByName.get(event.name) ?? [];
209
+ queue.push(call);
210
+ pendingByName.set(event.name, queue);
211
+ }
212
+ break;
213
+ }
214
+ case 'tool-result': {
215
+ let call;
216
+ if (event.correlationId) {
217
+ call = pendingByCorrelationId.get(event.correlationId);
218
+ pendingByCorrelationId.delete(event.correlationId);
219
+ }
220
+ else {
221
+ const queue = pendingByName.get(event.name);
222
+ call = queue?.shift();
223
+ }
224
+ if (!call)
225
+ break;
226
+ const timestamp = cursor.next(event.timestamp);
227
+ call.endTimeUnixNano = timestamp;
228
+ call.events = [
229
+ {
230
+ timeUnixNano: timestamp,
231
+ name: 'tool_result',
232
+ attributes: {
233
+ 'tool.result': truncate(event.content),
234
+ 'tool.result.is_error': event.isError ?? false,
235
+ },
236
+ },
237
+ ];
238
+ call.status = event.isError ? { code: 'ERROR' } : { code: 'OK' };
239
+ break;
240
+ }
241
+ default:
242
+ break;
243
+ }
244
+ }
245
+ const usage = findTerminalUsage(rawText);
246
+ if (usage && agentTurns.length > 0) {
247
+ const last = agentTurns[agentTurns.length - 1];
248
+ last.attributes['gen_ai.usage.input_tokens'] = usage.inputTokens;
249
+ last.attributes['gen_ai.usage.output_tokens'] = usage.outputTokens;
250
+ }
251
+ return spans;
252
+ }
253
+ }
@@ -0,0 +1,4 @@
1
+ export * from './attrs.js';
2
+ export * from './claude-code-stream-json.js';
3
+ export * from './codex-exec-json.js';
4
+ export * from './types.js';
@@ -0,0 +1,4 @@
1
+ export * from './attrs.js';
2
+ export * from './claude-code-stream-json.js';
3
+ export * from './codex-exec-json.js';
4
+ export * from './types.js';
@@ -0,0 +1,18 @@
1
+ import type { Span } from '../schema.js';
2
+ /** A canonical typed trajectory span before collector-assigned ids and chaining. */
3
+ export type TranscriptSpanInput = Omit<Span, 'traceId' | 'spanId' | 'parentSpanId'> & {
4
+ parentSpanId?: string | null;
5
+ };
6
+ /**
7
+ * Converts a native harness transcript to canonical typed trajectory spans.
8
+ * File parsing always degrades to an empty list. Parsers that can safely
9
+ * consume in-memory snapshot bytes expose the same implementation via
10
+ * `parseText`.
11
+ */
12
+ export interface TranscriptSpanParser {
13
+ readonly sourceFormat: string;
14
+ readonly parserName: string;
15
+ readonly parserVersion: string;
16
+ parse(transcriptPath: string): Promise<TranscriptSpanInput[]>;
17
+ parseText?(rawText: string): TranscriptSpanInput[];
18
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,12 @@
1
+ import { z } from 'zod/v3';
2
+ export declare const WindowSchema: z.ZodObject<{
3
+ startTs: z.ZodNumber;
4
+ endTs: z.ZodNumber;
5
+ }, "strip", z.ZodTypeAny, {
6
+ startTs: number;
7
+ endTs: number;
8
+ }, {
9
+ startTs: number;
10
+ endTs: number;
11
+ }>;
12
+ export type Window = z.infer<typeof WindowSchema>;
package/dist/window.js ADDED
@@ -0,0 +1,5 @@
1
+ import { z } from 'zod/v3';
2
+ export const WindowSchema = z.object({
3
+ startTs: z.number().int(),
4
+ endTs: z.number().int(),
5
+ });
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@jinn-network/core",
3
+ "version": "0.1.0",
4
+ "description": "Domain core for Jinn — evidence/contribution stores, scrub, trajectory parsing, and corpus reads. Independent of client/src.",
5
+ "type": "module",
6
+ "packageManager": "yarn@4.13.0",
7
+ "license": "MIT",
8
+ "main": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "files": [
11
+ "dist/"
12
+ ],
13
+ "publishConfig": {
14
+ "access": "public"
15
+ },
16
+ "exports": {
17
+ ".": {
18
+ "import": "./dist/index.js",
19
+ "types": "./dist/index.d.ts"
20
+ },
21
+ "./corpus-read": {
22
+ "import": "./dist/corpus-read/index.js",
23
+ "types": "./dist/corpus-read/index.d.ts"
24
+ },
25
+ "./scrub": {
26
+ "import": "./dist/scrub/index.js",
27
+ "types": "./dist/scrub/index.d.ts"
28
+ },
29
+ "./trajectory": {
30
+ "import": "./dist/trajectory/index.js",
31
+ "types": "./dist/trajectory/index.d.ts"
32
+ }
33
+ },
34
+ "scripts": {
35
+ "build": "tsc -p tsconfig.json",
36
+ "typecheck": "tsc --noEmit -p tsconfig.json",
37
+ "test": "vitest run"
38
+ },
39
+ "dependencies": {
40
+ "@huggingface/transformers": "^4.2.0",
41
+ "@jinn-network/plugin": "0.1.0",
42
+ "@noble/hashes": "^2.2.0",
43
+ "@secretlint/core": "^13.0.2",
44
+ "@secretlint/secretlint-rule-preset-recommend": "^13.0.2",
45
+ "better-sqlite3": "^12.10.0",
46
+ "canonicalize": "^3.0.0",
47
+ "openredaction": "^1.1.2",
48
+ "zod": "^4.4.3"
49
+ },
50
+ "peerDependencies": {
51
+ "vitest": "^4.1.8"
52
+ },
53
+ "peerDependenciesMeta": {
54
+ "vitest": {
55
+ "optional": true
56
+ }
57
+ },
58
+ "devDependencies": {
59
+ "@types/better-sqlite3": "^7.6.0",
60
+ "@types/node": "^26.1.0",
61
+ "typescript": "^5.4.0",
62
+ "vitest": "^4.1.8"
63
+ },
64
+ "resolutions": {
65
+ "@jinn-network/plugin": "portal:../plugin"
66
+ }
67
+ }