cli-jaw 2.2.3 → 2.2.4-preview.20260703203439
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.ja.md +1 -4
- package/README.ko.md +1 -4
- package/README.md +4 -7
- package/README.zh-CN.md +1 -4
- package/dist/bin/commands/bgtask.js +3 -1
- package/dist/bin/commands/bgtask.js.map +1 -1
- package/dist/bin/commands/chat.js +2 -2
- package/dist/bin/commands/chat.js.map +1 -1
- package/dist/bin/commands/dispatch.js +10 -3
- package/dist/bin/commands/dispatch.js.map +1 -1
- package/dist/bin/commands/tui/fullscreen-mode.js +44 -11
- package/dist/bin/commands/tui/fullscreen-mode.js.map +1 -1
- package/dist/bin/commands/tui/ws-handler.js +15 -1
- package/dist/bin/commands/tui/ws-handler.js.map +1 -1
- package/dist/scripts/fresh-install-smoke.js +1 -1
- package/dist/scripts/fresh-install-smoke.js.map +1 -1
- package/dist/server.js +1 -1
- package/dist/server.js.map +1 -1
- package/dist/src/agent/agy-bootstrap.js +104 -17
- package/dist/src/agent/agy-bootstrap.js.map +1 -1
- package/dist/src/agent/agy-runtime.js +104 -0
- package/dist/src/agent/agy-runtime.js.map +1 -1
- package/dist/src/agent/agy-transcript-watcher.js +14 -0
- package/dist/src/agent/agy-transcript-watcher.js.map +1 -1
- package/dist/src/agent/args.js +16 -83
- package/dist/src/agent/args.js.map +1 -1
- package/dist/src/agent/error-classifier.js +1 -3
- package/dist/src/agent/error-classifier.js.map +1 -1
- package/dist/src/agent/events/claude.js +60 -3
- package/dist/src/agent/events/claude.js.map +1 -1
- package/dist/src/agent/events/helpers.js +1 -1
- package/dist/src/agent/events/helpers.js.map +1 -1
- package/dist/src/agent/events/index.js +27 -27
- package/dist/src/agent/events/index.js.map +1 -1
- package/dist/src/agent/events/summary.js +0 -21
- package/dist/src/agent/events/summary.js.map +1 -1
- package/dist/src/agent/events/tool-labels.js +0 -28
- package/dist/src/agent/events/tool-labels.js.map +1 -1
- package/dist/src/agent/jwc-event-mapper.js +3 -3
- package/dist/src/agent/jwc-event-mapper.js.map +1 -1
- package/dist/src/agent/jwc-runtime.js +5 -1
- package/dist/src/agent/jwc-runtime.js.map +1 -1
- package/dist/src/agent/kiro-runtime.js +40 -14
- package/dist/src/agent/kiro-runtime.js.map +1 -1
- package/dist/src/agent/lifecycle-handler.js +2 -77
- package/dist/src/agent/lifecycle-handler.js.map +1 -1
- package/dist/src/agent/prompt-context.js +38 -0
- package/dist/src/agent/prompt-context.js.map +1 -0
- package/dist/src/agent/resume-classifier.js +0 -4
- package/dist/src/agent/resume-classifier.js.map +1 -1
- package/dist/src/agent/spawn/resume.js +0 -18
- package/dist/src/agent/spawn/resume.js.map +1 -1
- package/dist/src/agent/spawn-env.js +0 -28
- package/dist/src/agent/spawn-env.js.map +1 -1
- package/dist/src/agent/spawn.js +81 -76
- package/dist/src/agent/spawn.js.map +1 -1
- package/dist/src/bgtask/presets.js +13 -1
- package/dist/src/bgtask/presets.js.map +1 -1
- package/dist/src/cli/employee-handler.js +10 -10
- package/dist/src/cli/employee-handler.js.map +1 -1
- package/dist/src/cli/handlers-completions.js +29 -10
- package/dist/src/cli/handlers-completions.js.map +1 -1
- package/dist/src/cli/handlers-runtime.js +3 -2
- package/dist/src/cli/handlers-runtime.js.map +1 -1
- package/dist/src/cli/opencodex-models.js +118 -0
- package/dist/src/cli/opencodex-models.js.map +1 -0
- package/dist/src/cli/readiness.js +2 -8
- package/dist/src/cli/readiness.js.map +1 -1
- package/dist/src/cli/registry-live.js +21 -1
- package/dist/src/cli/registry-live.js.map +1 -1
- package/dist/src/cli/registry.js +10 -21
- package/dist/src/cli/registry.js.map +1 -1
- package/dist/src/cli/tui/jawcode-bridge.js +15 -13
- package/dist/src/cli/tui/jawcode-bridge.js.map +1 -1
- package/dist/src/cli/tui/jawcode-render.js +26 -0
- package/dist/src/cli/tui/jawcode-render.js.map +1 -1
- package/dist/src/cli/tui/render/frame.js +158 -16
- package/dist/src/cli/tui/render/frame.js.map +1 -1
- package/dist/src/cli/tui/transcript.js +79 -3
- package/dist/src/cli/tui/transcript.js.map +1 -1
- package/dist/src/core/cli-detect.js +1 -1
- package/dist/src/core/cli-detect.js.map +1 -1
- package/dist/src/core/employees.js +12 -7
- package/dist/src/core/employees.js.map +1 -1
- package/dist/src/core/event-bus.js +13 -0
- package/dist/src/core/event-bus.js.map +1 -1
- package/dist/src/goal/heartbeat.js +8 -0
- package/dist/src/goal/heartbeat.js.map +1 -1
- package/dist/src/manager/load-timing.js +29 -0
- package/dist/src/manager/load-timing.js.map +1 -0
- package/dist/src/manager/observability.js.map +1 -1
- package/dist/src/manager/server.js +67 -6
- package/dist/src/manager/server.js.map +1 -1
- package/dist/src/memory/bootstrap.js +43 -1
- package/dist/src/memory/bootstrap.js.map +1 -1
- package/dist/src/orchestrator/distribute.js +5 -1
- package/dist/src/orchestrator/distribute.js.map +1 -1
- package/dist/src/orchestrator/state-machine.js +20 -0
- package/dist/src/orchestrator/state-machine.js.map +1 -1
- package/dist/src/orchestrator/worker-registry.js +2 -1
- package/dist/src/orchestrator/worker-registry.js.map +1 -1
- package/dist/src/prompt/templates/a1-system.md +61 -11
- package/dist/src/prompt/templates/employee.md +13 -0
- package/dist/src/prompt/templates/orchestration.md +14 -0
- package/dist/src/prompt/templates/worker-context.md +4 -4
- package/dist/src/routes/employees.js +8 -8
- package/dist/src/routes/employees.js.map +1 -1
- package/dist/src/routes/events.js +57 -19
- package/dist/src/routes/events.js.map +1 -1
- package/dist/src/routes/orchestrate.js +42 -17
- package/dist/src/routes/orchestrate.js.map +1 -1
- package/dist/src/routes/quota-agy-reverse.js +0 -24
- package/dist/src/routes/quota-agy-reverse.js.map +1 -1
- package/dist/src/routes/quota.js +0 -145
- package/dist/src/routes/quota.js.map +1 -1
- package/dist/src/routes/settings.js +2 -7
- package/dist/src/routes/settings.js.map +1 -1
- package/dist/src/shared/tool-log-sanitize.js +6 -0
- package/dist/src/shared/tool-log-sanitize.js.map +1 -1
- package/dist/src/telegram/forwarder.js +53 -5
- package/dist/src/telegram/forwarder.js.map +1 -1
- package/dist/src/trace/store.js +82 -0
- package/dist/src/trace/store.js.map +1 -1
- package/dist/src/types/cli-engine.js +0 -1
- package/dist/src/types/cli-engine.js.map +1 -1
- package/dist/src/types/cli-events.js +1 -1
- package/dist/src/types/cli-events.js.map +1 -1
- package/package.json +2 -2
- package/public/dist/assets/Agent-CHCXjXSN.js +1 -0
- package/public/dist/assets/CodeCanvas-BzhNLZVF.js +3 -0
- package/public/dist/assets/DocPanel-6Z_RELzd.js +1 -0
- package/public/dist/assets/{DocPanel-D3FYBhMp.css → DocPanel-DZKPTOm8.css} +1 -1
- package/public/dist/assets/FolderPanel-DdlzWAuK.js +3 -0
- package/public/dist/assets/{Heartbeat-D-Rfp094.js → Heartbeat-BblY8Z4a.js} +1 -1
- package/public/dist/assets/MarkdownRenderer-BivJ4hJm.js +1 -0
- package/public/dist/assets/MarkdownRenderer-Cl0oEICj.js +15 -0
- package/public/dist/assets/{Memory-VH4ZJCMW.js → Memory-BWcfxzCz.js} +1 -1
- package/public/dist/assets/ModelProvider-D4LBX7K2.js +1 -0
- package/public/dist/assets/agent-meta-FyI15KAa.js +1 -0
- package/public/dist/assets/{app-DaORcAyD.js → app-DszWzakT.js} +4 -4
- package/public/dist/assets/bgtask-badge-DZEQ5fMl.js +1 -0
- package/public/dist/assets/{bgtask-badge-BtUXEe1T.js → bgtask-badge-b7pj_Dbh.js} +1 -1
- package/public/dist/assets/constants-EMUBd5RQ.js +1 -0
- package/public/dist/assets/{employees-CZSyvJbx.js → employees-DbgFV33i.js} +1 -1
- package/public/dist/assets/{manager-DB5qTw1A.js → manager-CdNOlCyS.js} +4 -4
- package/public/dist/assets/{manager-D3waO_XX.css → manager-rHNwUB4e.css} +1 -1
- package/public/dist/assets/memory-BT-rs3ag.js +1 -0
- package/public/dist/assets/{memory-cWI_Htbn.js → memory-QobGT0Kv.js} +1 -1
- package/public/dist/assets/message-history-BY1UNJAO.js +1 -0
- package/public/dist/assets/message-history-BmP5JKio.js +142 -0
- package/public/dist/assets/{render-Bp8eyqCf.js → render-C3r-9_-J.js} +2 -2
- package/public/dist/assets/settings-CJm8ZSJs.js +1 -0
- package/public/dist/assets/{settings-DLkP7qRV.js → settings-D70uFh8l.js} +1 -1
- package/public/dist/assets/{settings-core-B5XRRNcX.js → settings-core-B2lw2bgO.js} +1 -1
- package/public/dist/assets/settings-core-gdS0lo1b.js +1 -0
- package/public/dist/assets/{sidebar-CsogFOse.js → sidebar-BqWm2XWP.js} +3 -3
- package/public/dist/assets/{skills-Dmf4v9rj.js → skills-CdNOfXlk.js} +1 -1
- package/public/dist/assets/skills-DG_CbTEf.js +1 -0
- package/public/dist/assets/{slash-commands-vcf7FuPD.js → slash-commands-4Ntm5N7h.js} +1 -1
- package/public/dist/assets/slash-commands-B9kOEhJ_.js +1 -0
- package/public/dist/assets/{trace-drawer-DuQQ0SNq.js → trace-drawer-DqAwwHHQ.js} +1 -1
- package/public/dist/assets/ui-Anw2S64o.js +1 -0
- package/public/dist/assets/ui-DsK6r0Xv.js +2 -0
- package/public/dist/index.html +1 -1
- package/public/dist/manager/index.html +2 -2
- package/public/js/constants.ts +7 -7
- package/public/js/features/employees.ts +0 -3
- package/public/js/features/process-block-dom.ts +6 -1
- package/public/js/features/process-block.ts +59 -3
- package/public/js/render/file-links.ts +1 -1
- package/public/js/ui.ts +9 -1
- package/public/js/virtual-scroll.ts +23 -0
- package/public/js/ws.ts +7 -2
- package/public/manager/src/SidebarRailRouter.tsx +15 -10
- package/public/manager/src/code/CodeCanvas.tsx +3 -1
- package/public/manager/src/code/CodeTranscript.tsx +5 -4
- package/public/manager/src/code/CodeWorkbench.tsx +2 -1
- package/public/manager/src/doc-panel/DocPanel.tsx +52 -5
- package/public/manager/src/doc-panel/doc-panel.css +10 -0
- package/public/manager/src/folder-panel/FolderPanel.tsx +14 -16
- package/public/manager/src/folder-panel/use-folder-git-status.ts +15 -0
- package/public/manager/src/folder-panel/use-folder-preview-sync.ts +37 -0
- package/public/manager/src/folder-panel/use-folder-visible-refresh.ts +19 -6
- package/public/manager/src/manager-notes.css +23 -0
- package/public/manager/src/notes/rendering/MarkdownRenderer.tsx +80 -2
- package/public/manager/src/settings/pages/Agent.tsx +30 -8
- package/public/manager/src/settings/pages/ModelProvider.tsx +22 -4
- package/public/manager/src/settings/pages/components/agent/AgentEmployeesSection.tsx +5 -1
- package/public/manager/src/settings/pages/components/agent/FlushAgentSection.tsx +5 -3
- package/public/manager/src/settings/pages/components/agent/RuntimeEmployeeRow.tsx +6 -4
- package/public/manager/src/settings/pages/components/agent/RuntimeHeader.tsx +4 -2
- package/public/manager/src/settings/pages/components/agent/agent-meta.ts +45 -9
- package/public/manager/src/settings/pages/components/agent/runtime-employees-helpers.ts +7 -2
- package/scripts/capture-agy-quota-fixture.mjs +138 -0
- package/scripts/fresh-install-smoke.ts +1 -1
- package/dist/src/agent/events/gemini.js +0 -100
- package/dist/src/agent/events/gemini.js.map +0 -1
- package/public/dist/assets/Agent-Ci12HWhE.js +0 -1
- package/public/dist/assets/CodeCanvas-d1gh0-lY.js +0 -3
- package/public/dist/assets/DocPanel-C6XQ7W6A.js +0 -1
- package/public/dist/assets/FolderPanel-DIFAqajZ.js +0 -3
- package/public/dist/assets/MarkdownRenderer-DXKUEE2a.js +0 -1
- package/public/dist/assets/MarkdownRenderer-DcIxpNcX.js +0 -15
- package/public/dist/assets/ModelProvider-_tUCghOF.js +0 -1
- package/public/dist/assets/agent-meta-DqBTGRRQ.js +0 -1
- package/public/dist/assets/bgtask-badge-B3HLOZae.js +0 -1
- package/public/dist/assets/constants-DkJ3E63Y.js +0 -1
- package/public/dist/assets/memory-BEruUlfu.js +0 -1
- package/public/dist/assets/message-history-DU1V9ZAW.js +0 -142
- package/public/dist/assets/message-history-tjkyOp_K.js +0 -1
- package/public/dist/assets/settings-B-GgyJZI.js +0 -1
- package/public/dist/assets/settings-core-Cw1av-Ox.js +0 -1
- package/public/dist/assets/skills-CLcoop6W.js +0 -1
- package/public/dist/assets/slash-commands-DY6-hzq6.js +0 -1
- package/public/dist/assets/ui-BKYuBdZE.js +0 -2
- package/public/dist/assets/ui-CqlGwgUo.js +0 -1
|
@@ -13,10 +13,12 @@ import { FlushAgentSection } from './components/agent/FlushAgentSection';
|
|
|
13
13
|
import { AgentEmployeesSection } from './components/agent/AgentEmployeesSection';
|
|
14
14
|
import {
|
|
15
15
|
metaFor,
|
|
16
|
+
normalizeCliMetaRegistry,
|
|
16
17
|
optionList,
|
|
17
18
|
runtimeEffortFor,
|
|
18
19
|
runtimeModelFor,
|
|
19
20
|
type ActiveOverride,
|
|
21
|
+
type CliMeta,
|
|
20
22
|
type PerCliEntry,
|
|
21
23
|
} from './components/agent/agent-meta';
|
|
22
24
|
import {
|
|
@@ -75,6 +77,19 @@ export default function Agent({ port, client, dirty, registerSave }: SettingsPag
|
|
|
75
77
|
const [employeeDraft, setEmployeeDraft] = useState<RuntimeEmployeeRecord[]>([]);
|
|
76
78
|
const [employeeLoading, setEmployeeLoading] = useState(true);
|
|
77
79
|
const [employeeError, setEmployeeError] = useState<string | null>(null);
|
|
80
|
+
const [cliMeta, setCliMeta] = useState<Record<string, CliMeta> | null>(null);
|
|
81
|
+
|
|
82
|
+
const loadCliMeta = useCallback(async () => {
|
|
83
|
+
try {
|
|
84
|
+
const response = await client.get<{ data?: unknown } | Record<string, unknown>>('/api/cli-registry');
|
|
85
|
+
const data = response && typeof response === 'object' && 'data' in response
|
|
86
|
+
? (response as { data?: unknown }).data
|
|
87
|
+
: response;
|
|
88
|
+
setCliMeta(normalizeCliMetaRegistry(data));
|
|
89
|
+
} catch {
|
|
90
|
+
setCliMeta(null);
|
|
91
|
+
}
|
|
92
|
+
}, [client]);
|
|
78
93
|
|
|
79
94
|
const loadFlush = useCallback(async () => {
|
|
80
95
|
setFlushLoading(true);
|
|
@@ -107,24 +122,26 @@ export default function Agent({ port, client, dirty, registerSave }: SettingsPag
|
|
|
107
122
|
}, [client]);
|
|
108
123
|
|
|
109
124
|
useEffect(() => {
|
|
125
|
+
void loadCliMeta();
|
|
110
126
|
void loadFlush();
|
|
111
127
|
void loadEmployees();
|
|
112
|
-
}, [loadEmployees, loadFlush]);
|
|
128
|
+
}, [loadCliMeta, loadEmployees, loadFlush]);
|
|
113
129
|
|
|
114
130
|
useEffect(() => {
|
|
115
131
|
if (state.kind !== 'ready') return;
|
|
116
132
|
const cliKeys = Object.keys(state.data.perCli || {});
|
|
117
133
|
const cli = state.data.cli || cliKeys[0] || '';
|
|
118
134
|
const permissions = parsePermissionsValue(state.data.permissions);
|
|
135
|
+
const meta = metaFor(cli, cliMeta);
|
|
119
136
|
setDraft({
|
|
120
137
|
cli,
|
|
121
|
-
provider: state.data.perCli?.[cli]?.provider ||
|
|
138
|
+
provider: state.data.perCli?.[cli]?.provider || meta.defaultProvider || '',
|
|
122
139
|
model: runtimeModelFor(cli, state.data.perCli, state.data.activeOverrides),
|
|
123
140
|
effort: runtimeEffortFor(cli, state.data.perCli, state.data.activeOverrides),
|
|
124
141
|
workingDir: state.data.workingDir || '',
|
|
125
142
|
permissions: permissions.mode === 'custom' ? permissions.tokens : 'auto',
|
|
126
143
|
});
|
|
127
|
-
}, [state]);
|
|
144
|
+
}, [cliMeta, state]);
|
|
128
145
|
|
|
129
146
|
useEffect(() => {
|
|
130
147
|
return () => {
|
|
@@ -153,9 +170,10 @@ export default function Agent({ port, client, dirty, registerSave }: SettingsPag
|
|
|
153
170
|
dirty.clear();
|
|
154
171
|
if (freshSettings) setData(freshSettings as AgentSnapshot);
|
|
155
172
|
await refresh();
|
|
173
|
+
await loadCliMeta();
|
|
156
174
|
await loadFlush();
|
|
157
175
|
await loadEmployees();
|
|
158
|
-
}, [client, dirty, employeeDraft, employeeOriginal, loadEmployees, loadFlush, refresh, setData]);
|
|
176
|
+
}, [client, dirty, employeeDraft, employeeOriginal, loadCliMeta, loadEmployees, loadFlush, refresh, setData]);
|
|
159
177
|
|
|
160
178
|
useEffect(() => {
|
|
161
179
|
if (!registerSave) return;
|
|
@@ -167,7 +185,7 @@ export default function Agent({ port, client, dirty, registerSave }: SettingsPag
|
|
|
167
185
|
const perCli = settingsData.perCli || {};
|
|
168
186
|
const activeOverrides = settingsData.activeOverrides || {};
|
|
169
187
|
const cliOptions = useMemo(() => Object.keys(perCli), [perCli]);
|
|
170
|
-
const activeMeta = metaFor(draft.cli);
|
|
188
|
+
const activeMeta = metaFor(draft.cli, cliMeta);
|
|
171
189
|
const activeProvider = draft.provider || activeMeta.defaultProvider || activeMeta.providers?.[0] || '';
|
|
172
190
|
const isPiRuntime = draft.cli === 'pi';
|
|
173
191
|
const hasProviders = !isPiRuntime && (activeMeta.providers?.length ?? 0) > 0;
|
|
@@ -212,11 +230,13 @@ export default function Agent({ port, client, dirty, registerSave }: SettingsPag
|
|
|
212
230
|
effortOptions={activeEffortOptions}
|
|
213
231
|
workingDir={draft.workingDir}
|
|
214
232
|
workingDirError={workingDirError}
|
|
233
|
+
cliMeta={cliMeta}
|
|
215
234
|
onCliChange={(next) => {
|
|
235
|
+
const nextMeta = metaFor(next, cliMeta);
|
|
216
236
|
const nextDraft = {
|
|
217
237
|
...draft,
|
|
218
238
|
cli: next,
|
|
219
|
-
provider: perCli[next]?.provider ||
|
|
239
|
+
provider: perCli[next]?.provider || nextMeta.defaultProvider || '',
|
|
220
240
|
model: runtimeModelFor(next, perCli, activeOverrides),
|
|
221
241
|
effort: runtimeEffortFor(next, perCli, activeOverrides),
|
|
222
242
|
};
|
|
@@ -287,11 +307,12 @@ export default function Agent({ port, client, dirty, registerSave }: SettingsPag
|
|
|
287
307
|
flushCli={flushDraft.cli || ''}
|
|
288
308
|
flushModel={flushDraft.model || ''}
|
|
289
309
|
cliOptions={cliOptions}
|
|
290
|
-
|
|
310
|
+
cliMeta={cliMeta}
|
|
311
|
+
modelOptions={optionList(metaFor(flushDraft.cli || draft.cli, cliMeta).models, flushDraft.model || '')}
|
|
291
312
|
loading={flushLoading}
|
|
292
313
|
error={flushError}
|
|
293
314
|
onFlushCliChange={(next) => {
|
|
294
|
-
const model = next ? metaFor(next).models[0] || '' : '';
|
|
315
|
+
const model = next ? metaFor(next, cliMeta).models[0] || '' : '';
|
|
295
316
|
setFlushDraft({ cli: next, model });
|
|
296
317
|
setEntry('flushCli', { value: next, original: flushOriginal.cli || '', valid: true });
|
|
297
318
|
setEntry('flushModel', { value: model, original: flushOriginal.model || '', valid: true });
|
|
@@ -305,6 +326,7 @@ export default function Agent({ port, client, dirty, registerSave }: SettingsPag
|
|
|
305
326
|
roster={employeeDraft}
|
|
306
327
|
original={employeeOriginal}
|
|
307
328
|
cliOptions={cliOptions}
|
|
329
|
+
cliMeta={cliMeta}
|
|
308
330
|
loading={employeeLoading}
|
|
309
331
|
error={employeeError}
|
|
310
332
|
onRosterChange={(next) => {
|
|
@@ -12,8 +12,8 @@ import {
|
|
|
12
12
|
usePageSnapshot,
|
|
13
13
|
} from './page-shell';
|
|
14
14
|
import { PerCliRow } from './components/PerCliRow';
|
|
15
|
-
import { metaFor } from './components/agent/agent-meta';
|
|
16
|
-
import type { PerCliEntry } from './components/agent/agent-meta';
|
|
15
|
+
import { metaFor, normalizeCliMetaRegistry } from './components/agent/agent-meta';
|
|
16
|
+
import type { CliMeta, PerCliEntry } from './components/agent/agent-meta';
|
|
17
17
|
import type { PiSettingsView } from './components/pi-profile';
|
|
18
18
|
import { expandPatch } from './path-utils';
|
|
19
19
|
|
|
@@ -58,6 +58,23 @@ export default function ModelProvider({ port, client, dirty, registerSave }: Set
|
|
|
58
58
|
const [codexCtx, setCodexCtx] = useState<{ contextWindowSize?: number; contextWindowCompactLimit?: number }>({});
|
|
59
59
|
const [resetting, setResetting] = useState(false);
|
|
60
60
|
const [resetError, setResetError] = useState<string | null>(null);
|
|
61
|
+
const [cliMeta, setCliMeta] = useState<Record<string, CliMeta> | null>(null);
|
|
62
|
+
|
|
63
|
+
const loadCliMeta = useCallback(async () => {
|
|
64
|
+
try {
|
|
65
|
+
const response = await client.get<{ data?: unknown } | Record<string, unknown>>('/api/cli-registry');
|
|
66
|
+
const data = response && typeof response === 'object' && 'data' in response
|
|
67
|
+
? (response as { data?: unknown }).data
|
|
68
|
+
: response;
|
|
69
|
+
setCliMeta(normalizeCliMetaRegistry(data));
|
|
70
|
+
} catch {
|
|
71
|
+
setCliMeta(null);
|
|
72
|
+
}
|
|
73
|
+
}, [client]);
|
|
74
|
+
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
void loadCliMeta();
|
|
77
|
+
}, [loadCliMeta]);
|
|
61
78
|
|
|
62
79
|
useEffect(() => {
|
|
63
80
|
if (state.kind !== 'ready') return;
|
|
@@ -101,7 +118,8 @@ export default function ModelProvider({ port, client, dirty, registerSave }: Set
|
|
|
101
118
|
setPerCliDraft({ ...(fresh.perCli || {}) });
|
|
102
119
|
setFallback([...(fresh.fallbackOrder || [])]);
|
|
103
120
|
await refresh();
|
|
104
|
-
|
|
121
|
+
await loadCliMeta();
|
|
122
|
+
}, [client, dirty, loadCliMeta, refresh, setData]);
|
|
105
123
|
|
|
106
124
|
useEffect(() => {
|
|
107
125
|
if (!registerSave) return;
|
|
@@ -159,7 +177,7 @@ export default function ModelProvider({ port, client, dirty, registerSave }: Set
|
|
|
159
177
|
<PerCliRow
|
|
160
178
|
key={cli}
|
|
161
179
|
cli={cli}
|
|
162
|
-
meta={metaFor(cli)}
|
|
180
|
+
meta={metaFor(cli, cliMeta)}
|
|
163
181
|
original={perCliOriginal[cli] || {}}
|
|
164
182
|
value={perCliDraft[cli] || perCliOriginal[cli] || {}}
|
|
165
183
|
setValue={(next) => setPerCliDraft({ ...perCliDraft, [cli]: next })}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SettingsSection } from '../../page-shell';
|
|
2
2
|
import { RuntimeEmployeeRow } from './RuntimeEmployeeRow';
|
|
3
|
+
import type { CliMeta } from './agent-meta';
|
|
3
4
|
import {
|
|
4
5
|
makeDefaultRuntimeEmployee,
|
|
5
6
|
runtimeEmployeeChangeSummary,
|
|
@@ -11,6 +12,7 @@ type AgentEmployeesSectionProps = {
|
|
|
11
12
|
roster: RuntimeEmployeeRecord[];
|
|
12
13
|
original: RuntimeEmployeeRecord[];
|
|
13
14
|
cliOptions: ReadonlyArray<string>;
|
|
15
|
+
cliMeta?: Record<string, CliMeta> | null;
|
|
14
16
|
loading?: boolean;
|
|
15
17
|
error?: string | null;
|
|
16
18
|
onRosterChange(next: RuntimeEmployeeRecord[]): void;
|
|
@@ -20,6 +22,7 @@ export function AgentEmployeesSection({
|
|
|
20
22
|
roster,
|
|
21
23
|
original,
|
|
22
24
|
cliOptions,
|
|
25
|
+
cliMeta,
|
|
23
26
|
loading,
|
|
24
27
|
error,
|
|
25
28
|
onRosterChange,
|
|
@@ -58,6 +61,7 @@ export function AgentEmployeesSection({
|
|
|
58
61
|
employee={employee}
|
|
59
62
|
index={idx}
|
|
60
63
|
cliOptions={cliOptions}
|
|
64
|
+
cliMeta={cliMeta ?? null}
|
|
61
65
|
onChange={(patch) => updateRow(idx, patch)}
|
|
62
66
|
onRemove={() => removeRow(idx)}
|
|
63
67
|
/>
|
|
@@ -68,7 +72,7 @@ export function AgentEmployeesSection({
|
|
|
68
72
|
<button
|
|
69
73
|
type="button"
|
|
70
74
|
className="settings-action settings-action-discard"
|
|
71
|
-
onClick={() => onRosterChange([...roster, makeDefaultRuntimeEmployee(cliOptions)])}
|
|
75
|
+
onClick={() => onRosterChange([...roster, makeDefaultRuntimeEmployee(cliOptions, cliMeta)])}
|
|
72
76
|
>
|
|
73
77
|
+ Add employee
|
|
74
78
|
</button>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SelectField } from '../../../fields';
|
|
2
2
|
import { SettingsSection } from '../../page-shell';
|
|
3
|
-
import { metaFor } from './agent-meta';
|
|
3
|
+
import { metaFor, type CliMeta } from './agent-meta';
|
|
4
4
|
|
|
5
5
|
type FlushAgentSectionProps = {
|
|
6
6
|
activeCli: string;
|
|
@@ -8,6 +8,7 @@ type FlushAgentSectionProps = {
|
|
|
8
8
|
flushModel: string;
|
|
9
9
|
cliOptions: ReadonlyArray<string>;
|
|
10
10
|
modelOptions: ReadonlyArray<{ value: string; label: string }>;
|
|
11
|
+
cliMeta?: Record<string, CliMeta> | null;
|
|
11
12
|
loading?: boolean;
|
|
12
13
|
error?: string | null;
|
|
13
14
|
onFlushCliChange(next: string): void;
|
|
@@ -20,13 +21,14 @@ export function FlushAgentSection({
|
|
|
20
21
|
flushModel,
|
|
21
22
|
cliOptions,
|
|
22
23
|
modelOptions,
|
|
24
|
+
cliMeta,
|
|
23
25
|
loading,
|
|
24
26
|
error,
|
|
25
27
|
onFlushCliChange,
|
|
26
28
|
onFlushModelChange,
|
|
27
29
|
}: FlushAgentSectionProps) {
|
|
28
30
|
const effectiveCli = flushCli || activeCli;
|
|
29
|
-
const effectiveCliLabel = effectiveCli ? metaFor(effectiveCli).label || effectiveCli : 'active';
|
|
31
|
+
const effectiveCliLabel = effectiveCli ? metaFor(effectiveCli, cliMeta).label || effectiveCli : 'active';
|
|
30
32
|
return (
|
|
31
33
|
<SettingsSection
|
|
32
34
|
title="Flush Agent"
|
|
@@ -46,7 +48,7 @@ export function FlushAgentSection({
|
|
|
46
48
|
value={flushCli}
|
|
47
49
|
options={[
|
|
48
50
|
{ value: '', label: '(active CLI)' },
|
|
49
|
-
...cliOptions.map((value) => ({ value, label: metaFor(value).label || value })),
|
|
51
|
+
...cliOptions.map((value) => ({ value, label: metaFor(value, cliMeta).label || value })),
|
|
50
52
|
]}
|
|
51
53
|
onChange={onFlushCliChange}
|
|
52
54
|
/>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SelectField, TextField } from '../../../fields';
|
|
2
|
-
import { metaFor, optionList } from './agent-meta';
|
|
2
|
+
import { metaFor, optionList, type CliMeta } from './agent-meta';
|
|
3
3
|
import {
|
|
4
4
|
isStaticEmployee,
|
|
5
5
|
runtimeEmployeeError,
|
|
@@ -10,6 +10,7 @@ type RuntimeEmployeeRowProps = {
|
|
|
10
10
|
employee: RuntimeEmployeeRecord;
|
|
11
11
|
index: number;
|
|
12
12
|
cliOptions: ReadonlyArray<string>;
|
|
13
|
+
cliMeta?: Record<string, CliMeta> | null;
|
|
13
14
|
onChange(patch: Partial<RuntimeEmployeeRecord>): void;
|
|
14
15
|
onRemove(): void;
|
|
15
16
|
};
|
|
@@ -18,11 +19,12 @@ export function RuntimeEmployeeRow({
|
|
|
18
19
|
employee,
|
|
19
20
|
index,
|
|
20
21
|
cliOptions,
|
|
22
|
+
cliMeta,
|
|
21
23
|
onChange,
|
|
22
24
|
onRemove,
|
|
23
25
|
}: RuntimeEmployeeRowProps) {
|
|
24
26
|
const locked = isStaticEmployee(employee);
|
|
25
|
-
const meta = metaFor(employee.cli);
|
|
27
|
+
const meta = metaFor(employee.cli, cliMeta);
|
|
26
28
|
const modelOptions = optionList(meta.models, employee.model);
|
|
27
29
|
const error = runtimeEmployeeError(employee);
|
|
28
30
|
const cliChoices = Array.from(new Set([...cliOptions, employee.cli, 'claude'])).filter(Boolean);
|
|
@@ -47,9 +49,9 @@ export function RuntimeEmployeeRow({
|
|
|
47
49
|
label="CLI"
|
|
48
50
|
value={employee.cli}
|
|
49
51
|
disabled={locked}
|
|
50
|
-
options={cliChoices.map((value) => ({ value, label: metaFor(value).label || value }))}
|
|
52
|
+
options={cliChoices.map((value) => ({ value, label: metaFor(value, cliMeta).label || value }))}
|
|
51
53
|
onChange={(next) => {
|
|
52
|
-
const nextModel = metaFor(next).models[0] || 'default';
|
|
54
|
+
const nextModel = metaFor(next, cliMeta).models[0] || 'default';
|
|
53
55
|
onChange({ cli: next, model: nextModel });
|
|
54
56
|
}}
|
|
55
57
|
/>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SelectField, TextField } from '../../../fields';
|
|
2
2
|
import { SettingsSection } from '../../page-shell';
|
|
3
|
-
import { metaFor, orderRuntimeCliOptions, PRIMARY_CLIS } from './agent-meta';
|
|
3
|
+
import { metaFor, orderRuntimeCliOptions, PRIMARY_CLIS, type CliMeta } from './agent-meta';
|
|
4
4
|
|
|
5
5
|
type RuntimeHeaderProps = {
|
|
6
6
|
cli: string;
|
|
@@ -13,6 +13,7 @@ type RuntimeHeaderProps = {
|
|
|
13
13
|
effortOptions: ReadonlyArray<string>;
|
|
14
14
|
workingDir: string;
|
|
15
15
|
workingDirError: string | null;
|
|
16
|
+
cliMeta?: Record<string, CliMeta> | null;
|
|
16
17
|
onCliChange(next: string): void;
|
|
17
18
|
onProviderChange?(next: string): void;
|
|
18
19
|
onModelChange(next: string): void;
|
|
@@ -31,6 +32,7 @@ export function RuntimeHeader({
|
|
|
31
32
|
effortOptions,
|
|
32
33
|
workingDir,
|
|
33
34
|
workingDirError,
|
|
35
|
+
cliMeta,
|
|
34
36
|
onCliChange,
|
|
35
37
|
onProviderChange,
|
|
36
38
|
onModelChange,
|
|
@@ -50,7 +52,7 @@ export function RuntimeHeader({
|
|
|
50
52
|
id="agent-cli"
|
|
51
53
|
label="Active CLI"
|
|
52
54
|
value={cli}
|
|
53
|
-
options={orderedCliOptions.map((value) => ({ value, label: metaFor(value).label || value }))}
|
|
55
|
+
options={orderedCliOptions.map((value) => ({ value, label: metaFor(value, cliMeta).label || value }))}
|
|
54
56
|
collapsedAfter={orderedPrimaryCliCount}
|
|
55
57
|
onChange={onCliChange}
|
|
56
58
|
/>
|
|
@@ -26,6 +26,8 @@ export type ActiveOverride = {
|
|
|
26
26
|
effort?: string;
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
+
const CODEX_MODELS: ReadonlyArray<string> = ['gpt-5.5', 'gpt-5.4', 'gpt-5.4-mini', 'gpt-5.3-codex-spark'];
|
|
30
|
+
|
|
29
31
|
export const PRIMARY_CLIS: ReadonlyArray<string> = ['pi', 'claude', 'claude-e', 'jwc', 'agy', 'codex', 'cursor', 'kiro-code', 'gemini'];
|
|
30
32
|
|
|
31
33
|
export const CLI_META: Record<string, CliMeta> = {
|
|
@@ -48,11 +50,11 @@ export const CLI_META: Record<string, CliMeta> = {
|
|
|
48
50
|
label: 'AI-E',
|
|
49
51
|
defaultProvider: 'claude',
|
|
50
52
|
providers: ['claude', 'codex', 'gemini', 'grok', 'copilot', 'kiro'],
|
|
51
|
-
models: ['opus', 'sonnet', 'haiku',
|
|
53
|
+
models: ['opus', 'sonnet', 'haiku', ...CODEX_MODELS, 'gemini-3-flash-preview', 'grok-build', 'grok-composer-2.5-fast', 'gpt-5-mini'],
|
|
52
54
|
efforts: ['low', 'medium', 'high', 'xhigh', 'max'],
|
|
53
55
|
modelsByProvider: {
|
|
54
56
|
claude: ['claude-fable-5', 'claude-opus-4-8', 'opus', 'sonnet', 'haiku'],
|
|
55
|
-
codex:
|
|
57
|
+
codex: CODEX_MODELS,
|
|
56
58
|
gemini: ['gemini-3-flash-preview'],
|
|
57
59
|
grok: ['grok-build', 'grok-composer-2.5-fast'],
|
|
58
60
|
copilot: ['gpt-5-mini'],
|
|
@@ -64,7 +66,7 @@ export const CLI_META: Record<string, CliMeta> = {
|
|
|
64
66
|
gemini: [],
|
|
65
67
|
grok: [],
|
|
66
68
|
copilot: ['low', 'medium', 'high'],
|
|
67
|
-
kiro: [],
|
|
69
|
+
kiro: ['low', 'medium', 'high', 'xhigh'],
|
|
68
70
|
},
|
|
69
71
|
},
|
|
70
72
|
claude: {
|
|
@@ -126,12 +128,12 @@ export const CLI_META: Record<string, CliMeta> = {
|
|
|
126
128
|
},
|
|
127
129
|
codex: {
|
|
128
130
|
label: 'Codex',
|
|
129
|
-
models:
|
|
131
|
+
models: CODEX_MODELS,
|
|
130
132
|
efforts: ['low', 'medium', 'high', 'xhigh'],
|
|
131
133
|
},
|
|
132
134
|
'codex-app': {
|
|
133
135
|
label: 'Codex App',
|
|
134
|
-
models:
|
|
136
|
+
models: CODEX_MODELS,
|
|
135
137
|
efforts: ['low', 'medium', 'high', 'xhigh'],
|
|
136
138
|
},
|
|
137
139
|
cursor: {
|
|
@@ -171,8 +173,8 @@ export const CLI_META: Record<string, CliMeta> = {
|
|
|
171
173
|
'glm-5',
|
|
172
174
|
'qwen3-coder-next',
|
|
173
175
|
],
|
|
174
|
-
efforts: [],
|
|
175
|
-
effortNote: 'Kiro CLI
|
|
176
|
+
efforts: ['low', 'medium', 'high', 'xhigh'],
|
|
177
|
+
effortNote: 'Kiro CLI forwards --effort; cli-jaw maps xhigh to Kiro max on the wire',
|
|
176
178
|
},
|
|
177
179
|
gemini: {
|
|
178
180
|
label: 'Gemini',
|
|
@@ -197,8 +199,42 @@ export const CLI_META: Record<string, CliMeta> = {
|
|
|
197
199
|
},
|
|
198
200
|
};
|
|
199
201
|
|
|
200
|
-
|
|
201
|
-
return
|
|
202
|
+
function stringArray(value: unknown): string[] {
|
|
203
|
+
return Array.isArray(value) ? value.filter((entry): entry is string => typeof entry === 'string') : [];
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function stringArrayRecord(value: unknown): Record<string, string[]> | undefined {
|
|
207
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined;
|
|
208
|
+
const out: Record<string, string[]> = {};
|
|
209
|
+
for (const [key, raw] of Object.entries(value as Record<string, unknown>)) out[key] = stringArray(raw);
|
|
210
|
+
return out;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export function normalizeCliMetaRegistry(raw: unknown): Record<string, CliMeta> {
|
|
214
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return {};
|
|
215
|
+
const out: Record<string, CliMeta> = {};
|
|
216
|
+
for (const [key, value] of Object.entries(raw as Record<string, unknown>)) {
|
|
217
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) continue;
|
|
218
|
+
const record = value as Record<string, unknown>;
|
|
219
|
+
const modelsByProvider = stringArrayRecord(record['modelsByProvider']);
|
|
220
|
+
const effortsByProvider = stringArrayRecord(record['effortsByProvider']);
|
|
221
|
+
out[key] = {
|
|
222
|
+
label: typeof record['label'] === 'string' ? record['label'] : key,
|
|
223
|
+
models: stringArray(record['models']),
|
|
224
|
+
efforts: stringArray(record['efforts']),
|
|
225
|
+
...(typeof record['defaultProvider'] === 'string' ? { defaultProvider: record['defaultProvider'] } : {}),
|
|
226
|
+
...(record['providers'] ? { providers: stringArray(record['providers']) } : {}),
|
|
227
|
+
...(modelsByProvider ? { modelsByProvider } : {}),
|
|
228
|
+
...(effortsByProvider ? { effortsByProvider } : {}),
|
|
229
|
+
...(typeof record['effortNote'] === 'string' ? { effortNote: record['effortNote'] } : {}),
|
|
230
|
+
...(typeof record['modelNote'] === 'string' ? { modelNote: record['modelNote'] } : {}),
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
return out;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export function metaFor(cli: string, registry?: Record<string, CliMeta> | null): CliMeta {
|
|
237
|
+
return registry?.[cli] || CLI_META[cli] || { label: cli, models: [], efforts: [] };
|
|
202
238
|
}
|
|
203
239
|
|
|
204
240
|
export function orderRuntimeCliOptions(cliOptions: ReadonlyArray<string>): string[] {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { SettingsClient } from '../../../types';
|
|
2
|
+
import type { CliMeta } from './agent-meta';
|
|
2
3
|
|
|
3
4
|
export type RuntimeEmployeeSource = 'static' | 'db';
|
|
4
5
|
|
|
@@ -37,13 +38,17 @@ export function newRuntimeEmployeeId(): string {
|
|
|
37
38
|
return `new:${Date.now().toString(36)}:${Math.random().toString(36).slice(2, 8)}`;
|
|
38
39
|
}
|
|
39
40
|
|
|
40
|
-
export function makeDefaultRuntimeEmployee(
|
|
41
|
+
export function makeDefaultRuntimeEmployee(
|
|
42
|
+
cliOptions: ReadonlyArray<string>,
|
|
43
|
+
cliMeta?: Record<string, CliMeta> | null,
|
|
44
|
+
): RuntimeEmployeeRecord {
|
|
41
45
|
const cli = cliOptions[0] || 'claude';
|
|
46
|
+
const model = cliMeta?.[cli]?.models?.[0] || 'default';
|
|
42
47
|
return {
|
|
43
48
|
id: newRuntimeEmployeeId(),
|
|
44
49
|
name: 'New Agent',
|
|
45
50
|
cli,
|
|
46
|
-
model
|
|
51
|
+
model,
|
|
47
52
|
role: '',
|
|
48
53
|
status: 'idle',
|
|
49
54
|
source: 'db',
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { execFileSync } from 'node:child_process';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
|
|
7
|
+
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
8
|
+
const FIXTURE_DIR = path.join(ROOT, 'tests', 'fixtures', 'agy-quota');
|
|
9
|
+
const EMAIL_PLACEHOLDER = 'redacted@example.invalid';
|
|
10
|
+
const REDACTED = '[REDACTED]';
|
|
11
|
+
const REDACT_KEYS = new Set([
|
|
12
|
+
'email',
|
|
13
|
+
'account',
|
|
14
|
+
'accountid',
|
|
15
|
+
'user',
|
|
16
|
+
'id',
|
|
17
|
+
'requestid',
|
|
18
|
+
'request_id',
|
|
19
|
+
'token',
|
|
20
|
+
'accesstoken',
|
|
21
|
+
'refreshtoken',
|
|
22
|
+
'idtoken',
|
|
23
|
+
'apikey',
|
|
24
|
+
'secret',
|
|
25
|
+
'password',
|
|
26
|
+
'bearer',
|
|
27
|
+
'cookie',
|
|
28
|
+
'authorization',
|
|
29
|
+
]);
|
|
30
|
+
|
|
31
|
+
function usage() {
|
|
32
|
+
console.log(`Usage: node scripts/capture-agy-quota-fixture.mjs [--out <path>]
|
|
33
|
+
|
|
34
|
+
Capture antigravity-usage --json, redact account identifiers, and write an AGY
|
|
35
|
+
quota fixture. Review the output manually before committing.
|
|
36
|
+
|
|
37
|
+
Options:
|
|
38
|
+
--out <path> Write to a custom JSON path.
|
|
39
|
+
-h, --help Show this help.
|
|
40
|
+
`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function parseArgs(argv) {
|
|
44
|
+
const args = { out: '' };
|
|
45
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
46
|
+
const arg = argv[i];
|
|
47
|
+
if (arg === '-h' || arg === '--help') {
|
|
48
|
+
usage();
|
|
49
|
+
process.exit(0);
|
|
50
|
+
}
|
|
51
|
+
if (arg === '--out') {
|
|
52
|
+
const value = argv[i + 1];
|
|
53
|
+
if (!value) throw new Error('--out requires a path');
|
|
54
|
+
args.out = value;
|
|
55
|
+
i += 1;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
throw new Error(`unknown argument: ${arg}`);
|
|
59
|
+
}
|
|
60
|
+
return args;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function runJson() {
|
|
64
|
+
const commands = [
|
|
65
|
+
['antigravity-usage', ['--json']],
|
|
66
|
+
['npx', ['--yes', 'antigravity-usage', '--json']],
|
|
67
|
+
];
|
|
68
|
+
const errors = [];
|
|
69
|
+
for (const [binary, args] of commands) {
|
|
70
|
+
try {
|
|
71
|
+
return execFileSync(binary, args, {
|
|
72
|
+
encoding: 'utf8',
|
|
73
|
+
timeout: 15000,
|
|
74
|
+
maxBuffer: 1024 * 1024,
|
|
75
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
76
|
+
});
|
|
77
|
+
} catch (error) {
|
|
78
|
+
errors.push(`${binary}: ${error.message}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
throw new Error(`failed to run antigravity-usage JSON capture:\n${errors.join('\n')}`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function redactString(value, forceEmail = false) {
|
|
85
|
+
if (forceEmail) return EMAIL_PLACEHOLDER;
|
|
86
|
+
return value.replace(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/gi, EMAIL_PLACEHOLDER);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function redact(value, key = '') {
|
|
90
|
+
if (Array.isArray(value)) return value.map(item => redact(item));
|
|
91
|
+
if (value && typeof value === 'object') {
|
|
92
|
+
const out = {};
|
|
93
|
+
for (const [rawKey, rawValue] of Object.entries(value)) {
|
|
94
|
+
const normalized = rawKey.toLowerCase().replace(/[-_\s]/g, '');
|
|
95
|
+
if (REDACT_KEYS.has(normalized)) {
|
|
96
|
+
out[rawKey] = normalized === 'email'
|
|
97
|
+
? EMAIL_PLACEHOLDER
|
|
98
|
+
: typeof rawValue === 'string'
|
|
99
|
+
? redactString(rawValue) === rawValue ? REDACTED : EMAIL_PLACEHOLDER
|
|
100
|
+
: REDACTED;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
out[rawKey] = redact(rawValue, rawKey);
|
|
104
|
+
}
|
|
105
|
+
return out;
|
|
106
|
+
}
|
|
107
|
+
if (typeof value === 'string') {
|
|
108
|
+
return redactString(value, key.toLowerCase() === 'email');
|
|
109
|
+
}
|
|
110
|
+
return value;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function defaultOutPath() {
|
|
114
|
+
const day = new Date().toISOString().slice(0, 10);
|
|
115
|
+
return path.join(FIXTURE_DIR, `live-redacted-${day}.json`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function main() {
|
|
119
|
+
const args = parseArgs(process.argv.slice(2));
|
|
120
|
+
const raw = runJson().trim();
|
|
121
|
+
if (!raw.startsWith('{')) throw new Error('antigravity-usage output is not a JSON object');
|
|
122
|
+
const parsed = JSON.parse(raw);
|
|
123
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
124
|
+
throw new Error('antigravity-usage output must be a JSON object');
|
|
125
|
+
}
|
|
126
|
+
const redacted = redact(parsed);
|
|
127
|
+
const outPath = path.resolve(args.out || defaultOutPath());
|
|
128
|
+
fs.mkdirSync(path.dirname(outPath), { recursive: true });
|
|
129
|
+
fs.writeFileSync(outPath, `${JSON.stringify(redacted, null, 2)}\n`);
|
|
130
|
+
console.log(outPath);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
try {
|
|
134
|
+
main();
|
|
135
|
+
} catch (error) {
|
|
136
|
+
console.error((error instanceof Error ? error.message : String(error)));
|
|
137
|
+
process.exit(1);
|
|
138
|
+
}
|
|
@@ -179,7 +179,7 @@ async function main(): Promise<void> {
|
|
|
179
179
|
if (!cliRes.ok) throw new Error(`/api/cli-status HTTP ${cliRes.status}`);
|
|
180
180
|
const cliJson = (await cliRes.json()) as Record<string, unknown> | null;
|
|
181
181
|
const keys = Object.keys(cliJson ?? {});
|
|
182
|
-
const required: string[] = ['ai-e', 'claude', 'claude-e', 'codex', 'codex-app', 'copilot', 'cursor', 'kiro-code', '
|
|
182
|
+
const required: string[] = ['ai-e', 'claude', 'claude-e', 'codex', 'codex-app', 'copilot', 'cursor', 'kiro-code', 'grok', 'opencode'];
|
|
183
183
|
for (const k of required) {
|
|
184
184
|
if (!keys.includes(k)) throw new Error(`missing cli key in status: ${k}`);
|
|
185
185
|
}
|