@skaile/workspaces 6.11.0 → 6.12.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.
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Read-along context batching (spec §5.2): messages in a bound conversation
3
+ * that do not mention the bot are collected here and handed to
4
+ * `SessionPort.appendContext` in batches, so a busy channel costs the host one
5
+ * write per batch rather than one per message.
6
+ */
7
+ import type { ChannelLogger } from "./adapter.js";
8
+ import type { ChannelMessage, ConversationKey } from "./types.js";
9
+ /** Tuning for read-along context batching. Every field is optional. */
10
+ export type ContextBatchOptions = {
11
+ /** Flush a non-empty batch this long after its first message. Default 30 000. */
12
+ flushAfterMs?: number;
13
+ /** Flush as soon as a batch holds this many messages. Default 20. */
14
+ maxBatch?: number;
15
+ /** Most context messages accepted per conversation per hour; the rest are dropped. Default 200. */
16
+ hourlyCap?: number;
17
+ };
18
+ /** Outcome of {@link ContextBatcher.add}. */
19
+ export type ContextAddResult = "buffered" | "full" | "dropped";
20
+ /**
21
+ * One conversation's pending context batch plus its hourly budget.
22
+ *
23
+ * The batcher never calls the host itself: a full batch is reported to the
24
+ * caller (`add` returns `"full"`), and the timer calls `onDue`, so the engine
25
+ * can run every flush on the conversation's serial chain. `take()` drains.
26
+ *
27
+ * The hourly cap is a fixed window that opens on the first message after the
28
+ * previous window ran out. Dropped messages are counted; the first drop in a
29
+ * window logs a warning and the window's total is logged when it closes.
30
+ */
31
+ export declare class ContextBatcher {
32
+ private readonly flushAfterMs;
33
+ private readonly maxBatch;
34
+ private readonly hourlyCap;
35
+ private readonly now;
36
+ private readonly onDue;
37
+ private readonly logger;
38
+ private readonly conversationKey;
39
+ private pending;
40
+ private timer;
41
+ private windowStart;
42
+ private acceptedInWindow;
43
+ private droppedInWindow;
44
+ constructor(opts: {
45
+ options?: ContextBatchOptions;
46
+ conversationKey: ConversationKey;
47
+ now: () => number;
48
+ onDue: () => void;
49
+ logger: ChannelLogger;
50
+ });
51
+ /** Messages waiting for the next flush. */
52
+ get size(): number;
53
+ /** Buffers `msg` unless the hourly cap is spent. `"full"` means flush now. */
54
+ add(msg: ChannelMessage): ContextAddResult;
55
+ /** Drains the pending batch (possibly empty) and cancels its timer. */
56
+ take(): ChannelMessage[];
57
+ /** Cancels the timer and logs any drops still unreported. Pending messages are left to `take()`. */
58
+ dispose(): void;
59
+ private rollWindow;
60
+ private reportDropped;
61
+ private clearTimer;
62
+ }
63
+ //# sourceMappingURL=context-batch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-batch.d.ts","sourceRoot":"","sources":["../../../channels/src/context-batch.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElE,uEAAuE;AACvE,MAAM,MAAM,mBAAmB,GAAG;IAChC,iFAAiF;IACjF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mGAAmG;IACnG,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAOF,6CAA6C;AAC7C,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,MAAM,GAAG,SAAS,CAAC;AAE/D;;;;;;;;;;GAUG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAa;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkB;IAClD,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,KAAK,CAA4C;IACzD,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,eAAe,CAAK;gBAEhB,IAAI,EAAE;QAChB,OAAO,CAAC,EAAE,mBAAmB,CAAC;QAC9B,eAAe,EAAE,eAAe,CAAC;QACjC,GAAG,EAAE,MAAM,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,IAAI,CAAC;QAClB,MAAM,EAAE,aAAa,CAAC;KACvB;IAUD,2CAA2C;IAC3C,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,8EAA8E;IAC9E,GAAG,CAAC,GAAG,EAAE,cAAc,GAAG,gBAAgB;IA2B1C,uEAAuE;IACvE,IAAI,IAAI,cAAc,EAAE;IAOxB,oGAAoG;IACpG,OAAO,IAAI,IAAI;IAKf,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,UAAU;CAKnB"}
@@ -7,6 +7,13 @@
7
7
  import type { AgentEvent } from "@skaile/workspaces/types";
8
8
  import type { ChannelAdapter, ChannelLogger } from "../adapter.js";
9
9
  import type { Binding, MessageRef, ReplyTarget } from "../types.js";
10
+ /**
11
+ * True when `e` ends the agent's reply turn: `finished`, or the agent going
12
+ * idle. The runner reports idle when its turn queue drains (a failed or stopped
13
+ * turn with nothing queued behind it included). An `error` alone never ends
14
+ * the turn: non-fatal errors also arrive mid-turn.
15
+ */
16
+ export declare function endsTurn(e: AgentEvent): boolean;
10
17
  /** Options for {@link OutputMirror}. */
11
18
  export type OutputMirrorOptions = {
12
19
  adapter: ChannelAdapter;
@@ -1 +1 @@
1
- {"version":3,"file":"output-mirror.d.ts","sourceRoot":"","sources":["../../../../channels/src/egress/output-mirror.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,UAAU,EAAoB,MAAM,0BAA0B,CAAC;AAE7E,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAmB,WAAW,EAAE,MAAM,aAAa,CAAC;AAQrF,wCAAwC;AACxC,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,cAAc,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,WAAW,CAAC;IACpB,+DAA+D;IAC/D,WAAW,EAAE,MAAM,CAAC;IACpB,wGAAwG;IACxG,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5D,+EAA+E;IAC/E,mBAAmB,CAAC,EAAE,MAAM,OAAO,CAAC;IACpC,MAAM,EAAE,aAAa,CAAC;CACvB,CAAC;AAqBF;;;;;;;;;;;;;GAaG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAsB;IAC3C,OAAO,CAAC,IAAI,CAAmB;IAC/B,yEAAyE;IACzE,OAAO,CAAC,IAAI,CAAoC;IAChD,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,QAAQ,CAAS;gBAEb,IAAI,EAAE,mBAAmB;IAIrC,oFAAoF;IACpF,WAAW,CAAC,CAAC,EAAE,UAAU,GAAG,IAAI;IA6BhC,oCAAoC;IAC9B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAO9B,OAAO,CAAC,MAAM;IAWd;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAYrB,4EAA4E;IAC5E,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,OAAO;IA2Cf,yEAAyE;IACzE,OAAO,CAAC,SAAS;IAQjB,yFAAyF;YAC3E,aAAa;IAa3B,OAAO,CAAC,QAAQ;IAShB,iFAAiF;IACjF,OAAO,CAAC,aAAa;IASrB,gFAAgF;IAChF,OAAO,CAAC,OAAO;CAKhB"}
1
+ {"version":3,"file":"output-mirror.d.ts","sourceRoot":"","sources":["../../../../channels/src/egress/output-mirror.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,UAAU,EAAoB,MAAM,0BAA0B,CAAC;AAE7E,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAmB,WAAW,EAAE,MAAM,aAAa,CAAC;AAQrF;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,UAAU,GAAG,OAAO,CAE/C;AAED,wCAAwC;AACxC,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,cAAc,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,WAAW,CAAC;IACpB,+DAA+D;IAC/D,WAAW,EAAE,MAAM,CAAC;IACpB,wGAAwG;IACxG,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5D,+EAA+E;IAC/E,mBAAmB,CAAC,EAAE,MAAM,OAAO,CAAC;IACpC,MAAM,EAAE,aAAa,CAAC;CACvB,CAAC;AAqBF;;;;;;;;;;;;;GAaG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAsB;IAC3C,OAAO,CAAC,IAAI,CAAmB;IAC/B,yEAAyE;IACzE,OAAO,CAAC,IAAI,CAAoC;IAChD,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,QAAQ,CAAS;gBAEb,IAAI,EAAE,mBAAmB;IAIrC,oFAAoF;IACpF,WAAW,CAAC,CAAC,EAAE,UAAU,GAAG,IAAI;IAgChC,oCAAoC;IAC9B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAO9B,OAAO,CAAC,MAAM;IAWd;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAYrB,4EAA4E;IAC5E,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,OAAO;IA2Cf,yEAAyE;IACzE,OAAO,CAAC,SAAS;IAQjB,yFAAyF;YAC3E,aAAa;IAa3B,OAAO,CAAC,QAAQ;IAShB,iFAAiF;IACjF,OAAO,CAAC,aAAa;IASrB,gFAAgF;IAChF,OAAO,CAAC,OAAO;CAKhB"}
@@ -1,7 +1,8 @@
1
1
  import type { ChannelAdapter, ChannelLogger, IngressSink } from "./adapter.js";
2
+ import type { ContextBatchOptions } from "./context-batch.js";
2
3
  import type { DedupeStore } from "./dedupe.js";
3
4
  import type { BindingStore, CredentialPort, IdentityPort, IngressHost, SessionPort } from "./ports.js";
4
- import type { Binding, ChannelPlatform, ConversationKey } from "./types.js";
5
+ import type { Binding, ChannelPlatform, ConversationKey, MirrorMode } from "./types.js";
5
6
  /**
6
7
  * Notice posted when `unmappedActorPolicy === "reject"` turns an inbound
7
8
  * message away — ephemeral where the surface supports it, a threaded regular
@@ -35,6 +36,16 @@ export type ChannelEngineOptions = {
35
36
  * their actionable messages — and starts mirroring the enabled ones.
36
37
  */
37
38
  initialBindings?: Binding[];
39
+ /**
40
+ * Read-along batching for messages that do not mention the bot (spec §5.2).
41
+ * Only used when the SessionPort implements `appendContext`.
42
+ */
43
+ contextBatch?: ContextBatchOptions;
44
+ /**
45
+ * Mirror mode of the binding the engine creates itself when the bot is
46
+ * mentioned in an unbound conversation. Default "agent-only".
47
+ */
48
+ lazyBindMirrorMode?: MirrorMode;
38
49
  };
39
50
  /**
40
51
  * Runs the channels data flow for a set of adapters against one host's ports.
@@ -105,6 +116,14 @@ export declare class ChannelEngine {
105
116
  private enqueueIngress;
106
117
  /** Detached ingress work: identity, routing, lazy bind, attributed delivery. */
107
118
  private process;
119
+ /**
120
+ * Read-along: queues a message that did not mention the bot as session
121
+ * context. It never starts a turn, so an unmapped actor needs no reject
122
+ * notice: the message is framed as untrusted and carries no senderId.
123
+ */
124
+ private appendAsContext;
125
+ /** Hands the pending read-along batch to `SessionPort.appendContext`; logs, never throws. */
126
+ private flushContext;
108
127
  /** "Teams: <snippet>" — title for a lazily-created thread session. */
109
128
  private sessionTitle;
110
129
  /** Reject notice: ephemeral where supported; threaded regular reply otherwise. */
@@ -119,7 +138,7 @@ export declare class ChannelEngine {
119
138
  private disarmPlaceholder;
120
139
  /** Bind-time preflight in log-only form, for engine-start restoration. */
121
140
  private verifyOrLog;
122
- /** Disarm, unsubscribe, and flush/dispose the mirror of one binding. */
141
+ /** Flush pending context, disarm, unsubscribe, and flush/dispose the mirror of one binding. */
123
142
  private teardownState;
124
143
  }
125
144
  //# sourceMappingURL=engine.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../channels/src/engine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../channels/src/engine.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,7 @@
3
3
  * layer: core types, the per-platform adapter contract, and host-owned ports.
4
4
  */
5
5
  export * from "./adapter.js";
6
+ export * from "./context-batch.js";
6
7
  export * from "./dedupe.js";
7
8
  export * from "./egress/output-mirror.js";
8
9
  export * from "./engine.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../channels/src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,aAAa,CAAC;AAC5B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../channels/src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,aAAa,CAAC;AAC5B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC"}
@@ -31,6 +31,15 @@ export type NewSessionSpec = {
31
31
  export interface SessionPort {
32
32
  /** Wakes if hibernated; persists attributed; prompts the agent (spec §7.1.7). */
33
33
  deliver(binding: Binding, msg: ChannelMessage): Promise<void>;
34
+ /**
35
+ * Read-along (spec §5.2): stores chat messages that did not mention the bot
36
+ * as context in the bound session, in arrival order. Must NOT start an agent
37
+ * turn. Messages from mapped actors carry `meta.senderId`; unmapped ones carry
38
+ * none and arrive framed as untrusted. Batched by the engine (see
39
+ * `ContextBatchOptions`). Optional: without it, every message is delivered
40
+ * as a prompt, as before.
41
+ */
42
+ appendContext?(binding: Binding, messages: ChannelMessage[]): Promise<void>;
34
43
  /** One live subscription per active binding; consumes raw AgentEvents. */
35
44
  subscribe(binding: Binding, sink: (e: AgentEvent) => void): Unsubscribe;
36
45
  createSession?(spec: NewSessionSpec): Promise<SessionRef>;
@@ -1 +1 @@
1
- {"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../../../channels/src/ports.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EACV,OAAO,EACP,YAAY,EACZ,cAAc,EACd,eAAe,EACf,eAAe,EAChB,MAAM,YAAY,CAAC;AAEpB,wEAAwE;AACxE,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AAErC,2EAA2E;AAC3E,MAAM,MAAM,QAAQ,GAAG;IACrB,uEAAuE;IACvE,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,8EAA8E;AAC9E,MAAM,MAAM,UAAU,GAAG;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/C,0EAA0E;AAC1E,MAAM,MAAM,cAAc,GAAG;IAC3B,4DAA4D;IAC5D,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,eAAe,CAAC;IAC1B,eAAe,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,qFAAqF;AACrF,MAAM,WAAW,WAAW;IAC1B,iFAAiF;IACjF,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,0EAA0E;IAC1E,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,GAAG,WAAW,CAAC;IACxE,aAAa,CAAC,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAC3D;AAED,qEAAqE;AACrE,MAAM,WAAW,YAAY;IAC3B,2EAA2E;IAC3E,YAAY,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;CAC7D;AAED,4FAA4F;AAC5F,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IACnD,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IACtD,MAAM,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C;AAED,wEAAwE;AACxE,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GACxD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD,mFAAmF;AACnF,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,QAAQ,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACpF;AAED,sFAAsF;AACtF,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEjE,sDAAsD;AACtD,MAAM,WAAW,WAAW;IAC1B,2FAA2F;IAC3F,iBAAiB,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;CACjE"}
1
+ {"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../../../channels/src/ports.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EACV,OAAO,EACP,YAAY,EACZ,cAAc,EACd,eAAe,EACf,eAAe,EAChB,MAAM,YAAY,CAAC;AAEpB,wEAAwE;AACxE,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AAErC,2EAA2E;AAC3E,MAAM,MAAM,QAAQ,GAAG;IACrB,uEAAuE;IACvE,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,8EAA8E;AAC9E,MAAM,MAAM,UAAU,GAAG;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/C,0EAA0E;AAC1E,MAAM,MAAM,cAAc,GAAG;IAC3B,4DAA4D;IAC5D,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,eAAe,CAAC;IAC1B,eAAe,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,qFAAqF;AACrF,MAAM,WAAW,WAAW;IAC1B,iFAAiF;IACjF,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D;;;;;;;OAOG;IACH,aAAa,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5E,0EAA0E;IAC1E,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,GAAG,WAAW,CAAC;IACxE,aAAa,CAAC,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAC3D;AAED,qEAAqE;AACrE,MAAM,WAAW,YAAY;IAC3B,2EAA2E;IAC3E,YAAY,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;CAC7D;AAED,4FAA4F;AAC5F,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IACnD,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IACtD,MAAM,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C;AAED,wEAAwE;AACxE,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GACxD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD,mFAAmF;AACnF,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,QAAQ,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACpF;AAED,sFAAsF;AACtF,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEjE,sDAAsD;AACtD,MAAM,WAAW,WAAW;IAC1B,2FAA2F;IAC3F,iBAAiB,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;CACjE"}
@@ -119,6 +119,12 @@ export type ChannelMetaExtensions = {
119
119
  };
120
120
  /** Opaque platform-native ref of the source message. */
121
121
  messageRef?: unknown;
122
+ /**
123
+ * True when the message is addressed to the bot (an @mention, or a 1:1
124
+ * chat with it); only such messages start an agent turn (spec §5.2, §5.7).
125
+ * When an adapter leaves it unset, the engine falls back to `meta.mentions`.
126
+ */
127
+ mentioned?: boolean;
122
128
  };
123
129
  };
124
130
  /** A workspace message envelope whose meta block carries {@link ChannelMetaExtensions}. */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../channels/src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../channels/src/types.ts"],"names":[],"mappings":"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"}
@@ -68,5 +68,5 @@ function parseConversationKey(key) {
68
68
  }
69
69
 
70
70
  export { CHANNEL_PLATFORMS, makeConversationKey, makeQuestionCard, markdownToTeamsText, mentionsAgent, normalizeMentions, parseConversationKey, teamsFormatConverter };
71
- //# sourceMappingURL=chunk-F2IBDVBP.js.map
72
- //# sourceMappingURL=chunk-F2IBDVBP.js.map
71
+ //# sourceMappingURL=chunk-VHRGCLCR.js.map
72
+ //# sourceMappingURL=chunk-VHRGCLCR.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../channels/src/mention/normalize.ts","../channels/src/format/adaptive-card.ts","../channels/src/types.ts"],"names":[],"mappings":"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","file":"chunk-F2IBDVBP.js","sourcesContent":["/**\n * Inbound mention normalization (spec §6.1): adapter-parsed platform mention\n * entities → the existing `Mention` union. This touches INBOUND platform\n * entities only — the platform's session-member mention grammar is untouched\n * (spec §12).\n */\nimport type { Mention } from \"@skaile/workspaces/types\";\nimport type { IdentityPort } from \"../ports.js\";\nimport type { ChannelActor } from \"../types.js\";\n\n/** A platform mention entity as the adapter parsed it, pre-identity-resolution. */\nexport type ChannelMentionEntity = {\n externalId: string;\n displayName: string;\n /** True when the entity is the bot itself (adapter compares against its own id). */\n isBot: boolean;\n offset: number;\n length: number;\n};\n\n/**\n * Normalizes adapter-parsed mention entities into the existing Mention union\n * (spec §6.1): bot → { type:\"group\", group:\"agent\" }; mapped user → user;\n * unmapped → { type:\"custom\", kind:\"external\", data:{ platform, externalUserId } }.\n */\nexport async function normalizeMentions(\n entities: ChannelMentionEntity[],\n actorOf: (e: ChannelMentionEntity) => ChannelActor,\n identity: IdentityPort,\n): Promise<Mention[]> {\n return Promise.all(\n entities.map(async (e): Promise<Mention> => {\n const position = { offset: e.offset, length: e.length };\n if (e.isBot) return { type: \"group\", group: \"agent\", resolved: [], ...position };\n const actor = actorOf(e);\n const host = await identity.resolveActor(actor);\n if (host) return { type: \"user\", userId: host.id, name: host.displayName, ...position };\n return {\n type: \"custom\",\n kind: \"external\",\n resolved: [],\n data: { platform: actor.platform, externalUserId: actor.externalId },\n ...position,\n };\n }),\n );\n}\n\n/** True when any normalized mention addresses the agent (bot-mention gate, spec §7.1.6). */\nexport function mentionsAgent(mentions: Mention[]): boolean {\n return mentions.some((m) => m.type === \"group\" && m.group === \"agent\");\n}\n","/**\n * Teams-facing formatting: text normalization for the markdown subset Teams\n * renders, plus Adaptive Card construction for question posts with options.\n */\nimport type { FormatConverter } from \"./types.js\";\n\n/**\n * Teams' supported markdown subset pass-through: normalizes constructs Teams\n * cannot render (~~strike~~ → plain, heading # → bold line); everything else\n * verbatim. Line-based on purpose — no markdown parser; fenced code passes\n * through untouched.\n */\nexport function markdownToTeamsText(markdown: string): string {\n let inFence = false;\n return markdown\n .split(\"\\n\")\n .map((line) => {\n if (/^\\s*```/.test(line)) {\n inFence = !inFence;\n return line;\n }\n if (inFence) return line;\n const heading = line.match(/^#{1,6}\\s+(.*)$/);\n const text = heading ? `**${heading[1]}**` : line;\n return text.replace(/~~(.+?)~~/g, \"$1\");\n })\n .join(\"\\n\");\n}\n\n/** Adaptive Card 1.4 JSON for a question with option buttons (Action.Submit, data: { option }). */\nexport function makeQuestionCard(markdown: string, options: string[]): Record<string, unknown> {\n return {\n type: \"AdaptiveCard\",\n version: \"1.4\",\n $schema: \"http://adaptivecards.io/schemas/adaptive-card.json\",\n body: [{ type: \"TextBlock\", text: markdownToTeamsText(markdown), wrap: true }],\n actions: options.map((option) => ({\n type: \"Action.Submit\",\n title: option,\n data: { option },\n })),\n };\n}\n\n/** {@link FormatConverter} for adapters whose `textFormat` is `\"adaptive-card\"` (Teams). */\nexport const teamsFormatConverter: FormatConverter = { toPlatformText: markdownToTeamsText };\n","/**\n * Core value and message types for the channels layer — the bridge between\n * external chat platforms (Teams, Mattermost, Slack) and workspace sessions.\n *\n * Everything here is transport-neutral: no platform SDK types leak in, and\n * platform-native payloads only appear as opaque `raw`/`messageRef` slots.\n */\nimport type { MessageV2 } from \"@skaile/workspaces/types\";\n\n/** Chat platforms the channels layer can bridge. */\nexport const CHANNEL_PLATFORMS = [\"msteams\", \"mattermost\", \"slack\"] as const;\n\n/** One of the supported chat platforms (`\"msteams\" | \"mattermost\" | \"slack\"`). */\nexport type ChannelPlatform = (typeof CHANNEL_PLATFORMS)[number];\n\n/**\n * Canonical identifier of a place in a chat app: `\"<platform>:<conversationId>\"`,\n * optionally `\"…/<threadRootId>\"`. Never a session id — the Binding is the only\n * join between the two (spec §5.1).\n */\nexport type ConversationKey = string;\n\n/**\n * Builds a {@link ConversationKey} from its parts.\n *\n * Invariant: `parseConversationKey(makeConversationKey(p, c, t))` round-trips\n * exactly, provided `threadRootId` itself contains no `/`.\n */\nexport function makeConversationKey(\n platform: ChannelPlatform,\n conversationId: string,\n threadRootId?: string,\n): ConversationKey {\n return threadRootId\n ? `${platform}:${conversationId}/${threadRootId}`\n : `${platform}:${conversationId}`;\n}\n\n/**\n * Splits a {@link ConversationKey} into platform, conversation id, and optional\n * thread root. Throws on an unknown platform prefix.\n *\n * Gotcha: the thread separator is the LAST `/` — conversation ids may\n * themselves contain slashes (e.g. Mattermost `team/channel`).\n */\nexport function parseConversationKey(key: ConversationKey): {\n platform: ChannelPlatform;\n conversationId: string;\n threadRootId?: string;\n} {\n const sep = key.indexOf(\":\");\n const platform = key.slice(0, sep) as ChannelPlatform;\n if (!CHANNEL_PLATFORMS.includes(platform)) {\n throw new Error(`ConversationKey has unknown platform: ${key}`);\n }\n const rest = key.slice(sep + 1);\n // Thread separator is the LAST \"/\" — conversation ids may themselves contain slashes.\n const slash = rest.lastIndexOf(\"/\");\n if (slash === -1) return { platform, conversationId: rest };\n return { platform, conversationId: rest.slice(0, slash), threadRootId: rest.slice(slash + 1) };\n}\n\n/** A person (or bot) as the chat platform sees them — pre-IdentityPort resolution. */\nexport type ChannelActor = {\n platform: ChannelPlatform;\n /** Platform-native user id (Teams AAD object id, Slack user id, MM user id). */\n externalId: string;\n displayName: string;\n /** Teams tenant / MM team / Slack workspace, when known. */\n tenantId?: string;\n /** Identity hint for IdentityPort mapping, when the platform exposes it. */\n email?: string;\n isBot?: boolean;\n};\n\n/** Reference to a posted platform message. `raw` carries platform-native extras (e.g. Teams serviceUrl). */\nexport type MessageRef = {\n platform: ChannelPlatform;\n conversationKey: ConversationKey;\n /** Platform-native message id (Teams activity id, Slack ts, MM post id). */\n messageId: string;\n raw?: unknown;\n};\n\n/** Where to post: a conversation, optionally threaded under an existing message. */\nexport type ReplyTarget = {\n conversationKey: ConversationKey;\n /** Platform-native thread anchor; adapters thread under it where supported. */\n threadRef?: MessageRef;\n};\n\n/**\n * Declarative surface description consumed by the engine + egress pipeline.\n * Finalized per spec §13.1 by this plan — the conformance kit asserts adapters\n * honor `maxMessageLength` and `ackDeadlineMs`.\n */\nexport type SurfaceCapabilities = {\n canEditMessages: boolean;\n canDeleteMessages: boolean;\n supportsThreads: boolean;\n supportsCards: boolean;\n supportsTyping: boolean;\n supportsEphemeral: boolean;\n supportsReactions: boolean;\n /** Hard cap on a single posted message's text length; egress chunks at this. */\n maxMessageLength: number;\n /** IngressSink.onMessage must resolve within this (Slack ~3000, Teams 15000). */\n ackDeadlineMs: number;\n /** Minimum interval between successive edits of one message (egress throttle). */\n editThrottleMs: number;\n /** Outbound text dialect the adapter expects from the format layer. */\n textFormat: \"markdown\" | \"mrkdwn\" | \"adaptive-card\";\n};\n\n/** Per-binding egress policy (spec §7.2.4). */\nexport type MirrorMode = \"agent-only\" | \"full\" | \"chat-initiated\";\n\n/**\n * The conversationKey ↔ sessionId join, persisted by the host's BindingStore.\n * Deliberately not 1:1 (spec §5.1). Session ids never leak into chat payloads.\n */\nexport type Binding = {\n conversationKey: ConversationKey;\n sessionId: string;\n platform: ChannelPlatform;\n tenantId?: string;\n mirrorMode: MirrorMode;\n enabled: boolean;\n /** Host user id that created the binding (audit; authority stays with the host). */\n createdBy: string;\n /** ISO 8601. */\n createdAt: string;\n};\n\n/**\n * The one genuinely new meta type (spec §5) — rides on MessageMeta's extension\n * slot; hosts persist it untouched via the round-trip preservation contract.\n */\nexport type ChannelMetaExtensions = {\n channel?: {\n platform: ChannelPlatform;\n conversationKey: ConversationKey;\n /** Platform event id — the inbound dedupe key. */\n eventId: string;\n tenantId?: string;\n /** Pre-IdentityPort resolution attribution. */\n actor?: { externalId: string; displayName: string };\n /** Opaque platform-native ref of the source message. */\n messageRef?: unknown;\n };\n};\n\n/** A workspace message envelope whose meta block carries {@link ChannelMetaExtensions}. */\nexport type ChannelMessage = MessageV2<ChannelMetaExtensions>;\n\n/** What the engine hands an adapter to post. Format conversion is the adapter's job. */\nexport type OutboundMessage = {\n /** Markdown source; adapters convert via the format layer per their textFormat. */\n markdown: string;\n /** Rendering intent. Default \"text\". */\n kind?: \"text\" | \"question\" | \"status\" | \"error\";\n /** Options rendered as buttons where supportsCards; appended as a list otherwise. */\n options?: string[];\n};\n\n/** Fast-ack result of IngressSink.onMessage (spec §7.1.3). */\nexport type IngressAck = {\n status: \"accepted\" | \"duplicate\" | \"ignored\" | \"rejected\";\n reason?: string;\n};\n\n/** Inbound reaction event. Engine behavior deferred this milestone (Decision 7). */\nexport type InboundReaction = {\n conversationKey: ConversationKey;\n messageRef: MessageRef;\n emoji: string;\n actor: ChannelActor;\n action: \"added\" | \"removed\";\n eventId: string;\n};\n\n/** Non-message conversation lifecycle signals adapters may surface. */\nexport type ConversationEvent = {\n conversationKey: ConversationKey;\n kind: \"member_joined\" | \"member_left\" | \"conversation_renamed\" | \"conversation_deleted\";\n eventId: string;\n raw?: unknown;\n};\n\n/** Query for ChannelAdapter.lookupActor — backs the mentions-as-a-tool helper. */\nexport type ActorQuery = {\n externalId?: string;\n email?: string;\n /** Display-name substring match, platform semantics. */\n name?: string;\n};\n\n/** Result of verifyConversation — actionable problems, forge-tui preflight pattern. */\nexport type ConversationHealth = {\n ok: boolean;\n /** Human-actionable problem descriptions (\"bot is not a member of #x — invite it\"). */\n problems: string[];\n};\n"]}
1
+ {"version":3,"sources":["../channels/src/mention/normalize.ts","../channels/src/format/adaptive-card.ts","../channels/src/types.ts"],"names":[],"mappings":"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","file":"chunk-VHRGCLCR.js","sourcesContent":["/**\n * Inbound mention normalization (spec §6.1): adapter-parsed platform mention\n * entities → the existing `Mention` union. This touches INBOUND platform\n * entities only — the platform's session-member mention grammar is untouched\n * (spec §12).\n */\nimport type { Mention } from \"@skaile/workspaces/types\";\nimport type { IdentityPort } from \"../ports.js\";\nimport type { ChannelActor } from \"../types.js\";\n\n/** A platform mention entity as the adapter parsed it, pre-identity-resolution. */\nexport type ChannelMentionEntity = {\n externalId: string;\n displayName: string;\n /** True when the entity is the bot itself (adapter compares against its own id). */\n isBot: boolean;\n offset: number;\n length: number;\n};\n\n/**\n * Normalizes adapter-parsed mention entities into the existing Mention union\n * (spec §6.1): bot → { type:\"group\", group:\"agent\" }; mapped user → user;\n * unmapped → { type:\"custom\", kind:\"external\", data:{ platform, externalUserId } }.\n */\nexport async function normalizeMentions(\n entities: ChannelMentionEntity[],\n actorOf: (e: ChannelMentionEntity) => ChannelActor,\n identity: IdentityPort,\n): Promise<Mention[]> {\n return Promise.all(\n entities.map(async (e): Promise<Mention> => {\n const position = { offset: e.offset, length: e.length };\n if (e.isBot) return { type: \"group\", group: \"agent\", resolved: [], ...position };\n const actor = actorOf(e);\n const host = await identity.resolveActor(actor);\n if (host) return { type: \"user\", userId: host.id, name: host.displayName, ...position };\n return {\n type: \"custom\",\n kind: \"external\",\n resolved: [],\n data: { platform: actor.platform, externalUserId: actor.externalId },\n ...position,\n };\n }),\n );\n}\n\n/** True when any normalized mention addresses the agent (bot-mention gate, spec §7.1.6). */\nexport function mentionsAgent(mentions: Mention[]): boolean {\n return mentions.some((m) => m.type === \"group\" && m.group === \"agent\");\n}\n","/**\n * Teams-facing formatting: text normalization for the markdown subset Teams\n * renders, plus Adaptive Card construction for question posts with options.\n */\nimport type { FormatConverter } from \"./types.js\";\n\n/**\n * Teams' supported markdown subset pass-through: normalizes constructs Teams\n * cannot render (~~strike~~ → plain, heading # → bold line); everything else\n * verbatim. Line-based on purpose — no markdown parser; fenced code passes\n * through untouched.\n */\nexport function markdownToTeamsText(markdown: string): string {\n let inFence = false;\n return markdown\n .split(\"\\n\")\n .map((line) => {\n if (/^\\s*```/.test(line)) {\n inFence = !inFence;\n return line;\n }\n if (inFence) return line;\n const heading = line.match(/^#{1,6}\\s+(.*)$/);\n const text = heading ? `**${heading[1]}**` : line;\n return text.replace(/~~(.+?)~~/g, \"$1\");\n })\n .join(\"\\n\");\n}\n\n/** Adaptive Card 1.4 JSON for a question with option buttons (Action.Submit, data: { option }). */\nexport function makeQuestionCard(markdown: string, options: string[]): Record<string, unknown> {\n return {\n type: \"AdaptiveCard\",\n version: \"1.4\",\n $schema: \"http://adaptivecards.io/schemas/adaptive-card.json\",\n body: [{ type: \"TextBlock\", text: markdownToTeamsText(markdown), wrap: true }],\n actions: options.map((option) => ({\n type: \"Action.Submit\",\n title: option,\n data: { option },\n })),\n };\n}\n\n/** {@link FormatConverter} for adapters whose `textFormat` is `\"adaptive-card\"` (Teams). */\nexport const teamsFormatConverter: FormatConverter = { toPlatformText: markdownToTeamsText };\n","/**\n * Core value and message types for the channels layer — the bridge between\n * external chat platforms (Teams, Mattermost, Slack) and workspace sessions.\n *\n * Everything here is transport-neutral: no platform SDK types leak in, and\n * platform-native payloads only appear as opaque `raw`/`messageRef` slots.\n */\nimport type { MessageV2 } from \"@skaile/workspaces/types\";\n\n/** Chat platforms the channels layer can bridge. */\nexport const CHANNEL_PLATFORMS = [\"msteams\", \"mattermost\", \"slack\"] as const;\n\n/** One of the supported chat platforms (`\"msteams\" | \"mattermost\" | \"slack\"`). */\nexport type ChannelPlatform = (typeof CHANNEL_PLATFORMS)[number];\n\n/**\n * Canonical identifier of a place in a chat app: `\"<platform>:<conversationId>\"`,\n * optionally `\"…/<threadRootId>\"`. Never a session id — the Binding is the only\n * join between the two (spec §5.1).\n */\nexport type ConversationKey = string;\n\n/**\n * Builds a {@link ConversationKey} from its parts.\n *\n * Invariant: `parseConversationKey(makeConversationKey(p, c, t))` round-trips\n * exactly, provided `threadRootId` itself contains no `/`.\n */\nexport function makeConversationKey(\n platform: ChannelPlatform,\n conversationId: string,\n threadRootId?: string,\n): ConversationKey {\n return threadRootId\n ? `${platform}:${conversationId}/${threadRootId}`\n : `${platform}:${conversationId}`;\n}\n\n/**\n * Splits a {@link ConversationKey} into platform, conversation id, and optional\n * thread root. Throws on an unknown platform prefix.\n *\n * Gotcha: the thread separator is the LAST `/` — conversation ids may\n * themselves contain slashes (e.g. Mattermost `team/channel`).\n */\nexport function parseConversationKey(key: ConversationKey): {\n platform: ChannelPlatform;\n conversationId: string;\n threadRootId?: string;\n} {\n const sep = key.indexOf(\":\");\n const platform = key.slice(0, sep) as ChannelPlatform;\n if (!CHANNEL_PLATFORMS.includes(platform)) {\n throw new Error(`ConversationKey has unknown platform: ${key}`);\n }\n const rest = key.slice(sep + 1);\n // Thread separator is the LAST \"/\" — conversation ids may themselves contain slashes.\n const slash = rest.lastIndexOf(\"/\");\n if (slash === -1) return { platform, conversationId: rest };\n return { platform, conversationId: rest.slice(0, slash), threadRootId: rest.slice(slash + 1) };\n}\n\n/** A person (or bot) as the chat platform sees them — pre-IdentityPort resolution. */\nexport type ChannelActor = {\n platform: ChannelPlatform;\n /** Platform-native user id (Teams AAD object id, Slack user id, MM user id). */\n externalId: string;\n displayName: string;\n /** Teams tenant / MM team / Slack workspace, when known. */\n tenantId?: string;\n /** Identity hint for IdentityPort mapping, when the platform exposes it. */\n email?: string;\n isBot?: boolean;\n};\n\n/** Reference to a posted platform message. `raw` carries platform-native extras (e.g. Teams serviceUrl). */\nexport type MessageRef = {\n platform: ChannelPlatform;\n conversationKey: ConversationKey;\n /** Platform-native message id (Teams activity id, Slack ts, MM post id). */\n messageId: string;\n raw?: unknown;\n};\n\n/** Where to post: a conversation, optionally threaded under an existing message. */\nexport type ReplyTarget = {\n conversationKey: ConversationKey;\n /** Platform-native thread anchor; adapters thread under it where supported. */\n threadRef?: MessageRef;\n};\n\n/**\n * Declarative surface description consumed by the engine + egress pipeline.\n * Finalized per spec §13.1 by this plan — the conformance kit asserts adapters\n * honor `maxMessageLength` and `ackDeadlineMs`.\n */\nexport type SurfaceCapabilities = {\n canEditMessages: boolean;\n canDeleteMessages: boolean;\n supportsThreads: boolean;\n supportsCards: boolean;\n supportsTyping: boolean;\n supportsEphemeral: boolean;\n supportsReactions: boolean;\n /** Hard cap on a single posted message's text length; egress chunks at this. */\n maxMessageLength: number;\n /** IngressSink.onMessage must resolve within this (Slack ~3000, Teams 15000). */\n ackDeadlineMs: number;\n /** Minimum interval between successive edits of one message (egress throttle). */\n editThrottleMs: number;\n /** Outbound text dialect the adapter expects from the format layer. */\n textFormat: \"markdown\" | \"mrkdwn\" | \"adaptive-card\";\n};\n\n/** Per-binding egress policy (spec §7.2.4). */\nexport type MirrorMode = \"agent-only\" | \"full\" | \"chat-initiated\";\n\n/**\n * The conversationKey ↔ sessionId join, persisted by the host's BindingStore.\n * Deliberately not 1:1 (spec §5.1). Session ids never leak into chat payloads.\n */\nexport type Binding = {\n conversationKey: ConversationKey;\n sessionId: string;\n platform: ChannelPlatform;\n tenantId?: string;\n mirrorMode: MirrorMode;\n enabled: boolean;\n /** Host user id that created the binding (audit; authority stays with the host). */\n createdBy: string;\n /** ISO 8601. */\n createdAt: string;\n};\n\n/**\n * The one genuinely new meta type (spec §5) — rides on MessageMeta's extension\n * slot; hosts persist it untouched via the round-trip preservation contract.\n */\nexport type ChannelMetaExtensions = {\n channel?: {\n platform: ChannelPlatform;\n conversationKey: ConversationKey;\n /** Platform event id — the inbound dedupe key. */\n eventId: string;\n tenantId?: string;\n /** Pre-IdentityPort resolution attribution. */\n actor?: { externalId: string; displayName: string };\n /** Opaque platform-native ref of the source message. */\n messageRef?: unknown;\n /**\n * True when the message is addressed to the bot (an @mention, or a 1:1\n * chat with it); only such messages start an agent turn (spec §5.2, §5.7).\n * When an adapter leaves it unset, the engine falls back to `meta.mentions`.\n */\n mentioned?: boolean;\n };\n};\n\n/** A workspace message envelope whose meta block carries {@link ChannelMetaExtensions}. */\nexport type ChannelMessage = MessageV2<ChannelMetaExtensions>;\n\n/** What the engine hands an adapter to post. Format conversion is the adapter's job. */\nexport type OutboundMessage = {\n /** Markdown source; adapters convert via the format layer per their textFormat. */\n markdown: string;\n /** Rendering intent. Default \"text\". */\n kind?: \"text\" | \"question\" | \"status\" | \"error\";\n /** Options rendered as buttons where supportsCards; appended as a list otherwise. */\n options?: string[];\n};\n\n/** Fast-ack result of IngressSink.onMessage (spec §7.1.3). */\nexport type IngressAck = {\n status: \"accepted\" | \"duplicate\" | \"ignored\" | \"rejected\";\n reason?: string;\n};\n\n/** Inbound reaction event. Engine behavior deferred this milestone (Decision 7). */\nexport type InboundReaction = {\n conversationKey: ConversationKey;\n messageRef: MessageRef;\n emoji: string;\n actor: ChannelActor;\n action: \"added\" | \"removed\";\n eventId: string;\n};\n\n/** Non-message conversation lifecycle signals adapters may surface. */\nexport type ConversationEvent = {\n conversationKey: ConversationKey;\n kind: \"member_joined\" | \"member_left\" | \"conversation_renamed\" | \"conversation_deleted\";\n eventId: string;\n raw?: unknown;\n};\n\n/** Query for ChannelAdapter.lookupActor — backs the mentions-as-a-tool helper. */\nexport type ActorQuery = {\n externalId?: string;\n email?: string;\n /** Display-name substring match, platform semantics. */\n name?: string;\n};\n\n/** Result of verifyConversation — actionable problems, forge-tui preflight pattern. */\nexport type ConversationHealth = {\n ok: boolean;\n /** Human-actionable problem descriptions (\"bot is not a member of #x — invite it\"). */\n problems: string[];\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skaile/workspaces",
3
- "version": "6.11.0",
3
+ "version": "6.12.0",
4
4
  "description": "Skaile workspaces runtime — types, core, bridge, runner, store, connectors, and supporting layers as one publishable package",
5
5
  "type": "module",
6
6
  "packageManager": "bun@1.3.9",