Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ Native adapter changes require their build/check targets and live provider accep
| Provider ownership labels | `io.oac.*` |
| E2B metadata | `oac_*` |

Provider bootstrap, Runtime images and Harness adapters must agree on these names. Daemon startup rejects renamed settings before any subcommand and reports replacements without values; the separate Parsar product integration settings remain unchanged. No old label is accepted as a fallback.
Provider bootstrap, Runtime images and Harness adapters must agree on these names. The separate Parsar product integration settings keep their own names.

Historical Runtime and project-version upgrades are not supported. Do not ship retired installer conversion implementations; preserve rejection guards under the [installer lifecycle contract](deploy/install/README.md#versions-and-the-lock). Preserve older installations, Runtime files, provider resources and Session history; install the current release separately. Startup never verifies and rebinds historical allocations or accepts node deployments without a valid specification. Keep the original Core responsible for unresolved resources; see the [installation version policy](docs/getting-started/operations.md#installation-version-policy). Use this release's template builder for new E2B templates. Ordinary current-version database initialization uses the migration runner.

Expand Down
76 changes: 0 additions & 76 deletions apps/daemon/internal/cli/retired_configuration.go

This file was deleted.

38 changes: 0 additions & 38 deletions apps/daemon/internal/cli/retired_configuration_test.go

This file was deleted.

3 changes: 0 additions & 3 deletions apps/daemon/internal/cli/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,6 @@ func Execute(argv []string) error {

func execute(ctx *runContext, argv []string) error {
useInstalledNativeHome()
if err := validateRuntimeConfiguration(); err != nil {
return err
}
if len(argv) == 0 || argv[0] == "-h" || argv[0] == "--help" || argv[0] == "help" {
printRootHelp(ctx.stdout)
if len(argv) == 0 {
Expand Down
26 changes: 13 additions & 13 deletions apps/web/src/features/sessions/items/ApplyPatchDiffViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,35 +24,35 @@ export function ApplyPatchDiffViewer({ item, patch, result }: { item: SessionIte
});

return (
<section className="parsar-diff" aria-label={t("items.applyPatchDiff")} data-patch-status={item.status}>
<header className="parsar-diff__summary">
<section className="patch-diff" aria-label={t("items.applyPatchDiff")} data-patch-status={item.status}>
<header className="patch-diff__summary">
<FileDiff size={14} strokeWidth={1.5} aria-hidden="true" />
<strong>{t("items.fileCount", { count: patch.changes.length })}</strong>
<span className="parsar-diff__additions">+{patch.additions}</span>
<span className="parsar-diff__deletions">−{patch.deletions}</span>
<span className="parsar-diff__status">{status}</span>
<span className="patch-diff__additions">+{patch.additions}</span>
<span className="patch-diff__deletions">−{patch.deletions}</span>
<span className="patch-diff__status">{status}</span>
</header>
<div className="parsar-diff__files">
<div className="patch-diff__files">
{patch.changes.map((change, index) => {
const open = openFiles.has(index);
return (
<section className="parsar-diff__file" key={`${change.path}:${index}`}>
<button type="button" className="parsar-diff__file-toggle" aria-expanded={open} onClick={() => toggle(index)}>
<section className="patch-diff__file" key={`${change.path}:${index}`}>
<button type="button" className="patch-diff__file-toggle" aria-expanded={open} onClick={() => toggle(index)}>
<ChevronRight className={open ? "open" : ""} size={14} strokeWidth={1.5} aria-hidden="true" />
<span className={`parsar-diff__kind parsar-diff__kind--${change.kind}`}>{t(`items.changeKind.${change.kind}` as never)}</span>
<span className={`patch-diff__kind patch-diff__kind--${change.kind}`}>{t(`items.changeKind.${change.kind}` as never)}</span>
<code title={change.path}>{change.path}</code>
<span className="parsar-diff__counts"><i>+{change.additions}</i><b>−{change.deletions}</b></span>
<span className="patch-diff__counts"><i>+{change.additions}</i><b>−{change.deletions}</b></span>
</button>
{open ? (
<pre className="parsar-diff__content" tabIndex={0} aria-label={t("items.unifiedDiffFor", { path: change.path })}>
{change.lines.map((line, lineIndex) => <span className={`parsar-diff__line parsar-diff__line--${line.kind}`} key={lineIndex}>{line.text || " "}{"\n"}</span>)}
<pre className="patch-diff__content" tabIndex={0} aria-label={t("items.unifiedDiffFor", { path: change.path })}>
{change.lines.map((line, lineIndex) => <span className={`patch-diff__line patch-diff__line--${line.kind}`} key={lineIndex}>{line.text || " "}{"\n"}</span>)}
</pre>
) : null}
</section>
);
})}
</div>
<div className="parsar-diff__raw">
<div className="patch-diff__raw">
<details><summary>{t("items.rawArguments")}</summary><pre>{pretty(item.arguments)}</pre></details>
<details><summary>{t("items.rawResult")}</summary><pre>{result === undefined ? t("items.noResultYet") : pretty(result)}</pre></details>
</div>
Expand Down
4 changes: 2 additions & 2 deletions apps/web/src/features/sessions/items/ItemRenderers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Shimmer } from "../../../components/atoms/Shimmer";
import { MessageMarkdown } from "../../../components/MessageMarkdown";
import { StatusIcon, type StatusKind } from "../../../components/StatusIcon";
import { ApplyPatchDiffViewer } from "./ApplyPatchDiffViewer";
import { parseParsarApplyPatch } from "./apply-patch";
import { parseApplyPatch } from "./apply-patch";

function textOf(item: SessionItem): string {
return (item.content ?? []).map((content) => content.text).filter((value): value is string => Boolean(value)).join("\n");
Expand Down Expand Up @@ -106,7 +106,7 @@ function WorkStep({ item }: { item: SessionItem }) {
const result = supported && (item.status !== "in_progress" || item.type === "command_execution")
? toolResult(item)
: undefined;
const patch = supported && item.type === "function_call" && item.name === "apply_patch" ? parseParsarApplyPatch(item.arguments) : null;
const patch = supported && item.type === "function_call" && item.name === "apply_patch" ? parseApplyPatch(item.arguments) : null;
const expandable = args !== undefined && args !== null || result !== undefined && result !== null;
const row = <><Icon className="trace-step-icon" size={14} strokeWidth={1.5} aria-hidden="true" /><span className="trace-step-verb">{verb}</span><span className="trace-step-target" title={target}>{target}</span>{item.status != null && item.status !== "completed" ? <StatusIcon status={itemStatusKind(item.status)} title={t(`status.${item.status}` as never)} /> : null}{item.duration_ms ? <span className="trace-duration">{formatDuration(item.duration_ms)}</span> : null}{expandable ? <ChevronRight className={`trace-step-chevron ${open ? "open" : ""}`} size={14} strokeWidth={1.5} aria-hidden="true" /> : null}</>;
return <li className="trace-step" data-trace-step={item.id}>{expandable ? <button className="trace-step-row" type="button" aria-expanded={open} onClick={() => setOpen((value) => !value)}>{row}</button> : <div className="trace-step-row">{row}</div>}{expandable ? <TraceCollapse open={open}>{patch ? <ApplyPatchDiffViewer item={item} patch={patch} result={result} /> : <div className="trace-step-details">{args !== undefined && args !== null ? <div><p>{t("items.arguments")}</p><pre>{pretty(args)}</pre></div> : null}{result !== undefined && result !== null ? <div><p>{t("items.result")}</p><pre>{pretty(result)}</pre></div> : null}</div>}</TraceCollapse> : null}</li>;
Expand Down
16 changes: 8 additions & 8 deletions apps/web/src/features/sessions/items/apply-patch.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { describe, expect, it } from "vitest";
import type { SessionItem } from "@oac/agents-client";

import { ApplyPatchDiffViewer } from "./ApplyPatchDiffViewer";
import { parseParsarApplyPatch } from "./apply-patch";
import { parseApplyPatch } from "./apply-patch";
import { mergeFunctionSteps, ThreadItems, toolResult } from "./ItemRenderers";

const changes = [
Expand All @@ -17,9 +17,9 @@ function item(overrides: Partial<SessionItem> = {}): SessionItem {
return { id: "patch", turn_id: "turn", type: "function_call", status: "completed", name: "apply_patch", call_id: "call", arguments: { changes }, ...overrides } as SessionItem;
}

describe("Parsar apply_patch parsing", () => {
describe("apply_patch parsing", () => {
it("parses add, modify, delete, multiple files, and unified-diff counts", () => {
const parsed = parseParsarApplyPatch({ changes });
const parsed = parseApplyPatch({ changes });
expect(parsed?.changes.map((change) => change.kind)).toEqual(["add", "modify", "delete"]);
expect(parsed).toMatchObject({ additions: 3, deletions: 2 });
expect(parsed?.changes[0]?.lines.map((line) => line.kind)).toContain("header");
Expand All @@ -38,12 +38,12 @@ describe("Parsar apply_patch parsing", () => {
{ changes: [{ path: "x", kind: { type: "add" }, diff: "+x", alternate: true }] },
{ changes, provider: "another-core" },
])("fails closed for empty, malformed, string, missing, or alternate shapes", (value) => {
expect(parseParsarApplyPatch(value)).toBeNull();
expect(parseApplyPatch(value)).toBeNull();
});

it("keeps XSS-like text and long lines as inert text", () => {
const long = "x".repeat(20_000);
const parsed = parseParsarApplyPatch({ changes: [{ path: "<img src=x onerror=alert(1)>", kind: { type: "update" }, diff: `+<script>alert(1)</script>${long}` }] });
const parsed = parseApplyPatch({ changes: [{ path: "<img src=x onerror=alert(1)>", kind: { type: "update" }, diff: `+<script>alert(1)</script>${long}` }] });
expect(parsed?.changes[0]?.path).toContain("<img");
expect(parsed?.changes[0]?.diff).toContain(long);
const html = renderToStaticMarkup(<ApplyPatchDiffViewer item={item({ arguments: { changes: parsed && [{ path: parsed.changes[0]?.path, kind: { type: "update" }, diff: parsed.changes[0]?.diff }] } })} patch={parsed!} result={{ ok: true }} />);
Expand All @@ -60,9 +60,9 @@ describe("protocol-aware Item rendering", () => {
expect(merged).toHaveLength(1);
expect(merged[0]).toMatchObject({ status: "completed", output: { applied: true }, duration_ms: 12 });
expect(toolResult(merged[0]!)).toEqual({ output: { applied: true }, duration_ms: 12 });
expect(renderToStaticMarkup(<ApplyPatchDiffViewer item={item({ status: "in_progress" })} patch={parseParsarApplyPatch({ changes })!} result={undefined} />)).toContain("In progress");
expect(renderToStaticMarkup(<ApplyPatchDiffViewer item={item()} patch={parseParsarApplyPatch({ changes })!} result="ok" />)).toContain("Completed");
expect(renderToStaticMarkup(<ApplyPatchDiffViewer item={item({ status: "failed" })} patch={parseParsarApplyPatch({ changes })!} result={{ error: "no" }} />)).toContain("Failed");
expect(renderToStaticMarkup(<ApplyPatchDiffViewer item={item({ status: "in_progress" })} patch={parseApplyPatch({ changes })!} result={undefined} />)).toContain("In progress");
expect(renderToStaticMarkup(<ApplyPatchDiffViewer item={item()} patch={parseApplyPatch({ changes })!} result="ok" />)).toContain("Completed");
expect(renderToStaticMarkup(<ApplyPatchDiffViewer item={item({ status: "failed" })} patch={parseApplyPatch({ changes })!} result={{ error: "no" }} />)).toContain("Failed");
});

it("preserves message, command, MCP, function output, web search, and unknown fallbacks", () => {
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/features/sessions/items/apply-patch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ function parseDiff(diff: string): Pick<ParsedPatchChange, "lines" | "additions"
return { lines, additions, deletions };
}

export function parseParsarApplyPatch(argumentsValue: unknown): ParsedApplyPatch | null {
export function parseApplyPatch(argumentsValue: unknown): ParsedApplyPatch | null {
if (!argumentsValue || typeof argumentsValue !== "object" || Array.isArray(argumentsValue)) return null;
const root = argumentsValue as Record<string, unknown>;
if (!exactKeys(root, ["changes"]) || !Array.isArray(root.changes) || root.changes.length === 0) return null;
Expand Down
4 changes: 2 additions & 2 deletions apps/web/src/features/sessions/trace/TraceView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { HelpTip } from "../../../components/console-ui";
import { MessageMarkdown } from "../../../components/MessageMarkdown";
import { StatusIcon, type StatusKind } from "../../../components/StatusIcon";
import { ApplyPatchDiffViewer } from "../items/ApplyPatchDiffViewer";
import { parseParsarApplyPatch } from "../items/apply-patch";
import { parseApplyPatch } from "../items/apply-patch";
import {
buildTraceModel,
filterTraceModel,
Expand Down Expand Up @@ -273,7 +273,7 @@ function TracePreviewPanel({ row }: { row: TraceRow }) {

function ApplyPatchPreview({ row }: { row: TraceRow }) {
const item = applyPatchItem(row);
const patch = item ? parseParsarApplyPatch(item.arguments) : null;
const patch = item ? parseApplyPatch(item.arguments) : null;
if (!item || !patch) return null;
const result = row.tool?.result.state === "available" ? row.tool.result.value : undefined;
const effectiveItem = row.status ? { ...item, status: row.status } : item;
Expand Down
8 changes: 0 additions & 8 deletions apps/web/src/lib/vite-auth.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,6 @@ describe("Vite OpenAgentCore proxy authentication", () => {
expect(loadProxyBearerAuth({ homeDir })).toBeUndefined();
});

it("does not read the retired conventional token path", () => {
const homeDir = makeTemporaryDirectory();
const retiredDirectory = join(homeDir, ".parsar", "agents-api");
mkdirSync(retiredDirectory, { recursive: true });
writeFileSync(join(retiredDirectory, "web-token"), "retired-token-marker", { mode: 0o600 });
expect(loadProxyBearerAuth({ homeDir })).toBeUndefined();
});

it("expands the conventional home path and reads a private token file", () => {
const homeDir = makeTemporaryDirectory();
const stateDirectory = join(homeDir, ".oac", "dev");
Expand Down
7 changes: 0 additions & 7 deletions apps/web/src/lib/vite-config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,6 @@ describe("Web Vite settings boundary", () => {
expect(JSON.stringify(config.define)).not.toContain("private-");
});

it.each(["serve", "build"] as const)("rejects retired settings before reading credentials during %s", (command) => {
expect(() => configure({
AGENTS_API_PROXY_TOKEN: "retired-secret-marker",
OAC_WEB_DEV_PROXY_TOKEN_FILE: "/missing/private-file-marker",
}, command)).toThrow(new Error("Retired Web settings: AGENTS_API_PROXY_TOKEN is no longer supported; use OAC_WEB_DEV_PROXY_TOKEN."));
});

it("does not read a development credential file during a production build", async () => {
const config = await configure({ OAC_WEB_DEV_PROXY_TOKEN_FILE: "/missing/private-file-marker" }, "build");
expect(config.define?.__OAC_WEB_DEV_PROXY_AUTH__).toBe("false");
Expand Down
Loading
Loading