@stratusagent/agents 0.11.8 → 0.11.10
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/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/tools/gateway-only.d.ts.map +1 -1
- package/dist/tools/gateway-only.js +2 -1
- package/dist/tools/gateway-only.js.map +1 -1
- package/dist/tools/message.d.ts +63 -1
- package/dist/tools/message.d.ts.map +1 -1
- package/dist/tools/message.js +147 -3
- package/dist/tools/message.js.map +1 -1
- package/package.json +2 -2
- package/skills/stratus/SKILL.md +8 -8
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export { type AgentRouteRule, type AgentRouter, createAgentRouter, createAgentTe
|
|
|
7
7
|
export { MEMORY_TOOL_NAME, createRememberTool, RECALL_TOOL_NAME, createRecallTool, FORGET_TOOL_NAME, createForgetTool, PIN_TOOL_NAME, createPinTool, type MemoryToolOptions, } from './tools/memory.ts';
|
|
8
8
|
export { DELEGATE_TOOL_NAME, DELEGATED_BY_METADATA_KEY, ROOT_SESSION_ID_METADATA_KEY, DELEGATION_DEPTH_METADATA_KEY, DELEGATED_SESSION_ID_MARKER, isDelegatedSession, delegatingSessionIdOf, outstandingDelegationFor, withoutDelegation, type DelegateDispatch, type DelegateToolOptions, createDelegateTool, } from './tools/delegate.ts';
|
|
9
9
|
export { SCHEDULE_EVERY_TOOL_NAME, SCHEDULE_AT_TOOL_NAME, SCHEDULE_LIST_TOOL_NAME, SCHEDULE_CANCEL_TOOL_NAME, createScheduleTools, } from './tools/schedule.ts';
|
|
10
|
-
export { MESSAGE_SEND_TOOL_NAME, type OutboundMessenger, createMessageSendTool, } from './tools/message.ts';
|
|
10
|
+
export { MESSAGE_SEND_TOOL_NAME, type OutboundMessenger, createMessageSendTool, MESSAGE_READ_TOOL_NAME, MESSAGE_READ_MAX_LIMIT, MESSAGE_READ_TEXT_BUDGET, type ConversationReader, createMessageReadTool, } from './tools/message.ts';
|
|
11
11
|
export { CREDENTIAL_REQUEST_TOOL_NAME, type CredentialRequester, createCredentialRequestTool, } from './tools/credentials.ts';
|
|
12
12
|
export { GATEWAY_ONLY_TOOL_NAMES } from './tools/gateway-only.ts';
|
|
13
13
|
export { loadStratusSkill, STRATUS_SKILL_PATH } from './builtin-skills.ts';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EACd,oBAAoB,EACpB,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,KAAK,gBAAgB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEjE,OAAO,EACL,iBAAiB,EACjB,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,SAAS,EACT,UAAU,GACX,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,4BAA4B,EAC5B,8BAA8B,EAC9B,KAAK,mBAAmB,EACxB,kBAAkB,EAClB,KAAK,4BAA4B,EACjC,KAAK,eAAe,EACpB,qBAAqB,EACrB,KAAK,cAAc,EACnB,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,KAAK,mBAAmB,EACxB,oBAAoB,EACpB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,aAAa,EACb,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,wBAAwB,EACxB,2BAA2B,EAC3B,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,iBAAiB,EACjB,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,KAAK,iBAAiB,GACvB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,4BAA4B,EAC5B,6BAA6B,EAC7B,2BAA2B,EAC3B,kBAAkB,EAClB,qBAAqB,EACrB,wBAAwB,EACxB,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,wBAAwB,EACxB,qBAAqB,EACrB,uBAAuB,EACvB,yBAAyB,EACzB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,sBAAsB,EACtB,KAAK,iBAAiB,EACtB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,4BAA4B,EAC5B,KAAK,mBAAmB,EACxB,2BAA2B,GAC5B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EACd,oBAAoB,EACpB,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,KAAK,gBAAgB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEjE,OAAO,EACL,iBAAiB,EACjB,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,SAAS,EACT,UAAU,GACX,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,4BAA4B,EAC5B,8BAA8B,EAC9B,KAAK,mBAAmB,EACxB,kBAAkB,EAClB,KAAK,4BAA4B,EACjC,KAAK,eAAe,EACpB,qBAAqB,EACrB,KAAK,cAAc,EACnB,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,KAAK,mBAAmB,EACxB,oBAAoB,EACpB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,aAAa,EACb,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,wBAAwB,EACxB,2BAA2B,EAC3B,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,iBAAiB,EACjB,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,KAAK,iBAAiB,GACvB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,4BAA4B,EAC5B,6BAA6B,EAC7B,2BAA2B,EAC3B,kBAAkB,EAClB,qBAAqB,EACrB,wBAAwB,EACxB,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,wBAAwB,EACxB,qBAAqB,EACrB,uBAAuB,EACvB,yBAAyB,EACzB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,sBAAsB,EACtB,KAAK,iBAAiB,EACtB,qBAAqB,EACrB,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,KAAK,kBAAkB,EACvB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,4BAA4B,EAC5B,KAAK,mBAAmB,EACxB,2BAA2B,GAC5B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -12,7 +12,7 @@ export { createAgentRouter, createAgentTeam, } from "./router.js";
|
|
|
12
12
|
export { MEMORY_TOOL_NAME, createRememberTool, RECALL_TOOL_NAME, createRecallTool, FORGET_TOOL_NAME, createForgetTool, PIN_TOOL_NAME, createPinTool, } from "./tools/memory.js";
|
|
13
13
|
export { DELEGATE_TOOL_NAME, DELEGATED_BY_METADATA_KEY, ROOT_SESSION_ID_METADATA_KEY, DELEGATION_DEPTH_METADATA_KEY, DELEGATED_SESSION_ID_MARKER, isDelegatedSession, delegatingSessionIdOf, outstandingDelegationFor, withoutDelegation, createDelegateTool, } from "./tools/delegate.js";
|
|
14
14
|
export { SCHEDULE_EVERY_TOOL_NAME, SCHEDULE_AT_TOOL_NAME, SCHEDULE_LIST_TOOL_NAME, SCHEDULE_CANCEL_TOOL_NAME, createScheduleTools, } from "./tools/schedule.js";
|
|
15
|
-
export { MESSAGE_SEND_TOOL_NAME, createMessageSendTool, } from "./tools/message.js";
|
|
15
|
+
export { MESSAGE_SEND_TOOL_NAME, createMessageSendTool, MESSAGE_READ_TOOL_NAME, MESSAGE_READ_MAX_LIMIT, MESSAGE_READ_TEXT_BUDGET, createMessageReadTool, } from "./tools/message.js";
|
|
16
16
|
export { CREDENTIAL_REQUEST_TOOL_NAME, createCredentialRequestTool, } from "./tools/credentials.js";
|
|
17
17
|
export { GATEWAY_ONLY_TOOL_NAMES } from "./tools/gateway-only.js";
|
|
18
18
|
export { loadStratusSkill, STRATUS_SKILL_PATH } from "./builtin-skills.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,wEAAwE;AACxE,wEAAwE;AACxE,mEAAmE;AACnE,mDAAmD;AAEnD,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EACd,oBAAoB,EACpB,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAyB,WAAW,EAAE,MAAM,aAAa,CAAC;AAEjE,OAAO,EACL,iBAAiB,EAGjB,SAAS,EACT,UAAU,GACX,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,4BAA4B,EAC5B,8BAA8B,EAE9B,kBAAkB,EAGlB,qBAAqB,EAErB,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EAEL,oBAAoB,EAGpB,aAAa,EACb,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,wBAAwB,EACxB,2BAA2B,EAG3B,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAGL,iBAAiB,EACjB,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,aAAa,GAEd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,4BAA4B,EAC5B,6BAA6B,EAC7B,2BAA2B,EAC3B,kBAAkB,EAClB,qBAAqB,EACrB,wBAAwB,EACxB,iBAAiB,EAGjB,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,wBAAwB,EACxB,qBAAqB,EACrB,uBAAuB,EACvB,yBAAyB,EACzB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,sBAAsB,EAEtB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,4BAA4B,EAE5B,2BAA2B,GAC5B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,wEAAwE;AACxE,wEAAwE;AACxE,mEAAmE;AACnE,mDAAmD;AAEnD,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EACd,oBAAoB,EACpB,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAyB,WAAW,EAAE,MAAM,aAAa,CAAC;AAEjE,OAAO,EACL,iBAAiB,EAGjB,SAAS,EACT,UAAU,GACX,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,4BAA4B,EAC5B,8BAA8B,EAE9B,kBAAkB,EAGlB,qBAAqB,EAErB,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EAEL,oBAAoB,EAGpB,aAAa,EACb,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,wBAAwB,EACxB,2BAA2B,EAG3B,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAGL,iBAAiB,EACjB,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,aAAa,GAEd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,4BAA4B,EAC5B,6BAA6B,EAC7B,2BAA2B,EAC3B,kBAAkB,EAClB,qBAAqB,EACrB,wBAAwB,EACxB,iBAAiB,EAGjB,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,wBAAwB,EACxB,qBAAqB,EACrB,uBAAuB,EACvB,yBAAyB,EACzB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,sBAAsB,EAEtB,qBAAqB,EACrB,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EAExB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,4BAA4B,EAE5B,2BAA2B,GAC5B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway-only.d.ts","sourceRoot":"","sources":["../../src/tools/gateway-only.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,uBAAuB,EAAE,SAAS,MAAM,
|
|
1
|
+
{"version":3,"file":"gateway-only.d.ts","sourceRoot":"","sources":["../../src/tools/gateway-only.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,uBAAuB,EAAE,SAAS,MAAM,EASpD,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CREDENTIAL_REQUEST_TOOL_NAME } from "./credentials.js";
|
|
2
2
|
import { DELEGATE_TOOL_NAME } from "./delegate.js";
|
|
3
|
-
import { MESSAGE_SEND_TOOL_NAME } from "./message.js";
|
|
3
|
+
import { MESSAGE_READ_TOOL_NAME, MESSAGE_SEND_TOOL_NAME } from "./message.js";
|
|
4
4
|
import { SCHEDULE_EVERY_TOOL_NAME, SCHEDULE_AT_TOOL_NAME, SCHEDULE_LIST_TOOL_NAME, SCHEDULE_CANCEL_TOOL_NAME, } from "./schedule.js";
|
|
5
5
|
/**
|
|
6
6
|
* The tools only a running gateway registers. Each needs the dispatcher,
|
|
@@ -25,6 +25,7 @@ export const GATEWAY_ONLY_TOOL_NAMES = [
|
|
|
25
25
|
SCHEDULE_LIST_TOOL_NAME,
|
|
26
26
|
SCHEDULE_CANCEL_TOOL_NAME,
|
|
27
27
|
MESSAGE_SEND_TOOL_NAME,
|
|
28
|
+
MESSAGE_READ_TOOL_NAME,
|
|
28
29
|
DELEGATE_TOOL_NAME,
|
|
29
30
|
CREDENTIAL_REQUEST_TOOL_NAME,
|
|
30
31
|
];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway-only.js","sourceRoot":"","sources":["../../src/tools/gateway-only.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"gateway-only.js","sourceRoot":"","sources":["../../src/tools/gateway-only.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAC9E,OAAO,EACL,wBAAwB,EACxB,qBAAqB,EACrB,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,eAAe,CAAC;AAEvB;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAsB;IACxD,wBAAwB;IACxB,qBAAqB;IACrB,uBAAuB;IACvB,yBAAyB;IACzB,sBAAsB;IACtB,sBAAsB;IACtB,kBAAkB;IAClB,4BAA4B;CAC7B,CAAC"}
|
package/dist/tools/message.d.ts
CHANGED
|
@@ -5,12 +5,20 @@ export declare const MESSAGE_SEND_TOOL_NAME = "message.send";
|
|
|
5
5
|
* Delivers one outbound message through the agent's channel. The gateway
|
|
6
6
|
* implements it over the channel contract's `resolveOutbound`; rejecting is
|
|
7
7
|
* the way to say a destination cannot be served.
|
|
8
|
+
*
|
|
9
|
+
* Resolves with the channel-native id of the message it posted when the
|
|
10
|
+
* channel reports one (Slack: its `ts`), which is what lets an agent reply
|
|
11
|
+
* under its own post later — the id is the thread to name.
|
|
8
12
|
*/
|
|
9
13
|
export type OutboundMessenger = (input: {
|
|
10
14
|
agentId: string;
|
|
11
15
|
destination: ScheduleDestination;
|
|
12
16
|
text: string;
|
|
13
|
-
|
|
17
|
+
/** Channel-native id of the message to reply under, for a threaded post. */
|
|
18
|
+
thread?: string;
|
|
19
|
+
}) => Promise<{
|
|
20
|
+
id?: string;
|
|
21
|
+
} | void>;
|
|
14
22
|
/**
|
|
15
23
|
* Post to a channel or DM outside the current conversation — what makes a
|
|
16
24
|
* scheduled turn observable.
|
|
@@ -23,4 +31,58 @@ export type OutboundMessenger = (input: {
|
|
|
23
31
|
* schedule was approved with that destination.
|
|
24
32
|
*/
|
|
25
33
|
export declare const createMessageSendTool: (send: OutboundMessenger) => Tool;
|
|
34
|
+
export declare const MESSAGE_READ_TOOL_NAME = "message.read";
|
|
35
|
+
/** The most messages one `message.read` call returns. */
|
|
36
|
+
export declare const MESSAGE_READ_MAX_LIMIT = 200;
|
|
37
|
+
/**
|
|
38
|
+
* The most a call returns, in characters of the serialized messages: text,
|
|
39
|
+
* names, file names, and ids together. A count alone does not bound a
|
|
40
|
+
* read: fifty long posts can outgrow a model's context, and the result is
|
|
41
|
+
* kept in the transcript and sent on every later turn. A read that reaches
|
|
42
|
+
* it stops at the last whole message that fit and says `more`, so the
|
|
43
|
+
* agent pages on with `before`/`after`.
|
|
44
|
+
*/
|
|
45
|
+
export declare const MESSAGE_READ_TEXT_BUDGET = 40000;
|
|
46
|
+
/**
|
|
47
|
+
* Reads one conversation, or one thread in it, through the agent's own
|
|
48
|
+
* channel app. The gateway implements it over the channel contract's
|
|
49
|
+
* `readConversation`, structurally mirrored here the way `OutboundMessenger`
|
|
50
|
+
* mirrors `resolveOutbound`; rejecting is how a channel says it will not.
|
|
51
|
+
*/
|
|
52
|
+
export type ConversationReader = (input: {
|
|
53
|
+
agentId: string;
|
|
54
|
+
source: ScheduleDestination;
|
|
55
|
+
thread?: string;
|
|
56
|
+
after?: string;
|
|
57
|
+
before?: string;
|
|
58
|
+
limit: number;
|
|
59
|
+
}) => Promise<{
|
|
60
|
+
messages: Array<{
|
|
61
|
+
id: string;
|
|
62
|
+
author: string;
|
|
63
|
+
authorName?: string;
|
|
64
|
+
text: string;
|
|
65
|
+
at?: string;
|
|
66
|
+
thread?: string;
|
|
67
|
+
replies?: number;
|
|
68
|
+
files?: string[];
|
|
69
|
+
}>;
|
|
70
|
+
more: boolean;
|
|
71
|
+
}>;
|
|
72
|
+
/**
|
|
73
|
+
* Read a conversation's recent messages, or one thread — so an agent can
|
|
74
|
+
* catch up on a channel it was not mentioned in.
|
|
75
|
+
*
|
|
76
|
+
* `gated`, like `message.send`: what a channel says is the people in it's,
|
|
77
|
+
* and an agent talking somewhere else would carry it there. Judged by its
|
|
78
|
+
* source (`destinationFor`) for the same reason as a send: a durable
|
|
79
|
+
* per-tool grant would be a standing yes to every conversation the app is
|
|
80
|
+
* in, which anyone who can talk to the agent could then have it quote
|
|
81
|
+
* anywhere. So **Always allow** lasts for this session only, and a
|
|
82
|
+
* schedule approved with a destination may read that one conversation
|
|
83
|
+
* unattended. The channel's own rule decides which conversations are
|
|
84
|
+
* readable at all. Output is `external`: the messages are written by
|
|
85
|
+
* whoever is in the conversation, not by the operator.
|
|
86
|
+
*/
|
|
87
|
+
export declare const createMessageReadTool: (read: ConversationReader) => Tool;
|
|
26
88
|
//# sourceMappingURL=message.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../src/tools/message.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAuB,IAAI,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EACL,KAAK,mBAAmB,EAIzB,MAAM,iBAAiB,CAAC;AAEzB,eAAO,MAAM,sBAAsB,iBAAiB,CAAC;AAErD
|
|
1
|
+
{"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../../src/tools/message.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAuB,IAAI,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EACL,KAAK,mBAAmB,EAIzB,MAAM,iBAAiB,CAAC;AAEzB,eAAO,MAAM,sBAAsB,iBAAiB,CAAC;AAErD;;;;;;;;GAQG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,EAAE;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,mBAAmB,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,KAAK,OAAO,CAAC;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAAC;AAEtC;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB,GAAI,MAAM,iBAAiB,KAAG,IAuD9D,CAAC;AAEH,eAAO,MAAM,sBAAsB,iBAAiB,CAAC;AAErD,yDAAyD;AACzD,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAE1C;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAG/C;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf,KAAK,OAAO,CAAC;IACZ,QAAQ,EAAE,KAAK,CAAC;QACd,EAAE,EAAE,MAAM,CAAC;QACX,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC;QACb,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;KAClB,CAAC,CAAC;IACH,IAAI,EAAE,OAAO,CAAC;CACf,CAAC,CAAC;AAaH;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,qBAAqB,GAAI,MAAM,kBAAkB,KAAG,IAgF/D,CAAC"}
|
package/dist/tools/message.js
CHANGED
|
@@ -13,7 +13,10 @@ export const MESSAGE_SEND_TOOL_NAME = 'message.send';
|
|
|
13
13
|
*/
|
|
14
14
|
export const createMessageSendTool = (send) => ({
|
|
15
15
|
name: MESSAGE_SEND_TOOL_NAME,
|
|
16
|
-
description: 'Send a message to a channel or DM you are not currently talking in
|
|
16
|
+
description: 'Send a message to a channel or DM you are not currently talking in, at the top level or as a reply in one of its threads. '
|
|
17
|
+
+ 'Returns the posted message\'s id, and the thread to name to reply under it: '
|
|
18
|
+
+ 'pass that returned thread (never a reply\'s id) to every later send in the same thread. '
|
|
19
|
+
+ 'Scheduled turns may post to their schedule\'s approved destination without asking; anywhere else needs approval.',
|
|
17
20
|
risk: 'gated',
|
|
18
21
|
parameters: {
|
|
19
22
|
type: 'object',
|
|
@@ -23,6 +26,10 @@ export const createMessageSendTool = (send) => ({
|
|
|
23
26
|
description: 'Where to post: the channel kind plus the channel-native conversation id.',
|
|
24
27
|
},
|
|
25
28
|
text: { type: 'string', description: 'The message text.' },
|
|
29
|
+
thread: {
|
|
30
|
+
type: 'string',
|
|
31
|
+
description: 'The id of a message in that conversation to reply under (for Slack, its ts, e.g. 1791332967.606559). Omit to post at the top level.',
|
|
32
|
+
},
|
|
26
33
|
},
|
|
27
34
|
required: ['destination', 'text'],
|
|
28
35
|
},
|
|
@@ -39,8 +46,145 @@ export const createMessageSendTool = (send) => ({
|
|
|
39
46
|
if (!text) {
|
|
40
47
|
throw new Error('message.send requires a non-empty "text".');
|
|
41
48
|
}
|
|
42
|
-
|
|
43
|
-
|
|
49
|
+
const thread = optionalId(input, 'thread', MESSAGE_SEND_TOOL_NAME);
|
|
50
|
+
const posted = await send({
|
|
51
|
+
agentId: session.agent.id,
|
|
52
|
+
destination,
|
|
53
|
+
text,
|
|
54
|
+
...(thread !== undefined ? { thread } : {}),
|
|
55
|
+
});
|
|
56
|
+
const id = posted && typeof posted.id === 'string' && posted.id.length > 0 ? posted.id : undefined;
|
|
57
|
+
// The thread a reply to this post names: the root it went under, or,
|
|
58
|
+
// for a top-level post, the post itself. Always the root, because a
|
|
59
|
+
// reply's own id is not a thread to Slack — chaining sends through
|
|
60
|
+
// each reply's id would leave the thread after the second one.
|
|
61
|
+
const root = thread ?? id;
|
|
62
|
+
return {
|
|
63
|
+
sent: true,
|
|
64
|
+
destination: canonicalDestination(destination),
|
|
65
|
+
...(id !== undefined ? { id } : {}),
|
|
66
|
+
...(root !== undefined ? { thread: root } : {}),
|
|
67
|
+
};
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
export const MESSAGE_READ_TOOL_NAME = 'message.read';
|
|
71
|
+
/** The most messages one `message.read` call returns. */
|
|
72
|
+
export const MESSAGE_READ_MAX_LIMIT = 200;
|
|
73
|
+
const MESSAGE_READ_DEFAULT_LIMIT = 50;
|
|
74
|
+
/**
|
|
75
|
+
* The most a call returns, in characters of the serialized messages: text,
|
|
76
|
+
* names, file names, and ids together. A count alone does not bound a
|
|
77
|
+
* read: fifty long posts can outgrow a model's context, and the result is
|
|
78
|
+
* kept in the transcript and sent on every later turn. A read that reaches
|
|
79
|
+
* it stops at the last whole message that fit and says `more`, so the
|
|
80
|
+
* agent pages on with `before`/`after`.
|
|
81
|
+
*/
|
|
82
|
+
export const MESSAGE_READ_TEXT_BUDGET = 40_000;
|
|
83
|
+
const TRUNCATED_MARK = ' [... the rest of this message is not shown]';
|
|
84
|
+
const optionalId = (input, key, tool = MESSAGE_READ_TOOL_NAME) => {
|
|
85
|
+
const value = input[key];
|
|
86
|
+
if (value === undefined || value === null) {
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
if (typeof value !== 'string' || value.trim().length === 0) {
|
|
90
|
+
throw new Error(`${tool}: "${key}" must be a non-empty string when given.`);
|
|
91
|
+
}
|
|
92
|
+
return value.trim();
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Read a conversation's recent messages, or one thread — so an agent can
|
|
96
|
+
* catch up on a channel it was not mentioned in.
|
|
97
|
+
*
|
|
98
|
+
* `gated`, like `message.send`: what a channel says is the people in it's,
|
|
99
|
+
* and an agent talking somewhere else would carry it there. Judged by its
|
|
100
|
+
* source (`destinationFor`) for the same reason as a send: a durable
|
|
101
|
+
* per-tool grant would be a standing yes to every conversation the app is
|
|
102
|
+
* in, which anyone who can talk to the agent could then have it quote
|
|
103
|
+
* anywhere. So **Always allow** lasts for this session only, and a
|
|
104
|
+
* schedule approved with a destination may read that one conversation
|
|
105
|
+
* unattended. The channel's own rule decides which conversations are
|
|
106
|
+
* readable at all. Output is `external`: the messages are written by
|
|
107
|
+
* whoever is in the conversation, not by the operator.
|
|
108
|
+
*/
|
|
109
|
+
export const createMessageReadTool = (read) => ({
|
|
110
|
+
name: MESSAGE_READ_TOOL_NAME,
|
|
111
|
+
description: 'Read recent messages in a channel your app is a member of, or one thread in it. '
|
|
112
|
+
+ 'Without thread: the top level, newest first. With thread: that thread\'s root and replies, oldest first. '
|
|
113
|
+
+ 'For Slack, ids are channel ids and message ts values; a permalink '
|
|
114
|
+
+ '…/archives/C0123456789/p1791332967606559 is channel C0123456789 and message 1791332967.606559, '
|
|
115
|
+
+ 'and a thread_ts in the link is the thread to read. '
|
|
116
|
+
+ 'When more is true, page on with before (top level) or after (thread) set to the last id returned.',
|
|
117
|
+
risk: 'gated',
|
|
118
|
+
outputTrust: 'external',
|
|
119
|
+
parameters: {
|
|
120
|
+
type: 'object',
|
|
121
|
+
properties: {
|
|
122
|
+
source: {
|
|
123
|
+
...DESTINATION_PARAMETER,
|
|
124
|
+
description: 'The conversation to read: the channel kind plus the channel-native conversation id.',
|
|
125
|
+
},
|
|
126
|
+
thread: { type: 'string', description: 'The root message id of a thread to read instead of the top level.' },
|
|
127
|
+
after: { type: 'string', description: 'Only messages after this message id, exclusive.' },
|
|
128
|
+
before: { type: 'string', description: 'Only messages before this message id, exclusive.' },
|
|
129
|
+
limit: { type: 'integer', description: `How many messages, ${MESSAGE_READ_DEFAULT_LIMIT} by default, at most ${MESSAGE_READ_MAX_LIMIT}.` },
|
|
130
|
+
},
|
|
131
|
+
required: ['source'],
|
|
132
|
+
},
|
|
133
|
+
destinationFor(input) {
|
|
134
|
+
const source = parseDestinationInput(input.source);
|
|
135
|
+
return source ? canonicalDestination(source) : undefined;
|
|
136
|
+
},
|
|
137
|
+
async execute(input, session) {
|
|
138
|
+
const source = parseDestinationInput(input.source);
|
|
139
|
+
if (!source) {
|
|
140
|
+
throw new Error('message.read requires "source" as { channel, to } with non-empty strings.');
|
|
141
|
+
}
|
|
142
|
+
const thread = optionalId(input, 'thread');
|
|
143
|
+
const after = optionalId(input, 'after');
|
|
144
|
+
const before = optionalId(input, 'before');
|
|
145
|
+
const limit = typeof input.limit === 'number' && Number.isInteger(input.limit) && input.limit > 0
|
|
146
|
+
? Math.min(input.limit, MESSAGE_READ_MAX_LIMIT)
|
|
147
|
+
: MESSAGE_READ_DEFAULT_LIMIT;
|
|
148
|
+
const result = await read({
|
|
149
|
+
agentId: session.agent.id,
|
|
150
|
+
source,
|
|
151
|
+
limit,
|
|
152
|
+
...(thread !== undefined ? { thread } : {}),
|
|
153
|
+
...(after !== undefined ? { after } : {}),
|
|
154
|
+
...(before !== undefined ? { before } : {}),
|
|
155
|
+
});
|
|
156
|
+
const messages = [];
|
|
157
|
+
let used = 0;
|
|
158
|
+
let more = result.more;
|
|
159
|
+
for (const message of result.messages) {
|
|
160
|
+
const size = JSON.stringify(message).length;
|
|
161
|
+
if (used + size <= MESSAGE_READ_TEXT_BUDGET) {
|
|
162
|
+
messages.push({ ...message });
|
|
163
|
+
used += size;
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
// One message bigger than the whole budget is cut rather than
|
|
167
|
+
// dropped, or the read could never get past it. Its file list goes
|
|
168
|
+
// too, said by count, since a list can be as long as any text.
|
|
169
|
+
if (messages.length === 0) {
|
|
170
|
+
const { files, ...rest } = message;
|
|
171
|
+
const cut = {
|
|
172
|
+
...rest,
|
|
173
|
+
text: message.text.slice(0, MESSAGE_READ_TEXT_BUDGET / 2) + TRUNCATED_MARK,
|
|
174
|
+
...(files && files.length > 0 ? { files: [`${files.length} files, not listed`] } : {}),
|
|
175
|
+
};
|
|
176
|
+
messages.push(cut);
|
|
177
|
+
}
|
|
178
|
+
more = true;
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
source: canonicalDestination(source),
|
|
183
|
+
...(thread !== undefined ? { thread } : {}),
|
|
184
|
+
count: messages.length,
|
|
185
|
+
more,
|
|
186
|
+
messages,
|
|
187
|
+
};
|
|
44
188
|
},
|
|
45
189
|
});
|
|
46
190
|
//# sourceMappingURL=message.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message.js","sourceRoot":"","sources":["../../src/tools/message.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,CAAC,MAAM,sBAAsB,GAAG,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"message.js","sourceRoot":"","sources":["../../src/tools/message.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stratusagent/agents",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.10",
|
|
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.11.
|
|
21
|
+
"@stratusagent/core": "0.11.10"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@types/node": "^24.6.0",
|
package/skills/stratus/SKILL.md
CHANGED
|
@@ -54,7 +54,7 @@ The config decides which provider and model run, which plugins load, and how app
|
|
|
54
54
|
|
|
55
55
|
Which provider and model a turn uses: for `stratus run` and `stratus chat`, command-line flags beat `STRATUS_*` environment variables, which beat the soul's `provider`/`model`, which beat the file. Under `stratus serve` a soul's `provider`/`model` beats all of those, because each agent in a roster runs on its own. A changed `provider` or `model` in the config reaches the next turn without a restart.
|
|
56
56
|
|
|
57
|
-
A project-local `stratus.config.json` ships inside repositories, so it is **untrusted**. It cannot set `plugins`, `approvals`, `principals`, `slack`, `api`, `maxTurns`, `apiKeyEnv`, `soul`, `systemPrompt`, `executor`, or `memoryStore`. Those are read only from `~/.stratus/config.json` or a file named by `--config` or `STRATUS_CONFIG`. A project-local file that sets one of them has it ignored, with a warning. For `principals`, `slack`, `maxTurns`, `executor`, and `memoryStore` the daemon uses `~/.stratus/config.json`'s instead; for `plugins`, `approvals`, and `api` it uses none. A project-local file that says nothing about one of those eight leaves the global one in force.
|
|
57
|
+
A project-local `stratus.config.json` ships inside repositories, so it is **untrusted**. It cannot set `plugins`, `approvals`, `principals`, `slack`, `api`, `maxTurns`, `agentMaxTurns`, `autoContinue`, `apiKeyEnv`, `soul`, `systemPrompt`, `executor`, or `memoryStore`. Those are read only from `~/.stratus/config.json` or a file named by `--config` or `STRATUS_CONFIG`. A project-local file that sets one of them has it ignored, with a warning. For `principals`, `slack`, `maxTurns`, `executor`, and `memoryStore` the daemon uses `~/.stratus/config.json`'s instead; for `plugins`, `approvals`, and `api` it uses none. A project-local file that says nothing about one of those eight leaves the global one in force.
|
|
58
58
|
|
|
59
59
|
When a setting "isn't taking", these say why:
|
|
60
60
|
|
|
@@ -103,9 +103,9 @@ When a stored key "isn't found", check in this order:
|
|
|
103
103
|
|
|
104
104
|
## Tools, plugins, and approvals
|
|
105
105
|
|
|
106
|
-
- **Built in everywhere:** `memory.*` (remember, recall, forget, pin) and `skill.read`, which every agent has because this skill counts. **Only under the daemon:** `schedule.*`, `message.send`, `agent.delegate`, and `credential.request`, so `stratus run` and `stratus chat` cannot call them.
|
|
106
|
+
- **Built in everywhere:** `memory.*` (remember, recall, forget, pin) and `skill.read`, which every agent has because this skill counts. **Only under the daemon:** `schedule.*`, `message.send`, `message.read`, `agent.delegate`, and `credential.request`, so `stratus run` and `stratus chat` cannot call them.
|
|
107
107
|
- **Plugins** add the rest, each installed with `npm install -g <package>` and enabled under `plugins` in the trusted config:
|
|
108
|
-
- `@stratusagent/tool-fs` gives `fs.*`, inside configured roots only, so with no roots there is no filesystem. Roots go in `"@stratusagent/tool-fs": { "enabled": true, "roots": ["~/notes"] }`, or under `"agents": { "<id>": { "roots": [...] } }` for one agent.
|
|
108
|
+
- `@stratusagent/tool-fs` gives `fs.*`, inside configured roots only, so with no roots there is no filesystem. Whatever the roots, `fs.*` never reaches `~/.stratus` outside the agents' workspaces (credentials, config, logs, sessions, memories, souls, skills, grants), so a refusal there is by design, not a roots problem. Roots go in `"@stratusagent/tool-fs": { "enabled": true, "roots": ["~/notes"] }`, or under `"agents": { "<id>": { "roots": [...] } }` for one agent.
|
|
109
109
|
- `@stratusagent/tool-shell` gives `shell.run`.
|
|
110
110
|
- `@stratusagent/tool-web` gives `web.fetch`. `web.search` is not first-party: it comes from a search backend plugin someone else publishes, and needs `search.apiKey`.
|
|
111
111
|
- `@stratusagent/tool-browser` gives `browser.*`.
|
|
@@ -114,10 +114,10 @@ When a stored key "isn't found", check in this order:
|
|
|
114
114
|
- Enabled is not granted: your soul's `tools:` must also cover a plugin's tools. `stratus plugins` walks the whole chain for each tool (installed, enabled, granted to which agents, and what approvals do with a call), so it answers "why can't you use X" in one command.
|
|
115
115
|
- **Risk.** Every tool is `safe`, `gated`, or `dangerous`. The daemon runs `safe` tools unattended, among them `memory.*`, `skill.read`, `credential.request`, `agent.delegate`, `schedule.list`, `schedule.cancel`, and `fs.read`, `fs.list`, and `fs.search`. Gated tools include:
|
|
116
116
|
- `web.fetch`, `fs.write`, `shell.run`, `browser.*`, and `mcp.*`;
|
|
117
|
-
- `schedule.every`, `schedule.at`, and `message.
|
|
117
|
+
- `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`);
|
|
118
118
|
- every third-party tool, `web.search` included.
|
|
119
119
|
- 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.
|
|
120
|
-
- 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`). For `browser.act` it is an approved site, and for other gated tools a standing grant.
|
|
120
|
+
- 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.
|
|
121
121
|
- 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.
|
|
122
122
|
- **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.
|
|
123
123
|
- `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.
|
|
@@ -134,11 +134,11 @@ When a stored key "isn't found", check in this order:
|
|
|
134
134
|
|
|
135
135
|
- **One Slack app per agent**, each with its own tokens, connected over Socket Mode, so no public address is needed. Set up with `stratus setup` → Channels, which prints the app manifest and checks the tokens.
|
|
136
136
|
- **"Sending messages to this app has been turned off"** in a DM is a Slack setting, not Stratus. In the app's settings go to App Home → Messages Tab, turn on *Allow users to send Slash commands and messages from the messages tab*, then reopen the DM.
|
|
137
|
-
- **What reaches you.** In a DM, every message. In a channel, a message that mentions you, which starts a thread. In that thread, what happens to a reply that does not name you depends on your soul's `listens:`:
|
|
137
|
+
- **What reaches you.** In a DM, every message. In a channel, a message that mentions you, which starts a thread. In a channel listed under your `slack.agents.<id>.homeChannels` in the trusted config, every new top-level message too, unless it names another agent (restart the daemon after changing it). In that thread, what happens to a reply that does not name you depends on your soul's `listens:`:
|
|
138
138
|
- `thread`, the default, hears every such reply.
|
|
139
139
|
- `mentions` answers only messages that name you, though it still hears the rest of the thread.
|
|
140
140
|
- `judge` hears them and decides whether to answer.
|
|
141
|
-
- With several agents in one thread, an untagged reply goes to whoever spoke last.
|
|
141
|
+
- 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.
|
|
142
142
|
- **Answering only when mentioned**, never to thread replies, has three causes, and they are worth checking in this order:
|
|
143
143
|
1. `listens: mentions` in your soul.
|
|
144
144
|
2. Another agent spoke last in that thread.
|
|
@@ -167,7 +167,7 @@ When a stored key "isn't found", check in this order:
|
|
|
167
167
|
|
|
168
168
|
## When a reply stops or changes model
|
|
169
169
|
|
|
170
|
-
- **"Out of steps."** One message may take `maxTurns` rounds of tool calls (default 40, set in the trusted config, restart to change). Past that you are told you are out of steps, get one last call with no tools, and answer with what you did and what is left. Replying "continue" carries on with a fresh allowance. An agent that does long work should have it
|
|
170
|
+
- **"Out of steps."** One message may take `maxTurns` rounds of tool calls (default 40, set in the trusted config, restart to change). Past that you are told you are out of steps, get one last call with no tools, and answer with what you did and what is left. Replying "continue" carries on with a fresh allowance. An agent that does long work should have its own budget raised with `agentMaxTurns: { "<id>": 300 }` in the trusted config (restart to change), which leaves the rest of the fleet on `maxTurns`. With `autoContinue: { "<id>": true }` (or a number, to cap it) an agent is given another budget instead of stopping to ask, until its work is done, its cap is reached, or someone sends it another message meanwhile. Under a kernel-driven provider (Anthropic, OpenAI-compatible), it also stops when stuck on a repeating failure; the `claude-code` runtime runs its own loop and does not have that check, so an uncapped claude-code agent relies on the cap or a new message to stop. It applies to the built-in model loop and the `claude-code` runtime, not yet to `codex`.
|
|
171
171
|
- **Stopped with no reply.** On a provider that streams (Anthropic, Codex, and plugin providers that say they stream), the daemon's watchdog aborts a turn when the model reports nothing for `--idle-timeout` seconds (default 120). On one that does not, such as an OpenAI-compatible endpoint, there is no watchdog, and a silent request ends only when the provider's own request fails or times out, so `--idle-timeout` neither explains nor fixes it. The session ends failed, with `no activity for 120000ms`, and `stratus logs --agent <id>` names the last thing it heard. A tool that is running, or a call waiting on an approval, never trips it.
|
|
172
172
|
- **Cut off at the output cap.** A reply longer than the model may write in one turn fails rather than being posted half-finished, and the error says so. With an Anthropic API key that cap is `maxTokens` in the config (default 16000); a Claude subscription run does not take that setting, so raising it changes nothing there. Offer a shorter answer, or, on an API key, ask for the cap to be raised. Never ask for a longer timeout.
|
|
173
173
|
- **Answering on another model.** When the configured model fails a request and a `fallbackModel` is set, that conversation switches to the fallback and stays on it, even across restarts, so it never silently swaps back. Not every failure switches: a conversation too long for the window is trimmed and retried on the same model, a cancelled turn just stops, and a Codex or Claude subscription turn that fails after its tools already ran surfaces the error instead, since a retry elsewhere would run them twice. Those leave the conversation on the configured model, with nothing to roll over. Your instructions say when you are on the fallback. `stratus logs` shows the error that caused the switch, and `stratus session rollover <session id>` starts the conversation over on the configured model.
|