aimux-cli 0.1.19 → 0.1.20
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/README.md +13 -4
- package/bin/aimux +4 -0
- package/bin/aimux-dev +2 -6
- package/dist/agent-output-parser-audit.d.ts +23 -0
- package/dist/agent-output-parser-audit.js +187 -0
- package/dist/agent-output-parser-contract.d.ts +9 -0
- package/dist/agent-output-parser-contract.js +33 -0
- package/dist/agent-output-parser-fixtures.d.ts +15 -0
- package/dist/agent-output-parser-fixtures.js +593 -0
- package/dist/agent-output-parser-harness.d.ts +21 -0
- package/dist/agent-output-parser-harness.js +43 -0
- package/dist/agent-output-parser-test-utils.d.ts +1 -0
- package/dist/agent-output-parser-test-utils.js +7 -0
- package/dist/agent-output-parser.js +215 -35
- package/dist/atomic-write.d.ts +15 -0
- package/dist/atomic-write.js +69 -4
- package/dist/attachment-store.d.ts +7 -0
- package/dist/attachment-store.js +64 -5
- package/dist/backend-session-discovery.d.ts +17 -0
- package/dist/backend-session-discovery.js +57 -0
- package/dist/config.js +9 -4
- package/dist/connection-targets.js +20 -1
- package/dist/context/context-bridge.js +4 -1
- package/dist/credentials.js +3 -6
- package/dist/daemon.d.ts +1 -0
- package/dist/daemon.js +16 -0
- package/dist/dashboard/index.d.ts +1 -0
- package/dist/dashboard/index.js +1 -0
- package/dist/dashboard/targets.js +14 -2
- package/dist/dashboard/ui-state-store.js +4 -3
- package/dist/last-used.js +3 -2
- package/dist/launcher-env.d.ts +4 -0
- package/dist/launcher-env.js +70 -0
- package/dist/main.js +16 -1
- package/dist/metadata-server.d.ts +13 -2
- package/dist/metadata-server.js +60 -4
- package/dist/metadata-store.js +4 -3
- package/dist/mobile-push-bridge.d.ts +8 -0
- package/dist/mobile-push-bridge.js +22 -0
- package/dist/mobile-push-throttle.d.ts +23 -0
- package/dist/mobile-push-throttle.js +53 -0
- package/dist/multiplexer/dashboard-model.js +3 -2
- package/dist/multiplexer/dashboard-ops.d.ts +3 -2
- package/dist/multiplexer/dashboard-ops.js +2 -2
- package/dist/multiplexer/dashboard-tail-methods.d.ts +3 -2
- package/dist/multiplexer/dashboard-tail-methods.js +2 -2
- package/dist/multiplexer/dashboard-view-methods.js +2 -0
- package/dist/multiplexer/index.d.ts +1 -1
- package/dist/multiplexer/index.js +4 -4
- package/dist/multiplexer/persistence-methods.js +2 -1
- package/dist/multiplexer/runtime-lifecycle-methods.js +6 -2
- package/dist/multiplexer/runtime-state.js +13 -1
- package/dist/multiplexer/service-state-snapshot.js +4 -2
- package/dist/multiplexer/services.js +5 -4
- package/dist/multiplexer/session-launch.d.ts +1 -1
- package/dist/multiplexer/session-launch.js +18 -6
- package/dist/multiplexer/session-runtime-core.js +9 -2
- package/dist/multiplexer/tool-picker.d.ts +2 -1
- package/dist/multiplexer/tool-picker.js +29 -21
- package/dist/notify.d.ts +1 -1
- package/dist/notify.js +8 -5
- package/dist/paths.js +50 -4
- package/dist/project-takeover.d.ts +1 -0
- package/dist/project-takeover.js +117 -0
- package/dist/relay-client.d.ts +10 -0
- package/dist/relay-client.js +5 -0
- package/dist/runtime-core/backend-id-reconcile.d.ts +13 -0
- package/dist/runtime-core/backend-id-reconcile.js +23 -0
- package/dist/runtime-core/exchange-store.js +3 -8
- package/dist/runtime-core/topology-store.js +3 -8
- package/dist/runtime-owner.d.ts +3 -0
- package/dist/runtime-owner.js +10 -0
- package/dist/shell-args.d.ts +13 -0
- package/dist/shell-args.js +25 -0
- package/dist/shell-hooks.d.ts +1 -0
- package/dist/shell-hooks.js +1 -0
- package/dist/team.js +4 -3
- package/dist/tmux/runtime-manager.js +2 -0
- package/dist/tui/screens/dashboard-renderers.js +6 -6
- package/dist/vitest.setup.d.ts +1 -0
- package/dist/vitest.setup.js +9 -0
- package/dist-ui/_expo/static/css/web-8782287775683e5a944b821b854d0f60.css +1 -0
- package/dist-ui/_expo/static/js/web/{entry-477c745b2adc79367a4380ecf07d9ff6.js → entry-90d00d223eefabe5cc21e4329b274fa5.js} +260 -252
- package/dist-ui/index.html +2 -2
- package/package.json +3 -1
- package/dist-ui/_expo/static/css/web-30453ede1678c16acb08b97e83e8646d.css +0 -1
package/README.md
CHANGED
|
@@ -374,15 +374,24 @@ For simulator-local development, the helper scripts use `http://127.0.0.1:43191`
|
|
|
374
374
|
for iOS and `http://10.0.2.2:43191` for Android. For mobile use against a remote
|
|
375
375
|
machine, set `EXPO_PUBLIC_AIMUX_DAEMON_URL=http://<machine>:43190` in `app/.env`.
|
|
376
376
|
|
|
377
|
-
Release pipeline (uses
|
|
377
|
+
Release pipeline (uses the shared `@tradersamwise/eas-release` CLI). Two paths,
|
|
378
|
+
chosen by what changed — always bump the version first, then ship:
|
|
378
379
|
|
|
379
380
|
```bash
|
|
380
381
|
cd app
|
|
381
|
-
|
|
382
|
-
yarn
|
|
383
|
-
yarn
|
|
382
|
+
# OTA update — JavaScript / asset changes only
|
|
383
|
+
yarn version:bump-ota && yarn update # testflight
|
|
384
|
+
yarn version:bump-ota && yarn update:production # production
|
|
385
|
+
|
|
386
|
+
# Native build — native deps, Expo plugins, permissions, icons, splash, native config
|
|
387
|
+
yarn version:bump-build && yarn build:testflight # testflight
|
|
388
|
+
yarn version:bump-build && yarn build:production # production
|
|
384
389
|
```
|
|
385
390
|
|
|
391
|
+
OTA covers JS and assets; a native rebuild is required for anything that changes
|
|
392
|
+
the native binary or its Expo runtime fingerprint. `bump-ota` aborts if the runtime
|
|
393
|
+
changed since the last native build (an OTA can only target the installed runtime).
|
|
394
|
+
|
|
386
395
|
## Tmux Compatibility
|
|
387
396
|
|
|
388
397
|
Aimux treats tmux as a managed runtime, not a transparent pass-through. For aimux-owned tmux sessions, aimux applies a fixed compatibility contract instead of inheriting whatever ambient tmux defaults happen to exist on the machine.
|
package/bin/aimux
CHANGED
package/bin/aimux-dev
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import { join } from "node:path";
|
|
2
|
+
import { prepareDevCliEnv } from "../dist/launcher-env.js";
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
process.env.AIMUX_DAEMON_PORT ||= "43191";
|
|
7
|
-
process.env.AIMUX_ENV ||= "development";
|
|
8
|
-
process.env.AIMUX_WEB_APP_URL ||= "http://localhost:8081";
|
|
4
|
+
prepareDevCliEnv();
|
|
9
5
|
|
|
10
6
|
import("../dist/main.js");
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare const PARSER_AUDIT_FINDING_FLAGS: readonly ["prompt-from-response-record", "raw-block", "status-leak-response", "activity-status-leak", "action-status-leak"];
|
|
2
|
+
export type ParserAuditFindingFlag = (typeof PARSER_AUDIT_FINDING_FLAGS)[number];
|
|
3
|
+
export interface ParserAuditFinding {
|
|
4
|
+
source: string;
|
|
5
|
+
recordIndex?: number;
|
|
6
|
+
tool: string;
|
|
7
|
+
blockIndex: number;
|
|
8
|
+
blockType: string;
|
|
9
|
+
flags: ParserAuditFindingFlag[];
|
|
10
|
+
sample: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ParserAuditOptions {
|
|
13
|
+
historyDirs?: string[];
|
|
14
|
+
contextDirs?: string[];
|
|
15
|
+
maxFindings?: number;
|
|
16
|
+
flags?: ParserAuditFindingFlag[];
|
|
17
|
+
}
|
|
18
|
+
export interface ParserAuditSummary {
|
|
19
|
+
scanned: number;
|
|
20
|
+
findings: ParserAuditFinding[];
|
|
21
|
+
countsByFlag: Record<ParserAuditFindingFlag, number>;
|
|
22
|
+
}
|
|
23
|
+
export declare function auditAgentOutputParserCorpus(options: ParserAuditOptions): ParserAuditSummary;
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { parseAgentOutput } from "./agent-output-parser.js";
|
|
4
|
+
export const PARSER_AUDIT_FINDING_FLAGS = [
|
|
5
|
+
"prompt-from-response-record",
|
|
6
|
+
"raw-block",
|
|
7
|
+
"status-leak-response",
|
|
8
|
+
"activity-status-leak",
|
|
9
|
+
"action-status-leak",
|
|
10
|
+
];
|
|
11
|
+
const STATUS_LEAK_RESPONSE_PATTERNS = [
|
|
12
|
+
/(?:^|\n)\s*How is Claude doing this session/i,
|
|
13
|
+
/(?:^|\n)\s*Starting MCP servers/i,
|
|
14
|
+
/(?:^|\n)\s*(?:⏵⏵\s*)?bypass permissions/i,
|
|
15
|
+
/(?:^|\n)\s*(?:⎿\s*)?Running in the background/i,
|
|
16
|
+
/(?:^|\n)\s*(?:⏺\s*)?Bash\([^)]*terminal-notifier/i,
|
|
17
|
+
/(?:^|\n)\s*(?:Thiscommandrequiresapproval|Doyouwanttoproceed)/i,
|
|
18
|
+
/(?:^|\n)\s*(?:│\s*)?>_\s*OpenAI Codex\b/i,
|
|
19
|
+
/^\s*(?:⏺\s*)?Bash\([^)\n]+\)\s*$/i,
|
|
20
|
+
/^\s*(?:⏺\s*)?Read\s+\d+\s+files?(?:\s*\([^)\n]*ctrl\+o to expand[^)\n]*\))?\s*$/i,
|
|
21
|
+
];
|
|
22
|
+
const ACTIVITY_STATUS_LEAK_PATTERNS = [
|
|
23
|
+
/(?:^|\n)\s*(?:[-*✻✽✶]\s+)?[\p{Lu}][\p{L}-]*(?:ed|ing)\b(?:\s+for\s+\d+(?:ms|s|m|h)(?:\s+\d+(?:ms|s|m|h))*(?=$|(?=\s*[·•.)-]))|\s*(?:\.{3}|…)|\s*\([^)]*\b\d+(?:ms|s|m|h)\b[^)]*\))[^\n]*(?=$|\n)/u,
|
|
24
|
+
/(?:^|\n)\s*(?:•\s*)?Working\s*\(\d+(?:ms|s|m|h)\b[^\n]*\)\s*(?=$|\n)/i,
|
|
25
|
+
/(?:^|\n)\s*(?:•\s*)?Starting MCP servers\b[^\n]*(?=$|\n)/i,
|
|
26
|
+
];
|
|
27
|
+
const ACTION_STATUS_LEAK_PATTERNS = [
|
|
28
|
+
/(?:^|\n)\s*(?:•\s*)?Ran\s+(?:aimux|bash|bun|cat|cd|curl|docker|find|gh|git|grep|ls|mkdir|mv|node|npm|pnpm|python3?|rg|rm|sed|sh|tsc|tsx|vitest|yarn)\b(?![^\n]*(?:\.{3}|…|\b(?:was|is|now|earlier)\b))[^\n!?]*(?=$|\n)/i,
|
|
29
|
+
/(?:^|\n)\s*(?:•|⏺)?\s*(?:Bash|BashOutput|Edit|Explore|Glob|Grep|KillBash|LS|MultiEdit|NotebookEdit|Read|Task|TodoWrite|Update|WebFetch|WebSearch|Write)\s*(?:\([^)\n]*\)|\d+[^\n]*(?:ctrl\+o|to expand)|[^\n]*(?:Running in the background|exit code))\s*(?=$|\n)/i,
|
|
30
|
+
/(?:^|\n)\s*└\s+[^\n]*(?=$|\n)/,
|
|
31
|
+
];
|
|
32
|
+
const emptyCounts = () => Object.fromEntries(PARSER_AUDIT_FINDING_FLAGS.map((flag) => [flag, 0]));
|
|
33
|
+
const sampleText = (text) => String(text || "").replace(/\s+/g, " ").trim().slice(0, 320);
|
|
34
|
+
const toolForSource = (source) => {
|
|
35
|
+
const basename = source.split("/").pop() ?? "";
|
|
36
|
+
if (/^codex[-_]/i.test(basename) || /\/codex[-_]/i.test(source))
|
|
37
|
+
return "codex";
|
|
38
|
+
if (/^claude[-_]/i.test(basename) || /\/claude[-_]/i.test(source))
|
|
39
|
+
return "claude";
|
|
40
|
+
return "unknown";
|
|
41
|
+
};
|
|
42
|
+
const looksLikePromptLeakFooter = (block) => {
|
|
43
|
+
if (!block || block.type !== "status")
|
|
44
|
+
return false;
|
|
45
|
+
if (/Conversation interrupted/i.test(block.text))
|
|
46
|
+
return false;
|
|
47
|
+
if (/(?:^|\n)\s*(?:•\s*)?(?:Working \(\d+(?:ms|s|m|h)|Starting MCP servers)/i.test(block.text))
|
|
48
|
+
return false;
|
|
49
|
+
return /(?:^|\n)\s*(?:gpt-[\w.-]+\b|claude\b|⏵⏵\s*bypass permissions|bypass permissions|.*context\)|.*permissions:)/i.test(block.text);
|
|
50
|
+
};
|
|
51
|
+
const promptLeakLooksActionable = (blocks, blockIndex) => {
|
|
52
|
+
const prompt = blocks[blockIndex];
|
|
53
|
+
if (!prompt || prompt.text.trim().length < 3)
|
|
54
|
+
return false;
|
|
55
|
+
return looksLikePromptLeakFooter(blocks[blockIndex + 1]);
|
|
56
|
+
};
|
|
57
|
+
const rawBlockLooksActionable = (text) => {
|
|
58
|
+
const lines = String(text || "")
|
|
59
|
+
.split("\n")
|
|
60
|
+
.map((line) => line.trim().replace(/^\d+\s+(?:[+-]\s*)?/, ""))
|
|
61
|
+
.filter(Boolean);
|
|
62
|
+
if (lines.length === 0)
|
|
63
|
+
return false;
|
|
64
|
+
if (lines.every((line) => /^[{}\][(),;:\s]+$/.test(line)))
|
|
65
|
+
return false;
|
|
66
|
+
if (lines.every((line) => /^[\d⋮\s:+\-{},()[\];"\u2500-\u257f]+$/.test(line)))
|
|
67
|
+
return false;
|
|
68
|
+
if (lines.every((line) => /^[bcdlps-][rwx-]{9}@?\s+\d+\s+\S+\s+\S+\s+\d+\s+\w{3}\s+\d+/i.test(line))) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
return true;
|
|
72
|
+
};
|
|
73
|
+
function* historyCandidates(historyDir) {
|
|
74
|
+
if (!existsSync(historyDir) || !statSync(historyDir).isDirectory())
|
|
75
|
+
return;
|
|
76
|
+
for (const entry of readdirSync(historyDir).filter((name) => name.endsWith(".jsonl")).sort()) {
|
|
77
|
+
const source = join(historyDir, entry);
|
|
78
|
+
const tool = toolForSource(source);
|
|
79
|
+
const lines = readFileSync(source, "utf8").split("\n");
|
|
80
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
81
|
+
const line = lines[index]?.trim();
|
|
82
|
+
if (!line)
|
|
83
|
+
continue;
|
|
84
|
+
let record;
|
|
85
|
+
try {
|
|
86
|
+
record = JSON.parse(line);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (typeof record.content !== "string")
|
|
92
|
+
continue;
|
|
93
|
+
if (record.type !== "response")
|
|
94
|
+
continue;
|
|
95
|
+
yield {
|
|
96
|
+
source,
|
|
97
|
+
recordIndex: index,
|
|
98
|
+
recordType: String(record.type),
|
|
99
|
+
tool,
|
|
100
|
+
content: record.content,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function* contextCandidates(contextDir) {
|
|
106
|
+
if (!existsSync(contextDir) || !statSync(contextDir).isDirectory())
|
|
107
|
+
return;
|
|
108
|
+
const stack = [contextDir];
|
|
109
|
+
while (stack.length > 0) {
|
|
110
|
+
const dir = stack.pop();
|
|
111
|
+
if (!dir)
|
|
112
|
+
continue;
|
|
113
|
+
for (const entry of readdirSync(dir).sort()) {
|
|
114
|
+
const source = join(dir, entry);
|
|
115
|
+
const stats = statSync(source);
|
|
116
|
+
if (stats.isDirectory()) {
|
|
117
|
+
stack.push(source);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (entry !== "live.md" && entry !== "summary.md")
|
|
121
|
+
continue;
|
|
122
|
+
yield {
|
|
123
|
+
source,
|
|
124
|
+
tool: toolForSource(source),
|
|
125
|
+
content: readFileSync(source, "utf8"),
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
export function auditAgentOutputParserCorpus(options) {
|
|
131
|
+
const findings = [];
|
|
132
|
+
const countsByFlag = emptyCounts();
|
|
133
|
+
let scanned = 0;
|
|
134
|
+
const maxFindings = options.maxFindings ?? Number.POSITIVE_INFINITY;
|
|
135
|
+
const candidates = [
|
|
136
|
+
...(options.historyDirs ?? []).flatMap((dir) => Array.from(historyCandidates(dir))),
|
|
137
|
+
...(options.contextDirs ?? []).flatMap((dir) => Array.from(contextCandidates(dir))),
|
|
138
|
+
];
|
|
139
|
+
for (const candidate of candidates) {
|
|
140
|
+
scanned += 1;
|
|
141
|
+
const parsed = parseAgentOutput(candidate.content, { tool: candidate.tool });
|
|
142
|
+
parsed.blocks.forEach((block, blockIndex) => {
|
|
143
|
+
const flags = [];
|
|
144
|
+
if (block.type === "raw" && rawBlockLooksActionable(block.text)) {
|
|
145
|
+
flags.push("raw-block");
|
|
146
|
+
}
|
|
147
|
+
if (block.type === "response" && STATUS_LEAK_RESPONSE_PATTERNS.some((pattern) => pattern.test(block.text))) {
|
|
148
|
+
flags.push("status-leak-response");
|
|
149
|
+
}
|
|
150
|
+
if (block.type === "response" && ACTIVITY_STATUS_LEAK_PATTERNS.some((pattern) => pattern.test(block.text))) {
|
|
151
|
+
flags.push("activity-status-leak");
|
|
152
|
+
}
|
|
153
|
+
if (block.type === "response" && ACTION_STATUS_LEAK_PATTERNS.some((pattern) => pattern.test(block.text))) {
|
|
154
|
+
flags.push("action-status-leak");
|
|
155
|
+
}
|
|
156
|
+
if (candidate.recordType === "response" &&
|
|
157
|
+
block.type === "prompt" &&
|
|
158
|
+
promptLeakLooksActionable(parsed.blocks, blockIndex)) {
|
|
159
|
+
flags.push("prompt-from-response-record");
|
|
160
|
+
}
|
|
161
|
+
if (options.flags && options.flags.length > 0) {
|
|
162
|
+
for (let index = flags.length - 1; index >= 0; index -= 1) {
|
|
163
|
+
if (!options.flags.includes(flags[index])) {
|
|
164
|
+
flags.splice(index, 1);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (flags.length === 0)
|
|
169
|
+
return;
|
|
170
|
+
for (const flag of flags) {
|
|
171
|
+
countsByFlag[flag] += 1;
|
|
172
|
+
}
|
|
173
|
+
if (findings.length >= maxFindings)
|
|
174
|
+
return;
|
|
175
|
+
findings.push({
|
|
176
|
+
source: candidate.source,
|
|
177
|
+
recordIndex: candidate.recordIndex,
|
|
178
|
+
tool: parsed.parser.tool,
|
|
179
|
+
blockIndex,
|
|
180
|
+
blockType: block.type,
|
|
181
|
+
flags,
|
|
182
|
+
sample: sampleText(block.text),
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
return { scanned, findings, countsByFlag };
|
|
187
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AgentOutputBlockType } from "./agent-output-parser.js";
|
|
2
|
+
export interface AgentOutputParserContract {
|
|
3
|
+
readonly blockTypes: ReadonlyArray<{
|
|
4
|
+
readonly type: AgentOutputBlockType;
|
|
5
|
+
readonly description: string;
|
|
6
|
+
}>;
|
|
7
|
+
readonly invariants: readonly string[];
|
|
8
|
+
}
|
|
9
|
+
export declare const AGENT_OUTPUT_PARSER_CONTRACT: AgentOutputParserContract;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export const AGENT_OUTPUT_PARSER_CONTRACT = {
|
|
2
|
+
blockTypes: [
|
|
3
|
+
{
|
|
4
|
+
type: "prompt",
|
|
5
|
+
description: "User-authored input that was actually delivered to the agent.",
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
type: "response",
|
|
9
|
+
description: "Assistant-authored conversational output intended for chat history.",
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
type: "status",
|
|
13
|
+
description: "Transient runtime UI, progress, active input, suggestions, footers, or control-plane output.",
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
type: "meta",
|
|
17
|
+
description: "Startup chrome and non-conversational session metadata.",
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
type: "raw",
|
|
21
|
+
description: "Unclassified terminal text retained for diagnostics until a parser rule can classify it.",
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
invariants: [
|
|
25
|
+
"Suggested prompts and active input placeholders must not become prompt blocks.",
|
|
26
|
+
"Feedback/rating prompts must not become prompt blocks.",
|
|
27
|
+
"A prompt block must represent user text that was submitted to the agent, not text merely visible in the terminal input row.",
|
|
28
|
+
"Assistant text stays response text even when it contains prompt-looking markers, quotes, bullets, fences, or paths.",
|
|
29
|
+
"Startup banners, footer/status lines, progress rows, and permission hints must not become response blocks.",
|
|
30
|
+
"Activity/progress rows must remain status text with their exact activity wording preserved.",
|
|
31
|
+
"Parsing the same complete transcript repeatedly should produce the same block sequence.",
|
|
32
|
+
],
|
|
33
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { AgentOutputBlockType } from "./agent-output-parser.js";
|
|
2
|
+
export interface AgentOutputParserFixture {
|
|
3
|
+
name: string;
|
|
4
|
+
tool: "claude" | "codex";
|
|
5
|
+
raw: string;
|
|
6
|
+
expected: Array<{
|
|
7
|
+
type: AgentOutputBlockType;
|
|
8
|
+
includes: string[];
|
|
9
|
+
excludes?: string[];
|
|
10
|
+
}>;
|
|
11
|
+
invariants?: {
|
|
12
|
+
noPromptIncludes?: string[];
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export declare const AGENT_OUTPUT_PARSER_FIXTURES: AgentOutputParserFixture[];
|