@meistrari/chat-nuxt 1.4.0 → 1.5.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 (85) hide show
  1. package/README.md +51 -16
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +12 -8
  4. package/dist/runtime/components/MeistrariChatEmbed.d.vue.ts +2 -18
  5. package/dist/runtime/components/MeistrariChatEmbed.vue +22 -4
  6. package/dist/runtime/components/MeistrariChatEmbed.vue.d.ts +2 -18
  7. package/dist/runtime/components/chat/message-input.d.vue.ts +30 -4
  8. package/dist/runtime/components/chat/message-input.vue +268 -24
  9. package/dist/runtime/components/chat/message-input.vue.d.ts +30 -4
  10. package/dist/runtime/composables/useChat.d.ts +3 -5
  11. package/dist/runtime/composables/useChat.js +18 -4
  12. package/dist/runtime/composables/useChatApi.js +4 -0
  13. package/dist/runtime/composables/useConversations.js +8 -2
  14. package/dist/runtime/composables/useEmbedConfig.d.ts +7 -1
  15. package/dist/runtime/composables/useEmbedConfig.js +8 -0
  16. package/dist/runtime/composables/useFeatureFlags.d.ts +1 -2
  17. package/dist/runtime/composables/useTelaAgentMetadata.d.ts +8 -0
  18. package/dist/runtime/composables/useTelaAgentMetadata.js +65 -0
  19. package/dist/runtime/composables/useWorkspaceSettings.d.ts +1 -19
  20. package/dist/runtime/embed/components/ChatConfigurationModal.d.vue.ts +1 -1
  21. package/dist/runtime/embed/components/ChatConfigurationModal.vue.d.ts +1 -1
  22. package/dist/runtime/embed/components/ChatEmbed.d.vue.ts +3 -23
  23. package/dist/runtime/embed/components/ChatEmbed.vue +34 -9
  24. package/dist/runtime/embed/components/ChatEmbed.vue.d.ts +3 -23
  25. package/dist/runtime/embed/components/ChatEmbedInner.vue +36 -12
  26. package/dist/runtime/plugins/markstream.d.ts +1 -1
  27. package/dist/runtime/plugins/markstream.js +1 -1
  28. package/dist/runtime/server/api/conversations/[id]/cancel.post.d.ts +1 -1
  29. package/dist/runtime/server/api/conversations/[id]/cancel.post.js +37 -17
  30. package/dist/runtime/server/api/conversations/[id]/clear.post.js +28 -13
  31. package/dist/runtime/server/api/conversations/[id]/duplicate.post.js +11 -13
  32. package/dist/runtime/server/api/conversations/[id]/files.get.js +5 -7
  33. package/dist/runtime/server/api/conversations/[id]/index.delete.js +13 -12
  34. package/dist/runtime/server/api/conversations/[id]/index.get.js +6 -13
  35. package/dist/runtime/server/api/conversations/[id]/index.patch.js +11 -10
  36. package/dist/runtime/server/api/conversations/[id]/messages/[messageId]/retry.post.js +46 -80
  37. package/dist/runtime/server/api/conversations/[id]/messages/index.get.d.ts +1 -14
  38. package/dist/runtime/server/api/conversations/[id]/messages/index.get.js +81 -187
  39. package/dist/runtime/server/api/conversations/[id]/messages/index.post.js +68 -86
  40. package/dist/runtime/server/api/conversations/[id]/usage.get.js +4 -8
  41. package/dist/runtime/server/api/conversations/generate-title.post.js +4 -3
  42. package/dist/runtime/server/api/conversations/index.get.js +5 -4
  43. package/dist/runtime/server/api/conversations/index.post.js +5 -4
  44. package/dist/runtime/server/api/tela/agents/[id].get.d.ts +6 -0
  45. package/dist/runtime/server/api/tela/agents/[id].get.js +25 -0
  46. package/dist/runtime/server/api/workspace/settings.patch.js +1 -1
  47. package/dist/runtime/server/db/schema/conversations.d.ts +17 -0
  48. package/dist/runtime/server/db/schema/conversations.js +3 -1
  49. package/dist/runtime/server/db/schema/workspace-settings.d.ts +1 -1
  50. package/dist/runtime/server/utils/chat-context.d.ts +5 -0
  51. package/dist/runtime/server/utils/chat-context.js +20 -0
  52. package/dist/runtime/server/utils/conversation-agent-turn.d.ts +39 -0
  53. package/dist/runtime/server/utils/conversation-agent-turn.js +170 -0
  54. package/dist/runtime/server/utils/conversation-message-files.d.ts +10 -0
  55. package/dist/runtime/server/utils/conversation-message-files.js +77 -0
  56. package/dist/runtime/server/utils/conversation-message-sync.d.ts +31 -0
  57. package/dist/runtime/server/utils/conversation-message-sync.js +132 -0
  58. package/dist/runtime/server/utils/conversation-scope.d.ts +2 -0
  59. package/dist/runtime/server/utils/conversation-scope.js +12 -0
  60. package/dist/runtime/server/utils/tela-agent-api.d.ts +29 -0
  61. package/dist/runtime/server/utils/tela-agent-api.js +107 -0
  62. package/dist/runtime/server/utils/tela-agent-session.d.ts +48 -0
  63. package/dist/runtime/server/utils/tela-agent-session.js +350 -0
  64. package/dist/runtime/types/embed.d.ts +29 -0
  65. package/dist/runtime/types/embed.js +0 -0
  66. package/dist/runtime/types/tela-agent.d.ts +243 -0
  67. package/dist/runtime/types/tela-agent.js +98 -0
  68. package/dist/runtime/types/workspace-settings-data.d.ts +19 -0
  69. package/dist/runtime/types/workspace-settings-data.js +0 -0
  70. package/dist/runtime/types/workspace-settings.d.ts +1 -1
  71. package/dist/runtime/utils/agent-input-readiness.d.ts +14 -0
  72. package/dist/runtime/utils/agent-input-readiness.js +15 -0
  73. package/dist/runtime/utils/features.d.ts +9 -0
  74. package/dist/runtime/utils/features.js +5 -4
  75. package/dist/runtime/utils/file.js +46 -7
  76. package/dist/runtime/utils/markdown-nodes.d.ts +1 -0
  77. package/dist/runtime/utils/markdown-nodes.js +6 -0
  78. package/dist/runtime/utils/tela-chat.d.ts +6 -0
  79. package/dist/runtime/utils/tela-chat.js +12 -1
  80. package/drizzle/0014_faulty_lake.sql +2 -0
  81. package/drizzle/meta/0014_snapshot.json +732 -0
  82. package/drizzle/meta/_journal.json +7 -0
  83. package/package.json +1 -1
  84. package/dist/runtime/types/feature-flags.d.ts +0 -7
  85. package/dist/runtime/types/feature-flags.js +0 -6
@@ -1,25 +1,21 @@
1
1
  import { createError, defineEventHandler, getRouterParam, readBody } from "h3";
2
- import { useRuntimeConfig } from "nitropack/runtime";
3
- import { eq, and, isNull } from "drizzle-orm";
2
+ import { eq } from "drizzle-orm";
4
3
  import { useDb, schema } from "#chat-runtime/server/db";
5
- import { resolveChatContext } from "#chat-runtime/server/utils/chat-context";
6
- import { buildMessageWithContext, renderSystemPrompt, truncateTitle } from "#chat-runtime/server/utils/chat-message-builder";
4
+ import { resolveChatRuntimeContext } from "#chat-runtime/server/utils/chat-context";
5
+ import {
6
+ buildTelaAgentTurnPayload,
7
+ prepareDefaultAgentTurn,
8
+ queueTelaAgentTurn,
9
+ resolveDefaultAgentEnvironmentVariables,
10
+ withEnvironmentVariables
11
+ } from "#chat-runtime/server/utils/conversation-agent-turn";
12
+ import { conversationScopeConditions } from "#chat-runtime/server/utils/conversation-scope";
7
13
  import { getAgentDataToken, createChatAgentSession, continueSession } from "#chat-runtime/server/utils/agent-api";
8
14
  import { logger } from "#chat-runtime/server/utils/logger";
9
- import {
10
- getConversationAppliedSettings,
11
- getWorkspaceSettingsUpdatedAt,
12
- parseWorkspaceSettingsSnapshot,
13
- resolveWorkspaceSettings,
14
- serializeResolvedWorkspaceSettings
15
- } from "#chat-runtime/server/utils/chat-workspace-settings";
16
- import { resolveWorkspaceCredentials } from "#chat-runtime/server/utils/workspace";
17
- import { useChatNuxtFeatures } from "#chat-runtime/utils/features";
18
- import { mergeFileUrls } from "#chat-runtime/utils/file";
19
15
  import { isValidModel } from "#chat-runtime/types/chat";
16
+ import { telaAgentExecutionInputSchema } from "#chat-runtime/types/tela-agent";
20
17
  export default defineEventHandler(async (event) => {
21
- const context = resolveChatContext(event);
22
- const token = getAgentDataToken(event);
18
+ const context = resolveChatRuntimeContext(event);
23
19
  const db = useDb();
24
20
  const conversationId = getRouterParam(event, "id");
25
21
  const body = await readBody(event);
@@ -35,41 +31,37 @@ export default defineEventHandler(async (event) => {
35
31
  statusMessage: "Message content is required"
36
32
  });
37
33
  }
38
- if (body.model !== void 0 && !isValidModel(body.model)) {
34
+ const [conversation] = await db.select().from(schema.conversations).where(conversationScopeConditions(context, conversationId));
35
+ if (!conversation) {
36
+ throw createError({
37
+ statusCode: 404,
38
+ statusMessage: "Conversation not found"
39
+ });
40
+ }
41
+ if (!conversation.telaAgentId && body.model !== void 0 && !isValidModel(body.model)) {
39
42
  throw createError({
40
43
  statusCode: 400,
41
44
  statusMessage: "Invalid model"
42
45
  });
43
46
  }
44
- const [conversation] = await db.select().from(schema.conversations).where(
45
- and(
46
- eq(schema.conversations.id, conversationId),
47
- eq(schema.conversations.workspaceId, context.workspaceId)
48
- )
49
- );
50
- if (!conversation) {
47
+ const agentInputs = conversation.telaAgentId && body.agentInputs !== void 0 ? telaAgentExecutionInputSchema.array().safeParse(body.agentInputs) : null;
48
+ if (agentInputs && !agentInputs.success) {
51
49
  throw createError({
52
- statusCode: 404,
53
- statusMessage: "Conversation not found"
50
+ statusCode: 400,
51
+ statusMessage: "Invalid Tela agent inputs"
54
52
  });
55
53
  }
56
- const effectiveModel = body.model ?? (isValidModel(conversation.model) ? conversation.model : void 0);
57
- const explicitSettings = !conversation.appliedSettingsSnapshot && body.workspaceSettingsSnapshot !== void 0 ? parseWorkspaceSettingsSnapshot(body.workspaceSettingsSnapshot) : void 0;
58
- const trustedSettings = conversation.appliedSettingsSnapshot || explicitSettings ? null : await resolveWorkspaceSettings(event, context, db);
59
- const appliedSettings = getConversationAppliedSettings(conversation, trustedSettings, explicitSettings);
54
+ const telaAgentPayload = conversation.telaAgentId ? await buildTelaAgentTurnPayload(event, conversation, body.content, body.files, agentInputs?.data) : null;
55
+ const defaultAgentTurn = conversation.telaAgentId ? null : await prepareDefaultAgentTurn(event, db, context, {
56
+ conversation,
57
+ conversationId,
58
+ content: body.content,
59
+ files: body.files,
60
+ requestedModel: body.model,
61
+ workspaceSettingsSnapshot: body.workspaceSettingsSnapshot
62
+ });
60
63
  const now = /* @__PURE__ */ new Date();
61
64
  const assistantCreatedAt = new Date(now.getTime() + 1);
62
- const snapshotSettings = explicitSettings ?? trustedSettings;
63
- if (!conversation.appliedSettingsSnapshot && snapshotSettings) {
64
- await db.update(schema.conversations).set({
65
- appliedSettingsAt: getWorkspaceSettingsUpdatedAt(snapshotSettings),
66
- appliedSettingsSnapshot: serializeResolvedWorkspaceSettings(snapshotSettings),
67
- updatedAt: now
68
- }).where(and(
69
- eq(schema.conversations.id, conversationId),
70
- isNull(schema.conversations.appliedSettingsSnapshot)
71
- ));
72
- }
73
65
  const [userMessages, assistantMessages] = await Promise.all([
74
66
  db.insert(schema.messages).values({
75
67
  conversationId,
@@ -98,49 +90,42 @@ export default defineEventHandler(async (event) => {
98
90
  }
99
91
  logger.info({ conversationId, userMessageId: userMessage.id, hasFiles: !!body.files?.length }, "Message sent");
100
92
  const assistantMessageId = assistantMessage.id;
101
- const needsNewThread = conversation.threadSessionId === null;
102
- const fileUrls = mergeFileUrls(appliedSettings.contextFiles, body.files);
103
- const messageTitle = truncateTitle(body.content);
104
- const knowledgeSources = appliedSettings.knowledgeSources ?? null;
105
- const { vaultUrl } = useRuntimeConfig();
106
- const messageWithContext = buildMessageWithContext(
107
- body.content.trim(),
108
- appliedSettings.systemMessage ?? null,
109
- knowledgeSources,
110
- needsNewThread,
111
- needsNewThread ? renderSystemPrompt(vaultUrl) : ""
112
- );
113
- const canvasTools = appliedSettings.canvasTools;
114
- const hasKnowledgeSources = knowledgeSources && knowledgeSources.length > 0;
115
- const externalSkillRefs = appliedSettings.externalSkills?.map((skill) => skill.ref) ?? [];
116
- const settingsTimestamp = getWorkspaceSettingsUpdatedAt(appliedSettings);
117
- const skills = externalSkillRefs.length > 0 ? externalSkillRefs : void 0;
118
- if (needsNewThread) {
119
- let environmentVariables = {};
120
- if (useChatNuxtFeatures().credentials) {
121
- try {
122
- environmentVariables = await resolveWorkspaceCredentials(event, context.workspaceId);
123
- } catch (error) {
124
- logger.warn({ conversationId, error }, "Failed to resolve workspace credentials, proceeding without env vars");
125
- }
126
- }
127
- const hasEnvironmentVariables = Object.keys(environmentVariables).length > 0;
128
- createChatAgentSession(token, {
129
- message: messageWithContext,
130
- fileUrls,
131
- model: effectiveModel,
132
- customTools: canvasTools?.length ? { canvas: canvasTools } : void 0,
133
- tools: hasKnowledgeSources ? { workstationQueryTool: true } : void 0,
134
- environmentVariables: hasEnvironmentVariables ? environmentVariables : void 0,
135
- skills
136
- }).then(async (result) => {
93
+ if (conversation.telaAgentId) {
94
+ queueTelaAgentTurn(event, db, {
95
+ conversation,
96
+ conversationId,
97
+ assistantMessageId,
98
+ payload: telaAgentPayload,
99
+ titleContent: body.content,
100
+ operation: "send"
101
+ });
102
+ return {
103
+ userMessage,
104
+ assistantMessage
105
+ };
106
+ }
107
+ if (!defaultAgentTurn) {
108
+ throw createError({
109
+ statusCode: 500,
110
+ statusMessage: "Failed to prepare agent turn"
111
+ });
112
+ }
113
+ const token = getAgentDataToken(event);
114
+ if (defaultAgentTurn.needsNewThread) {
115
+ const environmentVariables = await resolveDefaultAgentEnvironmentVariables(
116
+ event,
117
+ context,
118
+ { conversationId },
119
+ "Failed to resolve workspace credentials, proceeding without env vars"
120
+ );
121
+ createChatAgentSession(token, withEnvironmentVariables(defaultAgentTurn.createPayload, environmentVariables)).then(async (result) => {
137
122
  if (result.success) {
138
123
  logger.info({ conversationId, sessionId: result.sessionId }, "New agent thread created");
139
124
  await db.update(schema.conversations).set({
140
125
  threadSessionId: result.sessionId,
141
- title: messageTitle,
142
- appliedSettingsAt: settingsTimestamp,
143
- model: effectiveModel ?? null,
126
+ title: defaultAgentTurn.messageTitle,
127
+ appliedSettingsAt: defaultAgentTurn.settingsTimestamp,
128
+ model: defaultAgentTurn.effectiveModel ?? null,
144
129
  updatedAt: /* @__PURE__ */ new Date()
145
130
  }).where(eq(schema.conversations.id, conversationId));
146
131
  } else {
@@ -158,20 +143,17 @@ export default defineEventHandler(async (event) => {
158
143
  }).where(eq(schema.messages.id, assistantMessageId));
159
144
  });
160
145
  } else {
161
- continueSession(token, conversation.threadSessionId, {
162
- content: body.content.trim(),
163
- fileUrls,
164
- model: effectiveModel
165
- }).then(async (result) => {
146
+ continueSession(token, conversation.threadSessionId, defaultAgentTurn.continuePayload).then(async (result) => {
166
147
  if (!result.success) {
167
148
  logger.warn({ conversationId, sessionId: conversation.threadSessionId, error: result.error }, "Agent session continue failed");
168
149
  await db.update(schema.messages).set({
169
150
  content: `Erro: ${result.error}`,
170
151
  status: "failed"
171
152
  }).where(eq(schema.messages.id, assistantMessageId));
153
+ return;
172
154
  }
173
155
  await db.update(schema.conversations).set({
174
- ...effectiveModel ? { model: effectiveModel } : {},
156
+ ...defaultAgentTurn.effectiveModel ? { model: defaultAgentTurn.effectiveModel } : {},
175
157
  updatedAt: /* @__PURE__ */ new Date()
176
158
  }).where(eq(schema.conversations.id, conversationId));
177
159
  }).catch(async (e) => {
@@ -1,10 +1,11 @@
1
1
  import { createError, defineEventHandler, getRouterParam } from "h3";
2
2
  import { eq, and } from "drizzle-orm";
3
3
  import { useDb, schema } from "#chat-runtime/server/db";
4
- import { resolveChatContext } from "#chat-runtime/server/utils/chat-context";
4
+ import { resolveChatRuntimeContext } from "#chat-runtime/server/utils/chat-context";
5
+ import { conversationScopeConditions } from "#chat-runtime/server/utils/conversation-scope";
5
6
  import { getWorkspaceBilling, transformCostForBilling } from "#chat-runtime/server/utils/billing";
6
7
  export default defineEventHandler(async (event) => {
7
- const context = resolveChatContext(event);
8
+ const context = resolveChatRuntimeContext(event);
8
9
  const db = useDb();
9
10
  const id = getRouterParam(event, "id");
10
11
  if (!id) {
@@ -13,12 +14,7 @@ export default defineEventHandler(async (event) => {
13
14
  statusMessage: "Conversation ID is required"
14
15
  });
15
16
  }
16
- const [conversation] = await db.select({ id: schema.conversations.id }).from(schema.conversations).where(
17
- and(
18
- eq(schema.conversations.id, id),
19
- eq(schema.conversations.workspaceId, context.workspaceId)
20
- )
21
- );
17
+ const [conversation] = await db.select({ id: schema.conversations.id }).from(schema.conversations).where(conversationScopeConditions(context, id));
22
18
  if (!conversation) {
23
19
  throw createError({
24
20
  statusCode: 404,
@@ -3,7 +3,7 @@ import { useRuntimeConfig } from "nitropack/runtime";
3
3
  import { createTelaClient } from "@meistrari/tela-sdk-js";
4
4
  import { logger } from "#chat-runtime/server/utils/logger";
5
5
  import { requireUser } from "#chat-runtime/server/utils/auth";
6
- import { useChatNuxtFeatures } from "#chat-runtime/utils/features";
6
+ import { resolveChatNuxtFeatures } from "#chat-runtime/utils/features";
7
7
  const TITLE_CANVAS_ID = "ba06c4a0-ef05-4fb6-b4ef-5af3d63a1ba2";
8
8
  const FALLBACK_TITLE_MAX_LENGTH = 60;
9
9
  const FALLBACK_TITLE_DEFAULT = "New chat";
@@ -26,8 +26,9 @@ export default defineEventHandler(async (event) => {
26
26
  statusMessage: "userMessage and assistantResponse are required"
27
27
  });
28
28
  }
29
- const { telaApiKey } = useRuntimeConfig();
30
- const features = useChatNuxtFeatures();
29
+ const runtimeConfig = useRuntimeConfig();
30
+ const { telaApiKey } = runtimeConfig;
31
+ const features = resolveChatNuxtFeatures(runtimeConfig);
31
32
  if (!features.generateTitle || !telaApiKey) {
32
33
  const fallback = buildFallbackTitle(userMessage);
33
34
  logger.debug({ titleLength: fallback.length, reason: !features.generateTitle ? "feature-disabled" : "no-tela-api-key" }, "Title generated via fallback");
@@ -1,12 +1,13 @@
1
1
  import { defineEventHandler } from "h3";
2
- import { desc, eq } from "drizzle-orm";
2
+ import { desc } from "drizzle-orm";
3
3
  import { useDb, schema } from "#chat-runtime/server/db";
4
- import { resolveChatContext } from "#chat-runtime/server/utils/chat-context";
4
+ import { resolveChatRuntimeContext } from "#chat-runtime/server/utils/chat-context";
5
+ import { conversationScopeConditions } from "#chat-runtime/server/utils/conversation-scope";
5
6
  import { logger } from "#chat-runtime/server/utils/logger";
6
7
  export default defineEventHandler(async (event) => {
7
- const context = resolveChatContext(event);
8
+ const context = resolveChatRuntimeContext(event);
8
9
  const db = useDb();
9
- const conversations = await db.select().from(schema.conversations).where(eq(schema.conversations.workspaceId, context.workspaceId)).orderBy(desc(schema.conversations.updatedAt));
10
+ const conversations = await db.select().from(schema.conversations).where(conversationScopeConditions(context)).orderBy(desc(schema.conversations.updatedAt));
10
11
  logger.debug({ workspaceId: context.workspaceId, count: conversations.length }, "Conversations listed");
11
12
  return conversations;
12
13
  });
@@ -1,10 +1,10 @@
1
1
  import { createError, defineEventHandler, getRequestHeader, readBody } from "h3";
2
2
  import { useDb, schema } from "#chat-runtime/server/db";
3
- import { resolveChatContext } from "#chat-runtime/server/utils/chat-context";
3
+ import { resolveChatRuntimeContext } from "#chat-runtime/server/utils/chat-context";
4
4
  import { logger } from "#chat-runtime/server/utils/logger";
5
5
  import { isValidModel } from "#chat-runtime/types/chat";
6
6
  export default defineEventHandler(async (event) => {
7
- const context = resolveChatContext(event);
7
+ const context = resolveChatRuntimeContext(event);
8
8
  const db = useDb();
9
9
  let body = {};
10
10
  const contentLength = getRequestHeader(event, "content-length");
@@ -19,7 +19,7 @@ export default defineEventHandler(async (event) => {
19
19
  });
20
20
  }
21
21
  }
22
- if (body.model !== void 0 && body.model !== null && !isValidModel(body.model)) {
22
+ if (!context.telaAgentId && body.model !== void 0 && body.model !== null && !isValidModel(body.model)) {
23
23
  throw createError({
24
24
  statusCode: 400,
25
25
  statusMessage: "Invalid model"
@@ -29,7 +29,8 @@ export default defineEventHandler(async (event) => {
29
29
  workspaceId: context.workspaceId,
30
30
  userId: context.user.id,
31
31
  createdBy: context.user.email,
32
- ...body.model ? { model: body.model } : {}
32
+ telaAgentId: context.telaAgentId,
33
+ ...context.telaAgentId ? { model: null } : body.model ? { model: body.model } : {}
33
34
  }).returning();
34
35
  if (!conversation) {
35
36
  throw createError({
@@ -0,0 +1,6 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<{
2
+ id: any;
3
+ inputSchema: any;
4
+ isMultiturn: any;
5
+ }>>;
6
+ export default _default;
@@ -0,0 +1,25 @@
1
+ import { createError, defineEventHandler, getRouterParam } from "h3";
2
+ import { requireUser } from "#chat-runtime/server/utils/auth";
3
+ import { getTelaAgent } from "#chat-runtime/server/utils/tela-agent-api";
4
+ export default defineEventHandler(async (event) => {
5
+ requireUser(event);
6
+ const agentId = getRouterParam(event, "id")?.trim();
7
+ if (!agentId) {
8
+ throw createError({
9
+ statusCode: 400,
10
+ statusMessage: "Agent ID is required"
11
+ });
12
+ }
13
+ const result = await getTelaAgent(event, agentId);
14
+ if (!result.success) {
15
+ throw createError({
16
+ statusCode: 502,
17
+ statusMessage: result.error
18
+ });
19
+ }
20
+ return {
21
+ id: result.data.id,
22
+ inputSchema: result.data.inputSchema,
23
+ isMultiturn: result.data.isMultiturn ?? null
24
+ };
25
+ });
@@ -55,7 +55,7 @@ export default defineEventHandler(async (event) => {
55
55
  name: skill.name,
56
56
  description: skill.description,
57
57
  runtime: skill.runtime,
58
- allowedTools: skill.allowedTools,
58
+ allowedTools: [...skill.allowedTools],
59
59
  isPublic: skill.isPublic,
60
60
  addedByUserId: skill.addedBy?.userId || session.user.id,
61
61
  addedByUsername: skill.addedBy?.username || session.user.name || "",
@@ -88,6 +88,23 @@ export declare const conversations: import("drizzle-orm/pg-core").PgTableWithCol
88
88
  identity: undefined;
89
89
  generated: undefined;
90
90
  }, {}, {}>;
91
+ telaAgentId: import("drizzle-orm/pg-core").PgColumn<{
92
+ name: "tela_agent_id";
93
+ tableName: "conversations";
94
+ dataType: "string";
95
+ columnType: "PgText";
96
+ data: string;
97
+ driverParam: string;
98
+ notNull: false;
99
+ hasDefault: false;
100
+ isPrimaryKey: false;
101
+ isAutoincrement: false;
102
+ hasRuntimeDefault: false;
103
+ enumValues: [string, ...string[]];
104
+ baseColumn: never;
105
+ identity: undefined;
106
+ generated: undefined;
107
+ }, {}, {}>;
91
108
  model: import("drizzle-orm/pg-core").PgColumn<{
92
109
  name: "model";
93
110
  tableName: "conversations";
@@ -6,6 +6,7 @@ export const conversations = chatSchema.table("conversations", {
6
6
  userId: text("user_id").notNull(),
7
7
  title: text("title").notNull().default("Nova conversa"),
8
8
  threadSessionId: text("thread_session_id"),
9
+ telaAgentId: text("tela_agent_id"),
9
10
  model: text("model").default("claude-sonnet-4-5"),
10
11
  appliedSettingsAt: timestamp("applied_settings_at", { withTimezone: true }),
11
12
  appliedSettingsSnapshot: jsonb("applied_settings_snapshot").$type(),
@@ -15,5 +16,6 @@ export const conversations = chatSchema.table("conversations", {
15
16
  }, (table) => [
16
17
  index("idx_conversations_workspace").on(table.workspaceId),
17
18
  index("idx_conversations_user").on(table.userId),
18
- index("idx_conversations_updated").on(table.updatedAt)
19
+ index("idx_conversations_updated").on(table.updatedAt),
20
+ index("idx_conversations_workspace_tela_agent_updated").on(table.workspaceId, table.telaAgentId, table.updatedAt)
19
21
  ]);
@@ -11,7 +11,7 @@ export type ExternalSkill = {
11
11
  name: string;
12
12
  description: string;
13
13
  runtime: string;
14
- allowedTools: string[];
14
+ allowedTools: readonly string[];
15
15
  isPublic: boolean;
16
16
  addedBy: {
17
17
  userId: string;
@@ -4,6 +4,11 @@ export type ChatContext = {
4
4
  user: AppSession['user'];
5
5
  workspaceId: string;
6
6
  };
7
+ export type ChatRuntimeContext = ChatContext & {
8
+ telaAgentId: string | null;
9
+ };
7
10
  export declare function resolveRequestedWorkspaceId(requestedWorkspaceId: string | null | undefined): string | null;
11
+ export declare function resolveRequestedTelaAgentId(requestedTelaAgentId: string | null | undefined): string | null;
8
12
  export declare function resolveChatContextFromSession(session: AppSession, requestedWorkspaceId?: string | null): ChatContext;
9
13
  export declare function resolveChatContext(event: H3Event): ChatContext;
14
+ export declare function resolveChatRuntimeContext(event: H3Event): ChatRuntimeContext;
@@ -1,9 +1,22 @@
1
1
  import { createError, getHeader } from "h3";
2
2
  import { requireUser } from "#chat-runtime/server/utils/auth";
3
+ const TELA_AGENT_ID_PATTERN = /^[A-Za-z0-9_-]{1,128}$/;
3
4
  export function resolveRequestedWorkspaceId(requestedWorkspaceId) {
4
5
  const normalized = requestedWorkspaceId?.trim();
5
6
  return normalized || null;
6
7
  }
8
+ export function resolveRequestedTelaAgentId(requestedTelaAgentId) {
9
+ const normalized = requestedTelaAgentId?.trim();
10
+ if (!normalized)
11
+ return null;
12
+ if (!TELA_AGENT_ID_PATTERN.test(normalized)) {
13
+ throw createError({
14
+ statusCode: 400,
15
+ statusMessage: "Invalid Tela agent ID"
16
+ });
17
+ }
18
+ return normalized;
19
+ }
7
20
  export function resolveChatContextFromSession(session, requestedWorkspaceId) {
8
21
  const normalizedRequestedWorkspaceId = resolveRequestedWorkspaceId(requestedWorkspaceId);
9
22
  if (normalizedRequestedWorkspaceId && normalizedRequestedWorkspaceId !== session.workspace.id) {
@@ -22,3 +35,10 @@ export function resolveChatContext(event) {
22
35
  const requestedWorkspaceId = getHeader(event, "x-chat-workspace-id");
23
36
  return resolveChatContextFromSession(session, requestedWorkspaceId);
24
37
  }
38
+ export function resolveChatRuntimeContext(event) {
39
+ const context = resolveChatContext(event);
40
+ return {
41
+ ...context,
42
+ telaAgentId: resolveRequestedTelaAgentId(getHeader(event, "x-chat-tela-agent-id"))
43
+ };
44
+ }
@@ -0,0 +1,39 @@
1
+ import type { H3Event } from 'h3';
2
+ import { schema } from '#chat-runtime/server/db';
3
+ import type { useDb } from '#chat-runtime/server/db';
4
+ import type { ChatRuntimeContext } from '#chat-runtime/server/utils/chat-context';
5
+ import type { FileUploadInput, MessageFile } from '#chat-runtime/types/chat';
6
+ import type { AgentApiChatPayload, ContinueSessionPayload } from '#chat-runtime/types/agent';
7
+ import type { TelaAgentExecutionInput, TelaAgentRunPayload } from '#chat-runtime/types/tela-agent';
8
+ type DbInstance = ReturnType<typeof useDb>;
9
+ type ConversationRecord = typeof schema.conversations.$inferSelect;
10
+ type AgentTurnOperation = 'send' | 'retry';
11
+ type AgentTurnFiles = FileUploadInput[] | MessageFile[] | null | undefined;
12
+ export type PreparedDefaultAgentTurn = {
13
+ needsNewThread: boolean;
14
+ effectiveModel?: string;
15
+ settingsTimestamp: Date;
16
+ messageTitle: string;
17
+ createPayload: AgentApiChatPayload;
18
+ continuePayload: ContinueSessionPayload;
19
+ };
20
+ export declare function buildTelaAgentTurnPayload(event: H3Event, conversation: Pick<ConversationRecord, 'threadSessionId' | 'telaAgentId'>, content: string, files?: FileUploadInput[] | MessageFile[] | null, agentInputs?: TelaAgentExecutionInput[] | null): Promise<TelaAgentRunPayload>;
21
+ export declare function queueTelaAgentTurn(event: H3Event, db: DbInstance, options: {
22
+ conversation: ConversationRecord;
23
+ conversationId: string;
24
+ assistantMessageId: string;
25
+ payload: TelaAgentRunPayload;
26
+ titleContent: string;
27
+ operation: AgentTurnOperation;
28
+ }): void;
29
+ export declare function prepareDefaultAgentTurn(event: H3Event, db: DbInstance, context: ChatRuntimeContext, options: {
30
+ conversation: ConversationRecord;
31
+ conversationId: string;
32
+ content: string;
33
+ files?: AgentTurnFiles;
34
+ requestedModel?: string;
35
+ workspaceSettingsSnapshot?: unknown;
36
+ }): Promise<PreparedDefaultAgentTurn>;
37
+ export declare function resolveDefaultAgentEnvironmentVariables(event: H3Event, context: ChatRuntimeContext, logContext: Record<string, unknown>, failureMessage: string): Promise<Record<string, string>>;
38
+ export declare function withEnvironmentVariables(payload: AgentApiChatPayload, environmentVariables: Record<string, string>): AgentApiChatPayload;
39
+ export {};