@segmentstream/agent 0.20.3 → 0.21.2

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.
Files changed (67) hide show
  1. package/README.md +47 -4
  2. package/dist/_chunks/{build-metadata-Bgh-kwt7.mjs → build-metadata-Giw3R0jW.mjs} +1 -1
  3. package/dist/_chunks/{principal-DFcIfKSa.mjs → principal-69qoDdqy.mjs} +2 -0
  4. package/dist/extension/channels/tasks.d.ts +7 -0
  5. package/dist/extension/channels/tasks.mjs +9 -0
  6. package/dist/extension/connections/ontology.d.ts +1 -1
  7. package/dist/extension/hooks/authorization.mjs +1 -1
  8. package/dist/extension/instructions/conversations.d.ts +4 -1
  9. package/dist/extension/instructions/conversations.mjs +2 -1
  10. package/dist/extension/lib/actor.d.ts +39 -0
  11. package/dist/extension/lib/actor.mjs +48 -0
  12. package/dist/extension/lib/agent-task-channel.d.ts +45 -0
  13. package/dist/extension/lib/agent-task-channel.mjs +203 -0
  14. package/dist/extension/lib/agent-task.d.ts +127 -0
  15. package/dist/extension/lib/agent-task.mjs +183 -0
  16. package/dist/extension/lib/attachment-tools.mjs +1 -1
  17. package/dist/extension/lib/attachments.mjs +1 -1
  18. package/dist/extension/lib/build-metadata.mjs +1 -1
  19. package/dist/extension/lib/chat-post-confirmation.d.ts +2 -0
  20. package/dist/extension/lib/chat-post-confirmation.mjs +3 -2
  21. package/dist/extension/lib/confirmation-outcome.d.ts +1 -1
  22. package/dist/extension/lib/confirmations.d.ts +8 -3
  23. package/dist/extension/lib/confirmations.mjs +17 -5
  24. package/dist/extension/lib/conversation-runtime.mjs +12 -2
  25. package/dist/extension/lib/deferred-confirmations.mjs +5 -4
  26. package/dist/extension/lib/group-routing/dequeue.mjs +1 -1
  27. package/dist/extension/lib/ontology-connection.d.ts +18 -16
  28. package/dist/extension/lib/ontology-connection.mjs +47 -42
  29. package/dist/extension/lib/ontology-file-call.mjs +26 -21
  30. package/dist/extension/lib/ontology-tools.d.ts +12 -9
  31. package/dist/extension/lib/ontology-tools.mjs +42 -33
  32. package/dist/extension/lib/runtime-envelope.mjs +1 -1
  33. package/dist/extension/lib/sandbox-session.mjs +1 -1
  34. package/dist/extension/lib/stored-files.mjs +3 -2
  35. package/dist/extension/lib/telegram/adapter.mjs +5 -5
  36. package/dist/extension/lib/telegram/attachments-send.mjs +4 -4
  37. package/dist/extension/lib/telegram/callbacks.mjs +1 -1
  38. package/dist/extension/lib/telegram/confirmation-expiry.mjs +2 -2
  39. package/dist/extension/lib/telegram/confirmations.mjs +2 -2
  40. package/dist/extension/lib/telegram/deferred-confirmations.mjs +1 -1
  41. package/dist/extension/lib/telegram/durable-typing.mjs +1 -1
  42. package/dist/extension/lib/telegram/files.mjs +1 -1
  43. package/dist/extension/lib/telegram/health.mjs +1 -1
  44. package/dist/extension/lib/telegram/held-approvals.d.ts +1 -1
  45. package/dist/extension/lib/telegram/inbound.mjs +1 -1
  46. package/dist/extension/lib/telegram/lifecycle.mjs +6 -5
  47. package/dist/extension/lib/telegram/principal.d.ts +4 -1
  48. package/dist/extension/lib/telegram/principal.mjs +1 -1
  49. package/dist/extension/lib/telegram/silent.mjs +1 -1
  50. package/dist/extension/lib/telegram/structured.mjs +1 -1
  51. package/dist/extension/lib/telegram/turn-errors.mjs +1 -1
  52. package/dist/extension/lib/telegram/workspace-action.mjs +4 -3
  53. package/dist/extension/model.mjs +2 -2
  54. package/dist/extension/tools/attachments_discard.d.ts +1 -7
  55. package/dist/extension/tools/attachments_discard.mjs +3 -1
  56. package/dist/extension/tools/attachments_list.d.ts +1 -7
  57. package/dist/extension/tools/attachments_list.mjs +3 -1
  58. package/dist/extension/tools/attachments_promote.d.ts +1 -4
  59. package/dist/extension/tools/attachments_promote.mjs +8 -6
  60. package/dist/extension/tools/attachments_read.d.ts +1 -8
  61. package/dist/extension/tools/attachments_read.mjs +3 -1
  62. package/dist/extension/tools/attachments_send.d.ts +1 -1
  63. package/dist/extension/tools/attachments_send.mjs +3 -1
  64. package/dist/extension/tools/attachments_table.d.ts +1 -3
  65. package/dist/extension/tools/attachments_table.mjs +3 -1
  66. package/dist/extension/tools/questions_ask.mjs +14 -1
  67. package/package.json +2 -2
@@ -4,7 +4,8 @@ import { createRequire as __eveCreateRequire } from "node:module";
4
4
  const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
- import { i as memberIdOf, u as runtimeEnvelope } from "../../_chunks/principal-DFcIfKSa.mjs";
7
+ import { u as runtimeEnvelope } from "../../_chunks/principal-69qoDdqy.mjs";
8
+ import { actorKey, actorOf } from "./actor.mjs";
8
9
  import { isChatPost } from "./chat-post-confirmation.mjs";
9
10
  import { actionApproval, confirmations, inputHash } from "./confirmations.mjs";
10
11
  import { ontologyTools } from "./ontology-tools.mjs";
@@ -21,6 +22,9 @@ function receipt(saved, dispatched = saved.dispatched) {
21
22
  ...dispatched ? { dispatched } : {}
22
23
  };
23
24
  }
25
+ function ownerOf(actor) {
26
+ return actor === void 0 ? void 0 : actor.kind === "member" ? actor.memberId : actorKey(actor);
27
+ }
24
28
  function releaseOntologyFilePayloads() {
25
29
  snapshots.update((all) => Object.fromEntries(Object.entries(all).map(([id, saved]) => [id, receipt(saved)])));
26
30
  }
@@ -35,27 +39,27 @@ function releasePayload(callId) {
35
39
  }
36
40
  function ontologyFileCall(texts) {
37
41
  const policy = (principal) => actionApproval({
38
- labels: async (memberId, _action, input) => {
39
- const saved = bound(input, memberId);
40
- return ontologyTools({ principal }).labels(memberId, saved.name, saved.arguments);
42
+ labels: async (actor, _action, input) => {
43
+ const saved = bound(input, ownerOf(actor));
44
+ return ontologyTools({ principal }).labels(actor, saved.name, saved.arguments);
41
45
  },
42
- describe: async (memberId, _action, input) => {
43
- const saved = bound(input, memberId);
44
- return ontologyTools({ principal }).describe(memberId, saved.name, saved.arguments);
46
+ describe: async (actor, _action, input) => {
47
+ const saved = bound(input, ownerOf(actor));
48
+ return ontologyTools({ principal }).describe(actor, saved.name, saved.arguments);
45
49
  },
46
50
  texts
47
51
  });
48
- function bound(input, memberId) {
52
+ function bound(input, owner) {
49
53
  const saved = snapshots.get()[String(input.snapshot)];
50
- if (saved === void 0 || saved.memberId !== memberId || saved.dispatched || saved.arguments === void 0) throw new Error("The file call is unavailable or already dispatched.");
54
+ if (saved === void 0 || saved.memberId !== owner || saved.dispatched || saved.arguments === void 0) throw new Error("The file call is unavailable or already dispatched.");
51
55
  return {
52
56
  ...saved,
53
57
  arguments: saved.arguments
54
58
  };
55
59
  }
56
- function request(callId, input, memberId) {
60
+ function request(callId, input, owner) {
57
61
  const saved = snapshots.get()[callId];
58
- if (saved === void 0 || saved.memberId !== memberId || saved.requestHash !== inputHash(input)) throw new Error("The file call belongs to another member or input.");
62
+ if (saved === void 0 || saved.memberId !== owner || saved.requestHash !== inputHash(input)) throw new Error("The file call belongs to another member or input.");
59
63
  return {
60
64
  snapshot: callId,
61
65
  digest: saved.digest
@@ -83,11 +87,11 @@ function ontologyFileCall(texts) {
83
87
  approval: {
84
88
  async request(ctx) {
85
89
  try {
86
- const memberId = memberIdOf(ctx.session.auth.current);
90
+ const owner = ownerOf(actorOf(ctx.session.auth.current));
87
91
  const input = ctx.toolInput;
88
- if (memberId === void 0 || input === void 0 || isChatPost(input.name) || input.name.startsWith("ontology_") || input.name.includes("__") || !/^[a-z][a-z0-9_]*$/.test(input.name)) return {
92
+ if (owner === void 0 || input === void 0 || isChatPost(input.name) || input.name.startsWith("ontology_") || input.name.includes("__") || !/^[a-z][a-z0-9_]*$/.test(input.name)) return {
89
93
  type: "denied",
90
- reason: "A paired member and a direct ontology tool are required."
94
+ reason: "A paired member or a task, and a direct ontology tool, are required."
91
95
  };
92
96
  if (snapshots.get()[ctx.callId] === void 0) {
93
97
  const { content } = await sandboxFile(ctx, input.arguments_file, { maximumBytes: 1048576 });
@@ -97,7 +101,7 @@ function ontologyFileCall(texts) {
97
101
  snapshots.update((all) => ({
98
102
  ...all,
99
103
  [ctx.callId]: {
100
- memberId,
104
+ memberId: owner,
101
105
  requestHash: inputHash(input),
102
106
  name: input.name,
103
107
  digest: inputHash(args),
@@ -107,7 +111,7 @@ function ontologyFileCall(texts) {
107
111
  }
108
112
  const decision = await policy(ctx.session.auth.current).request({
109
113
  ...ctx,
110
- toolInput: request(ctx.callId, input, memberId)
114
+ toolInput: request(ctx.callId, input, owner)
111
115
  });
112
116
  if (decision === "denied" || decision === false || typeof decision === "object" && decision?.type === "denied") {
113
117
  const current = confirmations.get()[ctx.callId];
@@ -128,7 +132,7 @@ function ontologyFileCall(texts) {
128
132
  ...ctx,
129
133
  request: {
130
134
  ...ctx.request,
131
- toolInput: request(ctx.request.callId, ctx.request.toolInput, memberIdOf(ctx.request.principal))
135
+ toolInput: request(ctx.request.callId, ctx.request.toolInput, ownerOf(actorOf(ctx.request.principal)))
132
136
  }
133
137
  });
134
138
  if (decision.status === "allowed" && ctx.response.decision === "deny") releasePayload(ctx.request.callId);
@@ -142,8 +146,9 @@ function ontologyFileCall(texts) {
142
146
  }
143
147
  },
144
148
  async execute(input, ctx) {
145
- const memberId = memberIdOf(ctx.session.auth.current);
146
- const saved = bound(request(ctx.callId, input, memberId), memberId);
149
+ const actor = actorOf(ctx.session.auth.current);
150
+ const owner = ownerOf(actor);
151
+ const saved = bound(request(ctx.callId, input, owner), owner);
147
152
  const confirmation = confirmations.get()[ctx.callId];
148
153
  if (confirmation !== void 0 && confirmation.status !== "consumed") throw new Error("The file call has not been confirmed.");
149
154
  const result = await ontologyTools({
@@ -154,13 +159,13 @@ function ontologyFileCall(texts) {
154
159
  callId: ctx.callId
155
160
  }),
156
161
  beforeCall: async () => {
157
- bound({ snapshot: ctx.callId }, memberId);
162
+ bound({ snapshot: ctx.callId }, owner);
158
163
  snapshots.update((all) => ({
159
164
  ...all,
160
165
  [ctx.callId]: receipt(saved, true)
161
166
  }));
162
167
  }
163
- }).rpc(memberId, "tools/call", {
168
+ }).rpc(actor, "tools/call", {
164
169
  name: saved.name,
165
170
  arguments: saved.arguments
166
171
  });
@@ -1,5 +1,6 @@
1
1
  import { type RuntimeEnvelope } from "./runtime-envelope.js";
2
2
  import type { SessionAuthContext } from "eve/context";
3
+ import { type OntologyActor } from "./actor.js";
3
4
  import type { ActionAnnotations } from "./confirmations.js";
4
5
  import { type Environment } from "./environment.js";
5
6
  import { type RuntimeToken } from "./runtime-token.js";
@@ -27,21 +28,23 @@ export declare function ontologyTools(options?: {
27
28
  readonly fetch?: typeof fetch;
28
29
  /** Install a durable dispatch fence after safe metadata/auth work, immediately before the action request. */
29
30
  readonly beforeCall?: (name: string) => Promise<void>;
31
+ /** Reads a task's live secret; the session's task state unless a test passes another. */
32
+ readonly secret?: (taskId: string) => string | undefined;
30
33
  /**
31
- * What a tools/list said about runtime-source support, per member, shared by the clients of
32
- * one caller. A large catalog's listing takes megabytes and seconds; without it, every client
34
+ * What a tools/list said about runtime-source support, per member or task, shared by the
35
+ * clients of one caller. A large catalog's listing takes megabytes and seconds; without it, every client
33
36
  * lists the whole catalog again before its first call.
34
37
  */
35
38
  readonly runtimeSources?: Map<string, boolean>;
36
39
  }): {
37
- rpc: (memberId: string, method: string, params: Record<string, unknown>, signal?: AbortSignal) => Promise<Record<string, unknown>>;
38
- list(memberId: string): Promise<Record<string, unknown>[]>;
39
- supportsRuntimeSource(memberId: string, signal?: AbortSignal): Promise<boolean>;
40
- supportsChatPosting(memberId: string): Promise<boolean>;
41
- labels(memberId: string, action: string, input?: Readonly<Record<string, unknown>>, signal?: AbortSignal): Promise<ActionAnnotations>;
42
- describe(memberId: string, action: string, input: Readonly<Record<string, unknown>>): Promise<import("./confirmation-description.js").ConfirmationDescription>;
40
+ rpc: (actor: OntologyActor, method: string, params: Record<string, unknown>, signal?: AbortSignal) => Promise<Record<string, unknown>>;
41
+ list(actor: OntologyActor): Promise<Record<string, unknown>[]>;
42
+ supportsRuntimeSource(actor: OntologyActor, signal?: AbortSignal): Promise<boolean>;
43
+ supportsChatPosting(actor: OntologyActor): Promise<boolean>;
44
+ labels(actor: OntologyActor, action: string, input?: Readonly<Record<string, unknown>>, signal?: AbortSignal): Promise<ActionAnnotations>;
45
+ describe(actor: OntologyActor, action: string, input: Readonly<Record<string, unknown>>): Promise<import("./confirmation-description.js").ConfirmationDescription>;
43
46
  };
44
- export declare function ontologyToolLabels(options?: Parameters<typeof ontologyTools>[0]): (memberId: string, action: string, input?: Readonly<Record<string, unknown>>, signal?: AbortSignal) => Promise<ActionAnnotations>;
47
+ export declare function ontologyToolLabels(options?: Parameters<typeof ontologyTools>[0]): (actor: OntologyActor, action: string, input?: Readonly<Record<string, unknown>>, signal?: AbortSignal) => Promise<ActionAnnotations>;
45
48
  /** MCP normalizes an authored camelCase action to snake_case. */
46
49
  export declare function actionToolName(entity: string, action: string): string;
47
50
  /** One target contract for native and MCP attachment promotion; never trust supplied safety hints. */
@@ -4,11 +4,13 @@ import { createRequire as __eveCreateRequire } from "node:module";
4
4
  const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
- import { appOrigin } from "./environment.mjs";
8
- import { c as compatibleRuntimeEnvelope, i as memberIdOf, r as identityProviderOf, s as RUNTIME_SOURCE_PROTOCOL, u as runtimeEnvelope } from "../../_chunks/principal-DFcIfKSa.mjs";
9
7
  import { redactDiagnostic } from "./diagnostics.mjs";
10
- import { describeConfirmation, object } from "./confirmation-description.mjs";
8
+ import { appOrigin } from "./environment.mjs";
11
9
  import { runtimeToken } from "./runtime-token.mjs";
10
+ import "./agent-task.mjs";
11
+ import { c as compatibleRuntimeEnvelope, s as RUNTIME_SOURCE_PROTOCOL, u as runtimeEnvelope } from "../../_chunks/principal-69qoDdqy.mjs";
12
+ import { describeConfirmation, object } from "./confirmation-description.mjs";
13
+ import { actorHeaders, actorKey, actorOf } from "./actor.mjs";
12
14
  import { describeChatPost, isChatPost, supportsChatPost } from "./chat-post-confirmation.mjs";
13
15
  import { randomUUID } from "node:crypto";
14
16
  var OntologyToolRejected = class extends Error {
@@ -29,29 +31,36 @@ var OntologyFileUnavailable = class extends Error {
29
31
  };
30
32
  function ontologyTools(options = {}) {
31
33
  const runtimeSources = options.runtimeSources ?? new Map();
32
- async function rpc(memberId, method, params, signal) {
34
+ async function rpc(actor, method, params, signal) {
35
+ const key = actorKey(actor);
36
+ const current = actorOf(options.principal);
37
+ const own = current !== void 0 && actorKey(current) === key ? options.principal : null;
33
38
  if (method === "tools/call") {
34
- const envelope = options.envelope ?? runtimeEnvelope({ principal: memberIdOf(options.principal) === memberId ? options.principal : null });
35
- if (envelope.source !== void 0 && !runtimeSources.has(memberId)) await rpc(memberId, "tools/list", {}, signal);
39
+ const envelope = options.envelope ?? runtimeEnvelope({ principal: own });
40
+ if (envelope.source !== void 0 && !runtimeSources.has(key)) await rpc(actor, "tools/list", {}, signal);
36
41
  params = {
37
42
  ...params,
38
43
  arguments: {
39
44
  ...object(params.arguments),
40
- _segmentstream: compatibleRuntimeEnvelope(envelope, runtimeSources.get(memberId) === true)
45
+ _segmentstream: compatibleRuntimeEnvelope(envelope, runtimeSources.get(key) === true)
41
46
  }
42
47
  };
43
48
  }
44
- const provider = memberIdOf(options.principal) === memberId ? identityProviderOf(options.principal) : void 0;
45
49
  const credential = await (options.token ?? runtimeToken)();
46
50
  const secrets = new Set([credential]);
47
51
  if (method === "tools/call") await options.beforeCall?.(String(params.name));
48
52
  try {
53
+ const acting = actorHeaders({
54
+ actor,
55
+ principal: own,
56
+ secret: options.secret
57
+ });
58
+ secrets.add(acting["X-SegmentStream-Agent-Task"] ?? "");
49
59
  const response = await (options.fetch ?? fetch)(`${appOrigin(options.environment ?? process.env)}/mcp`, {
50
60
  method: "POST",
51
61
  headers: {
52
62
  authorization: `Bearer ${credential}`,
53
- "X-SegmentStream-Act-As": memberId,
54
- ...provider === void 0 ? {} : { "X-SegmentStream-Identity-Provider": provider },
63
+ ...acting,
55
64
  "content-type": "application/json",
56
65
  accept: "application/json, text/event-stream",
57
66
  "mcp-protocol-version": "2025-11-25"
@@ -69,7 +78,7 @@ function ontologyTools(options = {}) {
69
78
  const body = object(await response.json());
70
79
  if (body.error !== void 0) throw new Error("Ontology metadata unavailable.", { cause: body.error });
71
80
  const result = object(body.result);
72
- if (method === "tools/list" && Array.isArray(result.tools)) runtimeSources.set(memberId, result.tools.map(object).some((tool) => object(tool._meta)[RUNTIME_SOURCE_PROTOCOL] === 1));
81
+ if (method === "tools/list" && Array.isArray(result.tools)) runtimeSources.set(key, result.tools.map(object).some((tool) => object(tool._meta)[RUNTIME_SOURCE_PROTOCOL] === 1));
73
82
  if (result.isError === true) {
74
83
  const failure = object(result.structuredContent);
75
84
  if (method === "tools/call" && params.name === "files_download" && failure.retryable === true && ["ontology_updating", "storage_unavailable"].includes(String(failure.error))) throw new OntologyFileUnavailable(String(failure.error), typeof failure.request_id === "string" ? failure.request_id : void 0, { cause: result });
@@ -104,13 +113,13 @@ function ontologyTools(options = {}) {
104
113
  throw new Error(`The ontology request failed (${reference}).`, { cause: diagnostic });
105
114
  }
106
115
  }
107
- async function toolFor(memberId, action, signal) {
108
- const result = await rpc(memberId, "tools/list", {}, signal);
116
+ async function toolFor(actor, action, signal) {
117
+ const result = await rpc(actor, "tools/list", {}, signal);
109
118
  const tools = Array.isArray(result.tools) ? result.tools.map(object) : [];
110
119
  const bareName = action.split("__").at(-1);
111
120
  let tool = tools.find((candidate) => candidate.name === bareName);
112
121
  if (tool === void 0 && tools.some((item) => item.name === "ontology_describe_tool")) {
113
- const inspected = await rpc(memberId, "tools/call", {
122
+ const inspected = await rpc(actor, "tools/call", {
114
123
  name: "ontology_describe_tool",
115
124
  arguments: { name: bareName }
116
125
  }, signal);
@@ -123,17 +132,17 @@ function ontologyTools(options = {}) {
123
132
  tools
124
133
  };
125
134
  }
126
- async function resolve(memberId, action, input, signal, depth = 0) {
135
+ async function resolve(actor, action, input, signal, depth = 0) {
127
136
  if (depth > 3) throw new Error("Too many nested ontology tools.");
128
- const found = await toolFor(memberId, action, signal);
137
+ const found = await toolFor(actor, action, signal);
129
138
  if (depth > 0 && isChatPost(String(found.tool.name))) throw new Error("Exact chat posting must use the direct chat_post_message tool.");
130
139
  if (found.tool.name === "ontology_call_tool") {
131
140
  if (typeof input.name !== "string") throw new Error("A target tool is required.");
132
- return resolve(memberId, input.name, object(input.arguments), signal, depth + 1);
141
+ return resolve(actor, input.name, object(input.arguments), signal, depth + 1);
133
142
  }
134
143
  if (found.tool.name === "attachments_promote") {
135
144
  const target = promotionTarget(input);
136
- return resolve(memberId, target.action, target.input, signal, depth + 1);
145
+ return resolve(actor, target.action, target.input, signal, depth + 1);
137
146
  }
138
147
  return {
139
148
  ...found,
@@ -142,28 +151,28 @@ function ontologyTools(options = {}) {
142
151
  }
143
152
  return {
144
153
  rpc,
145
- async list(memberId) {
146
- const result = await rpc(memberId, "tools/list", {});
154
+ async list(actor) {
155
+ const result = await rpc(actor, "tools/list", {});
147
156
  return Array.isArray(result.tools) ? result.tools.map(object) : [];
148
157
  },
149
- async supportsRuntimeSource(memberId, signal) {
150
- if (!runtimeSources.has(memberId)) await rpc(memberId, "tools/list", {}, signal);
151
- return runtimeSources.get(memberId) === true;
158
+ async supportsRuntimeSource(actor, signal) {
159
+ if (!runtimeSources.has(actorKey(actor))) await rpc(actor, "tools/list", {}, signal);
160
+ return runtimeSources.get(actorKey(actor)) === true;
152
161
  },
153
- async supportsChatPosting(memberId) {
154
- const result = await rpc(memberId, "tools/list", {});
162
+ async supportsChatPosting(actor) {
163
+ const result = await rpc(actor, "tools/list", {});
155
164
  return Array.isArray(result.tools) && result.tools.map(object).some(supportsChatPost);
156
165
  },
157
- async labels(memberId, action, input = {}, signal) {
158
- const { tool } = await resolve(memberId, action, input, signal);
166
+ async labels(actor, action, input = {}, signal) {
167
+ const { tool } = await resolve(actor, action, input, signal);
159
168
  return {
160
169
  ...object(tool.annotations),
161
170
  confirmation: object(object(tool.inputSchema).properties)._confirmation !== void 0
162
171
  };
163
172
  },
164
- async describe(memberId, action, input) {
173
+ async describe(actor, action, input) {
165
174
  const signal = AbortSignal.timeout(15e3);
166
- const resolved = await resolve(memberId, action, input, signal);
175
+ const resolved = await resolve(actor, action, input, signal);
167
176
  const { tool, tools } = resolved;
168
177
  input = resolved.input;
169
178
  action = String(tool.name);
@@ -171,7 +180,7 @@ function ontologyTools(options = {}) {
171
180
  if (!supportsChatPost(tool)) throw new Error("The ontology does not support exact chat confirmations.");
172
181
  const read = async (name, args) => {
173
182
  if (!tools.some((candidate) => candidate.name === name && object(candidate.annotations).readOnlyHint === true)) throw new Error("The chat preview reads are unavailable.");
174
- const result = await rpc(memberId, "tools/call", {
183
+ const result = await rpc(actor, "tools/call", {
175
184
  name,
176
185
  arguments: args
177
186
  }, signal);
@@ -190,7 +199,7 @@ function ontologyTools(options = {}) {
190
199
  }
191
200
  let entities = [];
192
201
  try {
193
- const catalog = await rpc(memberId, "resources/read", { uri: "ontology://catalog" }, signal);
202
+ const catalog = await rpc(actor, "resources/read", { uri: "ontology://catalog" }, signal);
194
203
  const text = object(Array.isArray(catalog.contents) ? catalog.contents[0] : void 0).text;
195
204
  const manifest = object(typeof text === "string" ? JSON.parse(text) : void 0);
196
205
  entities = Array.isArray(manifest.entities) ? manifest.entities.map(object) : [];
@@ -217,9 +226,9 @@ function ontologyTools(options = {}) {
217
226
  async read(entityName, id) {
218
227
  const name = actionToolName(entityName, "get");
219
228
  try {
220
- const permitted = (await toolFor(memberId, name, signal)).tool;
229
+ const permitted = (await toolFor(actor, name, signal)).tool;
221
230
  if (object(permitted.annotations).readOnlyHint !== true) return;
222
- const result = await rpc(memberId, "tools/call", {
231
+ const result = await rpc(actor, "tools/call", {
223
232
  name,
224
233
  arguments: { id }
225
234
  }, signal);
@@ -4,5 +4,5 @@ import { createRequire as __eveCreateRequire } from "node:module";
4
4
  const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
- import { c as compatibleRuntimeEnvelope, d as telegramRuntimeSource, l as principalRuntimeSource, s as RUNTIME_SOURCE_PROTOCOL, u as runtimeEnvelope } from "../../_chunks/principal-DFcIfKSa.mjs";
7
+ import { c as compatibleRuntimeEnvelope, d as telegramRuntimeSource, l as principalRuntimeSource, s as RUNTIME_SOURCE_PROTOCOL, u as runtimeEnvelope } from "../../_chunks/principal-69qoDdqy.mjs";
8
8
  export { RUNTIME_SOURCE_PROTOCOL, compatibleRuntimeEnvelope, principalRuntimeSource, runtimeEnvelope, telegramRuntimeSource };
@@ -4,8 +4,8 @@ import { createRequire as __eveCreateRequire } from "node:module";
4
4
  const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
- import { posix } from "node:path";
8
7
  import { defineState } from "eve/context";
8
+ import { posix } from "node:path";
9
9
  const SANDBOX_MARKER_PATH = "/workspace/.segmentstream/sandbox.json";
10
10
  const SANDBOX_ATTACHMENTS_DIRECTORY = "/workspace/.eve/attachments";
11
11
  const SANDBOX_MAXIMUM_AGE_MS = 864e5;
@@ -4,9 +4,10 @@ import { createRequire as __eveCreateRequire } from "node:module";
4
4
  const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
- import { i as memberIdOf } from "../../_chunks/principal-DFcIfKSa.mjs";
8
7
  import { redactDiagnostic } from "./diagnostics.mjs";
8
+ import { i as memberIdOf } from "../../_chunks/principal-69qoDdqy.mjs";
9
9
  import { object } from "./confirmation-description.mjs";
10
+ import { member } from "./actor.mjs";
10
11
  import { OntologyFileUnavailable, ontologyTools } from "./ontology-tools.mjs";
11
12
  import { createHash } from "node:crypto";
12
13
  async function readStoredFile(input, principal, options = {}) {
@@ -18,7 +19,7 @@ async function readStoredFile(input, principal, options = {}) {
18
19
  });
19
20
  const readGrant = async () => {
20
21
  for (let attempt = 0;; attempt++) try {
21
- return await tools.rpc(memberId, "tools/call", {
22
+ return await tools.rpc(member(memberId), "tools/call", {
22
23
  name: "files_download",
23
24
  arguments: input
24
25
  });
@@ -4,14 +4,15 @@ import { createRequire as __eveCreateRequire } from "node:module";
4
4
  const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
+ import { appOrigin, channelsEnabled, proxyEnvironment, runtimeIdentityEnvironment, webhookSecret } from "../environment.mjs";
8
+ import { runtimeToken } from "../runtime-token.mjs";
9
+ import { runtimeTokenVerifier } from "../runtime-identity.mjs";
7
10
  import { telegramText, withTelegramTexts } from "./texts.mjs";
8
11
  import { manifestOf } from "../../config.mjs";
9
- import { appOrigin, channelsEnabled, proxyEnvironment, runtimeIdentityEnvironment, webhookSecret } from "../environment.mjs";
10
- import { n as conversationLanguage, o as telegramPrincipal } from "../../../_chunks/principal-DFcIfKSa.mjs";
12
+ import { n as conversationLanguage, o as telegramPrincipal } from "../../../_chunks/principal-69qoDdqy.mjs";
11
13
  import { object } from "../confirmation-description.mjs";
12
14
  import { confirmationLocale } from "./confirmation-text.mjs";
13
15
  import { telegramSendScope } from "./send-queue.mjs";
14
- import { runtimeToken } from "../runtime-token.mjs";
15
16
  import { conversations } from "../conversations.mjs";
16
17
  import { withDeliveryDiagnostics } from "./delivery-diagnostics.mjs";
17
18
  import { d as failureText, h as withDeliveryLocale, i as withReplacedText, m as safeTelegramFetch, n as currentInboundRequest, o as currentLocale, p as reportTelegramError, r as runInboundRequest, t as InboundRequest } from "../../../_chunks/inbound-request-gJ5wpsBF.mjs";
@@ -23,7 +24,7 @@ import { MAXIMUM_DOWNLOAD_BYTES, connectionProxy } from "../connection-proxy.mjs
23
24
  import { dispatchStructuredMessage, structuredMessage } from "./structured.mjs";
24
25
  import { scopedAddress, sessionPolicy } from "./sessions.mjs";
25
26
  import { handleWorkspaceCallback, isWorkspaceCallback } from "./callbacks.mjs";
26
- import { t as agentBuild } from "../../../_chunks/build-metadata-Bgh-kwt7.mjs";
27
+ import { t as agentBuild } from "../../../_chunks/build-metadata-Giw3R0jW.mjs";
27
28
  import { attachmentLifecycle } from "./lifecycle.mjs";
28
29
  import { observedMessages } from "./observed.mjs";
29
30
  import { expireDeferredCards, handleDeferredCallback, isDeferredCallback } from "./deferred-confirmations.mjs";
@@ -34,7 +35,6 @@ import { agentIdentities } from "../identities.mjs";
34
35
  import { interimTexts, replyDelivery } from "./silent.mjs";
35
36
  import { handleConfirmationCallback, telegramConfirmationEvents } from "./confirmations.mjs";
36
37
  import { captureRouteDecider, captureTelegramFetch, conversationIdentities, recordGateDecision, telegramConversationCapture } from "./conversations.mjs";
37
- import { runtimeTokenVerifier } from "../runtime-identity.mjs";
38
38
  import { botIdentityCache } from "./bot.mjs";
39
39
  import { gatewayMediaCapabilities, planMedia } from "./media-policy.mjs";
40
40
  import { agentChats } from "./chats.mjs";
@@ -4,15 +4,15 @@ import { createRequire as __eveCreateRequire } from "node:module";
4
4
  const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
- import { appOrigin, channelsEnabled, proxyEnvironment } from "../environment.mjs";
8
- import "../../../_chunks/principal-DFcIfKSa.mjs";
9
7
  import { redactDiagnostic } from "../diagnostics.mjs";
8
+ import { appOrigin, channelsEnabled, proxyEnvironment } from "../environment.mjs";
9
+ import { runtimeToken } from "../runtime-token.mjs";
10
+ import "../../../_chunks/principal-69qoDdqy.mjs";
10
11
  import { confirmationLocale } from "./confirmation-text.mjs";
11
12
  import { inTelegramSendQueue, telegramSendScope } from "./send-queue.mjs";
12
- import { runtimeToken } from "../runtime-token.mjs";
13
13
  import { d as failureText, f as formattingRefused, l as customerMessage, p as reportTelegramError } from "../../../_chunks/inbound-request-gJ5wpsBF.mjs";
14
14
  import { MAXIMUM_PROXY_BODY_BYTES, connectionProxy } from "../connection-proxy.mjs";
15
- import { ACT_AS_HEADER } from "../ontology-connection.mjs";
15
+ import { ACT_AS_HEADER } from "../actor.mjs";
16
16
  import { AttachmentError, CONVERSATION_HEADER, SESSION_HEADER } from "../attachments.mjs";
17
17
  import { TELEGRAM_PLACEHOLDER_TOKEN, TELEGRAM_PROXY_ORIGIN, telegramProxyFetch } from "./proxy-fetch.mjs";
18
18
  import { attachmentOwner } from "../attachment-tools.mjs";
@@ -6,7 +6,7 @@ __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
7
  import { admitMessage } from "../admission.mjs";
8
8
  import { telegramText } from "./texts.mjs";
9
- import { d as telegramRuntimeSource, i as memberIdOf, o as telegramPrincipal, u as runtimeEnvelope } from "../../../_chunks/principal-DFcIfKSa.mjs";
9
+ import { d as telegramRuntimeSource, i as memberIdOf, o as telegramPrincipal, u as runtimeEnvelope } from "../../../_chunks/principal-69qoDdqy.mjs";
10
10
  import { object } from "../confirmation-description.mjs";
11
11
  import { n as currentInboundRequest, p as reportTelegramError } from "../../../_chunks/inbound-request-gJ5wpsBF.mjs";
12
12
  import { workspaceAction } from "./workspace-action.mjs";
@@ -4,10 +4,10 @@ import { createRequire as __eveCreateRequire } from "node:module";
4
4
  const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
- import { withTelegramTexts } from "./texts.mjs";
8
7
  import { proxyEnvironment } from "../environment.mjs";
9
- import { telegramSendScope } from "./send-queue.mjs";
10
8
  import { runtimeToken } from "../runtime-token.mjs";
9
+ import { withTelegramTexts } from "./texts.mjs";
10
+ import { telegramSendScope } from "./send-queue.mjs";
11
11
  import { conversations } from "../conversations.mjs";
12
12
  import { m as safeTelegramFetch, p as reportTelegramError } from "../../../_chunks/inbound-request-gJ5wpsBF.mjs";
13
13
  import { connectionProxy } from "../connection-proxy.mjs";
@@ -5,7 +5,7 @@ const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
7
  import { telegramText } from "./texts.mjs";
8
- import { i as memberIdOf, o as telegramPrincipal } from "../../../_chunks/principal-DFcIfKSa.mjs";
8
+ import { i as memberIdOf, o as telegramPrincipal } from "../../../_chunks/principal-69qoDdqy.mjs";
9
9
  import { humanText } from "../confirmation-description.mjs";
10
10
  import { renderConfirmation, withConfirmationText } from "./confirmation-text.mjs";
11
11
  import { chatPostCard, chatPostCardStatus, chatPostReceipt, withChatPostCard } from "./chat-post-card.mjs";
@@ -17,9 +17,9 @@ import { confirmations } from "../confirmations.mjs";
17
17
  import { formatAddress, scopedAddress } from "./sessions.mjs";
18
18
  import { postDeferredCard } from "./deferred-confirmations.mjs";
19
19
  import { answerMarker, isPendingQuestion, pendingQuestions, questionKey } from "../questions.mjs";
20
+ import { call } from "eve/events";
20
21
  import { createHash } from "node:crypto";
21
22
  import { telegramTextLinks } from "@segmentstream-cloud/ontology/telegram";
22
- import { call } from "eve/events";
23
23
  const PREFIX = "ss-confirm:";
24
24
  function shortHash(value) {
25
25
  return createHash("sha256").update(value).digest("hex").slice(0, 20);
@@ -5,7 +5,7 @@ const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
7
  import { telegramText, withTelegramLocale } from "./texts.mjs";
8
- import { o as telegramPrincipal } from "../../../_chunks/principal-DFcIfKSa.mjs";
8
+ import { o as telegramPrincipal } from "../../../_chunks/principal-69qoDdqy.mjs";
9
9
  import { humanText } from "../confirmation-description.mjs";
10
10
  import { renderConfirmation, withConfirmationText } from "./confirmation-text.mjs";
11
11
  import { chatPostCard, chatPostCardStatus, chatPostReceipt, withChatPostCard } from "./chat-post-card.mjs";
@@ -5,8 +5,8 @@ const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
7
  import { channelsEnabled, proxyEnvironment } from "../environment.mjs";
8
- import { redactTelegramDiagnostic } from "./diagnostic-redaction.mjs";
9
8
  import { runtimeToken } from "../runtime-token.mjs";
9
+ import { redactTelegramDiagnostic } from "./diagnostic-redaction.mjs";
10
10
  import { conversationEvent, conversations } from "../conversations.mjs";
11
11
  import { p as reportTelegramError } from "../../../_chunks/inbound-request-gJ5wpsBF.mjs";
12
12
  import { connectionProxy } from "../connection-proxy.mjs";
@@ -4,7 +4,7 @@ import { createRequire as __eveCreateRequire } from "node:module";
4
4
  const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
- import { n as conversationLanguage } from "../../../_chunks/principal-DFcIfKSa.mjs";
7
+ import { n as conversationLanguage } from "../../../_chunks/principal-69qoDdqy.mjs";
8
8
  import { d as failureText, p as reportTelegramError } from "../../../_chunks/inbound-request-gJ5wpsBF.mjs";
9
9
  import { describableImage, describeReceivedImage } from "./images.mjs";
10
10
  import { MAXIMUM_ATTACHMENT_BYTES, attachmentUrl } from "../attachments.mjs";
@@ -4,8 +4,8 @@ import { createRequire as __eveCreateRequire } from "node:module";
4
4
  const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
- import { t as agentBuild } from "../../../_chunks/build-metadata-Bgh-kwt7.mjs";
8
7
  import { runtimeRequestFailure } from "./runtime-request.mjs";
8
+ import { t as agentBuild } from "../../../_chunks/build-metadata-Giw3R0jW.mjs";
9
9
  import { GET } from "eve/channels";
10
10
  const HEALTH_ROUTE = "/eve/v1/telegram/health";
11
11
  function healthRoute(input) {
@@ -22,6 +22,6 @@ export declare function releaseHeldApproval(input: {
22
22
  turnId: string;
23
23
  startedAt: string;
24
24
  actions: string[];
25
- cancellation: "cancelled" | "failed" | "completed" | "awaiting-input";
25
+ cancellation: "completed" | "failed" | "cancelled" | "awaiting-input";
26
26
  executionRequested: boolean;
27
27
  } | undefined>;
@@ -6,7 +6,7 @@ __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
7
  import { effectiveGroupPolicy, groupPolicy } from "../group-routing/policy.mjs";
8
8
  import { admitMessage, localizedText } from "../admission.mjs";
9
- import { d as telegramRuntimeSource, n as conversationLanguage, o as telegramPrincipal, u as runtimeEnvelope } from "../../../_chunks/principal-DFcIfKSa.mjs";
9
+ import { d as telegramRuntimeSource, n as conversationLanguage, o as telegramPrincipal, u as runtimeEnvelope } from "../../../_chunks/principal-69qoDdqy.mjs";
10
10
  import { p as reportTelegramError } from "../../../_chunks/inbound-request-gJ5wpsBF.mjs";
11
11
  import { addressingReason, conversationKey, otherRecipient } from "../group-routing/signals.mjs";
12
12
  import { conversationAddressing, conversationState } from "../group-routing/conversation.mjs";
@@ -4,12 +4,13 @@ import { createRequire as __eveCreateRequire } from "node:module";
4
4
  const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
- import { d as telegramRuntimeSource, l as principalRuntimeSource, u as runtimeEnvelope } from "../../../_chunks/principal-DFcIfKSa.mjs";
7
+ import { d as telegramRuntimeSource, l as principalRuntimeSource, u as runtimeEnvelope } from "../../../_chunks/principal-69qoDdqy.mjs";
8
8
  import { object } from "../confirmation-description.mjs";
9
9
  import { n as currentInboundRequest, p as reportTelegramError } from "../../../_chunks/inbound-request-gJ5wpsBF.mjs";
10
+ import { member } from "../actor.mjs";
10
11
  import { needsConfirmation } from "../confirmations.mjs";
11
12
  import { OntologyActionNotPermitted, actionToolName, ontologyTools } from "../ontology-tools.mjs";
12
- import { t as agentBuild } from "../../../_chunks/build-metadata-Bgh-kwt7.mjs";
13
+ import { t as agentBuild } from "../../../_chunks/build-metadata-Giw3R0jW.mjs";
13
14
  var AttachmentLifecycleNotPermitted = class extends Error {
14
15
  code = "attachment_lifecycle_not_permitted";
15
16
  };
@@ -52,11 +53,11 @@ function attachmentLifecycle(options) {
52
53
  source: source()
53
54
  })
54
55
  });
55
- const labels = await tools.labels(options.memberId, action, input).catch((error) => {
56
+ const labels = await tools.labels(member(options.memberId), action, input).catch((error) => {
56
57
  throw error instanceof OntologyActionNotPermitted ? new AttachmentLifecycleNotPermitted("The sender may not run the lifecycle action.", { cause: error }) : error;
57
58
  });
58
59
  if (needsConfirmation(labels)) throw new Error("An attachment lifecycle hook must be a permitted routine action.");
59
- const raw = await tools.rpc(options.memberId, "tools/call", {
60
+ const raw = await tools.rpc(member(options.memberId), "tools/call", {
60
61
  name: action,
61
62
  arguments: input
62
63
  });
@@ -64,7 +65,7 @@ function attachmentLifecycle(options) {
64
65
  if (object(envelope.validation).ok === false) throw new Error("The attachment lifecycle action rejected its event.");
65
66
  const result = object(envelope.result ?? envelope);
66
67
  const retention = object(result.retain);
67
- if (typeof retention.entity === "string" && typeof retention.action === "string" && needsConfirmation(await tools.labels(options.memberId, actionToolName(retention.entity, retention.action), object(retention.input)))) throw new Error("Automatic retention requires a permitted routine storage action.");
68
+ if (typeof retention.entity === "string" && typeof retention.action === "string" && needsConfirmation(await tools.labels(member(options.memberId), actionToolName(retention.entity, retention.action), object(retention.input)))) throw new Error("Automatic retention requires a permitted routine storage action.");
68
69
  return {
69
70
  ...typeof result.dispatch === "boolean" ? { dispatch: result.dispatch } : {},
70
71
  ...typeof result.dispatch_token === "string" ? { dispatchToken: result.dispatch_token } : {},
@@ -18,7 +18,10 @@ export declare function telegramPrincipal(input: {
18
18
  }): SessionAuthContext;
19
19
  /** Short answers and attachment-only turns retain the recent chat language when known. */
20
20
  export declare function conversationLanguage(texts: readonly string[]): "ru" | "en" | undefined;
21
- /** The member a session principal acts for: `memberId` stamped by a SegmentStream channel. */
21
+ /**
22
+ * The member a session principal acts for: `memberId` stamped by a SegmentStream channel. A task
23
+ * session acts for no member; `actorOf` in `lib/actor.ts` names whom any session acts for.
24
+ */
22
25
  export declare function memberIdOf(principal: SessionAuthContext | null | undefined): string | undefined;
23
26
  /** The member's roles on a session principal; empty when it carries none. */
24
27
  export declare function rolesOf(principal: SessionAuthContext | null | undefined): ReadonlyArray<string>;
@@ -4,5 +4,5 @@ import { createRequire as __eveCreateRequire } from "node:module";
4
4
  const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
- import { a as rolesOf, i as memberIdOf, n as conversationLanguage, o as telegramPrincipal, r as identityProviderOf, t as TELEGRAM_AUTHENTICATOR } from "../../../_chunks/principal-DFcIfKSa.mjs";
7
+ import { a as rolesOf, i as memberIdOf, n as conversationLanguage, o as telegramPrincipal, r as identityProviderOf, t as TELEGRAM_AUTHENTICATOR } from "../../../_chunks/principal-69qoDdqy.mjs";
8
8
  export { TELEGRAM_AUTHENTICATOR, conversationLanguage, identityProviderOf, memberIdOf, rolesOf, telegramPrincipal };
@@ -4,7 +4,7 @@ import { createRequire as __eveCreateRequire } from "node:module";
4
4
  const __filename = __eveFileURLToPath(import.meta.url);
5
5
  __eveDirname(__filename);
6
6
  __eveCreateRequire(import.meta.url);
7
- import "../../../_chunks/principal-DFcIfKSa.mjs";
7
+ import "../../../_chunks/principal-69qoDdqy.mjs";
8
8
  import { confirmationLocale } from "./confirmation-text.mjs";
9
9
  import { splitTelegramText } from "./format.mjs";
10
10
  import { inTelegramSendQueue } from "./send-queue.mjs";