@extenshi/mcp 0.22.1 → 0.23.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
@@ -124,6 +124,9 @@ stdio or CLI. See the [development workflow](https://docs.extenshi.io/developers
124
124
  | `generate_landing_page` | Static landing-page (homepage) HTML with no JavaScript — same generator as the cabinet Page generator; returns `{html, bytes, warnings, nextSteps}`. Host it on any HTTPS origin and register the URL with `upsert_hosted_page` (feeds `HOMEPAGE_URL`) | Free (no key) |
125
125
  | `scan_extension` | Pre-publish security scan of a local artifact (.zip/.crx/.xpi), with live progress | 1 scan |
126
126
  | `publish_extension` | Publish to Chrome/Firefox/Edge with your own store credentials (fully local) | Free |
127
+ | `get_build_map` | The author's build map of `projectDir` (`npx @extenshi/cli map`): progress, steps waiting on the author, steps that can start now, every step's current task, and the variants offered with the author's answer. Local server only | Free (no key) |
128
+ | `report_build_step` | Report on a build map step (start, progress, done with hashed file proof, stop), or record the author's answer from the chat (`choice` / `redo`). Local server only | Free (no key) |
129
+ | `request_build_review` | Offer the author 1–8 variants to choose from on the map (icon concepts, screenshots, listing copy), each a preview page or image in the project; returns the link to the step. Local server only | Free (no key) |
127
130
 
128
131
  ### Identifying an extension by its store id
129
132
 
@@ -0,0 +1,117 @@
1
+ /**
2
+ * What an agent does on the build map (plan 2026-11-03-extension-build-map
3
+ * §6.3–6.4, phase 2): report a step, offer the author variants to choose from,
4
+ * record the author's answer from the chat, and wait for the author's answer.
5
+ *
6
+ * The CLI (`extenshi map step|review|choose|wait`) and the stdio MCP server
7
+ * (`report_build_step`, `request_build_review`, `get_build_map`) both call
8
+ * these. Every write goes through updateMapState, so it lands in the one map of
9
+ * the project from whichever worktree the agent works in, and an open page shows
10
+ * it within a second. The MCP server ships a byte-identical copy of this file
11
+ * next to its copy of build-map-store.ts; build-map-store-sync.test.ts there
12
+ * fails on any drift. Edit this file, then copy it over.
13
+ *
14
+ * Files an agent names are resolved here. Evidence files are hashed, so the
15
+ * journal entry is `checked`. A variant's preview and image must be files of
16
+ * the project, in the main checkout or any of its worktrees, or https
17
+ * addresses. The map server serves those files only for a variant that names
18
+ * them (reviewFileOnDisk), so naming a file elsewhere is refused up front.
19
+ */
20
+ import { type BuildEvidenceWhere, type BuildMapView, type BuildNodeRecord, type BuildReview, type BuildStepReport } from '@extenshi/contracts';
21
+ /** The file types a variant's preview or image may be, with the type the map server answers with. */
22
+ export declare const REVIEW_FILE_TYPES: Readonly<Record<string, string>>;
23
+ export declare const REVIEW_FILE_MAX_BYTES: number;
24
+ /**
25
+ * Where a variant's preview or image is, as the state file keeps it: an https
26
+ * address as given; a file relative to `home` when it is in the main checkout,
27
+ * absolute when it is in another checkout of the project. Throws for anything
28
+ * else, with what to do instead.
29
+ */
30
+ export declare function resolveReviewFile(home: string, from: string, value: string): Promise<string>;
31
+ /**
32
+ * The file behind a variant's preview or image, if the map may serve it: it
33
+ * is a file of a checkout of the project, of a type in REVIEW_FILE_TYPES, and
34
+ * not too big. Checked again at every request, since files change.
35
+ */
36
+ export declare function reviewFileOnDisk(home: string, stored: string): Promise<{
37
+ file: string;
38
+ type: string;
39
+ bytes: number;
40
+ } | undefined>;
41
+ /** Evidence files hashed: relative to `home` when inside it, absolute otherwise. Throws for a file that is not there. */
42
+ export declare function evidenceFiles(home: string, from: string, files: readonly string[]): Promise<BuildEvidenceWhere[]>;
43
+ /**
44
+ * The map as the running map server derives it: with the project facts and
45
+ * the bound Dojo project. Undefined when no server runs or it does not answer.
46
+ */
47
+ export declare function serverSnapshot(home: string): Promise<{
48
+ url: string;
49
+ snapshot: {
50
+ view: BuildMapView;
51
+ } & Record<string, unknown>;
52
+ } | undefined>;
53
+ /** The address that opens one step on the map. */
54
+ export declare const stepUrl: (url: string, node: string) => string;
55
+ export type StepInput = Omit<BuildStepReport, 'at' | 'where' | 'checked'> & {
56
+ /** Files that show the task done: hashed, so the entry is checked. */
57
+ files?: readonly string[];
58
+ urls?: readonly string[];
59
+ dojo?: readonly string[];
60
+ command?: string;
61
+ };
62
+ /**
63
+ * Report on a step. `view` checks that the step's inputs are done; without it
64
+ * (no project facts) nothing is refused for that. The entry is `checked` when
65
+ * every proof is a file this call hashed.
66
+ */
67
+ export declare function reportStep(home: string, from: string, input: StepInput, view?: BuildMapView): Promise<{
68
+ record: BuildNodeRecord | undefined;
69
+ checked: boolean;
70
+ }>;
71
+ export type VariantInput = {
72
+ label: string;
73
+ preview: string;
74
+ image?: string;
75
+ };
76
+ /** Offer the author variants to choose from; files are resolved against `from`. */
77
+ export declare function openReview(home: string, from: string, input: {
78
+ node: string;
79
+ agent: string;
80
+ variants: readonly VariantInput[];
81
+ }, view?: BuildMapView): Promise<BuildReview>;
82
+ /** Record the author's answer from the chat: the variant they picked, or what to change. */
83
+ export declare function answerReview(home: string, input: {
84
+ node: string;
85
+ agent: string;
86
+ choice?: string;
87
+ redo?: string;
88
+ round?: number;
89
+ }, view?: BuildMapView): Promise<BuildReview>;
90
+ export type ReviewAnswer = {
91
+ node: string;
92
+ round: number;
93
+ status: BuildReview['status'];
94
+ /** The variant picked. */
95
+ choice?: {
96
+ id: string;
97
+ label: string;
98
+ preview: string;
99
+ image?: string;
100
+ };
101
+ /** What to change, in the author's words. */
102
+ feedback?: string;
103
+ via?: 'map' | 'chat';
104
+ };
105
+ export declare function reviewAnswer(node: string, review: BuildReview): ReviewAnswer;
106
+ /**
107
+ * Wait until the author answers the review of `node`, reading the state file
108
+ * every `pollMs` (no map server needed). Resolves at once when it is answered
109
+ * already; with `timeoutMs`, resolves with the review still waiting once that
110
+ * passes.
111
+ */
112
+ export declare function waitForReview(home: string, node: string, options?: {
113
+ timeoutMs?: number;
114
+ pollMs?: number;
115
+ signal?: AbortSignal;
116
+ }): Promise<ReviewAnswer>;
117
+ //# sourceMappingURL=build-map-agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-map-agent.d.ts","sourceRoot":"","sources":["../src/build-map-agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,242 @@
1
+ /**
2
+ * What an agent does on the build map (plan 2026-11-03-extension-build-map
3
+ * §6.3–6.4, phase 2): report a step, offer the author variants to choose from,
4
+ * record the author's answer from the chat, and wait for the author's answer.
5
+ *
6
+ * The CLI (`extenshi map step|review|choose|wait`) and the stdio MCP server
7
+ * (`report_build_step`, `request_build_review`, `get_build_map`) both call
8
+ * these. Every write goes through updateMapState, so it lands in the one map of
9
+ * the project from whichever worktree the agent works in, and an open page shows
10
+ * it within a second. The MCP server ships a byte-identical copy of this file
11
+ * next to its copy of build-map-store.ts; build-map-store-sync.test.ts there
12
+ * fails on any drift. Edit this file, then copy it over.
13
+ *
14
+ * Files an agent names are resolved here. Evidence files are hashed, so the
15
+ * journal entry is `checked`. A variant's preview and image must be files of
16
+ * the project, in the main checkout or any of its worktrees, or https
17
+ * addresses. The map server serves those files only for a variant that names
18
+ * them (reviewFileOnDisk), so naming a file elsewhere is refused up front.
19
+ */
20
+ import { createHash } from 'node:crypto';
21
+ import { createReadStream } from 'node:fs';
22
+ import { realpath, stat } from 'node:fs/promises';
23
+ import path from 'node:path';
24
+ import { answerBuildReview, buildReviewLocationValid, openBuildReview, reportBuildStep, } from '@extenshi/contracts';
25
+ import { probeServer, projectCheckouts, readMapState, updateMapState } from './build-map-store.js';
26
+ /** The file types a variant's preview or image may be, with the type the map server answers with. */
27
+ export const REVIEW_FILE_TYPES = {
28
+ '.html': 'text/html; charset=utf-8',
29
+ '.htm': 'text/html; charset=utf-8',
30
+ '.svg': 'image/svg+xml',
31
+ '.png': 'image/png',
32
+ '.jpg': 'image/jpeg',
33
+ '.jpeg': 'image/jpeg',
34
+ '.webp': 'image/webp',
35
+ '.gif': 'image/gif',
36
+ };
37
+ export const REVIEW_FILE_MAX_BYTES = 20 * 1024 * 1024;
38
+ /** Evidence files bigger than this are refused rather than hashed for minutes. */
39
+ const EVIDENCE_FILE_MAX_BYTES = 64 * 1024 * 1024;
40
+ const isHttps = (value) => /^https:\/\//i.test(value);
41
+ const hasScheme = (value) => /^[a-z][a-z0-9+.-]*:\/\//i.test(value);
42
+ function inside(root, file) {
43
+ const relative = path.relative(root, file);
44
+ return relative !== '' && !relative.startsWith('..') && !path.isAbsolute(relative);
45
+ }
46
+ /** The project directory in every checkout of the repository, resolved: the map home first. */
47
+ async function checkoutRoots(home) {
48
+ const roots = [];
49
+ for (const dir of await projectCheckouts(home)) {
50
+ try {
51
+ const real = await realpath(dir);
52
+ if (!roots.includes(real))
53
+ roots.push(real);
54
+ }
55
+ catch {
56
+ // A worktree removed since git listed it.
57
+ }
58
+ }
59
+ return roots.length ? roots : [home];
60
+ }
61
+ async function sha256Of(file) {
62
+ const hash = createHash('sha256');
63
+ for await (const chunk of createReadStream(file))
64
+ hash.update(chunk);
65
+ return hash.digest('hex');
66
+ }
67
+ /**
68
+ * Where a variant's preview or image is, as the state file keeps it: an https
69
+ * address as given; a file relative to `home` when it is in the main checkout,
70
+ * absolute when it is in another checkout of the project. Throws for anything
71
+ * else, with what to do instead.
72
+ */
73
+ export async function resolveReviewFile(home, from, value) {
74
+ const given = value.trim();
75
+ if (hasScheme(given)) {
76
+ if (isHttps(given) && buildReviewLocationValid(given))
77
+ return given;
78
+ throw new Error(`${given}: a preview is a file of the project or an https address.`);
79
+ }
80
+ let real;
81
+ try {
82
+ real = await realpath(path.resolve(from, given));
83
+ }
84
+ catch {
85
+ throw new Error(`${given}: no such file.`);
86
+ }
87
+ const type = REVIEW_FILE_TYPES[path.extname(real).toLowerCase()];
88
+ if (!type)
89
+ throw new Error(`${given}: a preview is an HTML page or an image (${Object.keys(REVIEW_FILE_TYPES).join(', ')}).`);
90
+ const info = await stat(real);
91
+ if (!info.isFile())
92
+ throw new Error(`${given}: not a file.`);
93
+ if (info.size > REVIEW_FILE_MAX_BYTES)
94
+ throw new Error(`${given}: larger than ${REVIEW_FILE_MAX_BYTES / 1024 / 1024} MB.`);
95
+ if (inside(home, real))
96
+ return path.relative(home, real);
97
+ // Asking git for the other checkouts costs a process or two: only for a file outside the main one.
98
+ if ((await checkoutRoots(home)).some((root) => inside(root, real)))
99
+ return real;
100
+ throw new Error(`${given}: outside the project, so the map will not serve it. Write the preview inside the project (any of its git worktrees works).`);
101
+ }
102
+ /**
103
+ * The file behind a variant's preview or image, if the map may serve it: it
104
+ * is a file of a checkout of the project, of a type in REVIEW_FILE_TYPES, and
105
+ * not too big. Checked again at every request, since files change.
106
+ */
107
+ export async function reviewFileOnDisk(home, stored) {
108
+ if (!buildReviewLocationValid(stored) || hasScheme(stored))
109
+ return undefined;
110
+ try {
111
+ const real = await realpath(path.isAbsolute(stored) ? stored : path.join(home, stored));
112
+ const type = REVIEW_FILE_TYPES[path.extname(real).toLowerCase()];
113
+ if (!type)
114
+ return undefined;
115
+ const info = await stat(real);
116
+ if (!info.isFile() || info.size > REVIEW_FILE_MAX_BYTES)
117
+ return undefined;
118
+ if (!inside(home, real) && !(await checkoutRoots(home)).some((root) => inside(root, real)))
119
+ return undefined;
120
+ return { file: real, type, bytes: info.size };
121
+ }
122
+ catch {
123
+ return undefined;
124
+ }
125
+ }
126
+ /** Evidence files hashed: relative to `home` when inside it, absolute otherwise. Throws for a file that is not there. */
127
+ export async function evidenceFiles(home, from, files) {
128
+ const where = [];
129
+ for (const given of files) {
130
+ const absolute = path.resolve(from, given);
131
+ let info;
132
+ try {
133
+ info = await stat(absolute);
134
+ }
135
+ catch {
136
+ throw new Error(`${given}: no such file.`);
137
+ }
138
+ if (!info.isFile())
139
+ throw new Error(`${given}: not a file.`);
140
+ if (info.size > EVIDENCE_FILE_MAX_BYTES)
141
+ throw new Error(`${given}: larger than ${EVIDENCE_FILE_MAX_BYTES / 1024 / 1024} MB; name a smaller file as proof.`);
142
+ const real = await realpath(absolute);
143
+ where.push({ file: inside(home, real) ? path.relative(home, real) : real, sha256: await sha256Of(real) });
144
+ }
145
+ return where;
146
+ }
147
+ /**
148
+ * The map as the running map server derives it: with the project facts and
149
+ * the bound Dojo project. Undefined when no server runs or it does not answer.
150
+ */
151
+ export async function serverSnapshot(home) {
152
+ const server = await probeServer(home);
153
+ if (!server)
154
+ return undefined;
155
+ try {
156
+ const response = await fetch(`http://127.0.0.1:${server.port}/api/map`, {
157
+ signal: AbortSignal.timeout(3_000),
158
+ });
159
+ if (!response.ok)
160
+ return undefined;
161
+ const snapshot = (await response.json());
162
+ return snapshot.view ? { url: server.url, snapshot: snapshot } : undefined;
163
+ }
164
+ catch {
165
+ return undefined;
166
+ }
167
+ }
168
+ /** The address that opens one step on the map. */
169
+ export const stepUrl = (url, node) => `${url.replace(/#.*$/, '')}#node=${node}`;
170
+ /**
171
+ * Report on a step. `view` checks that the step's inputs are done; without it
172
+ * (no project facts) nothing is refused for that. The entry is `checked` when
173
+ * every proof is a file this call hashed.
174
+ */
175
+ export async function reportStep(home, from, input, view) {
176
+ const hashed = await evidenceFiles(home, from, input.files ?? []);
177
+ const where = [
178
+ ...hashed,
179
+ ...(input.urls ?? []).map((url) => ({ url })),
180
+ ...(input.dojo ?? []).map((dojo) => ({ dojo })),
181
+ ...(input.command ? [{ command: input.command }] : []),
182
+ ];
183
+ const checked = hashed.length > 0 && hashed.length === where.length;
184
+ const { files: _files, urls: _urls, dojo: _dojo, command: _command, ...report } = input;
185
+ const state = await updateMapState(home, (current) => reportBuildStep(current, view, { ...report, where, checked, at: new Date().toISOString() }));
186
+ return { record: state.nodes[input.node], checked };
187
+ }
188
+ /** Offer the author variants to choose from; files are resolved against `from`. */
189
+ export async function openReview(home, from, input, view) {
190
+ const variants = [];
191
+ for (const variant of input.variants)
192
+ variants.push({
193
+ label: variant.label,
194
+ preview: await resolveReviewFile(home, from, variant.preview),
195
+ ...(variant.image ? { image: await resolveReviewFile(home, from, variant.image) } : {}),
196
+ });
197
+ const state = await updateMapState(home, (current) => openBuildReview(current, view, {
198
+ node: input.node,
199
+ agent: input.agent,
200
+ variants,
201
+ at: new Date().toISOString(),
202
+ }));
203
+ return state.reviews[input.node];
204
+ }
205
+ /** Record the author's answer from the chat: the variant they picked, or what to change. */
206
+ export async function answerReview(home, input, view) {
207
+ const state = await updateMapState(home, (current) => answerBuildReview(current, view, { ...input, via: 'chat', at: new Date().toISOString() }));
208
+ return state.reviews[input.node];
209
+ }
210
+ export function reviewAnswer(node, review) {
211
+ const choice = review.status === 'picked' ? review.variants.find((v) => v.id === review.choice) : undefined;
212
+ return {
213
+ node,
214
+ round: review.round,
215
+ status: review.status,
216
+ ...(choice ? { choice } : {}),
217
+ ...(review.status === 'redo' && review.feedback ? { feedback: review.feedback } : {}),
218
+ ...(review.via && review.status !== 'waiting' ? { via: review.via } : {}),
219
+ };
220
+ }
221
+ /**
222
+ * Wait until the author answers the review of `node`, reading the state file
223
+ * every `pollMs` (no map server needed). Resolves at once when it is answered
224
+ * already; with `timeoutMs`, resolves with the review still waiting once that
225
+ * passes.
226
+ */
227
+ export async function waitForReview(home, node, options = {}) {
228
+ const pollMs = options.pollMs ?? 1_000;
229
+ const deadline = options.timeoutMs ? Date.now() + options.timeoutMs : Number.POSITIVE_INFINITY;
230
+ for (;;) {
231
+ const read = await readMapState(home);
232
+ if (read.problem)
233
+ throw new Error(`Cannot read the build map: ${read.problem}`);
234
+ const review = read.state.reviews[node];
235
+ if (!review)
236
+ throw new Error(`No review is open on "${node}": open one with the variants first.`);
237
+ if (review.status !== 'waiting' || Date.now() >= deadline || options.signal?.aborted)
238
+ return reviewAnswer(node, review);
239
+ await new Promise((resolve) => setTimeout(resolve, Math.min(pollMs, Math.max(0, deadline - Date.now()))));
240
+ }
241
+ }
242
+ //# sourceMappingURL=build-map-agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-map-agent.js","sourceRoot":"","sources":["../src/build-map-agent.ts"],"names":[],"mappings":"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"}
@@ -32,7 +32,7 @@ export declare const MAP_STATE_FILE = "build-map.json";
32
32
  export declare const MAP_SERVER_FILE = "build-map.server.json";
33
33
  export declare const MAP_LOG_FILE = "build-map.log";
34
34
  /** Bumped when the page/server protocol changes: a newer CLI replaces an older server instead of reusing it. */
35
- export declare const MAP_PROTOCOL = 1;
35
+ export declare const MAP_PROTOCOL = 6;
36
36
  export type MapHome = {
37
37
  /** Where the map's files live: this project directory in the main checkout. */
38
38
  home: string;
@@ -39,7 +39,7 @@ export const MAP_LOG_FILE = 'build-map.log';
39
39
  const STATE_LOCK = 'build-map.lock';
40
40
  const SERVER_LOCK = 'build-map.server.lock';
41
41
  /** Bumped when the page/server protocol changes: a newer CLI replaces an older server instead of reusing it. */
42
- export const MAP_PROTOCOL = 1;
42
+ export const MAP_PROTOCOL = 6;
43
43
  export const mapPath = (home, file) => path.join(home, MAP_DIR, file);
44
44
  function git(cwd, args) {
45
45
  return new Promise((resolve) => {
@@ -0,0 +1,43 @@
1
+ /**
2
+ * The agent side of the build map on the local (stdio) server (plan
3
+ * 2026-11-03-extension-build-map §6.4, phase 2): get_build_map,
4
+ * report_build_step and request_build_review. Same writes as the CLI's
5
+ * `extenshi map step|review|choose` (build-map-agent.ts, a copy of the CLI's),
6
+ * to the same state file, so the author's open map shows them within a second.
7
+ *
8
+ * The project facts (manifest, icons, builds, the bound Dojo project) are read
9
+ * by the CLI. While the author's map runs, its server has them, and these tools
10
+ * check writes against its view. Without it they still write, but nothing is
11
+ * refused for a step whose inputs are not done, and get_build_map says that
12
+ * steps proven only by files look not done.
13
+ *
14
+ * Local only: the hosted connector has no access to the author's files and
15
+ * registers none of these tools.
16
+ */
17
+ import { type VariantInput } from './build-map-agent.js';
18
+ export type BuildStepInput = {
19
+ step: string;
20
+ agent: string;
21
+ state?: 'start' | 'progress' | 'done' | 'stop';
22
+ task?: number;
23
+ progress?: number;
24
+ claim?: string;
25
+ note?: string;
26
+ files?: string[];
27
+ urls?: string[];
28
+ choice?: string;
29
+ redo?: string;
30
+ round?: number;
31
+ };
32
+ export type BuildReviewInput = {
33
+ step: string;
34
+ agent: string;
35
+ variants: VariantInput[];
36
+ };
37
+ export type BuildMapAgent = {
38
+ getMap(projectDir?: string): Promise<unknown>;
39
+ reportStep(projectDir: string | undefined, input: BuildStepInput): Promise<unknown>;
40
+ requestReview(projectDir: string | undefined, input: BuildReviewInput): Promise<unknown>;
41
+ };
42
+ export declare function buildMapAgent(cwd?: string): BuildMapAgent;
43
+ //# sourceMappingURL=build-map-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-map-tools.d.ts","sourceRoot":"","sources":["../src/build-map-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAWH,OAAO,EAON,KAAK,YAAY,EACjB,MAAM,sBAAsB,CAAA;AAG7B,MAAM,MAAM,cAAc,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAA;IAC9C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,YAAY,EAAE,CAAA;CAAE,CAAA;AAExF,MAAM,MAAM,aAAa,GAAG;IAC3B,MAAM,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAC7C,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACnF,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CACxF,CAAA;AAqDD,wBAAgB,aAAa,CAAC,GAAG,GAAE,MAAsB,GAAG,aAAa,CAqGxE"}
@@ -0,0 +1,149 @@
1
+ /**
2
+ * The agent side of the build map on the local (stdio) server (plan
3
+ * 2026-11-03-extension-build-map §6.4, phase 2): get_build_map,
4
+ * report_build_step and request_build_review. Same writes as the CLI's
5
+ * `extenshi map step|review|choose` (build-map-agent.ts, a copy of the CLI's),
6
+ * to the same state file, so the author's open map shows them within a second.
7
+ *
8
+ * The project facts (manifest, icons, builds, the bound Dojo project) are read
9
+ * by the CLI. While the author's map runs, its server has them, and these tools
10
+ * check writes against its view. Without it they still write, but nothing is
11
+ * refused for a step whose inputs are not done, and get_build_map says that
12
+ * steps proven only by files look not done.
13
+ *
14
+ * Local only: the hosted connector has no access to the author's files and
15
+ * registers none of these tools.
16
+ */
17
+ import path from 'node:path';
18
+ import { BuildStepError, buildNodeById, deriveBuildMap, } from '@extenshi/contracts';
19
+ import { answerReview, openReview, reportStep, reviewAnswer, serverSnapshot, stepUrl, } from './build-map-agent.js';
20
+ import { readMapState, resolveMapHome } from './build-map-store.js';
21
+ const NOT_RUNNING = 'The author’s map is not running, so steps only the project files prove look not done here, and nothing was refused for inputs that are not done. `npx @extenshi/cli map status --json` reads the files.';
22
+ /** A refusal reads as one sentence with its reason code; anything else passes through. */
23
+ function refusal(error) {
24
+ if (error instanceof BuildStepError)
25
+ throw new Error(`${error.message} (${error.code})`);
26
+ throw error;
27
+ }
28
+ function reviewsOf(reviews) {
29
+ return Object.fromEntries(Object.entries(reviews).map(([id, review]) => [
30
+ id,
31
+ { ...reviewAnswer(id, review), variants: review.variants },
32
+ ]));
33
+ }
34
+ /** Every step this extension needs: status, the task it is on, who works on it. */
35
+ function stepsOf(nodes) {
36
+ return Object.fromEntries(Object.values(nodes)
37
+ .filter((node) => node.status !== 'inactive')
38
+ .map((node) => {
39
+ const todo = node.status === 'done' ? undefined : buildNodeById(node.id)?.todos[node.taskIndex];
40
+ return [
41
+ node.id,
42
+ {
43
+ status: node.status,
44
+ ...(todo
45
+ ? { task: node.taskIndex, current: todo.t, ...(todo.a === 'you' ? { byAuthor: true } : {}) }
46
+ : {}),
47
+ ...(node.agent ? { agent: node.agent } : {}),
48
+ ...(node.redo ? { redo: true } : {}),
49
+ ...(node.basis ? { basis: node.basis } : {}),
50
+ },
51
+ ];
52
+ }));
53
+ }
54
+ function summary(view) {
55
+ return {
56
+ progress: { done: view.done, active: view.active, percent: view.percent },
57
+ needsYou: view.needsYou,
58
+ running: view.running.map((id) => ({ id, agent: view.nodes[id]?.agent })),
59
+ next: view.next,
60
+ byHand: view.byHand,
61
+ };
62
+ }
63
+ export function buildMapAgent(cwd = process.cwd()) {
64
+ const place = async (projectDir) => {
65
+ const dir = path.resolve(cwd, projectDir ?? '.');
66
+ const where = await resolveMapHome(dir);
67
+ const running = await serverSnapshot(where.home);
68
+ return { dir, home: where.home, running };
69
+ };
70
+ return {
71
+ async getMap(projectDir) {
72
+ const { home, running } = await place(projectDir);
73
+ if (running) {
74
+ const snapshot = running.snapshot;
75
+ return {
76
+ home,
77
+ url: running.url,
78
+ facts: true,
79
+ ...summary(snapshot.view),
80
+ reviews: reviewsOf(snapshot.reviews ?? {}),
81
+ steps: stepsOf(snapshot.view.nodes),
82
+ };
83
+ }
84
+ const read = await readMapState(home);
85
+ const view = deriveBuildMap(read.state, { done: {} });
86
+ return {
87
+ home,
88
+ facts: false,
89
+ note: NOT_RUNNING,
90
+ ...summary(view),
91
+ reviews: reviewsOf(read.state.reviews),
92
+ steps: stepsOf(view.nodes),
93
+ ...(read.problem ? { problem: read.problem } : {}),
94
+ };
95
+ },
96
+ async reportStep(projectDir, input) {
97
+ const { dir, home, running } = await place(projectDir);
98
+ const view = running?.snapshot.view;
99
+ if (input.choice !== undefined || input.redo !== undefined) {
100
+ const review = await answerReview(home, {
101
+ node: input.step,
102
+ agent: input.agent,
103
+ ...(input.choice !== undefined ? { choice: input.choice } : {}),
104
+ ...(input.redo !== undefined ? { redo: input.redo } : {}),
105
+ ...(input.round !== undefined ? { round: input.round } : {}),
106
+ }, view).catch(refusal);
107
+ return {
108
+ ...reviewAnswer(input.step, review),
109
+ ...(running ? { url: stepUrl(running.url, input.step) } : {}),
110
+ };
111
+ }
112
+ const result = await reportStep(home, dir, {
113
+ node: input.step,
114
+ state: input.state ?? 'done',
115
+ agent: input.agent,
116
+ ...(input.task !== undefined ? { task: input.task } : {}),
117
+ ...(input.progress !== undefined ? { progress: input.progress } : {}),
118
+ ...(input.claim ? { claim: input.claim } : {}),
119
+ ...(input.note ? { note: input.note } : {}),
120
+ ...(input.files?.length ? { files: input.files } : {}),
121
+ ...(input.urls?.length ? { urls: input.urls } : {}),
122
+ }, view).catch(refusal);
123
+ const step = buildNodeById(input.step);
124
+ return {
125
+ step: input.step,
126
+ tasksDone: result.record?.ti ?? 0,
127
+ tasks: step?.todos.length ?? 0,
128
+ checked: result.checked,
129
+ inputsChecked: Boolean(view),
130
+ ...(view ? {} : { note: NOT_RUNNING }),
131
+ };
132
+ },
133
+ async requestReview(projectDir, input) {
134
+ const { dir, home, running } = await place(projectDir);
135
+ const review = await openReview(home, dir, { node: input.step, agent: input.agent, variants: input.variants }, running?.snapshot.view).catch(refusal);
136
+ return {
137
+ step: input.step,
138
+ round: review.round,
139
+ variants: review.variants,
140
+ ...(running
141
+ ? { url: stepUrl(running.url, input.step) }
142
+ : {
143
+ note: 'The author’s map is not running: show the author the previews in the chat, then record the answer with report_build_step (choice or redo).',
144
+ }),
145
+ };
146
+ },
147
+ };
148
+ }
149
+ //# sourceMappingURL=build-map-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-map-tools.js","sourceRoot":"","sources":["../src/build-map-tools.ts"],"names":[],"mappings":"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"}