@stratusagent/channels 0.11.6 → 0.11.7

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 CHANGED
@@ -1,4 +1,4 @@
1
- import type { AgentDefinition, ApprovalAnswer, EventBus, ImageAttachment, JsonObject, Session } from '@stratusagent/core';
1
+ import type { AgentDefinition, ApprovalAnswer, CredentialScope, EventBus, ImageAttachment, JsonObject, Session, TrustLevel } from '@stratusagent/core';
2
2
  /**
3
3
  * One message arriving from a chat platform, normalized. Adapters translate
4
4
  * their platform's event shape into this before anything else happens.
@@ -33,15 +33,31 @@ export interface OutboundMessageRef {
33
33
  ts: string;
34
34
  }
35
35
  /**
36
- * The write side of one conversation. Streaming replies are the
37
- * placeholder-then-edit pattern: post once, edit as fragments arrive,
38
- * finalize with the full text.
36
+ * The write side of one conversation. `post` is the whole of what every
37
+ * caller needs: the gateway's `message.send` and schedule delivery only ever
38
+ * post. Everything else is a capability a platform may not have, so it is
39
+ * optional, and a caller that wants it checks for the method rather than
40
+ * assuming it — the way `ChannelAdapter.resolveOutbound` works.
41
+ *
42
+ * Streaming by placeholder-then-edit (post once, edit as fragments arrive,
43
+ * finalize with the full text) is how a platform with editable messages
44
+ * shows a reply forming. A text-message channel has no such thing — an
45
+ * iMessage edit is visibly marked and capped — so it posts the finished
46
+ * reply instead.
39
47
  */
40
48
  export interface OutboundConnection {
41
49
  post(text: string): Promise<OutboundMessageRef>;
42
- edit(ref: OutboundMessageRef, text: string): Promise<void>;
43
- /** Uploads a local file into the conversation (tool outputs, screenshots). */
44
- upload(filePath: string, title?: string): Promise<void>;
50
+ /**
51
+ * Rewrites a message this connection posted. A channel without it gives
52
+ * up streaming a reply in place: it posts the final text once.
53
+ */
54
+ edit?(ref: OutboundMessageRef, text: string): Promise<void>;
55
+ /**
56
+ * Uploads a local file into the conversation (tool outputs, screenshots).
57
+ * A channel without it cannot deliver files over an addressable
58
+ * destination; a caller says so instead of dropping the file silently.
59
+ */
60
+ upload?(filePath: string, title?: string): Promise<void>;
45
61
  /**
46
62
  * Optional typing affordance. Platforms without a real bot typing API
47
63
  * (Slack among them) no-op here and rely on the placeholder-edit pattern
@@ -151,6 +167,33 @@ export interface GatewayLike {
151
167
  * events from another caller's on the same session — see `activeTurnId`.
152
168
  */
153
169
  turnId?: string;
170
+ /**
171
+ * The platform's own id for the message, unique within the session, so
172
+ * a redelivery never starts a second turn — across a restart too, which
173
+ * in-memory dedupe cannot survive. A repeat resolves with the original
174
+ * turn: the live one, the finished session, or one the gateway continued
175
+ * after a crash. A finished session may have moved on since, so the
176
+ * reply to post is `turnReplyFor(session, key)` from
177
+ * `@stratusagent/core`, never the latest one. See `DispatchInput.idempotencyKey` in
178
+ * `@stratusagent/gateway`.
179
+ *
180
+ * A host without it ignores the field, and the adapter's own dedupe is
181
+ * all there is.
182
+ */
183
+ idempotencyKey?: string;
184
+ /**
185
+ * Called before the dispatch resolves when it repeats a turn. `live`:
186
+ * another dispatch of the same key in this process is still waiting on
187
+ * it and posts its outcome, so this caller takes down anything of its
188
+ * own and posts nothing. `finished`: nothing ran and no event will
189
+ * come, and the outcome may never have been posted, so this caller
190
+ * posts it from the session — `turnReplyFor`, `turnFilesFor`,
191
+ * `turnFailureFor` in `@stratusagent/core`. Not called for a repeat
192
+ * that continues a turn a crash left unfinished, which this caller
193
+ * renders as its own. See `DispatchInput.onRepeat` in
194
+ * `@stratusagent/gateway`.
195
+ */
196
+ onRepeat?: (repeat: 'live' | 'finished') => void;
154
197
  }): Promise<Session>;
155
198
  readonly bus: EventBus;
156
199
  agents(): AgentDefinition[];
@@ -174,6 +217,17 @@ export interface GatewayLike {
174
217
  * whose process is gone — nothing else.
175
218
  */
176
219
  sessionRouting?(sessionId: string): Promise<SessionRouting | undefined>;
220
+ /**
221
+ * Whether a session already accepted the message an idempotency key names,
222
+ * as addressed to it — a turn was started for it, finished or not; a turn
223
+ * nobody asked for (`addressed: false`) does not count. Asked before routing a message
224
+ * that more than one agent could answer: one an agent already accepted is
225
+ * that agent's, whoever the routing rule would pick now. Optional: a host
226
+ * without it leaves the choice to the rule alone, which after a restart can
227
+ * hand a redelivered message to an agent that has spoken since — and that
228
+ * agent, holding no key for it, runs it again.
229
+ */
230
+ holdsMessage?(sessionId: string, idempotencyKey: string): Promise<boolean>;
177
231
  /**
178
232
  * A message that reaches a session without running a turn: something
179
233
  * said in a conversation the agent is in, to somebody else. The next
@@ -217,6 +271,33 @@ export interface GatewayLike {
217
271
  */
218
272
  reason?: 'decided' | 'undeliverable';
219
273
  }): boolean;
274
+ /**
275
+ * Answers a `credential.requested` with the value a person entered.
276
+ * `ok: false` carries a sentence to show them. `retired` on it means no
277
+ * answer to this request can ever land (the name was stored since, or
278
+ * the request is gone), so the adapter should take the form down rather
279
+ * than leave a button that can only be refused.
280
+ *
281
+ * As with approvals, who may answer is the adapter's question: the
282
+ * approver set is written in the channel's own user ids. The value is
283
+ * handed over here and nowhere else — an adapter never logs it, posts it,
284
+ * or passes it to `dispatch`.
285
+ *
286
+ * Optional: a host that omits it gives up taking credentials from a
287
+ * channel, and an adapter says so to whoever tried instead of offering a
288
+ * form that cannot land.
289
+ */
290
+ provideCredential?(input: {
291
+ requestId: string;
292
+ value: string;
293
+ actor?: string;
294
+ }): Promise<{
295
+ ok: true;
296
+ } | {
297
+ ok: false;
298
+ message: string;
299
+ retired?: boolean;
300
+ }>;
220
301
  }
221
302
  /**
222
303
  * A destination this adapter is being asked to speak to, outside any
@@ -238,6 +319,23 @@ export interface OutboundAddress {
238
319
  */
239
320
  to: string;
240
321
  }
322
+ /**
323
+ * A credential an agent asked for, handed to the channel its conversation
324
+ * is in so a person there can be shown a form. Everything the answer needs
325
+ * stays with the gateway under `requestId`; the channel only has to show
326
+ * the question and quote the id back through `GatewayLike.provideCredential`.
327
+ */
328
+ export interface ChannelCredentialRequest {
329
+ sessionId: string;
330
+ agentId: string;
331
+ requestId: string;
332
+ name: string;
333
+ scope: CredentialScope;
334
+ /** The agent's own words for why; show them as the agent's. */
335
+ reason?: string;
336
+ /** The session's routing metadata: where the conversation is. */
337
+ metadata: JsonObject;
338
+ }
241
339
  export interface ChannelAdapter {
242
340
  name: string;
243
341
  start(gateway: GatewayLike): Promise<void>;
@@ -258,6 +356,20 @@ export interface ChannelAdapter {
258
356
  * also how a destination is checked without sending anything.
259
357
  */
260
358
  resolveOutbound?(address: OutboundAddress): Promise<OutboundConnection>;
359
+ /**
360
+ * Shows a person in the conversation a form for a credential the agent
361
+ * asked for. Optional, like `resolveOutbound`: a channel without it
362
+ * cannot take credentials, and the gateway refuses a request made in its
363
+ * conversations rather than telling the agent someone was asked.
364
+ *
365
+ * Resolves once the form is in front of someone who can answer it, and
366
+ * MUST reject otherwise (the post failed, nobody here may answer, the
367
+ * agent has no app connected), with a sentence for the agent: the
368
+ * gateway drops the request and hands the agent that sentence, because
369
+ * a request nobody can see would otherwise wait forever while the agent
370
+ * tells its user the operator was asked.
371
+ */
372
+ requestCredential?(request: ChannelCredentialRequest): Promise<void>;
261
373
  }
262
374
  export interface ChannelSessionKeyParts {
263
375
  /** Channel kind, e.g. 'slack'. */
@@ -280,4 +392,49 @@ export interface ChannelSessionKeyParts {
280
392
  * roots its own reply-thread conversation) and no thread for DMs.
281
393
  */
282
394
  export declare const channelSessionKey: (parts: ChannelSessionKeyParts) => string;
395
+ /**
396
+ * Whether a sender outside the principals list gets a turn at all.
397
+ * `anyone` admits them, labelled `unknown`; `principals` refuses them
398
+ * before a turn starts, and an adapter that overhears must not let the
399
+ * agent overhear them either — the text would be in the transcript, which
400
+ * is what this mode exists to keep out.
401
+ */
402
+ export type AdmitPolicy = 'anyone' | 'principals';
403
+ /**
404
+ * Who a channel treats as the operator, and whether anyone else is let in.
405
+ * Ids are the channel's own (a Slack user id, a phone number) — never a
406
+ * Stratus identity, for the same reason `OutboundAddress.to` is not.
407
+ *
408
+ * The two fields answer different questions. `principals` is provenance:
409
+ * an adapter's own admission checks (a DM, a mention) establish nothing
410
+ * about who is typing, and this list is what makes the `user` label mean
411
+ * something. `admit` is authorization. Absent `principals` and `[]` both
412
+ * mean nobody is a principal; an adapter may still tell them apart for
413
+ * presentation (Slack shows everyone's name when there is no list).
414
+ *
415
+ * Which `admit` applies when config gives none is the adapter's call, not
416
+ * this module's: Slack defaults to `anyone`, because only workspace members
417
+ * can reach it, while a channel anyone in the world can message should
418
+ * default to `principals`. Pass the policy with that default already
419
+ * applied.
420
+ */
421
+ export interface SenderPolicy {
422
+ principals?: readonly string[];
423
+ admit?: AdmitPolicy;
424
+ }
425
+ /** Whether `senderId` is on the policy's principals list. */
426
+ export declare const isPrincipal: (policy: SenderPolicy | undefined, senderId: string) => boolean;
427
+ /**
428
+ * Whether a message from `senderId` may start a turn. No policy admits:
429
+ * there is nobody's list to refuse against, which is the answer from
430
+ * before admission existed.
431
+ */
432
+ export declare const admitsSender: (policy: SenderPolicy | undefined, senderId: string) => boolean;
433
+ /**
434
+ * The trust label a turn from `senderId` carries (`SENDER_TRUST_METADATA_KEY`
435
+ * in `@stratusagent/core`): `user` for a principal, `unknown` for anyone else.
436
+ * Evaluated per message, never per session: a group conversation keys one
437
+ * session for everyone in it.
438
+ */
439
+ export declare const senderTrustFor: (policy: SenderPolicy | undefined, senderId: string) => Extract<TrustLevel, "user" | "unknown">;
283
440
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -12,4 +12,19 @@ export const channelSessionKey = (parts) => {
12
12
  }
13
13
  return segments.join(':');
14
14
  };
15
+ /** Whether `senderId` is on the policy's principals list. */
16
+ export const isPrincipal = (policy, senderId) => (policy?.principals ?? []).includes(senderId);
17
+ /**
18
+ * Whether a message from `senderId` may start a turn. No policy admits:
19
+ * there is nobody's list to refuse against, which is the answer from
20
+ * before admission existed.
21
+ */
22
+ export const admitsSender = (policy, senderId) => policy === undefined || policy.admit !== 'principals' || isPrincipal(policy, senderId);
23
+ /**
24
+ * The trust label a turn from `senderId` carries (`SENDER_TRUST_METADATA_KEY`
25
+ * in `@stratusagent/core`): `user` for a principal, `unknown` for anyone else.
26
+ * Evaluated per message, never per session: a group conversation keys one
27
+ * session for everyone in it.
28
+ */
29
+ export const senderTrustFor = (policy, senderId) => isPrincipal(policy, senderId) ? 'user' : 'unknown';
15
30
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA+RA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,KAA6B,EAAU,EAAE;IACzE,MAAM,QAAQ,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;IAChF,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA4YA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,KAA6B,EAAU,EAAE;IACzE,MAAM,QAAQ,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;IAChF,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC,CAAC;AAkCF,6DAA6D;AAC7D,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,MAAgC,EAAE,QAAgB,EAAW,EAAE,CACzF,CAAC,MAAM,EAAE,UAAU,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAEhD;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,MAAgC,EAAE,QAAgB,EAAW,EAAE,CAC1F,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,KAAK,YAAY,IAAI,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAEzF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,MAAgC,EAAE,QAAgB,EAA2C,EAAE,CAC5H,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stratusagent/channels",
3
- "version": "0.11.6",
3
+ "version": "0.11.7",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -17,7 +17,7 @@
17
17
  "node": ">=22.13 <23 || >=23.4"
18
18
  },
19
19
  "dependencies": {
20
- "@stratusagent/core": "0.11.6"
20
+ "@stratusagent/core": "0.11.7"
21
21
  },
22
22
  "devDependencies": {
23
23
  "@types/node": "^24.6.0",