@copilotkit/runtime 1.73.3 → 1.74.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.
- package/README.md +28 -0
- package/dist/agent/learned-skills.cjs.map +1 -1
- package/dist/agent/learned-skills.d.cts +1 -1
- package/dist/agent/learned-skills.d.mts +1 -1
- package/dist/agent/learned-skills.mjs.map +1 -1
- package/dist/internal/learned-skills.d.cts +2 -2
- package/dist/internal/learned-skills.d.mts +2 -2
- package/dist/package.cjs +1 -1
- package/dist/package.mjs +1 -1
- package/dist/v2/index.d.cts +2 -2
- package/dist/v2/index.d.mts +2 -2
- package/dist/v2/runtime/handlers/intelligence/memories.cjs +4 -1
- package/dist/v2/runtime/handlers/intelligence/memories.cjs.map +1 -1
- package/dist/v2/runtime/handlers/intelligence/memories.mjs +5 -2
- package/dist/v2/runtime/handlers/intelligence/memories.mjs.map +1 -1
- package/dist/v2/runtime/handlers/intelligence/thread-names.cjs +16 -2
- package/dist/v2/runtime/handlers/intelligence/thread-names.cjs.map +1 -1
- package/dist/v2/runtime/handlers/intelligence/thread-names.mjs +16 -2
- package/dist/v2/runtime/handlers/intelligence/thread-names.mjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/agent-utils.cjs +17 -4
- package/dist/v2/runtime/handlers/shared/agent-utils.cjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/agent-utils.mjs +18 -5
- package/dist/v2/runtime/handlers/shared/agent-utils.mjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/memory-policy.cjs +43 -5
- package/dist/v2/runtime/handlers/shared/memory-policy.cjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/memory-policy.mjs +43 -6
- package/dist/v2/runtime/handlers/shared/memory-policy.mjs.map +1 -1
- package/dist/v2/runtime/index.d.cts +1 -1
- package/dist/v2/runtime/index.d.cts.map +1 -1
- package/dist/v2/runtime/index.d.mts +1 -1
- package/dist/v2/runtime/index.d.mts.map +1 -1
- package/dist/v2/runtime/intelligence-platform/client.cjs +80 -0
- package/dist/v2/runtime/intelligence-platform/client.cjs.map +1 -1
- package/dist/v2/runtime/intelligence-platform/client.d.cts +3 -1
- package/dist/v2/runtime/intelligence-platform/client.d.cts.map +1 -1
- package/dist/v2/runtime/intelligence-platform/client.d.mts +3 -1
- package/dist/v2/runtime/intelligence-platform/client.d.mts.map +1 -1
- package/dist/v2/runtime/intelligence-platform/client.mjs +81 -1
- package/dist/v2/runtime/intelligence-platform/client.mjs.map +1 -1
- package/dist/v2/runtime/intelligence-platform/index.d.cts +1 -1
- package/dist/v2/runtime/intelligence-platform/index.d.mts +1 -1
- package/dist/v2/runtime/intelligence-platform/learned-skills.cjs +53 -0
- package/dist/v2/runtime/intelligence-platform/learned-skills.cjs.map +1 -1
- package/dist/v2/runtime/intelligence-platform/learned-skills.d.cts +11 -1
- package/dist/v2/runtime/intelligence-platform/learned-skills.d.cts.map +1 -1
- package/dist/v2/runtime/intelligence-platform/learned-skills.d.mts +11 -1
- package/dist/v2/runtime/intelligence-platform/learned-skills.d.mts.map +1 -1
- package/dist/v2/runtime/intelligence-platform/learned-skills.mjs +53 -1
- package/dist/v2/runtime/intelligence-platform/learned-skills.mjs.map +1 -1
- package/dist/v2/runtime/intelligence-platform/skill-registry/config.cjs +24 -6
- package/dist/v2/runtime/intelligence-platform/skill-registry/config.cjs.map +1 -1
- package/dist/v2/runtime/intelligence-platform/skill-registry/config.d.cts +28 -7
- package/dist/v2/runtime/intelligence-platform/skill-registry/config.d.cts.map +1 -1
- package/dist/v2/runtime/intelligence-platform/skill-registry/config.d.mts +28 -7
- package/dist/v2/runtime/intelligence-platform/skill-registry/config.d.mts.map +1 -1
- package/dist/v2/runtime/intelligence-platform/skill-registry/config.mjs +24 -6
- package/dist/v2/runtime/intelligence-platform/skill-registry/config.mjs.map +1 -1
- package/dist/v2/runtime/intelligence-platform/skill-registry/index.d.cts +1 -1
- package/dist/v2/runtime/intelligence-platform/skill-registry/index.d.mts +1 -1
- package/dist/v2/runtime/intelligence-platform/skill-registry/registry.cjs +120 -4
- package/dist/v2/runtime/intelligence-platform/skill-registry/registry.cjs.map +1 -1
- package/dist/v2/runtime/intelligence-platform/skill-registry/registry.d.cts +8 -2
- package/dist/v2/runtime/intelligence-platform/skill-registry/registry.d.cts.map +1 -1
- package/dist/v2/runtime/intelligence-platform/skill-registry/registry.d.mts +8 -2
- package/dist/v2/runtime/intelligence-platform/skill-registry/registry.d.mts.map +1 -1
- package/dist/v2/runtime/intelligence-platform/skill-registry/registry.mjs +119 -4
- package/dist/v2/runtime/intelligence-platform/skill-registry/registry.mjs.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -164,3 +164,31 @@ the existing 60-second durability window.
|
|
|
164
164
|
|
|
165
165
|
No Intelligence upgrade is required. The runtime uses the existing terminal
|
|
166
166
|
events and supports both single-event and batched gateway acknowledgments.
|
|
167
|
+
|
|
168
|
+
## BuiltInAgent skill delivery from multiple containers
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
import { BuiltInAgent } from "@copilotkit/runtime/v2";
|
|
172
|
+
|
|
173
|
+
const agent = new BuiltInAgent({
|
|
174
|
+
model: "openai/gpt-4o",
|
|
175
|
+
learnedSkills: {
|
|
176
|
+
containers: [
|
|
177
|
+
{ id: "support", revision: "revision-123" },
|
|
178
|
+
{ id: "company-wide" },
|
|
179
|
+
],
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Set `CPK_INTELLIGENCE_API_KEY` or supply an Intelligence client in `learnedSkills.client`.
|
|
185
|
+
The existing `containerId` and top-level `revision` interface remains supported.
|
|
186
|
+
The SDK rejects a combination of the old fields and `containers`.
|
|
187
|
+
The new interface ignores legacy container and revision environment variables.
|
|
188
|
+
Each container keeps its own revision and cache. A cold failure or confirmed denial blocks the whole invocation.
|
|
189
|
+
Skill names include the container prefix, such as `support/refund-policy`, when you use `containers`.
|
|
190
|
+
See [Skill delivery](https://docs.copilotkit.ai/intelligence/learned-skills) for all adapters, environment defaults, and factory-mode wiring.
|
|
191
|
+
|
|
192
|
+
Explicit `containers` accepts 1–50 unique container IDs and sends one batch request for all sources that need a refresh. This also applies to a list with one entry.
|
|
193
|
+
The server must support `POST /api/v1/learning/skills/batch` before you use this configuration. The SDK does not fall back to separate requests.
|
|
194
|
+
Legacy `containerId` configuration keeps its existing single-container request. Both interfaces use the same authentication configuration.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"learned-skills.cjs","names":["loadSkill","readSkillFile","formatSkillCatalog"],"sources":["../../src/agent/learned-skills.ts"],"sourcesContent":["import { jsonSchema, tool } from \"ai\";\nimport type { ToolSet } from \"ai\";\nimport type { SkillRegistry } from \"../v2/runtime/intelligence-platform/skill-registry\";\nimport {\n formatSkillCatalog,\n loadSkill,\n readSkillFile,\n} from \"../v2/runtime/intelligence-platform/skill-registry\";\nimport type { SkillRegistryOptions } from \"../v2/runtime/intelligence-platform/skill-registry\";\n\n/** Opt in to learned skills from one Intelligence learning
|
|
1
|
+
{"version":3,"file":"learned-skills.cjs","names":["loadSkill","readSkillFile","formatSkillCatalog"],"sources":["../../src/agent/learned-skills.ts"],"sourcesContent":["import { jsonSchema, tool } from \"ai\";\nimport type { ToolSet } from \"ai\";\nimport type { SkillRegistry } from \"../v2/runtime/intelligence-platform/skill-registry\";\nimport {\n formatSkillCatalog,\n loadSkill,\n readSkillFile,\n} from \"../v2/runtime/intelligence-platform/skill-registry\";\nimport type { SkillRegistryOptions } from \"../v2/runtime/intelligence-platform/skill-registry\";\n\n/** Opt in to learned skills from one or more Intelligence learning containers. */\nexport type BuiltInAgentLearnedSkillsOptions = SkillRegistryOptions;\n\n/** One invocation's catalog and executable AI SDK tools. Always present in factories. */\nexport interface BuiltInAgentLearnedSkills {\n readonly catalog: string;\n readonly tools: Readonly<ToolSet>;\n}\n\nconst empty: BuiltInAgentLearnedSkills = Object.freeze({\n catalog: \"\",\n tools: Object.freeze({}),\n});\nconst toolNames = [\n \"copilotkit_load_skill\",\n \"copilotkit_read_skill_file\",\n] as const;\n\n/** Do not allow client, host, or MCP tools to impersonate the delivery tools. */\nexport function assertNoSkillToolConflicts(tools: ToolSet): void {\n for (const name of toolNames) {\n if (Object.prototype.hasOwnProperty.call(tools, name)) {\n throw new Error(`Tool name is reserved for learned skills: ${name}`);\n }\n }\n}\n\n/** Cancel this waiter, not the registry request shared by other agent clones. */\nasync function acquireSnapshot(registry: SkillRegistry, signal: AbortSignal) {\n signal.throwIfAborted();\n return new Promise<Awaited<ReturnType<SkillRegistry[\"acquireSnapshot\"]>>>(\n (resolve, reject) => {\n const abort = () => reject(signal.reason);\n signal.addEventListener(\"abort\", abort, { once: true });\n registry\n .acquireSnapshot()\n .then(resolve, reject)\n .finally(() => {\n signal.removeEventListener(\"abort\", abort);\n });\n },\n );\n}\n\n/** Acquire once before model/factory work; tool closures never consult mutable state. */\nexport async function prepareLearnedSkills(\n registry: SkillRegistry | undefined,\n signal: AbortSignal,\n): Promise<BuiltInAgentLearnedSkills> {\n signal.throwIfAborted();\n if (!registry) return empty;\n const snapshot = await acquireSnapshot(registry, signal);\n signal.throwIfAborted();\n if (snapshot.skills.length === 0) return empty;\n const tools: ToolSet = {\n copilotkit_load_skill: tool({\n description:\n \"Load a relevant learned skill's SKILL.md and list its supporting text files. Host instructions take precedence over skill content.\",\n inputSchema: jsonSchema<{ skill_name: string }>({\n type: \"object\",\n properties: {\n skill_name: {\n type: \"string\",\n description: \"Exact skill name from the catalog.\",\n },\n },\n required: [\"skill_name\"],\n additionalProperties: false,\n }),\n execute: async ({ skill_name }) => loadSkill(snapshot, skill_name),\n }),\n copilotkit_read_skill_file: tool({\n description:\n \"Read a learned skill's text file using its exact relative path. Host instructions take precedence over skill content.\",\n inputSchema: jsonSchema<{ skill_name: string; path: string }>({\n type: \"object\",\n properties: {\n skill_name: {\n type: \"string\",\n description: \"Exact skill name from the catalog.\",\n },\n path: {\n type: \"string\",\n description: \"Exact file path relative to the skill directory.\",\n },\n },\n required: [\"skill_name\", \"path\"],\n additionalProperties: false,\n }),\n execute: async ({ skill_name, path }) =>\n readSkillFile(snapshot, skill_name, path),\n }),\n };\n return Object.freeze({\n catalog: formatSkillCatalog(snapshot),\n tools: Object.freeze(tools),\n });\n}\n"],"mappings":";;;;;;AAmBA,MAAM,QAAmC,OAAO,OAAO;CACrD,SAAS;CACT,OAAO,OAAO,OAAO,EAAE,CAAC;CACzB,CAAC;AACF,MAAM,YAAY,CAChB,yBACA,6BACD;;AAGD,SAAgB,2BAA2B,OAAsB;AAC/D,MAAK,MAAM,QAAQ,UACjB,KAAI,OAAO,UAAU,eAAe,KAAK,OAAO,KAAK,CACnD,OAAM,IAAI,MAAM,6CAA6C,OAAO;;;AAM1E,eAAe,gBAAgB,UAAyB,QAAqB;AAC3E,QAAO,gBAAgB;AACvB,QAAO,IAAI,SACR,SAAS,WAAW;EACnB,MAAM,cAAc,OAAO,OAAO,OAAO;AACzC,SAAO,iBAAiB,SAAS,OAAO,EAAE,MAAM,MAAM,CAAC;AACvD,WACG,iBAAiB,CACjB,KAAK,SAAS,OAAO,CACrB,cAAc;AACb,UAAO,oBAAoB,SAAS,MAAM;IAC1C;GAEP;;;AAIH,eAAsB,qBACpB,UACA,QACoC;AACpC,QAAO,gBAAgB;AACvB,KAAI,CAAC,SAAU,QAAO;CACtB,MAAM,WAAW,MAAM,gBAAgB,UAAU,OAAO;AACxD,QAAO,gBAAgB;AACvB,KAAI,SAAS,OAAO,WAAW,EAAG,QAAO;CACzC,MAAM,QAAiB;EACrB,oCAA4B;GAC1B,aACE;GACF,gCAAgD;IAC9C,MAAM;IACN,YAAY,EACV,YAAY;KACV,MAAM;KACN,aAAa;KACd,EACF;IACD,UAAU,CAAC,aAAa;IACxB,sBAAsB;IACvB,CAAC;GACF,SAAS,OAAO,EAAE,iBAAiBA,gCAAU,UAAU,WAAW;GACnE,CAAC;EACF,yCAAiC;GAC/B,aACE;GACF,gCAA8D;IAC5D,MAAM;IACN,YAAY;KACV,YAAY;MACV,MAAM;MACN,aAAa;MACd;KACD,MAAM;MACJ,MAAM;MACN,aAAa;MACd;KACF;IACD,UAAU,CAAC,cAAc,OAAO;IAChC,sBAAsB;IACvB,CAAC;GACF,SAAS,OAAO,EAAE,YAAY,WAC5BC,oCAAc,UAAU,YAAY,KAAK;GAC5C,CAAC;EACH;AACD,QAAO,OAAO,OAAO;EACnB,SAASC,yCAAmB,SAAS;EACrC,OAAO,OAAO,OAAO,MAAM;EAC5B,CAAC"}
|
|
@@ -4,7 +4,7 @@ import "../v2/runtime/intelligence-platform/skill-registry/index.cjs";
|
|
|
4
4
|
import { ToolSet } from "ai";
|
|
5
5
|
|
|
6
6
|
//#region src/agent/learned-skills.d.ts
|
|
7
|
-
/** Opt in to learned skills from one Intelligence learning
|
|
7
|
+
/** Opt in to learned skills from one or more Intelligence learning containers. */
|
|
8
8
|
type BuiltInAgentLearnedSkillsOptions = SkillRegistryOptions;
|
|
9
9
|
/** One invocation's catalog and executable AI SDK tools. Always present in factories. */
|
|
10
10
|
interface BuiltInAgentLearnedSkills {
|
|
@@ -4,7 +4,7 @@ import "../v2/runtime/intelligence-platform/skill-registry/index.mjs";
|
|
|
4
4
|
import { ToolSet } from "ai";
|
|
5
5
|
|
|
6
6
|
//#region src/agent/learned-skills.d.ts
|
|
7
|
-
/** Opt in to learned skills from one Intelligence learning
|
|
7
|
+
/** Opt in to learned skills from one or more Intelligence learning containers. */
|
|
8
8
|
type BuiltInAgentLearnedSkillsOptions = SkillRegistryOptions;
|
|
9
9
|
/** One invocation's catalog and executable AI SDK tools. Always present in factories. */
|
|
10
10
|
interface BuiltInAgentLearnedSkills {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"learned-skills.mjs","names":[],"sources":["../../src/agent/learned-skills.ts"],"sourcesContent":["import { jsonSchema, tool } from \"ai\";\nimport type { ToolSet } from \"ai\";\nimport type { SkillRegistry } from \"../v2/runtime/intelligence-platform/skill-registry\";\nimport {\n formatSkillCatalog,\n loadSkill,\n readSkillFile,\n} from \"../v2/runtime/intelligence-platform/skill-registry\";\nimport type { SkillRegistryOptions } from \"../v2/runtime/intelligence-platform/skill-registry\";\n\n/** Opt in to learned skills from one Intelligence learning
|
|
1
|
+
{"version":3,"file":"learned-skills.mjs","names":[],"sources":["../../src/agent/learned-skills.ts"],"sourcesContent":["import { jsonSchema, tool } from \"ai\";\nimport type { ToolSet } from \"ai\";\nimport type { SkillRegistry } from \"../v2/runtime/intelligence-platform/skill-registry\";\nimport {\n formatSkillCatalog,\n loadSkill,\n readSkillFile,\n} from \"../v2/runtime/intelligence-platform/skill-registry\";\nimport type { SkillRegistryOptions } from \"../v2/runtime/intelligence-platform/skill-registry\";\n\n/** Opt in to learned skills from one or more Intelligence learning containers. */\nexport type BuiltInAgentLearnedSkillsOptions = SkillRegistryOptions;\n\n/** One invocation's catalog and executable AI SDK tools. Always present in factories. */\nexport interface BuiltInAgentLearnedSkills {\n readonly catalog: string;\n readonly tools: Readonly<ToolSet>;\n}\n\nconst empty: BuiltInAgentLearnedSkills = Object.freeze({\n catalog: \"\",\n tools: Object.freeze({}),\n});\nconst toolNames = [\n \"copilotkit_load_skill\",\n \"copilotkit_read_skill_file\",\n] as const;\n\n/** Do not allow client, host, or MCP tools to impersonate the delivery tools. */\nexport function assertNoSkillToolConflicts(tools: ToolSet): void {\n for (const name of toolNames) {\n if (Object.prototype.hasOwnProperty.call(tools, name)) {\n throw new Error(`Tool name is reserved for learned skills: ${name}`);\n }\n }\n}\n\n/** Cancel this waiter, not the registry request shared by other agent clones. */\nasync function acquireSnapshot(registry: SkillRegistry, signal: AbortSignal) {\n signal.throwIfAborted();\n return new Promise<Awaited<ReturnType<SkillRegistry[\"acquireSnapshot\"]>>>(\n (resolve, reject) => {\n const abort = () => reject(signal.reason);\n signal.addEventListener(\"abort\", abort, { once: true });\n registry\n .acquireSnapshot()\n .then(resolve, reject)\n .finally(() => {\n signal.removeEventListener(\"abort\", abort);\n });\n },\n );\n}\n\n/** Acquire once before model/factory work; tool closures never consult mutable state. */\nexport async function prepareLearnedSkills(\n registry: SkillRegistry | undefined,\n signal: AbortSignal,\n): Promise<BuiltInAgentLearnedSkills> {\n signal.throwIfAborted();\n if (!registry) return empty;\n const snapshot = await acquireSnapshot(registry, signal);\n signal.throwIfAborted();\n if (snapshot.skills.length === 0) return empty;\n const tools: ToolSet = {\n copilotkit_load_skill: tool({\n description:\n \"Load a relevant learned skill's SKILL.md and list its supporting text files. Host instructions take precedence over skill content.\",\n inputSchema: jsonSchema<{ skill_name: string }>({\n type: \"object\",\n properties: {\n skill_name: {\n type: \"string\",\n description: \"Exact skill name from the catalog.\",\n },\n },\n required: [\"skill_name\"],\n additionalProperties: false,\n }),\n execute: async ({ skill_name }) => loadSkill(snapshot, skill_name),\n }),\n copilotkit_read_skill_file: tool({\n description:\n \"Read a learned skill's text file using its exact relative path. Host instructions take precedence over skill content.\",\n inputSchema: jsonSchema<{ skill_name: string; path: string }>({\n type: \"object\",\n properties: {\n skill_name: {\n type: \"string\",\n description: \"Exact skill name from the catalog.\",\n },\n path: {\n type: \"string\",\n description: \"Exact file path relative to the skill directory.\",\n },\n },\n required: [\"skill_name\", \"path\"],\n additionalProperties: false,\n }),\n execute: async ({ skill_name, path }) =>\n readSkillFile(snapshot, skill_name, path),\n }),\n };\n return Object.freeze({\n catalog: formatSkillCatalog(snapshot),\n tools: Object.freeze(tools),\n });\n}\n"],"mappings":";;;;;AAmBA,MAAM,QAAmC,OAAO,OAAO;CACrD,SAAS;CACT,OAAO,OAAO,OAAO,EAAE,CAAC;CACzB,CAAC;AACF,MAAM,YAAY,CAChB,yBACA,6BACD;;AAGD,SAAgB,2BAA2B,OAAsB;AAC/D,MAAK,MAAM,QAAQ,UACjB,KAAI,OAAO,UAAU,eAAe,KAAK,OAAO,KAAK,CACnD,OAAM,IAAI,MAAM,6CAA6C,OAAO;;;AAM1E,eAAe,gBAAgB,UAAyB,QAAqB;AAC3E,QAAO,gBAAgB;AACvB,QAAO,IAAI,SACR,SAAS,WAAW;EACnB,MAAM,cAAc,OAAO,OAAO,OAAO;AACzC,SAAO,iBAAiB,SAAS,OAAO,EAAE,MAAM,MAAM,CAAC;AACvD,WACG,iBAAiB,CACjB,KAAK,SAAS,OAAO,CACrB,cAAc;AACb,UAAO,oBAAoB,SAAS,MAAM;IAC1C;GAEP;;;AAIH,eAAsB,qBACpB,UACA,QACoC;AACpC,QAAO,gBAAgB;AACvB,KAAI,CAAC,SAAU,QAAO;CACtB,MAAM,WAAW,MAAM,gBAAgB,UAAU,OAAO;AACxD,QAAO,gBAAgB;AACvB,KAAI,SAAS,OAAO,WAAW,EAAG,QAAO;CACzC,MAAM,QAAiB;EACrB,uBAAuB,KAAK;GAC1B,aACE;GACF,aAAa,WAAmC;IAC9C,MAAM;IACN,YAAY,EACV,YAAY;KACV,MAAM;KACN,aAAa;KACd,EACF;IACD,UAAU,CAAC,aAAa;IACxB,sBAAsB;IACvB,CAAC;GACF,SAAS,OAAO,EAAE,iBAAiB,UAAU,UAAU,WAAW;GACnE,CAAC;EACF,4BAA4B,KAAK;GAC/B,aACE;GACF,aAAa,WAAiD;IAC5D,MAAM;IACN,YAAY;KACV,YAAY;MACV,MAAM;MACN,aAAa;MACd;KACD,MAAM;MACJ,MAAM;MACN,aAAa;MACd;KACF;IACD,UAAU,CAAC,cAAc,OAAO;IAChC,sBAAsB;IACvB,CAAC;GACF,SAAS,OAAO,EAAE,YAAY,WAC5B,cAAc,UAAU,YAAY,KAAK;GAC5C,CAAC;EACH;AACD,QAAO,OAAO,OAAO;EACnB,SAAS,mBAAmB,SAAS;EACrC,OAAO,OAAO,OAAO,MAAM;EAC5B,CAAC"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
|
|
2
2
|
import { MAX_ARCHIVE_ENTRIES, MAX_SNAPSHOT_BYTES, readArchive, safeRelativePath } from "../v2/runtime/intelligence-platform/skill-registry/archive.cjs";
|
|
3
3
|
import { LearnedSkillsError, LearnedSkillsErrorCode } from "../v2/runtime/intelligence-platform/learned-skills.cjs";
|
|
4
|
-
import { RegistryConfig, SkillRegistryOptions, resolveRegistryConfig } from "../v2/runtime/intelligence-platform/skill-registry/config.cjs";
|
|
4
|
+
import { RegistryConfig, SingleContainerConfig, SkillRegistryCommonOptions, SkillRegistryContainer, SkillRegistryOptions, resolveRegistryConfig } from "../v2/runtime/intelligence-platform/skill-registry/config.cjs";
|
|
5
5
|
import { invalidSnapshot } from "../v2/runtime/intelligence-platform/skill-registry/errors.cjs";
|
|
6
6
|
import { SnapshotFile, SnapshotSkill, VerifiedSnapshot, validateSnapshot } from "../v2/runtime/intelligence-platform/skill-registry/snapshot.cjs";
|
|
7
7
|
import { SkillRegistry, SkillRegistryStatus } from "../v2/runtime/intelligence-platform/skill-registry/registry.cjs";
|
|
8
8
|
import { formatSkillCatalog, loadSkill, readSkillFile } from "../v2/runtime/intelligence-platform/skill-registry/skill-content.cjs";
|
|
9
9
|
import "../v2/runtime/intelligence-platform/skill-registry/index.cjs";
|
|
10
|
-
export { MAX_ARCHIVE_ENTRIES, MAX_SNAPSHOT_BYTES, RegistryConfig, LearnedSkillsError as SkillDeliveryError, LearnedSkillsErrorCode as SkillDeliveryErrorCode, SkillRegistry, SkillRegistryOptions, SkillRegistryStatus, SnapshotFile, SnapshotSkill, VerifiedSnapshot, formatSkillCatalog, invalidSnapshot, loadSkill, readArchive, readSkillFile, resolveRegistryConfig, safeRelativePath, validateSnapshot };
|
|
10
|
+
export { MAX_ARCHIVE_ENTRIES, MAX_SNAPSHOT_BYTES, RegistryConfig, SingleContainerConfig, LearnedSkillsError as SkillDeliveryError, LearnedSkillsErrorCode as SkillDeliveryErrorCode, SkillRegistry, SkillRegistryCommonOptions, SkillRegistryContainer, SkillRegistryOptions, SkillRegistryStatus, SnapshotFile, SnapshotSkill, VerifiedSnapshot, formatSkillCatalog, invalidSnapshot, loadSkill, readArchive, readSkillFile, resolveRegistryConfig, safeRelativePath, validateSnapshot };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
|
|
2
2
|
import { MAX_ARCHIVE_ENTRIES, MAX_SNAPSHOT_BYTES, readArchive, safeRelativePath } from "../v2/runtime/intelligence-platform/skill-registry/archive.mjs";
|
|
3
3
|
import { LearnedSkillsError, LearnedSkillsErrorCode } from "../v2/runtime/intelligence-platform/learned-skills.mjs";
|
|
4
|
-
import { RegistryConfig, SkillRegistryOptions, resolveRegistryConfig } from "../v2/runtime/intelligence-platform/skill-registry/config.mjs";
|
|
4
|
+
import { RegistryConfig, SingleContainerConfig, SkillRegistryCommonOptions, SkillRegistryContainer, SkillRegistryOptions, resolveRegistryConfig } from "../v2/runtime/intelligence-platform/skill-registry/config.mjs";
|
|
5
5
|
import { invalidSnapshot } from "../v2/runtime/intelligence-platform/skill-registry/errors.mjs";
|
|
6
6
|
import { SnapshotFile, SnapshotSkill, VerifiedSnapshot, validateSnapshot } from "../v2/runtime/intelligence-platform/skill-registry/snapshot.mjs";
|
|
7
7
|
import { SkillRegistry, SkillRegistryStatus } from "../v2/runtime/intelligence-platform/skill-registry/registry.mjs";
|
|
8
8
|
import { formatSkillCatalog, loadSkill, readSkillFile } from "../v2/runtime/intelligence-platform/skill-registry/skill-content.mjs";
|
|
9
9
|
import "../v2/runtime/intelligence-platform/skill-registry/index.mjs";
|
|
10
|
-
export { MAX_ARCHIVE_ENTRIES, MAX_SNAPSHOT_BYTES, RegistryConfig, LearnedSkillsError as SkillDeliveryError, LearnedSkillsErrorCode as SkillDeliveryErrorCode, SkillRegistry, SkillRegistryOptions, SkillRegistryStatus, SnapshotFile, SnapshotSkill, VerifiedSnapshot, formatSkillCatalog, invalidSnapshot, loadSkill, readArchive, readSkillFile, resolveRegistryConfig, safeRelativePath, validateSnapshot };
|
|
10
|
+
export { MAX_ARCHIVE_ENTRIES, MAX_SNAPSHOT_BYTES, RegistryConfig, SingleContainerConfig, LearnedSkillsError as SkillDeliveryError, LearnedSkillsErrorCode as SkillDeliveryErrorCode, SkillRegistry, SkillRegistryCommonOptions, SkillRegistryContainer, SkillRegistryOptions, SkillRegistryStatus, SnapshotFile, SnapshotSkill, VerifiedSnapshot, formatSkillCatalog, invalidSnapshot, loadSkill, readArchive, readSkillFile, resolveRegistryConfig, safeRelativePath, validateSnapshot };
|
package/dist/package.cjs
CHANGED
|
@@ -5,7 +5,7 @@ const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
|
|
|
5
5
|
var require_package = /* @__PURE__ */ require_runtime.__commonJSMin(((exports, module) => {
|
|
6
6
|
module.exports = {
|
|
7
7
|
"name": "@copilotkit/runtime",
|
|
8
|
-
"version": "1.
|
|
8
|
+
"version": "1.74.0",
|
|
9
9
|
"private": false,
|
|
10
10
|
"keywords": [
|
|
11
11
|
"ai",
|
package/dist/package.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { __commonJSMin } from "./_virtual/_rolldown/runtime.mjs";
|
|
|
5
5
|
var require_package = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
6
6
|
module.exports = {
|
|
7
7
|
"name": "@copilotkit/runtime",
|
|
8
|
-
"version": "1.
|
|
8
|
+
"version": "1.74.0",
|
|
9
9
|
"private": false,
|
|
10
10
|
"keywords": [
|
|
11
11
|
"ai",
|
package/dist/v2/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
import { TranscribeFileOptions, TranscriptionService } from "./runtime/transcription-service/transcription-service.cjs";
|
|
3
3
|
import { AgentRunner, AgentRunnerConnectRequest, AgentRunnerIsRunningRequest, AgentRunnerRunRequest, AgentRunnerStopRequest, LocalThreadEndpointRecord, LocalThreadEndpointRunner, supportsLocalThreadEndpoints } from "./runtime/runner/agent-runner.cjs";
|
|
4
|
-
import { GetLearnedSkillsSnapshotRequest, LearnedSkillsError, LearnedSkillsErrorCode, LearnedSkillsSnapshotResult } from "./runtime/intelligence-platform/learned-skills.cjs";
|
|
4
|
+
import { GetLearnedSkillsSnapshotRequest, GetLearnedSkillsSnapshotsRequest, LearnedSkillsBatchResult, LearnedSkillsError, LearnedSkillsErrorCode, LearnedSkillsSnapshotResult } from "./runtime/intelligence-platform/learned-skills.cjs";
|
|
5
5
|
import { AgentFactoryContext, AgentsConfig, AgentsFactory, CopilotIntelligenceRuntime, CopilotIntelligenceRuntimeLike, CopilotIntelligenceRuntimeOptions, CopilotRuntime, CopilotRuntimeConstructor, CopilotRuntimeLike, CopilotRuntimeMemoryConfig, CopilotRuntimeOptions, CopilotSseRuntime, CopilotSseRuntimeLike, CopilotSseRuntimeOptions, IdentifyUserCallback, McpAppsConfig, McpAppsServerConfig, MemoryAccess, MemoryConsumer, MemoryGrant, OpenGenerativeUIConfig, OpenGenerativeUIOptions, RuntimeWithDeclaredChannels, VERSION, isA2UIEnabled, isIntelligenceRuntime, resolveAgents } from "./runtime/core/runtime.cjs";
|
|
6
6
|
import { CopilotRuntimeLearningConfig, CopilotRuntimeLearningContext, CopilotRuntimeUser, GetLearningContainerId, LearningContainerSelectorInput } from "./runtime/core/learning.cjs";
|
|
7
7
|
import { CopilotKitIntelligence, CopilotKitIntelligenceConfig, CreateThreadRequest, ListThreadsResponse, SubscribeToThreadsRequest, SubscribeToThreadsResponse, ThreadSummary, UpdateThreadRequest } from "./runtime/intelligence-platform/client.cjs";
|
|
@@ -21,4 +21,4 @@ import { BuiltInAgentLearnedSkills, BuiltInAgentLearnedSkillsOptions } from "../
|
|
|
21
21
|
import { convertAISDKStream } from "../agent/converters/aisdk.cjs";
|
|
22
22
|
import { TanStackChatMessage, TanStackInputResult, convertInputToTanStackAI, convertTanStackStream } from "../agent/converters/tanstack.cjs";
|
|
23
23
|
import { BasicAgent, BasicAgentConfiguration, BuiltInAgent, BuiltInAgentAISDKFactoryConfig, BuiltInAgentClassicConfig, BuiltInAgentConfiguration, BuiltInAgentCustomFactoryConfig, BuiltInAgentFactoryConfig, BuiltInAgentFactoryContext, BuiltInAgentModel, BuiltInAgentTanStackFactoryConfig, InterruptSignal, MCPClientConfig, MCPClientConfigHTTP, MCPClientConfigSSE, MCPClientProvider, MessageConversionOptions, ModelSpecifier, OverridableProperty, ToolDefinition, classifyModelSpec, convertJsonSchemaToZodSchema, convertMessagesToVercelAISDKMessages, convertToolDefinitionsToVercelAITools, convertToolsToVercelAITools, defineTool, resolveModel } from "../agent/index.cjs";
|
|
24
|
-
export { type AgentFactoryContext, AgentRunner, AgentRunnerConnectRequest, AgentRunnerIsRunningRequest, AgentRunnerRunRequest, AgentRunnerStopRequest, AgentsConfig, AgentsFactory, BasicAgent, BasicAgentConfiguration, BuiltInAgent, BuiltInAgentAISDKFactoryConfig, BuiltInAgentClassicConfig, BuiltInAgentConfiguration, BuiltInAgentCustomFactoryConfig, BuiltInAgentFactoryConfig, BuiltInAgentFactoryContext, BuiltInAgentLearnedSkills, BuiltInAgentLearnedSkillsOptions, BuiltInAgentModel, BuiltInAgentTanStackFactoryConfig, ChannelStatus, ChannelsControl, CopilotCorsConfig, CopilotEndpointCorsConfig, CopilotExpressEndpointParams, CopilotExpressRouter, CopilotHonoApp, CopilotIntelligenceRuntime, CopilotIntelligenceRuntimeLike, CopilotIntelligenceRuntimeOptions, CopilotKitIntelligence, CopilotKitIntelligenceConfig, CopilotKitRequestHandler, CopilotRuntime, CopilotRuntimeConstructor, CopilotRuntimeFetchHandler, CopilotRuntimeFetchHandlerWithChannels, CopilotRuntimeHandlerOptions, CopilotRuntimeHooks, CopilotRuntimeLearningConfig, CopilotRuntimeLearningContext, CopilotRuntimeLike, CopilotRuntimeMemoryConfig, CopilotRuntimeOptions, CopilotRuntimeUser, CopilotSseRuntime, CopilotSseRuntimeLike, CopilotSseRuntimeOptions, CreateThreadRequest, ErrorHookContext, FinalizeRunOptions, GetLearnedSkillsSnapshotRequest, GetLearningContainerId, HandlerHookContext, HookContext, IdentifyUserCallback, InMemoryAgentRunner, InMemoryAgentRunnerOptions, InMemoryLimits, InMemoryThread, IntelligenceAgentRunner, IntelligenceAgentRunnerOptions, InterruptSignal, LearnedSkillsError, LearnedSkillsErrorCode, LearnedSkillsSnapshotResult, LearningContainerSelectorInput, ListThreadsResponse, LocalThreadEndpointRecord, LocalThreadEndpointRunner, MCPClient, MCPClientConfig, MCPClientConfigHTTP, MCPClientConfigSSE, MCPClientProvider, MCPTransport, McpAppsConfig, McpAppsServerConfig, MemoryAccess, MemoryConsumer, MemoryGrant, MessageConversionOptions, ModelSpecifier, OpenGenerativeUIConfig, OpenGenerativeUIOptions, OverridableProperty, ResponseHookContext, RouteInfo, RunEventFinalizer, RunnerStartupBoundary, RuntimeWithDeclaredChannels, SubscribeToThreadsRequest, SubscribeToThreadsResponse, TanStackChatMessage, TanStackInputResult, ThreadSummary, ToolDefinition, TranscribeFileOptions, TranscriptionService, UpdateThreadRequest, VERSION, classifyModelSpec, convertAISDKStream, convertInputToTanStackAI, convertJsonSchemaToZodSchema, convertMessagesToVercelAISDKMessages, convertTanStackStream, convertToolDefinitionsToVercelAITools, convertToolsToVercelAITools, createCopilotEndpoint, createCopilotExpressHandler as createCopilotEndpointExpress, createCopilotExpressHandler, createCopilotEndpointSingleRoute, createCopilotEndpointSingleRouteExpress, createCopilotHonoHandler, createCopilotRuntimeHandler, createRunEventFinalizer, defineTool, finalizeRunEvents, isA2UIEnabled, isIntelligenceRuntime, resolveAgents, resolveModel, supportsLocalThreadEndpoints, toFetchCorsConfig, ɵBoundedThreadStore, ɵGLOBAL_STORE, ɵINMEMORY_DEFAULTS, ɵestimateBytes, ɵnormalizeLimits };
|
|
24
|
+
export { type AgentFactoryContext, AgentRunner, AgentRunnerConnectRequest, AgentRunnerIsRunningRequest, AgentRunnerRunRequest, AgentRunnerStopRequest, AgentsConfig, AgentsFactory, BasicAgent, BasicAgentConfiguration, BuiltInAgent, BuiltInAgentAISDKFactoryConfig, BuiltInAgentClassicConfig, BuiltInAgentConfiguration, BuiltInAgentCustomFactoryConfig, BuiltInAgentFactoryConfig, BuiltInAgentFactoryContext, BuiltInAgentLearnedSkills, BuiltInAgentLearnedSkillsOptions, BuiltInAgentModel, BuiltInAgentTanStackFactoryConfig, ChannelStatus, ChannelsControl, CopilotCorsConfig, CopilotEndpointCorsConfig, CopilotExpressEndpointParams, CopilotExpressRouter, CopilotHonoApp, CopilotIntelligenceRuntime, CopilotIntelligenceRuntimeLike, CopilotIntelligenceRuntimeOptions, CopilotKitIntelligence, CopilotKitIntelligenceConfig, CopilotKitRequestHandler, CopilotRuntime, CopilotRuntimeConstructor, CopilotRuntimeFetchHandler, CopilotRuntimeFetchHandlerWithChannels, CopilotRuntimeHandlerOptions, CopilotRuntimeHooks, CopilotRuntimeLearningConfig, CopilotRuntimeLearningContext, CopilotRuntimeLike, CopilotRuntimeMemoryConfig, CopilotRuntimeOptions, CopilotRuntimeUser, CopilotSseRuntime, CopilotSseRuntimeLike, CopilotSseRuntimeOptions, CreateThreadRequest, ErrorHookContext, FinalizeRunOptions, GetLearnedSkillsSnapshotRequest, GetLearnedSkillsSnapshotsRequest, GetLearningContainerId, HandlerHookContext, HookContext, IdentifyUserCallback, InMemoryAgentRunner, InMemoryAgentRunnerOptions, InMemoryLimits, InMemoryThread, IntelligenceAgentRunner, IntelligenceAgentRunnerOptions, InterruptSignal, LearnedSkillsBatchResult, LearnedSkillsError, LearnedSkillsErrorCode, LearnedSkillsSnapshotResult, LearningContainerSelectorInput, ListThreadsResponse, LocalThreadEndpointRecord, LocalThreadEndpointRunner, MCPClient, MCPClientConfig, MCPClientConfigHTTP, MCPClientConfigSSE, MCPClientProvider, MCPTransport, McpAppsConfig, McpAppsServerConfig, MemoryAccess, MemoryConsumer, MemoryGrant, MessageConversionOptions, ModelSpecifier, OpenGenerativeUIConfig, OpenGenerativeUIOptions, OverridableProperty, ResponseHookContext, RouteInfo, RunEventFinalizer, RunnerStartupBoundary, RuntimeWithDeclaredChannels, SubscribeToThreadsRequest, SubscribeToThreadsResponse, TanStackChatMessage, TanStackInputResult, ThreadSummary, ToolDefinition, TranscribeFileOptions, TranscriptionService, UpdateThreadRequest, VERSION, classifyModelSpec, convertAISDKStream, convertInputToTanStackAI, convertJsonSchemaToZodSchema, convertMessagesToVercelAISDKMessages, convertTanStackStream, convertToolDefinitionsToVercelAITools, convertToolsToVercelAITools, createCopilotEndpoint, createCopilotExpressHandler as createCopilotEndpointExpress, createCopilotExpressHandler, createCopilotEndpointSingleRoute, createCopilotEndpointSingleRouteExpress, createCopilotHonoHandler, createCopilotRuntimeHandler, createRunEventFinalizer, defineTool, finalizeRunEvents, isA2UIEnabled, isIntelligenceRuntime, resolveAgents, resolveModel, supportsLocalThreadEndpoints, toFetchCorsConfig, ɵBoundedThreadStore, ɵGLOBAL_STORE, ɵINMEMORY_DEFAULTS, ɵestimateBytes, ɵnormalizeLimits };
|
package/dist/v2/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
import { TranscribeFileOptions, TranscriptionService } from "./runtime/transcription-service/transcription-service.mjs";
|
|
3
3
|
import { AgentRunner, AgentRunnerConnectRequest, AgentRunnerIsRunningRequest, AgentRunnerRunRequest, AgentRunnerStopRequest, LocalThreadEndpointRecord, LocalThreadEndpointRunner, supportsLocalThreadEndpoints } from "./runtime/runner/agent-runner.mjs";
|
|
4
|
-
import { GetLearnedSkillsSnapshotRequest, LearnedSkillsError, LearnedSkillsErrorCode, LearnedSkillsSnapshotResult } from "./runtime/intelligence-platform/learned-skills.mjs";
|
|
4
|
+
import { GetLearnedSkillsSnapshotRequest, GetLearnedSkillsSnapshotsRequest, LearnedSkillsBatchResult, LearnedSkillsError, LearnedSkillsErrorCode, LearnedSkillsSnapshotResult } from "./runtime/intelligence-platform/learned-skills.mjs";
|
|
5
5
|
import { AgentFactoryContext, AgentsConfig, AgentsFactory, CopilotIntelligenceRuntime, CopilotIntelligenceRuntimeLike, CopilotIntelligenceRuntimeOptions, CopilotRuntime, CopilotRuntimeConstructor, CopilotRuntimeLike, CopilotRuntimeMemoryConfig, CopilotRuntimeOptions, CopilotSseRuntime, CopilotSseRuntimeLike, CopilotSseRuntimeOptions, IdentifyUserCallback, McpAppsConfig, McpAppsServerConfig, MemoryAccess, MemoryConsumer, MemoryGrant, OpenGenerativeUIConfig, OpenGenerativeUIOptions, RuntimeWithDeclaredChannels, VERSION, isA2UIEnabled, isIntelligenceRuntime, resolveAgents } from "./runtime/core/runtime.mjs";
|
|
6
6
|
import { CopilotRuntimeLearningConfig, CopilotRuntimeLearningContext, CopilotRuntimeUser, GetLearningContainerId, LearningContainerSelectorInput } from "./runtime/core/learning.mjs";
|
|
7
7
|
import { CopilotKitIntelligence, CopilotKitIntelligenceConfig, CreateThreadRequest, ListThreadsResponse, SubscribeToThreadsRequest, SubscribeToThreadsResponse, ThreadSummary, UpdateThreadRequest } from "./runtime/intelligence-platform/client.mjs";
|
|
@@ -21,4 +21,4 @@ import { BuiltInAgentLearnedSkills, BuiltInAgentLearnedSkillsOptions } from "../
|
|
|
21
21
|
import { convertAISDKStream } from "../agent/converters/aisdk.mjs";
|
|
22
22
|
import { TanStackChatMessage, TanStackInputResult, convertInputToTanStackAI, convertTanStackStream } from "../agent/converters/tanstack.mjs";
|
|
23
23
|
import { BasicAgent, BasicAgentConfiguration, BuiltInAgent, BuiltInAgentAISDKFactoryConfig, BuiltInAgentClassicConfig, BuiltInAgentConfiguration, BuiltInAgentCustomFactoryConfig, BuiltInAgentFactoryConfig, BuiltInAgentFactoryContext, BuiltInAgentModel, BuiltInAgentTanStackFactoryConfig, InterruptSignal, MCPClientConfig, MCPClientConfigHTTP, MCPClientConfigSSE, MCPClientProvider, MessageConversionOptions, ModelSpecifier, OverridableProperty, ToolDefinition, classifyModelSpec, convertJsonSchemaToZodSchema, convertMessagesToVercelAISDKMessages, convertToolDefinitionsToVercelAITools, convertToolsToVercelAITools, defineTool, resolveModel } from "../agent/index.mjs";
|
|
24
|
-
export { type AgentFactoryContext, AgentRunner, AgentRunnerConnectRequest, AgentRunnerIsRunningRequest, AgentRunnerRunRequest, AgentRunnerStopRequest, AgentsConfig, AgentsFactory, BasicAgent, BasicAgentConfiguration, BuiltInAgent, BuiltInAgentAISDKFactoryConfig, BuiltInAgentClassicConfig, BuiltInAgentConfiguration, BuiltInAgentCustomFactoryConfig, BuiltInAgentFactoryConfig, BuiltInAgentFactoryContext, BuiltInAgentLearnedSkills, BuiltInAgentLearnedSkillsOptions, BuiltInAgentModel, BuiltInAgentTanStackFactoryConfig, ChannelStatus, ChannelsControl, CopilotCorsConfig, CopilotEndpointCorsConfig, CopilotExpressEndpointParams, CopilotExpressRouter, CopilotHonoApp, CopilotIntelligenceRuntime, CopilotIntelligenceRuntimeLike, CopilotIntelligenceRuntimeOptions, CopilotKitIntelligence, CopilotKitIntelligenceConfig, CopilotKitRequestHandler, CopilotRuntime, CopilotRuntimeConstructor, CopilotRuntimeFetchHandler, CopilotRuntimeFetchHandlerWithChannels, CopilotRuntimeHandlerOptions, CopilotRuntimeHooks, CopilotRuntimeLearningConfig, CopilotRuntimeLearningContext, CopilotRuntimeLike, CopilotRuntimeMemoryConfig, CopilotRuntimeOptions, CopilotRuntimeUser, CopilotSseRuntime, CopilotSseRuntimeLike, CopilotSseRuntimeOptions, CreateThreadRequest, ErrorHookContext, FinalizeRunOptions, GetLearnedSkillsSnapshotRequest, GetLearningContainerId, HandlerHookContext, HookContext, IdentifyUserCallback, InMemoryAgentRunner, InMemoryAgentRunnerOptions, InMemoryLimits, InMemoryThread, IntelligenceAgentRunner, IntelligenceAgentRunnerOptions, InterruptSignal, LearnedSkillsError, LearnedSkillsErrorCode, LearnedSkillsSnapshotResult, LearningContainerSelectorInput, ListThreadsResponse, LocalThreadEndpointRecord, LocalThreadEndpointRunner, MCPClient, MCPClientConfig, MCPClientConfigHTTP, MCPClientConfigSSE, MCPClientProvider, MCPTransport, McpAppsConfig, McpAppsServerConfig, MemoryAccess, MemoryConsumer, MemoryGrant, MessageConversionOptions, ModelSpecifier, OpenGenerativeUIConfig, OpenGenerativeUIOptions, OverridableProperty, ResponseHookContext, RouteInfo, RunEventFinalizer, RunnerStartupBoundary, RuntimeWithDeclaredChannels, SubscribeToThreadsRequest, SubscribeToThreadsResponse, TanStackChatMessage, TanStackInputResult, ThreadSummary, ToolDefinition, TranscribeFileOptions, TranscriptionService, UpdateThreadRequest, VERSION, classifyModelSpec, convertAISDKStream, convertInputToTanStackAI, convertJsonSchemaToZodSchema, convertMessagesToVercelAISDKMessages, convertTanStackStream, convertToolDefinitionsToVercelAITools, convertToolsToVercelAITools, createCopilotEndpoint, createCopilotExpressHandler as createCopilotEndpointExpress, createCopilotExpressHandler, createCopilotEndpointSingleRoute, createCopilotEndpointSingleRouteExpress, createCopilotHonoHandler, createCopilotRuntimeHandler, createRunEventFinalizer, defineTool, finalizeRunEvents, isA2UIEnabled, isIntelligenceRuntime, resolveAgents, resolveModel, supportsLocalThreadEndpoints, toFetchCorsConfig, ɵBoundedThreadStore, ɵGLOBAL_STORE, ɵINMEMORY_DEFAULTS, ɵestimateBytes, ɵnormalizeLimits };
|
|
24
|
+
export { type AgentFactoryContext, AgentRunner, AgentRunnerConnectRequest, AgentRunnerIsRunningRequest, AgentRunnerRunRequest, AgentRunnerStopRequest, AgentsConfig, AgentsFactory, BasicAgent, BasicAgentConfiguration, BuiltInAgent, BuiltInAgentAISDKFactoryConfig, BuiltInAgentClassicConfig, BuiltInAgentConfiguration, BuiltInAgentCustomFactoryConfig, BuiltInAgentFactoryConfig, BuiltInAgentFactoryContext, BuiltInAgentLearnedSkills, BuiltInAgentLearnedSkillsOptions, BuiltInAgentModel, BuiltInAgentTanStackFactoryConfig, ChannelStatus, ChannelsControl, CopilotCorsConfig, CopilotEndpointCorsConfig, CopilotExpressEndpointParams, CopilotExpressRouter, CopilotHonoApp, CopilotIntelligenceRuntime, CopilotIntelligenceRuntimeLike, CopilotIntelligenceRuntimeOptions, CopilotKitIntelligence, CopilotKitIntelligenceConfig, CopilotKitRequestHandler, CopilotRuntime, CopilotRuntimeConstructor, CopilotRuntimeFetchHandler, CopilotRuntimeFetchHandlerWithChannels, CopilotRuntimeHandlerOptions, CopilotRuntimeHooks, CopilotRuntimeLearningConfig, CopilotRuntimeLearningContext, CopilotRuntimeLike, CopilotRuntimeMemoryConfig, CopilotRuntimeOptions, CopilotRuntimeUser, CopilotSseRuntime, CopilotSseRuntimeLike, CopilotSseRuntimeOptions, CreateThreadRequest, ErrorHookContext, FinalizeRunOptions, GetLearnedSkillsSnapshotRequest, GetLearnedSkillsSnapshotsRequest, GetLearningContainerId, HandlerHookContext, HookContext, IdentifyUserCallback, InMemoryAgentRunner, InMemoryAgentRunnerOptions, InMemoryLimits, InMemoryThread, IntelligenceAgentRunner, IntelligenceAgentRunnerOptions, InterruptSignal, LearnedSkillsBatchResult, LearnedSkillsError, LearnedSkillsErrorCode, LearnedSkillsSnapshotResult, LearningContainerSelectorInput, ListThreadsResponse, LocalThreadEndpointRecord, LocalThreadEndpointRunner, MCPClient, MCPClientConfig, MCPClientConfigHTTP, MCPClientConfigSSE, MCPClientProvider, MCPTransport, McpAppsConfig, McpAppsServerConfig, MemoryAccess, MemoryConsumer, MemoryGrant, MessageConversionOptions, ModelSpecifier, OpenGenerativeUIConfig, OpenGenerativeUIOptions, OverridableProperty, ResponseHookContext, RouteInfo, RunEventFinalizer, RunnerStartupBoundary, RuntimeWithDeclaredChannels, SubscribeToThreadsRequest, SubscribeToThreadsResponse, TanStackChatMessage, TanStackInputResult, ThreadSummary, ToolDefinition, TranscribeFileOptions, TranscriptionService, UpdateThreadRequest, VERSION, classifyModelSpec, convertAISDKStream, convertInputToTanStackAI, convertJsonSchemaToZodSchema, convertMessagesToVercelAISDKMessages, convertTanStackStream, convertToolDefinitionsToVercelAITools, convertToolsToVercelAITools, createCopilotEndpoint, createCopilotExpressHandler as createCopilotEndpointExpress, createCopilotExpressHandler, createCopilotEndpointSingleRoute, createCopilotEndpointSingleRouteExpress, createCopilotHonoHandler, createCopilotRuntimeHandler, createRunEventFinalizer, defineTool, finalizeRunEvents, isA2UIEnabled, isIntelligenceRuntime, resolveAgents, resolveModel, supportsLocalThreadEndpoints, toFetchCorsConfig, ɵBoundedThreadStore, ɵGLOBAL_STORE, ɵINMEMORY_DEFAULTS, ɵestimateBytes, ɵnormalizeLimits };
|
|
@@ -14,7 +14,10 @@ async function resolveClientMemory(runtime, request) {
|
|
|
14
14
|
request
|
|
15
15
|
});
|
|
16
16
|
if (require_json_response.isHandlerResponse(user)) return user;
|
|
17
|
-
|
|
17
|
+
const access = await require_memory_policy.resolveWebMemory(runtime, request, user, "client");
|
|
18
|
+
if (require_json_response.isHandlerResponse(access)) return access;
|
|
19
|
+
if (runtime.memory && !require_memory_policy.grantAllowsMemory(access.grant)) return require_json_response.errorResponse("Memory access denied", 403);
|
|
20
|
+
return access;
|
|
18
21
|
}
|
|
19
22
|
const MISSING_INTELLIGENCE_MESSAGE = "Missing CopilotKitIntelligence configuration. Memory operations require a CopilotKitIntelligence instance to be provided in CopilotRuntime options.";
|
|
20
23
|
/** Allowed `kind` vocabulary the platform's memory endpoints accept. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memories.cjs","names":["resolveIntelligenceUser","isHandlerResponse","resolveWebMemory","PlatformRequestError","errorResponse","isIntelligenceRuntime"],"sources":["../../../../../src/v2/runtime/handlers/intelligence/memories.ts"],"sourcesContent":["import type {\n CopilotIntelligenceRuntimeLike,\n CopilotRuntimeLike,\n} from \"../../core/runtime\";\nimport { isIntelligenceRuntime } from \"../../core/runtime\";\nimport { logger } from \"@copilotkit/shared\";\nimport { errorResponse, isHandlerResponse } from \"../shared/json-response\";\nimport { resolveIntelligenceUser } from \"../shared/resolve-intelligence-user\";\nimport { resolveWebMemory } from \"../shared/memory-policy\";\nimport { PlatformRequestError } from \"../../intelligence-platform/client\";\n\ninterface MemoriesHandlerParams {\n runtime: CopilotRuntimeLike;\n request: Request;\n}\n\ninterface MemoryMutationParams extends MemoriesHandlerParams {\n memoryId: string;\n}\n\nasync function resolveClientMemory(\n runtime: CopilotIntelligenceRuntimeLike,\n request: Request,\n) {\n const user = await resolveIntelligenceUser({ runtime, request });\n if (isHandlerResponse(user)) return user;\n return resolveWebMemory(runtime, request, user, \"client\");\n}\n\nconst MISSING_INTELLIGENCE_MESSAGE =\n \"Missing CopilotKitIntelligence configuration. Memory operations require a CopilotKitIntelligence instance to be provided in CopilotRuntime options.\";\n\n/** Allowed `kind` vocabulary the platform's memory endpoints accept. */\nconst MEMORY_KINDS: ReadonlySet<string> = new Set([\n \"topical\",\n \"episodic\",\n \"operational\",\n]);\n/** Allowed `scope` vocabulary the platform's memory endpoints accept. */\nconst MEMORY_SCOPES: ReadonlySet<string> = new Set([\"user\", \"project\"]);\n\n/**\n * Maps a thrown error to a `Response`.\n *\n * For a {@link PlatformRequestError}, forward only client-actionable **4xx**\n * statuses verbatim (e.g. 404 missing/wrong-scope memory, 409 conflict, 422\n * unprocessable) so a `useMemories` consumer can branch on them — a flat 500\n * would erase that distinction. A platform **5xx** (or any non-4xx / malformed\n * status) means the runtime is healthy but its dependency failed, so it surfaces\n * as `502 Bad Gateway` rather than echoing the upstream status as if the runtime\n * itself broke — and this also avoids a `new Response(..., { status })`\n * `RangeError` on an out-of-range status. Non-platform throws stay 500.\n */\nfunction memoryErrorResponse(error: unknown, message: string): Response {\n if (error instanceof PlatformRequestError) {\n const { status } = error;\n if (Number.isInteger(status) && status >= 400 && status <= 499) {\n return errorResponse(message, status);\n }\n return errorResponse(message, 502);\n }\n return errorResponse(message, 500);\n}\n\nasync function parseJsonBody(\n request: Request,\n): Promise<Record<string, unknown> | Response> {\n try {\n return (await request.json()) as Record<string, unknown>;\n } catch (error) {\n logger.error({ err: error }, \"Malformed JSON in memory request body\");\n return errorResponse(\"Invalid request body\", 400);\n }\n}\n\n/**\n * Extracts and validates the create/supersede body fields the platform's\n * memory endpoints require. Returns a `Response` (400) on invalid input.\n */\nfunction parseMemoryBody(body: Record<string, unknown>):\n | {\n content: string;\n kind: string;\n scope?: string;\n sourceThreadIds?: string[];\n }\n | Response {\n const { content, kind, scope, sourceThreadIds } = body;\n if (typeof content !== \"string\" || typeof kind !== \"string\") {\n return errorResponse(\"Memory requires string `content` and `kind`\", 400);\n }\n // `kind` must be one of the platform's known kinds. Reject an out-of-vocabulary\n // value here rather than forwarding it for the platform to reject.\n if (!MEMORY_KINDS.has(kind)) {\n return errorResponse(\n \"Memory `kind` must be one of: topical, episodic, operational\",\n 400,\n );\n }\n // `scope` is optional: when omitted the platform applies its default\n // (`\"user\"`). Only reject a present-but-wrong-typed scope.\n if (scope !== undefined && typeof scope !== \"string\") {\n return errorResponse(\"Memory `scope` must be a string when provided\", 400);\n }\n // When `scope` is present, it must be one of the known scopes.\n if (typeof scope === \"string\" && !MEMORY_SCOPES.has(scope)) {\n return errorResponse(\"Memory `scope` must be one of: user, project\", 400);\n }\n // `sourceThreadIds` is optional, but when present it must be a string array.\n // Validate every element so non-string ids are not forwarded to the platform.\n if (\n sourceThreadIds !== undefined &&\n (!Array.isArray(sourceThreadIds) ||\n !sourceThreadIds.every((id) => typeof id === \"string\"))\n ) {\n return errorResponse(\n \"Memory `sourceThreadIds` must be an array of strings when provided\",\n 400,\n );\n }\n return {\n content,\n kind,\n ...(typeof scope === \"string\" ? { scope } : {}),\n ...(Array.isArray(sourceThreadIds)\n ? { sourceThreadIds: sourceThreadIds as string[] }\n : {}),\n // `sourceThreadIds` elements are validated as strings above; the cast is safe.\n };\n}\n\n/**\n * Validates the recall body: `query` required non-empty string (trimmed);\n * `limit` optional finite positive integer; `scope` optional and in the known\n * scopes. Returns a 400 Response on invalid input. The returned `query` is the\n * trimmed value so a whitespace-padded query is never forwarded to the platform.\n */\nfunction parseRecallBody(\n body: Record<string, unknown>,\n): { query: string; limit?: number; scope?: string } | Response {\n const { query, limit, scope } = body;\n // Trim before the emptiness check so whitespace-only queries (e.g. \" \")\n // are rejected rather than forwarded as a useless query to the platform.\n const trimmedQuery = typeof query === \"string\" ? query.trim() : query;\n if (typeof trimmedQuery !== \"string\" || trimmedQuery.length === 0) {\n return errorResponse(\"Recall requires a non-empty string `query`\", 400);\n }\n // When provided, `limit` must be a finite positive integer. `Number.isInteger`\n // already rejects NaN, Infinity, and fractions (NaN/Infinity would otherwise\n // JSON-serialize to `null` and silently corrupt the forwarded request);\n // the `> 0` guard rejects zero and negatives.\n if (\n limit !== undefined &&\n !(typeof limit === \"number\" && Number.isInteger(limit) && limit > 0)\n ) {\n return errorResponse(\"Recall `limit` must be a positive integer\", 400);\n }\n if (scope !== undefined && typeof scope !== \"string\") {\n return errorResponse(\"Recall `scope` must be a string when provided\", 400);\n }\n if (typeof scope === \"string\" && !MEMORY_SCOPES.has(scope)) {\n return errorResponse(\"Recall `scope` must be one of: user, project\", 400);\n }\n return {\n query: trimmedQuery,\n ...(typeof limit === \"number\" ? { limit } : {}),\n ...(typeof scope === \"string\" ? { scope } : {}),\n };\n}\n\n/**\n * Lists the resolved user's long-term memories via CopilotKit Intelligence.\n *\n * Mirrors {@link handleListThreads}: requires a `CopilotKitIntelligence`\n * runtime, resolves the user with `identifyUser` (never trusting a\n * client-supplied id), and proxies to the platform's `GET /api/memories`\n * with the project API key + resolved user. The `?includeInvalidated=true`\n * query is forwarded so callers can opt into retired rows. The response is\n * the platform's `{ memories }` envelope, which the client memory store\n * consumes directly.\n */\nexport async function handleListMemories({\n runtime,\n request,\n}: MemoriesHandlerParams): Promise<Response> {\n if (isIntelligenceRuntime(runtime)) {\n try {\n const url = new URL(request.url);\n const includeInvalidated =\n url.searchParams.get(\"includeInvalidated\") === \"true\";\n\n const access = await resolveClientMemory(runtime, request);\n if (isHandlerResponse(access)) return access;\n\n const data = await runtime.intelligence.listMemories({\n userId: access.user.id,\n ...(runtime.memory ? { memoryGrant: access.grant } : {}),\n ...(includeInvalidated ? { includeInvalidated: true } : {}),\n });\n\n // The client memory store consumes the `{ memories: [...] }` envelope\n // directly. Assert the shape before forwarding so a platform contract\n // violation surfaces as a clear 502 (the runtime is healthy but its\n // dependency returned the wrong shape) instead of a 200 the client will\n // choke on.\n if (\n data == null ||\n typeof data !== \"object\" ||\n !Array.isArray((data as { memories?: unknown }).memories)\n ) {\n logger.error(\n { data },\n \"listMemories: platform returned a response without a `memories` array\",\n );\n return errorResponse(\n \"Memory platform returned an invalid list response\",\n 502,\n );\n }\n\n return Response.json(data);\n } catch (error) {\n logger.error({ err: error }, \"Error listing memories\");\n return memoryErrorResponse(error, \"Failed to list memories\");\n }\n }\n\n return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n}\n\n/**\n * Semantically recalls the resolved user's memories via the platform (`POST\n * /api/memories/recall`, hybrid RAG). Mirrors {@link handleListMemories}:\n * requires a `CopilotKitIntelligence` runtime, resolves the user with\n * `identifyUser` (never a client-supplied id), proxies with the project API\n * key + resolved user. Body `{ query, limit?, scope? }`; response `{ memories }`,\n * each optionally carrying `score`.\n */\nexport async function handleRecallMemories({\n runtime,\n request,\n}: MemoriesHandlerParams): Promise<Response> {\n if (!isIntelligenceRuntime(runtime)) {\n return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n }\n try {\n const body = await parseJsonBody(request);\n if (isHandlerResponse(body)) return body;\n const fields = parseRecallBody(body);\n if (isHandlerResponse(fields)) return fields;\n\n const access = await resolveClientMemory(runtime, request);\n if (isHandlerResponse(access)) return access;\n\n const data = await runtime.intelligence.recallMemories({\n userId: access.user.id,\n ...(runtime.memory ? { memoryGrant: access.grant } : {}),\n ...fields,\n });\n\n if (\n data == null ||\n typeof data !== \"object\" ||\n !Array.isArray((data as { memories?: unknown }).memories)\n ) {\n logger.error(\n { data },\n \"recallMemories: platform returned a response without a `memories` array\",\n );\n return errorResponse(\n \"Memory platform returned an invalid recall response\",\n 502,\n );\n }\n return Response.json(data);\n } catch (error) {\n logger.error({ err: error }, \"Error recalling memories\");\n return memoryErrorResponse(error, \"Failed to recall memories\");\n }\n}\n\n/**\n * Mints memory-realtime join credentials (platform `POST\n * /api/memories/subscribe`). Mirrors {@link handleSubscribeToThreads}: requires\n * a `CopilotKitIntelligence` runtime and resolves the user with `identifyUser`\n * (never a client-supplied id). Returns `{ joinToken, joinCode }` — memory needs\n * the `joinCode` here (unlike threads, where it rides the thread-list response)\n * because the client builds the `user_meta:memories:<joinCode>` channel topic\n * from it.\n *\n * When the platform also resolves a project scope, the response additionally\n * carries `projectJoinToken` / `projectJoinCode`, which the client uses to open\n * a second `project_meta:memories:<projectJoinCode>` channel. These are\n * optional: absent project scope → both fields are omitted (silent-degrade\n * contract; the client opens only the user channel).\n */\nexport async function handleSubscribeToMemories({\n runtime,\n request,\n}: MemoriesHandlerParams): Promise<Response> {\n if (isIntelligenceRuntime(runtime)) {\n try {\n const access = await resolveClientMemory(runtime, request);\n if (isHandlerResponse(access)) return access;\n\n const credentials = await runtime.intelligence.ɵsubscribeToMemories({\n userId: access.user.id,\n ...(runtime.memory ? { memoryGrant: access.grant } : {}),\n });\n\n return Response.json({\n ...(credentials.joinToken !== undefined\n ? { joinToken: credentials.joinToken }\n : {}),\n ...(credentials.joinCode !== undefined\n ? { joinCode: credentials.joinCode }\n : {}),\n // Project-scoped credentials ride along only when the platform minted\n // them; omit both when absent (silent-degrade contract).\n ...(credentials.projectJoinToken !== undefined\n ? { projectJoinToken: credentials.projectJoinToken }\n : {}),\n ...(credentials.projectJoinCode !== undefined\n ? { projectJoinCode: credentials.projectJoinCode }\n : {}),\n });\n } catch (error) {\n logger.error({ err: error }, \"Error subscribing to memories\");\n return memoryErrorResponse(error, \"Failed to subscribe to memories\");\n }\n }\n\n return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n}\n\n/**\n * Creates a memory for the resolved user (platform `POST /api/memories`).\n * Identity comes from `identifyUser`, never the request body. Returns 201\n * with the stored memory (the client store applies it server-authoritatively).\n */\nexport async function handleCreateMemory({\n runtime,\n request,\n}: MemoriesHandlerParams): Promise<Response> {\n if (!isIntelligenceRuntime(runtime)) {\n return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n }\n try {\n const body = await parseJsonBody(request);\n if (isHandlerResponse(body)) return body;\n const fields = parseMemoryBody(body);\n if (isHandlerResponse(fields)) return fields;\n\n const access = await resolveClientMemory(runtime, request);\n if (isHandlerResponse(access)) return access;\n\n const data = await runtime.intelligence.createMemory({\n userId: access.user.id,\n ...(runtime.memory ? { memoryGrant: access.grant } : {}),\n ...fields,\n });\n return Response.json(data, { status: 201 });\n } catch (error) {\n logger.error({ err: error }, \"Error creating memory\");\n return memoryErrorResponse(error, \"Failed to create memory\");\n }\n}\n\n/**\n * Supersedes a memory (platform `PATCH /api/memories/:id`): retires `:id` and\n * inserts the new content atomically; the response carries `retiredId`.\n */\nexport async function handleUpdateMemory({\n runtime,\n request,\n memoryId,\n}: MemoryMutationParams): Promise<Response> {\n if (!isIntelligenceRuntime(runtime)) {\n return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n }\n try {\n const body = await parseJsonBody(request);\n if (isHandlerResponse(body)) return body;\n const fields = parseMemoryBody(body);\n if (isHandlerResponse(fields)) return fields;\n\n const access = await resolveClientMemory(runtime, request);\n if (isHandlerResponse(access)) return access;\n\n const data = await runtime.intelligence.updateMemory({\n userId: access.user.id,\n ...(runtime.memory ? { memoryGrant: access.grant } : {}),\n id: memoryId,\n ...fields,\n });\n return Response.json(data);\n } catch (error) {\n logger.error({ err: error }, \"Error updating memory\");\n return memoryErrorResponse(error, \"Failed to update memory\");\n }\n}\n\n/**\n * Retires (forgets) a memory (platform `DELETE /api/memories/:id`). Non-lossy\n * on the platform side; returns 204.\n */\nexport async function handleRemoveMemory({\n runtime,\n request,\n memoryId,\n}: MemoryMutationParams): Promise<Response> {\n if (!isIntelligenceRuntime(runtime)) {\n return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n }\n try {\n const access = await resolveClientMemory(runtime, request);\n if (isHandlerResponse(access)) return access;\n\n await runtime.intelligence.removeMemory({\n userId: access.user.id,\n id: memoryId,\n ...(runtime.memory ? { memoryGrant: access.grant } : {}),\n });\n return new Response(null, { status: 204 });\n } catch (error) {\n logger.error({ err: error }, \"Error removing memory\");\n return memoryErrorResponse(error, \"Failed to remove memory\");\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"memories.cjs","names":["resolveIntelligenceUser","isHandlerResponse","resolveWebMemory","grantAllowsMemory","errorResponse","PlatformRequestError","isIntelligenceRuntime"],"sources":["../../../../../src/v2/runtime/handlers/intelligence/memories.ts"],"sourcesContent":["import type {\n CopilotIntelligenceRuntimeLike,\n CopilotRuntimeLike,\n} from \"../../core/runtime\";\nimport { isIntelligenceRuntime } from \"../../core/runtime\";\nimport { logger } from \"@copilotkit/shared\";\nimport { errorResponse, isHandlerResponse } from \"../shared/json-response\";\nimport { resolveIntelligenceUser } from \"../shared/resolve-intelligence-user\";\nimport { grantAllowsMemory, resolveWebMemory } from \"../shared/memory-policy\";\nimport { PlatformRequestError } from \"../../intelligence-platform/client\";\n\ninterface MemoriesHandlerParams {\n runtime: CopilotRuntimeLike;\n request: Request;\n}\n\ninterface MemoryMutationParams extends MemoriesHandlerParams {\n memoryId: string;\n}\n\nasync function resolveClientMemory(\n runtime: CopilotIntelligenceRuntimeLike,\n request: Request,\n) {\n const user = await resolveIntelligenceUser({ runtime, request });\n if (isHandlerResponse(user)) return user;\n const access = await resolveWebMemory(runtime, request, user, \"client\");\n if (isHandlerResponse(access)) return access;\n // Unlike an agent run — which proceeds without Memory tools when the policy\n // grants nothing — these routes exist ONLY to serve memories. A caller who\n // asked for them and may not have them gets 403; an empty list would imply\n // there are none, which is a different and false claim.\n if (runtime.memory && !grantAllowsMemory(access.grant)) {\n return errorResponse(\"Memory access denied\", 403);\n }\n return access;\n}\n\nconst MISSING_INTELLIGENCE_MESSAGE =\n \"Missing CopilotKitIntelligence configuration. Memory operations require a CopilotKitIntelligence instance to be provided in CopilotRuntime options.\";\n\n/** Allowed `kind` vocabulary the platform's memory endpoints accept. */\nconst MEMORY_KINDS: ReadonlySet<string> = new Set([\n \"topical\",\n \"episodic\",\n \"operational\",\n]);\n/** Allowed `scope` vocabulary the platform's memory endpoints accept. */\nconst MEMORY_SCOPES: ReadonlySet<string> = new Set([\"user\", \"project\"]);\n\n/**\n * Maps a thrown error to a `Response`.\n *\n * For a {@link PlatformRequestError}, forward only client-actionable **4xx**\n * statuses verbatim (e.g. 404 missing/wrong-scope memory, 409 conflict, 422\n * unprocessable) so a `useMemories` consumer can branch on them — a flat 500\n * would erase that distinction. A platform **5xx** (or any non-4xx / malformed\n * status) means the runtime is healthy but its dependency failed, so it surfaces\n * as `502 Bad Gateway` rather than echoing the upstream status as if the runtime\n * itself broke — and this also avoids a `new Response(..., { status })`\n * `RangeError` on an out-of-range status. Non-platform throws stay 500.\n */\nfunction memoryErrorResponse(error: unknown, message: string): Response {\n if (error instanceof PlatformRequestError) {\n const { status } = error;\n if (Number.isInteger(status) && status >= 400 && status <= 499) {\n return errorResponse(message, status);\n }\n return errorResponse(message, 502);\n }\n return errorResponse(message, 500);\n}\n\nasync function parseJsonBody(\n request: Request,\n): Promise<Record<string, unknown> | Response> {\n try {\n return (await request.json()) as Record<string, unknown>;\n } catch (error) {\n logger.error({ err: error }, \"Malformed JSON in memory request body\");\n return errorResponse(\"Invalid request body\", 400);\n }\n}\n\n/**\n * Extracts and validates the create/supersede body fields the platform's\n * memory endpoints require. Returns a `Response` (400) on invalid input.\n */\nfunction parseMemoryBody(body: Record<string, unknown>):\n | {\n content: string;\n kind: string;\n scope?: string;\n sourceThreadIds?: string[];\n }\n | Response {\n const { content, kind, scope, sourceThreadIds } = body;\n if (typeof content !== \"string\" || typeof kind !== \"string\") {\n return errorResponse(\"Memory requires string `content` and `kind`\", 400);\n }\n // `kind` must be one of the platform's known kinds. Reject an out-of-vocabulary\n // value here rather than forwarding it for the platform to reject.\n if (!MEMORY_KINDS.has(kind)) {\n return errorResponse(\n \"Memory `kind` must be one of: topical, episodic, operational\",\n 400,\n );\n }\n // `scope` is optional: when omitted the platform applies its default\n // (`\"user\"`). Only reject a present-but-wrong-typed scope.\n if (scope !== undefined && typeof scope !== \"string\") {\n return errorResponse(\"Memory `scope` must be a string when provided\", 400);\n }\n // When `scope` is present, it must be one of the known scopes.\n if (typeof scope === \"string\" && !MEMORY_SCOPES.has(scope)) {\n return errorResponse(\"Memory `scope` must be one of: user, project\", 400);\n }\n // `sourceThreadIds` is optional, but when present it must be a string array.\n // Validate every element so non-string ids are not forwarded to the platform.\n if (\n sourceThreadIds !== undefined &&\n (!Array.isArray(sourceThreadIds) ||\n !sourceThreadIds.every((id) => typeof id === \"string\"))\n ) {\n return errorResponse(\n \"Memory `sourceThreadIds` must be an array of strings when provided\",\n 400,\n );\n }\n return {\n content,\n kind,\n ...(typeof scope === \"string\" ? { scope } : {}),\n ...(Array.isArray(sourceThreadIds)\n ? { sourceThreadIds: sourceThreadIds as string[] }\n : {}),\n // `sourceThreadIds` elements are validated as strings above; the cast is safe.\n };\n}\n\n/**\n * Validates the recall body: `query` required non-empty string (trimmed);\n * `limit` optional finite positive integer; `scope` optional and in the known\n * scopes. Returns a 400 Response on invalid input. The returned `query` is the\n * trimmed value so a whitespace-padded query is never forwarded to the platform.\n */\nfunction parseRecallBody(\n body: Record<string, unknown>,\n): { query: string; limit?: number; scope?: string } | Response {\n const { query, limit, scope } = body;\n // Trim before the emptiness check so whitespace-only queries (e.g. \" \")\n // are rejected rather than forwarded as a useless query to the platform.\n const trimmedQuery = typeof query === \"string\" ? query.trim() : query;\n if (typeof trimmedQuery !== \"string\" || trimmedQuery.length === 0) {\n return errorResponse(\"Recall requires a non-empty string `query`\", 400);\n }\n // When provided, `limit` must be a finite positive integer. `Number.isInteger`\n // already rejects NaN, Infinity, and fractions (NaN/Infinity would otherwise\n // JSON-serialize to `null` and silently corrupt the forwarded request);\n // the `> 0` guard rejects zero and negatives.\n if (\n limit !== undefined &&\n !(typeof limit === \"number\" && Number.isInteger(limit) && limit > 0)\n ) {\n return errorResponse(\"Recall `limit` must be a positive integer\", 400);\n }\n if (scope !== undefined && typeof scope !== \"string\") {\n return errorResponse(\"Recall `scope` must be a string when provided\", 400);\n }\n if (typeof scope === \"string\" && !MEMORY_SCOPES.has(scope)) {\n return errorResponse(\"Recall `scope` must be one of: user, project\", 400);\n }\n return {\n query: trimmedQuery,\n ...(typeof limit === \"number\" ? { limit } : {}),\n ...(typeof scope === \"string\" ? { scope } : {}),\n };\n}\n\n/**\n * Lists the resolved user's long-term memories via CopilotKit Intelligence.\n *\n * Mirrors {@link handleListThreads}: requires a `CopilotKitIntelligence`\n * runtime, resolves the user with `identifyUser` (never trusting a\n * client-supplied id), and proxies to the platform's `GET /api/memories`\n * with the project API key + resolved user. The `?includeInvalidated=true`\n * query is forwarded so callers can opt into retired rows. The response is\n * the platform's `{ memories }` envelope, which the client memory store\n * consumes directly.\n */\nexport async function handleListMemories({\n runtime,\n request,\n}: MemoriesHandlerParams): Promise<Response> {\n if (isIntelligenceRuntime(runtime)) {\n try {\n const url = new URL(request.url);\n const includeInvalidated =\n url.searchParams.get(\"includeInvalidated\") === \"true\";\n\n const access = await resolveClientMemory(runtime, request);\n if (isHandlerResponse(access)) return access;\n\n const data = await runtime.intelligence.listMemories({\n userId: access.user.id,\n ...(runtime.memory ? { memoryGrant: access.grant } : {}),\n ...(includeInvalidated ? { includeInvalidated: true } : {}),\n });\n\n // The client memory store consumes the `{ memories: [...] }` envelope\n // directly. Assert the shape before forwarding so a platform contract\n // violation surfaces as a clear 502 (the runtime is healthy but its\n // dependency returned the wrong shape) instead of a 200 the client will\n // choke on.\n if (\n data == null ||\n typeof data !== \"object\" ||\n !Array.isArray((data as { memories?: unknown }).memories)\n ) {\n logger.error(\n { data },\n \"listMemories: platform returned a response without a `memories` array\",\n );\n return errorResponse(\n \"Memory platform returned an invalid list response\",\n 502,\n );\n }\n\n return Response.json(data);\n } catch (error) {\n logger.error({ err: error }, \"Error listing memories\");\n return memoryErrorResponse(error, \"Failed to list memories\");\n }\n }\n\n return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n}\n\n/**\n * Semantically recalls the resolved user's memories via the platform (`POST\n * /api/memories/recall`, hybrid RAG). Mirrors {@link handleListMemories}:\n * requires a `CopilotKitIntelligence` runtime, resolves the user with\n * `identifyUser` (never a client-supplied id), proxies with the project API\n * key + resolved user. Body `{ query, limit?, scope? }`; response `{ memories }`,\n * each optionally carrying `score`.\n */\nexport async function handleRecallMemories({\n runtime,\n request,\n}: MemoriesHandlerParams): Promise<Response> {\n if (!isIntelligenceRuntime(runtime)) {\n return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n }\n try {\n const body = await parseJsonBody(request);\n if (isHandlerResponse(body)) return body;\n const fields = parseRecallBody(body);\n if (isHandlerResponse(fields)) return fields;\n\n const access = await resolveClientMemory(runtime, request);\n if (isHandlerResponse(access)) return access;\n\n const data = await runtime.intelligence.recallMemories({\n userId: access.user.id,\n ...(runtime.memory ? { memoryGrant: access.grant } : {}),\n ...fields,\n });\n\n if (\n data == null ||\n typeof data !== \"object\" ||\n !Array.isArray((data as { memories?: unknown }).memories)\n ) {\n logger.error(\n { data },\n \"recallMemories: platform returned a response without a `memories` array\",\n );\n return errorResponse(\n \"Memory platform returned an invalid recall response\",\n 502,\n );\n }\n return Response.json(data);\n } catch (error) {\n logger.error({ err: error }, \"Error recalling memories\");\n return memoryErrorResponse(error, \"Failed to recall memories\");\n }\n}\n\n/**\n * Mints memory-realtime join credentials (platform `POST\n * /api/memories/subscribe`). Mirrors {@link handleSubscribeToThreads}: requires\n * a `CopilotKitIntelligence` runtime and resolves the user with `identifyUser`\n * (never a client-supplied id). Returns `{ joinToken, joinCode }` — memory needs\n * the `joinCode` here (unlike threads, where it rides the thread-list response)\n * because the client builds the `user_meta:memories:<joinCode>` channel topic\n * from it.\n *\n * When the platform also resolves a project scope, the response additionally\n * carries `projectJoinToken` / `projectJoinCode`, which the client uses to open\n * a second `project_meta:memories:<projectJoinCode>` channel. These are\n * optional: absent project scope → both fields are omitted (silent-degrade\n * contract; the client opens only the user channel).\n */\nexport async function handleSubscribeToMemories({\n runtime,\n request,\n}: MemoriesHandlerParams): Promise<Response> {\n if (isIntelligenceRuntime(runtime)) {\n try {\n const access = await resolveClientMemory(runtime, request);\n if (isHandlerResponse(access)) return access;\n\n const credentials = await runtime.intelligence.ɵsubscribeToMemories({\n userId: access.user.id,\n ...(runtime.memory ? { memoryGrant: access.grant } : {}),\n });\n\n return Response.json({\n ...(credentials.joinToken !== undefined\n ? { joinToken: credentials.joinToken }\n : {}),\n ...(credentials.joinCode !== undefined\n ? { joinCode: credentials.joinCode }\n : {}),\n // Project-scoped credentials ride along only when the platform minted\n // them; omit both when absent (silent-degrade contract).\n ...(credentials.projectJoinToken !== undefined\n ? { projectJoinToken: credentials.projectJoinToken }\n : {}),\n ...(credentials.projectJoinCode !== undefined\n ? { projectJoinCode: credentials.projectJoinCode }\n : {}),\n });\n } catch (error) {\n logger.error({ err: error }, \"Error subscribing to memories\");\n return memoryErrorResponse(error, \"Failed to subscribe to memories\");\n }\n }\n\n return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n}\n\n/**\n * Creates a memory for the resolved user (platform `POST /api/memories`).\n * Identity comes from `identifyUser`, never the request body. Returns 201\n * with the stored memory (the client store applies it server-authoritatively).\n */\nexport async function handleCreateMemory({\n runtime,\n request,\n}: MemoriesHandlerParams): Promise<Response> {\n if (!isIntelligenceRuntime(runtime)) {\n return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n }\n try {\n const body = await parseJsonBody(request);\n if (isHandlerResponse(body)) return body;\n const fields = parseMemoryBody(body);\n if (isHandlerResponse(fields)) return fields;\n\n const access = await resolveClientMemory(runtime, request);\n if (isHandlerResponse(access)) return access;\n\n const data = await runtime.intelligence.createMemory({\n userId: access.user.id,\n ...(runtime.memory ? { memoryGrant: access.grant } : {}),\n ...fields,\n });\n return Response.json(data, { status: 201 });\n } catch (error) {\n logger.error({ err: error }, \"Error creating memory\");\n return memoryErrorResponse(error, \"Failed to create memory\");\n }\n}\n\n/**\n * Supersedes a memory (platform `PATCH /api/memories/:id`): retires `:id` and\n * inserts the new content atomically; the response carries `retiredId`.\n */\nexport async function handleUpdateMemory({\n runtime,\n request,\n memoryId,\n}: MemoryMutationParams): Promise<Response> {\n if (!isIntelligenceRuntime(runtime)) {\n return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n }\n try {\n const body = await parseJsonBody(request);\n if (isHandlerResponse(body)) return body;\n const fields = parseMemoryBody(body);\n if (isHandlerResponse(fields)) return fields;\n\n const access = await resolveClientMemory(runtime, request);\n if (isHandlerResponse(access)) return access;\n\n const data = await runtime.intelligence.updateMemory({\n userId: access.user.id,\n ...(runtime.memory ? { memoryGrant: access.grant } : {}),\n id: memoryId,\n ...fields,\n });\n return Response.json(data);\n } catch (error) {\n logger.error({ err: error }, \"Error updating memory\");\n return memoryErrorResponse(error, \"Failed to update memory\");\n }\n}\n\n/**\n * Retires (forgets) a memory (platform `DELETE /api/memories/:id`). Non-lossy\n * on the platform side; returns 204.\n */\nexport async function handleRemoveMemory({\n runtime,\n request,\n memoryId,\n}: MemoryMutationParams): Promise<Response> {\n if (!isIntelligenceRuntime(runtime)) {\n return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n }\n try {\n const access = await resolveClientMemory(runtime, request);\n if (isHandlerResponse(access)) return access;\n\n await runtime.intelligence.removeMemory({\n userId: access.user.id,\n id: memoryId,\n ...(runtime.memory ? { memoryGrant: access.grant } : {}),\n });\n return new Response(null, { status: 204 });\n } catch (error) {\n logger.error({ err: error }, \"Error removing memory\");\n return memoryErrorResponse(error, \"Failed to remove memory\");\n }\n}\n"],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ import { isIntelligenceRuntime } from "../../core/runtime.mjs";
|
|
|
3
3
|
import { PlatformRequestError } from "../../intelligence-platform/client.mjs";
|
|
4
4
|
import { errorResponse, isHandlerResponse } from "../shared/json-response.mjs";
|
|
5
5
|
import { resolveIntelligenceUser } from "../shared/resolve-intelligence-user.mjs";
|
|
6
|
-
import { resolveWebMemory } from "../shared/memory-policy.mjs";
|
|
6
|
+
import { grantAllowsMemory, resolveWebMemory } from "../shared/memory-policy.mjs";
|
|
7
7
|
import { logger } from "@copilotkit/shared";
|
|
8
8
|
|
|
9
9
|
//#region src/v2/runtime/handlers/intelligence/memories.ts
|
|
@@ -13,7 +13,10 @@ async function resolveClientMemory(runtime, request) {
|
|
|
13
13
|
request
|
|
14
14
|
});
|
|
15
15
|
if (isHandlerResponse(user)) return user;
|
|
16
|
-
|
|
16
|
+
const access = await resolveWebMemory(runtime, request, user, "client");
|
|
17
|
+
if (isHandlerResponse(access)) return access;
|
|
18
|
+
if (runtime.memory && !grantAllowsMemory(access.grant)) return errorResponse("Memory access denied", 403);
|
|
19
|
+
return access;
|
|
17
20
|
}
|
|
18
21
|
const MISSING_INTELLIGENCE_MESSAGE = "Missing CopilotKitIntelligence configuration. Memory operations require a CopilotKitIntelligence instance to be provided in CopilotRuntime options.";
|
|
19
22
|
/** Allowed `kind` vocabulary the platform's memory endpoints accept. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memories.mjs","names":[],"sources":["../../../../../src/v2/runtime/handlers/intelligence/memories.ts"],"sourcesContent":["import type {\n CopilotIntelligenceRuntimeLike,\n CopilotRuntimeLike,\n} from \"../../core/runtime\";\nimport { isIntelligenceRuntime } from \"../../core/runtime\";\nimport { logger } from \"@copilotkit/shared\";\nimport { errorResponse, isHandlerResponse } from \"../shared/json-response\";\nimport { resolveIntelligenceUser } from \"../shared/resolve-intelligence-user\";\nimport { resolveWebMemory } from \"../shared/memory-policy\";\nimport { PlatformRequestError } from \"../../intelligence-platform/client\";\n\ninterface MemoriesHandlerParams {\n runtime: CopilotRuntimeLike;\n request: Request;\n}\n\ninterface MemoryMutationParams extends MemoriesHandlerParams {\n memoryId: string;\n}\n\nasync function resolveClientMemory(\n runtime: CopilotIntelligenceRuntimeLike,\n request: Request,\n) {\n const user = await resolveIntelligenceUser({ runtime, request });\n if (isHandlerResponse(user)) return user;\n return resolveWebMemory(runtime, request, user, \"client\");\n}\n\nconst MISSING_INTELLIGENCE_MESSAGE =\n \"Missing CopilotKitIntelligence configuration. Memory operations require a CopilotKitIntelligence instance to be provided in CopilotRuntime options.\";\n\n/** Allowed `kind` vocabulary the platform's memory endpoints accept. */\nconst MEMORY_KINDS: ReadonlySet<string> = new Set([\n \"topical\",\n \"episodic\",\n \"operational\",\n]);\n/** Allowed `scope` vocabulary the platform's memory endpoints accept. */\nconst MEMORY_SCOPES: ReadonlySet<string> = new Set([\"user\", \"project\"]);\n\n/**\n * Maps a thrown error to a `Response`.\n *\n * For a {@link PlatformRequestError}, forward only client-actionable **4xx**\n * statuses verbatim (e.g. 404 missing/wrong-scope memory, 409 conflict, 422\n * unprocessable) so a `useMemories` consumer can branch on them — a flat 500\n * would erase that distinction. A platform **5xx** (or any non-4xx / malformed\n * status) means the runtime is healthy but its dependency failed, so it surfaces\n * as `502 Bad Gateway` rather than echoing the upstream status as if the runtime\n * itself broke — and this also avoids a `new Response(..., { status })`\n * `RangeError` on an out-of-range status. Non-platform throws stay 500.\n */\nfunction memoryErrorResponse(error: unknown, message: string): Response {\n if (error instanceof PlatformRequestError) {\n const { status } = error;\n if (Number.isInteger(status) && status >= 400 && status <= 499) {\n return errorResponse(message, status);\n }\n return errorResponse(message, 502);\n }\n return errorResponse(message, 500);\n}\n\nasync function parseJsonBody(\n request: Request,\n): Promise<Record<string, unknown> | Response> {\n try {\n return (await request.json()) as Record<string, unknown>;\n } catch (error) {\n logger.error({ err: error }, \"Malformed JSON in memory request body\");\n return errorResponse(\"Invalid request body\", 400);\n }\n}\n\n/**\n * Extracts and validates the create/supersede body fields the platform's\n * memory endpoints require. Returns a `Response` (400) on invalid input.\n */\nfunction parseMemoryBody(body: Record<string, unknown>):\n | {\n content: string;\n kind: string;\n scope?: string;\n sourceThreadIds?: string[];\n }\n | Response {\n const { content, kind, scope, sourceThreadIds } = body;\n if (typeof content !== \"string\" || typeof kind !== \"string\") {\n return errorResponse(\"Memory requires string `content` and `kind`\", 400);\n }\n // `kind` must be one of the platform's known kinds. Reject an out-of-vocabulary\n // value here rather than forwarding it for the platform to reject.\n if (!MEMORY_KINDS.has(kind)) {\n return errorResponse(\n \"Memory `kind` must be one of: topical, episodic, operational\",\n 400,\n );\n }\n // `scope` is optional: when omitted the platform applies its default\n // (`\"user\"`). Only reject a present-but-wrong-typed scope.\n if (scope !== undefined && typeof scope !== \"string\") {\n return errorResponse(\"Memory `scope` must be a string when provided\", 400);\n }\n // When `scope` is present, it must be one of the known scopes.\n if (typeof scope === \"string\" && !MEMORY_SCOPES.has(scope)) {\n return errorResponse(\"Memory `scope` must be one of: user, project\", 400);\n }\n // `sourceThreadIds` is optional, but when present it must be a string array.\n // Validate every element so non-string ids are not forwarded to the platform.\n if (\n sourceThreadIds !== undefined &&\n (!Array.isArray(sourceThreadIds) ||\n !sourceThreadIds.every((id) => typeof id === \"string\"))\n ) {\n return errorResponse(\n \"Memory `sourceThreadIds` must be an array of strings when provided\",\n 400,\n );\n }\n return {\n content,\n kind,\n ...(typeof scope === \"string\" ? { scope } : {}),\n ...(Array.isArray(sourceThreadIds)\n ? { sourceThreadIds: sourceThreadIds as string[] }\n : {}),\n // `sourceThreadIds` elements are validated as strings above; the cast is safe.\n };\n}\n\n/**\n * Validates the recall body: `query` required non-empty string (trimmed);\n * `limit` optional finite positive integer; `scope` optional and in the known\n * scopes. Returns a 400 Response on invalid input. The returned `query` is the\n * trimmed value so a whitespace-padded query is never forwarded to the platform.\n */\nfunction parseRecallBody(\n body: Record<string, unknown>,\n): { query: string; limit?: number; scope?: string } | Response {\n const { query, limit, scope } = body;\n // Trim before the emptiness check so whitespace-only queries (e.g. \" \")\n // are rejected rather than forwarded as a useless query to the platform.\n const trimmedQuery = typeof query === \"string\" ? query.trim() : query;\n if (typeof trimmedQuery !== \"string\" || trimmedQuery.length === 0) {\n return errorResponse(\"Recall requires a non-empty string `query`\", 400);\n }\n // When provided, `limit` must be a finite positive integer. `Number.isInteger`\n // already rejects NaN, Infinity, and fractions (NaN/Infinity would otherwise\n // JSON-serialize to `null` and silently corrupt the forwarded request);\n // the `> 0` guard rejects zero and negatives.\n if (\n limit !== undefined &&\n !(typeof limit === \"number\" && Number.isInteger(limit) && limit > 0)\n ) {\n return errorResponse(\"Recall `limit` must be a positive integer\", 400);\n }\n if (scope !== undefined && typeof scope !== \"string\") {\n return errorResponse(\"Recall `scope` must be a string when provided\", 400);\n }\n if (typeof scope === \"string\" && !MEMORY_SCOPES.has(scope)) {\n return errorResponse(\"Recall `scope` must be one of: user, project\", 400);\n }\n return {\n query: trimmedQuery,\n ...(typeof limit === \"number\" ? { limit } : {}),\n ...(typeof scope === \"string\" ? { scope } : {}),\n };\n}\n\n/**\n * Lists the resolved user's long-term memories via CopilotKit Intelligence.\n *\n * Mirrors {@link handleListThreads}: requires a `CopilotKitIntelligence`\n * runtime, resolves the user with `identifyUser` (never trusting a\n * client-supplied id), and proxies to the platform's `GET /api/memories`\n * with the project API key + resolved user. The `?includeInvalidated=true`\n * query is forwarded so callers can opt into retired rows. The response is\n * the platform's `{ memories }` envelope, which the client memory store\n * consumes directly.\n */\nexport async function handleListMemories({\n runtime,\n request,\n}: MemoriesHandlerParams): Promise<Response> {\n if (isIntelligenceRuntime(runtime)) {\n try {\n const url = new URL(request.url);\n const includeInvalidated =\n url.searchParams.get(\"includeInvalidated\") === \"true\";\n\n const access = await resolveClientMemory(runtime, request);\n if (isHandlerResponse(access)) return access;\n\n const data = await runtime.intelligence.listMemories({\n userId: access.user.id,\n ...(runtime.memory ? { memoryGrant: access.grant } : {}),\n ...(includeInvalidated ? { includeInvalidated: true } : {}),\n });\n\n // The client memory store consumes the `{ memories: [...] }` envelope\n // directly. Assert the shape before forwarding so a platform contract\n // violation surfaces as a clear 502 (the runtime is healthy but its\n // dependency returned the wrong shape) instead of a 200 the client will\n // choke on.\n if (\n data == null ||\n typeof data !== \"object\" ||\n !Array.isArray((data as { memories?: unknown }).memories)\n ) {\n logger.error(\n { data },\n \"listMemories: platform returned a response without a `memories` array\",\n );\n return errorResponse(\n \"Memory platform returned an invalid list response\",\n 502,\n );\n }\n\n return Response.json(data);\n } catch (error) {\n logger.error({ err: error }, \"Error listing memories\");\n return memoryErrorResponse(error, \"Failed to list memories\");\n }\n }\n\n return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n}\n\n/**\n * Semantically recalls the resolved user's memories via the platform (`POST\n * /api/memories/recall`, hybrid RAG). Mirrors {@link handleListMemories}:\n * requires a `CopilotKitIntelligence` runtime, resolves the user with\n * `identifyUser` (never a client-supplied id), proxies with the project API\n * key + resolved user. Body `{ query, limit?, scope? }`; response `{ memories }`,\n * each optionally carrying `score`.\n */\nexport async function handleRecallMemories({\n runtime,\n request,\n}: MemoriesHandlerParams): Promise<Response> {\n if (!isIntelligenceRuntime(runtime)) {\n return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n }\n try {\n const body = await parseJsonBody(request);\n if (isHandlerResponse(body)) return body;\n const fields = parseRecallBody(body);\n if (isHandlerResponse(fields)) return fields;\n\n const access = await resolveClientMemory(runtime, request);\n if (isHandlerResponse(access)) return access;\n\n const data = await runtime.intelligence.recallMemories({\n userId: access.user.id,\n ...(runtime.memory ? { memoryGrant: access.grant } : {}),\n ...fields,\n });\n\n if (\n data == null ||\n typeof data !== \"object\" ||\n !Array.isArray((data as { memories?: unknown }).memories)\n ) {\n logger.error(\n { data },\n \"recallMemories: platform returned a response without a `memories` array\",\n );\n return errorResponse(\n \"Memory platform returned an invalid recall response\",\n 502,\n );\n }\n return Response.json(data);\n } catch (error) {\n logger.error({ err: error }, \"Error recalling memories\");\n return memoryErrorResponse(error, \"Failed to recall memories\");\n }\n}\n\n/**\n * Mints memory-realtime join credentials (platform `POST\n * /api/memories/subscribe`). Mirrors {@link handleSubscribeToThreads}: requires\n * a `CopilotKitIntelligence` runtime and resolves the user with `identifyUser`\n * (never a client-supplied id). Returns `{ joinToken, joinCode }` — memory needs\n * the `joinCode` here (unlike threads, where it rides the thread-list response)\n * because the client builds the `user_meta:memories:<joinCode>` channel topic\n * from it.\n *\n * When the platform also resolves a project scope, the response additionally\n * carries `projectJoinToken` / `projectJoinCode`, which the client uses to open\n * a second `project_meta:memories:<projectJoinCode>` channel. These are\n * optional: absent project scope → both fields are omitted (silent-degrade\n * contract; the client opens only the user channel).\n */\nexport async function handleSubscribeToMemories({\n runtime,\n request,\n}: MemoriesHandlerParams): Promise<Response> {\n if (isIntelligenceRuntime(runtime)) {\n try {\n const access = await resolveClientMemory(runtime, request);\n if (isHandlerResponse(access)) return access;\n\n const credentials = await runtime.intelligence.ɵsubscribeToMemories({\n userId: access.user.id,\n ...(runtime.memory ? { memoryGrant: access.grant } : {}),\n });\n\n return Response.json({\n ...(credentials.joinToken !== undefined\n ? { joinToken: credentials.joinToken }\n : {}),\n ...(credentials.joinCode !== undefined\n ? { joinCode: credentials.joinCode }\n : {}),\n // Project-scoped credentials ride along only when the platform minted\n // them; omit both when absent (silent-degrade contract).\n ...(credentials.projectJoinToken !== undefined\n ? { projectJoinToken: credentials.projectJoinToken }\n : {}),\n ...(credentials.projectJoinCode !== undefined\n ? { projectJoinCode: credentials.projectJoinCode }\n : {}),\n });\n } catch (error) {\n logger.error({ err: error }, \"Error subscribing to memories\");\n return memoryErrorResponse(error, \"Failed to subscribe to memories\");\n }\n }\n\n return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n}\n\n/**\n * Creates a memory for the resolved user (platform `POST /api/memories`).\n * Identity comes from `identifyUser`, never the request body. Returns 201\n * with the stored memory (the client store applies it server-authoritatively).\n */\nexport async function handleCreateMemory({\n runtime,\n request,\n}: MemoriesHandlerParams): Promise<Response> {\n if (!isIntelligenceRuntime(runtime)) {\n return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n }\n try {\n const body = await parseJsonBody(request);\n if (isHandlerResponse(body)) return body;\n const fields = parseMemoryBody(body);\n if (isHandlerResponse(fields)) return fields;\n\n const access = await resolveClientMemory(runtime, request);\n if (isHandlerResponse(access)) return access;\n\n const data = await runtime.intelligence.createMemory({\n userId: access.user.id,\n ...(runtime.memory ? { memoryGrant: access.grant } : {}),\n ...fields,\n });\n return Response.json(data, { status: 201 });\n } catch (error) {\n logger.error({ err: error }, \"Error creating memory\");\n return memoryErrorResponse(error, \"Failed to create memory\");\n }\n}\n\n/**\n * Supersedes a memory (platform `PATCH /api/memories/:id`): retires `:id` and\n * inserts the new content atomically; the response carries `retiredId`.\n */\nexport async function handleUpdateMemory({\n runtime,\n request,\n memoryId,\n}: MemoryMutationParams): Promise<Response> {\n if (!isIntelligenceRuntime(runtime)) {\n return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n }\n try {\n const body = await parseJsonBody(request);\n if (isHandlerResponse(body)) return body;\n const fields = parseMemoryBody(body);\n if (isHandlerResponse(fields)) return fields;\n\n const access = await resolveClientMemory(runtime, request);\n if (isHandlerResponse(access)) return access;\n\n const data = await runtime.intelligence.updateMemory({\n userId: access.user.id,\n ...(runtime.memory ? { memoryGrant: access.grant } : {}),\n id: memoryId,\n ...fields,\n });\n return Response.json(data);\n } catch (error) {\n logger.error({ err: error }, \"Error updating memory\");\n return memoryErrorResponse(error, \"Failed to update memory\");\n }\n}\n\n/**\n * Retires (forgets) a memory (platform `DELETE /api/memories/:id`). Non-lossy\n * on the platform side; returns 204.\n */\nexport async function handleRemoveMemory({\n runtime,\n request,\n memoryId,\n}: MemoryMutationParams): Promise<Response> {\n if (!isIntelligenceRuntime(runtime)) {\n return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n }\n try {\n const access = await resolveClientMemory(runtime, request);\n if (isHandlerResponse(access)) return access;\n\n await runtime.intelligence.removeMemory({\n userId: access.user.id,\n id: memoryId,\n ...(runtime.memory ? { memoryGrant: access.grant } : {}),\n });\n return new Response(null, { status: 204 });\n } catch (error) {\n logger.error({ err: error }, \"Error removing memory\");\n return memoryErrorResponse(error, \"Failed to remove memory\");\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"memories.mjs","names":[],"sources":["../../../../../src/v2/runtime/handlers/intelligence/memories.ts"],"sourcesContent":["import type {\n CopilotIntelligenceRuntimeLike,\n CopilotRuntimeLike,\n} from \"../../core/runtime\";\nimport { isIntelligenceRuntime } from \"../../core/runtime\";\nimport { logger } from \"@copilotkit/shared\";\nimport { errorResponse, isHandlerResponse } from \"../shared/json-response\";\nimport { resolveIntelligenceUser } from \"../shared/resolve-intelligence-user\";\nimport { grantAllowsMemory, resolveWebMemory } from \"../shared/memory-policy\";\nimport { PlatformRequestError } from \"../../intelligence-platform/client\";\n\ninterface MemoriesHandlerParams {\n runtime: CopilotRuntimeLike;\n request: Request;\n}\n\ninterface MemoryMutationParams extends MemoriesHandlerParams {\n memoryId: string;\n}\n\nasync function resolveClientMemory(\n runtime: CopilotIntelligenceRuntimeLike,\n request: Request,\n) {\n const user = await resolveIntelligenceUser({ runtime, request });\n if (isHandlerResponse(user)) return user;\n const access = await resolveWebMemory(runtime, request, user, \"client\");\n if (isHandlerResponse(access)) return access;\n // Unlike an agent run — which proceeds without Memory tools when the policy\n // grants nothing — these routes exist ONLY to serve memories. A caller who\n // asked for them and may not have them gets 403; an empty list would imply\n // there are none, which is a different and false claim.\n if (runtime.memory && !grantAllowsMemory(access.grant)) {\n return errorResponse(\"Memory access denied\", 403);\n }\n return access;\n}\n\nconst MISSING_INTELLIGENCE_MESSAGE =\n \"Missing CopilotKitIntelligence configuration. Memory operations require a CopilotKitIntelligence instance to be provided in CopilotRuntime options.\";\n\n/** Allowed `kind` vocabulary the platform's memory endpoints accept. */\nconst MEMORY_KINDS: ReadonlySet<string> = new Set([\n \"topical\",\n \"episodic\",\n \"operational\",\n]);\n/** Allowed `scope` vocabulary the platform's memory endpoints accept. */\nconst MEMORY_SCOPES: ReadonlySet<string> = new Set([\"user\", \"project\"]);\n\n/**\n * Maps a thrown error to a `Response`.\n *\n * For a {@link PlatformRequestError}, forward only client-actionable **4xx**\n * statuses verbatim (e.g. 404 missing/wrong-scope memory, 409 conflict, 422\n * unprocessable) so a `useMemories` consumer can branch on them — a flat 500\n * would erase that distinction. A platform **5xx** (or any non-4xx / malformed\n * status) means the runtime is healthy but its dependency failed, so it surfaces\n * as `502 Bad Gateway` rather than echoing the upstream status as if the runtime\n * itself broke — and this also avoids a `new Response(..., { status })`\n * `RangeError` on an out-of-range status. Non-platform throws stay 500.\n */\nfunction memoryErrorResponse(error: unknown, message: string): Response {\n if (error instanceof PlatformRequestError) {\n const { status } = error;\n if (Number.isInteger(status) && status >= 400 && status <= 499) {\n return errorResponse(message, status);\n }\n return errorResponse(message, 502);\n }\n return errorResponse(message, 500);\n}\n\nasync function parseJsonBody(\n request: Request,\n): Promise<Record<string, unknown> | Response> {\n try {\n return (await request.json()) as Record<string, unknown>;\n } catch (error) {\n logger.error({ err: error }, \"Malformed JSON in memory request body\");\n return errorResponse(\"Invalid request body\", 400);\n }\n}\n\n/**\n * Extracts and validates the create/supersede body fields the platform's\n * memory endpoints require. Returns a `Response` (400) on invalid input.\n */\nfunction parseMemoryBody(body: Record<string, unknown>):\n | {\n content: string;\n kind: string;\n scope?: string;\n sourceThreadIds?: string[];\n }\n | Response {\n const { content, kind, scope, sourceThreadIds } = body;\n if (typeof content !== \"string\" || typeof kind !== \"string\") {\n return errorResponse(\"Memory requires string `content` and `kind`\", 400);\n }\n // `kind` must be one of the platform's known kinds. Reject an out-of-vocabulary\n // value here rather than forwarding it for the platform to reject.\n if (!MEMORY_KINDS.has(kind)) {\n return errorResponse(\n \"Memory `kind` must be one of: topical, episodic, operational\",\n 400,\n );\n }\n // `scope` is optional: when omitted the platform applies its default\n // (`\"user\"`). Only reject a present-but-wrong-typed scope.\n if (scope !== undefined && typeof scope !== \"string\") {\n return errorResponse(\"Memory `scope` must be a string when provided\", 400);\n }\n // When `scope` is present, it must be one of the known scopes.\n if (typeof scope === \"string\" && !MEMORY_SCOPES.has(scope)) {\n return errorResponse(\"Memory `scope` must be one of: user, project\", 400);\n }\n // `sourceThreadIds` is optional, but when present it must be a string array.\n // Validate every element so non-string ids are not forwarded to the platform.\n if (\n sourceThreadIds !== undefined &&\n (!Array.isArray(sourceThreadIds) ||\n !sourceThreadIds.every((id) => typeof id === \"string\"))\n ) {\n return errorResponse(\n \"Memory `sourceThreadIds` must be an array of strings when provided\",\n 400,\n );\n }\n return {\n content,\n kind,\n ...(typeof scope === \"string\" ? { scope } : {}),\n ...(Array.isArray(sourceThreadIds)\n ? { sourceThreadIds: sourceThreadIds as string[] }\n : {}),\n // `sourceThreadIds` elements are validated as strings above; the cast is safe.\n };\n}\n\n/**\n * Validates the recall body: `query` required non-empty string (trimmed);\n * `limit` optional finite positive integer; `scope` optional and in the known\n * scopes. Returns a 400 Response on invalid input. The returned `query` is the\n * trimmed value so a whitespace-padded query is never forwarded to the platform.\n */\nfunction parseRecallBody(\n body: Record<string, unknown>,\n): { query: string; limit?: number; scope?: string } | Response {\n const { query, limit, scope } = body;\n // Trim before the emptiness check so whitespace-only queries (e.g. \" \")\n // are rejected rather than forwarded as a useless query to the platform.\n const trimmedQuery = typeof query === \"string\" ? query.trim() : query;\n if (typeof trimmedQuery !== \"string\" || trimmedQuery.length === 0) {\n return errorResponse(\"Recall requires a non-empty string `query`\", 400);\n }\n // When provided, `limit` must be a finite positive integer. `Number.isInteger`\n // already rejects NaN, Infinity, and fractions (NaN/Infinity would otherwise\n // JSON-serialize to `null` and silently corrupt the forwarded request);\n // the `> 0` guard rejects zero and negatives.\n if (\n limit !== undefined &&\n !(typeof limit === \"number\" && Number.isInteger(limit) && limit > 0)\n ) {\n return errorResponse(\"Recall `limit` must be a positive integer\", 400);\n }\n if (scope !== undefined && typeof scope !== \"string\") {\n return errorResponse(\"Recall `scope` must be a string when provided\", 400);\n }\n if (typeof scope === \"string\" && !MEMORY_SCOPES.has(scope)) {\n return errorResponse(\"Recall `scope` must be one of: user, project\", 400);\n }\n return {\n query: trimmedQuery,\n ...(typeof limit === \"number\" ? { limit } : {}),\n ...(typeof scope === \"string\" ? { scope } : {}),\n };\n}\n\n/**\n * Lists the resolved user's long-term memories via CopilotKit Intelligence.\n *\n * Mirrors {@link handleListThreads}: requires a `CopilotKitIntelligence`\n * runtime, resolves the user with `identifyUser` (never trusting a\n * client-supplied id), and proxies to the platform's `GET /api/memories`\n * with the project API key + resolved user. The `?includeInvalidated=true`\n * query is forwarded so callers can opt into retired rows. The response is\n * the platform's `{ memories }` envelope, which the client memory store\n * consumes directly.\n */\nexport async function handleListMemories({\n runtime,\n request,\n}: MemoriesHandlerParams): Promise<Response> {\n if (isIntelligenceRuntime(runtime)) {\n try {\n const url = new URL(request.url);\n const includeInvalidated =\n url.searchParams.get(\"includeInvalidated\") === \"true\";\n\n const access = await resolveClientMemory(runtime, request);\n if (isHandlerResponse(access)) return access;\n\n const data = await runtime.intelligence.listMemories({\n userId: access.user.id,\n ...(runtime.memory ? { memoryGrant: access.grant } : {}),\n ...(includeInvalidated ? { includeInvalidated: true } : {}),\n });\n\n // The client memory store consumes the `{ memories: [...] }` envelope\n // directly. Assert the shape before forwarding so a platform contract\n // violation surfaces as a clear 502 (the runtime is healthy but its\n // dependency returned the wrong shape) instead of a 200 the client will\n // choke on.\n if (\n data == null ||\n typeof data !== \"object\" ||\n !Array.isArray((data as { memories?: unknown }).memories)\n ) {\n logger.error(\n { data },\n \"listMemories: platform returned a response without a `memories` array\",\n );\n return errorResponse(\n \"Memory platform returned an invalid list response\",\n 502,\n );\n }\n\n return Response.json(data);\n } catch (error) {\n logger.error({ err: error }, \"Error listing memories\");\n return memoryErrorResponse(error, \"Failed to list memories\");\n }\n }\n\n return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n}\n\n/**\n * Semantically recalls the resolved user's memories via the platform (`POST\n * /api/memories/recall`, hybrid RAG). Mirrors {@link handleListMemories}:\n * requires a `CopilotKitIntelligence` runtime, resolves the user with\n * `identifyUser` (never a client-supplied id), proxies with the project API\n * key + resolved user. Body `{ query, limit?, scope? }`; response `{ memories }`,\n * each optionally carrying `score`.\n */\nexport async function handleRecallMemories({\n runtime,\n request,\n}: MemoriesHandlerParams): Promise<Response> {\n if (!isIntelligenceRuntime(runtime)) {\n return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n }\n try {\n const body = await parseJsonBody(request);\n if (isHandlerResponse(body)) return body;\n const fields = parseRecallBody(body);\n if (isHandlerResponse(fields)) return fields;\n\n const access = await resolveClientMemory(runtime, request);\n if (isHandlerResponse(access)) return access;\n\n const data = await runtime.intelligence.recallMemories({\n userId: access.user.id,\n ...(runtime.memory ? { memoryGrant: access.grant } : {}),\n ...fields,\n });\n\n if (\n data == null ||\n typeof data !== \"object\" ||\n !Array.isArray((data as { memories?: unknown }).memories)\n ) {\n logger.error(\n { data },\n \"recallMemories: platform returned a response without a `memories` array\",\n );\n return errorResponse(\n \"Memory platform returned an invalid recall response\",\n 502,\n );\n }\n return Response.json(data);\n } catch (error) {\n logger.error({ err: error }, \"Error recalling memories\");\n return memoryErrorResponse(error, \"Failed to recall memories\");\n }\n}\n\n/**\n * Mints memory-realtime join credentials (platform `POST\n * /api/memories/subscribe`). Mirrors {@link handleSubscribeToThreads}: requires\n * a `CopilotKitIntelligence` runtime and resolves the user with `identifyUser`\n * (never a client-supplied id). Returns `{ joinToken, joinCode }` — memory needs\n * the `joinCode` here (unlike threads, where it rides the thread-list response)\n * because the client builds the `user_meta:memories:<joinCode>` channel topic\n * from it.\n *\n * When the platform also resolves a project scope, the response additionally\n * carries `projectJoinToken` / `projectJoinCode`, which the client uses to open\n * a second `project_meta:memories:<projectJoinCode>` channel. These are\n * optional: absent project scope → both fields are omitted (silent-degrade\n * contract; the client opens only the user channel).\n */\nexport async function handleSubscribeToMemories({\n runtime,\n request,\n}: MemoriesHandlerParams): Promise<Response> {\n if (isIntelligenceRuntime(runtime)) {\n try {\n const access = await resolveClientMemory(runtime, request);\n if (isHandlerResponse(access)) return access;\n\n const credentials = await runtime.intelligence.ɵsubscribeToMemories({\n userId: access.user.id,\n ...(runtime.memory ? { memoryGrant: access.grant } : {}),\n });\n\n return Response.json({\n ...(credentials.joinToken !== undefined\n ? { joinToken: credentials.joinToken }\n : {}),\n ...(credentials.joinCode !== undefined\n ? { joinCode: credentials.joinCode }\n : {}),\n // Project-scoped credentials ride along only when the platform minted\n // them; omit both when absent (silent-degrade contract).\n ...(credentials.projectJoinToken !== undefined\n ? { projectJoinToken: credentials.projectJoinToken }\n : {}),\n ...(credentials.projectJoinCode !== undefined\n ? { projectJoinCode: credentials.projectJoinCode }\n : {}),\n });\n } catch (error) {\n logger.error({ err: error }, \"Error subscribing to memories\");\n return memoryErrorResponse(error, \"Failed to subscribe to memories\");\n }\n }\n\n return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n}\n\n/**\n * Creates a memory for the resolved user (platform `POST /api/memories`).\n * Identity comes from `identifyUser`, never the request body. Returns 201\n * with the stored memory (the client store applies it server-authoritatively).\n */\nexport async function handleCreateMemory({\n runtime,\n request,\n}: MemoriesHandlerParams): Promise<Response> {\n if (!isIntelligenceRuntime(runtime)) {\n return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n }\n try {\n const body = await parseJsonBody(request);\n if (isHandlerResponse(body)) return body;\n const fields = parseMemoryBody(body);\n if (isHandlerResponse(fields)) return fields;\n\n const access = await resolveClientMemory(runtime, request);\n if (isHandlerResponse(access)) return access;\n\n const data = await runtime.intelligence.createMemory({\n userId: access.user.id,\n ...(runtime.memory ? { memoryGrant: access.grant } : {}),\n ...fields,\n });\n return Response.json(data, { status: 201 });\n } catch (error) {\n logger.error({ err: error }, \"Error creating memory\");\n return memoryErrorResponse(error, \"Failed to create memory\");\n }\n}\n\n/**\n * Supersedes a memory (platform `PATCH /api/memories/:id`): retires `:id` and\n * inserts the new content atomically; the response carries `retiredId`.\n */\nexport async function handleUpdateMemory({\n runtime,\n request,\n memoryId,\n}: MemoryMutationParams): Promise<Response> {\n if (!isIntelligenceRuntime(runtime)) {\n return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n }\n try {\n const body = await parseJsonBody(request);\n if (isHandlerResponse(body)) return body;\n const fields = parseMemoryBody(body);\n if (isHandlerResponse(fields)) return fields;\n\n const access = await resolveClientMemory(runtime, request);\n if (isHandlerResponse(access)) return access;\n\n const data = await runtime.intelligence.updateMemory({\n userId: access.user.id,\n ...(runtime.memory ? { memoryGrant: access.grant } : {}),\n id: memoryId,\n ...fields,\n });\n return Response.json(data);\n } catch (error) {\n logger.error({ err: error }, \"Error updating memory\");\n return memoryErrorResponse(error, \"Failed to update memory\");\n }\n}\n\n/**\n * Retires (forgets) a memory (platform `DELETE /api/memories/:id`). Non-lossy\n * on the platform side; returns 204.\n */\nexport async function handleRemoveMemory({\n runtime,\n request,\n memoryId,\n}: MemoryMutationParams): Promise<Response> {\n if (!isIntelligenceRuntime(runtime)) {\n return errorResponse(MISSING_INTELLIGENCE_MESSAGE, 422);\n }\n try {\n const access = await resolveClientMemory(runtime, request);\n if (isHandlerResponse(access)) return access;\n\n await runtime.intelligence.removeMemory({\n userId: access.user.id,\n id: memoryId,\n ...(runtime.memory ? { memoryGrant: access.grant } : {}),\n });\n return new Response(null, { status: 204 });\n } catch (error) {\n logger.error({ err: error }, \"Error removing memory\");\n return memoryErrorResponse(error, \"Failed to remove memory\");\n }\n}\n"],"mappings":"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"}
|
|
@@ -55,7 +55,7 @@ async function generateThreadNameForNewThread({ runtime, request, agentId, sourc
|
|
|
55
55
|
threadId: thread.id,
|
|
56
56
|
userId,
|
|
57
57
|
agentId,
|
|
58
|
-
updates: { name: generatedTitle ??
|
|
58
|
+
updates: { name: generatedTitle ?? deriveFallbackTitleFromMessages(sourceInput.messages) }
|
|
59
59
|
});
|
|
60
60
|
}
|
|
61
61
|
async function runTitleGenerationAttempt(params) {
|
|
@@ -132,12 +132,26 @@ function normalizeGeneratedTitle(rawTitle) {
|
|
|
132
132
|
} catch {
|
|
133
133
|
if (jsonLike) return null;
|
|
134
134
|
}
|
|
135
|
-
candidate = candidate
|
|
135
|
+
candidate = cleanupTitleText(candidate);
|
|
136
136
|
if (!candidate) return null;
|
|
137
137
|
if (candidate.length > MAX_TITLE_LENGTH) candidate = candidate.slice(0, MAX_TITLE_LENGTH).trim();
|
|
138
138
|
if (candidate.split(/\s+/).length > MAX_TITLE_WORDS) return null;
|
|
139
139
|
return candidate;
|
|
140
140
|
}
|
|
141
|
+
function cleanupTitleText(text) {
|
|
142
|
+
return text.replace(/^["'`]+|["'`]+$/g, "").replace(/[*_#[\]()!~>|]+/g, "").replace(/[.!?,;:]+$/g, "").replace(/\s+/g, " ").trim();
|
|
143
|
+
}
|
|
144
|
+
function deriveFallbackTitleFromMessages(messages) {
|
|
145
|
+
for (const message of messages ?? []) {
|
|
146
|
+
if (message.role !== "user") continue;
|
|
147
|
+
const cleaned = cleanupTitleText(stringifyMessageContent(message.content));
|
|
148
|
+
if (!cleaned) continue;
|
|
149
|
+
let title = cleaned.split(/\s+/).slice(0, MAX_TITLE_WORDS).join(" ");
|
|
150
|
+
if (title.length > MAX_TITLE_LENGTH) title = title.slice(0, MAX_TITLE_LENGTH).trim();
|
|
151
|
+
return title || FALLBACK_THREAD_TITLE;
|
|
152
|
+
}
|
|
153
|
+
return FALLBACK_THREAD_TITLE;
|
|
154
|
+
}
|
|
141
155
|
function selectGeneratedTitleFromMessages(messages) {
|
|
142
156
|
for (let index = messages.length - 1; index >= 0; index--) {
|
|
143
157
|
const message = messages[index];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"thread-names.cjs","names":["cloneAgentForRequest","isHandlerResponse"],"sources":["../../../../../src/v2/runtime/handlers/intelligence/thread-names.ts"],"sourcesContent":["import type { Message, RunAgentInput } from \"@ag-ui/client\";\nimport { AbstractAgent } from \"@ag-ui/client\";\nimport { logger } from \"@copilotkit/shared\";\nimport { randomUUID } from \"node:crypto\";\nimport type { CopilotIntelligenceRuntimeLike } from \"../../core/runtime\";\nimport {\n cloneAgentForRequest,\n configureAgentForRequest,\n} from \"../shared/agent-utils\";\nimport type { ThreadSummary } from \"../../intelligence-platform\";\nimport { isHandlerResponse } from \"../shared/json-response\";\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, request);\n if (isHandlerResponse(agent)) {\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 = randomUUID();\n // Messages and state are picked up from the agent itself (set above);\n // RunAgentParameters no longer accepts them directly.\n const { newMessages } = await agent.runAgent({\n tools: [],\n context: [],\n forwardedProps: {},\n });\n\n return selectGeneratedTitleFromMessages(newMessages);\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 \"Conversation:\",\n transcript.join(\"\\n\"),\n 'Generate a short title for the conversation above. Return JSON only in this exact shape: {\"title\":\"...\"}. Do not answer the conversation.',\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 const jsonLike = isJsonLike(candidate);\n\n try {\n const parsed = JSON.parse(candidate) as { title?: unknown };\n if (typeof parsed.title === \"string\") {\n candidate = parsed.title;\n } else if (jsonLike) {\n return null;\n }\n } catch {\n if (jsonLike) {\n return null;\n }\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 selectGeneratedTitleFromMessages(messages: Message[]): string | null {\n for (let index = messages.length - 1; index >= 0; index--) {\n const message = messages[index];\n if (message.role !== \"assistant\" || typeof message.content !== \"string\") {\n continue;\n }\n\n const title = normalizeGeneratedTitle(message.content);\n if (title) {\n return title;\n }\n }\n\n return null;\n}\n\nfunction isJsonLike(candidate: string): boolean {\n return (\n (candidate.startsWith(\"{\") && candidate.endsWith(\"}\")) ||\n (candidate.startsWith(\"[\") && candidate.endsWith(\"]\"))\n );\n}\n\nfunction hasThreadName(name: string | null | undefined): boolean {\n return typeof name === \"string\" && name.trim().length > 0;\n}\n\n/** @internal Exported for testing only. */\nexport const ɵnormalizeGeneratedTitle = normalizeGeneratedTitle;\n/** @internal Exported for testing only. */\nexport const ɵselectGeneratedTitleFromMessages =\n selectGeneratedTitleFromMessages;\n/** @internal Exported for testing only. */\nexport const ɵbuildThreadTitlePrompt = buildThreadTitlePrompt;\n/** @internal Exported for testing only. */\nexport const ɵhasThreadName = hasThreadName;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"thread-names.cjs","names":["cloneAgentForRequest","isHandlerResponse"],"sources":["../../../../../src/v2/runtime/handlers/intelligence/thread-names.ts"],"sourcesContent":["import type { Message, RunAgentInput } from \"@ag-ui/client\";\nimport { logger } from \"@copilotkit/shared\";\nimport { randomUUID } from \"node:crypto\";\nimport type { CopilotIntelligenceRuntimeLike } from \"../../core/runtime\";\nimport {\n cloneAgentForRequest,\n configureAgentForRequest,\n} from \"../shared/agent-utils\";\nimport type { ThreadSummary } from \"../../intelligence-platform\";\nimport { isHandlerResponse } from \"../shared/json-response\";\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: {\n name:\n generatedTitle ?? deriveFallbackTitleFromMessages(sourceInput.messages),\n },\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, request);\n if (isHandlerResponse(agent)) {\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 = randomUUID();\n // Messages and state are picked up from the agent itself (set above);\n // RunAgentParameters no longer accepts them directly.\n const { newMessages } = await agent.runAgent({\n tools: [],\n context: [],\n forwardedProps: {},\n });\n\n return selectGeneratedTitleFromMessages(newMessages);\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 \"Conversation:\",\n transcript.join(\"\\n\"),\n 'Generate a short title for the conversation above. Return JSON only in this exact shape: {\"title\":\"...\"}. Do not answer the conversation.',\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 const jsonLike = isJsonLike(candidate);\n\n try {\n const parsed = JSON.parse(candidate) as { title?: unknown };\n if (typeof parsed.title === \"string\") {\n candidate = parsed.title;\n } else if (jsonLike) {\n return null;\n }\n } catch {\n if (jsonLike) {\n return null;\n }\n }\n\n candidate = cleanupTitleText(candidate);\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 cleanupTitleText(text: string): string {\n return text\n .replace(/^[\"'`]+|[\"'`]+$/g, \"\")\n .replace(/[*_#[\\]()!~>|]+/g, \"\")\n .replace(/[.!?,;:]+$/g, \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\nfunction deriveFallbackTitleFromMessages(\n messages: Message[] | undefined,\n): string {\n for (const message of messages ?? []) {\n if (message.role !== \"user\") {\n continue;\n }\n\n const cleaned = cleanupTitleText(stringifyMessageContent(message.content));\n if (!cleaned) {\n continue;\n }\n\n let title = cleaned.split(/\\s+/).slice(0, MAX_TITLE_WORDS).join(\" \");\n if (title.length > MAX_TITLE_LENGTH) {\n title = title.slice(0, MAX_TITLE_LENGTH).trim();\n }\n\n return title || FALLBACK_THREAD_TITLE;\n }\n\n return FALLBACK_THREAD_TITLE;\n}\n\nfunction selectGeneratedTitleFromMessages(messages: Message[]): string | null {\n for (let index = messages.length - 1; index >= 0; index--) {\n const message = messages[index];\n if (message.role !== \"assistant\" || typeof message.content !== \"string\") {\n continue;\n }\n\n const title = normalizeGeneratedTitle(message.content);\n if (title) {\n return title;\n }\n }\n\n return null;\n}\n\nfunction isJsonLike(candidate: string): boolean {\n return (\n (candidate.startsWith(\"{\") && candidate.endsWith(\"}\")) ||\n (candidate.startsWith(\"[\") && candidate.endsWith(\"]\"))\n );\n}\n\nfunction hasThreadName(name: string | null | undefined): boolean {\n return typeof name === \"string\" && name.trim().length > 0;\n}\n\n/** @internal Exported for testing only. */\nexport const ɵnormalizeGeneratedTitle = normalizeGeneratedTitle;\n/** @internal Exported for testing only. */\nexport const ɵselectGeneratedTitleFromMessages =\n selectGeneratedTitleFromMessages;\n/** @internal Exported for testing only. */\nexport const ɵbuildThreadTitlePrompt = buildThreadTitlePrompt;\n/** @internal Exported for testing only. */\nexport const ɵhasThreadName = hasThreadName;\n"],"mappings":"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"}
|