@copilotkitnext/runtime 1.54.0 → 1.54.1-next.1

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 (134) hide show
  1. package/dist/endpoints/express-single.cjs.map +1 -1
  2. package/dist/endpoints/express-single.d.cts +2 -2
  3. package/dist/endpoints/express-single.d.cts.map +1 -1
  4. package/dist/endpoints/express-single.d.mts +2 -2
  5. package/dist/endpoints/express-single.d.mts.map +1 -1
  6. package/dist/endpoints/express-single.mjs.map +1 -1
  7. package/dist/endpoints/express.cjs +38 -0
  8. package/dist/endpoints/express.cjs.map +1 -1
  9. package/dist/endpoints/express.d.cts +2 -2
  10. package/dist/endpoints/express.d.cts.map +1 -1
  11. package/dist/endpoints/express.d.mts +2 -2
  12. package/dist/endpoints/express.d.mts.map +1 -1
  13. package/dist/endpoints/express.mjs +38 -0
  14. package/dist/endpoints/express.mjs.map +1 -1
  15. package/dist/endpoints/hono-single.cjs.map +1 -1
  16. package/dist/endpoints/hono-single.d.cts +2 -2
  17. package/dist/endpoints/hono-single.d.cts.map +1 -1
  18. package/dist/endpoints/hono-single.d.mts +2 -2
  19. package/dist/endpoints/hono-single.d.mts.map +1 -1
  20. package/dist/endpoints/hono-single.mjs.map +1 -1
  21. package/dist/endpoints/hono.cjs +83 -0
  22. package/dist/endpoints/hono.cjs.map +1 -1
  23. package/dist/endpoints/hono.d.cts +3 -3
  24. package/dist/endpoints/hono.d.cts.map +1 -1
  25. package/dist/endpoints/hono.d.mts +3 -3
  26. package/dist/endpoints/hono.d.mts.map +1 -1
  27. package/dist/endpoints/hono.mjs +83 -0
  28. package/dist/endpoints/hono.mjs.map +1 -1
  29. package/dist/handlers/get-runtime-info.cjs +2 -0
  30. package/dist/handlers/get-runtime-info.cjs.map +1 -1
  31. package/dist/handlers/get-runtime-info.mjs +3 -1
  32. package/dist/handlers/get-runtime-info.mjs.map +1 -1
  33. package/dist/handlers/handle-connect.cjs +18 -80
  34. package/dist/handlers/handle-connect.cjs.map +1 -1
  35. package/dist/handlers/handle-connect.mjs +18 -79
  36. package/dist/handlers/handle-connect.mjs.map +1 -1
  37. package/dist/handlers/handle-run.cjs +26 -98
  38. package/dist/handlers/handle-run.cjs.map +1 -1
  39. package/dist/handlers/handle-run.mjs +26 -97
  40. package/dist/handlers/handle-run.mjs.map +1 -1
  41. package/dist/handlers/handle-stop.cjs.map +1 -1
  42. package/dist/handlers/handle-stop.mjs.map +1 -1
  43. package/dist/handlers/handle-threads.cjs +1 -0
  44. package/dist/handlers/handle-threads.mjs +3 -0
  45. package/dist/handlers/handle-transcribe.cjs.map +1 -1
  46. package/dist/handlers/handle-transcribe.mjs.map +1 -1
  47. package/dist/handlers/intelligence/connect.cjs +28 -0
  48. package/dist/handlers/intelligence/connect.cjs.map +1 -0
  49. package/dist/handlers/intelligence/connect.mjs +28 -0
  50. package/dist/handlers/intelligence/connect.mjs.map +1 -0
  51. package/dist/handlers/intelligence/run.cjs +77 -0
  52. package/dist/handlers/intelligence/run.cjs.map +1 -0
  53. package/dist/handlers/intelligence/run.mjs +76 -0
  54. package/dist/handlers/intelligence/run.mjs.map +1 -0
  55. package/dist/handlers/intelligence/thread-names.cjs +144 -0
  56. package/dist/handlers/intelligence/thread-names.cjs.map +1 -0
  57. package/dist/handlers/intelligence/thread-names.mjs +143 -0
  58. package/dist/handlers/intelligence/thread-names.mjs.map +1 -0
  59. package/dist/handlers/intelligence/threads.cjs +133 -0
  60. package/dist/handlers/intelligence/threads.cjs.map +1 -0
  61. package/dist/handlers/intelligence/threads.mjs +128 -0
  62. package/dist/handlers/intelligence/threads.mjs.map +1 -0
  63. package/dist/handlers/shared/agent-utils.cjs +73 -0
  64. package/dist/handlers/shared/agent-utils.cjs.map +1 -0
  65. package/dist/handlers/shared/agent-utils.mjs +69 -0
  66. package/dist/handlers/shared/agent-utils.mjs.map +1 -0
  67. package/dist/handlers/shared/intelligence-utils.cjs +20 -0
  68. package/dist/handlers/shared/intelligence-utils.cjs.map +1 -0
  69. package/dist/handlers/shared/intelligence-utils.mjs +19 -0
  70. package/dist/handlers/shared/intelligence-utils.mjs.map +1 -0
  71. package/dist/handlers/shared/json-response.cjs +7 -0
  72. package/dist/handlers/shared/json-response.cjs.map +1 -0
  73. package/dist/handlers/shared/json-response.mjs +6 -0
  74. package/dist/handlers/shared/json-response.mjs.map +1 -0
  75. package/dist/handlers/shared/sse-response.cjs +63 -0
  76. package/dist/handlers/shared/sse-response.cjs.map +1 -0
  77. package/dist/handlers/shared/sse-response.mjs +62 -0
  78. package/dist/handlers/shared/sse-response.mjs.map +1 -0
  79. package/dist/handlers/sse/connect.cjs +17 -0
  80. package/dist/handlers/sse/connect.cjs.map +1 -0
  81. package/dist/handlers/sse/connect.mjs +17 -0
  82. package/dist/handlers/sse/connect.mjs.map +1 -0
  83. package/dist/handlers/sse/run.cjs +17 -0
  84. package/dist/handlers/sse/run.cjs.map +1 -0
  85. package/dist/handlers/sse/run.mjs +17 -0
  86. package/dist/handlers/sse/run.mjs.map +1 -0
  87. package/dist/index.cjs +8 -2
  88. package/dist/index.d.cts +3 -2
  89. package/dist/index.d.mts +4 -2
  90. package/dist/index.mjs +5 -3
  91. package/dist/intelligence-platform/client.cjs +318 -0
  92. package/dist/intelligence-platform/client.cjs.map +1 -0
  93. package/dist/intelligence-platform/client.d.cts +327 -0
  94. package/dist/intelligence-platform/client.d.cts.map +1 -0
  95. package/dist/intelligence-platform/client.d.mts +327 -0
  96. package/dist/intelligence-platform/client.d.mts.map +1 -0
  97. package/dist/intelligence-platform/client.mjs +316 -0
  98. package/dist/intelligence-platform/client.mjs.map +1 -0
  99. package/dist/intelligence-platform/index.cjs +1 -0
  100. package/dist/intelligence-platform/index.d.mts +1 -0
  101. package/dist/intelligence-platform/index.mjs +3 -0
  102. package/dist/middleware.cjs.map +1 -1
  103. package/dist/middleware.d.cts +3 -3
  104. package/dist/middleware.d.cts.map +1 -1
  105. package/dist/middleware.d.mts +3 -3
  106. package/dist/middleware.d.mts.map +1 -1
  107. package/dist/middleware.mjs.map +1 -1
  108. package/dist/package.cjs +1 -1
  109. package/dist/package.mjs +1 -1
  110. package/dist/runner/agent-runner.cjs.map +1 -1
  111. package/dist/runner/agent-runner.d.cts +4 -1
  112. package/dist/runner/agent-runner.d.cts.map +1 -1
  113. package/dist/runner/agent-runner.d.mts +4 -1
  114. package/dist/runner/agent-runner.d.mts.map +1 -1
  115. package/dist/runner/agent-runner.mjs.map +1 -1
  116. package/dist/runner/in-memory.cjs +1 -1
  117. package/dist/runner/in-memory.mjs +1 -1
  118. package/dist/runner/intelligence.cjs +87 -24
  119. package/dist/runner/intelligence.cjs.map +1 -1
  120. package/dist/runner/intelligence.d.cts +8 -3
  121. package/dist/runner/intelligence.d.cts.map +1 -1
  122. package/dist/runner/intelligence.d.mts +8 -3
  123. package/dist/runner/intelligence.d.mts.map +1 -1
  124. package/dist/runner/intelligence.mjs +87 -24
  125. package/dist/runner/intelligence.mjs.map +1 -1
  126. package/dist/runtime.cjs +76 -6
  127. package/dist/runtime.cjs.map +1 -1
  128. package/dist/runtime.d.cts +71 -21
  129. package/dist/runtime.d.cts.map +1 -1
  130. package/dist/runtime.d.mts +72 -21
  131. package/dist/runtime.d.mts.map +1 -1
  132. package/dist/runtime.mjs +73 -7
  133. package/dist/runtime.mjs.map +1 -1
  134. package/package.json +5 -5
@@ -0,0 +1,77 @@
1
+ const require_runtime = require('../../_virtual/_rolldown/runtime.cjs');
2
+ const require_intelligence_utils = require('../shared/intelligence-utils.cjs');
3
+ const require_thread_names = require('./thread-names.cjs');
4
+ let _copilotkitnext_shared = require("@copilotkitnext/shared");
5
+
6
+ //#region src/handlers/intelligence/run.ts
7
+ async function handleIntelligenceRun({ runtime, request, agentId, agent, input }) {
8
+ if (!runtime.intelligence) return Response.json({
9
+ error: "Intelligence not configured",
10
+ message: "Intelligence mode requires a CopilotKitIntelligence"
11
+ }, { status: 500 });
12
+ const userId = request.headers.get("X-User-Id");
13
+ if (!require_intelligence_utils.isValidIdentifier(userId)) return Response.json({
14
+ error: "X-User-Id header is required",
15
+ message: "A valid X-User-Id header is required"
16
+ }, { status: 400 });
17
+ try {
18
+ const { thread, created } = await runtime.intelligence.getOrCreateThread({
19
+ threadId: input.threadId,
20
+ userId,
21
+ agentId
22
+ });
23
+ if (created && runtime.generateThreadNames && !thread.name?.trim()) require_thread_names.generateThreadNameForNewThread({
24
+ runtime,
25
+ request,
26
+ agentId,
27
+ sourceInput: input,
28
+ thread,
29
+ userId
30
+ }).catch((nameError) => {
31
+ _copilotkitnext_shared.logger.error("Failed to generate thread name:", nameError);
32
+ });
33
+ } catch (error) {
34
+ _copilotkitnext_shared.logger.error("Failed to get or create thread:", error);
35
+ return Response.json({ error: "Failed to initialize thread" }, { status: 502 });
36
+ }
37
+ let joinCode;
38
+ let joinToken;
39
+ try {
40
+ const lockResult = await runtime.intelligence.ɵacquireThreadLock({
41
+ threadId: input.threadId,
42
+ runId: input.runId
43
+ });
44
+ joinToken = lockResult.joinToken;
45
+ joinCode = lockResult.joinCode;
46
+ } catch (error) {
47
+ _copilotkitnext_shared.logger.error("Thread lock denied:", error);
48
+ return Response.json({ error: "Thread lock denied" }, { status: 409 });
49
+ }
50
+ if (!joinToken) return Response.json({
51
+ error: "Join token not available",
52
+ message: "Intelligence platform did not return a join token"
53
+ }, { status: 502 });
54
+ let persistedInputMessages;
55
+ if (Array.isArray(input.messages)) try {
56
+ const history = await runtime.intelligence.getThreadMessages({ threadId: input.threadId });
57
+ const historicMessageIds = new Set(history.messages.map((message) => message.id));
58
+ persistedInputMessages = input.messages.filter((message) => !historicMessageIds.has(message.id));
59
+ } catch (error) {
60
+ _copilotkitnext_shared.logger.error("Thread history lookup failed:", error);
61
+ return Response.json({ error: "Thread history lookup failed" }, { status: 502 });
62
+ }
63
+ runtime.runner.run({
64
+ threadId: input.threadId,
65
+ agent,
66
+ input,
67
+ ...persistedInputMessages !== void 0 ? { persistedInputMessages } : {},
68
+ ...joinCode ? { joinCode } : {}
69
+ }).subscribe({ error: (error) => {
70
+ _copilotkitnext_shared.logger.error("Error running agent:", error);
71
+ } });
72
+ return Response.json({ joinToken }, { headers: { "Cache-Control": "no-cache" } });
73
+ }
74
+
75
+ //#endregion
76
+ exports.handleIntelligenceRun = handleIntelligenceRun;
77
+ //# sourceMappingURL=run.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.cjs","names":["isValidIdentifier","generateThreadNameForNewThread"],"sources":["../../../src/handlers/intelligence/run.ts"],"sourcesContent":["import { AbstractAgent, Message, RunAgentInput } from \"@ag-ui/client\";\nimport { CopilotIntelligenceRuntimeLike } from \"../../runtime\";\nimport { isValidIdentifier } from \"../shared/intelligence-utils\";\nimport { generateThreadNameForNewThread } from \"./thread-names\";\nimport { logger } from \"@copilotkitnext/shared\";\n\ninterface HandleIntelligenceRunParams {\n runtime: CopilotIntelligenceRuntimeLike;\n request: Request;\n agentId: string;\n agent: AbstractAgent;\n input: RunAgentInput;\n}\n\nexport async function handleIntelligenceRun({\n runtime,\n request,\n agentId,\n agent,\n input,\n}: HandleIntelligenceRunParams): Promise<Response> {\n if (!runtime.intelligence) {\n return Response.json(\n {\n error: \"Intelligence not configured\",\n message: \"Intelligence mode requires a CopilotKitIntelligence\",\n },\n { status: 500 },\n );\n }\n\n const userId = request.headers.get(\"X-User-Id\");\n if (!isValidIdentifier(userId)) {\n return Response.json(\n {\n error: \"X-User-Id header is required\",\n message: \"A valid X-User-Id header is required\",\n },\n { status: 400 },\n );\n }\n\n try {\n const { thread, created } = await runtime.intelligence.getOrCreateThread({\n threadId: input.threadId,\n userId,\n agentId,\n });\n\n if (created && runtime.generateThreadNames && !thread.name?.trim()) {\n void generateThreadNameForNewThread({\n runtime,\n request,\n agentId,\n sourceInput: input,\n thread,\n userId,\n }).catch((nameError) => {\n logger.error(\"Failed to generate thread name:\", nameError);\n });\n }\n } catch (error) {\n logger.error(\"Failed to get or create thread:\", error);\n return Response.json(\n {\n error: \"Failed to initialize thread\",\n },\n { status: 502 },\n );\n }\n\n let joinCode: string | undefined;\n let joinToken: string | undefined;\n try {\n const lockResult = await runtime.intelligence.ɵacquireThreadLock({\n threadId: input.threadId,\n runId: input.runId,\n });\n joinToken = lockResult.joinToken;\n joinCode = lockResult.joinCode;\n } catch (error) {\n logger.error(\"Thread lock denied:\", error);\n return Response.json(\n {\n error: \"Thread lock denied\",\n },\n { status: 409 },\n );\n }\n\n if (!joinToken) {\n return Response.json(\n {\n error: \"Join token not available\",\n message: \"Intelligence platform did not return a join token\",\n },\n { status: 502 },\n );\n }\n\n let persistedInputMessages: Message[] | undefined;\n if (Array.isArray(input.messages)) {\n try {\n const history = await runtime.intelligence.getThreadMessages({\n threadId: input.threadId,\n });\n const historicMessageIds = new Set(\n history.messages.map((message) => message.id),\n );\n persistedInputMessages = input.messages.filter(\n (message) => !historicMessageIds.has(message.id),\n );\n } catch (error) {\n logger.error(\"Thread history lookup failed:\", error);\n return Response.json(\n {\n error: \"Thread history lookup failed\",\n },\n { status: 502 },\n );\n }\n }\n\n runtime.runner\n .run({\n threadId: input.threadId,\n agent,\n input,\n ...(persistedInputMessages !== undefined\n ? { persistedInputMessages }\n : {}),\n ...(joinCode ? { joinCode } : {}),\n })\n .subscribe({\n error: (error) => {\n logger.error(\"Error running agent:\", error);\n },\n });\n\n return Response.json(\n { joinToken },\n {\n headers: { \"Cache-Control\": \"no-cache\" },\n },\n );\n}\n"],"mappings":";;;;;;AAcA,eAAsB,sBAAsB,EAC1C,SACA,SACA,SACA,OACA,SACiD;AACjD,KAAI,CAAC,QAAQ,aACX,QAAO,SAAS,KACd;EACE,OAAO;EACP,SAAS;EACV,EACD,EAAE,QAAQ,KAAK,CAChB;CAGH,MAAM,SAAS,QAAQ,QAAQ,IAAI,YAAY;AAC/C,KAAI,CAACA,6CAAkB,OAAO,CAC5B,QAAO,SAAS,KACd;EACE,OAAO;EACP,SAAS;EACV,EACD,EAAE,QAAQ,KAAK,CAChB;AAGH,KAAI;EACF,MAAM,EAAE,QAAQ,YAAY,MAAM,QAAQ,aAAa,kBAAkB;GACvE,UAAU,MAAM;GAChB;GACA;GACD,CAAC;AAEF,MAAI,WAAW,QAAQ,uBAAuB,CAAC,OAAO,MAAM,MAAM,CAChE,CAAKC,oDAA+B;GAClC;GACA;GACA;GACA,aAAa;GACb;GACA;GACD,CAAC,CAAC,OAAO,cAAc;AACtB,iCAAO,MAAM,mCAAmC,UAAU;IAC1D;UAEG,OAAO;AACd,gCAAO,MAAM,mCAAmC,MAAM;AACtD,SAAO,SAAS,KACd,EACE,OAAO,+BACR,EACD,EAAE,QAAQ,KAAK,CAChB;;CAGH,IAAI;CACJ,IAAI;AACJ,KAAI;EACF,MAAM,aAAa,MAAM,QAAQ,aAAa,mBAAmB;GAC/D,UAAU,MAAM;GAChB,OAAO,MAAM;GACd,CAAC;AACF,cAAY,WAAW;AACvB,aAAW,WAAW;UACf,OAAO;AACd,gCAAO,MAAM,uBAAuB,MAAM;AAC1C,SAAO,SAAS,KACd,EACE,OAAO,sBACR,EACD,EAAE,QAAQ,KAAK,CAChB;;AAGH,KAAI,CAAC,UACH,QAAO,SAAS,KACd;EACE,OAAO;EACP,SAAS;EACV,EACD,EAAE,QAAQ,KAAK,CAChB;CAGH,IAAI;AACJ,KAAI,MAAM,QAAQ,MAAM,SAAS,CAC/B,KAAI;EACF,MAAM,UAAU,MAAM,QAAQ,aAAa,kBAAkB,EAC3D,UAAU,MAAM,UACjB,CAAC;EACF,MAAM,qBAAqB,IAAI,IAC7B,QAAQ,SAAS,KAAK,YAAY,QAAQ,GAAG,CAC9C;AACD,2BAAyB,MAAM,SAAS,QACrC,YAAY,CAAC,mBAAmB,IAAI,QAAQ,GAAG,CACjD;UACM,OAAO;AACd,gCAAO,MAAM,iCAAiC,MAAM;AACpD,SAAO,SAAS,KACd,EACE,OAAO,gCACR,EACD,EAAE,QAAQ,KAAK,CAChB;;AAIL,SAAQ,OACL,IAAI;EACH,UAAU,MAAM;EAChB;EACA;EACA,GAAI,2BAA2B,SAC3B,EAAE,wBAAwB,GAC1B,EAAE;EACN,GAAI,WAAW,EAAE,UAAU,GAAG,EAAE;EACjC,CAAC,CACD,UAAU,EACT,QAAQ,UAAU;AAChB,gCAAO,MAAM,wBAAwB,MAAM;IAE9C,CAAC;AAEJ,QAAO,SAAS,KACd,EAAE,WAAW,EACb,EACE,SAAS,EAAE,iBAAiB,YAAY,EACzC,CACF"}
@@ -0,0 +1,76 @@
1
+ import { isValidIdentifier } from "../shared/intelligence-utils.mjs";
2
+ import { generateThreadNameForNewThread } from "./thread-names.mjs";
3
+ import { logger } from "@copilotkitnext/shared";
4
+
5
+ //#region src/handlers/intelligence/run.ts
6
+ async function handleIntelligenceRun({ runtime, request, agentId, agent, input }) {
7
+ if (!runtime.intelligence) return Response.json({
8
+ error: "Intelligence not configured",
9
+ message: "Intelligence mode requires a CopilotKitIntelligence"
10
+ }, { status: 500 });
11
+ const userId = request.headers.get("X-User-Id");
12
+ if (!isValidIdentifier(userId)) return Response.json({
13
+ error: "X-User-Id header is required",
14
+ message: "A valid X-User-Id header is required"
15
+ }, { status: 400 });
16
+ try {
17
+ const { thread, created } = await runtime.intelligence.getOrCreateThread({
18
+ threadId: input.threadId,
19
+ userId,
20
+ agentId
21
+ });
22
+ if (created && runtime.generateThreadNames && !thread.name?.trim()) generateThreadNameForNewThread({
23
+ runtime,
24
+ request,
25
+ agentId,
26
+ sourceInput: input,
27
+ thread,
28
+ userId
29
+ }).catch((nameError) => {
30
+ logger.error("Failed to generate thread name:", nameError);
31
+ });
32
+ } catch (error) {
33
+ logger.error("Failed to get or create thread:", error);
34
+ return Response.json({ error: "Failed to initialize thread" }, { status: 502 });
35
+ }
36
+ let joinCode;
37
+ let joinToken;
38
+ try {
39
+ const lockResult = await runtime.intelligence.ɵacquireThreadLock({
40
+ threadId: input.threadId,
41
+ runId: input.runId
42
+ });
43
+ joinToken = lockResult.joinToken;
44
+ joinCode = lockResult.joinCode;
45
+ } catch (error) {
46
+ logger.error("Thread lock denied:", error);
47
+ return Response.json({ error: "Thread lock denied" }, { status: 409 });
48
+ }
49
+ if (!joinToken) return Response.json({
50
+ error: "Join token not available",
51
+ message: "Intelligence platform did not return a join token"
52
+ }, { status: 502 });
53
+ let persistedInputMessages;
54
+ if (Array.isArray(input.messages)) try {
55
+ const history = await runtime.intelligence.getThreadMessages({ threadId: input.threadId });
56
+ const historicMessageIds = new Set(history.messages.map((message) => message.id));
57
+ persistedInputMessages = input.messages.filter((message) => !historicMessageIds.has(message.id));
58
+ } catch (error) {
59
+ logger.error("Thread history lookup failed:", error);
60
+ return Response.json({ error: "Thread history lookup failed" }, { status: 502 });
61
+ }
62
+ runtime.runner.run({
63
+ threadId: input.threadId,
64
+ agent,
65
+ input,
66
+ ...persistedInputMessages !== void 0 ? { persistedInputMessages } : {},
67
+ ...joinCode ? { joinCode } : {}
68
+ }).subscribe({ error: (error) => {
69
+ logger.error("Error running agent:", error);
70
+ } });
71
+ return Response.json({ joinToken }, { headers: { "Cache-Control": "no-cache" } });
72
+ }
73
+
74
+ //#endregion
75
+ export { handleIntelligenceRun };
76
+ //# sourceMappingURL=run.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.mjs","names":[],"sources":["../../../src/handlers/intelligence/run.ts"],"sourcesContent":["import { AbstractAgent, Message, RunAgentInput } from \"@ag-ui/client\";\nimport { CopilotIntelligenceRuntimeLike } from \"../../runtime\";\nimport { isValidIdentifier } from \"../shared/intelligence-utils\";\nimport { generateThreadNameForNewThread } from \"./thread-names\";\nimport { logger } from \"@copilotkitnext/shared\";\n\ninterface HandleIntelligenceRunParams {\n runtime: CopilotIntelligenceRuntimeLike;\n request: Request;\n agentId: string;\n agent: AbstractAgent;\n input: RunAgentInput;\n}\n\nexport async function handleIntelligenceRun({\n runtime,\n request,\n agentId,\n agent,\n input,\n}: HandleIntelligenceRunParams): Promise<Response> {\n if (!runtime.intelligence) {\n return Response.json(\n {\n error: \"Intelligence not configured\",\n message: \"Intelligence mode requires a CopilotKitIntelligence\",\n },\n { status: 500 },\n );\n }\n\n const userId = request.headers.get(\"X-User-Id\");\n if (!isValidIdentifier(userId)) {\n return Response.json(\n {\n error: \"X-User-Id header is required\",\n message: \"A valid X-User-Id header is required\",\n },\n { status: 400 },\n );\n }\n\n try {\n const { thread, created } = await runtime.intelligence.getOrCreateThread({\n threadId: input.threadId,\n userId,\n agentId,\n });\n\n if (created && runtime.generateThreadNames && !thread.name?.trim()) {\n void generateThreadNameForNewThread({\n runtime,\n request,\n agentId,\n sourceInput: input,\n thread,\n userId,\n }).catch((nameError) => {\n logger.error(\"Failed to generate thread name:\", nameError);\n });\n }\n } catch (error) {\n logger.error(\"Failed to get or create thread:\", error);\n return Response.json(\n {\n error: \"Failed to initialize thread\",\n },\n { status: 502 },\n );\n }\n\n let joinCode: string | undefined;\n let joinToken: string | undefined;\n try {\n const lockResult = await runtime.intelligence.ɵacquireThreadLock({\n threadId: input.threadId,\n runId: input.runId,\n });\n joinToken = lockResult.joinToken;\n joinCode = lockResult.joinCode;\n } catch (error) {\n logger.error(\"Thread lock denied:\", error);\n return Response.json(\n {\n error: \"Thread lock denied\",\n },\n { status: 409 },\n );\n }\n\n if (!joinToken) {\n return Response.json(\n {\n error: \"Join token not available\",\n message: \"Intelligence platform did not return a join token\",\n },\n { status: 502 },\n );\n }\n\n let persistedInputMessages: Message[] | undefined;\n if (Array.isArray(input.messages)) {\n try {\n const history = await runtime.intelligence.getThreadMessages({\n threadId: input.threadId,\n });\n const historicMessageIds = new Set(\n history.messages.map((message) => message.id),\n );\n persistedInputMessages = input.messages.filter(\n (message) => !historicMessageIds.has(message.id),\n );\n } catch (error) {\n logger.error(\"Thread history lookup failed:\", error);\n return Response.json(\n {\n error: \"Thread history lookup failed\",\n },\n { status: 502 },\n );\n }\n }\n\n runtime.runner\n .run({\n threadId: input.threadId,\n agent,\n input,\n ...(persistedInputMessages !== undefined\n ? { persistedInputMessages }\n : {}),\n ...(joinCode ? { joinCode } : {}),\n })\n .subscribe({\n error: (error) => {\n logger.error(\"Error running agent:\", error);\n },\n });\n\n return Response.json(\n { joinToken },\n {\n headers: { \"Cache-Control\": \"no-cache\" },\n },\n );\n}\n"],"mappings":";;;;;AAcA,eAAsB,sBAAsB,EAC1C,SACA,SACA,SACA,OACA,SACiD;AACjD,KAAI,CAAC,QAAQ,aACX,QAAO,SAAS,KACd;EACE,OAAO;EACP,SAAS;EACV,EACD,EAAE,QAAQ,KAAK,CAChB;CAGH,MAAM,SAAS,QAAQ,QAAQ,IAAI,YAAY;AAC/C,KAAI,CAAC,kBAAkB,OAAO,CAC5B,QAAO,SAAS,KACd;EACE,OAAO;EACP,SAAS;EACV,EACD,EAAE,QAAQ,KAAK,CAChB;AAGH,KAAI;EACF,MAAM,EAAE,QAAQ,YAAY,MAAM,QAAQ,aAAa,kBAAkB;GACvE,UAAU,MAAM;GAChB;GACA;GACD,CAAC;AAEF,MAAI,WAAW,QAAQ,uBAAuB,CAAC,OAAO,MAAM,MAAM,CAChE,CAAK,+BAA+B;GAClC;GACA;GACA;GACA,aAAa;GACb;GACA;GACD,CAAC,CAAC,OAAO,cAAc;AACtB,UAAO,MAAM,mCAAmC,UAAU;IAC1D;UAEG,OAAO;AACd,SAAO,MAAM,mCAAmC,MAAM;AACtD,SAAO,SAAS,KACd,EACE,OAAO,+BACR,EACD,EAAE,QAAQ,KAAK,CAChB;;CAGH,IAAI;CACJ,IAAI;AACJ,KAAI;EACF,MAAM,aAAa,MAAM,QAAQ,aAAa,mBAAmB;GAC/D,UAAU,MAAM;GAChB,OAAO,MAAM;GACd,CAAC;AACF,cAAY,WAAW;AACvB,aAAW,WAAW;UACf,OAAO;AACd,SAAO,MAAM,uBAAuB,MAAM;AAC1C,SAAO,SAAS,KACd,EACE,OAAO,sBACR,EACD,EAAE,QAAQ,KAAK,CAChB;;AAGH,KAAI,CAAC,UACH,QAAO,SAAS,KACd;EACE,OAAO;EACP,SAAS;EACV,EACD,EAAE,QAAQ,KAAK,CAChB;CAGH,IAAI;AACJ,KAAI,MAAM,QAAQ,MAAM,SAAS,CAC/B,KAAI;EACF,MAAM,UAAU,MAAM,QAAQ,aAAa,kBAAkB,EAC3D,UAAU,MAAM,UACjB,CAAC;EACF,MAAM,qBAAqB,IAAI,IAC7B,QAAQ,SAAS,KAAK,YAAY,QAAQ,GAAG,CAC9C;AACD,2BAAyB,MAAM,SAAS,QACrC,YAAY,CAAC,mBAAmB,IAAI,QAAQ,GAAG,CACjD;UACM,OAAO;AACd,SAAO,MAAM,iCAAiC,MAAM;AACpD,SAAO,SAAS,KACd,EACE,OAAO,gCACR,EACD,EAAE,QAAQ,KAAK,CAChB;;AAIL,SAAQ,OACL,IAAI;EACH,UAAU,MAAM;EAChB;EACA;EACA,GAAI,2BAA2B,SAC3B,EAAE,wBAAwB,GAC1B,EAAE;EACN,GAAI,WAAW,EAAE,UAAU,GAAG,EAAE;EACjC,CAAC,CACD,UAAU,EACT,QAAQ,UAAU;AAChB,SAAO,MAAM,wBAAwB,MAAM;IAE9C,CAAC;AAEJ,QAAO,SAAS,KACd,EAAE,WAAW,EACb,EACE,SAAS,EAAE,iBAAiB,YAAY,EACzC,CACF"}
@@ -0,0 +1,144 @@
1
+ const require_runtime = require('../../_virtual/_rolldown/runtime.cjs');
2
+ const require_agent_utils = require('../shared/agent-utils.cjs');
3
+ let _copilotkitnext_shared = require("@copilotkitnext/shared");
4
+ let node_crypto = require("node:crypto");
5
+
6
+ //#region src/handlers/intelligence/thread-names.ts
7
+ const THREAD_NAME_SYSTEM_PROMPT = [
8
+ "You generate short, specific conversation titles.",
9
+ "Return JSON only in this exact shape: {\"title\":\"...\"}",
10
+ "The title must be 2 to 5 words.",
11
+ "Use sentence case.",
12
+ "No quotes.",
13
+ "No emoji.",
14
+ "No markdown characters or formatting.",
15
+ "Do not use *, _, #, `, [, ], (, ), !, ~, >, or |.",
16
+ "No trailing punctuation.",
17
+ "No explanations.",
18
+ "Do not call tools."
19
+ ].join("\n");
20
+ const MAX_TITLE_LENGTH = 80;
21
+ const MAX_TITLE_WORDS = 8;
22
+ const MAX_TRANSCRIPT_MESSAGES = 8;
23
+ const MAX_TITLE_GENERATION_ATTEMPTS = 3;
24
+ const FALLBACK_THREAD_TITLE = "Untitled";
25
+ async function generateThreadNameForNewThread({ runtime, request, agentId, sourceInput, thread, userId }) {
26
+ if (!runtime.generateThreadNames || hasThreadName(thread.name)) return;
27
+ const prompt = buildThreadTitlePrompt(sourceInput.messages);
28
+ if (!prompt) return;
29
+ let generatedTitle = null;
30
+ for (let attempt = 1; attempt <= MAX_TITLE_GENERATION_ATTEMPTS; attempt++) try {
31
+ generatedTitle = await runTitleGenerationAttempt({
32
+ runtime,
33
+ request,
34
+ agentId,
35
+ threadId: thread.id,
36
+ prompt
37
+ });
38
+ if (generatedTitle) break;
39
+ _copilotkitnext_shared.logger.warn({
40
+ agentId,
41
+ attempt,
42
+ threadId: thread.id
43
+ }, "Thread name generation returned an empty or invalid title");
44
+ } catch (error) {
45
+ _copilotkitnext_shared.logger.warn({
46
+ err: error,
47
+ agentId,
48
+ attempt,
49
+ threadId: thread.id
50
+ }, "Thread name generation attempt failed");
51
+ }
52
+ await runtime.intelligence.updateThread({
53
+ threadId: thread.id,
54
+ userId,
55
+ agentId,
56
+ updates: { name: generatedTitle ?? FALLBACK_THREAD_TITLE }
57
+ });
58
+ }
59
+ async function runTitleGenerationAttempt(params) {
60
+ const { runtime, request, agentId, threadId, prompt } = params;
61
+ const agent = await require_agent_utils.cloneAgentForRequest(runtime, agentId);
62
+ if (agent instanceof Response) {
63
+ _copilotkitnext_shared.logger.warn({
64
+ agentId,
65
+ threadId
66
+ }, "Skipping thread naming because the agent could not be cloned");
67
+ return null;
68
+ }
69
+ require_agent_utils.configureAgentForRequest({
70
+ runtime,
71
+ request,
72
+ agentId,
73
+ agent
74
+ });
75
+ const messages = [{
76
+ id: (0, node_crypto.randomUUID)(),
77
+ role: "system",
78
+ content: THREAD_NAME_SYSTEM_PROMPT
79
+ }, {
80
+ id: (0, node_crypto.randomUUID)(),
81
+ role: "user",
82
+ content: prompt
83
+ }];
84
+ agent.setMessages(messages);
85
+ agent.setState({});
86
+ agent.threadId = `thread-name:${threadId}:${(0, node_crypto.randomUUID)()}`;
87
+ const { newMessages } = await agent.runAgent({
88
+ messages,
89
+ state: {},
90
+ tools: [],
91
+ context: [],
92
+ forwardedProps: {}
93
+ });
94
+ const lastMessage = newMessages.at(-1);
95
+ return normalizeGeneratedTitle(lastMessage ? stringifyMessageContent(lastMessage.content) : "");
96
+ }
97
+ function buildThreadTitlePrompt(messages) {
98
+ const transcript = (messages ?? []).filter((message) => [
99
+ "user",
100
+ "assistant",
101
+ "system",
102
+ "developer"
103
+ ].includes(message.role)).map((message) => {
104
+ const content = stringifyMessageContent(message.content);
105
+ if (!content) return null;
106
+ return `${message.role}: ${content}`;
107
+ }).filter((message) => !!message).slice(-MAX_TRANSCRIPT_MESSAGES);
108
+ if (transcript.length === 0) return null;
109
+ return [
110
+ "Generate a short title for this conversation.",
111
+ "Conversation:",
112
+ transcript.join("\n")
113
+ ].join("\n\n");
114
+ }
115
+ function stringifyMessageContent(content) {
116
+ if (typeof content === "string") return content.trim();
117
+ if (content == null) return "";
118
+ try {
119
+ return JSON.stringify(content).trim();
120
+ } catch {
121
+ return "";
122
+ }
123
+ }
124
+ function normalizeGeneratedTitle(rawTitle) {
125
+ let candidate = rawTitle.trim();
126
+ if (!candidate) return null;
127
+ candidate = candidate.replace(/^```(?:json)?\s*/i, "").replace(/\s*```$/, "").trim();
128
+ try {
129
+ const parsed = JSON.parse(candidate);
130
+ if (typeof parsed.title === "string") candidate = parsed.title;
131
+ } catch {}
132
+ candidate = candidate.replace(/^["'`]+|["'`]+$/g, "").replace(/[*_#[\]()!~>|]+/g, "").replace(/[.!?,;:]+$/g, "").replace(/\s+/g, " ").trim();
133
+ if (!candidate) return null;
134
+ if (candidate.length > MAX_TITLE_LENGTH) candidate = candidate.slice(0, MAX_TITLE_LENGTH).trim();
135
+ if (candidate.split(/\s+/).length > MAX_TITLE_WORDS) return null;
136
+ return candidate;
137
+ }
138
+ function hasThreadName(name) {
139
+ return typeof name === "string" && name.trim().length > 0;
140
+ }
141
+
142
+ //#endregion
143
+ exports.generateThreadNameForNewThread = generateThreadNameForNewThread;
144
+ //# sourceMappingURL=thread-names.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thread-names.cjs","names":["cloneAgentForRequest"],"sources":["../../../src/handlers/intelligence/thread-names.ts"],"sourcesContent":["import { AbstractAgent, Message, RunAgentInput } from \"@ag-ui/client\";\nimport { logger } from \"@copilotkitnext/shared\";\nimport { randomUUID } from \"node:crypto\";\nimport { CopilotIntelligenceRuntimeLike } from \"../../runtime\";\nimport {\n cloneAgentForRequest,\n configureAgentForRequest,\n} from \"../shared/agent-utils\";\nimport { ThreadSummary } from \"../../intelligence-platform\";\n\nconst THREAD_NAME_SYSTEM_PROMPT = [\n \"You generate short, specific conversation titles.\",\n 'Return JSON only in this exact shape: {\"title\":\"...\"}',\n \"The title must be 2 to 5 words.\",\n \"Use sentence case.\",\n \"No quotes.\",\n \"No emoji.\",\n \"No markdown characters or formatting.\",\n \"Do not use *, _, #, `, [, ], (, ), !, ~, >, or |.\",\n \"No trailing punctuation.\",\n \"No explanations.\",\n \"Do not call tools.\",\n].join(\"\\n\");\n\nconst MAX_TITLE_LENGTH = 80;\nconst MAX_TITLE_WORDS = 8;\nconst MAX_TRANSCRIPT_MESSAGES = 8;\nconst MAX_TITLE_GENERATION_ATTEMPTS = 3;\nconst FALLBACK_THREAD_TITLE = \"Untitled\";\n\ninterface GenerateThreadNameParams {\n runtime: CopilotIntelligenceRuntimeLike;\n request: Request;\n agentId: string;\n sourceInput: RunAgentInput;\n thread: ThreadSummary;\n userId: string;\n}\n\nexport async function generateThreadNameForNewThread({\n runtime,\n request,\n agentId,\n sourceInput,\n thread,\n userId,\n}: GenerateThreadNameParams): Promise<void> {\n if (!runtime.generateThreadNames || hasThreadName(thread.name)) {\n return;\n }\n\n const prompt = buildThreadTitlePrompt(sourceInput.messages);\n if (!prompt) {\n return;\n }\n\n let generatedTitle: string | null = null;\n\n for (let attempt = 1; attempt <= MAX_TITLE_GENERATION_ATTEMPTS; attempt++) {\n try {\n generatedTitle = await runTitleGenerationAttempt({\n runtime,\n request,\n agentId,\n threadId: thread.id,\n prompt,\n });\n\n if (generatedTitle) {\n break;\n }\n\n logger.warn(\n { agentId, attempt, threadId: thread.id },\n \"Thread name generation returned an empty or invalid title\",\n );\n } catch (error) {\n logger.warn(\n { err: error, agentId, attempt, threadId: thread.id },\n \"Thread name generation attempt failed\",\n );\n }\n }\n\n await runtime.intelligence.updateThread({\n threadId: thread.id,\n userId,\n agentId,\n updates: { name: generatedTitle ?? FALLBACK_THREAD_TITLE },\n });\n}\n\nasync function runTitleGenerationAttempt(params: {\n runtime: CopilotIntelligenceRuntimeLike;\n request: Request;\n agentId: string;\n threadId: string;\n prompt: string;\n}): Promise<string | null> {\n const { runtime, request, agentId, threadId, prompt } = params;\n const agent = await cloneAgentForRequest(runtime, agentId);\n if (agent instanceof Response) {\n logger.warn(\n { agentId, threadId },\n \"Skipping thread naming because the agent could not be cloned\",\n );\n return null;\n }\n\n configureAgentForRequest({\n runtime,\n request,\n agentId,\n agent,\n });\n\n const messages: Message[] = [\n {\n id: randomUUID(),\n role: \"system\",\n content: THREAD_NAME_SYSTEM_PROMPT,\n },\n {\n id: randomUUID(),\n role: \"user\",\n content: prompt,\n },\n ];\n\n agent.setMessages(messages);\n agent.setState({});\n agent.threadId = `thread-name:${threadId}:${randomUUID()}`;\n const { newMessages } = await agent.runAgent({\n messages,\n state: {},\n tools: [],\n context: [],\n forwardedProps: {},\n });\n\n const lastMessage = newMessages.at(-1);\n const titleContent = lastMessage\n ? stringifyMessageContent(lastMessage.content)\n : \"\";\n\n return normalizeGeneratedTitle(titleContent);\n}\n\nfunction buildThreadTitlePrompt(\n messages: Message[] | undefined,\n): string | null {\n const transcript = (messages ?? [])\n .filter((message) =>\n [\"user\", \"assistant\", \"system\", \"developer\"].includes(message.role),\n )\n .map((message) => {\n const content = stringifyMessageContent(message.content);\n if (!content) {\n return null;\n }\n\n return `${message.role}: ${content}`;\n })\n .filter((message): message is string => !!message)\n .slice(-MAX_TRANSCRIPT_MESSAGES);\n\n if (transcript.length === 0) {\n return null;\n }\n\n return [\n \"Generate a short title for this conversation.\",\n \"Conversation:\",\n transcript.join(\"\\n\"),\n ].join(\"\\n\\n\");\n}\n\nfunction stringifyMessageContent(content: Message[\"content\"]): string {\n if (typeof content === \"string\") {\n return content.trim();\n }\n\n if (content == null) {\n return \"\";\n }\n\n try {\n return JSON.stringify(content).trim();\n } catch {\n return \"\";\n }\n}\n\nfunction normalizeGeneratedTitle(rawTitle: string): string | null {\n let candidate = rawTitle.trim();\n if (!candidate) {\n return null;\n }\n\n candidate = candidate\n .replace(/^```(?:json)?\\s*/i, \"\")\n .replace(/\\s*```$/, \"\")\n .trim();\n\n try {\n const parsed = JSON.parse(candidate) as { title?: unknown };\n if (typeof parsed.title === \"string\") {\n candidate = parsed.title;\n }\n } catch {\n // Fall back to using the raw text.\n }\n\n candidate = candidate\n .replace(/^[\"'`]+|[\"'`]+$/g, \"\")\n .replace(/[*_#[\\]()!~>|]+/g, \"\")\n .replace(/[.!?,;:]+$/g, \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n\n if (!candidate) {\n return null;\n }\n\n if (candidate.length > MAX_TITLE_LENGTH) {\n candidate = candidate.slice(0, MAX_TITLE_LENGTH).trim();\n }\n\n if (candidate.split(/\\s+/).length > MAX_TITLE_WORDS) {\n return null;\n }\n\n return candidate;\n}\n\nfunction hasThreadName(name: string | null | undefined): boolean {\n return typeof name === \"string\" && name.trim().length > 0;\n}\n"],"mappings":"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"}
@@ -0,0 +1,143 @@
1
+ import { cloneAgentForRequest, configureAgentForRequest } from "../shared/agent-utils.mjs";
2
+ import { logger } from "@copilotkitnext/shared";
3
+ import { randomUUID } from "node:crypto";
4
+
5
+ //#region src/handlers/intelligence/thread-names.ts
6
+ const THREAD_NAME_SYSTEM_PROMPT = [
7
+ "You generate short, specific conversation titles.",
8
+ "Return JSON only in this exact shape: {\"title\":\"...\"}",
9
+ "The title must be 2 to 5 words.",
10
+ "Use sentence case.",
11
+ "No quotes.",
12
+ "No emoji.",
13
+ "No markdown characters or formatting.",
14
+ "Do not use *, _, #, `, [, ], (, ), !, ~, >, or |.",
15
+ "No trailing punctuation.",
16
+ "No explanations.",
17
+ "Do not call tools."
18
+ ].join("\n");
19
+ const MAX_TITLE_LENGTH = 80;
20
+ const MAX_TITLE_WORDS = 8;
21
+ const MAX_TRANSCRIPT_MESSAGES = 8;
22
+ const MAX_TITLE_GENERATION_ATTEMPTS = 3;
23
+ const FALLBACK_THREAD_TITLE = "Untitled";
24
+ async function generateThreadNameForNewThread({ runtime, request, agentId, sourceInput, thread, userId }) {
25
+ if (!runtime.generateThreadNames || hasThreadName(thread.name)) return;
26
+ const prompt = buildThreadTitlePrompt(sourceInput.messages);
27
+ if (!prompt) return;
28
+ let generatedTitle = null;
29
+ for (let attempt = 1; attempt <= MAX_TITLE_GENERATION_ATTEMPTS; attempt++) try {
30
+ generatedTitle = await runTitleGenerationAttempt({
31
+ runtime,
32
+ request,
33
+ agentId,
34
+ threadId: thread.id,
35
+ prompt
36
+ });
37
+ if (generatedTitle) break;
38
+ logger.warn({
39
+ agentId,
40
+ attempt,
41
+ threadId: thread.id
42
+ }, "Thread name generation returned an empty or invalid title");
43
+ } catch (error) {
44
+ logger.warn({
45
+ err: error,
46
+ agentId,
47
+ attempt,
48
+ threadId: thread.id
49
+ }, "Thread name generation attempt failed");
50
+ }
51
+ await runtime.intelligence.updateThread({
52
+ threadId: thread.id,
53
+ userId,
54
+ agentId,
55
+ updates: { name: generatedTitle ?? FALLBACK_THREAD_TITLE }
56
+ });
57
+ }
58
+ async function runTitleGenerationAttempt(params) {
59
+ const { runtime, request, agentId, threadId, prompt } = params;
60
+ const agent = await cloneAgentForRequest(runtime, agentId);
61
+ if (agent instanceof Response) {
62
+ logger.warn({
63
+ agentId,
64
+ threadId
65
+ }, "Skipping thread naming because the agent could not be cloned");
66
+ return null;
67
+ }
68
+ configureAgentForRequest({
69
+ runtime,
70
+ request,
71
+ agentId,
72
+ agent
73
+ });
74
+ const messages = [{
75
+ id: randomUUID(),
76
+ role: "system",
77
+ content: THREAD_NAME_SYSTEM_PROMPT
78
+ }, {
79
+ id: randomUUID(),
80
+ role: "user",
81
+ content: prompt
82
+ }];
83
+ agent.setMessages(messages);
84
+ agent.setState({});
85
+ agent.threadId = `thread-name:${threadId}:${randomUUID()}`;
86
+ const { newMessages } = await agent.runAgent({
87
+ messages,
88
+ state: {},
89
+ tools: [],
90
+ context: [],
91
+ forwardedProps: {}
92
+ });
93
+ const lastMessage = newMessages.at(-1);
94
+ return normalizeGeneratedTitle(lastMessage ? stringifyMessageContent(lastMessage.content) : "");
95
+ }
96
+ function buildThreadTitlePrompt(messages) {
97
+ const transcript = (messages ?? []).filter((message) => [
98
+ "user",
99
+ "assistant",
100
+ "system",
101
+ "developer"
102
+ ].includes(message.role)).map((message) => {
103
+ const content = stringifyMessageContent(message.content);
104
+ if (!content) return null;
105
+ return `${message.role}: ${content}`;
106
+ }).filter((message) => !!message).slice(-MAX_TRANSCRIPT_MESSAGES);
107
+ if (transcript.length === 0) return null;
108
+ return [
109
+ "Generate a short title for this conversation.",
110
+ "Conversation:",
111
+ transcript.join("\n")
112
+ ].join("\n\n");
113
+ }
114
+ function stringifyMessageContent(content) {
115
+ if (typeof content === "string") return content.trim();
116
+ if (content == null) return "";
117
+ try {
118
+ return JSON.stringify(content).trim();
119
+ } catch {
120
+ return "";
121
+ }
122
+ }
123
+ function normalizeGeneratedTitle(rawTitle) {
124
+ let candidate = rawTitle.trim();
125
+ if (!candidate) return null;
126
+ candidate = candidate.replace(/^```(?:json)?\s*/i, "").replace(/\s*```$/, "").trim();
127
+ try {
128
+ const parsed = JSON.parse(candidate);
129
+ if (typeof parsed.title === "string") candidate = parsed.title;
130
+ } catch {}
131
+ candidate = candidate.replace(/^["'`]+|["'`]+$/g, "").replace(/[*_#[\]()!~>|]+/g, "").replace(/[.!?,;:]+$/g, "").replace(/\s+/g, " ").trim();
132
+ if (!candidate) return null;
133
+ if (candidate.length > MAX_TITLE_LENGTH) candidate = candidate.slice(0, MAX_TITLE_LENGTH).trim();
134
+ if (candidate.split(/\s+/).length > MAX_TITLE_WORDS) return null;
135
+ return candidate;
136
+ }
137
+ function hasThreadName(name) {
138
+ return typeof name === "string" && name.trim().length > 0;
139
+ }
140
+
141
+ //#endregion
142
+ export { generateThreadNameForNewThread };
143
+ //# sourceMappingURL=thread-names.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thread-names.mjs","names":[],"sources":["../../../src/handlers/intelligence/thread-names.ts"],"sourcesContent":["import { AbstractAgent, Message, RunAgentInput } from \"@ag-ui/client\";\nimport { logger } from \"@copilotkitnext/shared\";\nimport { randomUUID } from \"node:crypto\";\nimport { CopilotIntelligenceRuntimeLike } from \"../../runtime\";\nimport {\n cloneAgentForRequest,\n configureAgentForRequest,\n} from \"../shared/agent-utils\";\nimport { ThreadSummary } from \"../../intelligence-platform\";\n\nconst THREAD_NAME_SYSTEM_PROMPT = [\n \"You generate short, specific conversation titles.\",\n 'Return JSON only in this exact shape: {\"title\":\"...\"}',\n \"The title must be 2 to 5 words.\",\n \"Use sentence case.\",\n \"No quotes.\",\n \"No emoji.\",\n \"No markdown characters or formatting.\",\n \"Do not use *, _, #, `, [, ], (, ), !, ~, >, or |.\",\n \"No trailing punctuation.\",\n \"No explanations.\",\n \"Do not call tools.\",\n].join(\"\\n\");\n\nconst MAX_TITLE_LENGTH = 80;\nconst MAX_TITLE_WORDS = 8;\nconst MAX_TRANSCRIPT_MESSAGES = 8;\nconst MAX_TITLE_GENERATION_ATTEMPTS = 3;\nconst FALLBACK_THREAD_TITLE = \"Untitled\";\n\ninterface GenerateThreadNameParams {\n runtime: CopilotIntelligenceRuntimeLike;\n request: Request;\n agentId: string;\n sourceInput: RunAgentInput;\n thread: ThreadSummary;\n userId: string;\n}\n\nexport async function generateThreadNameForNewThread({\n runtime,\n request,\n agentId,\n sourceInput,\n thread,\n userId,\n}: GenerateThreadNameParams): Promise<void> {\n if (!runtime.generateThreadNames || hasThreadName(thread.name)) {\n return;\n }\n\n const prompt = buildThreadTitlePrompt(sourceInput.messages);\n if (!prompt) {\n return;\n }\n\n let generatedTitle: string | null = null;\n\n for (let attempt = 1; attempt <= MAX_TITLE_GENERATION_ATTEMPTS; attempt++) {\n try {\n generatedTitle = await runTitleGenerationAttempt({\n runtime,\n request,\n agentId,\n threadId: thread.id,\n prompt,\n });\n\n if (generatedTitle) {\n break;\n }\n\n logger.warn(\n { agentId, attempt, threadId: thread.id },\n \"Thread name generation returned an empty or invalid title\",\n );\n } catch (error) {\n logger.warn(\n { err: error, agentId, attempt, threadId: thread.id },\n \"Thread name generation attempt failed\",\n );\n }\n }\n\n await runtime.intelligence.updateThread({\n threadId: thread.id,\n userId,\n agentId,\n updates: { name: generatedTitle ?? FALLBACK_THREAD_TITLE },\n });\n}\n\nasync function runTitleGenerationAttempt(params: {\n runtime: CopilotIntelligenceRuntimeLike;\n request: Request;\n agentId: string;\n threadId: string;\n prompt: string;\n}): Promise<string | null> {\n const { runtime, request, agentId, threadId, prompt } = params;\n const agent = await cloneAgentForRequest(runtime, agentId);\n if (agent instanceof Response) {\n logger.warn(\n { agentId, threadId },\n \"Skipping thread naming because the agent could not be cloned\",\n );\n return null;\n }\n\n configureAgentForRequest({\n runtime,\n request,\n agentId,\n agent,\n });\n\n const messages: Message[] = [\n {\n id: randomUUID(),\n role: \"system\",\n content: THREAD_NAME_SYSTEM_PROMPT,\n },\n {\n id: randomUUID(),\n role: \"user\",\n content: prompt,\n },\n ];\n\n agent.setMessages(messages);\n agent.setState({});\n agent.threadId = `thread-name:${threadId}:${randomUUID()}`;\n const { newMessages } = await agent.runAgent({\n messages,\n state: {},\n tools: [],\n context: [],\n forwardedProps: {},\n });\n\n const lastMessage = newMessages.at(-1);\n const titleContent = lastMessage\n ? stringifyMessageContent(lastMessage.content)\n : \"\";\n\n return normalizeGeneratedTitle(titleContent);\n}\n\nfunction buildThreadTitlePrompt(\n messages: Message[] | undefined,\n): string | null {\n const transcript = (messages ?? [])\n .filter((message) =>\n [\"user\", \"assistant\", \"system\", \"developer\"].includes(message.role),\n )\n .map((message) => {\n const content = stringifyMessageContent(message.content);\n if (!content) {\n return null;\n }\n\n return `${message.role}: ${content}`;\n })\n .filter((message): message is string => !!message)\n .slice(-MAX_TRANSCRIPT_MESSAGES);\n\n if (transcript.length === 0) {\n return null;\n }\n\n return [\n \"Generate a short title for this conversation.\",\n \"Conversation:\",\n transcript.join(\"\\n\"),\n ].join(\"\\n\\n\");\n}\n\nfunction stringifyMessageContent(content: Message[\"content\"]): string {\n if (typeof content === \"string\") {\n return content.trim();\n }\n\n if (content == null) {\n return \"\";\n }\n\n try {\n return JSON.stringify(content).trim();\n } catch {\n return \"\";\n }\n}\n\nfunction normalizeGeneratedTitle(rawTitle: string): string | null {\n let candidate = rawTitle.trim();\n if (!candidate) {\n return null;\n }\n\n candidate = candidate\n .replace(/^```(?:json)?\\s*/i, \"\")\n .replace(/\\s*```$/, \"\")\n .trim();\n\n try {\n const parsed = JSON.parse(candidate) as { title?: unknown };\n if (typeof parsed.title === \"string\") {\n candidate = parsed.title;\n }\n } catch {\n // Fall back to using the raw text.\n }\n\n candidate = candidate\n .replace(/^[\"'`]+|[\"'`]+$/g, \"\")\n .replace(/[*_#[\\]()!~>|]+/g, \"\")\n .replace(/[.!?,;:]+$/g, \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n\n if (!candidate) {\n return null;\n }\n\n if (candidate.length > MAX_TITLE_LENGTH) {\n candidate = candidate.slice(0, MAX_TITLE_LENGTH).trim();\n }\n\n if (candidate.split(/\\s+/).length > MAX_TITLE_WORDS) {\n return null;\n }\n\n return candidate;\n}\n\nfunction hasThreadName(name: string | null | undefined): boolean {\n return typeof name === \"string\" && name.trim().length > 0;\n}\n"],"mappings":"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"}
@@ -0,0 +1,133 @@
1
+ const require_runtime = require('../../_virtual/_rolldown/runtime.cjs');
2
+ const require_runtime$1 = require('../../runtime.cjs');
3
+ const require_intelligence_utils = require('../shared/intelligence-utils.cjs');
4
+ const require_json_response = require('../shared/json-response.cjs');
5
+ let _copilotkitnext_shared = require("@copilotkitnext/shared");
6
+
7
+ //#region src/handlers/intelligence/threads.ts
8
+ async function parseJsonBody(request) {
9
+ try {
10
+ return await request.json();
11
+ } catch (error) {
12
+ _copilotkitnext_shared.logger.error({ err: error }, "Malformed JSON in request body");
13
+ return require_json_response.errorResponse("Invalid request body", 400);
14
+ }
15
+ }
16
+ function requireIntelligenceRuntime(runtime) {
17
+ if (!require_runtime$1.isIntelligenceRuntime(runtime)) return require_json_response.errorResponse("Missing CopilotKitIntelligence configuration. Thread operations require a CopilotKitIntelligence instance to be provided in CopilotRuntime options.", 422);
18
+ return runtime;
19
+ }
20
+ async function handleListThreads({ runtime, request }) {
21
+ const intelligenceRuntime = requireIntelligenceRuntime(runtime);
22
+ if (intelligenceRuntime instanceof Response) return intelligenceRuntime;
23
+ try {
24
+ const url = new URL(request.url);
25
+ const userId = url.searchParams.get("userId");
26
+ const agentId = url.searchParams.get("agentId");
27
+ if (!require_intelligence_utils.isValidIdentifier(userId) || !require_intelligence_utils.isValidIdentifier(agentId)) return require_json_response.errorResponse("Valid userId and agentId query params are required", 400);
28
+ const data = await intelligenceRuntime.intelligence.listThreads({
29
+ userId,
30
+ agentId
31
+ });
32
+ return Response.json(data);
33
+ } catch (error) {
34
+ _copilotkitnext_shared.logger.error({ err: error }, "Error listing threads");
35
+ return require_json_response.errorResponse("Failed to list threads", 500);
36
+ }
37
+ }
38
+ async function handleUpdateThread({ runtime, request, threadId }) {
39
+ const intelligenceRuntime = requireIntelligenceRuntime(runtime);
40
+ if (intelligenceRuntime instanceof Response) return intelligenceRuntime;
41
+ try {
42
+ const body = await parseJsonBody(request);
43
+ if (body instanceof Response) return body;
44
+ const { userId, agentId, ...updates } = body;
45
+ if (!require_intelligence_utils.isValidIdentifier(userId) || !require_intelligence_utils.isValidIdentifier(agentId)) return require_json_response.errorResponse("Valid userId and agentId are required", 400);
46
+ const thread = await intelligenceRuntime.intelligence.updateThread({
47
+ threadId,
48
+ userId,
49
+ agentId,
50
+ updates
51
+ });
52
+ return Response.json(thread);
53
+ } catch (error) {
54
+ _copilotkitnext_shared.logger.error({
55
+ err: error,
56
+ threadId
57
+ }, "Error updating thread");
58
+ return require_json_response.errorResponse("Failed to update thread", 500);
59
+ }
60
+ }
61
+ async function handleSubscribeToThreads({ runtime, request }) {
62
+ const intelligenceRuntime = requireIntelligenceRuntime(runtime);
63
+ if (intelligenceRuntime instanceof Response) return intelligenceRuntime;
64
+ try {
65
+ const body = await parseJsonBody(request);
66
+ if (body instanceof Response) return body;
67
+ const userId = body.userId;
68
+ if (typeof userId !== "string" || userId.length === 0) return require_json_response.errorResponse("userId is required", 400);
69
+ const credentials = await intelligenceRuntime.intelligence.ɵsubscribeToThreads({ userId });
70
+ return Response.json({ joinToken: credentials.joinToken });
71
+ } catch (error) {
72
+ _copilotkitnext_shared.logger.error({ err: error }, "Error subscribing to threads");
73
+ return require_json_response.errorResponse("Failed to subscribe to threads", 500);
74
+ }
75
+ }
76
+ async function handleArchiveThread({ runtime, request, threadId }) {
77
+ const intelligenceRuntime = requireIntelligenceRuntime(runtime);
78
+ if (intelligenceRuntime instanceof Response) return intelligenceRuntime;
79
+ try {
80
+ const body = await parseJsonBody(request);
81
+ if (body instanceof Response) return body;
82
+ const { userId, agentId } = body;
83
+ if (!require_intelligence_utils.isValidIdentifier(userId) || !require_intelligence_utils.isValidIdentifier(agentId)) return require_json_response.errorResponse("Valid userId and agentId are required", 400);
84
+ await intelligenceRuntime.intelligence.archiveThread({
85
+ threadId,
86
+ userId,
87
+ agentId
88
+ });
89
+ return Response.json({
90
+ threadId,
91
+ archived: true
92
+ });
93
+ } catch (error) {
94
+ _copilotkitnext_shared.logger.error({
95
+ err: error,
96
+ threadId
97
+ }, "Error archiving thread");
98
+ return require_json_response.errorResponse("Failed to archive thread", 500);
99
+ }
100
+ }
101
+ async function handleDeleteThread({ runtime, request, threadId }) {
102
+ const intelligenceRuntime = requireIntelligenceRuntime(runtime);
103
+ if (intelligenceRuntime instanceof Response) return intelligenceRuntime;
104
+ try {
105
+ const body = await parseJsonBody(request);
106
+ if (body instanceof Response) return body;
107
+ const { userId, agentId } = body;
108
+ if (!require_intelligence_utils.isValidIdentifier(userId) || !require_intelligence_utils.isValidIdentifier(agentId)) return require_json_response.errorResponse("Valid userId and agentId are required", 400);
109
+ await intelligenceRuntime.intelligence.deleteThread({
110
+ threadId,
111
+ userId,
112
+ agentId
113
+ });
114
+ return Response.json({
115
+ threadId,
116
+ deleted: true
117
+ });
118
+ } catch (error) {
119
+ _copilotkitnext_shared.logger.error({
120
+ err: error,
121
+ threadId
122
+ }, "Error deleting thread");
123
+ return require_json_response.errorResponse("Failed to delete thread", 500);
124
+ }
125
+ }
126
+
127
+ //#endregion
128
+ exports.handleArchiveThread = handleArchiveThread;
129
+ exports.handleDeleteThread = handleDeleteThread;
130
+ exports.handleListThreads = handleListThreads;
131
+ exports.handleSubscribeToThreads = handleSubscribeToThreads;
132
+ exports.handleUpdateThread = handleUpdateThread;
133
+ //# sourceMappingURL=threads.cjs.map