@loucompanion/forge-bridge 0.1.3-dev.0b2f81d660c0 → 0.1.3-dev.34ddcb672775
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 +1 -4
- package/dist/cli/cli.service.js +1 -2
- package/dist/session/phase-completion.artifacts.js +2 -23
- package/dist/session/provider-cli/provider-cli.prompts.d.ts +0 -1
- package/dist/session/provider-cli/provider-cli.prompts.js +0 -3
- package/dist/session/provider-cli/provider-cli.service.js +12 -32
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/dist/shared/provider-capabilities.d.ts +0 -1
- package/dist/shared/provider-capabilities.js +0 -3
|
@@ -2,7 +2,6 @@ import { HubConnectionBuilder, HttpTransportType, LogLevel } from "@microsoft/si
|
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { defaultForgeBridgeConfig } from "../config.js";
|
|
5
|
-
import { supportsDraftImageAttachmentsFor } from "../shared/provider-capabilities.js";
|
|
6
5
|
import { redactSecrets, redactText } from "../shared/redaction/redaction.js";
|
|
7
6
|
import { BridgeSessionService } from "../session/session.service.js";
|
|
8
7
|
import { failureResult, parseRunOnceDispatchPacket } from "../session/session.types.js";
|
|
@@ -352,7 +351,7 @@ export function defaultBridgeServiceConfig(overrides = {}) {
|
|
|
352
351
|
supportsRunnerAuthoredPhaseArtifacts: true,
|
|
353
352
|
supportsDraftRunOnce: true,
|
|
354
353
|
supportsDraftAttachments: true,
|
|
355
|
-
supportsDraftImageAttachments:
|
|
354
|
+
supportsDraftImageAttachments: false,
|
|
356
355
|
version: process.env.FORGE_BRIDGE_VERSION ?? forgeBridgeVersion,
|
|
357
356
|
protocolVersion: 1,
|
|
358
357
|
minServerVersion: null,
|
|
@@ -362,9 +361,7 @@ export function defaultBridgeServiceConfig(overrides = {}) {
|
|
|
362
361
|
};
|
|
363
362
|
return {
|
|
364
363
|
...config,
|
|
365
|
-
providerStatuses: overrides.providerStatuses ?? providerStatusesFor(config.cliProviders),
|
|
366
364
|
sandboxProfiles: config.sandboxProfiles ?? defaultSandboxProfiles(config.cliProviders),
|
|
367
|
-
supportsDraftImageAttachments: (overrides.supportsDraftImageAttachments ?? true) && supportsDraftImageAttachmentsFor(config.cliProviders),
|
|
368
365
|
heartbeatIntervalMs: positiveFiniteNumber(config.heartbeatIntervalMs, 30_000)
|
|
369
366
|
};
|
|
370
367
|
}
|
package/dist/cli/cli.service.js
CHANGED
|
@@ -6,7 +6,6 @@ import { createInterface } from "node:readline/promises";
|
|
|
6
6
|
import { promisify } from "node:util";
|
|
7
7
|
import { resolveCursorAgentDirectLaunch } from "../shared/cursor-agent/cursor-agent.launch.js";
|
|
8
8
|
import { buildWindowsCmdLaunch } from "../shared/process/windows-launch.js";
|
|
9
|
-
import { supportsDraftImageAttachmentsFor } from "../shared/provider-capabilities.js";
|
|
10
9
|
import { redactSecrets, redactText } from "../shared/redaction/redaction.js";
|
|
11
10
|
import { defaultBridgeServiceConfig, ForgeBridgeService } from "../bridge/bridge.service.js";
|
|
12
11
|
import { forgeBridgeVersion } from "../version.js";
|
|
@@ -501,7 +500,7 @@ function pairedConfig(current, args, claim) {
|
|
|
501
500
|
supportsRunnerAuthoredPhaseArtifacts: current.supportsRunnerAuthoredPhaseArtifacts ?? true,
|
|
502
501
|
supportsDraftRunOnce: current.supportsDraftRunOnce ?? true,
|
|
503
502
|
supportsDraftAttachments: current.supportsDraftAttachments ?? true,
|
|
504
|
-
supportsDraftImageAttachments:
|
|
503
|
+
supportsDraftImageAttachments: current.supportsDraftImageAttachments ?? false,
|
|
505
504
|
repoMappings: current.repoMappings ?? []
|
|
506
505
|
};
|
|
507
506
|
}
|
|
@@ -424,7 +424,7 @@ async function synthesizeQaCycleVerdictPayload(config, payload, status) {
|
|
|
424
424
|
]);
|
|
425
425
|
merged.browser_checks = dedupeUnknownArray([
|
|
426
426
|
...qaArray(payload, "browser_checks", payloadEvidence),
|
|
427
|
-
...evidenceGates.flatMap((gate) => qaArray(gate, "browser_checks")
|
|
427
|
+
...evidenceGates.flatMap((gate) => qaArray(gate, "browser_checks"))
|
|
428
428
|
]);
|
|
429
429
|
merged.sidecars = dedupeUnknownArray([
|
|
430
430
|
...qaArray(payload, "sidecars", payloadEvidence),
|
|
@@ -516,27 +516,6 @@ function dedupeStrings(values) {
|
|
|
516
516
|
}
|
|
517
517
|
return deduped;
|
|
518
518
|
}
|
|
519
|
-
function normalizeInheritedQaBrowserCheck(browserCheck) {
|
|
520
|
-
if (!browserCheck || typeof browserCheck !== "object" || Array.isArray(browserCheck)) {
|
|
521
|
-
return browserCheck;
|
|
522
|
-
}
|
|
523
|
-
const record = browserCheck;
|
|
524
|
-
if (optionalString(record, "summary")) {
|
|
525
|
-
return record;
|
|
526
|
-
}
|
|
527
|
-
const target = optionalString(record, "url") ?? optionalString(record, "route") ?? "the configured browser target";
|
|
528
|
-
const status = optionalString(record, "status") ?? "recorded";
|
|
529
|
-
return {
|
|
530
|
-
...record,
|
|
531
|
-
summary: `Inherited browser check ${status} for ${target}.`
|
|
532
|
-
};
|
|
533
|
-
}
|
|
534
|
-
function normalizeSha256ContentHash(contentHash) {
|
|
535
|
-
const normalized = contentHash.trim().toLowerCase();
|
|
536
|
-
return normalized.startsWith("sha256:")
|
|
537
|
-
? normalized.slice("sha256:".length)
|
|
538
|
-
: normalized;
|
|
539
|
-
}
|
|
540
519
|
async function validateQaSidecarReferences(worktreePath, workItemId, sidecars, ownerType, ownerId) {
|
|
541
520
|
if (sidecars.length === 0) {
|
|
542
521
|
return [];
|
|
@@ -578,7 +557,7 @@ async function validateQaSidecarReferences(worktreePath, workItemId, sidecars, o
|
|
|
578
557
|
throw new Error(`sidecars[${index}].bytes does not match the referenced file.`);
|
|
579
558
|
}
|
|
580
559
|
const actualHash = await sha256File(fullPath);
|
|
581
|
-
if (actualHash !==
|
|
560
|
+
if (actualHash !== contentHash.trim().toLowerCase()) {
|
|
582
561
|
throw new Error(`sidecars[${index}].content_hash does not match the referenced file.`);
|
|
583
562
|
}
|
|
584
563
|
validated.push({
|
|
@@ -20,7 +20,6 @@ export declare function buildProviderCliCommand(dispatch: RunOnceDispatchPacket,
|
|
|
20
20
|
readonly worktreePath?: string;
|
|
21
21
|
readonly completionTools?: CompletionToolRuntime;
|
|
22
22
|
readonly skipGitRepoCheck?: boolean;
|
|
23
|
-
readonly imagePaths?: readonly string[];
|
|
24
23
|
}): ProviderCliCommand;
|
|
25
24
|
export declare function codexSandboxModeForPlatform(platform?: NodeJS.Platform): "workspace-write" | "danger-full-access";
|
|
26
25
|
export declare function buildArchitectPrompt(dispatch: RunOnceDispatchPacket): string;
|
|
@@ -164,9 +164,6 @@ export function buildProviderCliCommand(dispatch, run) {
|
|
|
164
164
|
if (run.skipGitRepoCheck) {
|
|
165
165
|
args.push("--skip-git-repo-check");
|
|
166
166
|
}
|
|
167
|
-
for (const imagePath of run.imagePaths ?? []) {
|
|
168
|
-
args.push("--image", imagePath);
|
|
169
|
-
}
|
|
170
167
|
args.push(run.prompt ?? "");
|
|
171
168
|
}
|
|
172
169
|
return { command: "codex", args };
|
|
@@ -64,17 +64,16 @@ export class ProcessBackedProviderCliService {
|
|
|
64
64
|
await fs.mkdir(metadataRoot, { recursive: true });
|
|
65
65
|
await fs.writeFile(path.join(metadataRoot, "draft-input.json"), JSON.stringify(durableDraftInput(dispatch), null, 2) + "\n", "utf8");
|
|
66
66
|
await fs.writeFile(path.join(metadataRoot, "spec.md"), buildDraftSpec(dispatch), "utf8");
|
|
67
|
-
const
|
|
67
|
+
const attachmentReferences = await stageDraftTextAttachments(dispatch, metadataRoot);
|
|
68
68
|
const decomposeDraft = isDecomposeDraftDispatch(dispatch);
|
|
69
69
|
const completionTools = await prepareCompletionToolRuntime({ dispatch, worktree, phase: decomposeDraft ? "decompose" : "draft" });
|
|
70
|
-
const draftPrompt = buildDraftPrompt(dispatch, { attachmentReferences
|
|
70
|
+
const draftPrompt = buildDraftPrompt(dispatch, { attachmentReferences });
|
|
71
71
|
const pipePromptToStdin = shouldPipePromptToStdin(dispatch.execution.provider, draftPrompt);
|
|
72
72
|
const command = buildProviderCliCommand(dispatch, {
|
|
73
73
|
worktreePath: worktree.worktreePath,
|
|
74
74
|
prompt: pipePromptToStdin ? "-" : draftPrompt,
|
|
75
75
|
completionTools: completionTools ?? undefined,
|
|
76
|
-
skipGitRepoCheck: false
|
|
77
|
-
imagePaths: stagedAttachments.imagePaths
|
|
76
|
+
skipGitRepoCheck: false
|
|
78
77
|
});
|
|
79
78
|
const draftArtifactSlugs = dispatch.artifacts
|
|
80
79
|
.filter((artifact) => artifact.scope === "operational" && ["command", "skill", "hook"].includes(artifact.kind))
|
|
@@ -577,42 +576,23 @@ export class ProcessBackedProviderCliService {
|
|
|
577
576
|
};
|
|
578
577
|
}
|
|
579
578
|
}
|
|
580
|
-
async function
|
|
579
|
+
async function stageDraftTextAttachments(dispatch, metadataRoot) {
|
|
581
580
|
const attachments = dispatch.draft?.attachments ?? [];
|
|
582
|
-
const
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
return { textReferences: [], imagePaths: [] };
|
|
581
|
+
const textAttachments = attachments.filter((attachment) => attachment.kind === "text" && typeof attachment.textContent === "string");
|
|
582
|
+
if (textAttachments.length === 0) {
|
|
583
|
+
return [];
|
|
586
584
|
}
|
|
587
585
|
const attachmentRoot = path.join(metadataRoot, "draft-attachments");
|
|
588
586
|
const worktreeRoot = path.resolve(metadataRoot, "../../..");
|
|
589
587
|
await fs.mkdir(attachmentRoot, { recursive: true });
|
|
590
|
-
const
|
|
591
|
-
const
|
|
592
|
-
for (const attachment of stageable) {
|
|
588
|
+
const references = [];
|
|
589
|
+
for (const attachment of textAttachments) {
|
|
593
590
|
const fileName = `${String(attachment.index + 1).padStart(2, "0")}-${safeAttachmentFileName(attachment.fileName)}`;
|
|
594
591
|
const absolutePath = path.join(attachmentRoot, fileName);
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
textReferences.push({ index: attachment.index, path: path.relative(worktreeRoot, absolutePath).replaceAll(path.sep, "/") });
|
|
598
|
-
continue;
|
|
599
|
-
}
|
|
600
|
-
const imageContent = decodeDraftImageAttachment(attachment.contentBase64 ?? "", attachment.fileName, attachment.index);
|
|
601
|
-
await fs.writeFile(absolutePath, imageContent, { mode: 0o600 });
|
|
602
|
-
imagePaths.push(absolutePath);
|
|
603
|
-
}
|
|
604
|
-
return { textReferences, imagePaths };
|
|
605
|
-
}
|
|
606
|
-
function decodeDraftImageAttachment(contentBase64, fileName, index) {
|
|
607
|
-
const normalized = contentBase64.replace(/\s+/gu, "");
|
|
608
|
-
if (normalized.length === 0 || normalized.length % 4 !== 0 || !/^[A-Za-z0-9+/]*={0,2}$/u.test(normalized)) {
|
|
609
|
-
throw new Error(`Draft image attachment ${index + 1} (${fileName}) is not valid base64.`);
|
|
610
|
-
}
|
|
611
|
-
const decoded = Buffer.from(normalized, "base64");
|
|
612
|
-
if (decoded.length === 0 || decoded.toString("base64") !== normalized) {
|
|
613
|
-
throw new Error(`Draft image attachment ${index + 1} (${fileName}) is not valid base64.`);
|
|
592
|
+
await fs.writeFile(absolutePath, attachment.textContent ?? "", { encoding: "utf8", mode: 0o600 });
|
|
593
|
+
references.push({ index: attachment.index, path: path.relative(worktreeRoot, absolutePath).replaceAll(path.sep, "/") });
|
|
614
594
|
}
|
|
615
|
-
return
|
|
595
|
+
return references;
|
|
616
596
|
}
|
|
617
597
|
function safeAttachmentFileName(fileName) {
|
|
618
598
|
const sanitized = path.basename(fileName || "attachment.txt")
|
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.34ddcb672775";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const forgeBridgeVersion = "0.1.3-dev.
|
|
1
|
+
export const forgeBridgeVersion = "0.1.3-dev.34ddcb672775";
|
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.34ddcb672775",
|
|
4
4
|
"description": "Forge runner bridge CLI for connecting local developer machines to Forge dispatch.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function supportsDraftImageAttachmentsFor(cliProviders: readonly string[]): boolean;
|