aicodeman 1.45.0 → 1.47.0
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 +26 -6
- package/dist/agent-codex-identity.d.ts +26 -0
- package/dist/agent-codex-identity.d.ts.map +1 -0
- package/dist/agent-codex-identity.js +253 -0
- package/dist/agent-codex-identity.js.map +1 -0
- package/dist/agent-inspection.d.ts +32 -0
- package/dist/agent-inspection.d.ts.map +1 -0
- package/dist/agent-inspection.js +196 -0
- package/dist/agent-inspection.js.map +1 -0
- package/dist/agent-staging.d.ts +130 -0
- package/dist/agent-staging.d.ts.map +1 -0
- package/dist/agent-staging.js +312 -0
- package/dist/agent-staging.js.map +1 -0
- package/dist/cli-agent.d.ts +31 -2
- package/dist/cli-agent.d.ts.map +1 -1
- package/dist/cli-agent.js +279 -34
- package/dist/cli-agent.js.map +1 -1
- package/dist/cli-history.d.ts +20 -0
- package/dist/cli-history.d.ts.map +1 -0
- package/dist/cli-history.js +61 -0
- package/dist/cli-history.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +6 -1
- package/dist/cli.js.map +1 -1
- package/dist/codex-rollout-format.d.ts +66 -0
- package/dist/codex-rollout-format.d.ts.map +1 -0
- package/dist/codex-rollout-format.js +111 -0
- package/dist/codex-rollout-format.js.map +1 -0
- package/dist/codex-transcript.d.ts +3 -0
- package/dist/codex-transcript.d.ts.map +1 -1
- package/dist/codex-transcript.js +13 -41
- package/dist/codex-transcript.js.map +1 -1
- package/dist/config/cli-registry/schema.d.ts +12 -7
- package/dist/config/cli-registry/schema.d.ts.map +1 -1
- package/dist/config/cli-registry/schema.js +26 -0
- package/dist/config/cli-registry/schema.js.map +1 -1
- package/dist/config/cli-registry/stock.d.ts.map +1 -1
- package/dist/config/cli-registry/stock.js +40 -1
- package/dist/config/cli-registry/stock.js.map +1 -1
- package/dist/config/cli-registry/types.d.ts +57 -0
- package/dist/config/cli-registry/types.d.ts.map +1 -1
- package/dist/config/server-timing.d.ts +6 -0
- package/dist/config/server-timing.d.ts.map +1 -1
- package/dist/config/server-timing.js +9 -0
- package/dist/config/server-timing.js.map +1 -1
- package/dist/daemon-control.d.ts +1 -0
- package/dist/daemon-control.d.ts.map +1 -1
- package/dist/daemon-control.js +2 -0
- package/dist/daemon-control.js.map +1 -1
- package/dist/deepseek-transcript.d.ts +9 -7
- package/dist/deepseek-transcript.d.ts.map +1 -1
- package/dist/deepseek-transcript.js +9 -7
- package/dist/deepseek-transcript.js.map +1 -1
- package/dist/docker-hosts.d.ts +8 -0
- package/dist/docker-hosts.d.ts.map +1 -1
- package/dist/docker-hosts.js +29 -0
- package/dist/docker-hosts.js.map +1 -1
- package/dist/git-fetch-scheduler.d.ts +124 -0
- package/dist/git-fetch-scheduler.d.ts.map +1 -0
- package/dist/git-fetch-scheduler.js +249 -0
- package/dist/git-fetch-scheduler.js.map +1 -0
- package/dist/git-fetch.d.ts +241 -0
- package/dist/git-fetch.d.ts.map +1 -0
- package/dist/git-fetch.js +392 -0
- package/dist/git-fetch.js.map +1 -0
- package/dist/git-workspace-status.d.ts +36 -1
- package/dist/git-workspace-status.d.ts.map +1 -1
- package/dist/git-workspace-status.js +42 -5
- package/dist/git-workspace-status.js.map +1 -1
- package/dist/hooks-config.d.ts +14 -2
- package/dist/hooks-config.d.ts.map +1 -1
- package/dist/hooks-config.js +39 -3
- package/dist/hooks-config.js.map +1 -1
- package/dist/local-history.d.ts +71 -0
- package/dist/local-history.d.ts.map +1 -0
- package/dist/local-history.js +750 -0
- package/dist/local-history.js.map +1 -0
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +2 -2
- package/dist/mcp-server.js.map +1 -1
- package/dist/mux-interface.d.ts +5 -2
- package/dist/mux-interface.d.ts.map +1 -1
- package/dist/prompt-cache-keepwarm.d.ts.map +1 -1
- package/dist/prompt-cache-keepwarm.js +5 -3
- package/dist/prompt-cache-keepwarm.js.map +1 -1
- package/dist/ralph-fix-plan-watcher.d.ts +13 -1
- package/dist/ralph-fix-plan-watcher.d.ts.map +1 -1
- package/dist/ralph-fix-plan-watcher.js +21 -3
- package/dist/ralph-fix-plan-watcher.js.map +1 -1
- package/dist/ralph-tracker.d.ts +6 -0
- package/dist/ralph-tracker.d.ts.map +1 -1
- package/dist/ralph-tracker.js +8 -0
- package/dist/ralph-tracker.js.map +1 -1
- package/dist/session.d.ts +113 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +341 -13
- package/dist/session.js.map +1 -1
- package/dist/terminal-input-classifier.d.ts +8 -0
- package/dist/terminal-input-classifier.d.ts.map +1 -0
- package/dist/terminal-input-classifier.js +60 -0
- package/dist/terminal-input-classifier.js.map +1 -0
- package/dist/tmux-manager.d.ts +23 -1
- package/dist/tmux-manager.d.ts.map +1 -1
- package/dist/tmux-manager.js +54 -6
- package/dist/tmux-manager.js.map +1 -1
- package/dist/types/session.d.ts +15 -0
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types/session.js.map +1 -1
- package/dist/web/network-auth-policy.d.ts +13 -3
- package/dist/web/network-auth-policy.d.ts.map +1 -1
- package/dist/web/network-auth-policy.js +15 -3
- package/dist/web/network-auth-policy.js.map +1 -1
- package/dist/web/ports/infra-port.d.ts +2 -0
- package/dist/web/ports/infra-port.d.ts.map +1 -1
- package/dist/web/public/admin-ui.js.gz +0 -0
- package/dist/web/public/api-client.c9b1cddc.js.gz +0 -0
- package/dist/web/public/app.fe8a6b4c.js +43 -0
- package/dist/web/public/app.fe8a6b4c.js.br +0 -0
- package/dist/web/public/app.fe8a6b4c.js.gz +0 -0
- package/dist/web/public/approvals-ui.js.gz +0 -0
- package/dist/web/public/{constants.0b3cdde9.js → constants.affcdde6.js} +611 -12
- package/dist/web/public/constants.affcdde6.js.br +0 -0
- package/dist/web/public/constants.affcdde6.js.gz +0 -0
- package/dist/web/public/cron-ui.js.gz +0 -0
- package/dist/web/public/entrance-animations.js.gz +0 -0
- package/dist/web/public/git-status-ui.js +88 -5
- package/dist/web/public/git-status-ui.js.br +0 -0
- package/dist/web/public/git-status-ui.js.gz +0 -0
- package/dist/web/public/header-divider.eb2d2463.js.gz +0 -0
- package/dist/web/public/home-sessions.js.gz +0 -0
- package/dist/web/public/host-wake-ui.js.gz +0 -0
- package/dist/web/public/i18n.a618ef4e.js +2 -0
- package/dist/web/public/i18n.a618ef4e.js.br +0 -0
- package/dist/web/public/i18n.a618ef4e.js.gz +0 -0
- package/dist/web/public/{image-input.941386e7.js → image-input.a5d0f8f3.js} +18 -9
- package/dist/web/public/image-input.a5d0f8f3.js.br +0 -0
- package/dist/web/public/image-input.a5d0f8f3.js.gz +0 -0
- package/dist/web/public/index.html +110 -19
- package/dist/web/public/index.html.br +0 -0
- package/dist/web/public/index.html.gz +0 -0
- package/dist/web/public/input-cjk.8bc46081.js.gz +0 -0
- package/dist/web/public/{keyboard-accessory.4e8b20ac.js → keyboard-accessory.ff64fafc.js} +5 -1
- package/dist/web/public/keyboard-accessory.ff64fafc.js.br +0 -0
- package/dist/web/public/keyboard-accessory.ff64fafc.js.gz +0 -0
- package/dist/web/public/{mobile-handlers.1c0cbcd8.js → mobile-handlers.f7c3f692.js} +22 -0
- package/dist/web/public/mobile-handlers.f7c3f692.js.br +0 -0
- package/dist/web/public/mobile-handlers.f7c3f692.js.gz +0 -0
- package/dist/web/public/mobile-ime-preview.2dbaf262.js.gz +0 -0
- package/dist/web/public/mobile-overview.js.gz +0 -0
- package/dist/web/public/mobile.1bbd2d67.css +1 -0
- package/dist/web/public/mobile.1bbd2d67.css.br +0 -0
- package/dist/web/public/mobile.1bbd2d67.css.gz +0 -0
- package/dist/web/public/notification-manager.feb82c04.js.gz +0 -0
- package/dist/web/public/orchestrator-panel.js.gz +0 -0
- package/dist/web/public/{panels-ui.78c3defb.js → panels-ui.4a56ee63.js} +1 -1
- package/dist/web/public/panels-ui.4a56ee63.js.br +0 -0
- package/dist/web/public/panels-ui.4a56ee63.js.gz +0 -0
- package/dist/web/public/ralph-panel.b350e2ef.js.gz +0 -0
- package/dist/web/public/ralph-wizard.b6c0dd19.js.gz +0 -0
- package/dist/web/public/readmymind-ui.js.gz +0 -0
- package/dist/web/public/reboot-restore-ui.js.gz +0 -0
- package/dist/web/public/respawn-ui.d7adcf6a.js.gz +0 -0
- package/dist/web/public/sanitize-html.e7147e76.js.gz +0 -0
- package/dist/web/public/session-lineage.js.gz +0 -0
- package/dist/web/public/{session-ui.ea6b1994.js → session-ui.426fb671.js} +8 -8
- package/dist/web/public/session-ui.426fb671.js.br +0 -0
- package/dist/web/public/session-ui.426fb671.js.gz +0 -0
- package/dist/web/public/{settings-ui.085dd202.js → settings-ui.a191154e.js} +11 -11
- package/dist/web/public/settings-ui.a191154e.js.br +0 -0
- package/dist/web/public/settings-ui.a191154e.js.gz +0 -0
- package/dist/web/public/spreadsheet-preview-worker.js.gz +0 -0
- package/dist/web/public/spreadsheet-preview.75c751de.js.gz +0 -0
- package/dist/web/public/spreadsheet-xlsx-core.js.gz +0 -0
- package/dist/web/public/styles.4f0c67a0.css +1 -0
- package/dist/web/public/styles.4f0c67a0.css.br +0 -0
- package/dist/web/public/styles.4f0c67a0.css.gz +0 -0
- package/dist/web/public/subagent-windows.07277a58.js.gz +0 -0
- package/dist/web/public/sw.js +2 -2
- package/dist/web/public/sw.js.br +0 -0
- package/dist/web/public/sw.js.gz +0 -0
- package/dist/web/public/tab-layout-browser.2d6189f7.js.gz +0 -0
- package/dist/web/public/{tab-rail-resize.7157e0bd.js → tab-rail-resize.b5cdceaf.js} +1 -1
- package/dist/web/public/tab-rail-resize.b5cdceaf.js.br +0 -0
- package/dist/web/public/tab-rail-resize.b5cdceaf.js.gz +0 -0
- package/dist/web/public/terminal-keycode229-recovery.98843069.js +1 -0
- package/dist/web/public/terminal-keycode229-recovery.98843069.js.br +0 -0
- package/dist/web/public/terminal-keycode229-recovery.98843069.js.gz +0 -0
- package/dist/web/public/terminal-split.js.gz +0 -0
- package/dist/web/public/terminal-tile.js +10 -6
- package/dist/web/public/terminal-tile.js.br +0 -0
- package/dist/web/public/terminal-tile.js.gz +0 -0
- package/dist/web/public/terminal-ui.7e787829.js +4 -0
- package/dist/web/public/terminal-ui.7e787829.js.br +0 -0
- package/dist/web/public/terminal-ui.7e787829.js.gz +0 -0
- package/dist/web/public/tile-grid.js.gz +0 -0
- package/dist/web/public/ultracode-panel.js.gz +0 -0
- package/dist/web/public/ultracode-windows.js.gz +0 -0
- package/dist/web/public/vendor/dompurify.min.js.gz +0 -0
- package/dist/web/public/vendor/exceljs.min.js.gz +0 -0
- package/dist/web/public/vendor/fflate.min.js.gz +0 -0
- package/dist/web/public/vendor/marked.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-serialize.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
- package/dist/web/public/vendor/{xterm-predictive-echo.ae5e3d5d.js → xterm-predictive-echo.276b11d9.js} +1 -1
- package/dist/web/public/vendor/xterm-predictive-echo.276b11d9.js.br +0 -0
- package/dist/web/public/vendor/xterm-predictive-echo.276b11d9.js.gz +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.1be42307.js +5 -0
- package/dist/web/public/vendor/xterm-zerolag-input.1be42307.js.br +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.1be42307.js.gz +0 -0
- package/dist/web/public/vendor/xterm.css.gz +0 -0
- package/dist/web/public/vendor/xterm.min.js.gz +0 -0
- package/dist/web/public/voice-input.2342c37b.js.gz +0 -0
- package/dist/web/public/voice-pcm-worklet.js.gz +0 -0
- package/dist/web/public/webview-tabs.js.gz +0 -0
- package/dist/web/public/whats-new.json +8 -9
- package/dist/web/request-body-parser.d.ts +23 -0
- package/dist/web/request-body-parser.d.ts.map +1 -0
- package/dist/web/request-body-parser.js +57 -0
- package/dist/web/request-body-parser.js.map +1 -0
- package/dist/web/routes/agent-session-routes.d.ts +20 -0
- package/dist/web/routes/agent-session-routes.d.ts.map +1 -0
- package/dist/web/routes/agent-session-routes.js +160 -0
- package/dist/web/routes/agent-session-routes.js.map +1 -0
- package/dist/web/routes/case-routes.d.ts.map +1 -1
- package/dist/web/routes/case-routes.js +32 -26
- package/dist/web/routes/case-routes.js.map +1 -1
- package/dist/web/routes/config-backup-routes.js +2 -2
- package/dist/web/routes/config-backup-routes.js.map +1 -1
- package/dist/web/routes/file-routes.d.ts +5 -0
- package/dist/web/routes/file-routes.d.ts.map +1 -1
- package/dist/web/routes/file-routes.js +5 -1
- package/dist/web/routes/file-routes.js.map +1 -1
- package/dist/web/routes/git-status-routes.d.ts +21 -7
- package/dist/web/routes/git-status-routes.d.ts.map +1 -1
- package/dist/web/routes/git-status-routes.js +78 -12
- package/dist/web/routes/git-status-routes.js.map +1 -1
- package/dist/web/routes/index.d.ts +1 -0
- package/dist/web/routes/index.d.ts.map +1 -1
- package/dist/web/routes/index.js +1 -0
- package/dist/web/routes/index.js.map +1 -1
- package/dist/web/routes/ralph-routes.d.ts.map +1 -1
- package/dist/web/routes/ralph-routes.js +52 -18
- package/dist/web/routes/ralph-routes.js.map +1 -1
- package/dist/web/routes/session-routes.d.ts.map +1 -1
- package/dist/web/routes/session-routes.js +101 -28
- package/dist/web/routes/session-routes.js.map +1 -1
- package/dist/web/routes/system-routes.d.ts.map +1 -1
- package/dist/web/routes/system-routes.js +87 -59
- package/dist/web/routes/system-routes.js.map +1 -1
- package/dist/web/routes/ws-routes.d.ts +5 -0
- package/dist/web/routes/ws-routes.d.ts.map +1 -1
- package/dist/web/routes/ws-routes.js +84 -47
- package/dist/web/routes/ws-routes.js.map +1 -1
- package/dist/web/schemas.d.ts +30 -7
- package/dist/web/schemas.d.ts.map +1 -1
- package/dist/web/schemas.js +40 -1
- package/dist/web/schemas.js.map +1 -1
- package/dist/web/server.d.ts +5 -2
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +102 -18
- package/dist/web/server.js.map +1 -1
- package/dist/web/settings-writer.d.ts +47 -0
- package/dist/web/settings-writer.d.ts.map +1 -0
- package/dist/web/settings-writer.js +110 -0
- package/dist/web/settings-writer.js.map +1 -0
- package/package.json +1 -1
- package/skills/codeman/SKILL.md +25 -6
- package/skills/codeman/reference/history.md +84 -0
- package/skills/codeman/reference/inspection-and-staging.md +152 -0
- package/skills/codeman/reference/messaging.md +1 -1
- package/skills/codeman/reference/verbs.md +18 -3
- package/dist/web/public/app.42d0abae.js +0 -43
- package/dist/web/public/app.42d0abae.js.br +0 -0
- package/dist/web/public/app.42d0abae.js.gz +0 -0
- package/dist/web/public/constants.0b3cdde9.js.br +0 -0
- package/dist/web/public/constants.0b3cdde9.js.gz +0 -0
- package/dist/web/public/i18n.1e68220d.js +0 -2
- package/dist/web/public/i18n.1e68220d.js.br +0 -0
- package/dist/web/public/i18n.1e68220d.js.gz +0 -0
- package/dist/web/public/image-input.941386e7.js.br +0 -0
- package/dist/web/public/image-input.941386e7.js.gz +0 -0
- package/dist/web/public/keyboard-accessory.4e8b20ac.js.br +0 -0
- package/dist/web/public/keyboard-accessory.4e8b20ac.js.gz +0 -0
- package/dist/web/public/mobile-handlers.1c0cbcd8.js.br +0 -0
- package/dist/web/public/mobile-handlers.1c0cbcd8.js.gz +0 -0
- package/dist/web/public/mobile.12fb18de.css +0 -1
- package/dist/web/public/mobile.12fb18de.css.br +0 -0
- package/dist/web/public/mobile.12fb18de.css.gz +0 -0
- package/dist/web/public/panels-ui.78c3defb.js.br +0 -0
- package/dist/web/public/panels-ui.78c3defb.js.gz +0 -0
- package/dist/web/public/session-ui.ea6b1994.js.br +0 -0
- package/dist/web/public/session-ui.ea6b1994.js.gz +0 -0
- package/dist/web/public/settings-ui.085dd202.js.br +0 -0
- package/dist/web/public/settings-ui.085dd202.js.gz +0 -0
- package/dist/web/public/styles.3b59b41d.css +0 -1
- package/dist/web/public/styles.3b59b41d.css.br +0 -0
- package/dist/web/public/styles.3b59b41d.css.gz +0 -0
- package/dist/web/public/tab-rail-resize.7157e0bd.js.br +0 -0
- package/dist/web/public/tab-rail-resize.7157e0bd.js.gz +0 -0
- package/dist/web/public/terminal-keycode229-recovery.af09f99a.js +0 -1
- package/dist/web/public/terminal-keycode229-recovery.af09f99a.js.br +0 -0
- package/dist/web/public/terminal-keycode229-recovery.af09f99a.js.gz +0 -0
- package/dist/web/public/terminal-ui.fb2a27f5.js +0 -2
- package/dist/web/public/terminal-ui.fb2a27f5.js.br +0 -0
- package/dist/web/public/terminal-ui.fb2a27f5.js.gz +0 -0
- package/dist/web/public/vendor/xterm-predictive-echo.ae5e3d5d.js.br +0 -0
- package/dist/web/public/vendor/xterm-predictive-echo.ae5e3d5d.js.gz +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.0b69623c.js +0 -4
- package/dist/web/public/vendor/xterm-zerolag-input.0b69623c.js.br +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.0b69623c.js.gz +0 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The writer of the server's `settings.json` (`SETTINGS_PATH`).
|
|
3
|
+
*
|
|
4
|
+
* Every read-modify-write of that file goes through `mutateSettingsFile()`, the same shape as
|
|
5
|
+
* `mutateRegistryFile()` (config/cli-registry/registry-writer.ts). The one direct writer is
|
|
6
|
+
* config-backup restore (`restoreConfigBackup()`, as for `clis.json`): it must work on a file that
|
|
7
|
+
* does not parse, which this writer refuses.
|
|
8
|
+
*
|
|
9
|
+
* - **Serialized.** Mutations run one at a time on a single promise chain, each one reading,
|
|
10
|
+
* changing and writing before the next starts. The writers used to run unserialized with a
|
|
11
|
+
* plain truncate-then-write `fs.writeFile`, and quick-start did not even await its
|
|
12
|
+
* `lastUsedCase` write, so a quick-start followed by a settings save could tear the file (one
|
|
13
|
+
* write's bytes over the tail of a longer one) or drop the other writer's key.
|
|
14
|
+
* - **Atomic.** Each write goes to its own temp file beside the target and is renamed over it,
|
|
15
|
+
* so a reader never sees a half-written file.
|
|
16
|
+
* - **Refuses a file it must not trust.** Only a missing (or empty) file starts from `{}`. A file
|
|
17
|
+
* that cannot be read or does not parse is left alone and the write throws
|
|
18
|
+
* `SettingsWriteRefusedError`: the writers used to read such a file as `{}` and write back only
|
|
19
|
+
* their own keys, which erased every other setting.
|
|
20
|
+
*/
|
|
21
|
+
import { type ApiResponse } from '../types.js';
|
|
22
|
+
export type SettingsFile = Record<string, unknown>;
|
|
23
|
+
/** A write refused because the existing `settings.json` must not be overwritten. The message is user-facing. */
|
|
24
|
+
export declare class SettingsWriteRefusedError extends Error {
|
|
25
|
+
constructor(message: string);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Run one change to `settings.json`. `fn` receives the current settings and returns the settings
|
|
29
|
+
* to write, or `undefined` to write nothing. Resolves with the settings before and after the
|
|
30
|
+
* change (`after` is `undefined` when nothing was written). A refused or failed mutation rejects
|
|
31
|
+
* its own caller only; the chain keeps going.
|
|
32
|
+
*/
|
|
33
|
+
export declare function mutateSettingsFile(fn: (current: SettingsFile) => SettingsFile | undefined): Promise<{
|
|
34
|
+
before: SettingsFile;
|
|
35
|
+
after: SettingsFile | undefined;
|
|
36
|
+
}>;
|
|
37
|
+
/**
|
|
38
|
+
* Rejects with `SettingsWriteRefusedError` when `mutateSettingsFile()` would refuse a write right
|
|
39
|
+
* now: the writer's own read-for-write rule, run on its own. For a route that does something it
|
|
40
|
+
* cannot take back (case rename ends sessions) before its settings write. A check only, outside
|
|
41
|
+
* the chain (writes are atomic, so it never reads a half-written file); the file can still change
|
|
42
|
+
* before the write.
|
|
43
|
+
*/
|
|
44
|
+
export declare function assertSettingsWritable(): Promise<void>;
|
|
45
|
+
/** A refused write answers 409 CONFLICT with the fix; any other failure stays OPERATION_FAILED. */
|
|
46
|
+
export declare function settingsWriteErrorResponse(err: unknown): ApiResponse<never>;
|
|
47
|
+
//# sourceMappingURL=settings-writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings-writer.d.ts","sourceRoot":"","sources":["../../src/web/settings-writer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAKH,OAAO,EAAsD,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAGnG,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEnD,gHAAgH;AAChH,qBAAa,yBAA0B,SAAQ,KAAK;gBACtC,OAAO,EAAE,MAAM;CAI5B;AA6CD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,YAAY,GAAG,SAAS,GACtD,OAAO,CAAC;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,YAAY,GAAG,SAAS,CAAA;CAAE,CAAC,CAYpE;AAED;;;;;;GAMG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC,CAE5D;AAED,mGAAmG;AACnG,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,CAG3E"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The writer of the server's `settings.json` (`SETTINGS_PATH`).
|
|
3
|
+
*
|
|
4
|
+
* Every read-modify-write of that file goes through `mutateSettingsFile()`, the same shape as
|
|
5
|
+
* `mutateRegistryFile()` (config/cli-registry/registry-writer.ts). The one direct writer is
|
|
6
|
+
* config-backup restore (`restoreConfigBackup()`, as for `clis.json`): it must work on a file that
|
|
7
|
+
* does not parse, which this writer refuses.
|
|
8
|
+
*
|
|
9
|
+
* - **Serialized.** Mutations run one at a time on a single promise chain, each one reading,
|
|
10
|
+
* changing and writing before the next starts. The writers used to run unserialized with a
|
|
11
|
+
* plain truncate-then-write `fs.writeFile`, and quick-start did not even await its
|
|
12
|
+
* `lastUsedCase` write, so a quick-start followed by a settings save could tear the file (one
|
|
13
|
+
* write's bytes over the tail of a longer one) or drop the other writer's key.
|
|
14
|
+
* - **Atomic.** Each write goes to its own temp file beside the target and is renamed over it,
|
|
15
|
+
* so a reader never sees a half-written file.
|
|
16
|
+
* - **Refuses a file it must not trust.** Only a missing (or empty) file starts from `{}`. A file
|
|
17
|
+
* that cannot be read or does not parse is left alone and the write throws
|
|
18
|
+
* `SettingsWriteRefusedError`: the writers used to read such a file as `{}` and write back only
|
|
19
|
+
* their own keys, which erased every other setting.
|
|
20
|
+
*/
|
|
21
|
+
import { randomUUID } from 'node:crypto';
|
|
22
|
+
import fs from 'node:fs/promises';
|
|
23
|
+
import { dirname } from 'node:path';
|
|
24
|
+
import { ApiErrorCode, createErrorResponse, getErrorMessage } from '../types.js';
|
|
25
|
+
import { SETTINGS_PATH } from './route-helpers.js';
|
|
26
|
+
/** A write refused because the existing `settings.json` must not be overwritten. The message is user-facing. */
|
|
27
|
+
export class SettingsWriteRefusedError extends Error {
|
|
28
|
+
constructor(message) {
|
|
29
|
+
super(message);
|
|
30
|
+
this.name = 'SettingsWriteRefusedError';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async function readSettingsForWrite(path) {
|
|
34
|
+
let raw;
|
|
35
|
+
try {
|
|
36
|
+
raw = await fs.readFile(path, 'utf-8');
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
if (err.code === 'ENOENT')
|
|
40
|
+
return {};
|
|
41
|
+
throw new SettingsWriteRefusedError(`Cannot read ${path} (${err.message}), so this change was not saved.`);
|
|
42
|
+
}
|
|
43
|
+
// An empty file holds no settings to lose.
|
|
44
|
+
if (raw.trim() === '')
|
|
45
|
+
return {};
|
|
46
|
+
let parsed;
|
|
47
|
+
try {
|
|
48
|
+
parsed = JSON.parse(raw);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
parsed = undefined;
|
|
52
|
+
}
|
|
53
|
+
// The parser's own message is not repeated: it can quote the file, which may hold an API key.
|
|
54
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
55
|
+
throw new SettingsWriteRefusedError(`${path} is not a valid JSON object, so this change was not saved (saving would have replaced every other setting in it). Fix or delete the file, or restore it from a config backup, then try again.`);
|
|
56
|
+
}
|
|
57
|
+
return parsed;
|
|
58
|
+
}
|
|
59
|
+
async function writeSettingsFile(path, settings) {
|
|
60
|
+
// Through a symlink, as the plain writeFile this replaces did: the rename lands on the real file.
|
|
61
|
+
const target = await fs.realpath(path).catch(() => path);
|
|
62
|
+
await fs.mkdir(dirname(target), { recursive: true });
|
|
63
|
+
const tmp = `${target}.${process.pid}.${randomUUID()}.tmp`;
|
|
64
|
+
try {
|
|
65
|
+
await fs.writeFile(tmp, JSON.stringify(settings, null, 2), { mode: 0o600 });
|
|
66
|
+
await fs.rename(tmp, target);
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
await fs.rm(tmp, { force: true }).catch(() => { });
|
|
70
|
+
throw err;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
let mutationChain = Promise.resolve();
|
|
74
|
+
/**
|
|
75
|
+
* Run one change to `settings.json`. `fn` receives the current settings and returns the settings
|
|
76
|
+
* to write, or `undefined` to write nothing. Resolves with the settings before and after the
|
|
77
|
+
* change (`after` is `undefined` when nothing was written). A refused or failed mutation rejects
|
|
78
|
+
* its own caller only; the chain keeps going.
|
|
79
|
+
*/
|
|
80
|
+
export function mutateSettingsFile(fn) {
|
|
81
|
+
const run = mutationChain.then(async () => {
|
|
82
|
+
const before = await readSettingsForWrite(SETTINGS_PATH).catch((err) => {
|
|
83
|
+
console.warn(`[settings] write refused: ${getErrorMessage(err)}`);
|
|
84
|
+
throw err;
|
|
85
|
+
});
|
|
86
|
+
const after = fn({ ...before });
|
|
87
|
+
if (after)
|
|
88
|
+
await writeSettingsFile(SETTINGS_PATH, after);
|
|
89
|
+
return { before, after };
|
|
90
|
+
});
|
|
91
|
+
mutationChain = run.catch(() => { });
|
|
92
|
+
return run;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Rejects with `SettingsWriteRefusedError` when `mutateSettingsFile()` would refuse a write right
|
|
96
|
+
* now: the writer's own read-for-write rule, run on its own. For a route that does something it
|
|
97
|
+
* cannot take back (case rename ends sessions) before its settings write. A check only, outside
|
|
98
|
+
* the chain (writes are atomic, so it never reads a half-written file); the file can still change
|
|
99
|
+
* before the write.
|
|
100
|
+
*/
|
|
101
|
+
export async function assertSettingsWritable() {
|
|
102
|
+
await readSettingsForWrite(SETTINGS_PATH);
|
|
103
|
+
}
|
|
104
|
+
/** A refused write answers 409 CONFLICT with the fix; any other failure stays OPERATION_FAILED. */
|
|
105
|
+
export function settingsWriteErrorResponse(err) {
|
|
106
|
+
if (err instanceof SettingsWriteRefusedError)
|
|
107
|
+
return createErrorResponse(ApiErrorCode.CONFLICT, err.message);
|
|
108
|
+
return createErrorResponse(ApiErrorCode.OPERATION_FAILED, getErrorMessage(err));
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=settings-writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings-writer.js","sourceRoot":"","sources":["../../src/web/settings-writer.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aicodeman",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.47.0",
|
|
4
4
|
"description": "Self-hosted mission control for AI coding agents: run Claude Code, Codex, OpenCode, Gemini, DeepSeek, Grok and more 24/7 in tmux, from any device.",
|
|
5
5
|
"mcpName": "io.github.Ark0N/codeman",
|
|
6
6
|
"type": "module",
|
package/skills/codeman/SKILL.md
CHANGED
|
@@ -8,12 +8,19 @@ description: >-
|
|
|
8
8
|
read their output, and clean up; where available, message claude workers directly
|
|
9
9
|
(Claude Code cross-session messaging). Use when asked to orchestrate or parallelize
|
|
10
10
|
work across Codeman sessions, get a second opinion from another CLI or model, watch
|
|
11
|
-
another session,
|
|
12
|
-
|
|
11
|
+
another session, start and manage workers, or retrieve saved local Codex history
|
|
12
|
+
by file/native ID or root and descendants with topic/date filters. Live API
|
|
13
|
+
operations require a Codeman-managed session (CODEMAN_MUX=1). Offline history
|
|
14
|
+
reads do not require a server or managed session.
|
|
13
15
|
---
|
|
14
16
|
|
|
15
17
|
# Driving Codeman from inside a session
|
|
16
18
|
|
|
19
|
+
For **saved Codex conversation history**, use `codeman history read` and
|
|
20
|
+
[reference/history.md](reference/history.md). This is a read-only local command:
|
|
21
|
+
route to it **before §0**, including outside a managed session. It needs no API
|
|
22
|
+
URL, credentials or running server. All live API operations below retain §0.
|
|
23
|
+
|
|
17
24
|
You are an agent running inside a Codeman-managed terminal session. Codeman is the
|
|
18
25
|
server that spawned you; its HTTP API can start, prompt, watch, and delete other
|
|
19
26
|
sessions.
|
|
@@ -30,21 +37,33 @@ through: the verbs in detail (the old §5) in [reference/verbs.md](reference/ver
|
|
|
30
37
|
worked multi-worker flows in [reference/recipes.md](reference/recipes.md), endpoint
|
|
31
38
|
tables and a symptom gallery in [reference/endpoints.md](reference/endpoints.md), and
|
|
32
39
|
direct messaging to claude workers in [reference/messaging.md](reference/messaging.md).
|
|
40
|
+
Experimental bounded inspection and guarded stage/submit load only when needed from
|
|
41
|
+
[reference/inspection-and-staging.md](reference/inspection-and-staging.md).
|
|
33
42
|
|
|
34
43
|
This skill works the same whichever CLI you are: Codeman puts it where each CLI looks
|
|
35
44
|
for skills (`.claude/skills/` for Claude Code, `.agents/skills/` for Codex, Gemini CLI,
|
|
36
45
|
OpenCode, Antigravity, Grok, DeepSeek and OMP). A **pi** or **shell** worker never gets
|
|
37
46
|
it, but has the same environment: tell it *"other sessions: `codeman agent --help`"*.
|
|
38
|
-
That bundled CLI (`ls`, `spawn`, `send`, `wait`, `read`, `
|
|
39
|
-
verbs `post`, `inbox`, `ack`) is the same
|
|
47
|
+
That bundled CLI (`ls`, `spawn`, `send`, `wait`, `read`, `inspect`, `stage`, `submit`,
|
|
48
|
+
`interrupt`, `rm`, and the inbox verbs `post`, `inbox`, `ack`) is the same
|
|
40
49
|
verbs over the same endpoints, with the guards below (no control bytes, no self-delete,
|
|
41
50
|
no guessed URL) enforced in code, and it is also your own way through when this
|
|
42
51
|
machine has no `jq` for the preamble below.
|
|
43
52
|
|
|
53
|
+
For an existing project, use one command:
|
|
54
|
+
`codeman agent spawn --working-dir /path/to/project --mode codex`. With no case and
|
|
55
|
+
no `--working-dir`, `spawn` uses cwd. Give editing workers separate worktrees. A
|
|
56
|
+
positional case keeps quick-start behavior and cannot be combined with
|
|
57
|
+
`--working-dir`; an empty `--working-dir` (`"$WT"` unset) refuses with exit 4
|
|
58
|
+
rather than falling back to cwd, and a cwd that is HOME refuses too (hooks would
|
|
59
|
+
land in `~/.claude`; pass `--working-dir ~` to mean it). Directory launches keep parent lineage and never
|
|
60
|
+
mark the project as agent scratch. If startup fails or is ambiguous, the CLI
|
|
61
|
+
reports the exact created ID: inspect it before retrying or cleaning up.
|
|
62
|
+
|
|
44
63
|
## 0. Guard and bootstrap
|
|
45
64
|
|
|
46
|
-
|
|
47
|
-
you are not part of is not yours to drive.
|
|
65
|
+
For live API operations, if `CODEMAN_MUX` is not `1`, **stop and say so**.
|
|
66
|
+
Do not guess an API URL; a server you are not part of is not yours to drive.
|
|
48
67
|
|
|
49
68
|
Two failures come from your CLI, not from Codeman: name them to the user instead of
|
|
50
69
|
retrying.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Saved Codex history (offline)
|
|
2
|
+
|
|
3
|
+
Use `codeman history read` for retained local Codex JSONL transcripts. This command
|
|
4
|
+
works outside a managed session and never calls the HTTP API. Do not bootstrap
|
|
5
|
+
API credentials or require `CODEMAN_MUX` for this read-only job.
|
|
6
|
+
|
|
7
|
+
Choose exactly one selector:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
codeman history read --file /path/to/rollout.jsonl
|
|
11
|
+
codeman history read --session-id aaaaaaaa --sessions-root /path/to/sessions
|
|
12
|
+
codeman history read --root-session-id aaaaaaaa-1111-4111-8111-111111111111 \
|
|
13
|
+
--topic 'authentication' --after 2026-10-01 --before 2026-10-24 \
|
|
14
|
+
--max-bytes 65536
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`--session-id` accepts a native conversation UUID or unique prefix of at least
|
|
18
|
+
8 characters; identity comes from metadata, not filenames. `--root-session-id`
|
|
19
|
+
requires a full native UUID and includes transitive descendants found in metadata
|
|
20
|
+
(spawned sub-agents and forks). The default store is `$CODEX_HOME/sessions`, or
|
|
21
|
+
`~/.codex/sessions` when unset; a store directory that is itself a symlink is
|
|
22
|
+
followed, links inside it are skipped. `--file` selects one file and does not
|
|
23
|
+
search for its ancestors or children.
|
|
24
|
+
|
|
25
|
+
Topic matching is a case-insensitive literal substring. Dates are inclusive
|
|
26
|
+
`YYYY-MM-DD` bounds compared as UTC calendar dates. Each filter selects whole
|
|
27
|
+
user/assistant turns; a turn is retained if it has a date match and a topic match,
|
|
28
|
+
which may be different messages in that turn. Tool calls/results and injected
|
|
29
|
+
context (rows Codex adds that start with `#` or `<`, such as AGENTS.md and
|
|
30
|
+
`<environment_context>`) are omitted. Adjacent duplicate native representations
|
|
31
|
+
are collapsed; repeated messages from the same representation are retained.
|
|
32
|
+
|
|
33
|
+
A forked or spawned thread's file starts with a copy of its parent's history. That
|
|
34
|
+
copy is dropped (it is in the parent's own file), so each record belongs to the
|
|
35
|
+
thread that wrote it. A later `session_meta` for any thread that is not a declared
|
|
36
|
+
ancestor still refuses the file.
|
|
37
|
+
|
|
38
|
+
JSON is the default (`--json` or `--format json`); `--format text` prints one block
|
|
39
|
+
per record. `--json` together with `--format text` is an error.
|
|
40
|
+
Results identify source paths, native session/root IDs, timestamps, roles and phases,
|
|
41
|
+
plus scan counters and `complete`. `phase` is Codex's own (`commentary` or
|
|
42
|
+
`final_answer`) on assistant records and `null` on user records or when none was
|
|
43
|
+
recorded. A root ID is `null` when ancestry cannot be proven.
|
|
44
|
+
Report that uncertainty; never relabel the queried child as its own root.
|
|
45
|
+
`complete: false` reports malformed or partial records (a running Codex may be
|
|
46
|
+
mid-write), skipped links, unattributed files, compressed rollouts, unreadable
|
|
47
|
+
directories, missing ancestors, or an inherited copy whose end could not be found
|
|
48
|
+
or proven (including when the parent's file is present but cannot be read). It
|
|
49
|
+
does not prove the store includes every conversation ever created, and a filtered
|
|
50
|
+
result is only evidence for its selected scope.
|
|
51
|
+
|
|
52
|
+
Reads require regular UTF8 files and reject final-component symlinks, conflicting
|
|
53
|
+
metadata, ambiguous IDs, cyclic ancestry and invalid selectors. A store file that
|
|
54
|
+
cannot be attributed (invalid UTF8 in its head, no metadata in its first 128 KiB,
|
|
55
|
+
changing while its head is read) is counted in `unattributedFiles` instead of
|
|
56
|
+
failing the lookup. Codex's optional rollout compression rewrites cold rollouts to
|
|
57
|
+
`*.jsonl.zst`; those are not read. Each is counted in `compressedFiles` (one whose
|
|
58
|
+
plain `.jsonl` sibling exists is skipped, as Codex skips it), and a lookup that
|
|
59
|
+
misses names them. A compressed file passed to `--file` is refused; read a
|
|
60
|
+
decompressed copy instead (`zstd -dc <file> > copy.jsonl`). A selected rollout
|
|
61
|
+
that a running Codex is appending to is read as a snapshot up to its last complete
|
|
62
|
+
line; one that was replaced or truncated fails. Parent directories of an explicitly supplied path must be trusted; this is
|
|
63
|
+
not a filesystem sandbox.
|
|
64
|
+
|
|
65
|
+
Budgets, each failing with an error rather than a partial answer. Every flag is
|
|
66
|
+
validated before the first file is read, and only plain decimal integers are
|
|
67
|
+
accepted:
|
|
68
|
+
|
|
69
|
+
| Flag | Bounds | Default | Maximum |
|
|
70
|
+
| ---- | ------ | ------- | ------- |
|
|
71
|
+
| `--metadata-bytes` | head reads attributing every rollout in the store | 1 GiB | 16 GiB |
|
|
72
|
+
| `--max-entries` | directory entries visited | 65536 | 1048576 |
|
|
73
|
+
| `--scan-bytes` | the selected transcripts, plus any parent file read to prove where a copy ends (each file charged once) | 16 MiB | 256 MiB |
|
|
74
|
+
| `--max-bytes` | output, including the final newline | 8192 | 1048576 |
|
|
75
|
+
|
|
76
|
+
Each rollout's `session_meta` carries Codex's base instructions (about 20 KiB), so
|
|
77
|
+
attributing a store costs about that much per rollout, charged to
|
|
78
|
+
`--metadata-bytes`, never to `--scan-bytes`. Directory depth is capped at 8 (Codex
|
|
79
|
+
writes `YYYY/MM/DD`). Output is never silently truncated or split into partial
|
|
80
|
+
JSON or turns. Narrow the store/filters or explicitly raise the relevant budget.
|
|
81
|
+
Missing evidence is an error, not an empty success.
|
|
82
|
+
|
|
83
|
+
This command does not inspect live panes, stage prompts, submit input or manage
|
|
84
|
+
sessions. For live operations return to the managed-session guard in the skill.
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Experimental bounded inspection and guarded submission
|
|
2
|
+
|
|
3
|
+
**Experimental:** `codeman agent inspect`, `stage` and `submit`, and their
|
|
4
|
+
`/api/v1/sessions/:id/inspect|stage|submit` routes (including `/api` aliases),
|
|
5
|
+
are labeled experimental and so are not part of the stable CLI/HTTP contract. Their commands, flags, paths,
|
|
6
|
+
payloads and behavior may change or be removed in a minor or patch release.
|
|
7
|
+
Pin a compatible Codeman version when automating them. Authentication and
|
|
8
|
+
session ownership checks still apply.
|
|
9
|
+
|
|
10
|
+
They are also opt-in: until the user turns on **Experimental agent coordination**
|
|
11
|
+
in App Settings (`agentCoordinationEnabled`, off by default), every one of them
|
|
12
|
+
fails with `FORBIDDEN: ... (HTTP 403)` naming that setting. That is not something
|
|
13
|
+
to retry or work around: tell the user, or use `send`/`read` instead.
|
|
14
|
+
|
|
15
|
+
Use these commands inside a Codeman session. They use its authenticated HTTP API.
|
|
16
|
+
They supplement `send`, `wait` and `read` over the same HTTP transport; no direct
|
|
17
|
+
tmux access is required.
|
|
18
|
+
|
|
19
|
+
## Inspect recent evidence
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
codeman agent inspect "$SID" --max-bytes 8192 --json
|
|
23
|
+
codeman agent inspect "$SID" --max-bytes 8192 --since "$CURSOR" --json
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Read `source`, `identity`, `activity`, `evidence`, `truncated` and `cursor` before
|
|
27
|
+
interpreting the result. `maxBytes` bounds UTF8 evidence bytes, excluding the JSON
|
|
28
|
+
metadata/envelope. The default is 8192, maximum 65536.
|
|
29
|
+
|
|
30
|
+
- `codex-jsonl`: strictly attributed local Codex JSONL records. The first call
|
|
31
|
+
selects recent complete records within a bounded tail window;
|
|
32
|
+
`omittedBeforeBytes` labels older bytes deliberately omitted. A cursor continues
|
|
33
|
+
after the last consumed complete record. Partial final records remain pending.
|
|
34
|
+
- `pane-snapshot`: UTF8-safe tail of a visible frame or the session's buffered
|
|
35
|
+
output. It has `incremental:false` and `cursor:null`. This is the fallback for
|
|
36
|
+
other modes, remote/container sessions, ambiguous attribution, and exhausted
|
|
37
|
+
attribution budgets. Repeating a snapshot can repeat evidence.
|
|
38
|
+
|
|
39
|
+
Attribution proves which file supplied the evidence, not which thread is now
|
|
40
|
+
active in the TUI. A launch resume that conflicts with a newly owned rollout
|
|
41
|
+
falls back to a snapshot. An in-CLI `/resume` of an existing foreign-originator
|
|
42
|
+
thread may leave launch metadata unchanged. Check `identity.conversationId`;
|
|
43
|
+
these reads do not provide authoritative current-thread tracking.
|
|
44
|
+
|
|
45
|
+
Terminal resizes preserve inspection cursors. Cursors are opaque, scoped to the
|
|
46
|
+
requesting identity, session, pane lifecycle generation
|
|
47
|
+
and attributed transcript, expire after 15 minutes, and disappear on server
|
|
48
|
+
restart. Each caller and session keeps its newest 8 (so retrying the last call
|
|
49
|
+
works), at most 1024 in all; an older cursor can be retired. A replaced/truncated/rewritten source, reassociated session, foreign cursor
|
|
50
|
+
or unavailable native source returns `409 CONFLICT`. Inspect again without
|
|
51
|
+
`--since` to establish a new tail baseline; this may omit older evidence.
|
|
52
|
+
|
|
53
|
+
`blockedReason` explains an unfinished or oversized record. Incremental reads
|
|
54
|
+
never split or silently skip one. Increase the byte budget for
|
|
55
|
+
`record-exceeds-output-budget`; when the record exceeds the maximum or scan cap,
|
|
56
|
+
use `read --tail` for a labeled terminal view or start a fresh tail baseline.
|
|
57
|
+
Inspect scans at most 256 KiB of record data plus bounded generation anchors.
|
|
58
|
+
Attribution separately caps directory entries (8192), depth (8), negative-filter
|
|
59
|
+
prefix reads (8 MiB) and candidate metadata including final verification (1 MiB). Evidence and
|
|
60
|
+
activity are observations, not proof of task completion or authorization.
|
|
61
|
+
|
|
62
|
+
## Stage, inspect, then submit once
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
printf '%s' 'Review src/ and report the failing tests' > /tmp/codeman-message.txt
|
|
66
|
+
codeman agent stage "$SID" --message-file /tmp/codeman-message.txt --json
|
|
67
|
+
# Review the returned stageId, sha256, expiresAt; inspect the target if needed.
|
|
68
|
+
codeman agent submit "$SID" --stage-id "$STAGE_ID" --confirm-sha "$SHA256" --json
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Stage types the file contents **without Enter**. The file must be regular, UTF8,
|
|
72
|
+
one printable line, at most 8192 bytes, with no control characters or trailing
|
|
73
|
+
whitespace/newline. It initially supports a local Codex composer with a recognized
|
|
74
|
+
footer and an exact, unwrapped line/caret capture. Before typing, stage checks
|
|
75
|
+
the actual captured width and composer indentation; a message that would reach
|
|
76
|
+
the right edge or wrap is refused without writing anything. Unknown, working, modal,
|
|
77
|
+
wrapped, remote/container and shell composers are refused. A customized footer or
|
|
78
|
+
unsupported character-width rendering can also make verification unavailable.
|
|
79
|
+
Self-targets are refused by the CLI.
|
|
80
|
+
|
|
81
|
+
Stage also refuses, before typing, a message that would change what Enter does:
|
|
82
|
+
one starting with `/` (a Codex slash command; with its command list open, Enter
|
|
83
|
+
would run the highlighted command instead) or `!` (a shell command), and one whose
|
|
84
|
+
**last** word starts with `@` (file/mention search) or `$` (skills). Those popups
|
|
85
|
+
follow the caret, which stage leaves at the end, so `look at @src/app.ts please`
|
|
86
|
+
is fine. Send slash and shell commands with `codeman agent send`, and end a
|
|
87
|
+
message with an ordinary word when it mentions a file. A frame showing a
|
|
88
|
+
suggestion popup above the composer is refused at stage and submit too.
|
|
89
|
+
|
|
90
|
+
The receipt stores a hash and ephemeral identities, never prompt content. It
|
|
91
|
+
expires after two minutes; capacity is 1024 live receipts. After typing, stage
|
|
92
|
+
re-reads the pane (every 50 ms, up to one second, since Codex repaints a little
|
|
93
|
+
after the keys) and issues a receipt only for a frame that shows exactly the
|
|
94
|
+
message with the caret after it. Any refusal after the keys went out (typing
|
|
95
|
+
failed or was ambiguous, the pane or input changed, or no frame verified in time)
|
|
96
|
+
says the message may already be in the composer: no receipt was issued. Do not
|
|
97
|
+
stage again on top of it; follow [Recover a stranded draft](#recover-a-stranded-draft) below first.
|
|
98
|
+
|
|
99
|
+
While a submit's Enter is in flight (milliseconds, plus the moment it takes to
|
|
100
|
+
write input held behind it), TAGGED input to that session (`clientId` and `seq`,
|
|
101
|
+
which `codeman agent send` and `interrupt` always carry) answers `409 CONFLICT`
|
|
102
|
+
with nothing written; retry it. Untagged input, terminal keystrokes, `send-key`
|
|
103
|
+
and Codeman's own managed writes are held instead and written in arrival order
|
|
104
|
+
once the Enter is out.
|
|
105
|
+
|
|
106
|
+
Submit checks the caller, session, hash, expiry, pane lifecycle, input revision,
|
|
107
|
+
geometry, exact composer and caret, then sends one conditional Enter at the session's input
|
|
108
|
+
boundary. It first waits until 250 ms have passed since stage typed (Codex turns an
|
|
109
|
+
Enter that follows typed text within 120 ms into a newline), so submitting right
|
|
110
|
+
after stage is fine. Competing Codeman writes are held during dispatch and written
|
|
111
|
+
after it, except tagged input, which is refused with `409`. Browser/API/key
|
|
112
|
+
input and managed restarts invalidate receipts even when the visible text or pid
|
|
113
|
+
is restored. Direct tmux edits are outside that input serialization; captures
|
|
114
|
+
remain evidence at the time observed, rather than terminal isolation.
|
|
115
|
+
|
|
116
|
+
Every owned submit attempt consumes its receipt, including hash mismatch,
|
|
117
|
+
verification failure and delivery failure. Concurrent/repeated submits cannot
|
|
118
|
+
replay Enter, and there is no autonomous retry. A successful response means one
|
|
119
|
+
Enter was delivered; use inspection or a suitable wait signal to observe native
|
|
120
|
+
acceptance. A `409` or broken connection means inspect first. Do not automatically
|
|
121
|
+
stage/submit again or send an unguarded Enter to recover.
|
|
122
|
+
|
|
123
|
+
## Recover a stranded draft
|
|
124
|
+
|
|
125
|
+
A consumed receipt cannot be reused, and a stage refused after typing issued
|
|
126
|
+
none. First observe whether the prompt is still in the composer or was accepted: use transcript evidence/wait signals and a fresh terminal capture
|
|
127
|
+
(`GET /api/v1/sessions/:id/terminal?tail=8192`). If the target is working, has
|
|
128
|
+
accepted the prompt, shows a dialog, or delivery is ambiguous, keep observing;
|
|
129
|
+
do not clear or resend anything. A transcript prompt row alone is not proof
|
|
130
|
+
that text remains unsent in the current composer.
|
|
131
|
+
|
|
132
|
+
Only recover an unambiguously unsent draft in an input-ready local Codex
|
|
133
|
+
composer: verify the complete draft, recognized footer and caret at its end in
|
|
134
|
+
the current frame, and ensure no other writer can edit this target during
|
|
135
|
+
recovery. If the frame is wrapped, incomplete or unclear, ask the user to clear
|
|
136
|
+
it in the terminal instead of guessing keys. Never use `send` to overwrite a
|
|
137
|
+
draft: that appends and submits both prompts together.
|
|
138
|
+
|
|
139
|
+
After those checks, the known Codex line-clear chord may be sent once through
|
|
140
|
+
the existing raw input route, with **no Enter**. This conditional example uses
|
|
141
|
+
the authenticated `CURL`/`API` values loaded by §0 and the exact target id:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
"${CURL[@]}" -X POST "$API/api/v1/sessions/$SID/input" \
|
|
145
|
+
-H 'Content-Type: application/json' -d '{"input":"\u0015","useMux":false}'
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Do not retry a failed/ambiguous clear blindly. Read a fresh terminal frame and
|
|
149
|
+
verify the composer is empty and input-ready. Only then create a **fresh** stage
|
|
150
|
+
receipt for the intended prompt and submit that receipt once. If the draft did
|
|
151
|
+
not clear, the target began working, or verification remains uncertain, stop and
|
|
152
|
+
ask the user; do not send an unguarded Enter or replay the old prompt.
|
|
@@ -48,7 +48,7 @@ own head: the worker enforcing the cap is the one who has to be told about it.
|
|
|
48
48
|
|
|
49
49
|
| Job | Channel |
|
|
50
50
|
| --- | --- |
|
|
51
|
-
| spawn a worker, create its case | HTTP `quick-start` (the only path) |
|
|
51
|
+
| spawn a worker, create its case | HTTP `quick-start` (the only path that creates a case); an existing directory is `POST sessions` + `interactive` (`codeman agent spawn --working-dir`) |
|
|
52
52
|
| readiness, incl. the trust dialog | HTTP, Flow 1 (a message cannot answer a dialog) |
|
|
53
53
|
| deliver a task to a READY claude worker | **messaging** (preferred) or HTTP input |
|
|
54
54
|
| steer a BUSY claude worker mid-turn | **messaging** (read between the worker's tool calls; the HTTP path can only type into the composer, where text waits for the turn to end) |
|
|
@@ -31,7 +31,7 @@ wrong directory.** `quick-start` with a new `caseName` does not find your repo:
|
|
|
31
31
|
|-------------------|------|------------------------------|
|
|
32
32
|
| a fresh scratch dir (throwaway experiments) | `POST /api/v1/quick-start {"caseName":"scratch-1","mode":"claude"}` with a **new** case name | Codeman creates the directory and **writes hooks**: `stop` and `blocked` fire, send-and-wait is trustworthy |
|
|
33
33
|
| a linked case (a real repo in the linked-cases registry) | same call with the linked name | **hooks installed at session create**, so `stop` fires here too. Not guaranteed: the operator can turn it off. Check |
|
|
34
|
-
| any other absolute path, e.g. a git worktree you made | `POST /api/v1/sessions {"workingDir":"/abs/path","mode":"claude"}` then `POST /api/v1/sessions/:id/interactive` | same: **hooks installed at session create**, subject to the same setting. Check |
|
|
34
|
+
| any other absolute path, e.g. a git worktree you made | `POST /api/v1/sessions {"workingDir":"/abs/path","mode":"claude"}` then `POST /api/v1/sessions/:id/interactive` (what `codeman agent spawn --working-dir /abs/path` sends) | same: **hooks installed at session create**, subject to the same setting. Check |
|
|
35
35
|
|
|
36
36
|
Read `.data.casePath` back from the `quick-start` response and check it is where you
|
|
37
37
|
meant. `caseName` accepts letters, digits, `-` and `_` only, and it resolves through
|
|
@@ -550,8 +550,10 @@ this (`src/web/routes/approval-routes.ts:43`). ESC is then claude's own interrup
|
|
|
550
550
|
that half is the CLI's behavior, not something this API guarantees.
|
|
551
551
|
|
|
552
552
|
- **This is not the composer-clearing tool.** Esc (and Ctrl+U) do **not** clear a
|
|
553
|
-
typed-but-unsubmitted prompt, verified live.
|
|
554
|
-
|
|
553
|
+
typed-but-unsubmitted Claude prompt, verified live. Do not submit an unverified
|
|
554
|
+
draft merely to clear it. For a refused guarded local Codex stage or submit, use the
|
|
555
|
+
verified-unsent recovery in [inspection and staging](inspection-and-staging.md#recover-a-stranded-draft);
|
|
556
|
+
when the composer is unclear, ask the user to clear it in the terminal.
|
|
555
557
|
- The interrupted turn already burned its tokens. Interrupting early saves the rest.
|
|
556
558
|
- `POST /api/sessions/:id/send-key` is a different endpoint and cannot do this: its
|
|
557
559
|
allowlist is S-Enter / C-Enter only.
|
|
@@ -811,3 +813,16 @@ Rules that matter:
|
|
|
811
813
|
not parked, `send` it one line ("read your inbox: `codeman agent inbox`").
|
|
812
814
|
- **Lifetime.** An inbox goes with its session on delete. A server restart empties all
|
|
813
815
|
inboxes unless the user turned on *Keep agent inbox across restarts* in Settings.
|
|
816
|
+
|
|
817
|
+
## Experimental bounded inspection and guarded submission
|
|
818
|
+
|
|
819
|
+
These three commands and their HTTP routes are labeled experimental, so they may
|
|
820
|
+
change or be removed in minor or patch releases. They are also opt-in
|
|
821
|
+
(`agentCoordinationEnabled`, off by default: a 403 naming it until the user turns
|
|
822
|
+
it on). Use `codeman agent inspect` for bounded evidence and incremental local
|
|
823
|
+
Codex cursors.
|
|
824
|
+
Use `codeman agent stage --message-file` followed by one hash-confirmed
|
|
825
|
+
`codeman agent submit --stage-id --confirm-sha` when the exact local Codex
|
|
826
|
+
composer and caret can be verified. Other targets provide labeled snapshots or
|
|
827
|
+
refuse guarded input. See [inspection and staging](inspection-and-staging.md)
|
|
828
|
+
for budgets, receipt expiry, conflict handling and supported composers.
|