Skip to content

Commit 473e9fc

Browse files
authored
chore: sync public mirror from internal (#825)
* chore: sync public mirror from internal * chore: sync public mirror from internal * chore: sync public mirror from internal * chore: sync public mirror from internal * chore: sync public mirror from internal
1 parent 811179e commit 473e9fc

91 files changed

Lines changed: 6347 additions & 70 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.husky/pre-commit

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,17 @@ fi
1212
# Run Composer Guardian (secrets + CI hygiene) before heavier tasks.
1313
bash "$ROOT/scripts/guardian.sh" --trigger pre-commit
1414
15-
mapfile -t STAGED_FORMAT_FILES < <(
15+
# Biome config (biome.json files.include) scopes it to src/test/packages/docs, and
16+
# Biome 1.9.x only handles ts/tsx/js/jsx/mjs/cjs/json/jsonc/css. Restrict the input
17+
# to both, so a commit touching only out-of-scope files (e.g. scripts/*.json, docs/*.md)
18+
# does not trip the "No files were processed" error and block the commit.
19+
mapfile -t BIOME_FILES < <(
1620
git diff --cached --name-only --diff-filter=ACMR |
17-
grep -E "\\.(ts|tsx|js|jsx|mjs|cjs|json|jsonc|css|md|yml|yaml)$" || true
21+
grep -E "^(src|test|packages|docs)/.*\.(ts|tsx|js|jsx|mjs|cjs|json|jsonc|css)$" || true
1822
)
1923
20-
if [ "${#STAGED_FORMAT_FILES[@]}" -gt 0 ]; then
21-
bunx biome check "${STAGED_FORMAT_FILES[@]}"
24+
if [ "${#BIOME_FILES[@]}" -gt 0 ]; then
25+
bunx biome check "${BIOME_FILES[@]}"
2226
else
2327
echo "No staged Biome-supported files to check."
2428
fi

docs/AGENT_PROFILES.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,9 @@ Oracle configurations must be read-only and reasoning-capable at runtime. The bu
5050
An assistant response completing without an error is not a verified success. Automatic promotion requires at least 20 verified outcomes for the workload. Verification results, explicit user acceptance, rejection, and retries can supply outcome evidence; unverified runs remain useful for latency and cost observations only.
5151
5252
Clients can request a profile through `X-Maestro-Agent-Profile` (or the compatibility `X-Composer-Agent-Profile`) and inspect the versioned resolved profile on the routing decision.
53+
54+
## Outcome-calibrated Oracle experiments
55+
56+
Hosts can enable deterministic session-level control/treatment assignment with `MAESTRO_ORACLE_EXPERIMENT_ID`, `MAESTRO_ORACLE_EXPERIMENT_ALLOCATION`, `MAESTRO_ORACLE_EXPERIMENT_CONTROL_VERSION`, and `MAESTRO_ORACLE_EXPERIMENT_TREATMENT_VERSION`. Configuration must be complete and allocation must be between `0` and `1`.
57+
58+
The assigned arm and policy version appear in routing receipts and bounded telemetry attributes. Assignment is immutable for an experiment/session pair; promotion remains advisory and requires verified outcome gates.

docs/CUSTOM_AGENTS.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Governed Custom Agents
2+
3+
Installed Maestro packages can prepare primary or subagent modes with the capability-scoped API exported from `src/agent/plugin-agent-api.ts`.
4+
5+
Declare agent resource directories in the package manifest. Each child directory is one statically discoverable agent and can be filtered like other package resources:
6+
7+
```json
8+
{
9+
"keywords": ["maestro-package"],
10+
"maestro": { "agents": ["./agents"] }
11+
}
12+
```
13+
14+
For example, `agents/focused-reviewer/agent.json` supplies the static `key`, `label`, and `entry` metadata. Runtime registration must match that metadata before the agent becomes available.
15+
16+
```ts
17+
const agents = createPluginAgentApi({
18+
policy: hostPolicy,
19+
metadata: discoveredAgentMetadata,
20+
});
21+
22+
const reviewer = agents.createAgent({
23+
key: "focused-reviewer",
24+
label: "Focused reviewer",
25+
description: "Reviews a bounded change",
26+
systemPrompt: "Review the requested change and report actionable findings.",
27+
model: "anthropic/claude-sonnet-4-6",
28+
tools: ["read", "search"],
29+
budgets: { maxTurns: 10, maxToolCalls: 20, maxCostUsd: 5 },
30+
approvalMode: "fail",
31+
sandboxMode: "read-only",
32+
});
33+
34+
agents.registerAgentMode({
35+
key: "focused-reviewer",
36+
label: "Focused reviewer",
37+
agent: reviewer,
38+
primary: true,
39+
});
40+
```
41+
42+
`tools: "all"` means every tool already allowed by the host policy, not every installed tool. Explicit tool lists, models, and all three budget limits must remain within the host policy. Approval and sandbox settings may be equal to or more restrictive than the host, never less restrictive.
43+
44+
Registration is atomic and requires a matching static metadata declaration. Duplicate names, metadata mismatches, foreign or forged handles, unknown tools, disallowed models, invalid budgets, and permission escalation are rejected without modifying the registry.
45+
46+
This API configures agent modes only. It does not add executable tools, UI extensions, raw process access, or authority beyond the package installation and host runtime policy. Extensions and MCP remain the supported executable-tool mechanisms.

docs/PAINTER.md

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
# Painter
2+
3+
Painter generates and edits images from inside an agent thread. It is the
4+
visual counterpart to the Oracle: where the Oracle brings a second model's
5+
reasoning, Painter brings an image model's output. Use it for UI mockups,
6+
app icons, illustrations, and editing existing images (for example,
7+
redacting a screenshot before pasting it into a PR).
8+
9+
Painter is a tool the main agent invokes. It is **not** always-on — tell the
10+
agent to use it, the same way you would tell it to use the Oracle.
11+
12+
## Setup
13+
14+
Painter calls an image API and needs a credential in the environment where the
15+
agent runs. The default provider is OpenAI (`gpt-image-2`):
16+
17+
```bash
18+
export OPENAI_API_KEY=sk-...
19+
```
20+
21+
To use FLUX via fal.ai instead:
22+
23+
```bash
24+
export MAESTRO_PAINTER_PROVIDER=flux
25+
export FAL_KEY=<your fal key>
26+
```
27+
28+
## Providers
29+
30+
| Provider | `MAESTRO_PAINTER_PROVIDER` | Generate | Edit | Mask | Credential |
31+
| --- | --- | --- | --- | --- | --- |
32+
| OpenAI (default) | `openai` | yes | yes | yes | `OPENAI_API_KEY` |
33+
| FLUX (fal.ai) | `flux` | yes | no | no | `FAL_KEY` |
34+
35+
Each provider declares a `supports` map; the painter checks it before calling
36+
edit, so asking for an edit on FLUX fails fast with a clear error instead of a
37+
buried API failure.
38+
39+
## What it does
40+
41+
- **Generate** — text prompt → new image.
42+
- **Edit** — one to three input images + a prompt → edited image (OpenAI only).
43+
Restrict changes to a region with a mask (see Masking).
44+
- Outputs are **persisted to disk** and returned as absolute paths. The agent
45+
references those paths in later turns. Transcripts stay small (image bytes
46+
are never inlined as base64 into the conversation).
47+
48+
## Masking
49+
50+
Two ways to restrict an edit to part of an image:
51+
52+
- **Bounding box** — pass `maskRegion: {x, y, width, height}` in pixels. Painter
53+
synthesizes the mask PNG automatically (transparent = editable region,
54+
matching OpenAI's mask semantics). Input dimensions come from the PNG header
55+
(no deps), fall back to the optional `sharp` package, then an explicit
56+
caller-supplied `maskSize`. Coordinates outside the image are clipped.
57+
- **Mask file** — pass `mask` pointing at a PNG whose transparent pixels mark
58+
the editable region.
59+
60+
Omit both for a whole-image edit.
61+
62+
## Output location
63+
64+
Defaults to `~/.maestro/assets/painter/`. Override with
65+
`MAESTRO_PAINTER_OUTPUT_DIR`. Files are named `painter-<timestamp>-<rand>.png`.
66+
67+
## Inline preview
68+
69+
View a generated image inline in a capable terminal:
70+
71+
```bash
72+
maestro painter show ~/.maestro/assets/painter/painter-....png
73+
```
74+
75+
Renders via iTerm2/WezTerm (OSC 1337) or kitty (graphics protocol). Run it from
76+
a plain shell, not inside the full-screen TUI. This writes only to stdout — it
77+
never routes through the agent loop, so it can't waste model tokens or corrupt
78+
the conversation context.
79+
80+
## Spend ceiling (opt-in)
81+
82+
Painter checks a process-level budget before every API call. Enable by setting
83+
both:
84+
85+
- `MAESTRO_PAINTER_MAX_COST_CENTS` — whole-dollar-cents ceiling.
86+
- `MAESTRO_PAINTER_PRICE_TABLE` — JSON mapping
87+
`${model}|${size}|${quality}` → cents per image, with `*` wildcards, e.g.
88+
`{"gpt-image-2|*|high": 8}`.
89+
90+
When the next call would exceed the ceiling, Painter fails fast with a clear
91+
reason and makes no API call. Prices are **not** fabricated: the default table
92+
is empty, and when a ceiling is set but no price matches, the gate fails **open**
93+
(allows the call) rather than blocking on missing data.
94+
95+
## Configuration
96+
97+
| Variable | Default | Purpose |
98+
| --- | --- | --- |
99+
| `OPENAI_API_KEY` / `FAL_KEY` || Required provider credential. |
100+
| `MAESTRO_PAINTER_PROVIDER` | `openai` | `openai` or `flux`. |
101+
| `MAESTRO_PAINTER_MODEL` | `gpt-image-2` (OpenAI) / `fal-ai/flux/schnell` (FLUX) | Model id. |
102+
| `MAESTRO_PAINTER_BASE_URL` || OpenAI-compatible base URL (proxies). |
103+
| `MAESTRO_PAINTER_OUTPUT_DIR` | `~/.maestro/assets/painter` | Where images are written. |
104+
| `MAESTRO_PAINTER_TIMEOUT_MS` | `180000` | Per-call timeout. |
105+
| `MAESTRO_PAINTER_MAX_COST_CENTS` || Opt-in spend ceiling (whole cents). |
106+
| `MAESTRO_PAINTER_PRICE_TABLE` || JSON price table for the ceiling. |
107+
108+
## Examples
109+
110+
Ask the agent directly:
111+
112+
- "Use the painter to create a UI mockup for the settings page, dark theme."
113+
- "Use the painter to generate an app icon: dark background, glowing cyan cursor."
114+
- "Redact the API keys in `screenshots/bug.png` using the painter."
115+
116+
For edits, point the agent at one or more image paths (use `@`-mention).
117+
Painter accepts up to three reference images.
118+
119+
## Model notes
120+
121+
`gpt-image-2` does **not** support transparency; requesting
122+
`background: transparent` is rejected by the API. It supports arbitrary `WxH`
123+
sizes where both dimensions are divisible by 16 and the aspect ratio is between
124+
1:3 and 3:1, in addition to the standard sizes.
125+
126+
## Permissions
127+
128+
Painter writes files only inside the configured output directory. Inputs are
129+
read-only — Painter never mutates a file you pass in. Painter is part of the
130+
`advanced` tool category: available to `coder` and `custom` subagent types, and
131+
explicitly denied from `explorer` (read-only), mirroring the Oracle.
132+
133+
## Composing with Conductor (browser automation)
134+
135+
The Maestro-native loop is Painter + Conductor together:
136+
137+
1. **Mockup → diff.** Painter generates a UI mockup; Conductor screenshots the
138+
live page; the agent compares and iterates.
139+
2. **Bug → redact → PR.** Conductor captures a failing-state screenshot;
140+
Painter redacts secrets; the agent opens a PR with the clean image.
141+
142+
## Not yet implemented
143+
144+
- Sixel rasterization (sixel terminals are detected but not encoded; needs a
145+
real image library).
146+
- FLUX editing / inpainting (fal exposes this on a separate endpoint).
147+
- Inline rendering *inside* the full-screen TUI itself (the `maestro painter
148+
show` CLI command covers plain-shell preview; a TUI-integrated viewer is a
149+
separate piece of work in the TUI package).
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Agent Operations UI Implementation Plan
2+
3+
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4+
5+
**Goal:** Add a web operations panel that presents durable parent/child agent lineage, live status, navigation, and safe cancellation.
6+
7+
**Architecture:** Extend the replay-lab wire projection with complete lineage, derive a deterministic forest in a pure web helper, and render it in a focused panel embedded in the composer. Existing session navigation and abort paths remain the only control mechanisms.
8+
9+
**Tech Stack:** TypeScript, Lit, Maestro trajectory/replay contracts, Vitest.
10+
11+
## Global Constraints
12+
13+
- Sparse legacy lineage renders as roots.
14+
- No new execution-control channel or permission bypass.
15+
- HTTP and persisted replay data remain compatible.
16+
17+
---
18+
19+
### Task 1: Complete the web lineage contract
20+
21+
**Files:**
22+
- Modify: `packages/web/src/services/api-client.types.ts`
23+
- Modify: `src/server/agent-trajectory-replay-lab.ts`
24+
- Test: `test/server/agent-trajectory-replay-lab.test.ts`
25+
26+
**Interfaces:**
27+
- Produces: `TrajectoryReplayLabTimelineItem.parentAgentRunId?: string` and existing `childAgentRunId?: string` from server projection.
28+
29+
- [ ] **Step 1: Add a failing projection test** asserting a parent and child timeline record retain both IDs.
30+
- [ ] **Step 2: Run** `bunx vitest --run test/server/agent-trajectory-replay-lab.test.ts` and confirm the parent field assertion fails.
31+
- [ ] **Step 3: Add `parentAgentRunId?: string` to the web type and copy the field in replay-lab projection.**
32+
- [ ] **Step 4: Re-run the focused test** and expect PASS.
33+
- [ ] **Step 5: Commit** with `git commit -m "feat(trajectory): project complete agent lineage"`.
34+
35+
### Task 2: Derive a deterministic operations forest
36+
37+
**Files:**
38+
- Create: `packages/web/src/components/agent-operations-tree.ts`
39+
- Create: `packages/web/src/components/agent-operations-tree.test.ts`
40+
41+
**Interfaces:**
42+
- Produces: `buildAgentOperationsTree(items): AgentOperationsNode[]` where each node contains `runId`, `parentRunId?`, `status`, `latestItem`, and `children`.
43+
44+
- [ ] **Step 1: Write failing tests** for nested runs, missing parents, duplicate events, latest-status selection, and stable timestamp/run-ID ordering.
45+
- [ ] **Step 2: Run** `bunx vitest --run packages/web/src/components/agent-operations-tree.test.ts` and confirm the missing module fails.
46+
- [ ] **Step 3: Implement a pure two-pass builder:** coalesce items by run ID, attach known parents, retain orphans as roots, recursively sort by latest timestamp then run ID.
47+
- [ ] **Step 4: Re-run the focused test** and expect PASS.
48+
- [ ] **Step 5: Commit** with `git commit -m "feat(web): derive agent operations tree"`.
49+
50+
### Task 3: Render and control the operations panel
51+
52+
**Files:**
53+
- Create: `packages/web/src/components/composer-agent-operations-panel.ts`
54+
- Create: `packages/web/src/components/composer-agent-operations-panel.test.ts`
55+
- Modify: `packages/web/src/components/composer-chat.ts`
56+
- Modify: `packages/web/src/components/composer-chat-overlays.ts`
57+
58+
**Interfaces:**
59+
- Consumes: `ApiClient.getSessionReplayLab(sessionId)` and `buildAgentOperationsTree`.
60+
- Emits: `open-session` with `{ sessionId, runId }`, `cancel-run` with `{ runId }`, and `close`.
61+
62+
- [ ] **Step 1: Write failing component tests** that verify nesting, status copy, expansion, navigation events, and that cancellation is absent for terminal runs.
63+
- [ ] **Step 2: Run** `bunx vitest --run packages/web/src/components/composer-agent-operations-panel.test.ts` and confirm the component is missing.
64+
- [ ] **Step 3: Implement the panel and wire navigation/cancellation to existing composer handlers.** Disable cancellation while a request is pending and expose the server error inline.
65+
- [ ] **Step 4: Run** the panel tests plus `packages/web/src/components/composer-chat.test.ts`; expect PASS.
66+
- [ ] **Step 5: Build** with `npx nx run maestro-web:build --skip-nx-cache`; expect PASS.
67+
- [ ] **Step 6: Commit** with `git commit -m "feat(web): add agent operations panel"`.
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# AI Package Build Unblocker Implementation Plan
2+
3+
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4+
5+
**Goal:** Restore the required Maestro test baseline by including painter image-provider dependencies in the AI package TypeScript project.
6+
7+
**Architecture:** Keep the current AI facade boundary and explicitly include the root image-provider directory alongside the other temporary root-owned sources. Protect the include with a source-level regression test.
8+
9+
**Tech Stack:** TypeScript project references, Vitest, Nx.
10+
11+
## Global Constraints
12+
13+
- Do not move painter implementation files in this unblocker.
14+
- Do not skip hooks or required builds.
15+
16+
---
17+
18+
### Task 1: Cover and repair the package input boundary
19+
20+
**Files:**
21+
- Modify: `packages/ai/tsconfig.build.json`
22+
- Create: `test/packages/ai-tsconfig-boundary.test.ts`
23+
24+
**Interfaces:**
25+
- Consumes: `packages/ai/tsconfig.build.json#include`.
26+
- Produces: inclusion of `../../src/services/image-providers/**/*.ts` in the AI composite project.
27+
28+
- [ ] **Step 1: Write the failing test**
29+
30+
```ts
31+
import { readFileSync } from "node:fs";
32+
import { describe, expect, it } from "vitest";
33+
34+
describe("@evalops/ai TypeScript boundary", () => {
35+
it("includes painter image-provider dependencies", () => {
36+
const config = JSON.parse(readFileSync("packages/ai/tsconfig.build.json", "utf8"));
37+
expect(config.include).toContain("../../src/services/image-providers/**/*.ts");
38+
});
39+
});
40+
```
41+
42+
- [ ] **Step 2: Verify the test and package build fail**
43+
44+
Run: `bunx vitest --run test/packages/ai-tsconfig-boundary.test.ts`
45+
Expected: FAIL because the include is absent.
46+
47+
Run: `npx nx run @evalops/ai:build --skip-nx-cache`
48+
Expected: FAIL with TS6307 for `src/services/image-providers/*.ts`.
49+
50+
- [ ] **Step 3: Add the minimal include**
51+
52+
```json
53+
"../../src/services/image-providers/**/*.ts",
54+
```
55+
56+
Place it next to the existing `../../src/tools/**/*.ts` facade input.
57+
58+
- [ ] **Step 4: Verify the regression and baseline**
59+
60+
Run: `bunx vitest --run test/packages/ai-tsconfig-boundary.test.ts`
61+
Expected: PASS.
62+
63+
Run: `npx nx run @evalops/ai:build --skip-nx-cache`
64+
Expected: PASS.
65+
66+
Run: `npx nx run maestro:test --skip-nx-cache`
67+
Expected: PASS.
68+
69+
- [ ] **Step 5: Commit**
70+
71+
```bash
72+
git add packages/ai/tsconfig.build.json test/packages/ai-tsconfig-boundary.test.ts
73+
git commit -m "fix(ai): include painter providers in package build"
74+
```

0 commit comments

Comments
 (0)