@molecule/api-agent-transcript-copilot-chat 1.0.0 → 1.0.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.
package/README.md ADDED
@@ -0,0 +1,126 @@
1
+ <!--
2
+ AUTO-GENERATED — DO NOT EDIT THIS FILE.
3
+ Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
4
+ Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
5
+ To change this document, edit the module-level JSDoc in src/index.ts.
6
+ Generated: 2026-09-29T16:49:57.282Z
7
+ -->
8
+
9
+ # @molecule/api-agent-transcript-copilot-chat
10
+
11
+ > **Auto-generated, AI-first package reference** for the [molecule.dev](https://molecule.dev) ecosystem.
12
+ > It is written to be read by coding agents as much as by people, and is generated from this
13
+ > package's source — edit `src/index.ts` JSDoc, not this file.
14
+
15
+ GitHub Copilot Chat transcript reader for `@molecule/api-agent-transcript`.
16
+
17
+ Reads the `chat.json` VS Code saves from "Chat: Export Chat…" (Command
18
+ Palette, or the chat view's ⋯ menu) into a normalized `AgentSession`: each
19
+ request as you typed it, each response's markdown, the model that answered,
20
+ and the files the response edited.
21
+
22
+ ## Quick Start
23
+
24
+ ```typescript
25
+ import { readFileSync } from 'node:fs'
26
+ import { readTranscript, setProvider } from '@molecule/api-agent-transcript'
27
+ import { provider } from '@molecule/api-agent-transcript-copilot-chat'
28
+
29
+ setProvider(provider)
30
+ const file = 'chat.json'
31
+ const session = readTranscript({ text: readFileSync(file, 'utf8'), fileName: file })
32
+ console.log(session.harness, session.model) // 'GitHub Copilot Chat', 'copilot/…'
33
+ ```
34
+
35
+ ## Type
36
+
37
+ `provider`
38
+
39
+ ## Installation
40
+
41
+ ```bash
42
+ npm install @molecule/api-agent-transcript-copilot-chat @molecule/api-agent-transcript
43
+ ```
44
+
45
+ ## API
46
+
47
+ ### Functions
48
+
49
+ #### `looksLikeChatExport(text)`
50
+
51
+ Whether a text is a VS Code chat export.
52
+
53
+ ```typescript
54
+ function looksLikeChatExport(text: string): boolean
55
+ ```
56
+
57
+ - `text` — The file's text.
58
+
59
+ **Returns:** True on a positive match.
60
+
61
+ #### `readChatExport(text)`
62
+
63
+ Read a VS Code chat export.
64
+
65
+ ```typescript
66
+ function readChatExport(text: string): AgentSession
67
+ ```
68
+
69
+ - `text` — The export's text.
70
+
71
+ **Returns:** The normalized session.
72
+
73
+ ### Constants
74
+
75
+ #### `provider`
76
+
77
+ Reads the JSON VS Code's "Chat: Export Chat…" saves.
78
+
79
+ ```typescript
80
+ const provider: AgentTranscriptReader
81
+ ```
82
+
83
+ ## Core Interface
84
+
85
+ Implements `@molecule/api-agent-transcript` interface.
86
+
87
+ ## Bond Wiring
88
+
89
+ Setup function to register this provider with the core interface:
90
+
91
+ ```typescript
92
+ import { setProvider } from '@molecule/api-agent-transcript'
93
+ import { provider } from '@molecule/api-agent-transcript-copilot-chat'
94
+
95
+ export function setupAgentTranscriptCopilotChat(): void {
96
+ setProvider(provider)
97
+ }
98
+ ```
99
+
100
+ ## Injection Notes
101
+
102
+ ### Requirements
103
+
104
+ Peer dependencies:
105
+
106
+ - `@molecule/api-agent-transcript` ^1.0.0
107
+
108
+ ### Runtime Dependencies
109
+
110
+ - `@molecule/api-agent-transcript`
111
+
112
+ - **The export is VS Code's, not Copilot's**, so any chat participant's
113
+ export reads the same way. `harness` is `GitHub Copilot Chat` when the
114
+ responder is Copilot, otherwise `VS Code Chat (<responder>)`.
115
+ - `model` on each reply is the request's `modelId` as VS Code records it
116
+ (e.g. `copilot/gpt-5.3`); the session's `model` is set when every reply
117
+ used the same one.
118
+ - Reply text is the response's markdown with inline file references
119
+ written as `` `name` ``; thinking, tool-invocation and progress parts are
120
+ not prose.
121
+ - Files: each `textEditGroup` part is an edit, its text the inserted text
122
+ of every edit in the group. Requests VS Code started itself
123
+ (`isSystemInitiated`) contribute their reply but no user turn; requests
124
+ hidden from the transcript are skipped.
125
+ - Format verified 2026-09-29 against the VS Code source
126
+ (`chatImportExport.ts`, `chatModel.ts` `toExport()`).
@@ -0,0 +1,53 @@
1
+ /**
2
+ * VS Code's chat export — the JSON "Chat: Export Chat…" saves
3
+ * (`chat.json`) from GitHub Copilot Chat or any other chat participant.
4
+ * Verified 2026-09-29 against microsoft/vscode `main`:
5
+ * `src/vs/workbench/contrib/chat/browser/actions/chatImportExport.ts`
6
+ * (writes `JSON.stringify(model.toExport())`) and
7
+ * `src/vs/workbench/contrib/chat/common/model/chatModel.ts`
8
+ * (`IExportableChatData`, `ISerializableChatRequestData`, `toExport()`).
9
+ *
10
+ * ```json
11
+ * {
12
+ * "initialLocation": "panel",
13
+ * "responderUsername": "GitHub Copilot",
14
+ * "requests": [
15
+ * {
16
+ * "requestId": "request_…",
17
+ * "message": { "text": "the message as typed", "parts": [ … ] },
18
+ * "timestamp": 1790582400000,
19
+ * "modelId": "copilot/gpt-5.3",
20
+ * "response": [
21
+ * { "value": "markdown…" },
22
+ * { "kind": "inlineReference", "inlineReference": { "path": "/src/app.ts", … }, "name"?: "…" },
23
+ * { "kind": "textEditGroup", "uri": { "path": "/src/app.ts", … }, "edits": [[{ "range": …, "text": "…" }]] },
24
+ * { "kind": "toolInvocationSerialized", … }
25
+ * ]
26
+ * }
27
+ * ]
28
+ * }
29
+ * ```
30
+ *
31
+ * A response is a list of parts: markdown is written as a bare
32
+ * `IMarkdownString` (`{ value }`, no `kind`), everything else keeps its
33
+ * `kind`. Older exports stored `message` as a plain string.
34
+ *
35
+ * @module
36
+ */
37
+ import type { AgentSession } from '@molecule/api-agent-transcript';
38
+ /**
39
+ * Whether a text is a VS Code chat export.
40
+ *
41
+ * @param text - The file's text.
42
+ * @returns True on a positive match.
43
+ */
44
+ export declare function looksLikeChatExport(text: string): boolean;
45
+ /**
46
+ * Read a VS Code chat export.
47
+ *
48
+ * @param text - The export's text.
49
+ * @returns The normalized session.
50
+ * @throws {Error} When the text is not an export.
51
+ */
52
+ export declare function readChatExport(text: string): AgentSession;
53
+ //# sourceMappingURL=export.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../src/export.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,KAAK,EAAkB,YAAY,EAAa,MAAM,gCAAgC,CAAA;AAoD7F;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AA0DD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAuCzD"}
package/dist/export.js ADDED
@@ -0,0 +1,173 @@
1
+ /**
2
+ * VS Code's chat export — the JSON "Chat: Export Chat…" saves
3
+ * (`chat.json`) from GitHub Copilot Chat or any other chat participant.
4
+ * Verified 2026-09-29 against microsoft/vscode `main`:
5
+ * `src/vs/workbench/contrib/chat/browser/actions/chatImportExport.ts`
6
+ * (writes `JSON.stringify(model.toExport())`) and
7
+ * `src/vs/workbench/contrib/chat/common/model/chatModel.ts`
8
+ * (`IExportableChatData`, `ISerializableChatRequestData`, `toExport()`).
9
+ *
10
+ * ```json
11
+ * {
12
+ * "initialLocation": "panel",
13
+ * "responderUsername": "GitHub Copilot",
14
+ * "requests": [
15
+ * {
16
+ * "requestId": "request_…",
17
+ * "message": { "text": "the message as typed", "parts": [ … ] },
18
+ * "timestamp": 1790582400000,
19
+ * "modelId": "copilot/gpt-5.3",
20
+ * "response": [
21
+ * { "value": "markdown…" },
22
+ * { "kind": "inlineReference", "inlineReference": { "path": "/src/app.ts", … }, "name"?: "…" },
23
+ * { "kind": "textEditGroup", "uri": { "path": "/src/app.ts", … }, "edits": [[{ "range": …, "text": "…" }]] },
24
+ * { "kind": "toolInvocationSerialized", … }
25
+ * ]
26
+ * }
27
+ * ]
28
+ * }
29
+ * ```
30
+ *
31
+ * A response is a list of parts: markdown is written as a bare
32
+ * `IMarkdownString` (`{ value }`, no `kind`), everything else keeps its
33
+ * `kind`. Older exports stored `message` as a plain string.
34
+ *
35
+ * @module
36
+ */
37
+ /**
38
+ * The export, when the text is one.
39
+ *
40
+ * @param text - The file's text.
41
+ * @returns The export, or `null`.
42
+ */
43
+ function parse(text) {
44
+ const trimmed = text.trim();
45
+ if (!trimmed.startsWith('{'))
46
+ return null;
47
+ let v;
48
+ try {
49
+ v = JSON.parse(trimmed);
50
+ }
51
+ catch (_error) {
52
+ // Not JSON: not an export.
53
+ return null;
54
+ }
55
+ const e = v;
56
+ if (!e || typeof e.responderUsername !== 'string' || !Array.isArray(e.requests))
57
+ return null;
58
+ const ok = e.requests.every((r) => r &&
59
+ typeof r === 'object' &&
60
+ (typeof r.message === 'string' || (typeof r.message === 'object' && r.message !== null)) &&
61
+ (r.response === undefined || r.response === null || Array.isArray(r.response)));
62
+ return ok ? e : null;
63
+ }
64
+ /**
65
+ * Whether a text is a VS Code chat export.
66
+ *
67
+ * @param text - The file's text.
68
+ * @returns True on a positive match.
69
+ */
70
+ export function looksLikeChatExport(text) {
71
+ return parse(text) !== null;
72
+ }
73
+ /**
74
+ * The path a serialized URI (or location) points at.
75
+ *
76
+ * @param v - The URI, or a `{ uri, range }` location.
77
+ * @returns The path, or ''.
78
+ */
79
+ function pathOf(v) {
80
+ const u = v;
81
+ if (!u || typeof u !== 'object')
82
+ return '';
83
+ if (u.uri)
84
+ return pathOf(u.uri);
85
+ return u.fsPath ?? u.path ?? '';
86
+ }
87
+ /**
88
+ * The prose and files of one response.
89
+ *
90
+ * @param parts - The response parts.
91
+ * @returns The reply's text and writes.
92
+ */
93
+ function readResponse(parts) {
94
+ let text = '';
95
+ const files = [];
96
+ for (const raw of parts) {
97
+ const p = raw;
98
+ if (!p || typeof p !== 'object')
99
+ continue;
100
+ if (p.kind === undefined && typeof p.value === 'string') {
101
+ text += p.value;
102
+ }
103
+ else if (p.kind === 'inlineReference') {
104
+ const path = pathOf(p.inlineReference);
105
+ const label = p.name ?? path.split('/').pop() ?? '';
106
+ if (label)
107
+ text += `\`${label}\``;
108
+ }
109
+ else if (p.kind === 'textEditGroup') {
110
+ const path = pathOf(p.uri);
111
+ const groups = Array.isArray(p.edits) ? p.edits : [];
112
+ const inserted = groups
113
+ .flatMap((g) => (Array.isArray(g) ? g : []))
114
+ .map((e) => e && typeof e.text === 'string'
115
+ ? e.text
116
+ : '')
117
+ .filter(Boolean);
118
+ if (path && inserted.length)
119
+ files.push({ path, kind: 'edit', text: inserted.join('\n'), complete: true });
120
+ }
121
+ }
122
+ return { text: text.trim(), files };
123
+ }
124
+ /**
125
+ * Read a VS Code chat export.
126
+ *
127
+ * @param text - The export's text.
128
+ * @returns The normalized session.
129
+ * @throws {Error} When the text is not an export.
130
+ */
131
+ export function readChatExport(text) {
132
+ const e = parse(text);
133
+ if (!e)
134
+ throw new Error('Not a VS Code chat export.');
135
+ const turns = [];
136
+ const iso = (ms) => typeof ms === 'number' ? new Date(ms).toISOString() : undefined;
137
+ for (const r of e.requests) {
138
+ if (r.hiddenFromTranscript)
139
+ continue;
140
+ const said = (typeof r.message === 'string' ? r.message : (r.message?.text ?? '')).trim();
141
+ if (said && !r.isSystemInitiated) {
142
+ turns.push({ role: 'user', text: said, timestamp: iso(r.timestamp), files: [] });
143
+ }
144
+ const { text: reply, files } = readResponse(r.response ?? []);
145
+ if (reply || files.length) {
146
+ const last = turns[turns.length - 1];
147
+ if (last && last.role === 'assistant') {
148
+ last.text = [last.text, reply].filter(Boolean).join('\n\n');
149
+ last.files.push(...files);
150
+ }
151
+ else {
152
+ turns.push({
153
+ role: 'assistant',
154
+ text: reply,
155
+ timestamp: iso(r.timestamp),
156
+ model: r.modelId,
157
+ files,
158
+ });
159
+ }
160
+ }
161
+ }
162
+ const copilot = /copilot/i.test(e.responderUsername);
163
+ const session = {
164
+ format: 'copilot-chat',
165
+ harness: copilot ? 'GitHub Copilot Chat' : `VS Code Chat (${e.responderUsername})`,
166
+ startedAt: turns[0]?.timestamp,
167
+ turns,
168
+ };
169
+ const models = new Set(turns.map((t) => t.model).filter(Boolean));
170
+ if (models.size === 1)
171
+ session.model = [...models][0];
172
+ return session;
173
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * GitHub Copilot Chat transcript reader for `@molecule/api-agent-transcript`.
3
+ *
4
+ * Reads the `chat.json` VS Code saves from "Chat: Export Chat…" (Command
5
+ * Palette, or the chat view's ⋯ menu) into a normalized `AgentSession`: each
6
+ * request as you typed it, each response's markdown, the model that answered,
7
+ * and the files the response edited.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * import { readFileSync } from 'node:fs'
12
+ * import { readTranscript, setProvider } from '@molecule/api-agent-transcript'
13
+ * import { provider } from '@molecule/api-agent-transcript-copilot-chat'
14
+ *
15
+ * setProvider(provider)
16
+ * const file = 'chat.json'
17
+ * const session = readTranscript({ text: readFileSync(file, 'utf8'), fileName: file })
18
+ * console.log(session.harness, session.model) // 'GitHub Copilot Chat', 'copilot/…'
19
+ * ```
20
+ *
21
+ * @remarks
22
+ * - **The export is VS Code's, not Copilot's**, so any chat participant's
23
+ * export reads the same way. `harness` is `GitHub Copilot Chat` when the
24
+ * responder is Copilot, otherwise `VS Code Chat (<responder>)`.
25
+ * - `model` on each reply is the request's `modelId` as VS Code records it
26
+ * (e.g. `copilot/gpt-5.3`); the session's `model` is set when every reply
27
+ * used the same one.
28
+ * - Reply text is the response's markdown with inline file references
29
+ * written as `` `name` ``; thinking, tool-invocation and progress parts are
30
+ * not prose.
31
+ * - Files: each `textEditGroup` part is an edit, its text the inserted text
32
+ * of every edit in the group. Requests VS Code started itself
33
+ * (`isSystemInitiated`) contribute their reply but no user turn; requests
34
+ * hidden from the transcript are skipped.
35
+ * - Format verified 2026-09-29 against the VS Code source
36
+ * (`chatImportExport.ts`, `chatModel.ts` `toExport()`).
37
+ *
38
+ * @module
39
+ */
40
+ export * from './browser-guard.js';
41
+ export * from './export.js';
42
+ export * from './provider.js';
43
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,cAAc,oBAAoB,CAAA;AAClC,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,42 @@
1
+ /**
2
+ * GitHub Copilot Chat transcript reader for `@molecule/api-agent-transcript`.
3
+ *
4
+ * Reads the `chat.json` VS Code saves from "Chat: Export Chat…" (Command
5
+ * Palette, or the chat view's ⋯ menu) into a normalized `AgentSession`: each
6
+ * request as you typed it, each response's markdown, the model that answered,
7
+ * and the files the response edited.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * import { readFileSync } from 'node:fs'
12
+ * import { readTranscript, setProvider } from '@molecule/api-agent-transcript'
13
+ * import { provider } from '@molecule/api-agent-transcript-copilot-chat'
14
+ *
15
+ * setProvider(provider)
16
+ * const file = 'chat.json'
17
+ * const session = readTranscript({ text: readFileSync(file, 'utf8'), fileName: file })
18
+ * console.log(session.harness, session.model) // 'GitHub Copilot Chat', 'copilot/…'
19
+ * ```
20
+ *
21
+ * @remarks
22
+ * - **The export is VS Code's, not Copilot's**, so any chat participant's
23
+ * export reads the same way. `harness` is `GitHub Copilot Chat` when the
24
+ * responder is Copilot, otherwise `VS Code Chat (<responder>)`.
25
+ * - `model` on each reply is the request's `modelId` as VS Code records it
26
+ * (e.g. `copilot/gpt-5.3`); the session's `model` is set when every reply
27
+ * used the same one.
28
+ * - Reply text is the response's markdown with inline file references
29
+ * written as `` `name` ``; thinking, tool-invocation and progress parts are
30
+ * not prose.
31
+ * - Files: each `textEditGroup` part is an edit, its text the inserted text
32
+ * of every edit in the group. Requests VS Code started itself
33
+ * (`isSystemInitiated`) contribute their reply but no user turn; requests
34
+ * hidden from the transcript are skipped.
35
+ * - Format verified 2026-09-29 against the VS Code source
36
+ * (`chatImportExport.ts`, `chatModel.ts` `toExport()`).
37
+ *
38
+ * @module
39
+ */
40
+ export * from './browser-guard.js';
41
+ export * from './export.js';
42
+ export * from './provider.js';
@@ -0,0 +1,11 @@
1
+ /**
2
+ * The GitHub Copilot Chat (VS Code chat export) transcript reader.
3
+ *
4
+ * @module
5
+ */
6
+ import type { AgentTranscriptReader } from '@molecule/api-agent-transcript';
7
+ /**
8
+ * Reads the JSON VS Code's "Chat: Export Chat…" saves.
9
+ */
10
+ export declare const provider: AgentTranscriptReader;
11
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAEV,qBAAqB,EAEtB,MAAM,gCAAgC,CAAA;AAIvC;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,qBActB,CAAA"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * The GitHub Copilot Chat (VS Code chat export) transcript reader.
3
+ *
4
+ * @module
5
+ */
6
+ import { looksLikeChatExport, readChatExport } from './export.js';
7
+ /**
8
+ * Reads the JSON VS Code's "Chat: Export Chat…" saves.
9
+ */
10
+ export const provider = {
11
+ format: 'copilot-chat',
12
+ label: 'GitHub Copilot Chat',
13
+ detect(input) {
14
+ return looksLikeChatExport(input.text);
15
+ },
16
+ read(input) {
17
+ if (!looksLikeChatExport(input.text)) {
18
+ throw new Error(`Not a GitHub Copilot Chat transcript${input.fileName ? ` (${input.fileName})` : ''}: expected the chat.json VS Code's "Export Chat…" saves.`);
19
+ }
20
+ return readChatExport(input.text);
21
+ },
22
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@molecule/api-agent-transcript-copilot-chat",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Reads VS Code GitHub Copilot Chat exports (Chat: Export Chat…) into a normalized agent session",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",