@loucompanion/forge-bridge 0.1.3-dev.ab8510b71f9b → 0.1.3-dev.af261f369eae
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/bridge/bridge.service.js +24 -4
- package/dist/bridge/bridge.types.d.ts +4 -0
- package/dist/cli/cli.help.d.ts +2 -0
- package/dist/cli/cli.help.js +171 -0
- package/dist/cli/cli.service.js +8 -183
- package/dist/cli/local-config.d.ts +2 -0
- package/dist/cli/local-config.js +6 -2
- package/dist/session/phase-completion.artifacts.d.ts +10 -0
- package/dist/session/phase-completion.artifacts.js +620 -0
- package/dist/session/phase-completion.d.ts +32 -44
- package/dist/session/phase-completion.helpers.d.ts +112 -0
- package/dist/session/phase-completion.helpers.js +660 -0
- package/dist/session/phase-completion.js +28 -3497
- package/dist/session/phase-completion.prompts.d.ts +14 -0
- package/dist/session/phase-completion.prompts.js +220 -0
- package/dist/session/phase-completion.runtime.d.ts +36 -0
- package/dist/session/phase-completion.runtime.js +609 -0
- package/dist/session/phase-completion.schemas.d.ts +3 -0
- package/dist/session/phase-completion.schemas.js +707 -0
- package/dist/session/phase-completion.validation.d.ts +34 -0
- package/dist/session/phase-completion.validation.js +724 -0
- package/dist/session/provider-cli/provider-cli.artifacts.d.ts +93 -0
- package/dist/session/provider-cli/provider-cli.artifacts.js +754 -0
- package/dist/session/provider-cli/provider-cli.base.d.ts +1 -0
- package/dist/session/provider-cli/provider-cli.deterministic-payloads.d.ts +12 -0
- package/dist/session/provider-cli/provider-cli.deterministic-payloads.js +279 -0
- package/dist/session/provider-cli/provider-cli.deterministic.d.ts +14 -0
- package/dist/session/provider-cli/provider-cli.deterministic.js +329 -0
- package/dist/session/provider-cli/provider-cli.process.d.ts +32 -0
- package/dist/session/provider-cli/provider-cli.process.js +287 -0
- package/dist/session/provider-cli/provider-cli.prompts.d.ts +44 -0
- package/dist/session/provider-cli/provider-cli.prompts.js +528 -0
- package/dist/session/provider-cli/provider-cli.qa-sidecars.d.ts +11 -0
- package/dist/session/provider-cli/provider-cli.qa-sidecars.js +65 -0
- package/dist/session/provider-cli/provider-cli.runtime.d.ts +9 -0
- package/dist/session/provider-cli/provider-cli.runtime.js +40 -0
- package/dist/session/provider-cli/provider-cli.service.d.ts +9 -53
- package/dist/session/provider-cli/provider-cli.service.js +161 -2561
- package/dist/session/provider-cli/provider-cli.types.d.ts +1 -0
- package/dist/session/provider-cli/provider-output-state.d.ts +20 -0
- package/dist/session/provider-cli/provider-output-state.js +445 -0
- package/dist/session/session.service.js +30 -23
- package/dist/session/session.types.d.ts +48 -0
- package/dist/session/session.types.js +90 -1
- package/dist/shared/process/windows-launch.d.ts +8 -0
- package/dist/shared/process/windows-launch.js +41 -0
- package/dist/shared/provider-capabilities.d.ts +1 -0
- package/dist/shared/provider-capabilities.js +3 -0
- package/dist/shared/redaction/redaction.js +4 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worktree/dependency-warmer.d.ts +11 -0
- package/dist/worktree/dependency-warmer.js +45 -1
- package/package.json +1 -1
|
@@ -26,6 +26,7 @@ export function parseRunOnceDispatchPacket(value) {
|
|
|
26
26
|
architectDependencies: parseArchitectDependencies(packet.architectDependencies),
|
|
27
27
|
storyDevelop: parseStoryDevelop(packet.storyDevelop),
|
|
28
28
|
storyQa: parseStoryQa(packet.storyQa),
|
|
29
|
+
designerRefs: parseDesignerRefs(packet.designerRefs ?? packet.designer_refs),
|
|
29
30
|
draft: parseDraftPrompt(packet.draft)
|
|
30
31
|
};
|
|
31
32
|
}
|
|
@@ -120,9 +121,45 @@ function parseDraftPrompt(value) {
|
|
|
120
121
|
return {
|
|
121
122
|
kind: requiredString(draft, "kind"),
|
|
122
123
|
systemPrompt: requiredString(draft, "systemPrompt"),
|
|
123
|
-
userPrompt: requiredString(draft, "userPrompt")
|
|
124
|
+
userPrompt: requiredString(draft, "userPrompt"),
|
|
125
|
+
projectName: optionalString(draft, "projectName"),
|
|
126
|
+
repoName: optionalString(draft, "repoName"),
|
|
127
|
+
attachments: parseDraftAttachments(draft.attachments)
|
|
124
128
|
};
|
|
125
129
|
}
|
|
130
|
+
function parseDraftAttachments(value) {
|
|
131
|
+
if (value === undefined || value === null) {
|
|
132
|
+
return [];
|
|
133
|
+
}
|
|
134
|
+
if (!Array.isArray(value)) {
|
|
135
|
+
throw new Error("draft.attachments must be an array when provided.");
|
|
136
|
+
}
|
|
137
|
+
return value.map((entry, index) => {
|
|
138
|
+
const attachment = asObject(entry, `draft.attachments[${index}]`);
|
|
139
|
+
const kind = requiredString(attachment, "kind").trim().toLowerCase();
|
|
140
|
+
if (kind !== "text" && kind !== "image") {
|
|
141
|
+
throw new Error(`draft.attachments[${index}].kind must be text or image.`);
|
|
142
|
+
}
|
|
143
|
+
const textContent = optionalString(attachment, "textContent");
|
|
144
|
+
const contentBase64 = optionalString(attachment, "contentBase64");
|
|
145
|
+
if (kind === "text" && textContent === null) {
|
|
146
|
+
throw new Error(`draft.attachments[${index}].textContent is required for text attachments.`);
|
|
147
|
+
}
|
|
148
|
+
if (kind === "image" && contentBase64 === null) {
|
|
149
|
+
throw new Error(`draft.attachments[${index}].contentBase64 is required for image attachments.`);
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
index: optionalNonNegativeInteger(attachment, "index") ?? index,
|
|
153
|
+
fileName: requiredString(attachment, "fileName"),
|
|
154
|
+
contentType: optionalString(attachment, "contentType") ?? "",
|
|
155
|
+
kind,
|
|
156
|
+
byteCount: optionalNonNegativeInteger(attachment, "byteCount") ?? 0,
|
|
157
|
+
summary: optionalString(attachment, "summary") ?? "",
|
|
158
|
+
textContent,
|
|
159
|
+
contentBase64
|
|
160
|
+
};
|
|
161
|
+
});
|
|
162
|
+
}
|
|
126
163
|
function parseApiKeySecretGrant(value) {
|
|
127
164
|
if (value === undefined || value === null) {
|
|
128
165
|
return null;
|
|
@@ -416,6 +453,58 @@ function parseStoryQaDependencies(value) {
|
|
|
416
453
|
};
|
|
417
454
|
});
|
|
418
455
|
}
|
|
456
|
+
function parseDesignerRefs(value) {
|
|
457
|
+
if (value === undefined || value === null) {
|
|
458
|
+
return null;
|
|
459
|
+
}
|
|
460
|
+
const context = asObject(value, "designerRefs");
|
|
461
|
+
const refs = context.refs;
|
|
462
|
+
if (!Array.isArray(refs)) {
|
|
463
|
+
throw new Error("designerRefs.refs must be an array.");
|
|
464
|
+
}
|
|
465
|
+
return {
|
|
466
|
+
schemaVersion: requiredNumber(context, "schemaVersion"),
|
|
467
|
+
kind: requiredString(context, "kind"),
|
|
468
|
+
ownerType: requiredString(context, "ownerType"),
|
|
469
|
+
ownerId: requiredString(context, "ownerId"),
|
|
470
|
+
projectId: requiredString(context, "projectId"),
|
|
471
|
+
repoId: requiredString(context, "repoId"),
|
|
472
|
+
title: requiredString(context, "title"),
|
|
473
|
+
refs: refs.map((entry, index) => parseDesignerRefAttachment(entry, index))
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
function parseDesignerRefAttachment(value, index) {
|
|
477
|
+
const attachment = asObject(value, `designerRefs.refs[${index}]`);
|
|
478
|
+
return {
|
|
479
|
+
ref: parseDesignerRef(attachment.ref, index),
|
|
480
|
+
reason: optionalString(attachment, "reason") ?? "",
|
|
481
|
+
required: requiredBoolean(attachment, "required"),
|
|
482
|
+
source: optionalString(attachment, "source") ?? "",
|
|
483
|
+
lineageKind: optionalString(attachment, "lineageKind") ?? optionalString(attachment, "lineage_kind") ?? "",
|
|
484
|
+
inheritedFromItemType: optionalString(attachment, "inheritedFromItemType") ?? optionalString(attachment, "inherited_from_item_type"),
|
|
485
|
+
inheritedFromItemId: optionalString(attachment, "inheritedFromItemId") ?? optionalString(attachment, "inherited_from_item_id"),
|
|
486
|
+
inheritedFromDesignerRefId: optionalString(attachment, "inheritedFromDesignerRefId") ?? optionalString(attachment, "inherited_from_designer_ref_id"),
|
|
487
|
+
addedByLane: optionalString(attachment, "addedByLane") ?? optionalString(attachment, "added_by_lane") ?? "",
|
|
488
|
+
sortOrder: requiredNumber(attachment, "sortOrder"),
|
|
489
|
+
createdAt: requiredString(attachment, "createdAt")
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
function parseDesignerRef(value, index) {
|
|
493
|
+
const designerRef = asObject(value, `designerRefs.refs[${index}].ref`);
|
|
494
|
+
return {
|
|
495
|
+
id: requiredString(designerRef, "id"),
|
|
496
|
+
projectId: requiredString(designerRef, "projectId"),
|
|
497
|
+
repoId: requiredString(designerRef, "repoId"),
|
|
498
|
+
refKey: requiredString(designerRef, "refKey"),
|
|
499
|
+
kind: requiredString(designerRef, "kind"),
|
|
500
|
+
path: requiredString(designerRef, "path"),
|
|
501
|
+
anchor: optionalString(designerRef, "anchor"),
|
|
502
|
+
title: optionalString(designerRef, "title") ?? "",
|
|
503
|
+
contentHash: requiredString(designerRef, "contentHash"),
|
|
504
|
+
commitSha: requiredString(designerRef, "commitSha"),
|
|
505
|
+
createdAt: requiredString(designerRef, "createdAt")
|
|
506
|
+
};
|
|
507
|
+
}
|
|
419
508
|
function parseStringArray(value, label) {
|
|
420
509
|
if (!Array.isArray(value)) {
|
|
421
510
|
throw new Error(`${label} must be an array.`);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface LaunchCommand {
|
|
2
|
+
readonly command: string;
|
|
3
|
+
readonly args: readonly string[];
|
|
4
|
+
}
|
|
5
|
+
export declare function buildWindowsCmdLaunch(command: string, args: readonly string[], comSpec?: string | undefined): LaunchCommand;
|
|
6
|
+
export declare function buildWindowsLaunchCommand(commandPath: string, args: readonly string[]): LaunchCommand;
|
|
7
|
+
export declare function windowsCommandLine(command: string, args: readonly string[]): string;
|
|
8
|
+
export declare function quoteWindowsCommandLineArg(value: string): string;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
export function buildWindowsCmdLaunch(command, args, comSpec = process.env.ComSpec) {
|
|
3
|
+
const resolvedComSpec = comSpec?.trim();
|
|
4
|
+
const commandLine = windowsCommandLine(command, args);
|
|
5
|
+
const cmdPayload = commandLine.startsWith('"') ? `"${commandLine}"` : commandLine;
|
|
6
|
+
return {
|
|
7
|
+
command: resolvedComSpec || "cmd.exe",
|
|
8
|
+
args: ["/d", "/s", "/v:off", "/c", cmdPayload]
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export function buildWindowsLaunchCommand(commandPath, args) {
|
|
12
|
+
const extension = path.extname(commandPath).toLowerCase();
|
|
13
|
+
if (extension === ".ps1") {
|
|
14
|
+
return {
|
|
15
|
+
command: powershellExecutable(),
|
|
16
|
+
args: ["-NoProfile", "-ExecutionPolicy", "Bypass", "-File", commandPath, ...args]
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
if (extension === ".cmd" || extension === ".bat") {
|
|
20
|
+
return buildWindowsCmdLaunch(commandPath, args);
|
|
21
|
+
}
|
|
22
|
+
return { command: commandPath, args };
|
|
23
|
+
}
|
|
24
|
+
export function windowsCommandLine(command, args) {
|
|
25
|
+
return [command, ...args].map(quoteWindowsCommandLineArg).join(" ");
|
|
26
|
+
}
|
|
27
|
+
export function quoteWindowsCommandLineArg(value) {
|
|
28
|
+
const escaped = value
|
|
29
|
+
.replace(/\^/g, "^^")
|
|
30
|
+
.replace(/%/g, "^%");
|
|
31
|
+
if (escaped.length > 0 && !/[\s"&|<>()^%!]/.test(escaped)) {
|
|
32
|
+
return escaped;
|
|
33
|
+
}
|
|
34
|
+
return `"${escaped.replace(/(\\*)"/g, '$1$1\\"').replace(/(\\+)$/g, "$1$1")}"`;
|
|
35
|
+
}
|
|
36
|
+
function powershellExecutable() {
|
|
37
|
+
const systemRoot = process.env.SystemRoot;
|
|
38
|
+
return systemRoot
|
|
39
|
+
? path.join(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe")
|
|
40
|
+
: "powershell.exe";
|
|
41
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function supportsDraftImageAttachmentsFor(cliProviders: readonly string[]): boolean;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
const secretKeyPattern = /(api[_-]?key|authorization|bearer|client[_-]?secret|password|secret|token)/i;
|
|
2
|
+
const attachmentContentKeyPattern = /^(textContent|contentBase64)$/i;
|
|
3
|
+
const serializedAttachmentContentPattern = /("(?:textContent|contentBase64)"\s*:\s*")(?:(?:\\.)|[^"\\])*(")/gi;
|
|
2
4
|
export function redactSecrets(value, exactSecrets = []) {
|
|
3
5
|
return redactValue(value, exactSecrets);
|
|
4
6
|
}
|
|
5
7
|
export function redactText(value, exactSecrets = []) {
|
|
6
|
-
let redacted = value;
|
|
8
|
+
let redacted = value.replace(serializedAttachmentContentPattern, "$1[REDACTED]$2");
|
|
7
9
|
for (const secret of exactSecrets) {
|
|
8
10
|
if (secret.length > 0) {
|
|
9
11
|
redacted = redacted.split(secret).join("[REDACTED]");
|
|
@@ -25,6 +27,6 @@ function redactValue(value, exactSecrets) {
|
|
|
25
27
|
}
|
|
26
28
|
return Object.fromEntries(Object.entries(value).map(([key, item]) => [
|
|
27
29
|
key,
|
|
28
|
-
secretKeyPattern.test(key) ? "[REDACTED]" : redactValue(item, exactSecrets)
|
|
30
|
+
secretKeyPattern.test(key) || attachmentContentKeyPattern.test(key) ? "[REDACTED]" : redactValue(item, exactSecrets)
|
|
29
31
|
]));
|
|
30
32
|
}
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const forgeBridgeVersion = "0.1.3-dev.
|
|
1
|
+
export declare const forgeBridgeVersion = "0.1.3-dev.af261f369eae";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const forgeBridgeVersion = "0.1.3-dev.
|
|
1
|
+
export const forgeBridgeVersion = "0.1.3-dev.af261f369eae";
|
|
@@ -30,3 +30,14 @@ export declare function createDirectoryLink(sourcePath: string, targetPath: stri
|
|
|
30
30
|
export declare function lockfilesDiffer(baseCheckoutPath: string, worktreePath: string, packageRootRelative: string): Promise<boolean>;
|
|
31
31
|
export declare function requiresInstallFallback(entry: WarmPathEntry, baseCheckoutPath: string, worktreePath: string, sourceExists: boolean): Promise<string | null>;
|
|
32
32
|
export declare function declaresNativeModules(packageRootPath: string): Promise<boolean>;
|
|
33
|
+
export interface NpmLaunchOptions {
|
|
34
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
35
|
+
readonly execPath?: string;
|
|
36
|
+
readonly platform?: NodeJS.Platform;
|
|
37
|
+
readonly homeDir?: string;
|
|
38
|
+
readonly candidates?: readonly string[];
|
|
39
|
+
}
|
|
40
|
+
export declare function resolveNpmLaunch(args: readonly string[], options?: NpmLaunchOptions): {
|
|
41
|
+
command: string;
|
|
42
|
+
args: readonly string[];
|
|
43
|
+
};
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { existsSync, realpathSync } from "node:fs";
|
|
1
2
|
import fs from "node:fs/promises";
|
|
3
|
+
import os from "node:os";
|
|
2
4
|
import path from "node:path";
|
|
3
5
|
import { NodeProcessRunner } from "../shared/process/process.js";
|
|
6
|
+
import { buildWindowsCmdLaunch } from "../shared/process/windows-launch.js";
|
|
4
7
|
import { isSubPath } from "../shared/path/path.js";
|
|
5
8
|
const SKIP_DIR_NAMES = new Set([
|
|
6
9
|
".git",
|
|
@@ -184,7 +187,8 @@ async function runInstallFallback(entry, worktreePath, reason, executor) {
|
|
|
184
187
|
if (entry.ecosystem === "node") {
|
|
185
188
|
const lockPath = path.join(cwd, "package-lock.json");
|
|
186
189
|
const args = (await pathExists(lockPath)) ? ["ci"] : ["install"];
|
|
187
|
-
|
|
190
|
+
const launch = resolveNpmLaunch(args);
|
|
191
|
+
await executor.run(cwd, launch.command, launch.args);
|
|
188
192
|
return { ecosystem: entry.ecosystem, packageRoot: entry.packageRoot, reason, command: `npm ${args.join(" ")}` };
|
|
189
193
|
}
|
|
190
194
|
if (entry.ecosystem === "python") {
|
|
@@ -286,6 +290,46 @@ async function sha256File(filePath) {
|
|
|
286
290
|
const content = await fs.readFile(filePath);
|
|
287
291
|
return crypto.createHash("sha256").update(content).digest("hex");
|
|
288
292
|
}
|
|
293
|
+
export function resolveNpmLaunch(args, options = {}) {
|
|
294
|
+
const env = options.env ?? process.env;
|
|
295
|
+
const execPath = options.execPath ?? process.execPath;
|
|
296
|
+
const npmExecPath = env.npm_execpath;
|
|
297
|
+
if (npmExecPath) {
|
|
298
|
+
return { command: execPath, args: [npmExecPath, ...args] };
|
|
299
|
+
}
|
|
300
|
+
const platform = options.platform ?? process.platform;
|
|
301
|
+
if (platform === "win32") {
|
|
302
|
+
const comSpec = options.env ? env.ComSpec ?? "cmd.exe" : env.ComSpec;
|
|
303
|
+
return buildWindowsCmdLaunch("npm.cmd", args, comSpec);
|
|
304
|
+
}
|
|
305
|
+
for (const candidate of options.candidates ?? defaultNpmCliCandidates(execPath, options.homeDir ?? os.homedir())) {
|
|
306
|
+
const resolvedCandidate = tryResolveNpmCandidate(candidate);
|
|
307
|
+
if (resolvedCandidate) {
|
|
308
|
+
return { command: execPath, args: [resolvedCandidate, ...args] };
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
return { command: "npm", args };
|
|
312
|
+
}
|
|
313
|
+
function tryResolveNpmCandidate(candidate) {
|
|
314
|
+
try {
|
|
315
|
+
if (!existsSync(candidate)) {
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
318
|
+
return realpathSync(candidate);
|
|
319
|
+
}
|
|
320
|
+
catch {
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
function defaultNpmCliCandidates(execPath, homeDir) {
|
|
325
|
+
const candidates = [];
|
|
326
|
+
const execDir = path.dirname(execPath);
|
|
327
|
+
if (path.isAbsolute(execDir)) {
|
|
328
|
+
candidates.push(path.join(execDir, "npm"), path.join(execDir, "npm-cli.js"), path.join(execDir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js"));
|
|
329
|
+
}
|
|
330
|
+
candidates.push("/usr/bin/npm", "/usr/local/bin/npm", path.join(homeDir, ".npm-global", "bin", "npm"), path.join(homeDir, ".npm-global", "lib", "node_modules", "npm", "bin", "npm-cli.js"));
|
|
331
|
+
return candidates;
|
|
332
|
+
}
|
|
289
333
|
const defaultCommandExecutor = {
|
|
290
334
|
async run(cwd, command, args) {
|
|
291
335
|
const result = await defaultProcessRunner.run({ command, cwd, args });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loucompanion/forge-bridge",
|
|
3
|
-
"version": "0.1.3-dev.
|
|
3
|
+
"version": "0.1.3-dev.af261f369eae",
|
|
4
4
|
"description": "Forge runner bridge CLI for connecting local developer machines to Forge dispatch.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|