@wjarka/cezarion 0.14.8 → 0.14.9-dev.1009
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 +131 -2
- package/dist/application-update/bin-recovery.d.ts +5 -0
- package/dist/application-update/bin-recovery.js +96 -0
- package/dist/application-update/bin-recovery.js.map +1 -0
- package/dist/application-update/discovery.d.ts +22 -0
- package/dist/application-update/discovery.js +91 -0
- package/dist/application-update/discovery.js.map +1 -0
- package/dist/application-update/helper.d.ts +57 -0
- package/dist/application-update/helper.js +374 -0
- package/dist/application-update/helper.js.map +1 -0
- package/dist/application-update/launcher.d.ts +8 -0
- package/dist/application-update/launcher.js +53 -0
- package/dist/application-update/launcher.js.map +1 -0
- package/dist/application-update/lock.d.ts +4 -0
- package/dist/application-update/lock.js +70 -0
- package/dist/application-update/lock.js.map +1 -0
- package/dist/application-update/npm-process.d.ts +17 -0
- package/dist/application-update/npm-process.js +133 -0
- package/dist/application-update/npm-process.js.map +1 -0
- package/dist/application-update/service.d.ts +69 -0
- package/dist/application-update/service.js +456 -0
- package/dist/application-update/service.js.map +1 -0
- package/dist/artifacts/cli.d.ts +1 -0
- package/dist/artifacts/cli.js +32 -0
- package/dist/artifacts/cli.js.map +1 -0
- package/dist/artifacts/lifecycle.d.ts +4 -0
- package/dist/artifacts/lifecycle.js +42 -0
- package/dist/artifacts/lifecycle.js.map +1 -0
- package/dist/artifacts/resolve.d.ts +18 -0
- package/dist/artifacts/resolve.js +102 -0
- package/dist/artifacts/resolve.js.map +1 -0
- package/dist/artifacts/store.d.ts +8 -0
- package/dist/artifacts/store.js +323 -0
- package/dist/artifacts/store.js.map +1 -0
- package/dist/automations/scheduler.d.ts +6 -0
- package/dist/automations/scheduler.js +45 -17
- package/dist/automations/scheduler.js.map +1 -1
- package/dist/automations/store.d.ts +12 -4
- package/dist/automations/store.js +199 -22
- package/dist/automations/store.js.map +1 -1
- package/dist/automations/types.d.ts +2 -0
- package/dist/automations/types.js +1 -0
- package/dist/automations/types.js.map +1 -1
- package/dist/ci-wait/mcp.d.ts +3 -0
- package/dist/ci-wait/mcp.js +14 -3
- package/dist/ci-wait/mcp.js.map +1 -1
- package/dist/contract/application-update.d.ts +32 -0
- package/dist/contract/artifacts.d.ts +83 -0
- package/dist/contract/ask-schema.d.ts +32 -0
- package/dist/contract/ask.d.ts +2 -32
- package/dist/contract/automations.d.ts +6 -0
- package/dist/contract/conversations.d.ts +165 -0
- package/dist/contract/delegation.d.ts +68 -0
- package/dist/contract/discovery.d.ts +134 -0
- package/dist/contract/events.d.ts +49 -0
- package/dist/contract/health.d.ts +12 -0
- package/dist/contract/index.d.ts +3 -0
- package/dist/contract/index.js +1654 -1454
- package/dist/contract/projects.d.ts +40 -0
- package/dist/contract/runs.d.ts +186 -0
- package/dist/contract/skills.d.ts +33 -0
- package/dist/core/agent-runner.d.ts +33 -4
- package/dist/core/agent-runner.js +5 -0
- package/dist/core/agent-runner.js.map +1 -1
- package/dist/core/claude-cli-runner.d.ts +6 -12
- package/dist/core/claude-cli-runner.js +90 -20
- package/dist/core/claude-cli-runner.js.map +1 -1
- package/dist/core/codex-app-server-runner.d.ts +2 -1
- package/dist/core/codex-app-server-runner.js +327 -92
- package/dist/core/codex-app-server-runner.js.map +1 -1
- package/dist/core/codex-app-server-transport.d.ts +13 -1
- package/dist/core/codex-app-server-transport.js +58 -17
- package/dist/core/codex-app-server-transport.js.map +1 -1
- package/dist/core/cursor-acp-runner.d.ts +6 -1
- package/dist/core/cursor-acp-runner.js +162 -26
- package/dist/core/cursor-acp-runner.js.map +1 -1
- package/dist/core/cursor-provider-error.d.ts +3 -0
- package/dist/core/cursor-provider-error.js +16 -1
- package/dist/core/cursor-provider-error.js.map +1 -1
- package/dist/core/input-submissions.d.ts +14 -0
- package/dist/core/input-submissions.js +26 -0
- package/dist/core/input-submissions.js.map +1 -0
- package/dist/core/opencode-server-runner.d.ts +4 -1
- package/dist/core/opencode-server-runner.js +156 -26
- package/dist/core/opencode-server-runner.js.map +1 -1
- package/dist/core/pi-runner.d.ts +2 -1
- package/dist/core/pi-runner.js +88 -10
- package/dist/core/pi-runner.js.map +1 -1
- package/dist/core/provider-auth.d.ts +99 -1
- package/dist/core/provider-auth.js +203 -2
- package/dist/core/provider-auth.js.map +1 -1
- package/dist/delegation/cli.d.ts +1 -0
- package/dist/delegation/cli.js +103 -7
- package/dist/delegation/cli.js.map +1 -1
- package/dist/delegation/conversations.js +13 -5
- package/dist/delegation/conversations.js.map +1 -1
- package/dist/delegation/input.d.ts +2 -1
- package/dist/delegation/input.js +6 -1
- package/dist/delegation/input.js.map +1 -1
- package/dist/delegation/policy.d.ts +3 -2
- package/dist/delegation/policy.js +3 -1
- package/dist/delegation/policy.js.map +1 -1
- package/dist/delegation/process-liveness.d.ts +66 -0
- package/dist/delegation/process-liveness.js +215 -0
- package/dist/delegation/process-liveness.js.map +1 -0
- package/dist/delegation/provision.d.ts +1 -1
- package/dist/delegation/provision.js +10 -5
- package/dist/delegation/provision.js.map +1 -1
- package/dist/delegation/questions.d.ts +19 -0
- package/dist/delegation/questions.js +45 -0
- package/dist/delegation/questions.js.map +1 -0
- package/dist/delegation/results.d.ts +1 -1
- package/dist/delegation/results.js +33 -19
- package/dist/delegation/results.js.map +1 -1
- package/dist/delegation/routes.d.ts +185 -11
- package/dist/delegation/routes.js +6 -2
- package/dist/delegation/routes.js.map +1 -1
- package/dist/delegation/service.d.ts +23 -5
- package/dist/delegation/service.js +240 -17
- package/dist/delegation/service.js.map +1 -1
- package/dist/delegation/transport.d.ts +178 -15
- package/dist/delegation/workspace.d.ts +1 -1
- package/dist/delegation/workspace.js +13 -6
- package/dist/delegation/workspace.js.map +1 -1
- package/dist/discovery/catalog.d.ts +14 -0
- package/dist/discovery/catalog.js +31 -0
- package/dist/discovery/catalog.js.map +1 -0
- package/dist/discovery/cli.d.ts +8 -0
- package/dist/discovery/cli.js +104 -0
- package/dist/discovery/cli.js.map +1 -0
- package/dist/git-worktree.d.ts +3 -1
- package/dist/git-worktree.js +26 -4
- package/dist/git-worktree.js.map +1 -1
- package/dist/index.js +93 -26
- package/dist/index.js.map +1 -1
- package/dist/open-url.d.ts +2 -0
- package/dist/open-url.js +20 -0
- package/dist/open-url.js.map +1 -0
- package/dist/release/snapshot.d.ts +3 -3
- package/dist/release/snapshot.js +6 -6
- package/dist/release/snapshot.js.map +1 -1
- package/dist/runs/agent-tmpdir.d.ts +2 -0
- package/dist/runs/agent-tmpdir.js +5 -2
- package/dist/runs/agent-tmpdir.js.map +1 -1
- package/dist/runs/client-request.d.ts +11 -0
- package/dist/runs/client-request.js +26 -0
- package/dist/runs/client-request.js.map +1 -0
- package/dist/runs/delegation-state.d.ts +17 -0
- package/dist/runs/event-history.js +6 -0
- package/dist/runs/event-history.js.map +1 -1
- package/dist/runs/retention.d.ts +7 -2
- package/dist/runs/retention.js +39 -7
- package/dist/runs/retention.js.map +1 -1
- package/dist/runs/store.d.ts +100 -6
- package/dist/runs/store.js +245 -2
- package/dist/runs/store.js.map +1 -1
- package/dist/runs/webhook.d.ts +125 -0
- package/dist/runs/webhook.js +256 -0
- package/dist/runs/webhook.js.map +1 -0
- package/dist/server/project-context.d.ts +2 -0
- package/dist/server/project-context.js +1 -0
- package/dist/server/project-context.js.map +1 -1
- package/dist/server/provider-auth-runtime.d.ts +30 -4
- package/dist/server/provider-auth-runtime.js +71 -6
- package/dist/server/provider-auth-runtime.js.map +1 -1
- package/dist/server/server.d.ts +8226 -4860
- package/dist/server/server.js +311 -15
- package/dist/server/server.js.map +1 -1
- package/dist/server-install/platforms/ubuntu-vps.d.ts +5 -1
- package/dist/server-install/platforms/ubuntu-vps.js +160 -18
- package/dist/server-install/platforms/ubuntu-vps.js.map +1 -1
- package/dist/server-install/steps.d.ts +4 -2
- package/dist/server-install/steps.js +5 -4
- package/dist/server-install/steps.js.map +1 -1
- package/dist/skills-remote.d.ts +30 -5
- package/dist/skills-remote.js +122 -32
- package/dist/skills-remote.js.map +1 -1
- package/dist/skills.js +15 -6
- package/dist/skills.js.map +1 -1
- package/dist/task-cli/cli.d.ts +38 -0
- package/dist/task-cli/cli.js +580 -0
- package/dist/task-cli/cli.js.map +1 -0
- package/dist/task-cli/discovery.d.ts +22 -0
- package/dist/task-cli/discovery.js +96 -0
- package/dist/task-cli/discovery.js.map +1 -0
- package/dist/task-cli/http.d.ts +46 -0
- package/dist/task-cli/http.js +101 -0
- package/dist/task-cli/http.js.map +1 -0
- package/dist/task-cli/projections.d.ts +40 -0
- package/dist/task-cli/projections.js +45 -0
- package/dist/task-cli/projections.js.map +1 -0
- package/dist/task-cli/watch.d.ts +78 -0
- package/dist/task-cli/watch.js +336 -0
- package/dist/task-cli/watch.js.map +1 -0
- package/dist/workflows/run.d.ts +160 -2
- package/dist/workflows/run.js +1141 -108
- package/dist/workflows/run.js.map +1 -1
- package/dist/workspace/agent-profiles.d.ts +22 -0
- package/dist/workspace/agent-profiles.js +15 -0
- package/dist/workspace/agent-profiles.js.map +1 -1
- package/dist/workspace/config.d.ts +9 -0
- package/dist/workspace/config.js +13 -1
- package/dist/workspace/config.js.map +1 -1
- package/dist/workspace/projects-cli.js +1 -1
- package/dist/workspace/projects.d.ts +24 -1
- package/dist/workspace/projects.js +14 -1
- package/dist/workspace/projects.js.map +1 -1
- package/package.json +5 -5
- package/scripts/mock-claude.mjs +64 -2
- package/scripts/mock-codex-app-server.mjs +124 -1
- package/scripts/mock-cursor-acp.mjs +54 -3
- package/scripts/mock-cursor-hang-stdin-late.mjs +35 -0
- package/scripts/mock-cursor-hang-stdin.mjs +30 -0
- package/scripts/mock-opencode-serve.mjs +102 -2
- package/scripts/mock-pi-rpc.mjs +82 -3
- package/web/dist/assets/agent-accounts-CerclGiO.js +1 -0
- package/web/dist/assets/centered-state-DH8qtCz-.js +43 -0
- package/web/dist/assets/collapsible-De2G0xqQ.js +1 -0
- package/web/dist/assets/commit-list-s6JPY3qv.js +1 -0
- package/web/dist/assets/compare-variants-BQu_t-_g.js +1 -0
- package/web/dist/assets/{diff-tRE59UNb2.js → diff-8M5HlDxq2.js} +2 -2
- package/web/dist/assets/diff-controls-B6ok0TtQ.js +1 -0
- package/web/dist/assets/{diff-stat-Cgnl_hYF.js → diff-stat-D1AODN2a.js} +1 -1
- package/web/dist/assets/{diff-view-DN1ort7Q.js → diff-view-Bs5Gh7UF.js} +2 -2
- package/web/dist/assets/dropdown-menu-7KGQMoFj.js +1 -0
- package/web/dist/assets/git-toolbar-DqbapMXr.js +1 -0
- package/web/dist/assets/github-DCkk6sBm.js +1 -0
- package/web/dist/assets/{image-preview-C2JGcBlC.js → image-preview-jzHoEyLM.js} +1 -1
- package/web/dist/assets/index-Bnva-ttR.js +7 -0
- package/web/dist/assets/index-D5NkwqY7.css +1 -0
- package/web/dist/assets/markdown-DvbymqXz.js +2 -0
- package/web/dist/assets/pill-BL6ugwXo.js +1 -0
- package/web/dist/assets/project-router-ChC5Rb-Y.js +1 -0
- package/web/dist/assets/prompt-templates-j8qlK7c-.js +15 -0
- package/web/dist/assets/repo-git-_h1NjOVt.js +1 -0
- package/web/dist/assets/{run-diff-CyG0Nciv.js → run-diff-BuATgZpx.js} +2 -2
- package/web/dist/assets/run-header-DuAWswYM.js +1 -0
- package/web/dist/assets/skills-C-fq5BrZ.js +1 -0
- package/web/dist/assets/{tab-link-BWNp3mLY.js → tab-link-BmGKj9Rt.js} +1 -1
- package/web/dist/assets/task-changes-CHa6JWOS.js +1 -0
- package/web/dist/assets/task-commits-BqCqyWm1.js +1 -0
- package/web/dist/assets/task-files-BSA0l-YP.js +2 -0
- package/web/dist/assets/task-thread-Bw_nQuTx.css +1 -0
- package/web/dist/assets/task-thread-Q7Nj33DH.js +9 -0
- package/web/dist/assets/textarea-ByZ-txS7.js +1 -0
- package/web/dist/assets/thread-loading-DHT9p5o5.js +1 -0
- package/web/dist/assets/token-metrics-k4XoovDS.js +1 -0
- package/web/dist/assets/utils-BTFBhZ55.js +64 -0
- package/web/dist/assets/workflows-HJOd3lVi.js +11 -0
- package/web/dist/assets/{zoomable-image-Z3JDnm0b.js → zoomable-image-Ba6y6Wyl.js} +1 -1
- package/web/dist/index.html +14 -14
- package/web/dist/assets/agent-accounts-BZm_2WAv.js +0 -1
- package/web/dist/assets/alert-dialog-B422RI-k.js +0 -43
- package/web/dist/assets/collapsible-Cy_Fmkrd.js +0 -1
- package/web/dist/assets/commit-list-Dcnk7TnI.js +0 -1
- package/web/dist/assets/compare-variants-Ciqwvd_f.js +0 -1
- package/web/dist/assets/diff-controls-BGrXGi7O.js +0 -1
- package/web/dist/assets/dropdown-menu-dwDGT8MM.js +0 -1
- package/web/dist/assets/git-toolbar-UiHnGvE0.js +0 -1
- package/web/dist/assets/github-D-MrkbJ7.js +0 -1
- package/web/dist/assets/ibm-plex-mono-regular-BF3vfe7_.ttf +0 -0
- package/web/dist/assets/index-BszfYvBq.js +0 -7
- package/web/dist/assets/index-CWh4pKP3.css +0 -1
- package/web/dist/assets/markdown-C_IcKVQd.js +0 -2
- package/web/dist/assets/pill-BsbO6G7y.js +0 -1
- package/web/dist/assets/project-router-DbLkll25.js +0 -1
- package/web/dist/assets/prompt-templates-BlTGJB5W.js +0 -15
- package/web/dist/assets/repo-git-Bm3s6Why.js +0 -1
- package/web/dist/assets/run-header-IFyIGCey.js +0 -1
- package/web/dist/assets/skills-C-C4DVFY.js +0 -1
- package/web/dist/assets/task-changes-D2PHtWUW.js +0 -1
- package/web/dist/assets/task-commits-N5u9U0_R.js +0 -1
- package/web/dist/assets/task-files-BS7c7CFm.js +0 -2
- package/web/dist/assets/task-thread-BQFdz1dJ.css +0 -1
- package/web/dist/assets/task-thread-DGM2dZV-.js +0 -9
- package/web/dist/assets/textarea-FjaU370i.js +0 -1
- package/web/dist/assets/thread-loading-77sJ8Yu_.js +0 -1
- package/web/dist/assets/token-metrics-Clxh03bE.js +0 -1
- package/web/dist/assets/utils-PYYcpCFZ.js +0 -64
- package/web/dist/assets/workflows-Czl0ZfXH.js +0 -11
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { realpath } from 'node:fs/promises';
|
|
3
|
+
import { basename, dirname, resolve } from 'node:path';
|
|
4
|
+
import { healthResponseSchema, projectsResponseSchema } from '../contract/index.js';
|
|
5
|
+
import { fetchJson, TaskCliError } from './http.js';
|
|
6
|
+
/**
|
|
7
|
+
* Which cockpit serves this checkout (#504, spec 2026-09-24-cez-task-cli). Zero config: probe the
|
|
8
|
+
* range `pickPort` can land on and match the registry's project roots against this repo. Never
|
|
9
|
+
* starts a server and never writes anything — a missing cockpit is an answer, not a fallback.
|
|
10
|
+
*/
|
|
11
|
+
/** The ports `cez` can bind: 4321 plus the 49 `pickPort` tries after it. */
|
|
12
|
+
export const COCKPIT_PORTS = Array.from({ length: 50 }, (_, index) => 4321 + index);
|
|
13
|
+
const PROBE_TIMEOUT_MS = 1_500;
|
|
14
|
+
function git(cwd, args) {
|
|
15
|
+
return new Promise((done) => {
|
|
16
|
+
execFile('git', ['-C', cwd, ...args], { timeout: 5_000 }, (error, stdout) => done(error ? undefined : stdout.trim()));
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
async function realpathOr(path) {
|
|
20
|
+
try {
|
|
21
|
+
return await realpath(path);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return resolve(path);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The main checkout that owns `dir`. A task worktree's common git dir is the parent repo's
|
|
29
|
+
* `.git`, so this is what maps `.ai/cezar/worktrees/<id>` back to the project that ran it.
|
|
30
|
+
* Submodules instead keep their git dir under `.git/modules/` and record `core.worktree`.
|
|
31
|
+
*/
|
|
32
|
+
export async function checkoutRoot(dir) {
|
|
33
|
+
const common = await git(dir, ['rev-parse', '--path-format=absolute', '--git-common-dir']);
|
|
34
|
+
if (common && basename(common) === '.git')
|
|
35
|
+
return realpathOr(dirname(common));
|
|
36
|
+
if (common) {
|
|
37
|
+
// Read the main worktree's config, not a linked worktree override. Git resolves a relative
|
|
38
|
+
// core.worktree against this shared git dir, even when the caller is in a task worktree.
|
|
39
|
+
const main = await git(dir, ['--git-dir', common, 'config', '--path', '--get', 'core.worktree']);
|
|
40
|
+
if (main)
|
|
41
|
+
return realpathOr(resolve(common, main));
|
|
42
|
+
}
|
|
43
|
+
const top = await git(dir, ['rev-parse', '--show-toplevel']);
|
|
44
|
+
return realpathOr(top ?? dir);
|
|
45
|
+
}
|
|
46
|
+
/** Health first (cheap, and it proves this is a cezar), then the registry with its roots. */
|
|
47
|
+
async function probe(origin, timeoutMs) {
|
|
48
|
+
try {
|
|
49
|
+
const health = await fetchJson(`${origin}/api/v1/health`, { timeoutMs });
|
|
50
|
+
if (health.status !== 200 || !healthResponseSchema.safeParse(health.data).success)
|
|
51
|
+
return undefined;
|
|
52
|
+
const registry = await fetchJson(`${origin}/api/v1/projects`, { timeoutMs });
|
|
53
|
+
const parsed = projectsResponseSchema.safeParse(registry.data);
|
|
54
|
+
if (registry.status !== 200 || !parsed.success)
|
|
55
|
+
return undefined;
|
|
56
|
+
const projects = await Promise.all(parsed.data.projects.map(async (entry) => ({ id: entry.id, root: await realpathOr(entry.root), hasWebhook: entry.webhook !== undefined })));
|
|
57
|
+
return { origin, projects, bootProject: parsed.data.bootProject };
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function cockpitFor(origin, projectId, hasWebhook) {
|
|
64
|
+
return { origin, projectId, api: `${origin}/api/v1/p/${encodeURIComponent(projectId)}`, hasWebhook };
|
|
65
|
+
}
|
|
66
|
+
export async function discoverCockpit(options) {
|
|
67
|
+
const root = await checkoutRoot(options.repoDir);
|
|
68
|
+
const timeoutMs = options.timeoutMs ?? PROBE_TIMEOUT_MS;
|
|
69
|
+
const hint = `start the cockpit in ${root} with: cez`;
|
|
70
|
+
if (options.url) {
|
|
71
|
+
let origin;
|
|
72
|
+
try {
|
|
73
|
+
origin = new URL(options.url).origin;
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
throw new TaskCliError(64, { code: 'invalid_input', error: `invalid cockpit url: ${options.url}` });
|
|
77
|
+
}
|
|
78
|
+
const found = await probe(origin, Math.max(timeoutMs, 5_000));
|
|
79
|
+
if (!found)
|
|
80
|
+
throw new TaskCliError(2, { code: 'no-cockpit', error: `no cezar cockpit answered at ${origin}`, hint });
|
|
81
|
+
// A remote cockpit's roots are its own paths, so no match is the ordinary case there.
|
|
82
|
+
const match = found.projects.find((entry) => entry.root === root);
|
|
83
|
+
const id = match?.id ?? found.bootProject;
|
|
84
|
+
return cockpitFor(origin, id, found.projects.some((entry) => entry.id === id && entry.hasWebhook));
|
|
85
|
+
}
|
|
86
|
+
const ports = options.ports ?? COCKPIT_PORTS;
|
|
87
|
+
const candidates = await Promise.all(ports.map((port) => probe(`http://127.0.0.1:${port}`, timeoutMs)));
|
|
88
|
+
// `ports` is ascending, so the first match is the lowest port serving this checkout.
|
|
89
|
+
for (const candidate of candidates) {
|
|
90
|
+
const match = candidate?.projects.find((entry) => entry.root === root);
|
|
91
|
+
if (candidate && match)
|
|
92
|
+
return cockpitFor(candidate.origin, match.id, match.hasWebhook);
|
|
93
|
+
}
|
|
94
|
+
throw new TaskCliError(2, { code: 'no-cockpit', error: `no running cockpit serves ${root}`, hint });
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/task-cli/discovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The loopback HTTP half of `cez task` (#504, spec 2026-09-24-cez-task-cli): plain `fetch`
|
|
3
|
+
* against the cockpit's own `/api/v1/p/:projectId` routes, with request deadlines.
|
|
4
|
+
*
|
|
5
|
+
* No credential is read, sent or printed: the cockpit's origin guard (#426) admits a loopback
|
|
6
|
+
* `Host` with no `Origin`, which is exactly what `fetch` sends.
|
|
7
|
+
*/
|
|
8
|
+
export declare const REQUEST_TIMEOUT_MS = 45000;
|
|
9
|
+
/** Every failure carries its exit code and the JSON body the CLI prints. */
|
|
10
|
+
export declare class TaskCliError extends Error {
|
|
11
|
+
readonly exitCode: number;
|
|
12
|
+
readonly body: Record<string, unknown>;
|
|
13
|
+
constructor(exitCode: number, body: Record<string, unknown>);
|
|
14
|
+
}
|
|
15
|
+
export interface Cockpit {
|
|
16
|
+
/** `http://127.0.0.1:<port>` — no trailing slash. */
|
|
17
|
+
origin: string;
|
|
18
|
+
projectId: string;
|
|
19
|
+
/** `${origin}/api/v1/p/${projectId}` */
|
|
20
|
+
api: string;
|
|
21
|
+
/** The project has a task webhook (#589), read from the registry discovery already fetched.
|
|
22
|
+
* Absent = unknown, which `start` treats as "do not opt in". */
|
|
23
|
+
hasWebhook?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export declare function threadUrl(cockpit: Cockpit, runId: string): string;
|
|
26
|
+
export interface HttpResult {
|
|
27
|
+
status: number;
|
|
28
|
+
data: unknown;
|
|
29
|
+
}
|
|
30
|
+
/** One request to an absolute URL. JSON bodies are parsed; anything else comes back as text. */
|
|
31
|
+
export declare function fetchJson(url: string, init?: {
|
|
32
|
+
method?: string;
|
|
33
|
+
body?: unknown;
|
|
34
|
+
timeoutMs?: number;
|
|
35
|
+
responseLimitBytes?: number;
|
|
36
|
+
}): Promise<HttpResult>;
|
|
37
|
+
/** A project-scoped route: `path` starts with `/`, relative to `/api/v1/p/:projectId`. */
|
|
38
|
+
export declare function request(cockpit: Cockpit, path: string, init?: {
|
|
39
|
+
method?: string;
|
|
40
|
+
body?: unknown;
|
|
41
|
+
timeoutMs?: number;
|
|
42
|
+
}): Promise<HttpResult>;
|
|
43
|
+
/** The cockpit said no: pass its `{ error }` through verbatim, exit 2. */
|
|
44
|
+
export declare function refuse(result: HttpResult): never;
|
|
45
|
+
/** A response the contract does not describe is a cockpit problem, not a caller problem. */
|
|
46
|
+
export declare function invalidResponse(what: string): never;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The loopback HTTP half of `cez task` (#504, spec 2026-09-24-cez-task-cli): plain `fetch`
|
|
3
|
+
* against the cockpit's own `/api/v1/p/:projectId` routes, with request deadlines.
|
|
4
|
+
*
|
|
5
|
+
* No credential is read, sent or printed: the cockpit's origin guard (#426) admits a loopback
|
|
6
|
+
* `Host` with no `Origin`, which is exactly what `fetch` sends.
|
|
7
|
+
*/
|
|
8
|
+
const RESPONSE_BYTES = 3_145_728;
|
|
9
|
+
export const REQUEST_TIMEOUT_MS = 45_000;
|
|
10
|
+
/** Every failure carries its exit code and the JSON body the CLI prints. */
|
|
11
|
+
export class TaskCliError extends Error {
|
|
12
|
+
exitCode;
|
|
13
|
+
body;
|
|
14
|
+
constructor(exitCode, body) {
|
|
15
|
+
super(typeof body.error === 'string' ? body.error : 'cez task failed');
|
|
16
|
+
this.exitCode = exitCode;
|
|
17
|
+
this.body = body;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export function threadUrl(cockpit, runId) {
|
|
21
|
+
return `${cockpit.origin}/p/${encodeURIComponent(cockpit.projectId)}/tasks/${encodeURIComponent(runId)}`;
|
|
22
|
+
}
|
|
23
|
+
/** Enforce a byte limit where the route has a bounded response, including error bodies. */
|
|
24
|
+
async function boundedText(response, limit) {
|
|
25
|
+
if (Number(response.headers.get('content-length')) > limit) {
|
|
26
|
+
await response.body?.cancel();
|
|
27
|
+
throw new Error('Response too large');
|
|
28
|
+
}
|
|
29
|
+
const reader = response.body?.getReader();
|
|
30
|
+
if (!reader)
|
|
31
|
+
return '';
|
|
32
|
+
let size = 0;
|
|
33
|
+
const chunks = [];
|
|
34
|
+
try {
|
|
35
|
+
for (;;) {
|
|
36
|
+
const next = await reader.read();
|
|
37
|
+
if (next.done)
|
|
38
|
+
break;
|
|
39
|
+
size += next.value.length;
|
|
40
|
+
if (size > limit) {
|
|
41
|
+
await reader.cancel();
|
|
42
|
+
throw new Error('Response too large');
|
|
43
|
+
}
|
|
44
|
+
chunks.push(next.value);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
finally {
|
|
48
|
+
reader.releaseLock();
|
|
49
|
+
}
|
|
50
|
+
return Buffer.concat(chunks, size).toString('utf8');
|
|
51
|
+
}
|
|
52
|
+
/** One request to an absolute URL. JSON bodies are parsed; anything else comes back as text. */
|
|
53
|
+
export async function fetchJson(url, init = {}) {
|
|
54
|
+
let response;
|
|
55
|
+
let text;
|
|
56
|
+
try {
|
|
57
|
+
response = await fetch(url, {
|
|
58
|
+
method: init.method ?? (init.body === undefined ? 'GET' : 'POST'),
|
|
59
|
+
redirect: 'error',
|
|
60
|
+
headers: init.body === undefined ? {} : { 'content-type': 'application/json' },
|
|
61
|
+
...(init.body === undefined ? {} : { body: JSON.stringify(init.body) }),
|
|
62
|
+
signal: AbortSignal.timeout(init.timeoutMs ?? REQUEST_TIMEOUT_MS),
|
|
63
|
+
});
|
|
64
|
+
text = await boundedText(response, response.ok ? (init.responseLimitBytes ?? RESPONSE_BYTES) : RESPONSE_BYTES);
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
throw new TaskCliError(2, { code: 'unavailable', error: `cockpit request failed: ${error instanceof Error ? error.message : String(error)}` });
|
|
68
|
+
}
|
|
69
|
+
const json = (response.headers.get('content-type') ?? '').includes('application/json');
|
|
70
|
+
if (!json)
|
|
71
|
+
return { status: response.status, data: text };
|
|
72
|
+
try {
|
|
73
|
+
return { status: response.status, data: JSON.parse(text) };
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
throw new TaskCliError(2, { code: 'unavailable', error: 'cockpit returned invalid JSON' });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/** A project-scoped route: `path` starts with `/`, relative to `/api/v1/p/:projectId`. */
|
|
80
|
+
export function request(cockpit, path, init = {}) {
|
|
81
|
+
// GET /runs is the existing unpaginated full history. Even 32 valid 100k-character tasks
|
|
82
|
+
// exceed the ordinary cap. Match the cockpit's full-list read rather than making list/wait
|
|
83
|
+
// fail as history grows; retain deadlines, error-body caps and every other route's cap.
|
|
84
|
+
const fullRunList = path === '/runs' && (init.method ?? (init.body === undefined ? 'GET' : 'POST')) === 'GET';
|
|
85
|
+
return fetchJson(`${cockpit.api}${path}`, {
|
|
86
|
+
...init,
|
|
87
|
+
...(fullRunList ? { responseLimitBytes: Infinity } : {}),
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/** The cockpit said no: pass its `{ error }` through verbatim, exit 2. */
|
|
91
|
+
export function refuse(result) {
|
|
92
|
+
const error = result.data && typeof result.data === 'object' && typeof result.data.error === 'string'
|
|
93
|
+
? result.data.error
|
|
94
|
+
: `cockpit answered HTTP ${result.status}`;
|
|
95
|
+
throw new TaskCliError(2, { code: 'refused', status: result.status, error });
|
|
96
|
+
}
|
|
97
|
+
/** A response the contract does not describe is a cockpit problem, not a caller problem. */
|
|
98
|
+
export function invalidResponse(what) {
|
|
99
|
+
throw new TaskCliError(2, { code: 'unavailable', error: `cockpit returned an unexpected ${what} response` });
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/task-cli/http.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ApiRun, RunStatus } from '../contract/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* The slim shapes `cez task` prints (#504). A bot polls these every few seconds, so each one
|
|
4
|
+
* carries what a caller branches on and nothing it would have to pay tokens to skip: no
|
|
5
|
+
* `steps[]`, no `workflowDef`, no reference candidates. `--full` is the escape hatch.
|
|
6
|
+
*/
|
|
7
|
+
export declare const TERMINAL_STATUSES: readonly RunStatus[];
|
|
8
|
+
export declare const SUCCESS_STATUSES: readonly RunStatus[];
|
|
9
|
+
export declare function runTitle(run: Pick<ApiRun, 'title' | 'titleSummary'>): string;
|
|
10
|
+
export declare function projectStatus(run: ApiRun, url: string, question?: unknown): Partial<{
|
|
11
|
+
id: string;
|
|
12
|
+
title: string;
|
|
13
|
+
status: "cancelled" | "done" | "failed" | "queued" | "review" | "running" | "waiting";
|
|
14
|
+
activity: "monitoring" | undefined;
|
|
15
|
+
currentStepId: string | undefined;
|
|
16
|
+
hasPendingHumanAsk: boolean;
|
|
17
|
+
question: unknown;
|
|
18
|
+
branch: string | undefined;
|
|
19
|
+
diffStat: {
|
|
20
|
+
adds: number;
|
|
21
|
+
dels: number;
|
|
22
|
+
files: number;
|
|
23
|
+
repointed?: boolean | undefined;
|
|
24
|
+
} | undefined;
|
|
25
|
+
pullRequestUrl: string | undefined;
|
|
26
|
+
error: string | undefined;
|
|
27
|
+
tokensUsed: number;
|
|
28
|
+
startedAt: string | undefined;
|
|
29
|
+
finishedAt: string | undefined;
|
|
30
|
+
url: string;
|
|
31
|
+
}>;
|
|
32
|
+
/** The record carries no `updatedAt`; the newest lifecycle stamp is the honest stand-in. */
|
|
33
|
+
export declare function projectListRow(run: ApiRun): Partial<{
|
|
34
|
+
id: string;
|
|
35
|
+
title: string;
|
|
36
|
+
status: "cancelled" | "done" | "failed" | "queued" | "review" | "running" | "waiting";
|
|
37
|
+
activity: "monitoring" | undefined;
|
|
38
|
+
hasPendingHumanAsk: boolean;
|
|
39
|
+
updatedAt: string;
|
|
40
|
+
}>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The slim shapes `cez task` prints (#504). A bot polls these every few seconds, so each one
|
|
3
|
+
* carries what a caller branches on and nothing it would have to pay tokens to skip: no
|
|
4
|
+
* `steps[]`, no `workflowDef`, no reference candidates. `--full` is the escape hatch.
|
|
5
|
+
*/
|
|
6
|
+
export const TERMINAL_STATUSES = ['done', 'review', 'failed', 'cancelled'];
|
|
7
|
+
export const SUCCESS_STATUSES = ['done', 'review'];
|
|
8
|
+
/** Keys with an undefined value are left off, so the JSON stays as small as the run is. */
|
|
9
|
+
function defined(value) {
|
|
10
|
+
return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined));
|
|
11
|
+
}
|
|
12
|
+
export function runTitle(run) {
|
|
13
|
+
return run.titleSummary ?? run.title;
|
|
14
|
+
}
|
|
15
|
+
export function projectStatus(run, url, question) {
|
|
16
|
+
return defined({
|
|
17
|
+
id: run.id,
|
|
18
|
+
title: runTitle(run),
|
|
19
|
+
status: run.status,
|
|
20
|
+
activity: run.activity,
|
|
21
|
+
currentStepId: run.currentStepId,
|
|
22
|
+
hasPendingHumanAsk: run.hasPendingHumanAsk ?? false,
|
|
23
|
+
question,
|
|
24
|
+
branch: run.branch,
|
|
25
|
+
diffStat: run.diffStat,
|
|
26
|
+
pullRequestUrl: run.pullRequestUrl,
|
|
27
|
+
error: run.error,
|
|
28
|
+
tokensUsed: run.tokensUsed,
|
|
29
|
+
startedAt: run.startedAt,
|
|
30
|
+
finishedAt: run.finishedAt,
|
|
31
|
+
url,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/** The record carries no `updatedAt`; the newest lifecycle stamp is the honest stand-in. */
|
|
35
|
+
export function projectListRow(run) {
|
|
36
|
+
return defined({
|
|
37
|
+
id: run.id,
|
|
38
|
+
title: runTitle(run),
|
|
39
|
+
status: run.status,
|
|
40
|
+
activity: run.activity,
|
|
41
|
+
hasPendingHumanAsk: run.hasPendingHumanAsk ?? false,
|
|
42
|
+
updatedAt: run.finishedAt ?? run.startedAt ?? run.createdAt,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=projections.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projections.js","sourceRoot":"","sources":["../../src/task-cli/projections.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAyB,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;AACjG,MAAM,CAAC,MAAM,gBAAgB,GAAyB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAEzE,2FAA2F;AAC3F,SAAS,OAAO,CAAoC,KAAQ;IAC1D,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CAAe,CAAC;AAC5G,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,GAA2C;IAClE,OAAO,GAAG,CAAC,YAAY,IAAI,GAAG,CAAC,KAAK,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAW,EAAE,GAAW,EAAE,QAAkB;IACxE,OAAO,OAAO,CAAC;QACb,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC;QACpB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,aAAa,EAAE,GAAG,CAAC,aAAa;QAChC,kBAAkB,EAAE,GAAG,CAAC,kBAAkB,IAAI,KAAK;QACnD,QAAQ;QACR,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,cAAc,EAAE,GAAG,CAAC,cAAc;QAClC,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,GAAG;KACJ,CAAC,CAAC;AACL,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,OAAO,OAAO,CAAC;QACb,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC;QACpB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,kBAAkB,EAAE,GAAG,CAAC,kBAAkB,IAAI,KAAK;QACnD,SAAS,EAAE,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,SAAS;KAC5D,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { type RunHistoryEvent, type RunStatus } from '../contract/index.js';
|
|
2
|
+
import { type Cockpit } from './http.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Watching a task from a terminal (#504, spec 2026-09-24-cez-task-cli). Every loop here ends —
|
|
5
|
+
* on a terminal status or at the caller's deadline — because a bot's tool call that never
|
|
6
|
+
* returns is the failure this command family exists to prevent.
|
|
7
|
+
*/
|
|
8
|
+
export declare const DEFAULT_POLL_MS = 1500;
|
|
9
|
+
export type WaitMode = 'any' | 'all';
|
|
10
|
+
export type WaitUntil = 'settled' | 'attention';
|
|
11
|
+
export interface WaitEntry {
|
|
12
|
+
id: string;
|
|
13
|
+
/** `unknown`: the deadline passed before any poll answered. */
|
|
14
|
+
status: RunStatus | 'missing' | 'unknown';
|
|
15
|
+
activity?: string;
|
|
16
|
+
hasPendingHumanAsk?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface WaitResult {
|
|
19
|
+
exitCode: number;
|
|
20
|
+
runs: WaitEntry[];
|
|
21
|
+
timedOut: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Grace for the millisecond race between a budget-bounded poll's abort and the
|
|
25
|
+
* deadline check (#538): `AbortSignal.timeout(budget)` can fire while
|
|
26
|
+
* `Date.now()` still reads just under the deadline, turning a timeout into an
|
|
27
|
+
* `unavailable` error (exit 2 instead of 3). A poll whose own abort consumed
|
|
28
|
+
* (almost) all of its budget failed *at* the deadline, so it answers "timed
|
|
29
|
+
* out". The grace never applies to other errors: a genuine failure stays
|
|
30
|
+
* `unavailable` even when it lands inside the grace window.
|
|
31
|
+
*/
|
|
32
|
+
export declare const TIMEOUT_GRACE_MS = 250;
|
|
33
|
+
export declare function pollHitDeadline(startedAt: number, budgetMs: number, now?: number): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* True when the wrapped cockpit error came from the poll's own abort (its
|
|
36
|
+
* budget running out) rather than a fast failure such as a refused
|
|
37
|
+
* connection. `fetchJson` folds every fetch failure into `unavailable`, so the
|
|
38
|
+
* abort surfaces only through the original message it preserves (`TimeoutError:
|
|
39
|
+
* The operation was aborted due to timeout`).
|
|
40
|
+
*/
|
|
41
|
+
export declare function abortedPoll(error: unknown): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Polls `GET /runs`: one call covers any number of runs and holds no socket open. Each poll is
|
|
44
|
+
* bounded by what is left of the deadline, so a slow cockpit answers "timed out" on time rather
|
|
45
|
+
* than holding the caller for a full request timeout.
|
|
46
|
+
*/
|
|
47
|
+
export declare function waitForRuns(cockpit: Cockpit, ids: string[], options: {
|
|
48
|
+
mode: WaitMode;
|
|
49
|
+
until: WaitUntil;
|
|
50
|
+
timeoutMs: number;
|
|
51
|
+
pollMs?: number;
|
|
52
|
+
}): Promise<WaitResult>;
|
|
53
|
+
/** One printable line per event the log keeps, or undefined for the rest. */
|
|
54
|
+
export declare function logLine(event: RunHistoryEvent): Record<string, unknown> | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* `log`, read from the run's SSE stream, which replays every event after `afterSeq` and then
|
|
57
|
+
* streams live. The route subscribes to live `run` updates BEFORE it replays, so a `run` frame
|
|
58
|
+
* says nothing about where the replay is; the only reliable boundary is a `seq`. So:
|
|
59
|
+
*
|
|
60
|
+
* - the replay ends at `asOfSeq`, the event file's high-water mark read from `GET /history` just
|
|
61
|
+
* before connecting — everything up to it is the tail, bounded to `maxChars`, and without
|
|
62
|
+
* `follow` the command ends there;
|
|
63
|
+
* - with `follow`, a terminal status ends the command only once the stream has caught up with a
|
|
64
|
+
* SECOND high-water read taken after that status arrived, so events the engine wrote just
|
|
65
|
+
* before finishing are not dropped when the status frame overtakes them (exit 0/1, final line
|
|
66
|
+
* is the status).
|
|
67
|
+
*
|
|
68
|
+
* One `deadline` bounds every request, the history reads included (exit 3). Deduped by `seq`.
|
|
69
|
+
* The stream rather than `GET /history` pages: a history page starts at its first transcript
|
|
70
|
+
* item, so it drops lifecycle events such as the opening `step-start`.
|
|
71
|
+
*/
|
|
72
|
+
export declare function readLog(cockpit: Cockpit, id: string, options: {
|
|
73
|
+
afterSeq: number;
|
|
74
|
+
maxChars: number;
|
|
75
|
+
follow: boolean;
|
|
76
|
+
deadline: number;
|
|
77
|
+
print: (line: string) => void;
|
|
78
|
+
}): Promise<number>;
|