@agent-native/core 0.48.4 → 0.49.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/dist/agent/context-xray/actions/context-evict.d.ts +1 -1
- package/dist/agent/context-xray/actions/context-pin.d.ts +1 -1
- package/dist/agent/context-xray/actions/context-report.d.ts +4 -4
- package/dist/agent/context-xray/actions/context-restore.d.ts +1 -1
- package/dist/application-state/handlers.d.ts +2 -2
- package/dist/application-state/handlers.d.ts.map +1 -1
- package/dist/cli/app-skill.d.ts +157 -0
- package/dist/cli/app-skill.d.ts.map +1 -0
- package/dist/cli/app-skill.js +17 -7
- package/dist/cli/app-skill.js.map +1 -1
- package/dist/cli/audit-agent-web.d.ts +2 -0
- package/dist/cli/audit-agent-web.d.ts.map +1 -0
- package/dist/cli/code-agent-connector.d.ts +17 -0
- package/dist/cli/code-agent-connector.d.ts.map +1 -0
- package/dist/cli/code.d.ts +66 -0
- package/dist/cli/code.d.ts.map +1 -0
- package/dist/cli/connect.d.ts +168 -0
- package/dist/cli/connect.d.ts.map +1 -0
- package/dist/cli/connect.js +118 -30
- package/dist/cli/connect.js.map +1 -1
- package/dist/cli/context-xray-local.d.ts +16 -0
- package/dist/cli/context-xray-local.d.ts.map +1 -0
- package/dist/cli/create-workspace.d.ts +8 -0
- package/dist/cli/create-workspace.d.ts.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/info.d.ts +2 -0
- package/dist/cli/info.d.ts.map +1 -0
- package/dist/cli/mcp-config-writers.d.ts +108 -0
- package/dist/cli/mcp-config-writers.d.ts.map +1 -0
- package/dist/cli/mcp-config-writers.js +143 -0
- package/dist/cli/mcp-config-writers.js.map +1 -1
- package/dist/cli/mcp.d.ts +16 -0
- package/dist/cli/mcp.d.ts.map +1 -0
- package/dist/cli/mcp.js +10 -10
- package/dist/cli/mcp.js.map +1 -1
- package/dist/cli/migrate.d.ts +38 -0
- package/dist/cli/migrate.d.ts.map +1 -0
- package/dist/cli/plan-local.d.ts +43 -0
- package/dist/cli/plan-local.d.ts.map +1 -0
- package/dist/cli/plan-publish-store.d.ts +62 -0
- package/dist/cli/plan-publish-store.d.ts.map +1 -0
- package/dist/cli/pr-visual-recap-workflow.d.ts +11 -0
- package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -0
- package/dist/cli/pr-visual-recap-workflow.js +1 -1
- package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
- package/dist/cli/recap.d.ts +453 -0
- package/dist/cli/recap.d.ts.map +1 -0
- package/dist/cli/recap.js +228 -95
- package/dist/cli/recap.js.map +1 -1
- package/dist/cli/skills.d.ts +193 -0
- package/dist/cli/skills.d.ts.map +1 -0
- package/dist/cli/skills.js +369 -171
- package/dist/cli/skills.js.map +1 -1
- package/dist/cli/telemetry.d.ts +13 -0
- package/dist/cli/telemetry.d.ts.map +1 -0
- package/dist/cli/telemetry.js +115 -0
- package/dist/cli/telemetry.js.map +1 -0
- package/dist/cli/workspace-dev.d.ts +96 -0
- package/dist/cli/workspace-dev.d.ts.map +1 -0
- package/dist/client/blocks/library/AnnotatedCodeBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/AnnotatedCodeBlock.js +15 -7
- package/dist/client/blocks/library/AnnotatedCodeBlock.js.map +1 -1
- package/dist/client/blocks/library/DiffBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/DiffBlock.js +17 -10
- package/dist/client/blocks/library/DiffBlock.js.map +1 -1
- package/dist/client/blocks/library/annotation-rail.d.ts +5 -0
- package/dist/client/blocks/library/annotation-rail.d.ts.map +1 -1
- package/dist/client/blocks/library/annotation-rail.js +6 -0
- package/dist/client/blocks/library/annotation-rail.js.map +1 -1
- package/dist/client/blocks/types.d.ts +5 -0
- package/dist/client/blocks/types.d.ts.map +1 -1
- package/dist/client/blocks/types.js.map +1 -1
- package/dist/extensions/schema.d.ts +54 -54
- package/dist/extensions/slots/schema.d.ts +13 -13
- package/dist/file-upload/actions/upload-image.d.ts +4 -4
- package/dist/mcp/actions/create-org-service-token.d.ts +1 -1
- package/dist/mcp/actions/list-org-service-tokens.d.ts +7 -7
- package/dist/mcp/build-server.d.ts +12 -12
- package/dist/mcp/build-server.d.ts.map +1 -1
- package/dist/mcp/build-server.js.map +1 -1
- package/dist/mcp/connect-route.js +1 -1
- package/dist/mcp/connect-route.js.map +1 -1
- package/dist/mcp/oauth-route.d.ts +10 -0
- package/dist/mcp/oauth-route.d.ts.map +1 -1
- package/dist/mcp/oauth-route.js +34 -3
- package/dist/mcp/oauth-route.js.map +1 -1
- package/dist/mcp/oauth-store.d.ts +15 -1
- package/dist/mcp/oauth-store.d.ts.map +1 -1
- package/dist/mcp/oauth-store.js +60 -4
- package/dist/mcp/oauth-store.js.map +1 -1
- package/dist/mcp/oauth-token.d.ts +3 -1
- package/dist/mcp/oauth-token.d.ts.map +1 -1
- package/dist/mcp/oauth-token.js +78 -6
- package/dist/mcp/oauth-token.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +8 -6
- package/dist/mcp/server.js.map +1 -1
- package/dist/observability/routes.d.ts +11 -11
- package/dist/org/handlers.d.ts +7 -11
- package/dist/org/handlers.d.ts.map +1 -1
- package/dist/secrets/schema.d.ts +7 -7
- package/dist/server/csrf.d.ts +1 -1
- package/dist/server/csrf.d.ts.map +1 -1
- package/dist/server/poll-events.d.ts +1 -1
- package/dist/server/security-headers.d.ts +1 -1
- package/dist/server/security-headers.d.ts.map +1 -1
- package/dist/sharing/actions/list-resource-shares.d.ts +3 -3
- package/dist/sharing/actions/set-resource-visibility.d.ts +2 -2
- package/dist/sharing/actions/share-resource.d.ts +4 -4
- package/dist/sharing/actions/unshare-resource.d.ts +1 -1
- package/dist/sharing/schema.d.ts +12 -12
- package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +2 -2
- package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +6 -6
- package/dist/templates/workspace-core/.agents/skills/external-agents/references/mcp-apps-embedding.md +2 -2
- package/dist/workspace-files/schema.d.ts +8 -8
- package/docs/content/external-agents.md +14 -0
- package/docs/content/plan-plugin.md +16 -7
- package/package.json +5 -1
- package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +2 -2
- package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +6 -6
- package/src/templates/workspace-core/.agents/skills/external-agents/references/mcp-apps-embedding.md +2 -2
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface CliTelemetryOptions {
|
|
2
|
+
/** Stable identifier for the emitting CLI, e.g. "skills-installer". */
|
|
3
|
+
cli: string;
|
|
4
|
+
cliVersion: string;
|
|
5
|
+
command: string;
|
|
6
|
+
interactive: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface CliTelemetry {
|
|
9
|
+
track(event: string, properties?: Record<string, unknown>): void;
|
|
10
|
+
flush(): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
export declare function createCliTelemetry(options: CliTelemetryOptions): CliTelemetry;
|
|
13
|
+
//# sourceMappingURL=telemetry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../src/cli/telemetry.ts"],"names":[],"mappings":"AA8BA,MAAM,WAAW,mBAAmB;IAClC,uEAAuE;IACvE,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACjE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AA2CD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,mBAAmB,GAAG,YAAY,CAmD7E"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Best-effort install-funnel telemetry for the core CLI.
|
|
3
|
+
*
|
|
4
|
+
* Events are POSTed to the first-party Agent Native Analytics endpoint
|
|
5
|
+
* (analytics.agent-native.com/track) using a PUBLIC, write-only key — the same
|
|
6
|
+
* mechanism every agent-native app uses to report client-side events. Nothing
|
|
7
|
+
* here ever blocks or throws into the install flow: sends are fire-and-forget
|
|
8
|
+
* and `flush()` awaits any in-flight requests with a short cap before exit.
|
|
9
|
+
*
|
|
10
|
+
* Privacy: we report skill NAMES, client ids, scope, counts, platform, and the
|
|
11
|
+
* CLI version — never file paths, repo names, cwd, skill sources, or anything
|
|
12
|
+
* user-identifying. A random per-machine install id (unique installs) and a
|
|
13
|
+
* per-invocation run id (step-by-step dropoff) are the only identifiers.
|
|
14
|
+
*
|
|
15
|
+
* Opt out with DO_NOT_TRACK=1 or AGENT_NATIVE_TELEMETRY_DISABLED=1.
|
|
16
|
+
*/
|
|
17
|
+
import crypto from "node:crypto";
|
|
18
|
+
import fs from "node:fs";
|
|
19
|
+
import os from "node:os";
|
|
20
|
+
import path from "node:path";
|
|
21
|
+
// Public, write-only analytics key. Safe to embed (revocable from the Analytics
|
|
22
|
+
// settings UI). Override with AGENT_NATIVE_ANALYTICS_PUBLIC_KEY for testing or
|
|
23
|
+
// to point telemetry at a different first-party analytics instance.
|
|
24
|
+
// guard:allow-public-key -- first-party analytics write key is public by design.
|
|
25
|
+
const EMBEDDED_PUBLIC_KEY = "anpk_dc523e34b99bc34d76e82d94c46593544e4a8509a4bfc93c";
|
|
26
|
+
const DEFAULT_ENDPOINT = "https://analytics.agent-native.com/track";
|
|
27
|
+
const FLUSH_TIMEOUT_MS = 1500;
|
|
28
|
+
function resolvePublicKey() {
|
|
29
|
+
const fromEnv = process.env.AGENT_NATIVE_ANALYTICS_PUBLIC_KEY?.trim();
|
|
30
|
+
return fromEnv || EMBEDDED_PUBLIC_KEY;
|
|
31
|
+
}
|
|
32
|
+
function resolveEndpoint() {
|
|
33
|
+
const fromEnv = process.env.AGENT_NATIVE_ANALYTICS_ENDPOINT?.trim();
|
|
34
|
+
return (fromEnv || DEFAULT_ENDPOINT).replace(/\/+$/, "");
|
|
35
|
+
}
|
|
36
|
+
function telemetryDisabled() {
|
|
37
|
+
return (process.env.DO_NOT_TRACK === "1" ||
|
|
38
|
+
process.env.AGENT_NATIVE_TELEMETRY_DISABLED === "1" ||
|
|
39
|
+
process.env.NODE_ENV === "test" ||
|
|
40
|
+
typeof fetch !== "function");
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Read (or lazily create) a stable per-machine install id, shared across both
|
|
44
|
+
* skills CLIs so one developer counts once. Best-effort: an unwritable home
|
|
45
|
+
* directory just yields an ephemeral id for this run.
|
|
46
|
+
*/
|
|
47
|
+
function resolveInstallId() {
|
|
48
|
+
try {
|
|
49
|
+
const dir = path.join(os.homedir(), ".agent-native");
|
|
50
|
+
const file = path.join(dir, "installation-id");
|
|
51
|
+
const existing = fs.existsSync(file)
|
|
52
|
+
? fs.readFileSync(file, "utf8").trim()
|
|
53
|
+
: "";
|
|
54
|
+
if (existing)
|
|
55
|
+
return existing;
|
|
56
|
+
const id = crypto.randomUUID();
|
|
57
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
58
|
+
fs.writeFileSync(file, `${id}\n`, "utf8");
|
|
59
|
+
return id;
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return crypto.randomUUID();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
export function createCliTelemetry(options) {
|
|
66
|
+
const publicKey = resolvePublicKey();
|
|
67
|
+
const disabled = telemetryDisabled() || !publicKey;
|
|
68
|
+
const endpoint = resolveEndpoint();
|
|
69
|
+
const installId = disabled ? "" : resolveInstallId();
|
|
70
|
+
const runId = crypto.randomUUID();
|
|
71
|
+
const inFlight = new Set();
|
|
72
|
+
const base = {
|
|
73
|
+
cli: options.cli,
|
|
74
|
+
cliVersion: options.cliVersion,
|
|
75
|
+
command: options.command,
|
|
76
|
+
node: process.version,
|
|
77
|
+
platform: process.platform,
|
|
78
|
+
ci: process.env.CI === "true",
|
|
79
|
+
interactive: options.interactive,
|
|
80
|
+
runId,
|
|
81
|
+
installId,
|
|
82
|
+
};
|
|
83
|
+
function track(event, properties) {
|
|
84
|
+
if (disabled)
|
|
85
|
+
return;
|
|
86
|
+
const body = JSON.stringify({
|
|
87
|
+
publicKey,
|
|
88
|
+
event,
|
|
89
|
+
anonymousId: installId,
|
|
90
|
+
sessionId: runId,
|
|
91
|
+
timestamp: new Date().toISOString(),
|
|
92
|
+
properties: { ...base, ...properties },
|
|
93
|
+
});
|
|
94
|
+
const promise = fetch(endpoint, {
|
|
95
|
+
method: "POST",
|
|
96
|
+
headers: { "Content-Type": "application/json" },
|
|
97
|
+
body,
|
|
98
|
+
keepalive: true,
|
|
99
|
+
})
|
|
100
|
+
.then(() => undefined)
|
|
101
|
+
.catch(() => undefined);
|
|
102
|
+
inFlight.add(promise);
|
|
103
|
+
void promise.finally(() => inFlight.delete(promise));
|
|
104
|
+
}
|
|
105
|
+
async function flush() {
|
|
106
|
+
if (disabled || inFlight.size === 0)
|
|
107
|
+
return;
|
|
108
|
+
await Promise.race([
|
|
109
|
+
Promise.allSettled([...inFlight]),
|
|
110
|
+
new Promise((resolve) => setTimeout(resolve, FLUSH_TIMEOUT_MS)),
|
|
111
|
+
]);
|
|
112
|
+
}
|
|
113
|
+
return { track, flush };
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=telemetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../src/cli/telemetry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Best-effort install-funnel telemetry for the core CLI.\n *\n * Events are POSTed to the first-party Agent Native Analytics endpoint\n * (analytics.agent-native.com/track) using a PUBLIC, write-only key — the same\n * mechanism every agent-native app uses to report client-side events. Nothing\n * here ever blocks or throws into the install flow: sends are fire-and-forget\n * and `flush()` awaits any in-flight requests with a short cap before exit.\n *\n * Privacy: we report skill NAMES, client ids, scope, counts, platform, and the\n * CLI version — never file paths, repo names, cwd, skill sources, or anything\n * user-identifying. A random per-machine install id (unique installs) and a\n * per-invocation run id (step-by-step dropoff) are the only identifiers.\n *\n * Opt out with DO_NOT_TRACK=1 or AGENT_NATIVE_TELEMETRY_DISABLED=1.\n */\nimport crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\n// Public, write-only analytics key. Safe to embed (revocable from the Analytics\n// settings UI). Override with AGENT_NATIVE_ANALYTICS_PUBLIC_KEY for testing or\n// to point telemetry at a different first-party analytics instance.\n// guard:allow-public-key -- first-party analytics write key is public by design.\nconst EMBEDDED_PUBLIC_KEY =\n \"anpk_dc523e34b99bc34d76e82d94c46593544e4a8509a4bfc93c\";\nconst DEFAULT_ENDPOINT = \"https://analytics.agent-native.com/track\";\nconst FLUSH_TIMEOUT_MS = 1500;\n\nexport interface CliTelemetryOptions {\n /** Stable identifier for the emitting CLI, e.g. \"skills-installer\". */\n cli: string;\n cliVersion: string;\n command: string;\n interactive: boolean;\n}\n\nexport interface CliTelemetry {\n track(event: string, properties?: Record<string, unknown>): void;\n flush(): Promise<void>;\n}\n\nfunction resolvePublicKey(): string {\n const fromEnv = process.env.AGENT_NATIVE_ANALYTICS_PUBLIC_KEY?.trim();\n return fromEnv || EMBEDDED_PUBLIC_KEY;\n}\n\nfunction resolveEndpoint(): string {\n const fromEnv = process.env.AGENT_NATIVE_ANALYTICS_ENDPOINT?.trim();\n return (fromEnv || DEFAULT_ENDPOINT).replace(/\\/+$/, \"\");\n}\n\nfunction telemetryDisabled(): boolean {\n return (\n process.env.DO_NOT_TRACK === \"1\" ||\n process.env.AGENT_NATIVE_TELEMETRY_DISABLED === \"1\" ||\n process.env.NODE_ENV === \"test\" ||\n typeof fetch !== \"function\"\n );\n}\n\n/**\n * Read (or lazily create) a stable per-machine install id, shared across both\n * skills CLIs so one developer counts once. Best-effort: an unwritable home\n * directory just yields an ephemeral id for this run.\n */\nfunction resolveInstallId(): string {\n try {\n const dir = path.join(os.homedir(), \".agent-native\");\n const file = path.join(dir, \"installation-id\");\n const existing = fs.existsSync(file)\n ? fs.readFileSync(file, \"utf8\").trim()\n : \"\";\n if (existing) return existing;\n const id = crypto.randomUUID();\n fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(file, `${id}\\n`, \"utf8\");\n return id;\n } catch {\n return crypto.randomUUID();\n }\n}\n\nexport function createCliTelemetry(options: CliTelemetryOptions): CliTelemetry {\n const publicKey = resolvePublicKey();\n const disabled = telemetryDisabled() || !publicKey;\n const endpoint = resolveEndpoint();\n const installId = disabled ? \"\" : resolveInstallId();\n const runId = crypto.randomUUID();\n const inFlight = new Set<Promise<void>>();\n\n const base = {\n cli: options.cli,\n cliVersion: options.cliVersion,\n command: options.command,\n node: process.version,\n platform: process.platform,\n ci: process.env.CI === \"true\",\n interactive: options.interactive,\n runId,\n installId,\n };\n\n function track(event: string, properties?: Record<string, unknown>): void {\n if (disabled) return;\n const body = JSON.stringify({\n publicKey,\n event,\n anonymousId: installId,\n sessionId: runId,\n timestamp: new Date().toISOString(),\n properties: { ...base, ...properties },\n });\n const promise = fetch(endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body,\n keepalive: true,\n })\n .then(() => undefined)\n .catch(() => undefined);\n inFlight.add(promise);\n void promise.finally(() => inFlight.delete(promise));\n }\n\n async function flush(): Promise<void> {\n if (disabled || inFlight.size === 0) return;\n await Promise.race([\n Promise.allSettled([...inFlight]),\n new Promise((resolve) => setTimeout(resolve, FLUSH_TIMEOUT_MS)),\n ]);\n }\n\n return { track, flush };\n}\n"]}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { spawn, type ChildProcess } from "node:child_process";
|
|
3
|
+
import http from "node:http";
|
|
4
|
+
import { type WorkspaceAppAudience } from "../shared/workspace-app-audience.js";
|
|
5
|
+
export interface WorkspaceApp {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
description: string;
|
|
9
|
+
audience: WorkspaceAppAudience;
|
|
10
|
+
publicPaths: string[];
|
|
11
|
+
protectedPaths: string[];
|
|
12
|
+
dir: string;
|
|
13
|
+
port: number;
|
|
14
|
+
process?: ChildProcess;
|
|
15
|
+
restartTimer?: NodeJS.Timeout;
|
|
16
|
+
restartAttempts?: number;
|
|
17
|
+
lastFailure?: {
|
|
18
|
+
code: number | null;
|
|
19
|
+
signal: NodeJS.Signals | null;
|
|
20
|
+
at: number;
|
|
21
|
+
installing: boolean;
|
|
22
|
+
output: string;
|
|
23
|
+
nextRetryAt: number;
|
|
24
|
+
};
|
|
25
|
+
outputTail?: string;
|
|
26
|
+
installing?: boolean;
|
|
27
|
+
installAttempted?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Set true once we've successfully connected to the upstream. After that we
|
|
30
|
+
* skip the readiness probe on every request; the child server stays
|
|
31
|
+
* listening for the rest of the dev session.
|
|
32
|
+
*/
|
|
33
|
+
ready?: boolean;
|
|
34
|
+
readinessProbe?: Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
export interface WorkspaceDevOptions {
|
|
37
|
+
args?: string[];
|
|
38
|
+
env?: NodeJS.ProcessEnv;
|
|
39
|
+
root?: string;
|
|
40
|
+
spawnProcess?: typeof spawn;
|
|
41
|
+
openBrowser?: boolean;
|
|
42
|
+
stdout?: Pick<NodeJS.WriteStream, "write">;
|
|
43
|
+
stderr?: Pick<NodeJS.WriteStream, "write">;
|
|
44
|
+
}
|
|
45
|
+
export interface WorkspaceDevHandle {
|
|
46
|
+
apps: WorkspaceApp[];
|
|
47
|
+
defaultApp: string;
|
|
48
|
+
gatewayUrl: () => string;
|
|
49
|
+
ready: Promise<{
|
|
50
|
+
port: number;
|
|
51
|
+
url: string;
|
|
52
|
+
}>;
|
|
53
|
+
server: http.Server;
|
|
54
|
+
shutdown: () => void;
|
|
55
|
+
}
|
|
56
|
+
export declare function isWorkspaceWatcherLimitError(err: Pick<NodeJS.ErrnoException, "code">): boolean;
|
|
57
|
+
export declare function shouldEagerStartWorkspaceApps(args?: string[], env?: NodeJS.ProcessEnv): boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Whether the gateway should spawn the rest of the apps in the background
|
|
60
|
+
* after the default app boots. Lazy spawn already covers correctness — this
|
|
61
|
+
* is purely a UX optimization so the second/third/Nth app the user clicks
|
|
62
|
+
* into is already warm instead of paying the Vite + esbuild prebundle cost
|
|
63
|
+
* on demand.
|
|
64
|
+
*
|
|
65
|
+
* Defaults to ON in lazy mode. Off when the user passed --no-prewarm /
|
|
66
|
+
* WORKSPACE_NO_PREWARM=1, or when eager mode is already starting every app
|
|
67
|
+
* up front (in which case prewarm would be redundant).
|
|
68
|
+
*/
|
|
69
|
+
export declare function shouldPrewarmWorkspaceApps(args?: string[], env?: NodeJS.ProcessEnv): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* How many apps to prewarm in parallel. Each Vite spawn briefly maxes out a
|
|
72
|
+
* CPU core during esbuild prebundling, so booting all 9 templates at once on
|
|
73
|
+
* a 4-core laptop just produces a thundering herd. Default 2 — gentle on
|
|
74
|
+
* laptops, fast enough that all apps finish within a few cold-spawn windows.
|
|
75
|
+
* Override via --prewarm-concurrency=N or WORKSPACE_PREWARM_CONCURRENCY=N.
|
|
76
|
+
*/
|
|
77
|
+
export declare function workspacePrewarmConcurrency(args?: string[], env?: NodeJS.ProcessEnv): number;
|
|
78
|
+
/**
|
|
79
|
+
* How long the prewarm queue waits after the gateway is ready before kicking
|
|
80
|
+
* off background spawns. Lets the default app's prebundle get first dibs on
|
|
81
|
+
* CPU. Override via WORKSPACE_PREWARM_DELAY_MS (mostly for tests).
|
|
82
|
+
*/
|
|
83
|
+
export declare function workspacePrewarmDelayMs(env?: NodeJS.ProcessEnv): number;
|
|
84
|
+
export type PollingFileWatcherMode = "enable" | "disable-explicit" | "disable-default";
|
|
85
|
+
/**
|
|
86
|
+
* Three-way classification of the polling-watcher decision so callers can
|
|
87
|
+
* tell apart "the user explicitly turned this off" (where we want to override
|
|
88
|
+
* any inherited chokidar/TSC env vars from the parent shell) from "we just
|
|
89
|
+
* didn't auto-detect a Builder/Codespaces/Gitpod container" (where the user's
|
|
90
|
+
* own watcher vars should pass through untouched).
|
|
91
|
+
*/
|
|
92
|
+
export declare function pollingFileWatcherMode(env?: NodeJS.ProcessEnv, root?: string): PollingFileWatcherMode;
|
|
93
|
+
export declare function shouldUsePollingFileWatcher(env?: NodeJS.ProcessEnv, root?: string): boolean;
|
|
94
|
+
export declare function initialWorkspaceAppIds(apps: Array<Pick<WorkspaceApp, "id">>, defaultApp: string, eager: boolean, startDefault?: boolean): string[];
|
|
95
|
+
export declare function runWorkspaceDev(options?: WorkspaceDevOptions): Promise<WorkspaceDevHandle>;
|
|
96
|
+
//# sourceMappingURL=workspace-dev.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-dev.d.ts","sourceRoot":"","sources":["../../src/cli/workspace-dev.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnnotatedCodeBlock.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/AnnotatedCodeBlock.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAEV,iBAAiB,EAClB,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"AnnotatedCodeBlock.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/AnnotatedCodeBlock.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,KAAK,EAEV,iBAAiB,EAClB,MAAM,4BAA4B,CAAC;AA4IpC,iBAAS,iBAAiB,CAAC,EACzB,IAAI,EACJ,OAAO,EACP,KAAK,EACL,OAAO,EACP,GAAG,GACJ,EAAE,cAAc,CAAC,iBAAiB,CAAC,2CAsQnC;AAOD,iBAAS,iBAAiB,CAAC,EACzB,IAAI,EACJ,QAAQ,EACR,QAAQ,GACT,EAAE,cAAc,CAAC,iBAAiB,CAAC,2CAiJnC;AAED,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,CAAC"}
|
|
@@ -3,7 +3,7 @@ import { useMemo, useRef, useState } from "react";
|
|
|
3
3
|
import { IconCode, IconPlus, IconTrash } from "@tabler/icons-react";
|
|
4
4
|
import { cn } from "../../utils.js";
|
|
5
5
|
import { highlightCode, inferLanguageFromFilename, normalizeCodeLanguage, } from "./code-highlight.js";
|
|
6
|
-
import { AnnotationHiddenStack, AnnotationHoverCard, anchorFromElements, buildLineMarkerMap, hasRailAnnotations, resolveAnnotations, useAnnotationHover, } from "./annotation-rail.js";
|
|
6
|
+
import { AnnotationHiddenStack, AnnotationHoverCard, AnnotationInlineOverlayStack, anchorFromElements, buildLineMarkerMap, hasRailAnnotations, resolveAnnotations, useAnnotationHover, } from "./annotation-rail.js";
|
|
7
7
|
import { CodeFilenameLabel } from "./code-filename-label.js";
|
|
8
8
|
import { DevInput, DevLabel, DevTextarea } from "./dev-doc-ui.js";
|
|
9
9
|
/**
|
|
@@ -119,6 +119,7 @@ function AnnotatedCodeRead({ data, blockId, title, summary, ctx, }) {
|
|
|
119
119
|
// line number (1-based) → resolved annotations covering it.
|
|
120
120
|
const lineMarkers = useMemo(() => buildLineMarkerMap(resolved), [resolved]);
|
|
121
121
|
const hasAnnotations = hasRailAnnotations(resolved);
|
|
122
|
+
const showAnnotationOverlays = Boolean(ctx.showCodeAnnotationOverlays);
|
|
122
123
|
const langChip = data.language?.trim();
|
|
123
124
|
const hasFilename = Boolean(data.filename?.trim());
|
|
124
125
|
const showLangChip = Boolean(langChip && !hasFilename);
|
|
@@ -134,6 +135,9 @@ function AnnotatedCodeRead({ data, blockId, title, summary, ctx, }) {
|
|
|
134
135
|
const markers = lineMarkers.get(lineNo);
|
|
135
136
|
const isAnnotated = !!markers?.length;
|
|
136
137
|
const isActive = activeIndex != null && !!markers?.some((m) => m.index === activeIndex);
|
|
138
|
+
const overlayItems = showAnnotationOverlays && markers
|
|
139
|
+
? markers.filter((item) => item.range?.start === lineNo)
|
|
140
|
+
: [];
|
|
137
141
|
const buildAnchorForRow = (el) => {
|
|
138
142
|
if (!markers)
|
|
139
143
|
return null;
|
|
@@ -142,11 +146,13 @@ function AnnotatedCodeRead({ data, blockId, title, summary, ctx, }) {
|
|
|
142
146
|
const anchorRow = lineRefs.current.get(anchorLine) ?? el;
|
|
143
147
|
return anchorFromElements(codeRef.current, anchorRow);
|
|
144
148
|
};
|
|
145
|
-
return (_jsxs("div", { ref: (node) => setLineRef(lineNo, node), "data-code-line": lineNo, "data-annot-row": isAnnotated ? markers?.[0].index : undefined, tabIndex: isAnnotated ? 0 : undefined, role: isAnnotated ? "button" : undefined, "aria-expanded": isAnnotated ? isActive : undefined, "aria-label": isAnnotated ? `Line ${lineNo} annotation` : undefined, className: cn("flex w-full", isAnnotated && "cursor-pointer", isActive
|
|
149
|
+
return (_jsxs("div", { ref: (node) => setLineRef(lineNo, node), "data-code-line": lineNo, "data-annot-row": isAnnotated ? markers?.[0].index : undefined, tabIndex: isAnnotated ? 0 : undefined, role: isAnnotated ? "button" : undefined, "aria-expanded": isAnnotated ? isActive : undefined, "aria-label": isAnnotated ? `Line ${lineNo} annotation` : undefined, className: cn("relative flex w-full", isAnnotated && "cursor-pointer", isActive
|
|
146
150
|
? "bg-amber-400/20 dark:bg-amber-300/15"
|
|
147
|
-
: isAnnotated
|
|
148
|
-
? "bg-amber-
|
|
149
|
-
:
|
|
151
|
+
: isAnnotated && showAnnotationOverlays
|
|
152
|
+
? "bg-amber-300/25 dark:bg-amber-300/15"
|
|
153
|
+
: isAnnotated
|
|
154
|
+
? "bg-amber-400/[0.07] dark:bg-amber-300/[0.07]"
|
|
155
|
+
: null), onMouseEnter: isAnnotated && markers
|
|
150
156
|
? (event) => {
|
|
151
157
|
const anchor = buildAnchorForRow(event.currentTarget);
|
|
152
158
|
if (anchor)
|
|
@@ -176,8 +182,10 @@ function AnnotatedCodeRead({ data, blockId, title, summary, ctx, }) {
|
|
|
176
182
|
: undefined, onBlur: isAnnotated ? () => hover.scheduleClose() : undefined, children: [_jsx("span", { "aria-hidden": true, className: cn("w-[3px] shrink-0 self-stretch", isAnnotated
|
|
177
183
|
? isActive
|
|
178
184
|
? "bg-amber-500 dark:bg-amber-400"
|
|
179
|
-
:
|
|
180
|
-
|
|
185
|
+
: showAnnotationOverlays
|
|
186
|
+
? "bg-amber-500/90 dark:bg-amber-300/70"
|
|
187
|
+
: "bg-amber-400/45 dark:bg-amber-300/35"
|
|
188
|
+
: null) }), _jsx("span", { className: "w-11 shrink-0 select-none px-3 text-right text-[11px] tabular-nums text-plan-muted/60", children: lineNo }), _jsx("span", { className: "flex-1 whitespace-pre pr-4 text-plan-code-text", children: highlightedLines[lineNo - 1] }), overlayItems.length > 0 && (_jsx(AnnotationInlineOverlayStack, { items: overlayItems, ctx: ctx }))] }, lineNo));
|
|
181
189
|
};
|
|
182
190
|
const codeSurface = (_jsxs("div", { ref: codeRef, className: "overflow-hidden rounded-xl border border-plan-line bg-plan-code", children: [(hasFilename || showLangChip) && (_jsxs("div", { className: "flex items-center gap-2 border-b border-plan-line bg-plan-block/50 px-3.5 py-2", children: [_jsx(IconCode, { className: "size-3.5 shrink-0 text-plan-muted" }), _jsx(CodeFilenameLabel, { filename: data.filename, className: "text-[13px] font-medium", directoryClassName: "text-plan-muted", basenameClassName: "text-plan-code-text" }), showLangChip && (_jsx("span", { className: "shrink-0 rounded border border-plan-line px-1.5 py-0.5 font-mono text-[10px] uppercase tracking-wide text-plan-muted", children: langChip }))] })), _jsx("div", { className: "overflow-x-auto py-1.5", "data-code-surface": true, children: _jsx("div", { className: "min-w-full font-mono [font-size:var(--plan-doc-code-size)] leading-[22px]", children: segments.map((seg) => {
|
|
183
191
|
if (seg.kind === "visible") {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnnotatedCodeBlock.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/AnnotatedCodeBlock.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useMemo, useRef, useState } from \"react\";\nimport { IconCode, IconPlus, IconTrash } from \"@tabler/icons-react\";\nimport { cn } from \"../../utils.js\";\nimport type { BlockEditProps, BlockReadProps } from \"../types.js\";\nimport type {\n AnnotatedCodeAnnotation,\n AnnotatedCodeData,\n} from \"./annotated-code.config.js\";\nimport {\n highlightCode,\n inferLanguageFromFilename,\n normalizeCodeLanguage,\n} from \"./code-highlight.js\";\nimport {\n AnnotationHiddenStack,\n AnnotationHoverCard,\n anchorFromElements,\n buildLineMarkerMap,\n hasRailAnnotations,\n resolveAnnotations,\n useAnnotationHover,\n type ResolvedAnnotation,\n} from \"./annotation-rail.js\";\nimport { CodeFilenameLabel } from \"./code-filename-label.js\";\nimport { DevInput, DevLabel, DevTextarea } from \"./dev-doc-ui.js\";\n\n/**\n * \"Explain this code\" walkthrough block: a standard syntax-highlighted code\n * surface on the left with line-anchored annotation cards on the right (the\n * Stripe-docs / Sourcegraph layout). Each annotated line range gets a subtle\n * highlight band + an accent rail down the gutter; its card shows the `lines`\n * range, optional `label`, and the always-visible markdown `note` (via\n * `ctx.renderMarkdown`). Hovering a card highlights its lines and vice-versa.\n *\n * Syntax highlighting reuses the shared `highlightCode` lowlight helper (the same\n * colorful palette as the `code-tabs` block) per line, so it matches the app's\n * standard code styling and supports per-line bands without an async loader. The\n * surface uses the plan `--plan-code*`/`--plan-*` tokens and Tailwind `dark:`\n * pairs, so it reads correctly in BOTH light and dark mode. Code lines render as\n * `<span>`s (never one `<pre>` per line) so they don't pick up document\n * code/pre chrome. Lives in core so any app can register the dev-doc block.\n *\n * Editing is panel-driven (config-style, like the diff/HTML blocks): a monospace\n * code Textarea, filename/language Inputs, and add/remove-able annotation rows.\n */\n\n/* ── Collapse helpers ──────────────────────────────────────────────────────── */\n\n/**\n * Minimum total line count before collapse is considered. Short files render\n * fully expanded regardless of annotation coverage.\n */\nconst COLLAPSE_MIN_TOTAL_LINES = 40;\n\n/**\n * Number of unannotated lines in a run that triggers collapse. Runs at or\n * below this threshold always stay expanded (no expander button).\n */\nconst COLLAPSE_THRESHOLD = 16;\n\n/**\n * Context lines kept visible at each edge of a collapsed run (8 lines of\n * breathing room so the collapsed region is clearly framed).\n */\nconst COLLAPSE_CONTEXT_EDGE = 8;\n\ntype CollapsedSegment = {\n kind: \"collapsed\";\n startLine: number;\n endLine: number;\n};\ntype VisibleSegment = { kind: \"visible\"; startLine: number; endLine: number };\ntype LineSegment = VisibleSegment | CollapsedSegment;\n\n/**\n * Partition line numbers [1..lineCount] into visible and collapsed segments.\n * Annotated lines (and COLLAPSE_CONTEXT_EDGE lines on either side of them) are\n * always visible. Runs of unannotated lines longer than COLLAPSE_THRESHOLD are\n * collapsed. The file header (first COLLAPSE_CONTEXT_EDGE lines) is always\n * visible so context is preserved.\n */\nfunction buildLineSegments(\n lineCount: number,\n lineMarkers: Map<number, Array<{ index: number }>>,\n): LineSegment[] {\n if (lineCount <= COLLAPSE_MIN_TOTAL_LINES) {\n return [{ kind: \"visible\", startLine: 1, endLine: lineCount }];\n }\n\n // Build a boolean array: true if the line must stay visible.\n const mustShow = new Array<boolean>(lineCount + 1).fill(false);\n // File header always visible.\n for (let i = 1; i <= Math.min(COLLAPSE_CONTEXT_EDGE, lineCount); i += 1) {\n mustShow[i] = true;\n }\n // Annotated lines and their context edges.\n for (const lineNo of lineMarkers.keys()) {\n for (\n let i = Math.max(1, lineNo - COLLAPSE_CONTEXT_EDGE);\n i <= Math.min(lineCount, lineNo + COLLAPSE_CONTEXT_EDGE);\n i += 1\n ) {\n mustShow[i] = true;\n }\n }\n\n // Compute initial segments.\n const raw: LineSegment[] = [];\n let segStart = 1;\n let visible = mustShow[1] ?? false;\n for (let i = 2; i <= lineCount; i += 1) {\n const nextVisible = mustShow[i] ?? false;\n if (nextVisible !== visible) {\n raw.push(\n visible\n ? { kind: \"visible\", startLine: segStart, endLine: i - 1 }\n : { kind: \"collapsed\", startLine: segStart, endLine: i - 1 },\n );\n segStart = i;\n visible = nextVisible;\n }\n }\n raw.push(\n visible\n ? { kind: \"visible\", startLine: segStart, endLine: lineCount }\n : { kind: \"collapsed\", startLine: segStart, endLine: lineCount },\n );\n\n // Don't collapse short hidden runs — expand them in-place.\n return raw.map((seg) => {\n if (\n seg.kind === \"collapsed\" &&\n seg.endLine - seg.startLine + 1 <= COLLAPSE_THRESHOLD\n ) {\n return {\n kind: \"visible\",\n startLine: seg.startLine,\n endLine: seg.endLine,\n };\n }\n return seg;\n });\n}\n\n/* ── Read ──────────────────────────────────────────────────────────────────── */\n\nfunction AnnotatedCodeRead({\n data,\n blockId,\n title,\n summary,\n ctx,\n}: BlockReadProps<AnnotatedCodeData>) {\n // On-hover popover (anchored to the right of the code) replaces the old\n // persistent rail: nothing is visible when idle. `codeRef` measures the code\n // block's right edge; `hover` carries the active index + captured geometry.\n const hover = useAnnotationHover();\n const { activeIndex } = hover;\n const codeRef = useRef<HTMLDivElement | null>(null);\n const lineRefs = useRef(new Map<number, HTMLDivElement>());\n\n const setLineRef = (lineNo: number, node: HTMLDivElement | null) => {\n if (node) lineRefs.current.set(lineNo, node);\n else lineRefs.current.delete(lineNo);\n };\n\n const lines = useMemo(\n () => data.code.replace(/\\n$/, \"\").split(\"\\n\"),\n [data.code],\n );\n const lineCount = lines.length;\n\n const language = useMemo(\n () =>\n normalizeCodeLanguage(data.language) ??\n inferLanguageFromFilename(data.filename),\n [data.language, data.filename],\n );\n\n // Highlight each line once; empty lines keep their height with a NBSP.\n const highlightedLines = useMemo(\n () =>\n lines.map((text) => (text.length ? highlightCode(text, language) : \" \")),\n [lines, language],\n );\n\n const resolved = useMemo(\n () => resolveAnnotations(data.annotations, () => lineCount),\n [data.annotations, lineCount],\n );\n\n // line number (1-based) → resolved annotations covering it.\n const lineMarkers = useMemo(() => buildLineMarkerMap(resolved), [resolved]);\n\n const hasAnnotations = hasRailAnnotations(resolved);\n const langChip = data.language?.trim();\n const hasFilename = Boolean(data.filename?.trim());\n const showLangChip = Boolean(langChip && !hasFilename);\n\n // The resolved annotation whose card is currently shown on hover.\n const activeItem =\n useMemo<ResolvedAnnotation<AnnotatedCodeAnnotation> | null>(\n () =>\n activeIndex == null\n ? null\n : (resolved.find((item) => item.index === activeIndex) ?? null),\n [activeIndex, resolved],\n );\n\n // Line-collapse state: a set of collapsed segment start lines that have been\n // expanded by the reader. Starts empty (all segments in their default state).\n const [expandedCollapsed, setExpandedCollapsed] = useState<Set<number>>(\n () => new Set(),\n );\n\n const segments = useMemo(\n () => buildLineSegments(lineCount, lineMarkers),\n [lineCount, lineMarkers],\n );\n\n const renderLine = (lineNo: number) => {\n const markers = lineMarkers.get(lineNo);\n const isAnnotated = !!markers?.length;\n const isActive =\n activeIndex != null && !!markers?.some((m) => m.index === activeIndex);\n\n const buildAnchorForRow = (el: HTMLElement) => {\n if (!markers) return null;\n const primaryMarker = markers[0];\n const anchorLine = primaryMarker.range?.start ?? lineNo;\n const anchorRow = lineRefs.current.get(anchorLine) ?? el;\n return anchorFromElements(codeRef.current, anchorRow);\n };\n\n return (\n <div\n key={lineNo}\n ref={(node) => setLineRef(lineNo, node)}\n data-code-line={lineNo}\n data-annot-row={isAnnotated ? markers?.[0].index : undefined}\n tabIndex={isAnnotated ? 0 : undefined}\n role={isAnnotated ? \"button\" : undefined}\n aria-expanded={isAnnotated ? isActive : undefined}\n aria-label={isAnnotated ? `Line ${lineNo} annotation` : undefined}\n className={cn(\n \"flex w-full\",\n isAnnotated && \"cursor-pointer\",\n isActive\n ? \"bg-amber-400/20 dark:bg-amber-300/15\"\n : isAnnotated\n ? \"bg-amber-400/[0.07] dark:bg-amber-300/[0.07]\"\n : null,\n )}\n onMouseEnter={\n isAnnotated && markers\n ? (event) => {\n const anchor = buildAnchorForRow(event.currentTarget);\n if (anchor) hover.open(markers[0].index, anchor);\n }\n : undefined\n }\n onMouseLeave={isAnnotated ? () => hover.scheduleClose() : undefined}\n onClick={\n isAnnotated && markers\n ? (event) => {\n const anchor = buildAnchorForRow(event.currentTarget);\n if (anchor) hover.open(markers[0].index, anchor);\n }\n : undefined\n }\n onKeyDown={\n isAnnotated && markers\n ? (event) => {\n if (event.key !== \"Enter\" && event.key !== \" \") return;\n event.preventDefault();\n const anchor = buildAnchorForRow(event.currentTarget);\n if (anchor) hover.open(markers[0].index, anchor);\n }\n : undefined\n }\n onFocus={\n isAnnotated && markers\n ? (event) => {\n const anchor = buildAnchorForRow(event.currentTarget);\n if (anchor) hover.open(markers[0].index, anchor);\n }\n : undefined\n }\n onBlur={isAnnotated ? () => hover.scheduleClose() : undefined}\n >\n <span\n aria-hidden\n className={cn(\n \"w-[3px] shrink-0 self-stretch\",\n isAnnotated\n ? isActive\n ? \"bg-amber-500 dark:bg-amber-400\"\n : \"bg-amber-400/45 dark:bg-amber-300/35\"\n : null,\n )}\n />\n <span className=\"w-11 shrink-0 select-none px-3 text-right text-[11px] tabular-nums text-plan-muted/60\">\n {lineNo}\n </span>\n <span className=\"flex-1 whitespace-pre pr-4 text-plan-code-text\">\n {highlightedLines[lineNo - 1]}\n </span>\n </div>\n );\n };\n\n const codeSurface = (\n <div\n ref={codeRef}\n className=\"overflow-hidden rounded-xl border border-plan-line bg-plan-code\"\n >\n {(hasFilename || showLangChip) && (\n <div className=\"flex items-center gap-2 border-b border-plan-line bg-plan-block/50 px-3.5 py-2\">\n <IconCode className=\"size-3.5 shrink-0 text-plan-muted\" />\n <CodeFilenameLabel\n filename={data.filename}\n className=\"text-[13px] font-medium\"\n directoryClassName=\"text-plan-muted\"\n basenameClassName=\"text-plan-code-text\"\n />\n {showLangChip && (\n <span className=\"shrink-0 rounded border border-plan-line px-1.5 py-0.5 font-mono text-[10px] uppercase tracking-wide text-plan-muted\">\n {langChip}\n </span>\n )}\n </div>\n )}\n <div className=\"overflow-x-auto py-1.5\" data-code-surface>\n <div className=\"min-w-full font-mono [font-size:var(--plan-doc-code-size)] leading-[22px]\">\n {segments.map((seg) => {\n if (seg.kind === \"visible\") {\n const lineNos = Array.from(\n { length: seg.endLine - seg.startLine + 1 },\n (_, i) => seg.startLine + i,\n );\n return lineNos.map(renderLine);\n }\n // Collapsed segment — show an expander row.\n const isExpanded = expandedCollapsed.has(seg.startLine);\n const hiddenCount = seg.endLine - seg.startLine + 1;\n if (isExpanded) {\n const lineNos = Array.from(\n { length: hiddenCount },\n (_, i) => seg.startLine + i,\n );\n return lineNos.map(renderLine);\n }\n return (\n <button\n key={`collapse-${seg.startLine}`}\n type=\"button\"\n data-plan-interactive\n onClick={() =>\n setExpandedCollapsed((prev) => {\n const next = new Set(prev);\n next.add(seg.startLine);\n return next;\n })\n }\n className=\"flex w-full cursor-pointer items-center gap-2 border-y border-plan-line/50 bg-plan-block/20 px-3 py-0.5 text-left hover:bg-plan-block/40\"\n >\n <span aria-hidden className=\"w-[3px] shrink-0 self-stretch\" />\n <span className=\"w-8 shrink-0 select-none text-right text-[11px] tabular-nums text-plan-muted/40\">\n ···\n </span>\n <span className=\"flex-1 text-[11px] text-plan-muted/70\">\n {hiddenCount} lines — click to expand\n </span>\n </button>\n );\n })}\n </div>\n </div>\n </div>\n );\n\n return (\n <section className=\"plan-block relative\" data-block-id={blockId}>\n {title && <div className=\"plan-block-label\">{title}</div>}\n {/* The code keeps its full width — no persistent annotation column. Notes\n live in a visually-hidden stack (a11y + tests) and surface ONE at a\n time as an on-hover popover anchored to the right of the code. */}\n {codeSurface}\n {hasAnnotations && <AnnotationHiddenStack items={resolved} ctx={ctx} />}\n {hasAnnotations && activeItem && hover.anchor && (\n <AnnotationHoverCard\n item={activeItem}\n anchor={hover.anchor}\n ctx={ctx}\n onMouseEnter={hover.cancelClose}\n onMouseLeave={hover.scheduleClose}\n onClose={hover.closeForScroll}\n />\n )}\n {summary && <p className=\"mt-5 text-plan-muted\">{summary}</p>}\n </section>\n );\n}\n\n/* ── Edit (panel) ──────────────────────────────────────────────────────────── */\n\nconst codeAreaClass =\n \"min-h-[160px] font-mono [font-size:var(--plan-code-size)] leading-5\";\n\nfunction AnnotatedCodeEdit({\n data,\n onChange,\n editable,\n}: BlockEditProps<AnnotatedCodeData>) {\n const annotations = data.annotations ?? [];\n const patch = (next: Partial<AnnotatedCodeData>) =>\n onChange({ ...data, ...next });\n\n const updateAnnotation = (\n index: number,\n next: Partial<AnnotatedCodeAnnotation>,\n ) =>\n patch({\n annotations: annotations.map((annotation, i) =>\n i === index ? { ...annotation, ...next } : annotation,\n ),\n });\n\n const removeAnnotation = (index: number) =>\n patch({ annotations: annotations.filter((_, i) => i !== index) });\n\n const addAnnotation = () => {\n if (annotations.length >= 80) return; // schema max\n patch({\n annotations: [...annotations, { lines: \"1\", label: \"\", note: \"\" }],\n });\n };\n\n return (\n <div className=\"flex flex-col gap-3\" data-plan-interactive>\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1.5\">\n <DevLabel htmlFor=\"annotated-code-filename\" className=\"text-xs\">\n Filename\n </DevLabel>\n <DevInput\n id=\"annotated-code-filename\"\n value={data.filename ?? \"\"}\n placeholder=\"src/server/auth.ts\"\n disabled={!editable}\n onChange={(event) =>\n patch({ filename: event.target.value || undefined })\n }\n />\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <DevLabel htmlFor=\"annotated-code-language\" className=\"text-xs\">\n Language\n </DevLabel>\n <DevInput\n id=\"annotated-code-language\"\n value={data.language ?? \"\"}\n placeholder=\"ts\"\n disabled={!editable}\n onChange={(event) =>\n patch({ language: event.target.value || undefined })\n }\n />\n </div>\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <DevLabel htmlFor=\"annotated-code-code\" className=\"text-xs\">\n Code\n </DevLabel>\n <DevTextarea\n id=\"annotated-code-code\"\n spellCheck={false}\n className={codeAreaClass}\n value={data.code}\n disabled={!editable}\n onChange={(event) => patch({ code: event.target.value })}\n />\n </div>\n\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex items-center justify-between\">\n <DevLabel className=\"text-xs\">Annotations</DevLabel>\n {editable && annotations.length < 80 && (\n <button\n type=\"button\"\n data-plan-interactive\n onClick={addAnnotation}\n className=\"flex cursor-pointer items-center gap-1 rounded-md px-2 py-1 text-xs font-medium text-plan-muted transition-colors hover:bg-plan-block/60 hover:text-plan-text\"\n >\n <IconPlus className=\"size-3.5\" />\n Add annotation\n </button>\n )}\n </div>\n {annotations.length === 0 && (\n <p className=\"text-xs text-plan-muted\">\n No annotations yet. Add one to anchor a note to a line range.\n </p>\n )}\n {annotations.map((annotation, index) => (\n <div\n key={index}\n className=\"flex flex-col gap-2 rounded-md border border-plan-line bg-plan-block/30 p-2\"\n >\n <div className=\"grid gap-2 sm:grid-cols-[120px_minmax(0,1fr)_auto]\">\n <DevInput\n aria-label={`Annotation ${index + 1} lines`}\n value={annotation.lines}\n placeholder=\"3-5\"\n disabled={!editable}\n onChange={(event) =>\n updateAnnotation(index, { lines: event.target.value })\n }\n />\n <DevInput\n aria-label={`Annotation ${index + 1} label`}\n value={annotation.label ?? \"\"}\n placeholder=\"Label (optional)\"\n disabled={!editable}\n onChange={(event) =>\n updateAnnotation(index, {\n label: event.target.value || undefined,\n })\n }\n />\n {editable && (\n <button\n type=\"button\"\n data-plan-interactive\n aria-label={`Remove annotation ${index + 1}`}\n onClick={() => removeAnnotation(index)}\n className=\"flex size-9 shrink-0 cursor-pointer items-center justify-center rounded-md text-plan-muted transition-colors hover:bg-muted hover:text-foreground\"\n >\n <IconTrash className=\"size-4\" />\n </button>\n )}\n </div>\n <DevTextarea\n aria-label={`Annotation ${index + 1} note`}\n className=\"min-h-[60px] text-sm\"\n value={annotation.note}\n placeholder=\"Explain what these lines do…\"\n disabled={!editable}\n onChange={(event) =>\n updateAnnotation(index, { note: event.target.value })\n }\n />\n </div>\n ))}\n </div>\n </div>\n );\n}\n\nexport { AnnotatedCodeRead, AnnotatedCodeEdit };\n"]}
|
|
1
|
+
{"version":3,"file":"AnnotatedCodeBlock.js","sourceRoot":"","sources":["../../../../src/client/blocks/library/AnnotatedCodeBlock.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useMemo, useRef, useState } from \"react\";\nimport { IconCode, IconPlus, IconTrash } from \"@tabler/icons-react\";\nimport { cn } from \"../../utils.js\";\nimport type { BlockEditProps, BlockReadProps } from \"../types.js\";\nimport type {\n AnnotatedCodeAnnotation,\n AnnotatedCodeData,\n} from \"./annotated-code.config.js\";\nimport {\n highlightCode,\n inferLanguageFromFilename,\n normalizeCodeLanguage,\n} from \"./code-highlight.js\";\nimport {\n AnnotationHiddenStack,\n AnnotationHoverCard,\n AnnotationInlineOverlayStack,\n anchorFromElements,\n buildLineMarkerMap,\n hasRailAnnotations,\n resolveAnnotations,\n useAnnotationHover,\n type ResolvedAnnotation,\n} from \"./annotation-rail.js\";\nimport { CodeFilenameLabel } from \"./code-filename-label.js\";\nimport { DevInput, DevLabel, DevTextarea } from \"./dev-doc-ui.js\";\n\n/**\n * \"Explain this code\" walkthrough block: a standard syntax-highlighted code\n * surface on the left with line-anchored annotation cards on the right (the\n * Stripe-docs / Sourcegraph layout). Each annotated line range gets a subtle\n * highlight band + an accent rail down the gutter; its card shows the `lines`\n * range, optional `label`, and the always-visible markdown `note` (via\n * `ctx.renderMarkdown`). Hovering a card highlights its lines and vice-versa.\n *\n * Syntax highlighting reuses the shared `highlightCode` lowlight helper (the same\n * colorful palette as the `code-tabs` block) per line, so it matches the app's\n * standard code styling and supports per-line bands without an async loader. The\n * surface uses the plan `--plan-code*`/`--plan-*` tokens and Tailwind `dark:`\n * pairs, so it reads correctly in BOTH light and dark mode. Code lines render as\n * `<span>`s (never one `<pre>` per line) so they don't pick up document\n * code/pre chrome. Lives in core so any app can register the dev-doc block.\n *\n * Editing is panel-driven (config-style, like the diff/HTML blocks): a monospace\n * code Textarea, filename/language Inputs, and add/remove-able annotation rows.\n */\n\n/* ── Collapse helpers ──────────────────────────────────────────────────────── */\n\n/**\n * Minimum total line count before collapse is considered. Short files render\n * fully expanded regardless of annotation coverage.\n */\nconst COLLAPSE_MIN_TOTAL_LINES = 40;\n\n/**\n * Number of unannotated lines in a run that triggers collapse. Runs at or\n * below this threshold always stay expanded (no expander button).\n */\nconst COLLAPSE_THRESHOLD = 16;\n\n/**\n * Context lines kept visible at each edge of a collapsed run (8 lines of\n * breathing room so the collapsed region is clearly framed).\n */\nconst COLLAPSE_CONTEXT_EDGE = 8;\n\ntype CollapsedSegment = {\n kind: \"collapsed\";\n startLine: number;\n endLine: number;\n};\ntype VisibleSegment = { kind: \"visible\"; startLine: number; endLine: number };\ntype LineSegment = VisibleSegment | CollapsedSegment;\n\n/**\n * Partition line numbers [1..lineCount] into visible and collapsed segments.\n * Annotated lines (and COLLAPSE_CONTEXT_EDGE lines on either side of them) are\n * always visible. Runs of unannotated lines longer than COLLAPSE_THRESHOLD are\n * collapsed. The file header (first COLLAPSE_CONTEXT_EDGE lines) is always\n * visible so context is preserved.\n */\nfunction buildLineSegments(\n lineCount: number,\n lineMarkers: Map<number, Array<{ index: number }>>,\n): LineSegment[] {\n if (lineCount <= COLLAPSE_MIN_TOTAL_LINES) {\n return [{ kind: \"visible\", startLine: 1, endLine: lineCount }];\n }\n\n // Build a boolean array: true if the line must stay visible.\n const mustShow = new Array<boolean>(lineCount + 1).fill(false);\n // File header always visible.\n for (let i = 1; i <= Math.min(COLLAPSE_CONTEXT_EDGE, lineCount); i += 1) {\n mustShow[i] = true;\n }\n // Annotated lines and their context edges.\n for (const lineNo of lineMarkers.keys()) {\n for (\n let i = Math.max(1, lineNo - COLLAPSE_CONTEXT_EDGE);\n i <= Math.min(lineCount, lineNo + COLLAPSE_CONTEXT_EDGE);\n i += 1\n ) {\n mustShow[i] = true;\n }\n }\n\n // Compute initial segments.\n const raw: LineSegment[] = [];\n let segStart = 1;\n let visible = mustShow[1] ?? false;\n for (let i = 2; i <= lineCount; i += 1) {\n const nextVisible = mustShow[i] ?? false;\n if (nextVisible !== visible) {\n raw.push(\n visible\n ? { kind: \"visible\", startLine: segStart, endLine: i - 1 }\n : { kind: \"collapsed\", startLine: segStart, endLine: i - 1 },\n );\n segStart = i;\n visible = nextVisible;\n }\n }\n raw.push(\n visible\n ? { kind: \"visible\", startLine: segStart, endLine: lineCount }\n : { kind: \"collapsed\", startLine: segStart, endLine: lineCount },\n );\n\n // Don't collapse short hidden runs — expand them in-place.\n return raw.map((seg) => {\n if (\n seg.kind === \"collapsed\" &&\n seg.endLine - seg.startLine + 1 <= COLLAPSE_THRESHOLD\n ) {\n return {\n kind: \"visible\",\n startLine: seg.startLine,\n endLine: seg.endLine,\n };\n }\n return seg;\n });\n}\n\n/* ── Read ──────────────────────────────────────────────────────────────────── */\n\nfunction AnnotatedCodeRead({\n data,\n blockId,\n title,\n summary,\n ctx,\n}: BlockReadProps<AnnotatedCodeData>) {\n // On-hover popover (anchored to the right of the code) replaces the old\n // persistent rail: nothing is visible when idle. `codeRef` measures the code\n // block's right edge; `hover` carries the active index + captured geometry.\n const hover = useAnnotationHover();\n const { activeIndex } = hover;\n const codeRef = useRef<HTMLDivElement | null>(null);\n const lineRefs = useRef(new Map<number, HTMLDivElement>());\n\n const setLineRef = (lineNo: number, node: HTMLDivElement | null) => {\n if (node) lineRefs.current.set(lineNo, node);\n else lineRefs.current.delete(lineNo);\n };\n\n const lines = useMemo(\n () => data.code.replace(/\\n$/, \"\").split(\"\\n\"),\n [data.code],\n );\n const lineCount = lines.length;\n\n const language = useMemo(\n () =>\n normalizeCodeLanguage(data.language) ??\n inferLanguageFromFilename(data.filename),\n [data.language, data.filename],\n );\n\n // Highlight each line once; empty lines keep their height with a NBSP.\n const highlightedLines = useMemo(\n () =>\n lines.map((text) => (text.length ? highlightCode(text, language) : \" \")),\n [lines, language],\n );\n\n const resolved = useMemo(\n () => resolveAnnotations(data.annotations, () => lineCount),\n [data.annotations, lineCount],\n );\n\n // line number (1-based) → resolved annotations covering it.\n const lineMarkers = useMemo(() => buildLineMarkerMap(resolved), [resolved]);\n\n const hasAnnotations = hasRailAnnotations(resolved);\n const showAnnotationOverlays = Boolean(ctx.showCodeAnnotationOverlays);\n const langChip = data.language?.trim();\n const hasFilename = Boolean(data.filename?.trim());\n const showLangChip = Boolean(langChip && !hasFilename);\n\n // The resolved annotation whose card is currently shown on hover.\n const activeItem =\n useMemo<ResolvedAnnotation<AnnotatedCodeAnnotation> | null>(\n () =>\n activeIndex == null\n ? null\n : (resolved.find((item) => item.index === activeIndex) ?? null),\n [activeIndex, resolved],\n );\n\n // Line-collapse state: a set of collapsed segment start lines that have been\n // expanded by the reader. Starts empty (all segments in their default state).\n const [expandedCollapsed, setExpandedCollapsed] = useState<Set<number>>(\n () => new Set(),\n );\n\n const segments = useMemo(\n () => buildLineSegments(lineCount, lineMarkers),\n [lineCount, lineMarkers],\n );\n\n const renderLine = (lineNo: number) => {\n const markers = lineMarkers.get(lineNo);\n const isAnnotated = !!markers?.length;\n const isActive =\n activeIndex != null && !!markers?.some((m) => m.index === activeIndex);\n const overlayItems =\n showAnnotationOverlays && markers\n ? markers.filter((item) => item.range?.start === lineNo)\n : [];\n\n const buildAnchorForRow = (el: HTMLElement) => {\n if (!markers) return null;\n const primaryMarker = markers[0];\n const anchorLine = primaryMarker.range?.start ?? lineNo;\n const anchorRow = lineRefs.current.get(anchorLine) ?? el;\n return anchorFromElements(codeRef.current, anchorRow);\n };\n\n return (\n <div\n key={lineNo}\n ref={(node) => setLineRef(lineNo, node)}\n data-code-line={lineNo}\n data-annot-row={isAnnotated ? markers?.[0].index : undefined}\n tabIndex={isAnnotated ? 0 : undefined}\n role={isAnnotated ? \"button\" : undefined}\n aria-expanded={isAnnotated ? isActive : undefined}\n aria-label={isAnnotated ? `Line ${lineNo} annotation` : undefined}\n className={cn(\n \"relative flex w-full\",\n isAnnotated && \"cursor-pointer\",\n isActive\n ? \"bg-amber-400/20 dark:bg-amber-300/15\"\n : isAnnotated && showAnnotationOverlays\n ? \"bg-amber-300/25 dark:bg-amber-300/15\"\n : isAnnotated\n ? \"bg-amber-400/[0.07] dark:bg-amber-300/[0.07]\"\n : null,\n )}\n onMouseEnter={\n isAnnotated && markers\n ? (event) => {\n const anchor = buildAnchorForRow(event.currentTarget);\n if (anchor) hover.open(markers[0].index, anchor);\n }\n : undefined\n }\n onMouseLeave={isAnnotated ? () => hover.scheduleClose() : undefined}\n onClick={\n isAnnotated && markers\n ? (event) => {\n const anchor = buildAnchorForRow(event.currentTarget);\n if (anchor) hover.open(markers[0].index, anchor);\n }\n : undefined\n }\n onKeyDown={\n isAnnotated && markers\n ? (event) => {\n if (event.key !== \"Enter\" && event.key !== \" \") return;\n event.preventDefault();\n const anchor = buildAnchorForRow(event.currentTarget);\n if (anchor) hover.open(markers[0].index, anchor);\n }\n : undefined\n }\n onFocus={\n isAnnotated && markers\n ? (event) => {\n const anchor = buildAnchorForRow(event.currentTarget);\n if (anchor) hover.open(markers[0].index, anchor);\n }\n : undefined\n }\n onBlur={isAnnotated ? () => hover.scheduleClose() : undefined}\n >\n <span\n aria-hidden\n className={cn(\n \"w-[3px] shrink-0 self-stretch\",\n isAnnotated\n ? isActive\n ? \"bg-amber-500 dark:bg-amber-400\"\n : showAnnotationOverlays\n ? \"bg-amber-500/90 dark:bg-amber-300/70\"\n : \"bg-amber-400/45 dark:bg-amber-300/35\"\n : null,\n )}\n />\n <span className=\"w-11 shrink-0 select-none px-3 text-right text-[11px] tabular-nums text-plan-muted/60\">\n {lineNo}\n </span>\n <span className=\"flex-1 whitespace-pre pr-4 text-plan-code-text\">\n {highlightedLines[lineNo - 1]}\n </span>\n {overlayItems.length > 0 && (\n <AnnotationInlineOverlayStack items={overlayItems} ctx={ctx} />\n )}\n </div>\n );\n };\n\n const codeSurface = (\n <div\n ref={codeRef}\n className=\"overflow-hidden rounded-xl border border-plan-line bg-plan-code\"\n >\n {(hasFilename || showLangChip) && (\n <div className=\"flex items-center gap-2 border-b border-plan-line bg-plan-block/50 px-3.5 py-2\">\n <IconCode className=\"size-3.5 shrink-0 text-plan-muted\" />\n <CodeFilenameLabel\n filename={data.filename}\n className=\"text-[13px] font-medium\"\n directoryClassName=\"text-plan-muted\"\n basenameClassName=\"text-plan-code-text\"\n />\n {showLangChip && (\n <span className=\"shrink-0 rounded border border-plan-line px-1.5 py-0.5 font-mono text-[10px] uppercase tracking-wide text-plan-muted\">\n {langChip}\n </span>\n )}\n </div>\n )}\n <div className=\"overflow-x-auto py-1.5\" data-code-surface>\n <div className=\"min-w-full font-mono [font-size:var(--plan-doc-code-size)] leading-[22px]\">\n {segments.map((seg) => {\n if (seg.kind === \"visible\") {\n const lineNos = Array.from(\n { length: seg.endLine - seg.startLine + 1 },\n (_, i) => seg.startLine + i,\n );\n return lineNos.map(renderLine);\n }\n // Collapsed segment — show an expander row.\n const isExpanded = expandedCollapsed.has(seg.startLine);\n const hiddenCount = seg.endLine - seg.startLine + 1;\n if (isExpanded) {\n const lineNos = Array.from(\n { length: hiddenCount },\n (_, i) => seg.startLine + i,\n );\n return lineNos.map(renderLine);\n }\n return (\n <button\n key={`collapse-${seg.startLine}`}\n type=\"button\"\n data-plan-interactive\n onClick={() =>\n setExpandedCollapsed((prev) => {\n const next = new Set(prev);\n next.add(seg.startLine);\n return next;\n })\n }\n className=\"flex w-full cursor-pointer items-center gap-2 border-y border-plan-line/50 bg-plan-block/20 px-3 py-0.5 text-left hover:bg-plan-block/40\"\n >\n <span aria-hidden className=\"w-[3px] shrink-0 self-stretch\" />\n <span className=\"w-8 shrink-0 select-none text-right text-[11px] tabular-nums text-plan-muted/40\">\n ···\n </span>\n <span className=\"flex-1 text-[11px] text-plan-muted/70\">\n {hiddenCount} lines — click to expand\n </span>\n </button>\n );\n })}\n </div>\n </div>\n </div>\n );\n\n return (\n <section className=\"plan-block relative\" data-block-id={blockId}>\n {title && <div className=\"plan-block-label\">{title}</div>}\n {/* The code keeps its full width — no persistent annotation column. Notes\n live in a visually-hidden stack (a11y + tests) and surface ONE at a\n time as an on-hover popover anchored to the right of the code. */}\n {codeSurface}\n {hasAnnotations && <AnnotationHiddenStack items={resolved} ctx={ctx} />}\n {hasAnnotations && activeItem && hover.anchor && (\n <AnnotationHoverCard\n item={activeItem}\n anchor={hover.anchor}\n ctx={ctx}\n onMouseEnter={hover.cancelClose}\n onMouseLeave={hover.scheduleClose}\n onClose={hover.closeForScroll}\n />\n )}\n {summary && <p className=\"mt-5 text-plan-muted\">{summary}</p>}\n </section>\n );\n}\n\n/* ── Edit (panel) ──────────────────────────────────────────────────────────── */\n\nconst codeAreaClass =\n \"min-h-[160px] font-mono [font-size:var(--plan-code-size)] leading-5\";\n\nfunction AnnotatedCodeEdit({\n data,\n onChange,\n editable,\n}: BlockEditProps<AnnotatedCodeData>) {\n const annotations = data.annotations ?? [];\n const patch = (next: Partial<AnnotatedCodeData>) =>\n onChange({ ...data, ...next });\n\n const updateAnnotation = (\n index: number,\n next: Partial<AnnotatedCodeAnnotation>,\n ) =>\n patch({\n annotations: annotations.map((annotation, i) =>\n i === index ? { ...annotation, ...next } : annotation,\n ),\n });\n\n const removeAnnotation = (index: number) =>\n patch({ annotations: annotations.filter((_, i) => i !== index) });\n\n const addAnnotation = () => {\n if (annotations.length >= 80) return; // schema max\n patch({\n annotations: [...annotations, { lines: \"1\", label: \"\", note: \"\" }],\n });\n };\n\n return (\n <div className=\"flex flex-col gap-3\" data-plan-interactive>\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"flex flex-col gap-1.5\">\n <DevLabel htmlFor=\"annotated-code-filename\" className=\"text-xs\">\n Filename\n </DevLabel>\n <DevInput\n id=\"annotated-code-filename\"\n value={data.filename ?? \"\"}\n placeholder=\"src/server/auth.ts\"\n disabled={!editable}\n onChange={(event) =>\n patch({ filename: event.target.value || undefined })\n }\n />\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <DevLabel htmlFor=\"annotated-code-language\" className=\"text-xs\">\n Language\n </DevLabel>\n <DevInput\n id=\"annotated-code-language\"\n value={data.language ?? \"\"}\n placeholder=\"ts\"\n disabled={!editable}\n onChange={(event) =>\n patch({ language: event.target.value || undefined })\n }\n />\n </div>\n </div>\n\n <div className=\"flex flex-col gap-1.5\">\n <DevLabel htmlFor=\"annotated-code-code\" className=\"text-xs\">\n Code\n </DevLabel>\n <DevTextarea\n id=\"annotated-code-code\"\n spellCheck={false}\n className={codeAreaClass}\n value={data.code}\n disabled={!editable}\n onChange={(event) => patch({ code: event.target.value })}\n />\n </div>\n\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex items-center justify-between\">\n <DevLabel className=\"text-xs\">Annotations</DevLabel>\n {editable && annotations.length < 80 && (\n <button\n type=\"button\"\n data-plan-interactive\n onClick={addAnnotation}\n className=\"flex cursor-pointer items-center gap-1 rounded-md px-2 py-1 text-xs font-medium text-plan-muted transition-colors hover:bg-plan-block/60 hover:text-plan-text\"\n >\n <IconPlus className=\"size-3.5\" />\n Add annotation\n </button>\n )}\n </div>\n {annotations.length === 0 && (\n <p className=\"text-xs text-plan-muted\">\n No annotations yet. Add one to anchor a note to a line range.\n </p>\n )}\n {annotations.map((annotation, index) => (\n <div\n key={index}\n className=\"flex flex-col gap-2 rounded-md border border-plan-line bg-plan-block/30 p-2\"\n >\n <div className=\"grid gap-2 sm:grid-cols-[120px_minmax(0,1fr)_auto]\">\n <DevInput\n aria-label={`Annotation ${index + 1} lines`}\n value={annotation.lines}\n placeholder=\"3-5\"\n disabled={!editable}\n onChange={(event) =>\n updateAnnotation(index, { lines: event.target.value })\n }\n />\n <DevInput\n aria-label={`Annotation ${index + 1} label`}\n value={annotation.label ?? \"\"}\n placeholder=\"Label (optional)\"\n disabled={!editable}\n onChange={(event) =>\n updateAnnotation(index, {\n label: event.target.value || undefined,\n })\n }\n />\n {editable && (\n <button\n type=\"button\"\n data-plan-interactive\n aria-label={`Remove annotation ${index + 1}`}\n onClick={() => removeAnnotation(index)}\n className=\"flex size-9 shrink-0 cursor-pointer items-center justify-center rounded-md text-plan-muted transition-colors hover:bg-muted hover:text-foreground\"\n >\n <IconTrash className=\"size-4\" />\n </button>\n )}\n </div>\n <DevTextarea\n aria-label={`Annotation ${index + 1} note`}\n className=\"min-h-[60px] text-sm\"\n value={annotation.note}\n placeholder=\"Explain what these lines do…\"\n disabled={!editable}\n onChange={(event) =>\n updateAnnotation(index, { note: event.target.value })\n }\n />\n </div>\n ))}\n </div>\n </div>\n );\n}\n\nexport { AnnotatedCodeRead, AnnotatedCodeEdit };\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DiffBlock.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/DiffBlock.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"DiffBlock.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/DiffBlock.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EAEf,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAkB,QAAQ,EAAY,MAAM,kBAAkB,CAAC;AAgB3E;;;;;;;;;;;;;;;GAeG;AAIH,UAAU,MAAM;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAqBD;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAsEjE;AAoeD,iBAAS,QAAQ,CAAC,EAChB,IAAI,EACJ,OAAO,EACP,KAAK,EACL,OAAO,EACP,GAAG,GACJ,EAAE,cAAc,CAAC,QAAQ,CAAC,2CAuT1B;AA0hBD,iBAAS,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,cAAc,CAAC,QAAQ,CAAC,2CA2LvE;AAED,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC"}
|