@wjarka/cezarion 0.14.6 → 0.14.7
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 +37 -2
- package/dist/agent-config/model-settings/shared.d.ts +2 -1
- package/dist/agent-config/model-settings/shared.js +1 -1
- package/dist/agent-config/model-settings/shared.js.map +1 -1
- package/dist/ci-wait/client.d.ts +4 -0
- package/dist/ci-wait/client.js +67 -0
- package/dist/ci-wait/client.js.map +1 -0
- package/dist/ci-wait/controller.d.ts +78 -0
- package/dist/ci-wait/controller.js +148 -0
- package/dist/ci-wait/controller.js.map +1 -0
- package/dist/ci-wait/github.d.ts +61 -0
- package/dist/ci-wait/github.js +209 -0
- package/dist/ci-wait/github.js.map +1 -0
- package/dist/ci-wait/injection.d.ts +3 -0
- package/dist/ci-wait/injection.js +26 -0
- package/dist/ci-wait/injection.js.map +1 -0
- package/dist/ci-wait/mcp.d.ts +97 -0
- package/dist/ci-wait/mcp.js +35 -0
- package/dist/ci-wait/mcp.js.map +1 -0
- package/dist/ci-wait/resources.d.ts +7 -0
- package/dist/ci-wait/resources.js +32 -0
- package/dist/ci-wait/resources.js.map +1 -0
- package/dist/ci-wait/supervisor.d.ts +21 -0
- package/dist/ci-wait/supervisor.js +163 -0
- package/dist/ci-wait/supervisor.js.map +1 -0
- package/dist/contract/ci-wait.d.ts +151 -0
- package/dist/contract/conversations.d.ts +7 -0
- package/dist/contract/delegation.d.ts +2 -0
- package/dist/contract/events.d.ts +3 -0
- package/dist/contract/index.d.ts +1 -0
- package/dist/contract/index.js +1016 -935
- package/dist/contract/runs.d.ts +461 -0
- package/dist/contract/skills.d.ts +92 -0
- package/dist/core/agent-env.js +2 -0
- package/dist/core/agent-env.js.map +1 -1
- package/dist/core/agent-runner.d.ts +6 -0
- package/dist/core/agent-runner.js +1 -0
- package/dist/core/agent-runner.js.map +1 -1
- package/dist/core/claude-cli-runner.js +10 -0
- package/dist/core/claude-cli-runner.js.map +1 -1
- package/dist/core/codex-app-server-runner.js +5 -1
- package/dist/core/codex-app-server-runner.js.map +1 -1
- package/dist/core/codex-app-server-transport.js +3 -1
- package/dist/core/codex-app-server-transport.js.map +1 -1
- package/dist/core/cursor-acp-runner.js +9 -1
- package/dist/core/cursor-acp-runner.js.map +1 -1
- package/dist/core/opencode-server-runner.js +6 -2
- package/dist/core/opencode-server-runner.js.map +1 -1
- package/dist/core/pi-runner.js +7 -1
- package/dist/core/pi-runner.js.map +1 -1
- package/dist/delegation/cli.js +8 -4
- package/dist/delegation/cli.js.map +1 -1
- package/dist/delegation/conversations.js +2 -1
- package/dist/delegation/conversations.js.map +1 -1
- package/dist/delegation/input.d.ts +6 -0
- package/dist/delegation/input.js +22 -0
- package/dist/delegation/input.js.map +1 -1
- package/dist/delegation/provision.js +3 -1
- package/dist/delegation/provision.js.map +1 -1
- package/dist/delegation/routes.d.ts +11 -0
- package/dist/delegation/service.js +31 -7
- package/dist/delegation/service.js.map +1 -1
- package/dist/delegation/transport.d.ts +11 -0
- package/dist/runs/delegation-state.d.ts +2 -0
- package/dist/runs/run-index.js +2 -3
- package/dist/runs/run-index.js.map +1 -1
- package/dist/runs/store.d.ts +514 -3
- package/dist/runs/store.js +85 -6
- package/dist/runs/store.js.map +1 -1
- package/dist/server/server.d.ts +1376 -12
- package/dist/workflows/run.d.ts +25 -1
- package/dist/workflows/run.js +470 -43
- package/dist/workflows/run.js.map +1 -1
- package/package.json +4 -3
- package/scripts/mock-ci-tool.mjs +53 -0
- package/scripts/mock-claude.mjs +8 -0
- package/scripts/mock-codex-app-server.mjs +212 -0
- package/scripts/mock-cursor-acp.mjs +6 -2
- package/scripts/mock-opencode-serve.mjs +392 -0
- package/scripts/mock-pi-rpc.mjs +7 -0
- package/scripts/pi-ci-wait.mjs +14 -0
- package/web/dist/assets/{agent-accounts-lP_xK83o.js → agent-accounts-BZm_2WAv.js} +1 -1
- package/web/dist/assets/{alert-dialog-CmDuefYh.js → alert-dialog-B422RI-k.js} +1 -1
- package/web/dist/assets/{collapsible-BqX8REmY.js → collapsible-Cy_Fmkrd.js} +1 -1
- package/web/dist/assets/{commit-list-BWvv1H7A.js → commit-list-CLxXMZvP.js} +1 -1
- package/web/dist/assets/{compare-variants-Bg7eLW3z.js → compare-variants-D2dRj6H_.js} +1 -1
- package/web/dist/assets/{diff-controls-HwWHHait.js → diff-controls-BGrXGi7O.js} +1 -1
- package/web/dist/assets/{diff-stat-mNkhAc5m.js → diff-stat-Cgnl_hYF.js} +1 -1
- package/web/dist/assets/{diff-0GBum40Q2.js → diff-tRE59UNb2.js} +2 -2
- package/web/dist/assets/{diff-view-DW64doDY.js → diff-view-DN1ort7Q.js} +1 -1
- package/web/dist/assets/{dropdown-menu-sZjYPcLh.js → dropdown-menu-dwDGT8MM.js} +1 -1
- package/web/dist/assets/{git-toolbar-DBW5EIcY.js → git-toolbar-UiHnGvE0.js} +1 -1
- package/web/dist/assets/{github-CkZ4hWI5.js → github-CaGjGQnW.js} +1 -1
- package/web/dist/assets/{image-preview-DZicGNkU.js → image-preview-C2JGcBlC.js} +1 -1
- package/web/dist/assets/index-CXZukB1O.css +1 -0
- package/web/dist/assets/{index-DWWI-B9n.js → index-D0RwD9-c.js} +3 -3
- package/web/dist/assets/{markdown-AY2K3kIV.js → markdown-C_IcKVQd.js} +1 -1
- package/web/dist/assets/{pill-CcJqA1cL.js → pill-BsbO6G7y.js} +1 -1
- package/web/dist/assets/{project-router-SwsXRKXs.js → project-router-DbLkll25.js} +1 -1
- package/web/dist/assets/{prompt-templates-iV2WD2jy.js → prompt-templates-BlTGJB5W.js} +1 -1
- package/web/dist/assets/{repo-git-BW3TOs3U.js → repo-git-CWD2dO8S.js} +1 -1
- package/web/dist/assets/{run-diff-DPUNj56q.js → run-diff-CyG0Nciv.js} +1 -1
- package/web/dist/assets/{run-header-CSaJIGXl.css → run-header-BJQfFL2l.css} +1 -1
- package/web/dist/assets/run-header-IFyIGCey.js +1 -0
- package/web/dist/assets/{skills-Dv8Vwv5D.js → skills-e7wHnuoc.js} +1 -1
- package/web/dist/assets/{tab-link-DSftvkZS.js → tab-link-BWNp3mLY.js} +1 -1
- package/web/dist/assets/{task-changes-CTCuVls1.js → task-changes-CpJImtq8.js} +1 -1
- package/web/dist/assets/{task-commits-weJQ5GSl.js → task-commits-hujrykPI.js} +1 -1
- package/web/dist/assets/{task-files-B4bUimY8.js → task-files-CjTiGtjt.js} +1 -1
- package/web/dist/assets/{task-thread-BuXrVB9K.js → task-thread-DDPFDS8C.js} +4 -4
- package/web/dist/assets/task-thread-Dc3wplva.css +1 -0
- package/web/dist/assets/{textarea-CxRdTWlq.js → textarea-FjaU370i.js} +1 -1
- package/web/dist/assets/thread-loading-77sJ8Yu_.js +1 -0
- package/web/dist/assets/{token-metrics-Z3UFYbuD.js → token-metrics-Clxh03bE.js} +1 -1
- package/web/dist/assets/utils-PYYcpCFZ.js +64 -0
- package/web/dist/assets/{workflows-vA27Yi8W.js → workflows-DGUQmWy7.js} +1 -1
- package/web/dist/assets/{zoomable-image-DUE1KFJ0.js → zoomable-image-Z3JDnm0b.js} +1 -1
- package/web/dist/index.html +14 -14
- package/web/dist/assets/index-DK0Mkv2m.css +0 -1
- package/web/dist/assets/run-header-DbDluWoV.js +0 -1
- package/web/dist/assets/task-thread-DMRD0IVt.css +0 -1
- package/web/dist/assets/thread-loading-JlP6dUpX.js +0 -1
- package/web/dist/assets/utils-CUnaAifW.js +0 -64
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Bundled dry-run mock of `opencode serve` — speaks just enough of the HTTP+SSE
|
|
3
|
+
// API (§4 of agent-event-protocols.md) for the runner wiring test in
|
|
4
|
+
// `opencode-ui-mapper.test.ts`: POST /session, GET /event (SSE bus), one
|
|
5
|
+
// scripted prompt turn. Like the real server's `prompt_async`, the HTTP
|
|
6
|
+
// response resolves immediately — every part and the closing `session.idle`
|
|
7
|
+
// arrive over SSE afterwards, so a correct stream (v1 and v2 alike) must
|
|
8
|
+
// take its turn-end from `session.idle`, never from the HTTP response.
|
|
9
|
+
import { appendFileSync } from 'node:fs';
|
|
10
|
+
import { createServer } from 'node:http';
|
|
11
|
+
|
|
12
|
+
if (process.env.CEZ_MOCK_ARGS_FILE && process.env.OPENCODE_CONFIG_CONTENT) appendFileSync(process.env.CEZ_MOCK_ARGS_FILE, JSON.stringify({ type: 'runtime-config', config: JSON.parse(process.env.OPENCODE_CONFIG_CONTENT) }) + '\n');
|
|
13
|
+
if (process.env.CEZ_MOCK_CI_PR) { const { probeCiTool } = await import('./mock-ci-tool.mjs'); await probeCiTool('opencode', JSON.parse(process.env.OPENCODE_CONFIG_CONTENT ?? '{}')); }
|
|
14
|
+
const args = process.argv.slice(2);
|
|
15
|
+
const arg = (flag, fallback) => {
|
|
16
|
+
const i = args.indexOf(flag);
|
|
17
|
+
return i >= 0 && args[i + 1] !== undefined ? args[i + 1] : fallback;
|
|
18
|
+
};
|
|
19
|
+
const hostname = arg('--hostname', '127.0.0.1');
|
|
20
|
+
|
|
21
|
+
const SESSION_ID = 'ses_mock_1';
|
|
22
|
+
const MESSAGE_ID = 'msg_mock_1';
|
|
23
|
+
|
|
24
|
+
let sse = null;
|
|
25
|
+
const send = (event) => {
|
|
26
|
+
if (sse) sse.write(`data: ${JSON.stringify(event)}\n\n`);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/** Questions the runner can look up an id for. `replyQuestion`/`rejectQuestion`
|
|
30
|
+
* resolve the id through `GET /question` before answering (see
|
|
31
|
+
* `opencode-server-runner.ts`), so a native ask needs an entry here. */
|
|
32
|
+
const pendingQuestions = [];
|
|
33
|
+
let echoSerial = 0;
|
|
34
|
+
let lateQuestionReply = false;
|
|
35
|
+
let answerDone = false;
|
|
36
|
+
|
|
37
|
+
/** The question tool arrives as a `tool` part whose state.input holds it —
|
|
38
|
+
* the shape `opencode-server-runner.test.ts`'s sendQuestion helper drives. */
|
|
39
|
+
const sendQuestionPart = (input) =>
|
|
40
|
+
send({
|
|
41
|
+
type: 'message.part.updated',
|
|
42
|
+
properties: {
|
|
43
|
+
part: {
|
|
44
|
+
id: 'prt_mock_question',
|
|
45
|
+
messageID: MESSAGE_ID,
|
|
46
|
+
sessionID: SESSION_ID,
|
|
47
|
+
type: 'tool',
|
|
48
|
+
callID: 'call_mock_question',
|
|
49
|
+
tool: 'question',
|
|
50
|
+
state: { status: 'running', input },
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
const info = (extra) => ({
|
|
55
|
+
id: MESSAGE_ID,
|
|
56
|
+
sessionID: SESSION_ID,
|
|
57
|
+
role: 'assistant',
|
|
58
|
+
time: { created: 1760000000000 },
|
|
59
|
+
modelID: 'mock-model',
|
|
60
|
+
providerID: 'mock',
|
|
61
|
+
mode: 'build',
|
|
62
|
+
path: { cwd: '/repo', root: '/repo' },
|
|
63
|
+
cost: 0,
|
|
64
|
+
tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } },
|
|
65
|
+
...extra,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const server = createServer((req, res) => {
|
|
69
|
+
const url = req.url ?? '';
|
|
70
|
+
if (req.method === 'GET' && url === '/question') {
|
|
71
|
+
res.writeHead(200, { 'content-type': 'application/json' });
|
|
72
|
+
res.end(JSON.stringify(pendingQuestions));
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (req.method === 'GET' && url.startsWith('/event')) {
|
|
76
|
+
res.writeHead(200, { 'content-type': 'text/event-stream', 'cache-control': 'no-cache' });
|
|
77
|
+
sse = res;
|
|
78
|
+
send({ type: 'server.connected', properties: {} });
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
let body = '';
|
|
82
|
+
req.on('data', (chunk) => (body += chunk));
|
|
83
|
+
req.on('end', async () => {
|
|
84
|
+
if (process.env.CEZ_MOCK_ARGS_FILE) appendFileSync(process.env.CEZ_MOCK_ARGS_FILE, `${JSON.stringify({ method: req.method, url, body: body ? JSON.parse(body) : undefined })}\n`);
|
|
85
|
+
if (req.method === 'POST' && /^\/question\/[^/]+\/(reply|reject)$/.test(url)) {
|
|
86
|
+
// Native question reply resumes the held turn, then its own session.idle
|
|
87
|
+
// ends it (same SSE lifecycle shape as the baseline; never the HTTP ack).
|
|
88
|
+
const answered = pendingQuestions.some(question => question.id === 'q_mock_1');
|
|
89
|
+
pendingQuestions.length = 0;
|
|
90
|
+
if (answered && url.endsWith('/reply')) setTimeout(() => {
|
|
91
|
+
send({ type: 'message.part.updated', properties: { part: {
|
|
92
|
+
id: 'prt_answer', messageID: MESSAGE_ID, sessionID: SESSION_ID, type: 'text', text: `human answer: ${body}${answerDone ? '\n\nCEZ:DONE' : ''}`,
|
|
93
|
+
} } });
|
|
94
|
+
send({ type: 'session.idle', properties: { sessionID: SESSION_ID } });
|
|
95
|
+
}, 30);
|
|
96
|
+
const acknowledge = () => { res.writeHead(200, { 'content-type': 'application/json' }); res.end('{}'); };
|
|
97
|
+
if (lateQuestionReply) setTimeout(acknowledge, 250);
|
|
98
|
+
else acknowledge();
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (req.method === 'POST' && url === '/session') {
|
|
102
|
+
res.writeHead(200, { 'content-type': 'application/json' });
|
|
103
|
+
res.end(JSON.stringify({ id: SESSION_ID, title: 'cezar task' }));
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (
|
|
107
|
+
req.method === 'POST' &&
|
|
108
|
+
(url === `/session/${SESSION_ID}/prompt_async` || url === `/session/${SESSION_ID}/message`)
|
|
109
|
+
) {
|
|
110
|
+
if (body.includes('mock:reject-agent-post')) {
|
|
111
|
+
res.writeHead(503, { 'content-type': 'application/json' });
|
|
112
|
+
res.end(JSON.stringify({ error: 'agent prompt rejected' }));
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
// `prompt_async` semantics: acknowledge now, stream the turn over SSE.
|
|
116
|
+
res.writeHead(200, { 'content-type': 'application/json' });
|
|
117
|
+
res.end(JSON.stringify({ info: info({}), parts: [] }));
|
|
118
|
+
// The raw body is enough to spot a `mock:` marker — the prompt text is
|
|
119
|
+
// inside it whatever part shape the runner used to wrap it.
|
|
120
|
+
if (body.includes('mock:ci-wait')) {
|
|
121
|
+
const { ciPrompt } = await import('./mock-ci-tool.mjs');
|
|
122
|
+
const text = await ciPrompt('opencode', JSON.parse(process.env.OPENCODE_CONFIG_CONTENT ?? '{}'), body);
|
|
123
|
+
send({ type: 'message.part.updated', properties: { part: { id: 'ci-result', messageID: MESSAGE_ID, sessionID: SESSION_ID, type: 'text', text } } });
|
|
124
|
+
send({ type: 'session.idle', properties: { sessionID: SESSION_ID } });
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (body.includes('mock:agent-echo')) {
|
|
128
|
+
send({ type: 'message.updated', properties: { info: info({}) } });
|
|
129
|
+
send({ type: 'message.part.updated', properties: { part: {
|
|
130
|
+
id: `prt_echo_${++echoSerial}`, messageID: MESSAGE_ID, sessionID: SESSION_ID, type: 'text',
|
|
131
|
+
text: JSON.parse(body).parts.map(part => part.text ?? '').join('\n'),
|
|
132
|
+
} } });
|
|
133
|
+
send({ type: 'session.idle', properties: { sessionID: SESSION_ID } });
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (body.includes('mock:subagent')) {
|
|
137
|
+
// Wire shape from `__fixtures__/opencode/subtask-nested.ndjson`: a
|
|
138
|
+
// `subtask` part on the parent message, then a child message whose info
|
|
139
|
+
// carries `parentID`, its parts, and the CHILD's own `session.idle`.
|
|
140
|
+
// That child idle arrives first on purpose — the parent turn has to
|
|
141
|
+
// survive it and close only on its own (#5, #600; harness parity S9).
|
|
142
|
+
send({ type: 'message.updated', properties: { info: info({}) } });
|
|
143
|
+
send({ type: 'message.part.updated', properties: { part: {
|
|
144
|
+
id: 'prt_mock_subt', messageID: MESSAGE_ID, sessionID: SESSION_ID, type: 'subtask',
|
|
145
|
+
prompt: 'Trace every caller of resolveSession', description: 'Trace resolveSession callers',
|
|
146
|
+
agent: 'general',
|
|
147
|
+
} } });
|
|
148
|
+
send({ type: 'message.updated', properties: { info: {
|
|
149
|
+
...info({}), id: 'msg_mock_child', sessionID: 'ses_mock_child',
|
|
150
|
+
parentID: SESSION_ID, mode: 'subagent',
|
|
151
|
+
} } });
|
|
152
|
+
send({ type: 'message.part.updated', properties: { part: {
|
|
153
|
+
id: 'prt_mock_ctxt', messageID: 'msg_mock_child', sessionID: 'ses_mock_child',
|
|
154
|
+
type: 'text', text: 'Two callers: router.ts and session.ts.',
|
|
155
|
+
time: { start: 1760000008800, end: 1760000008900 },
|
|
156
|
+
} } });
|
|
157
|
+
send({ type: 'session.idle', properties: { sessionID: 'ses_mock_child' } });
|
|
158
|
+
// A second child is still running when the parent declares monitoring.
|
|
159
|
+
send({ type: 'message.part.updated', properties: { part: {
|
|
160
|
+
id: 'prt_mock_late_subt', messageID: MESSAGE_ID, sessionID: SESSION_ID, type: 'subtask',
|
|
161
|
+
prompt: 'Review the callers', description: 'Review callers', agent: 'general',
|
|
162
|
+
} } });
|
|
163
|
+
send({ type: 'message.updated', properties: { info: {
|
|
164
|
+
...info({}), id: 'msg_mock_late_child', sessionID: 'ses_mock_late_child',
|
|
165
|
+
parentID: SESSION_ID, mode: 'subagent',
|
|
166
|
+
} } });
|
|
167
|
+
setTimeout(() => {
|
|
168
|
+
send({ type: 'message.part.updated', properties: { part: {
|
|
169
|
+
id: 'prt_mock_ptxt', messageID: MESSAGE_ID, sessionID: SESSION_ID,
|
|
170
|
+
type: 'text', text: 'Still working after the sub-agent.\nCEZ:MONITORING',
|
|
171
|
+
time: { start: 1760000009000, end: 1760000009200 },
|
|
172
|
+
} } });
|
|
173
|
+
// #149: foreign-session text after the parent's marker must stay v2-only.
|
|
174
|
+
send({ type: 'message.part.updated', properties: { part: {
|
|
175
|
+
id: 'prt_mock_late_child', messageID: 'msg_mock_late_child', sessionID: 'ses_mock_late_child',
|
|
176
|
+
type: 'text', text: 'Child review finished.',
|
|
177
|
+
time: { start: 1760000009200, end: 1760000009300 },
|
|
178
|
+
} } });
|
|
179
|
+
send({ type: 'message.updated', properties: { info: info({
|
|
180
|
+
cost: 0.0001, tokens: { input: 20, output: 10, reasoning: 0, cache: { read: 0, write: 0 } },
|
|
181
|
+
}) } });
|
|
182
|
+
setTimeout(() => send({ type: 'session.idle', properties: { sessionID: SESSION_ID } }), 30);
|
|
183
|
+
}, 60);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
if (body.includes('mock:provider-error')) {
|
|
187
|
+
// The session-level error frame, wire shape copied verbatim from
|
|
188
|
+
// `__fixtures__/opencode/session-error.ndjson`. #53: a bare upstream
|
|
189
|
+
// rejection used to read like a missing executable, and the run parked
|
|
190
|
+
// as "Needs You" rather than failing (harness parity S7).
|
|
191
|
+
send({ type: 'message.updated', properties: { info: info({}) } });
|
|
192
|
+
send({ type: 'message.part.updated', properties: { part: {
|
|
193
|
+
id: 'prt_mock_perr', messageID: MESSAGE_ID, sessionID: SESSION_ID,
|
|
194
|
+
type: 'text', text: 'Starting the review',
|
|
195
|
+
} } });
|
|
196
|
+
send({ type: 'session.error', properties: { sessionID: SESSION_ID, error: {
|
|
197
|
+
name: 'ProviderAuthError',
|
|
198
|
+
data: { message: 'API key expired — run `opencode auth login`' },
|
|
199
|
+
} } });
|
|
200
|
+
setTimeout(() => send({ type: 'session.idle', properties: { sessionID: SESSION_ID } }), 30);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
if (body.includes('mock:split-text')) {
|
|
204
|
+
// OpenCode streams a text part as successive GROWING snapshots of the
|
|
205
|
+
// same part id; only the final one carries `time.end`. A runner emitting
|
|
206
|
+
// one v1 `text` per snapshot publishes the torn `…CEZ:` prefix, which is
|
|
207
|
+
// #2 on opencode's wire (harness parity S8).
|
|
208
|
+
const full = 'parity split text\n\nCEZ:MONITORING';
|
|
209
|
+
send({ type: 'message.updated', properties: { info: info({}) } });
|
|
210
|
+
for (const upto of [17, 24, full.length]) {
|
|
211
|
+
send({ type: 'message.part.updated', properties: { part: {
|
|
212
|
+
id: 'prt_mock_split', messageID: MESSAGE_ID, sessionID: SESSION_ID, type: 'text',
|
|
213
|
+
text: full.slice(0, upto),
|
|
214
|
+
...(upto === full.length ? { time: { start: 1760000000500, end: 1760000000600 } } : {}),
|
|
215
|
+
} } });
|
|
216
|
+
}
|
|
217
|
+
send({ type: 'message.updated', properties: { info: info({
|
|
218
|
+
cost: 0.0001, tokens: { input: 20, output: 10, reasoning: 0, cache: { read: 0, write: 0 } },
|
|
219
|
+
}) } });
|
|
220
|
+
setTimeout(() => send({ type: 'session.idle', properties: { sessionID: SESSION_ID } }), 30);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if (body.includes('mock:ask-bad')) {
|
|
224
|
+
// Malformed: `questions` is not an array, so the runner must REJECT the
|
|
225
|
+
// native question and finish the turn rather than wait for an answer to
|
|
226
|
+
// a card that can never render (#6's rejection path, harness parity R4).
|
|
227
|
+
send({ type: 'message.updated', properties: { info: info({}) } });
|
|
228
|
+
pendingQuestions.push({ id: 'q_mock_bad', sessionID: SESSION_ID });
|
|
229
|
+
sendQuestionPart({ questions: 'not-an-array' });
|
|
230
|
+
setTimeout(() => send({ type: 'session.idle', properties: { sessionID: SESSION_ID } }), 60);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
if (body.includes('mock:ask')) {
|
|
234
|
+
lateQuestionReply = body.includes('mock:ask-reply-late');
|
|
235
|
+
answerDone = body.includes('mock:ask-reply-late-done');
|
|
236
|
+
// The native question tool (#6). No `session.idle` follows: a real ask
|
|
237
|
+
// holds the turn open until the answer is routed back.
|
|
238
|
+
send({ type: 'message.updated', properties: { info: info({}) } });
|
|
239
|
+
pendingQuestions.push({ id: 'q_mock_1', sessionID: SESSION_ID });
|
|
240
|
+
sendQuestionPart({ questions: [{
|
|
241
|
+
header: 'Library',
|
|
242
|
+
question: 'Which test library?',
|
|
243
|
+
options: [
|
|
244
|
+
{ label: 'Vitest', description: 'Use the existing test runner' },
|
|
245
|
+
{ label: 'Node test', description: 'Use node:test' },
|
|
246
|
+
],
|
|
247
|
+
}] });
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if (body.includes('mock:done')) {
|
|
251
|
+
// Declares the task complete so the run reaches cezar's review gate; a
|
|
252
|
+
// markerless turn-end correctly parks as `waiting` instead (harness
|
|
253
|
+
// parity R1).
|
|
254
|
+
send({ type: 'message.updated', properties: { info: info({}) } });
|
|
255
|
+
send({ type: 'message.part.updated', properties: { part: {
|
|
256
|
+
id: 'prt_mock_done', messageID: MESSAGE_ID, sessionID: SESSION_ID, type: 'text',
|
|
257
|
+
text: 'parity done: the task is complete\n\nCEZ:DONE',
|
|
258
|
+
time: { start: 1760000000500, end: 1760000000600 },
|
|
259
|
+
} } });
|
|
260
|
+
send({ type: 'message.updated', properties: { info: info({
|
|
261
|
+
cost: 0.0001, tokens: { input: 20, output: 10, reasoning: 0, cache: { read: 0, write: 0 } },
|
|
262
|
+
}) } });
|
|
263
|
+
setTimeout(() => send({ type: 'session.idle', properties: { sessionID: SESSION_ID } }), 30);
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
if (body.includes('mock:hold-ask')) {
|
|
267
|
+
// Portable CEZ:ASK after a pause, so a mid-turn sendMessage can queue
|
|
268
|
+
// and then race the park (run.ts must discard that waiter).
|
|
269
|
+
setTimeout(() => {
|
|
270
|
+
const ask = 'Pick one.\n\nCEZ:ASK {"questions":[{"header":"Library","question":"Which date library should I standardize on?","options":[{"label":"date-fns","description":"Tree-shakeable, functional"},{"label":"Luxon","description":"Immutable, tz-aware"}]}]}';
|
|
271
|
+
send({ type: 'message.updated', properties: { info: info({}) } });
|
|
272
|
+
send({ type: 'message.part.updated', properties: { part: {
|
|
273
|
+
id: 'prt_mock_hold_ask', messageID: MESSAGE_ID, sessionID: SESSION_ID, type: 'text',
|
|
274
|
+
text: ask,
|
|
275
|
+
time: { start: 1760000000500, end: 1760000000600 },
|
|
276
|
+
} } });
|
|
277
|
+
send({ type: 'message.updated', properties: { info: info({
|
|
278
|
+
cost: 0.0001, tokens: { input: 20, output: 10, reasoning: 0, cache: { read: 0, write: 0 } },
|
|
279
|
+
}) } });
|
|
280
|
+
setTimeout(() => send({ type: 'session.idle', properties: { sessionID: SESSION_ID } }), 30);
|
|
281
|
+
}, 250);
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
if (body.includes('mock:hold')) {
|
|
285
|
+
// The response above is the ack (this is the #4 wire: `prompt_async`
|
|
286
|
+
// resolves immediately, the turn arrives over SSE afterwards). Holding
|
|
287
|
+
// the content behind it is what makes harness parity S2 meaningful.
|
|
288
|
+
setTimeout(() => {
|
|
289
|
+
const held = 'parity hold: content after the pause';
|
|
290
|
+
send({ type: 'message.updated', properties: { info: info({}) } });
|
|
291
|
+
send({ type: 'message.part.updated', properties: { part: {
|
|
292
|
+
id: 'prt_mock_hold', messageID: MESSAGE_ID, sessionID: SESSION_ID, type: 'text', text: held,
|
|
293
|
+
} } });
|
|
294
|
+
send({ type: 'message.updated', properties: { info: info({
|
|
295
|
+
cost: 0.0001, tokens: { input: 20, output: 10, reasoning: 0, cache: { read: 0, write: 0 } },
|
|
296
|
+
}) } });
|
|
297
|
+
setTimeout(() => send({ type: 'session.idle', properties: { sessionID: SESSION_ID } }), 30);
|
|
298
|
+
}, 250);
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
send({ type: 'message.updated', properties: { info: info({}) } });
|
|
302
|
+
send({
|
|
303
|
+
type: 'message.part.updated',
|
|
304
|
+
properties: {
|
|
305
|
+
part: { id: 'prt_mock_t1', messageID: MESSAGE_ID, sessionID: SESSION_ID, type: 'text', text: 'Checking the working tree.' },
|
|
306
|
+
},
|
|
307
|
+
});
|
|
308
|
+
send({
|
|
309
|
+
type: 'message.part.updated',
|
|
310
|
+
properties: {
|
|
311
|
+
part: {
|
|
312
|
+
id: 'prt_mock_c1',
|
|
313
|
+
messageID: MESSAGE_ID,
|
|
314
|
+
sessionID: SESSION_ID,
|
|
315
|
+
type: 'tool',
|
|
316
|
+
callID: 'call_mock_1',
|
|
317
|
+
tool: 'bash',
|
|
318
|
+
state: { status: 'pending', input: { command: 'git status --short' }, raw: '{}' },
|
|
319
|
+
},
|
|
320
|
+
},
|
|
321
|
+
});
|
|
322
|
+
send({
|
|
323
|
+
type: 'message.part.updated',
|
|
324
|
+
properties: {
|
|
325
|
+
part: {
|
|
326
|
+
id: 'prt_mock_c1',
|
|
327
|
+
messageID: MESSAGE_ID,
|
|
328
|
+
sessionID: SESSION_ID,
|
|
329
|
+
type: 'tool',
|
|
330
|
+
callID: 'call_mock_1',
|
|
331
|
+
tool: 'bash',
|
|
332
|
+
state: { status: 'running', input: { command: 'git status --short' }, title: 'git status --short', time: { start: 1760000000100 } },
|
|
333
|
+
},
|
|
334
|
+
},
|
|
335
|
+
});
|
|
336
|
+
send({
|
|
337
|
+
type: 'message.part.updated',
|
|
338
|
+
properties: {
|
|
339
|
+
part: {
|
|
340
|
+
id: 'prt_mock_c1',
|
|
341
|
+
messageID: MESSAGE_ID,
|
|
342
|
+
sessionID: SESSION_ID,
|
|
343
|
+
type: 'tool',
|
|
344
|
+
callID: 'call_mock_1',
|
|
345
|
+
tool: 'bash',
|
|
346
|
+
state: {
|
|
347
|
+
status: 'completed',
|
|
348
|
+
input: { command: 'git status --short' },
|
|
349
|
+
output: ' M src/example.ts\n',
|
|
350
|
+
title: 'git status --short',
|
|
351
|
+
metadata: { exit: 0 },
|
|
352
|
+
time: { start: 1760000000100, end: 1760000000400 },
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
},
|
|
356
|
+
});
|
|
357
|
+
send({
|
|
358
|
+
type: 'message.updated',
|
|
359
|
+
properties: {
|
|
360
|
+
info: info({ cost: 0.0021, tokens: { input: 1200, output: 300, reasoning: 0, cache: { read: 0, write: 0 } } }),
|
|
361
|
+
},
|
|
362
|
+
});
|
|
363
|
+
setTimeout(() => {
|
|
364
|
+
send({
|
|
365
|
+
type: 'message.part.updated',
|
|
366
|
+
properties: {
|
|
367
|
+
part: {
|
|
368
|
+
id: 'prt_mock_t2',
|
|
369
|
+
messageID: MESSAGE_ID,
|
|
370
|
+
sessionID: SESSION_ID,
|
|
371
|
+
type: 'text',
|
|
372
|
+
text: 'Done.',
|
|
373
|
+
time: { start: 1760000000500, end: 1760000000600 },
|
|
374
|
+
},
|
|
375
|
+
},
|
|
376
|
+
});
|
|
377
|
+
}, 30);
|
|
378
|
+
setTimeout(() => send({ type: 'session.idle', properties: { sessionID: SESSION_ID } }), 90);
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
res.writeHead(200, { 'content-type': 'application/json' });
|
|
382
|
+
res.end('{}');
|
|
383
|
+
});
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
// Test sessions share a host: let the OS allocate a port instead of racing
|
|
387
|
+
// the runner’s random requested port against other fixtures.
|
|
388
|
+
server.listen(0, hostname, () => {
|
|
389
|
+
// The runner reads the bound URL back from stdout, like the real server.
|
|
390
|
+
console.log(`opencode server listening on http://${hostname}:${server.address().port}`);
|
|
391
|
+
});
|
|
392
|
+
process.on('SIGTERM', () => process.exit(0));
|
package/scripts/mock-pi-rpc.mjs
CHANGED
|
@@ -6,6 +6,7 @@ if (process.env.CEZ_MOCK_ARGS_FILE) appendFileSync(process.env.CEZ_MOCK_ARGS_FIL
|
|
|
6
6
|
// Pi handles SIGTERM and reports 128 + signal, rather than a null exit code.
|
|
7
7
|
process.on('SIGTERM', () => process.exit(143));
|
|
8
8
|
|
|
9
|
+
if (process.env.CEZ_MOCK_CI_PR) { const { probeCiTool } = await import('./mock-ci-tool.mjs'); await probeCiTool('pi', process.argv.slice(2)); }
|
|
9
10
|
const sessionId = '00000000-0000-4000-8000-0000000000pi';
|
|
10
11
|
const send = (value) => process.stdout.write(`${JSON.stringify(value)}\n`);
|
|
11
12
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
@@ -61,6 +62,12 @@ for await (const line of readline.createInterface({ input: process.stdin })) {
|
|
|
61
62
|
pendingMessageCount: 0,
|
|
62
63
|
},
|
|
63
64
|
});
|
|
65
|
+
} else if (command.type === 'prompt' && command.message.includes('mock:ci-wait')) {
|
|
66
|
+
send({ id: command.id, type: 'response', command: 'prompt', success: true });
|
|
67
|
+
send({ type: 'agent_start' }); send({ type: 'turn_start' });
|
|
68
|
+
const { ciPrompt } = await import('./mock-ci-tool.mjs');
|
|
69
|
+
sendText([await ciPrompt('pi', process.argv.slice(2), command.message)]);
|
|
70
|
+
sendTurnEnd();
|
|
64
71
|
} else if (command.type === 'prompt' && command.message.includes('mock:agent-echo')) {
|
|
65
72
|
// rpc-lifecycle.ndjson's normal prompt/assistant/settled sequence.
|
|
66
73
|
send({ id: command.id, type: 'response', command: 'prompt', success: true });
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Pi 0.87.0 extension API accepts JSON Schema (TypeBox-compatible parameters).
|
|
2
|
+
// Resolve beside this installed script; no private workspace dependency or download.
|
|
3
|
+
import { existsSync } from 'node:fs';
|
|
4
|
+
const source = new URL('../src/ci-wait/mcp.ts', import.meta.url);
|
|
5
|
+
const { ciToolDefinition, invokeCiTool } = await import(existsSync(source) ? source.href : new URL('../dist/ci-wait/mcp.js', import.meta.url).href);
|
|
6
|
+
export default function ciWaitExtension(pi) {
|
|
7
|
+
pi.registerTool({
|
|
8
|
+
name: ciToolDefinition.name,
|
|
9
|
+
label: 'Wait for CI',
|
|
10
|
+
description: ciToolDefinition.description,
|
|
11
|
+
parameters: ciToolDefinition.inputSchema,
|
|
12
|
+
async execute(_toolCallId, params) { return invokeCiTool(params); },
|
|
13
|
+
});
|
|
14
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-QTnfLwEv.js";import{i as t,t as n}from"./react-runtime-CCIEwYL0.js";import{C as r,D as i,I as a,Jn as o,M as s,N as c,O as l,S as u,T as d,b as f,j as p,k as m,un as h,w as g,x as _,z as v}from"./alert-dialog-
|
|
1
|
+
import{r as e}from"./rolldown-runtime-QTnfLwEv.js";import{i as t,t as n}from"./react-runtime-CCIEwYL0.js";import{C as r,D as i,I as a,Jn as o,M as s,N as c,O as l,S as u,T as d,b as f,j as p,k as m,un as h,w as g,x as _,z as v}from"./alert-dialog-B422RI-k.js";import{t as y}from"./utils-PYYcpCFZ.js";import{_ as b,g as x,h as ee,m as te,p as S}from"./dropdown-menu-dwDGT8MM.js";var C=e(t(),1),w=n(),T=`Popover`,[E,ne]=s(T,[b]),D=b(),[O,k]=E(T),A=e=>{let{__scopePopover:t,children:n,open:r,defaultOpen:a,onOpenChange:o,modal:s=!1}=e,c=D(t),l=C.useRef(null),[u,d]=C.useState(!1),[f,p]=m({prop:r,defaultProp:a??!1,onChange:o,caller:T});return(0,w.jsx)(x,{...c,children:(0,w.jsx)(O,{scope:t,contentId:i(),triggerRef:l,open:f,onOpenChange:p,onOpenToggle:C.useCallback(()=>p(e=>!e),[p]),hasCustomAnchor:u,onCustomAnchorAdd:C.useCallback(()=>d(!0),[]),onCustomAnchorRemove:C.useCallback(()=>d(!1),[]),modal:s,children:n})})};A.displayName=T;var j=`PopoverAnchor`,M=C.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=k(j,n),a=D(n),{onCustomAnchorAdd:o,onCustomAnchorRemove:s}=i;return C.useEffect(()=>(o(),()=>s()),[o,s]),(0,w.jsx)(S,{...a,...r,ref:t})});M.displayName=j;var N=`PopoverTrigger`,P=C.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=k(N,n),a=D(n),o=v(t,i.triggerRef),s=(0,w.jsx)(c.button,{type:`button`,"aria-haspopup":`dialog`,"aria-expanded":i.open,"aria-controls":i.open?i.contentId:void 0,"data-state":J(i.open),...r,ref:o,onClick:p(e.onClick,i.onOpenToggle)});return i.hasCustomAnchor?s:(0,w.jsx)(S,{asChild:!0,...a,children:s})});P.displayName=N;var F=`PopoverPortal`,[re,I]=E(F,{forceMount:void 0}),L=e=>{let{__scopePopover:t,forceMount:n,children:i,container:a}=e,o=k(F,t);return(0,w.jsx)(re,{scope:t,forceMount:n,children:(0,w.jsx)(l,{present:n||o.open,children:(0,w.jsx)(r,{asChild:!0,container:a,children:i})})})};L.displayName=F;var R=`PopoverContent`,z=C.forwardRef((e,t)=>{let n=I(R,e.__scopePopover),{forceMount:r=n.forceMount,...i}=e,a=k(R,e.__scopePopover);return(0,w.jsx)(l,{present:r||a.open,children:a.modal?(0,w.jsx)(V,{...i,ref:t}):(0,w.jsx)(H,{...i,ref:t})})});z.displayName=R;var B=a(`PopoverContent.RemoveScroll`),V=C.forwardRef((e,t)=>{let n=k(R,e.__scopePopover),r=C.useRef(null),i=v(t,r),a=C.useRef(!1);return C.useEffect(()=>{let e=r.current;if(e)return f(e)},[]),(0,w.jsx)(_,{as:B,allowPinchZoom:!0,children:(0,w.jsx)(U,{...e,ref:i,trapFocus:n.open,disableOutsidePointerEvents:!0,onCloseAutoFocus:p(e.onCloseAutoFocus,e=>{e.preventDefault(),a.current||n.triggerRef.current?.focus()}),onPointerDownOutside:p(e.onPointerDownOutside,e=>{let t=e.detail.originalEvent,n=t.button===0&&t.ctrlKey===!0,r=t.button===2||n;a.current=r},{checkForDefaultPrevented:!1}),onFocusOutside:p(e.onFocusOutside,e=>e.preventDefault(),{checkForDefaultPrevented:!1})})})}),H=C.forwardRef((e,t)=>{let n=k(R,e.__scopePopover),r=C.useRef(!1),i=C.useRef(!1);return(0,w.jsx)(U,{...e,ref:t,trapFocus:!1,disableOutsidePointerEvents:!1,onCloseAutoFocus:t=>{e.onCloseAutoFocus?.(t),t.defaultPrevented||(r.current||n.triggerRef.current?.focus(),t.preventDefault()),r.current=!1,i.current=!1},onInteractOutside:t=>{e.onInteractOutside?.(t),t.defaultPrevented||(r.current=!0,t.detail.originalEvent.type===`pointerdown`&&(i.current=!0));let a=t.target;n.triggerRef.current?.contains(a)&&t.preventDefault(),t.detail.originalEvent.type===`focusin`&&i.current&&t.preventDefault()}})}),U=C.forwardRef((e,t)=>{let{__scopePopover:n,trapFocus:r,onOpenAutoFocus:i,onCloseAutoFocus:a,disableOutsidePointerEvents:o,onEscapeKeyDown:s,onPointerDownOutside:c,onFocusOutside:l,onInteractOutside:f,...p}=e,m=k(R,n),h=D(n);return u(),(0,w.jsx)(g,{asChild:!0,loop:!0,trapped:r,onMountAutoFocus:i,onUnmountAutoFocus:a,children:(0,w.jsx)(d,{asChild:!0,disableOutsidePointerEvents:o,onInteractOutside:f,onEscapeKeyDown:s,onPointerDownOutside:c,onFocusOutside:l,onDismiss:()=>m.onOpenChange(!1),deferPointerDownOutside:!0,children:(0,w.jsx)(ee,{"data-state":J(m.open),role:`dialog`,id:m.contentId,...h,...p,ref:t,style:{...p.style,"--radix-popover-content-transform-origin":`var(--radix-popper-transform-origin)`,"--radix-popover-content-available-width":`var(--radix-popper-available-width)`,"--radix-popover-content-available-height":`var(--radix-popper-available-height)`,"--radix-popover-trigger-width":`var(--radix-popper-anchor-width)`,"--radix-popover-trigger-height":`var(--radix-popper-anchor-height)`}})})})}),W=`PopoverClose`,G=C.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=k(W,n);return(0,w.jsx)(c.button,{type:`button`,...r,ref:t,onClick:p(e.onClick,()=>i.onOpenChange(!1))})});G.displayName=W;var K=`PopoverArrow`,q=C.forwardRef((e,t)=>{let{__scopePopover:n,...r}=e,i=D(n);return(0,w.jsx)(te,{...i,...r,ref:t})});q.displayName=K;function J(e){return e?`open`:`closed`}var Y=A,X=M,Z=P,ie=L,ae=z;function Q(e){let t=e.visualViewport;return t?Math.max(0,Math.round(e.innerHeight-t.height-t.offsetTop)):0}function oe(e,t,n,r=250){let i=e.visualViewport;if(!i)return t(0),()=>{};let a,o=()=>{let i=Q(e);t(i),n&&(clearTimeout(a),a=setTimeout(()=>n(i),r))};return t(Q(e)),i.addEventListener(`resize`,o),i.addEventListener(`scroll`,o),()=>{clearTimeout(a),i.removeEventListener(`resize`,o),i.removeEventListener(`scroll`,o),t(0)}}function se(e){let t=e.visualViewport;return t?{top:Math.max(0,Math.round(t.offsetTop)),bottom:Q(e)}:{top:0,bottom:0}}function ce(e,t=0){let n=typeof t==`number`?{top:t,right:t,bottom:t,left:t}:t;return{top:(n.top??0)+e.top,right:n.right??0,bottom:(n.bottom??0)+e.bottom,left:n.left??0}}function le(e,t){let n=e.visualViewport;if(!n)return t({top:0,bottom:0}),()=>{};let r=()=>t(se(e));return r(),n.addEventListener(`resize`,r),n.addEventListener(`scroll`,r),()=>{n.removeEventListener(`resize`,r),n.removeEventListener(`scroll`,r)}}function ue(){let[e,t]=(0,C.useState)({top:0,bottom:0});return(0,C.useEffect)(()=>le(window,e=>t(t=>t.top===e.top&&t.bottom===e.bottom?t:e)),[]),e}function de(e){let t=(0,C.useRef)(e);t.current=e,(0,C.useEffect)(()=>{let e=document.documentElement;return oe(window,t=>e.style.setProperty(`--kb`,`${t}px`),e=>t.current?.(e))},[])}var $=C.createContext(null);function fe({...e}){let t=C.useRef(!1);return(0,w.jsx)($,{value:t,children:(0,w.jsx)(Y,{"data-slot":`popover`,...e})})}function pe({onPointerDownCapture:e,onKeyDownCapture:t,...n}){let r=C.useContext($);return(0,w.jsx)(Z,{"data-slot":`popover-trigger`,...n,onPointerDownCapture:t=>{r&&(r.current=t.pointerType===`touch`),e?.(t)},onKeyDownCapture:e=>{r&&(r.current=!1),t?.(e)}})}function me({className:e,align:t=`center`,sideOffset:n=4,collisionPadding:r,onOpenAutoFocus:i,...a}){let o=ue(),s=C.useContext($);return(0,w.jsx)(ie,{children:(0,w.jsx)(ae,{"data-slot":`popover-content`,align:t,sideOffset:n,onOpenAutoFocus:e=>{let t=s?.current;if(s&&(s.current=!1),i?.(e),e.defaultPrevented||!t)return;let n=e.target;n instanceof HTMLElement&&n.querySelector(`[cmdk-input]`)&&(e.preventDefault(),n.focus({preventScroll:!0}))},collisionPadding:ce(o,r),className:y(`z-50 w-72 max-w-(--radix-popover-content-available-width) [overflow-wrap:anywhere] origin-(--radix-popover-content-transform-origin) rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-hidden data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95`,e),...a})})}function he({...e}){return(0,w.jsx)(X,{"data-slot":`popover-anchor`,...e})}function ge(){let e=h(),t=o(),n=(e.data?.profiles??[]).map(e=>({provider:e.provider,id:e.id,label:e.label,configDir:e.configDir})),r=t.data?.info?.root;return{accounts:n,repoAccount:r?e.data?.selections?.[r]:void 0}}function _e(e,t){return e.filter(e=>e.provider===t).length>1}export{me as a,he as i,ge as n,pe as o,fe as r,de as s,_e as t};
|