@monster-orange/den 0.4.21 → 0.4.23
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/CHANGELOG.md +115 -0
- package/docs/distributions.md +186 -42
- package/package.json +1 -1
- package/service/install.sh +213 -63
- package/src/shared/agents/den-claude.ts +13 -1
- package/src/shared/agents/guardrails/rotation-hook.ts +5 -0
- package/src/shared/agents/records.ts +6 -0
- package/src/shared/agents/rotate-settings.ts +309 -0
- package/src/shared/agents/rotation.ts +110 -5
- package/src/shared/agents/runtime.ts +6 -0
- package/src/shared/agents/session-name.ts +21 -1
- package/src/shared/den-config.ts +27 -12
- package/src/shared/launchd-session.ts +92 -0
- package/src/shared/sessions/client.ts +24 -0
- package/src/shared/sessions/host.ts +114 -5
- package/src/shared/sessions/types.ts +5 -0
- package/src/ui/cli/agent-ops.ts +469 -17
- package/src/ui/cli/agents-command.ts +200 -3
- package/src/ui/cli/doctor-command.ts +72 -0
- package/src/ui/cli/doctor-where.ts +203 -0
- package/src/ui/cli/index.ts +1 -1
- package/src/ui/cli/server-agent-ops.ts +2 -2
- package/src/ui/cli/service-command.ts +217 -11
- package/src/ui/cli/sessions-command.ts +46 -12
- package/src/ui/cli/web-command.ts +36 -5
- package/src/ui/cli/web-service.ts +160 -0
- package/src/ui/server/agent-routes.ts +149 -5
- package/src/ui/server/index.ts +17 -5
- package/src/ui/server/public/agents-page.js +316 -27
- package/src/ui/server/public/agents.html +62 -0
- package/src/ui/server/public/i18n/es.js +58 -2
- package/src/ui/server/public/i18n/ja.js +54 -2
- package/src/ui/server/public/settings-registry.js +204 -0
- package/src/ui/server/public/settings.html +43 -4
- package/src/ui/server/public/shell.js +56 -2
- package/src/ui/server/route-classes.ts +21 -0
- package/src/ui/server/session-routes.ts +27 -5
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,121 @@ All notable changes to Den are documented here. Each release lists the
|
|
|
4
4
|
config and manifest changes a distribution must make to move to it under
|
|
5
5
|
**Migrations**.
|
|
6
6
|
|
|
7
|
+
## [0.4.23] - 2026-11-10
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **Agents relaunch from their handoff by themselves (D28).** When an
|
|
12
|
+
agent's rotation is due (after `after_compactions` compactions, or its
|
|
13
|
+
pull request merged), Den asks it for its handoff at its next idle,
|
|
14
|
+
never mid-turn, and relaunches it once the handoff passes: a fresh
|
|
15
|
+
conversation with the same name, persona, workspace and folder. A toast
|
|
16
|
+
and the audit log say so, and the old conversation is kept. Den asks
|
|
17
|
+
twice at most, then falls back to asking you.
|
|
18
|
+
- **The rotation callout has buttons, running or stopped**, on the row and
|
|
19
|
+
in the pane bar: Relaunch now (asking for the handoff first if needed),
|
|
20
|
+
Write handoff, Keep this conversation (with "Don't ask again for this
|
|
21
|
+
agent") and Settings. It says what happens next and where the settings
|
|
22
|
+
come from. Before, a running agent got a message and nothing to press,
|
|
23
|
+
and Stop then Start showed the same message again.
|
|
24
|
+
- **Rotation settings at every scope.** `after_compactions` (a number or
|
|
25
|
+
`never`), `on_due` (`auto`, the default, `ask` or `off`) and
|
|
26
|
+
`on_pr_merged`. The most specific wins: agent, persona in a workspace,
|
|
27
|
+
persona, workspace, service, this install, org config. Settings › Agents
|
|
28
|
+
› Rotation and `<cli> agents rotate` set them; `<cli> agents rotate <id>
|
|
29
|
+
--show` names where each value comes from. `<cli> agents keep` and
|
|
30
|
+
`<cli> agents handoff` are the callout's buttons. A change applies to
|
|
31
|
+
running agents too.
|
|
32
|
+
- Resume (or Start) on a due agent follows `on_due`: `auto` relaunches it
|
|
33
|
+
from its handoff, `ask` refuses with the callout's choices, `off` goes
|
|
34
|
+
on with the same conversation.
|
|
35
|
+
|
|
36
|
+
### Fixed
|
|
37
|
+
|
|
38
|
+
- **`web restart` with the service installed** restarts the launchd job
|
|
39
|
+
and names its pid and the service's log. Before, it started a plain
|
|
40
|
+
server, said "started", and that server died seconds later because
|
|
41
|
+
launchd had brought the job back onto the port. `web up` starts a job
|
|
42
|
+
that isn't answering; `web down` refuses and names `service uninstall`.
|
|
43
|
+
- The "port in use" message no longer says to kill whatever holds the
|
|
44
|
+
port, which killed the service. It names `service status` and `web
|
|
45
|
+
restart`.
|
|
46
|
+
|
|
47
|
+
### Migrations
|
|
48
|
+
|
|
49
|
+
- None required. Rotation now relaunches by itself (`on_due: auto`). To
|
|
50
|
+
keep den#4's behavior (a person relaunches), set `on_due: ask` under
|
|
51
|
+
`agents.rotate` in the org config, or `<cli> agents rotate on_due ask`.
|
|
52
|
+
`agents.rotate.standing` still works; a persona override replaces it.
|
|
53
|
+
|
|
54
|
+
## [0.4.22] - 2026-11-10
|
|
55
|
+
|
|
56
|
+
### Added
|
|
57
|
+
|
|
58
|
+
- **Opt-in: agents meant to keep running across logout (D18, D20).**
|
|
59
|
+
`service install --mode always` installs the web server and the session
|
|
60
|
+
host as LaunchDaemons that run as you (`UserName`): they start at boot
|
|
61
|
+
and are meant to keep running when you log out of the desktop, and so
|
|
62
|
+
every terminal and agent. It is not yet proven across a logout: `service
|
|
63
|
+
help`, `--plan`, install, `doctor` and the agents page say so. It takes your admin password once (sudo); `--mode login`, the
|
|
64
|
+
default, keeps LaunchAgents in the desktop session (they stop at
|
|
65
|
+
logout). Without `--mode`, install keeps the mode already installed.
|
|
66
|
+
Switching removes the other mode's jobs.
|
|
67
|
+
- **The session host is its own launchd job** (`<label>` with `.web` →
|
|
68
|
+
`.sessions`), in both modes, so it runs in the mode's session whoever
|
|
69
|
+
starts the first terminal: before, it inherited the launchd session of
|
|
70
|
+
whatever started it, and one started from the desktop ended at logout
|
|
71
|
+
with every agent in it. `<cli> sessions` and agents wait for the job.
|
|
72
|
+
- **Full Disk Access for Den, not for every node program.** The host job
|
|
73
|
+
runs a copy of node Den owns, `<stateDir>/bin/<cli>-sessions-host`
|
|
74
|
+
(0700), the path to grant Full Disk Access to (protected folders: other
|
|
75
|
+
volumes, Desktop, Documents); agents inherit it. Install refreshes the
|
|
76
|
+
copy when node changes and says when the grant must be given again (a
|
|
77
|
+
new signer, an ad-hoc signed node). A node that can't be copied
|
|
78
|
+
(Homebrew's) is run directly, and install says so.
|
|
79
|
+
- **Where it runs, shown honestly.** Every session records the launchd
|
|
80
|
+
session its host ran in (`launchctl managername`). The Agents page tags
|
|
81
|
+
each agent **Stops at logout** (the desktop session; tap for the fix) or
|
|
82
|
+
**No GUI** (kept across logout: no login keychain, no GUI apps; 1Password
|
|
83
|
+
through the service-account token, headless browsers, Full Disk Access
|
|
84
|
+
for protected folders). `doctor` ends with **where it runs**: the
|
|
85
|
+
server's and the host's session, Full Disk Access and the path to grant,
|
|
86
|
+
and the service's mode. `web up` from an ssh (Background) shell says what
|
|
87
|
+
a server started there means.
|
|
88
|
+
- **Rename, visible (D25).** **Rename…** in an agent pane's ⋯ menu and
|
|
89
|
+
**Rename** on a stopped agent's row, by touch or keyboard, and
|
|
90
|
+
`<cli> agents rename <id> <name>` (`--clear`: back to its id). Before,
|
|
91
|
+
only a double-click on an open tab renamed one.
|
|
92
|
+
- **Agents tell apart in a list of sessions (D24).** Den names each
|
|
93
|
+
Claude Code agent's session `<cli>-<ws>:<name, else id>` (`--name`) at
|
|
94
|
+
start and resume, so another session listing its peers sees which agent
|
|
95
|
+
is which, not a generic name. A rename shows at its next start or resume.
|
|
96
|
+
|
|
97
|
+
### Fixed
|
|
98
|
+
|
|
99
|
+
- **`service install` said running while its job crash-looped (D26).** A
|
|
100
|
+
plain `web up` server of the same install on the port answered the
|
|
101
|
+
check, while the job failed to start on the taken port. Install now
|
|
102
|
+
stops a plain server of this install first, and says running only when
|
|
103
|
+
the server answering is the job's own process; `service status` says
|
|
104
|
+
when another process holds the port. `--plan` says when install would
|
|
105
|
+
stop one.
|
|
106
|
+
- **`service status` names a job whose plist is present but not loaded**,
|
|
107
|
+
with the `launchctl bootstrap` that loads it (`sudo` for a LaunchDaemon);
|
|
108
|
+
`doctor` shows it too.
|
|
109
|
+
- **Tests never reach this machine's launchctl, gh or vendor CLIs**, even
|
|
110
|
+
through a spawn without `env`: the inert stand-ins are now first on the
|
|
111
|
+
real PATH (jest's globalSetup), not only on each test file's sandboxed
|
|
112
|
+
`process.env`.
|
|
113
|
+
|
|
114
|
+
### Migrations
|
|
115
|
+
|
|
116
|
+
- None required. An existing install keeps its mode (login). To try
|
|
117
|
+
keeping agents running across logout (not yet proven), run
|
|
118
|
+
`<cli> service install --mode always` once (one sudo), then grant Full
|
|
119
|
+
Disk Access to the path `doctor` names if agents read protected folders.
|
|
120
|
+
- `<cli> service` with no subcommand prints its help (before, an error).
|
|
121
|
+
|
|
7
122
|
## [0.4.21] - 2026-11-09
|
|
8
123
|
|
|
9
124
|
### Added
|
package/docs/distributions.md
CHANGED
|
@@ -1957,16 +1957,96 @@ Apps › New GitHub App):
|
|
|
1957
1957
|
|
|
1958
1958
|
## Running the web UI as a service (macOS)
|
|
1959
1959
|
|
|
1960
|
-
Den ships a launchd installer that runs the web UI
|
|
1961
|
-
|
|
1960
|
+
Den ships a launchd installer that runs the web UI and the session host (every
|
|
1961
|
+
terminal and agent) as launchd jobs, restarted if they exit:
|
|
1962
1962
|
|
|
1963
1963
|
```bash
|
|
1964
|
-
./bin/acme service install
|
|
1964
|
+
./bin/acme service install # install (or refresh) and start them
|
|
1965
|
+
./bin/acme service install --mode always # meant to keep them running across logout (opt-in, not yet proven)
|
|
1965
1966
|
./bin/acme service install --plan # what install would do; writes and loads nothing
|
|
1966
1967
|
./bin/acme service status # launchd's view: state, pid, last exit code
|
|
1967
|
-
./bin/acme service print # the
|
|
1968
|
-
./bin/acme service uninstall # stop
|
|
1969
|
-
```
|
|
1968
|
+
./bin/acme service print # the web plist it would install; installs nothing
|
|
1969
|
+
./bin/acme service uninstall # stop them and remove their plists
|
|
1970
|
+
```
|
|
1971
|
+
|
|
1972
|
+
With the service installed, `web` works through launchd. `web restart`
|
|
1973
|
+
restarts the job (`launchctl kickstart -k`) and names its new pid and the
|
|
1974
|
+
service's log. `web up` starts the job when it isn't answering. `web down`
|
|
1975
|
+
refuses, because launchd would only start it again: use `service
|
|
1976
|
+
uninstall` to stop it. Under `always`, restarting needs sudo, so `web
|
|
1977
|
+
restart` prints the `sudo launchctl kickstart -k system/<label>` line for
|
|
1978
|
+
you to run.
|
|
1979
|
+
|
|
1980
|
+
### Login or always
|
|
1981
|
+
|
|
1982
|
+
| `--mode` | Jobs | At logout |
|
|
1983
|
+
| ----------------- | ----------------------------------------------------- | ------------------------------------ |
|
|
1984
|
+
| `login` (default) | LaunchAgents in the desktop session (`gui/<uid>`) | stop, with every agent |
|
|
1985
|
+
| `always` | LaunchDaemons that run as you (`UserName`), from boot | meant to keep running, and so agents |
|
|
1986
|
+
|
|
1987
|
+
`always` is opt-in and not yet proven across a logout: no logout has
|
|
1988
|
+
shown it keeping an agent on the same conversation yet. Use `login` unless
|
|
1989
|
+
you are testing it.
|
|
1990
|
+
|
|
1991
|
+
`always` takes your admin password once (sudo writes and loads the
|
|
1992
|
+
LaunchDaemons in `/Library/LaunchDaemons`); it is never asked for again.
|
|
1993
|
+
Without `--mode`, install keeps the mode already installed, so re-running it
|
|
1994
|
+
after an upgrade never changes it. Switching mode removes the other mode's
|
|
1995
|
+
jobs: never both. Use `always` on a machine you reach from elsewhere (ssh, a
|
|
1996
|
+
browser on another machine); `login` on a laptop.
|
|
1997
|
+
|
|
1998
|
+
A process outside the desktop session has no login keychain and no GUI. So
|
|
1999
|
+
under `always`, agents use:
|
|
2000
|
+
|
|
2001
|
+
- **1Password**: the service-account token (`secrets.onepassword.token`),
|
|
2002
|
+
not the desktop app. `doctor` warns when this process has none.
|
|
2003
|
+
- **Browsers**: headless Chromium and Firefox. WebKit on macOS needs a
|
|
2004
|
+
desktop session; run it from Playwright's Linux image instead
|
|
2005
|
+
(CONTRIBUTING.md, `DEN_PW_WS`).
|
|
2006
|
+
- **Protected folders** (other volumes, Desktop, Documents): Full Disk
|
|
2007
|
+
Access, granted once (below).
|
|
2008
|
+
|
|
2009
|
+
Each session records the launchd session its host ran in, and the Agents page
|
|
2010
|
+
tags it: **Stops at logout** (the desktop session; tap it for the fix) or
|
|
2011
|
+
**No GUI** (kept across logout). `web up` from an ssh shell (a Background
|
|
2012
|
+
session) says the same before it starts a server there.
|
|
2013
|
+
|
|
2014
|
+
### The session host job and Full Disk Access
|
|
2015
|
+
|
|
2016
|
+
Both modes install the session host as its own job, `<label>` with `.web`
|
|
2017
|
+
replaced by `.sessions` (`local.acme.sessions`), so it runs in the mode's
|
|
2018
|
+
session whoever starts the first terminal; `<cli> sessions` and agents then
|
|
2019
|
+
wait for it rather than starting a host in the caller's session. It runs a
|
|
2020
|
+
copy of node Den owns, `<stateDir>/bin/<cli>-sessions-host` (0700), and
|
|
2021
|
+
macOS grants Full Disk Access to that path: never to the shared node, which
|
|
2022
|
+
would give it to every node program. To grant it: System Settings → Privacy &
|
|
2023
|
+
Security → Full Disk Access → + → that path (⌘⇧G to type it), then
|
|
2024
|
+
`<cli> sessions host --stop` (it restarts with the grant). Agents inherit it.
|
|
2025
|
+
|
|
2026
|
+
Install refreshes the copy when node changes. An official node build
|
|
2027
|
+
(nodejs.org, nvm) is signed by the Node.js project, so the grant holds across
|
|
2028
|
+
upgrades; install says when the signer changed and it must be granted again.
|
|
2029
|
+
An ad-hoc signed node needs a new grant after every change, and Homebrew's
|
|
2030
|
+
node loads libraries beside it and can't be copied: install then runs it
|
|
2031
|
+
directly and says so. `doctor` shows whether the host has Full Disk Access,
|
|
2032
|
+
and the path to grant.
|
|
2033
|
+
|
|
2034
|
+
### What doctor shows
|
|
2035
|
+
|
|
2036
|
+
`doctor` ends with **where it runs**: the web server's and the session host's
|
|
2037
|
+
launchd session (a warning with the fix when it stops at logout), Full Disk
|
|
2038
|
+
Access, and the service: its mode, or `plist present, job not loaded:
|
|
2039
|
+
launchctl bootstrap <domain> <plist>` (`sudo` for a LaunchDaemon) when launchd
|
|
2040
|
+
has dropped a job whose plist is still there.
|
|
2041
|
+
|
|
2042
|
+
### Running means the job's own process
|
|
2043
|
+
|
|
2044
|
+
A plain `web up` server of the same install on the port would answer for the
|
|
2045
|
+
job, which then fails to start on the taken port and restarts forever. So
|
|
2046
|
+
install stops a plain server of this install first (and says so), and says
|
|
2047
|
+
`running` only when the server answering is the job's own process (its pid is
|
|
2048
|
+
launchd's). Otherwise it says `port <N> is served by pid <P>, not the job`
|
|
2049
|
+
and exits 1; `status` says the same.
|
|
1970
2050
|
|
|
1971
2051
|
The label and log directory come from the org config:
|
|
1972
2052
|
|
|
@@ -2011,12 +2091,14 @@ node_modules/@monster-orange/den/service/install.sh uninstall
|
|
|
2011
2091
|
node_modules/@monster-orange/den/service/install.sh print # the plist only
|
|
2012
2092
|
```
|
|
2013
2093
|
|
|
2014
|
-
| Variable
|
|
2015
|
-
|
|
|
2016
|
-
| `DEN_ROOT`
|
|
2017
|
-
| `DEN_SERVICE_LABEL`
|
|
2018
|
-
| `DEN_SERVICE_LOGS`
|
|
2019
|
-
| `DEN_SERVICE_NODE`
|
|
2094
|
+
| Variable | Default |
|
|
2095
|
+
| ---------------------- | ----------------------------------------------------------------------- |
|
|
2096
|
+
| `DEN_ROOT` | required in a distribution |
|
|
2097
|
+
| `DEN_SERVICE_LABEL` | `local.<distribution dir name>.web` |
|
|
2098
|
+
| `DEN_SERVICE_LOGS` | `~/Library/Logs/<distribution dir name>` |
|
|
2099
|
+
| `DEN_SERVICE_NODE` | see below |
|
|
2100
|
+
| `DEN_SERVICE_MODE` | `login` (or `always`) |
|
|
2101
|
+
| `DEN_SERVICE_HOST_EXE` | none: the host runs that node (`<cli> service install` sets Den's copy) |
|
|
2020
2102
|
|
|
2021
2103
|
The service runs the engine's server, from the distribution root, with the
|
|
2022
2104
|
`node` on your `PATH` at install time. A version manager's node (nvm, fnm,
|
|
@@ -2495,6 +2577,15 @@ server scoped to its workspace.
|
|
|
2495
2577
|
start and resume answers). 0.4.12 sent the name shown as `sessionName`;
|
|
2496
2578
|
read `sessionTitle` instead. Records are unchanged, so none written
|
|
2497
2579
|
before needs migrating.
|
|
2580
|
+
- **Renaming.** `agents rename <id> <name>` (or `--clear`, back to its
|
|
2581
|
+
id) names an agent; so do **Rename…** in its pane's ⋯ menu and **Rename**
|
|
2582
|
+
on a stopped agent's row, by touch or keyboard, as well as a double-click
|
|
2583
|
+
on its tab. The id never changes.
|
|
2584
|
+
- **The name other sessions see.** Den names a Claude Code agent's session
|
|
2585
|
+
`<cli>-<ws>:<name, else id>` (`--name`) at every start and resume, so
|
|
2586
|
+
another session listing its peers tells Den's agents apart. A rename
|
|
2587
|
+
shows at its next start or resume. The record's `peerName` is the name
|
|
2588
|
+
last given, so reading it back is never taken for a `/rename`.
|
|
2498
2589
|
- `list` shows agents only: sessions with an agent record. A session from
|
|
2499
2590
|
`sessions start` is not an agent; `sessions list` shows it.
|
|
2500
2591
|
- `stop` sends its session TERM and marks it stopped. `resume` works only
|
|
@@ -3213,10 +3304,12 @@ report. It works on den-claude for personas with Den's hooks on.
|
|
|
3213
3304
|
the turn once while the handoff is missing or fails the check. The
|
|
3214
3305
|
instruction: write `handoff.md` in the agent's files folder, then end
|
|
3215
3306
|
the turn.
|
|
3216
|
-
4. Den relaunches the role
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3307
|
+
4. Den relaunches the role, by itself unless the settings say otherwise
|
|
3308
|
+
(`on_due`, below). A relaunch starts a fresh conversation (a new
|
|
3309
|
+
conversation id) with the same name, persona, workspace, folder and
|
|
3310
|
+
grants. Its first prompt is the handoff. The handoff moves to
|
|
3311
|
+
`agent-files/<id>/handoffs/`, the record notes the rotation, and the
|
|
3312
|
+
old conversation is kept.
|
|
3220
3313
|
|
|
3221
3314
|
**The handoff** has five parts, each a heading, each filled in. Write it
|
|
3222
3315
|
plainly, and explain every ID, as in a hand-back. It must stay under 20,000
|
|
@@ -3249,38 +3342,89 @@ agent's `handoff.md` (by its id), a file, or stdin: exit 0 when
|
|
|
3249
3342
|
it passes, 1 with each missing or empty part and each unexplained ID. A
|
|
3250
3343
|
part can also be a line such as `Next step: open the PR`.
|
|
3251
3344
|
|
|
3252
|
-
**
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
(
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
**
|
|
3345
|
+
**What happens when a rotation is due** (`on_due`):
|
|
3346
|
+
|
|
3347
|
+
- `auto` (the default). At the agent's next idle, never mid-turn, Den
|
|
3348
|
+
types the instruction into its session: write the handoff. Once the
|
|
3349
|
+
handoff passes the check and the agent is idle, Den relaunches it. The
|
|
3350
|
+
page shows a toast ("Relaunched <id> from its handoff after 3
|
|
3351
|
+
compactions. The old conversation <id> is kept.") and the audit log
|
|
3352
|
+
records it. Den asks at most twice, two minutes apart. If the handoff
|
|
3353
|
+
still fails, it falls back to `ask`.
|
|
3354
|
+
- `ask`. Nothing happens by itself. The agent's callout has the buttons.
|
|
3355
|
+
- `off`. Nothing happens, and no callout shows. Resume goes on with the
|
|
3356
|
+
same conversation.
|
|
3357
|
+
|
|
3358
|
+
**The callout** shows on a due agent's row (running or stopped) and in its
|
|
3359
|
+
pane bar. It says what happens next and where the settings come from
|
|
3360
|
+
("Rotates after 3 compactions (persona planner); when due: relaunch by
|
|
3361
|
+
itself (default)"). Its buttons:
|
|
3362
|
+
|
|
3363
|
+
- **Relaunch now**: from the handoff when it passes. Otherwise Den asks
|
|
3364
|
+
for it first (a stopped agent resumes to write it) and relaunches it
|
|
3365
|
+
once it passes, whatever `on_due` says.
|
|
3366
|
+
- **Write handoff**: on a running agent without one, types the
|
|
3367
|
+
instruction. It is refused mid-turn.
|
|
3368
|
+
- **Keep this conversation**: the compaction count starts again. With
|
|
3369
|
+
"Don't ask again for this agent", that agent's `after_compactions` is
|
|
3370
|
+
set to `never`. A person's only.
|
|
3371
|
+
- **Settings**: Settings › Agents › Rotation.
|
|
3372
|
+
|
|
3373
|
+
**Resume and Start on a due agent** follow `on_due`. Under `auto`, Resume
|
|
3374
|
+
relaunches it from its handoff once the handoff passes. Under `ask`,
|
|
3375
|
+
`<cli> agents resume <id>` refuses (exit 1) and names
|
|
3376
|
+
`<cli> agents relaunch <id>`, and the resume route answers 409 with code
|
|
3377
|
+
`rotated`. `<cli> agents relaunch <id> [-w <ws>]` and
|
|
3378
|
+
`POST /api/workspaces/<ws>/agents/<id>/relaunch` relaunch it at any time
|
|
3379
|
+
(a running agent is stopped first; a missing or failing handoff is a 409
|
|
3380
|
+
`no_handoff`). After a restart, a standing persona that rotated relaunches
|
|
3381
|
+
on its own.
|
|
3382
|
+
|
|
3383
|
+
**Settings.** Three keys:
|
|
3384
|
+
|
|
3385
|
+
| Key | Values | Default |
|
|
3386
|
+
| ------------------- | ---------------------- | ------- |
|
|
3387
|
+
| `after_compactions` | 1 to 100, or `never` | 3 |
|
|
3388
|
+
| `on_due` | `auto`, `ask` or `off` | `auto` |
|
|
3389
|
+
| `on_pr_merged` | `true` or `false` | `true` |
|
|
3390
|
+
|
|
3391
|
+
Each key comes from the most specific scope that sets it: the agent, the
|
|
3392
|
+
persona in a workspace, the persona, the workspace, the service (the
|
|
3393
|
+
workspace service whose folder holds the agent's folder), this install,
|
|
3394
|
+
the org config, then Den's default. A change applies to running agents
|
|
3395
|
+
too, at their next look (about every 15 seconds).
|
|
3396
|
+
|
|
3397
|
+
The org's values go in the org config:
|
|
3271
3398
|
|
|
3272
3399
|
```yaml
|
|
3273
3400
|
agents:
|
|
3274
3401
|
rotate:
|
|
3275
|
-
after_compactions: 3 # 1 to 100
|
|
3276
|
-
|
|
3402
|
+
after_compactions: 3 # 1 to 100, or never
|
|
3403
|
+
on_due: auto # auto, ask or off
|
|
3404
|
+
on_pr_merged: true
|
|
3277
3405
|
```
|
|
3278
3406
|
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3407
|
+
This install's values and every override are set in Settings › Agents ›
|
|
3408
|
+
Rotation, or from the command line, and kept in
|
|
3409
|
+
`<stateDir>/agent-rotation.json`:
|
|
3410
|
+
|
|
3411
|
+
```bash
|
|
3412
|
+
<cli> agents rotate # every value and override
|
|
3413
|
+
<cli> agents rotate on_due ask # this install
|
|
3414
|
+
<cli> agents rotate --persona planner after_compactions never
|
|
3415
|
+
<cli> agents rotate --persona planner -w notes after_compactions 5 # that persona in notes
|
|
3416
|
+
<cli> agents rotate --workspace notes on_due off
|
|
3417
|
+
<cli> agents rotate --service shop on_pr_merged false
|
|
3418
|
+
<cli> agents rotate --agent art --unset after_compactions
|
|
3419
|
+
<cli> agents rotate art --show # its values, and where each comes from
|
|
3420
|
+
<cli> agents keep <id> [--never] # Keep this conversation
|
|
3421
|
+
<cli> agents handoff <id> # Write handoff
|
|
3422
|
+
```
|
|
3423
|
+
|
|
3424
|
+
`agents rotate` and `agents keep` are refused inside an agent's session.
|
|
3425
|
+
den#4's `standing: false` still works: standing personas never rotate,
|
|
3426
|
+
unless a persona or agent override says otherwise. Set it per persona
|
|
3427
|
+
instead (`--persona planner after_compactions never`).
|
|
3284
3428
|
|
|
3285
3429
|
### Runtimes
|
|
3286
3430
|
|