@segmentstream/agent 0.16.0 → 0.17.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.
Files changed (41) hide show
  1. package/README.md +64 -1
  2. package/dist/_chunks/{build-metadata-CIFPiRho.mjs → build-metadata-DR4gACLZ.mjs} +1 -1
  3. package/dist/extension/config.d.ts +14 -0
  4. package/dist/extension/config.mjs +14 -0
  5. package/dist/extension/hooks/sandbox.d.ts +9 -0
  6. package/dist/extension/hooks/sandbox.mjs +12 -0
  7. package/dist/extension/instructions/sandbox.d.ts +2 -0
  8. package/dist/extension/instructions/sandbox.mjs +36 -0
  9. package/dist/extension/lib/attachment-formats.d.ts +2 -0
  10. package/dist/extension/lib/attachment-formats.mjs +29 -1
  11. package/dist/extension/lib/attachments.d.ts +4 -0
  12. package/dist/extension/lib/attachments.mjs +1 -1
  13. package/dist/extension/lib/build-metadata.mjs +1 -1
  14. package/dist/extension/lib/conversation-runtime.d.ts +5 -1
  15. package/dist/extension/lib/conversation-runtime.mjs +31 -5
  16. package/dist/extension/lib/conversations.d.ts +6 -0
  17. package/dist/extension/lib/conversations.mjs +4 -1
  18. package/dist/extension/lib/ontology-arguments.d.ts +28 -0
  19. package/dist/extension/lib/ontology-arguments.mjs +54 -0
  20. package/dist/extension/lib/sandbox-session.d.ts +104 -0
  21. package/dist/extension/lib/sandbox-session.mjs +142 -0
  22. package/dist/extension/lib/sandbox.d.ts +38 -0
  23. package/dist/extension/lib/sandbox.mjs +64 -0
  24. package/dist/extension/lib/telegram/adapter.mjs +11 -4
  25. package/dist/extension/lib/telegram/conversations.d.ts +16 -0
  26. package/dist/extension/lib/telegram/conversations.mjs +60 -15
  27. package/dist/extension/lib/telegram/health.mjs +1 -1
  28. package/dist/extension/lib/telegram/lifecycle.mjs +1 -1
  29. package/dist/extension/lib/telegram/silent.d.ts +24 -2
  30. package/dist/extension/lib/telegram/silent.mjs +30 -4
  31. package/dist/extension/lib/telegram/turn-errors.d.ts +7 -1
  32. package/dist/extension/lib/telegram/turn-errors.mjs +89 -76
  33. package/dist/extension/tools/attachments_promote.d.ts +2 -7
  34. package/dist/extension/tools/attachments_promote.mjs +34 -10
  35. package/dist/extension/tools/ontology.d.ts +4 -3
  36. package/dist/extension/tools/ontology.mjs +10 -3
  37. package/dist/extension/tools/sandbox.d.ts +7 -0
  38. package/dist/extension/tools/sandbox.mjs +29 -0
  39. package/dist/tools/index.d.ts +1 -0
  40. package/dist/tools/index.mjs +2 -1
  41. package/package.json +6 -2
@@ -7,82 +7,95 @@ __eveCreateRequire(import.meta.url);
7
7
  import { telegramText } from "./texts.mjs";
8
8
  import { i as memberIdOf } from "../../../_chunks/principal-MEMlG3EG.mjs";
9
9
  import { confirmationLocale } from "./confirmation-text.mjs";
10
- import { c as customerCopy, d as failureText, o as currentLocale, p as reportTelegramError } from "../../../_chunks/inbound-request-RIRNBxUC.mjs";
11
- const telegramFailureEvents = {
12
- async "authorization.required"(event, channel, context) {
13
- if (event.candidateId !== void 0) return;
14
- const locale = confirmationLocale(context.session.auth.current, currentLocale());
15
- const prompt = telegramText("authorization", "prompt", locale);
16
- const url = telegramText("authorization", "url", locale);
17
- const button = telegramText("authorization", "button", locale);
18
- if (prompt !== void 0) {
19
- const sent = await channel.telegram.post({
20
- text: prompt,
21
- ...url === void 0 || button === void 0 ? {} : { reply_markup: { inline_keyboard: [[{
22
- text: button,
23
- url
24
- }]] } }
10
+ import { c as customerCopy, d as failureText, o as currentLocale, p as reportTelegramError, s as currentThreadId } from "../../../_chunks/inbound-request-RIRNBxUC.mjs";
11
+ import { recordSessionFailure } from "./conversations.mjs";
12
+ function telegramFailureEvents(input) {
13
+ return {
14
+ async "authorization.required"(event, channel, context) {
15
+ if (event.candidateId !== void 0) return;
16
+ const locale = confirmationLocale(context.session.auth.current, currentLocale());
17
+ const prompt = telegramText("authorization", "prompt", locale);
18
+ const url = telegramText("authorization", "url", locale);
19
+ const button = telegramText("authorization", "button", locale);
20
+ if (prompt !== void 0) {
21
+ const sent = await channel.telegram.post({
22
+ text: prompt,
23
+ ...url === void 0 || button === void 0 ? {} : { reply_markup: { inline_keyboard: [[{
24
+ text: button,
25
+ url
26
+ }]] } }
27
+ });
28
+ if (sent.id) channel.state.pendingAuthMessageIds = {
29
+ ...channel.state.pendingAuthMessageIds,
30
+ [event.name]: sent.id
31
+ };
32
+ return;
33
+ }
34
+ const state = channel.state;
35
+ state.authorizationCancellationTurnId = event.turnId;
36
+ const errorId = reportTelegramError("authorization_prompt_unconfigured", new Error("texts.authorization.prompt is not configured."), { sessionId: context.session.id });
37
+ await channel.telegram.post(failureText(errorId, "authorization", locale));
38
+ },
39
+ async "turn.cancelled"(event, channel, context) {
40
+ const state = channel.state;
41
+ const authorizationTurn = state.authorizationCancellationTurnId;
42
+ delete state.authorizationCancellationTurnId;
43
+ if (typeof event.turnId === "string" && authorizationTurn === event.turnId) return;
44
+ const errorId = reportTelegramError("turn_cancelled", event, {
45
+ chatId: channel.state.chatId,
46
+ sessionId: context.session.id,
47
+ turnId: event.turnId
25
48
  });
26
- if (sent.id) channel.state.pendingAuthMessageIds = {
27
- ...channel.state.pendingAuthMessageIds,
28
- [event.name]: sent.id
29
- };
30
- return;
31
- }
32
- const state = channel.state;
33
- state.authorizationCancellationTurnId = event.turnId;
34
- const errorId = reportTelegramError("authorization_prompt_unconfigured", new Error("texts.authorization.prompt is not configured."), { sessionId: context.session.id });
35
- await channel.telegram.post(failureText(errorId, "authorization", locale));
36
- },
37
- async "turn.cancelled"(event, channel, context) {
38
- const state = channel.state;
39
- const authorizationTurn = state.authorizationCancellationTurnId;
40
- delete state.authorizationCancellationTurnId;
41
- if (typeof event.turnId === "string" && authorizationTurn === event.turnId) return;
42
- const errorId = reportTelegramError("turn_cancelled", event, {
43
- chatId: channel.state.chatId,
44
- sessionId: context.session.id,
45
- turnId: event.turnId
46
- });
47
- await channel.telegram.post(failureText(errorId, "cancelled", confirmationLocale(context.session.auth.current, currentLocale())));
48
- },
49
- async "turn.failed"(event, channel, context) {
50
- const errorId = reportTelegramError("turn_failed", event, {
51
- chatId: channel.state.chatId,
52
- memberId: memberIdOf(context.session.auth.current) ?? null,
53
- sessionId: context.session.id,
54
- turnId: event.turnId
55
- });
56
- await channel.telegram.post(failureText(errorId, "failed", confirmationLocale(context.session.auth.current, currentLocale())));
57
- },
58
- async "session.failed"(event, channel) {
59
- const errorId = reportTelegramError("session_recovery_failed", event, {
60
- chatId: channel.state.chatId,
61
- sessionId: event.sessionId
62
- });
63
- const locale = channel.state.customerLocale ?? "en";
64
- await channel.telegram.post(failureText(errorId, "recovery", locale));
65
- },
66
- async "authorization.completed"(event, channel, context) {
67
- const messageId = channel.state.pendingAuthMessageIds?.[event.name];
68
- if (event.candidateId !== void 0 || messageId === void 0) return;
69
- const locale = confirmationLocale(context.session.auth.current);
70
- const copy = customerCopy(locale);
71
- let text = event.outcome === "authorized" ? copy.connected : copy.disconnected;
72
- if (event.reason !== void 0) {
73
- const errorId = reportTelegramError("authorization_not_completed", event, { chatId: channel.state.chatId });
74
- text = failureText(errorId, "authorization", locale);
49
+ await channel.telegram.post(failureText(errorId, "cancelled", confirmationLocale(context.session.auth.current, currentLocale())));
50
+ },
51
+ async "turn.failed"(event, channel, context) {
52
+ const errorId = reportTelegramError("turn_failed", event, {
53
+ chatId: channel.state.chatId,
54
+ memberId: memberIdOf(context.session.auth.current) ?? null,
55
+ sessionId: context.session.id,
56
+ turnId: event.turnId
57
+ });
58
+ await channel.telegram.post(failureText(errorId, "failed", confirmationLocale(context.session.auth.current, currentLocale())));
59
+ },
60
+ async "session.failed"(event, channel) {
61
+ const errorId = reportTelegramError("session_recovery_failed", event, {
62
+ chatId: channel.state.chatId,
63
+ sessionId: event.sessionId
64
+ });
65
+ const locale = channel.state.customerLocale ?? "en";
66
+ const recorded = recordSessionFailure({
67
+ ...input,
68
+ chatId: channel.state.chatId,
69
+ threadId: typeof channel.state.messageThreadId === "number" ? String(channel.state.messageThreadId) : currentThreadId() ?? null,
70
+ failure: event
71
+ });
72
+ try {
73
+ await channel.telegram.post(failureText(errorId, "recovery", locale));
74
+ } finally {
75
+ await recorded;
76
+ }
77
+ },
78
+ async "authorization.completed"(event, channel, context) {
79
+ const messageId = channel.state.pendingAuthMessageIds?.[event.name];
80
+ if (event.candidateId !== void 0 || messageId === void 0) return;
81
+ const locale = confirmationLocale(context.session.auth.current);
82
+ const copy = customerCopy(locale);
83
+ let text = event.outcome === "authorized" ? copy.connected : copy.disconnected;
84
+ if (event.reason !== void 0) {
85
+ const errorId = reportTelegramError("authorization_not_completed", event, { chatId: channel.state.chatId });
86
+ text = failureText(errorId, "authorization", locale);
87
+ }
88
+ if (text !== void 0) await channel.telegram.editMessageText({
89
+ messageId,
90
+ text,
91
+ replyMarkup: { inline_keyboard: [] }
92
+ });
93
+ else await channel.telegram.editMessageReplyMarkup({
94
+ messageId,
95
+ replyMarkup: { inline_keyboard: [] }
96
+ });
97
+ delete channel.state.pendingAuthMessageIds?.[event.name];
75
98
  }
76
- if (text !== void 0) await channel.telegram.editMessageText({
77
- messageId,
78
- text,
79
- replyMarkup: { inline_keyboard: [] }
80
- });
81
- else await channel.telegram.editMessageReplyMarkup({
82
- messageId,
83
- replyMarkup: { inline_keyboard: [] }
84
- });
85
- delete channel.state.pendingAuthMessageIds?.[event.name];
86
- }
87
- };
99
+ };
100
+ }
88
101
  export { telegramFailureEvents };
@@ -1,10 +1,5 @@
1
- /**
2
- * `segmentstream__attachments_promote`: keeps an attachment by running an ontology action that
3
- * stores it, such as `document.upload`, as the member and with their permissions. The platform
4
- * hands the action the file already stored, so nothing is uploaded again, and a file whose SHA-256
5
- * was already promoted through the same action is not stored twice.
6
- */
1
+ import { type ToolContext } from "eve/tools";
7
2
  declare const _default: import("eve/tools").ToolDefinition<Record<string, unknown>, import("../lib/workflow-serializable.js").WorkflowSerializable> & {
8
- execute(input: Record<string, unknown>, ctx: import("eve/tools").ToolContext): Promise<import("../lib/workflow-serializable.js").WorkflowSerializable>;
3
+ execute(input: Record<string, unknown>, ctx: ToolContext): Promise<import("../lib/workflow-serializable.js").WorkflowSerializable>;
9
4
  };
10
5
  export default _default;
@@ -9,8 +9,26 @@ import { n as workflowToolResult } from "../../_chunks/workflow-serializable-DVQ
9
9
  import segmentstream from "../extension.mjs";
10
10
  import { actionApproval } from "../lib/confirmations.mjs";
11
11
  import { ontologyTools, promotionTarget } from "../lib/ontology-tools.mjs";
12
+ import { MAXIMUM_ATTACHMENT_BYTES } from "../lib/attachments.mjs";
13
+ import { sandboxFile } from "../lib/sandbox-session.mjs";
14
+ import { contentTypeOf } from "../lib/attachment-formats.mjs";
12
15
  import { attachmentForModel, attachmentOwner, optionalObject, optionalString, stringArgument, toolAttachments } from "../lib/attachment-tools.mjs";
16
+ import { createHash } from "node:crypto";
13
17
  import { defineTool } from "eve/tools";
18
+ const MAXIMUM_SESSION_REFERENCE = 127;
19
+ async function sandboxAttachment(ctx, owner, path) {
20
+ if (!segmentstream.config.sandbox) throw new TypeError("path needs the sandbox, which agent/segmentstream.json turns on with \"sandbox\": true.");
21
+ const file = await sandboxFile(ctx, path, { maximumBytes: MAXIMUM_ATTACHMENT_BYTES });
22
+ const sha256 = createHash("sha256").update(file.content).digest("hex");
23
+ const session = ctx.session.id.length <= MAXIMUM_SESSION_REFERENCE ? ctx.session.id : createHash("sha256").update(ctx.session.id).digest("hex");
24
+ return (await toolAttachments().receive(owner, {
25
+ bytes: file.content,
26
+ filename: file.filename,
27
+ contentType: contentTypeOf(file.filename),
28
+ source: "sandbox",
29
+ sourceRef: `sandbox:${session}:${sha256}`
30
+ })).id;
31
+ }
14
32
  var attachments_promote_default = defineTool({
15
33
  approval: actionApproval({
16
34
  texts: () => segmentstream.config.texts ?? {},
@@ -23,7 +41,7 @@ var attachments_promote_default = defineTool({
23
41
  return ontologyTools().describe(memberId, target.action, target.input);
24
42
  }
25
43
  }),
26
- description: "Keep a file the member sent by storing it in a record through an ontology action that takes a file, such as document.upload. Give the entity, the action and the action's input without the file field: the platform fills it with the attachment, and fills sha256 when the action takes one. Runs with the member's permissions. The same file promoted again through the same action returns the earlier result instead of a duplicate.",
44
+ description: "Keep a file the member sent by storing it in a record through an ontology action that takes a file, such as document.upload. Give the entity, the action and the action's input without the file field: the platform fills it with the attachment, and fills sha256 when the action takes one. Runs with the member's permissions. The same file promoted again through the same action returns the earlier result instead of a duplicate. With the sandbox on, give path instead of id to keep a file from /workspace, such as a result in /workspace/work.",
27
45
  inputSchema: {
28
46
  type: "object",
29
47
  properties: {
@@ -34,7 +52,11 @@ var attachments_promote_default = defineTool({
34
52
  },
35
53
  id: {
36
54
  type: "string",
37
- description: "The attachment's id."
55
+ description: "The attachment's id. Give id or path."
56
+ },
57
+ path: {
58
+ type: "string",
59
+ description: "Instead of id: the absolute path of a file inside /workspace in the sandbox, at most 20 MB. It is stored as an attachment of this chat first."
38
60
  },
39
61
  entity: {
40
62
  type: "string",
@@ -57,11 +79,7 @@ var attachments_promote_default = defineTool({
57
79
  description: "The record the action sets the file on, for an action that updates one."
58
80
  }
59
81
  },
60
- required: [
61
- "id",
62
- "entity",
63
- "action"
64
- ],
82
+ required: ["entity", "action"],
65
83
  additionalProperties: false
66
84
  },
67
85
  label: { start: (input) => `Store attachment with ${String(input.entity)}.${String(input.action)}` },
@@ -70,17 +88,23 @@ var attachments_promote_default = defineTool({
70
88
  principal: ctx.session.auth.current,
71
89
  sessionId: ctx.session.id
72
90
  });
91
+ const id = optionalString(input, "id");
92
+ const path = optionalString(input, "path");
73
93
  const field = optionalString(input, "field");
74
94
  const recordId = optionalString(input, "record_id");
75
95
  const actionInput = optionalObject(input, "input");
76
- const promoted = await toolAttachments().promote(owner, stringArgument(input, "id"), {
96
+ const entity = stringArgument(input, "entity");
97
+ const action = stringArgument(input, "action");
98
+ if (id === void 0 === (path === void 0)) throw new TypeError("Give either id or path.");
99
+ const attachmentId = id ?? await sandboxAttachment(ctx, owner, path);
100
+ const promoted = await toolAttachments().promote(owner, attachmentId, {
77
101
  runtime: runtimeEnvelope({
78
102
  principal: ctx.session.auth.current,
79
103
  sessionId: ctx.session.id,
80
104
  callId: ctx.callId
81
105
  }),
82
- entity: stringArgument(input, "entity"),
83
- action: stringArgument(input, "action"),
106
+ entity,
107
+ action,
84
108
  ...actionInput === void 0 ? {} : { input: actionInput },
85
109
  ...field === void 0 ? {} : { field },
86
110
  ...recordId === void 0 ? {} : { recordId }
@@ -1,3 +1,4 @@
1
+ import { type OntologyCallInput } from "../lib/ontology-arguments.js";
1
2
  declare const _default: import("eve").DynamicSentinel<{
2
3
  ontology_discover: import("eve/tools").ToolDefinition<Record<string, unknown>, Record<string, unknown>> & {
3
4
  execute(input: Record<string, unknown>, ctx: import("eve/tools").ToolContext): Promise<Record<string, unknown>>;
@@ -20,8 +21,8 @@ declare const _default: import("eve").DynamicSentinel<{
20
21
  })[];
21
22
  }>;
22
23
  };
23
- ontology_call: import("eve/tools").ToolDefinition<Record<string, unknown>, Record<string, unknown>> & {
24
- execute(input: Record<string, unknown>, ctx: import("eve/tools").ToolContext): Promise<Record<string, unknown>>;
25
- };
24
+ ontology_call: import("eve/tools").ToolDefinition<{
25
+ name: string;
26
+ } & OntologyCallInput, Record<string, unknown>>;
26
27
  } | null>;
27
28
  export default _default;
@@ -7,11 +7,13 @@ __eveCreateRequire(import.meta.url);
7
7
  import { i as memberIdOf } from "../../_chunks/principal-MEMlG3EG.mjs";
8
8
  import segmentstream from "../extension.mjs";
9
9
  import { executeDeferredTool } from "../lib/deferred-confirmations.mjs";
10
+ import { MAXIMUM_ARGUMENTS_FILE_BYTES, ontologyCallArguments } from "../lib/ontology-arguments.mjs";
10
11
  import { ontologyInspect, ontologyMetadata } from "../lib/ontology-gateway.mjs";
11
12
  import { defineDynamic, defineTool } from "eve/tools";
12
13
  var ontology_default = defineDynamic({ events: { "turn.started": async (_event, context) => {
13
14
  const memberId = memberIdOf(context.session.auth.current);
14
15
  if (!segmentstream.config.ontology.connection || segmentstream.config.confirmations.mode !== "deferred" || memberId === void 0) return null;
16
+ const sandbox = segmentstream.config.sandbox === true;
15
17
  return {
16
18
  ontology_discover: defineTool({
17
19
  description: "Search the permitted ontology's entities, actions and measures by words. Inspect returned refs with ontology_describe before calling ontology_call.",
@@ -107,7 +109,7 @@ var ontology_default = defineDynamic({ events: { "turn.started": async (_event,
107
109
  execute: (input, ctx) => ontologyInspect(memberId, input, ctx)
108
110
  }),
109
111
  ontology_call: defineTool({
110
- description: "Run a permitted ontology operation by the exact MCP tool name from its inspected definition, with arguments matching that schema. Reads and routine actions run immediately; consequential actions retain native deferred confirmation. An awaiting_confirmation result means the action has not run.",
112
+ description: "Run a permitted ontology operation by the exact MCP tool name from its inspected definition, with arguments matching that schema. Reads and routine actions run immediately; consequential actions retain native deferred confirmation. An awaiting_confirmation result means the action has not run." + (sandbox ? " Instead of arguments, give arguments_file: the path of a JSON object file inside /workspace that a script wrote, so large or exact values reach the operation unchanged instead of being retyped." : ""),
111
113
  inputSchema: {
112
114
  type: "object",
113
115
  properties: {
@@ -118,12 +120,17 @@ var ontology_default = defineDynamic({ events: { "turn.started": async (_event,
118
120
  arguments: {
119
121
  type: "object",
120
122
  additionalProperties: true
121
- }
123
+ },
124
+ ...sandbox ? { arguments_file: {
125
+ type: "string",
126
+ minLength: 1,
127
+ description: `Instead of arguments: the absolute path of a UTF-8 JSON file inside /workspace in the sandbox, at most ${MAXIMUM_ARGUMENTS_FILE_BYTES / 1024 / 1024} MiB, holding one object used as the arguments. Give arguments or arguments_file, not both.`
128
+ } } : {}
122
129
  },
123
130
  required: ["name"],
124
131
  additionalProperties: false
125
132
  },
126
- execute: (input, ctx) => executeDeferredTool(memberId, input.name, input.arguments ?? {}, ctx, { texts: () => segmentstream.config.texts ?? {} })
133
+ execute: async (input, ctx) => executeDeferredTool(memberId, input.name, await ontologyCallArguments(input, ctx, { sandbox }), ctx, { texts: () => segmentstream.config.texts ?? {} })
127
134
  })
128
135
  };
129
136
  } } });
@@ -0,0 +1,7 @@
1
+ import { type ToolDefinition } from "eve/tools";
2
+ declare const _default: import("eve").DynamicSentinel<{
3
+ bash: ToolDefinition<import("eve/tools/bash").BashToolInput, import("eve/tools/bash").BashToolOutput>;
4
+ read_file: ToolDefinition<import("eve/tools/read_file").ReadFileToolInput, import("eve/tools/read_file").ReadFileToolOutput>;
5
+ write_file: ToolDefinition<import("eve/tools/write_file").WriteFileToolInput, import("eve/tools/write_file").WriteFileToolOutput>;
6
+ } | null>;
7
+ export default _default;
@@ -0,0 +1,29 @@
1
+ import { fileURLToPath as __eveFileURLToPath } from "node:url";
2
+ import { dirname as __eveDirname } from "node:path";
3
+ import { createRequire as __eveCreateRequire } from "node:module";
4
+ const __filename = __eveFileURLToPath(import.meta.url);
5
+ __eveDirname(__filename);
6
+ __eveCreateRequire(import.meta.url);
7
+ import segmentstream from "../extension.mjs";
8
+ import { sessionSandbox } from "../lib/sandbox-session.mjs";
9
+ import { defineDynamic, defineTool } from "eve/tools";
10
+ import { bash } from "eve/tools/bash";
11
+ import { readFile } from "eve/tools/read_file";
12
+ import { writeFile } from "eve/tools/write_file";
13
+ function gated(tool, description = tool.description) {
14
+ return defineTool({
15
+ ...tool,
16
+ description,
17
+ async execute(input, ctx) {
18
+ await sessionSandbox(ctx);
19
+ return await tool.execute(input, ctx);
20
+ }
21
+ });
22
+ }
23
+ const tools = {
24
+ bash: gated(bash, "Run a shell command in this conversation's isolated sandbox, which has no network. A command still running after 30 seconds keeps running and returns status \"running\" with its output so far and the directory of its stdout, stderr and exit files."),
25
+ read_file: gated(readFile),
26
+ write_file: gated(writeFile, "Write a complete file in this conversation's isolated sandbox, creating directories as needed. Read an existing file with read_file before overwriting it.")
27
+ };
28
+ var sandbox_default = defineDynamic({ events: { "turn.started": () => segmentstream.config.sandbox ? tools : null } });
29
+ export { sandbox_default as default };
@@ -8,3 +8,4 @@ export { default as attachments_send } from "../extension/tools/attachments_send
8
8
  export { default as attachments_table } from "../extension/tools/attachments_table.js";
9
9
  export { default as ontology } from "../extension/tools/ontology.js";
10
10
  export { default as questions_ask } from "../extension/tools/questions_ask.js";
11
+ export { default as sandbox } from "../extension/tools/sandbox.js";
@@ -12,4 +12,5 @@ import attachments_send_default from "../extension/tools/attachments_send.mjs";
12
12
  import attachments_table_default from "../extension/tools/attachments_table.mjs";
13
13
  import ontology_default from "../extension/tools/ontology.mjs";
14
14
  import questions_ask_default from "../extension/tools/questions_ask.mjs";
15
- export { attachments_discard_default as attachments_discard, attachments_list_default as attachments_list, attachments_promote_default as attachments_promote, attachments_read_default as attachments_read, attachments_send_default as attachments_send, attachments_table_default as attachments_table, ontology_default as ontology, questions_ask_default as questions_ask };
15
+ import sandbox_default from "../extension/tools/sandbox.mjs";
16
+ export { attachments_discard_default as attachments_discard, attachments_list_default as attachments_list, attachments_promote_default as attachments_promote, attachments_read_default as attachments_read, attachments_send_default as attachments_send, attachments_table_default as attachments_table, ontology_default as ontology, questions_ask_default as questions_ask, sandbox_default as sandbox };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@segmentstream/agent",
3
- "version": "0.16.0",
3
+ "version": "0.17.0",
4
4
  "description": "Mount a SegmentStream workspace's agent on eve: the ontology as tools, acting as the member who writes, and Telegram through the workspace's connection.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "SegmentStream",
@@ -31,6 +31,10 @@
31
31
  "types": "./dist/extension/extension.d.ts",
32
32
  "default": "./dist/extension/extension.mjs"
33
33
  },
34
+ "./sandbox": {
35
+ "types": "./dist/extension/lib/sandbox.d.ts",
36
+ "default": "./dist/extension/lib/sandbox.mjs"
37
+ },
34
38
  "./tools": {
35
39
  "types": "./dist/tools/index.d.ts",
36
40
  "default": "./dist/tools/index.mjs"
@@ -62,7 +66,7 @@
62
66
  },
63
67
  "dependencies": {
64
68
  "@chat-adapter/telegram": "4.41.0",
65
- "@segmentstream-cloud/ontology": "0.52.0",
69
+ "@segmentstream-cloud/ontology": "0.53.0",
66
70
  "@vercel/oidc": "^3.8.4",
67
71
  "ai": "^7.0.128",
68
72
  "csv-parse": "^7.0.3",