@stratusagent/agents 0.12.1 → 0.12.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stratusagent/agents",
3
- "version": "0.12.1",
3
+ "version": "0.12.3",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -18,7 +18,7 @@
18
18
  "node": ">=22.13 <23 || >=23.4"
19
19
  },
20
20
  "dependencies": {
21
- "@stratusagent/core": "0.12.1"
21
+ "@stratusagent/core": "0.12.3"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@types/node": "^24.6.0",
@@ -34,7 +34,9 @@ Everything is under `~/.stratus/` on the daemon's machine:
34
34
  | `gateway.json`, `gateway-token` | Where the control API is listening, and its bearer token. `0600` |
35
35
  | `stratusd.lock` | The running daemon's claim on this home: one daemon per home |
36
36
 
37
- Deleting a soul file takes the agent off the roster but keeps its `agents/<id>/` state, its standing approvals included (a new agent given the same id inherits them), and its schedules in `fleet.db`. Deleting `agents/<id>/` erases its history, memories, grants, and files.
37
+ Souls and workspaces are normally links into a visible agents folder in the home directory: `agents/<id>.md` points to `~/Agents/<id>/soul.md` and `agents/<id>/workspace` to `~/Agents/<id>/workspace/`. That is where a person edits a soul or finds an agent's files. The folder is `~/Stratus` instead when `~/Agents` already belonged to something else. There is none (everything stays in `~/.stratus/agents/`) when both names are taken, when `~/.stratus` is on a different disk from the home directory (the Docker image), or with `STRATUS_AGENTS_DIR=off`; `STRATUS_AGENTS_DIR=<path>` chooses one outright, and `stratus doctor` names the one in use. A soul or workspace still kept as a real file under `~/.stratus/agents/` is moved there by the next `stratus serve` or `stratus update`. `fs.*` refuses every soul, under either name.
38
+
39
+ Deleting a soul file takes the agent off the roster but keeps its `agents/<id>/` state, its standing approvals included (a new agent given the same id inherits them), and its schedules in `fleet.db`. Deleting `agents/<id>/` erases its history, memories, and grants; the files in `~/Agents/<id>/workspace/` stay until that folder is deleted too. Deleting or renaming `~/Agents/<id>/` takes the agent off the roster (its state is untouched) until the folder is put back.
38
40
 
39
41
  ## Your soul
40
42
 
@@ -118,8 +120,8 @@ When a stored key "isn't found", check in this order:
118
120
  - `schedule.every`, `schedule.at`, `message.send`, and `message.read` (which reads a channel your Slack app is in, never a DM, and labels what it returns `external`);
119
121
  - every third-party tool, `web.search` included.
120
122
  - What happens to a gated call depends on the approvals mode. Under `headless` (the default) it is refused. Under `remote` the people in `approvals.slackApprovers` are asked in Slack (or through the control API's `/approvals`) with **Allow once**, **Always allow**, and **Deny**. Under `remote` with nobody to ask, it is refused too.
121
- - Either way, what was already approved still runs unattended. For `shell.run` that is a command scope plus a built-in safe list of read-only commands (`git status`, `git log`, `git diff`, `pwd`, and a few more; not `ls`), plus `grep`, `head`, `tail`, `wc`, `sort`, and `uniq` as filters that are never handed a path. A pipeline runs unattended when every stage would on its own (`git log | grep fix | head -n 20`); `||`, `;`, `&`, redirection, and `$( )` still mean asking. For `browser.act` and `web.fetch` it is an approved site (a `web.fetch` redirect to another site is reported as `redirectedTo`, not followed), and for other gated tools a standing grant.
122
- - The exception is `approvals.externalContent: "gate"`, set for every agent or per agent under `approvals.agents.<id>`. Once your conversation has read external content (`web.fetch`, `browser.*`, `web.search`, or an `mcp.*` tool), no grant applies for the rest of it: every gated call is asked or, headless, refused, and **Always allow** is not offered. `safe` tools, the built-in read-only commands, and a schedule's pre-authorized destination still run. Your next conversation starts with its grants again.
123
+ - Either way, what was already approved still runs unattended. For `shell.run` that is a command scope plus a short built-in safe list (`pwd`, `whoami`, and `uname`; not `ls`, and no `git` command, not even `git status`, since git runs programs a repository names), plus `grep`, `head`, `tail`, `wc`, `sort`, and `uniq` as filters that are never handed a path. **Always allow** on a git command keeps that scope. A pipeline runs unattended when every stage would on its own (with a `git log` scope approved, `git log | grep fix | head -n 20`); `||`, `;`, `&`, redirection, and `$( )` still mean asking. For `browser.act` and `web.fetch` it is an approved site (a `web.fetch` redirect to another site is reported as `redirectedTo`, not followed), and for other gated tools a standing grant.
124
+ - The exception is `approvals.externalContent: "gate"`, set for every agent or per agent under `approvals.agents.<id>`. Once your conversation has read external content (`web.fetch`, `browser.*`, `web.search`, or an `mcp.*` tool), no grant applies for the rest of it: every gated call is asked or, headless, refused, and **Always allow** is not offered. `safe` tools, the built-in safe list (`pwd`, `whoami`, `uname`, and the stdin filters), and a schedule's pre-authorized destination still run. Your next conversation starts with its grants again.
123
125
  - **Always allow** writes one of those to `agents/<id>/whitelist.json`, except for a tool that names a destination, such as `message.send`, where it lasts for the conversation. A `dangerous` call is never offered it.
124
126
  - `stratus grants <id>` lists the grants, and `stratus grants revoke <id> --tool|--scope|--origin` takes one back. There is no command to add one: a headless daemon asks nobody, so it never creates a grant, and a call nobody has approved yet needs `remote` mode first.
125
127
 
@@ -142,7 +144,7 @@ When a stored key "isn't found", check in this order:
142
144
  - With several agents in one thread, an untagged reply goes to whoever spoke last. Mentioned partway into a thread, your first turn opens with what was said before it (the parent and the newest earlier messages, marked as overheard). Mentioned at the top of a channel, it opens with the channel's 20 most recent messages. Both need the Slack app's history scopes. Without them you hear the thread from the mention onward only. A stranger or another bot among those earlier messages lowers the conversation's trust as if they had spoken to you.
143
145
  - **Answering only when mentioned**, never to thread replies, has three causes, and they are worth checking in this order:
144
146
  1. `listens: mentions` in your soul.
145
- 2. Another agent spoke last in that thread.
147
+ 2. Another agent spoke last in that thread. That includes an agent on another daemon or machine, and any other app's bot that posted there.
146
148
  3. The app is missing the history scopes (`channels:history`, `groups:history`, `mpim:history`) and their `message.*` events, which means adding them and reinstalling the app.
147
149
 
148
150
  Not answering at all also happens when the daemon is down, the app was removed from the channel, or `admit: "principals"` turned the person away.