@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.
@@ -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: supportsDraftImageAttachmentsFor(cliProviders),
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
  }
@@ -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: supportsDraftImageAttachmentsFor(args.cliProviders),
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").map(normalizeInheritedQaBrowserCheck))
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 !== normalizeSha256ContentHash(contentHash)) {
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 stagedAttachments = await stageDraftAttachments(dispatch, metadataRoot);
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: stagedAttachments.textReferences });
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 stageDraftAttachments(dispatch, metadataRoot) {
579
+ async function stageDraftTextAttachments(dispatch, metadataRoot) {
581
580
  const attachments = dispatch.draft?.attachments ?? [];
582
- const stageable = attachments.filter((attachment) => (attachment.kind === "text" && typeof attachment.textContent === "string")
583
- || (attachment.kind === "image" && typeof attachment.contentBase64 === "string"));
584
- if (stageable.length === 0) {
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 textReferences = [];
591
- const imagePaths = [];
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
- if (attachment.kind === "text") {
596
- await fs.writeFile(absolutePath, attachment.textContent ?? "", { encoding: "utf8", mode: 0o600 });
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 decoded;
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.0b2f81d660c0";
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.0b2f81d660c0";
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.0b2f81d660c0",
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;
@@ -1,3 +0,0 @@
1
- export function supportsDraftImageAttachmentsFor(cliProviders) {
2
- return cliProviders.some((provider) => provider.trim().toLowerCase() === "codex");
3
- }