@copilotkit/channels-core 0.9.3 → 0.11.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/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/single-string-parameter-schema.test.d.ts +2 -0
- package/dist/single-string-parameter-schema.test.d.ts.map +1 -0
- package/dist/single-string-parameter-schema.test.js +183 -0
- package/dist/standard-schema.d.ts +77 -2
- package/dist/standard-schema.d.ts.map +1 -1
- package/dist/standard-schema.js +127 -2
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -23,6 +23,8 @@ export { Transcripts } from "./transcripts.js";
|
|
|
23
23
|
export type { TranscriptEntry, TranscriptsConfig } from "./transcripts.js";
|
|
24
24
|
export { toAgentToolDescriptors, parseToolArgs, stringifyHandlerResult, defineChannelTool, } from "./tools.js";
|
|
25
25
|
export type { ChannelTool, ObjectSchema, ChannelToolContext, ContextEntry, AgentToolDescriptor, } from "./tools.js";
|
|
26
|
+
export { singleStringParameterSchema } from "./standard-schema.js";
|
|
27
|
+
export type { SingleStringParameterSchema } from "./standard-schema.js";
|
|
26
28
|
export { mintId, stableStringify } from "./mint-id.js";
|
|
27
29
|
export { runAgentLoop } from "./run-loop.js";
|
|
28
30
|
export type { RunLoopArgs } from "./run-loop.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EACL,oBAAoB,EACpB,yBAAyB,GAC1B,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAGtE,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,YAAY,EACV,OAAO,EACP,oBAAoB,EACpB,wBAAwB,EACxB,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,WAAW,EACX,oBAAoB,EACpB,kBAAkB,EAClB,cAAc,EACd,gBAAgB,EAChB,4BAA4B,GAC7B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,YAAY,EACV,0BAA0B,EAC1B,wBAAwB,EACxB,6BAA6B,GAC9B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,oBAAoB,EACpB,8BAA8B,EAC9B,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,oBAAoB,EACpB,mBAAmB,EACnB,YAAY,EACZ,mBAAmB,EACnB,sBAAsB,EACtB,mBAAmB,EACnB,aAAa,EACb,sBAAsB,GACvB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG9C,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,WAAW,EACX,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,WAAW,EACX,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,yBAAyB,EACzB,sBAAsB,EACtB,oBAAoB,EACpB,SAAS,EACT,aAAa,GACd,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,GACd,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,cAAc,EACd,cAAc,EACd,WAAW,GACZ,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,YAAY,EACV,WAAW,EACX,cAAc,EACd,yBAAyB,EACzB,yBAAyB,EACzB,2BAA2B,EAC3B,0BAA0B,GAC3B,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,cAAc,EACd,+BAA+B,EAC/B,kBAAkB,GACnB,MAAM,sBAAsB,CAAC;AAG9B,YAAY,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAMtD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,kCAAkC,EAAE,MAAM,qCAAqC,CAAC;AAGzF,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAG3E,OAAO,EACL,sBAAsB,EACtB,aAAa,EACb,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,WAAW,EACX,YAAY,EACZ,kBAAkB,EAClB,YAAY,EACZ,mBAAmB,GACpB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -30,6 +30,10 @@ export { createStateBackedConversationStore } from "./state/state-conversation-s
|
|
|
30
30
|
export { Transcripts } from "./transcripts.js";
|
|
31
31
|
// Tools & context
|
|
32
32
|
export { toAgentToolDescriptors, parseToolArgs, stringifyHandlerResult, defineChannelTool, } from "./tools.js";
|
|
33
|
+
// Parameter-schema builder for the `lookup_<platform>_user` tool every
|
|
34
|
+
// adapter ships. Lets an adapter describe a one-string parameter without
|
|
35
|
+
// declaring `zod` (PE-30) — see `standard-schema.ts` for why that matters.
|
|
36
|
+
export { singleStringParameterSchema } from "./standard-schema.js";
|
|
33
37
|
// Id / serialization helpers
|
|
34
38
|
export { mintId, stableStringify } from "./mint-id.js";
|
|
35
39
|
// Run loop
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"single-string-parameter-schema.test.d.ts","sourceRoot":"","sources":["../src/single-string-parameter-schema.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `singleStringParameterSchema` replaces the `z.object({query: z.string()
|
|
3
|
+
* .min(1).describe(...)})` that every platform adapter used to build its
|
|
4
|
+
* `lookup_<platform>_user` parameter with, so that no adapter declares a
|
|
5
|
+
* `zod` range (PE-30).
|
|
6
|
+
*
|
|
7
|
+
* The contract it has to honor is "behaves like the Zod object it replaces",
|
|
8
|
+
* so these tests assert against Zod itself rather than against a transcribed
|
|
9
|
+
* expectation. `zod` is a devDependency of this package; nothing published
|
|
10
|
+
* imports it.
|
|
11
|
+
*/
|
|
12
|
+
import { describe, it, expect } from "vitest";
|
|
13
|
+
import { z } from "zod";
|
|
14
|
+
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
15
|
+
import { singleStringParameterSchema } from "./standard-schema.js";
|
|
16
|
+
import { toJsonSchema, validateSchema } from "./standard-schema.js";
|
|
17
|
+
const DESCRIPTION = "Handle, display name, or first name of the person.";
|
|
18
|
+
const schema = singleStringParameterSchema({
|
|
19
|
+
name: "query",
|
|
20
|
+
description: DESCRIPTION,
|
|
21
|
+
});
|
|
22
|
+
/** The exact Zod object this helper is a drop-in replacement for. */
|
|
23
|
+
const zodEquivalent = z.object({
|
|
24
|
+
query: z.string().min(1).describe(DESCRIPTION),
|
|
25
|
+
});
|
|
26
|
+
describe("singleStringParameterSchema", () => {
|
|
27
|
+
it("emits the JSON Schema document the Zod object emits", () => {
|
|
28
|
+
expect(toJsonSchema(schema)).toEqual(zodToJsonSchema(zodEquivalent, { $refStrategy: "none" }));
|
|
29
|
+
});
|
|
30
|
+
it("names the field the caller asked for", () => {
|
|
31
|
+
const renamed = singleStringParameterSchema({
|
|
32
|
+
name: "handle",
|
|
33
|
+
description: DESCRIPTION,
|
|
34
|
+
});
|
|
35
|
+
const doc = toJsonSchema(renamed);
|
|
36
|
+
expect(Object.keys(doc.properties)).toEqual(["handle"]);
|
|
37
|
+
expect(doc.required).toEqual(["handle"]);
|
|
38
|
+
});
|
|
39
|
+
it("names this package as the vendor, not zod and not the caller", () => {
|
|
40
|
+
// The Standard Schema `vendor` names the library that produced the
|
|
41
|
+
// schema, which is `channels-core` whichever adapter calls the helper.
|
|
42
|
+
// It also has to not be "zod": `schemaToJsonSchema` routes a
|
|
43
|
+
// `vendor: "zod"` schema through `zod-to-json-schema`, and anything else
|
|
44
|
+
// must carry its own document.
|
|
45
|
+
expect(schema["~standard"].vendor).toBe("@copilotkit/channels-core");
|
|
46
|
+
const renamed = singleStringParameterSchema({
|
|
47
|
+
name: "handle",
|
|
48
|
+
description: DESCRIPTION,
|
|
49
|
+
});
|
|
50
|
+
expect(renamed["~standard"].vendor).toBe("@copilotkit/channels-core");
|
|
51
|
+
});
|
|
52
|
+
it("accepts a valid value, exactly as the Zod object does", async () => {
|
|
53
|
+
expect(await validateSchema(schema, { query: "ada" })).toEqual({
|
|
54
|
+
ok: true,
|
|
55
|
+
value: { query: "ada" },
|
|
56
|
+
});
|
|
57
|
+
expect(zodEquivalent.safeParse({ query: "ada" }).data).toEqual({
|
|
58
|
+
query: "ada",
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
it("strips unknown keys rather than rejecting them, as z.object does", async () => {
|
|
62
|
+
const input = { query: "ada", extra: "ignored" };
|
|
63
|
+
expect(await validateSchema(schema, input)).toEqual({
|
|
64
|
+
ok: true,
|
|
65
|
+
value: { query: "ada" },
|
|
66
|
+
});
|
|
67
|
+
// Pin the Zod behavior this mirrors, so a Zod default change is visible.
|
|
68
|
+
expect(zodEquivalent.safeParse(input).data).toEqual({ query: "ada" });
|
|
69
|
+
});
|
|
70
|
+
it("rejects a missing field and names it", async () => {
|
|
71
|
+
const r = await validateSchema(schema, {});
|
|
72
|
+
expect(r.ok).toBe(false);
|
|
73
|
+
expect(r.ok === false && r.error).toContain("query");
|
|
74
|
+
expect(zodEquivalent.safeParse({}).success).toBe(false);
|
|
75
|
+
});
|
|
76
|
+
it("rejects an empty string, which is what .min(1) guarded", async () => {
|
|
77
|
+
const r = await validateSchema(schema, { query: "" });
|
|
78
|
+
expect(r.ok).toBe(false);
|
|
79
|
+
expect(zodEquivalent.safeParse({ query: "" }).success).toBe(false);
|
|
80
|
+
});
|
|
81
|
+
it.each([
|
|
82
|
+
["a number", 42, "number"],
|
|
83
|
+
["null", null, "null"],
|
|
84
|
+
["an array", [], "array"],
|
|
85
|
+
])("rejects %s field, naming the received type", async (_label, value, received) => {
|
|
86
|
+
const r = await validateSchema(schema, { query: value });
|
|
87
|
+
expect(r.ok).toBe(false);
|
|
88
|
+
expect(r.ok === false && r.error).toContain(received);
|
|
89
|
+
});
|
|
90
|
+
it.each([
|
|
91
|
+
["null", null],
|
|
92
|
+
["an array", []],
|
|
93
|
+
["a string", "ada"],
|
|
94
|
+
])("rejects %s as the whole argument payload", async (_label, value) => {
|
|
95
|
+
const r = await validateSchema(schema, value);
|
|
96
|
+
expect(r.ok).toBe(false);
|
|
97
|
+
expect(zodEquivalent.safeParse(value).success).toBe(false);
|
|
98
|
+
});
|
|
99
|
+
/**
|
|
100
|
+
* The error string is what the agent reads back on a bad tool call, so it
|
|
101
|
+
* is part of the contract, not an implementation detail. Asserting only
|
|
102
|
+
* "both reject" let a real divergence through: a missing field reported
|
|
103
|
+
* "Expected string, received undefined" where Zod reports "Required".
|
|
104
|
+
* Compare the rendered text, formatted the same way `validateSchema` does.
|
|
105
|
+
*/
|
|
106
|
+
it.each([
|
|
107
|
+
["a missing field", {}],
|
|
108
|
+
["a number field", { query: 42 }],
|
|
109
|
+
["a null field", { query: null }],
|
|
110
|
+
["an array field", { query: [] }],
|
|
111
|
+
["a boolean field", { query: true }],
|
|
112
|
+
["an object field", { query: {} }],
|
|
113
|
+
["an explicit undefined field", { query: undefined }],
|
|
114
|
+
["an empty string", { query: "" }],
|
|
115
|
+
["null as the payload", null],
|
|
116
|
+
["an array as the payload", []],
|
|
117
|
+
["a string as the payload", "ada"],
|
|
118
|
+
["a number as the payload", 7],
|
|
119
|
+
])("renders the same error text as zod for %s", async (_label, value) => {
|
|
120
|
+
const mine = await validateSchema(schema, value);
|
|
121
|
+
const theirs = zodEquivalent.safeParse(value);
|
|
122
|
+
expect(mine.ok).toBe(theirs.success);
|
|
123
|
+
expect(theirs.success).toBe(false);
|
|
124
|
+
const zodText = theirs.success
|
|
125
|
+
? null
|
|
126
|
+
: theirs.error.issues
|
|
127
|
+
.map((i) => `${i.path.join(".") || "(root)"}: ${i.message}`)
|
|
128
|
+
.join("; ");
|
|
129
|
+
expect(mine.ok === false && mine.error).toBe(zodText);
|
|
130
|
+
});
|
|
131
|
+
/**
|
|
132
|
+
* `zodToJsonSchema` built a fresh document on every call and
|
|
133
|
+
* `toAgentToolDescriptors` hands its result straight to the caller, so a
|
|
134
|
+
* consumer that normalizes the schema in place (dropping `$schema` for a
|
|
135
|
+
* provider that rejects it, for instance) must not corrupt later turns.
|
|
136
|
+
*/
|
|
137
|
+
it("returns a fresh JSON Schema document on every call", () => {
|
|
138
|
+
const first = toJsonSchema(schema);
|
|
139
|
+
const second = toJsonSchema(schema);
|
|
140
|
+
expect(first).not.toBe(second);
|
|
141
|
+
expect(first).toEqual(second);
|
|
142
|
+
first.properties.query.description = "mutated by a consumer";
|
|
143
|
+
const third = toJsonSchema(schema);
|
|
144
|
+
expect(third.properties.query.description).toBe(DESCRIPTION);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
/**
|
|
148
|
+
* Type-level assertions. `check-types` runs `tsconfig.check.json`, which
|
|
149
|
+
* includes this file, so a `@ts-expect-error` here fails the build when the
|
|
150
|
+
* error it expects stops happening. Nothing below runs.
|
|
151
|
+
*
|
|
152
|
+
* The output type is built by mapping over `Name`. A union of names would
|
|
153
|
+
* claim every member is a present `string` while the function creates exactly
|
|
154
|
+
* one key, and a widened `string` would claim every possible key. Both promise
|
|
155
|
+
* a `string` where the value is `undefined`, so both have to be rejected at
|
|
156
|
+
* the call.
|
|
157
|
+
*/
|
|
158
|
+
describe("type-level contract", () => {
|
|
159
|
+
it("is enforced by check-types, not at runtime", () => {
|
|
160
|
+
const literal = singleStringParameterSchema({
|
|
161
|
+
name: "query",
|
|
162
|
+
description: DESCRIPTION,
|
|
163
|
+
});
|
|
164
|
+
// The literal key is inferred, and nothing else exists on the output.
|
|
165
|
+
const ok = { query: "ada" };
|
|
166
|
+
// @ts-expect-error `nope` is not a key of the inferred output
|
|
167
|
+
const bogus = { query: "ada", nope: 1 };
|
|
168
|
+
const unionName = (Math.random() > 0.5 ? "query" : "handle");
|
|
169
|
+
singleStringParameterSchema({
|
|
170
|
+
// @ts-expect-error a union of names would promise a key that is never created
|
|
171
|
+
name: unionName,
|
|
172
|
+
description: DESCRIPTION,
|
|
173
|
+
});
|
|
174
|
+
const dynamicName = "query";
|
|
175
|
+
singleStringParameterSchema({
|
|
176
|
+
// @ts-expect-error a widened `string` would promise every possible key
|
|
177
|
+
name: dynamicName,
|
|
178
|
+
description: DESCRIPTION,
|
|
179
|
+
});
|
|
180
|
+
expect(ok.query).toBe("ada");
|
|
181
|
+
expect(bogus).toBeDefined();
|
|
182
|
+
});
|
|
183
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { StandardSchemaV1, InferSchemaOutput } from "@copilotkit/shared";
|
|
2
|
-
export type { StandardSchemaV1, InferSchemaOutput };
|
|
1
|
+
import type { StandardSchemaV1, StandardJSONSchemaV1, InferSchemaOutput } from "@copilotkit/shared";
|
|
2
|
+
export type { StandardSchemaV1, StandardJSONSchemaV1, InferSchemaOutput };
|
|
3
3
|
/**
|
|
4
4
|
* A Standard Schema whose validated output is an object record.
|
|
5
5
|
*
|
|
@@ -35,4 +35,79 @@ export type SchemaParseResult<T> = {
|
|
|
35
35
|
* a JSON tool result so the agent can recover from a bad tool call.
|
|
36
36
|
*/
|
|
37
37
|
export declare function validateSchema<S extends StandardSchemaV1>(schema: S, value: unknown): Promise<SchemaParseResult<InferSchemaOutput<S>>>;
|
|
38
|
+
/** True when `T` is a union of more than one member. */
|
|
39
|
+
type IsUnion<T, U = T> = T extends unknown ? [U] extends [T] ? false : true : never;
|
|
40
|
+
/**
|
|
41
|
+
* `Name` unless it is a union or the widened `string`, in which case `never`.
|
|
42
|
+
*
|
|
43
|
+
* The output type is built by mapping over `Name`, so a union claims every
|
|
44
|
+
* member is present while the function creates exactly one key, and a widened
|
|
45
|
+
* `string` claims every possible key. Either way the type promises a `string`
|
|
46
|
+
* where the value is `undefined`. Restricting the parameter to one literal is
|
|
47
|
+
* what makes `SingleStringParameterSchema` honest.
|
|
48
|
+
*/
|
|
49
|
+
type SingleLiteral<Name extends string> = string extends Name ? never : true extends IsUnion<Name> ? never : Name;
|
|
50
|
+
/**
|
|
51
|
+
* A parameter schema for a tool that takes exactly one required string.
|
|
52
|
+
*
|
|
53
|
+
* The output type is keyed by the literal `Name` passed in, so a handler
|
|
54
|
+
* written against it destructures the real field name and not a widened
|
|
55
|
+
* `Record`.
|
|
56
|
+
*/
|
|
57
|
+
export type SingleStringParameterSchema<Name extends string> = StandardSchemaV1<unknown, {
|
|
58
|
+
[K in Name]: string;
|
|
59
|
+
}> & StandardJSONSchemaV1<unknown, {
|
|
60
|
+
[K in Name]: string;
|
|
61
|
+
}>;
|
|
62
|
+
/**
|
|
63
|
+
* Build a tool parameter schema for a single required, non-empty string,
|
|
64
|
+
* written directly against the [Standard Schema](https://standardschema.dev)
|
|
65
|
+
* protocol.
|
|
66
|
+
*
|
|
67
|
+
* WHY THIS EXISTS (PE-30, OSS-1173)
|
|
68
|
+
* ---------------------------------
|
|
69
|
+
* Every platform adapter ships one `lookup_<platform>_user` tool, and each
|
|
70
|
+
* one took the same parameter: a single string to resolve to a user. Each
|
|
71
|
+
* built that parameter with `z.object({query: z.string().min(1)})`, and a
|
|
72
|
+
* `zod` range in the adapter's `package.json` was the price.
|
|
73
|
+
*
|
|
74
|
+
* That price was not local. The `@copilotkit/channels` umbrella depends on
|
|
75
|
+
* every adapter, and `@microsoft/agents-hosting` and
|
|
76
|
+
* `@microsoft/agents-activity` pin `zod` at exactly `3.25.75`. An adapter
|
|
77
|
+
* asking for `^3.25.76` is a range that excludes that pin, so installing the
|
|
78
|
+
* umbrella alongside the Microsoft packages left a tree no application could
|
|
79
|
+
* repair from its own `package.json` — the conflict came from two packages we
|
|
80
|
+
* publish. One dependency for one object literal was not a trade worth
|
|
81
|
+
* keeping, three times over.
|
|
82
|
+
*
|
|
83
|
+
* `defineChannelTool` accepts any Standard Schema, and `toJsonSchema()` reads
|
|
84
|
+
* `~standard.jsonSchema.input()` in preference to every other path, so this
|
|
85
|
+
* one small object is all a tool ever needed.
|
|
86
|
+
*
|
|
87
|
+
* Behavior mirrors the `z.object({[name]: z.string().min(1).describe(...)})`
|
|
88
|
+
* it replaces: the field is required, must be a string of at least one
|
|
89
|
+
* character, and unknown keys are stripped rather than rejected (Zod's
|
|
90
|
+
* default `strip` mode for `z.object`). The emitted document is what
|
|
91
|
+
* `zod-to-json-schema` emitted for that object, so the descriptor the model
|
|
92
|
+
* is shown does not change. Its body is target-agnostic — `type`,
|
|
93
|
+
* `properties`, `required`, `minLength` and `additionalProperties` mean the
|
|
94
|
+
* same thing in draft-07 and draft-2020-12 — so one document serves every
|
|
95
|
+
* target a caller asks for, and `$schema` keeps the draft-07 value the
|
|
96
|
+
* previous output carried.
|
|
97
|
+
*
|
|
98
|
+
* The one-character floor is fixed rather than configurable because all three
|
|
99
|
+
* call sites want it and a knob nobody turns is a knob nobody tests.
|
|
100
|
+
*/
|
|
101
|
+
export declare function singleStringParameterSchema<const Name extends string>(options: {
|
|
102
|
+
/**
|
|
103
|
+
* Field name, e.g. `"query"`. Becomes the sole key of the output object.
|
|
104
|
+
*
|
|
105
|
+
* Must be a single string literal. A union or a widened `string` is a
|
|
106
|
+
* compile error, because the output type would then promise keys this
|
|
107
|
+
* function never creates. See `SingleLiteral`.
|
|
108
|
+
*/
|
|
109
|
+
name: SingleLiteral<Name>;
|
|
110
|
+
/** Field description handed to the model. Was `z.string().describe(...)`. */
|
|
111
|
+
description: string;
|
|
112
|
+
}): SingleStringParameterSchema<Name>;
|
|
38
113
|
//# sourceMappingURL=standard-schema.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"standard-schema.d.ts","sourceRoot":"","sources":["../src/standard-schema.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"standard-schema.d.ts","sourceRoot":"","sources":["../src/standard-schema.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EAClB,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,CAAC;AAE1E;;;;;;;;;GASG;AACH,MAAM,MAAM,YAAY,GAAG,gBAAgB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAE9E;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,gBAAgB,GACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAWzB;AAED,4EAA4E;AAC5E,MAAM,MAAM,iBAAiB,CAAC,CAAC,IAC3B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GACtB;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjC;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,CAAC,SAAS,gBAAgB,EAC7D,MAAM,EAAE,CAAC,EACT,KAAK,EAAE,OAAO,GACb,OAAO,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,CAWlD;AAwBD,wDAAwD;AACxD,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,OAAO,GACtC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GACb,KAAK,GACL,IAAI,GACN,KAAK,CAAC;AAEV;;;;;;;;GAQG;AACH,KAAK,aAAa,CAAC,IAAI,SAAS,MAAM,IAAI,MAAM,SAAS,IAAI,GACzD,KAAK,GACL,IAAI,SAAS,OAAO,CAAC,IAAI,CAAC,GACxB,KAAK,GACL,IAAI,CAAC;AAEX;;;;;;GAMG;AACH,MAAM,MAAM,2BAA2B,CAAC,IAAI,SAAS,MAAM,IAAI,gBAAgB,CAC7E,OAAO,EACP;KAAG,CAAC,IAAI,IAAI,GAAG,MAAM;CAAE,CACxB,GACC,oBAAoB,CAAC,OAAO,EAAE;KAAG,CAAC,IAAI,IAAI,GAAG,MAAM;CAAE,CAAC,CAAC;AAazD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,CAAC,IAAI,SAAS,MAAM,EACzB,OAAO,EAAE;IACT;;;;;;OAMG;IACH,IAAI,EAAE,aAAa,CAAC,IAAI,CAAC,CAAC;IAC1B,6EAA6E;IAC7E,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,2BAA2B,CAAC,IAAI,CAAC,CA6EpC"}
|
package/dist/standard-schema.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Schema-library-agnostic helpers for the
|
|
2
|
+
* Schema-library-agnostic helpers for the Channels SDK.
|
|
3
3
|
*
|
|
4
4
|
* The public API accepts any [Standard Schema](https://standardschema.dev)
|
|
5
5
|
* validator — Zod 3.24+, Valibot v1+, ArkType v2+, and anything else that
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*
|
|
11
11
|
* These wrap the canonical primitives from `@copilotkit/shared` (the same
|
|
12
12
|
* ones `@copilotkit/core` uses for its `FrontendTool` parameters) plus a
|
|
13
|
-
* couple of
|
|
13
|
+
* couple of Channels-local conveniences.
|
|
14
14
|
*/
|
|
15
15
|
import { schemaToJsonSchema as sharedSchemaToJsonSchema } from "@copilotkit/shared";
|
|
16
16
|
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
@@ -64,3 +64,128 @@ function formatIssues(issues) {
|
|
|
64
64
|
})
|
|
65
65
|
.join("; ");
|
|
66
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* `typeof` reports "object" for both `null` and arrays. Zod names them
|
|
69
|
+
* separately, and this message is what the agent reads back on a bad call,
|
|
70
|
+
* so it is worth the three lines to keep the wording it used to get.
|
|
71
|
+
*/
|
|
72
|
+
function parsedTypeOf(value) {
|
|
73
|
+
if (value === null)
|
|
74
|
+
return "null";
|
|
75
|
+
if (Array.isArray(value))
|
|
76
|
+
return "array";
|
|
77
|
+
return typeof value;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Build a tool parameter schema for a single required, non-empty string,
|
|
81
|
+
* written directly against the [Standard Schema](https://standardschema.dev)
|
|
82
|
+
* protocol.
|
|
83
|
+
*
|
|
84
|
+
* WHY THIS EXISTS (PE-30, OSS-1173)
|
|
85
|
+
* ---------------------------------
|
|
86
|
+
* Every platform adapter ships one `lookup_<platform>_user` tool, and each
|
|
87
|
+
* one took the same parameter: a single string to resolve to a user. Each
|
|
88
|
+
* built that parameter with `z.object({query: z.string().min(1)})`, and a
|
|
89
|
+
* `zod` range in the adapter's `package.json` was the price.
|
|
90
|
+
*
|
|
91
|
+
* That price was not local. The `@copilotkit/channels` umbrella depends on
|
|
92
|
+
* every adapter, and `@microsoft/agents-hosting` and
|
|
93
|
+
* `@microsoft/agents-activity` pin `zod` at exactly `3.25.75`. An adapter
|
|
94
|
+
* asking for `^3.25.76` is a range that excludes that pin, so installing the
|
|
95
|
+
* umbrella alongside the Microsoft packages left a tree no application could
|
|
96
|
+
* repair from its own `package.json` — the conflict came from two packages we
|
|
97
|
+
* publish. One dependency for one object literal was not a trade worth
|
|
98
|
+
* keeping, three times over.
|
|
99
|
+
*
|
|
100
|
+
* `defineChannelTool` accepts any Standard Schema, and `toJsonSchema()` reads
|
|
101
|
+
* `~standard.jsonSchema.input()` in preference to every other path, so this
|
|
102
|
+
* one small object is all a tool ever needed.
|
|
103
|
+
*
|
|
104
|
+
* Behavior mirrors the `z.object({[name]: z.string().min(1).describe(...)})`
|
|
105
|
+
* it replaces: the field is required, must be a string of at least one
|
|
106
|
+
* character, and unknown keys are stripped rather than rejected (Zod's
|
|
107
|
+
* default `strip` mode for `z.object`). The emitted document is what
|
|
108
|
+
* `zod-to-json-schema` emitted for that object, so the descriptor the model
|
|
109
|
+
* is shown does not change. Its body is target-agnostic — `type`,
|
|
110
|
+
* `properties`, `required`, `minLength` and `additionalProperties` mean the
|
|
111
|
+
* same thing in draft-07 and draft-2020-12 — so one document serves every
|
|
112
|
+
* target a caller asks for, and `$schema` keeps the draft-07 value the
|
|
113
|
+
* previous output carried.
|
|
114
|
+
*
|
|
115
|
+
* The one-character floor is fixed rather than configurable because all three
|
|
116
|
+
* call sites want it and a knob nobody turns is a knob nobody tests.
|
|
117
|
+
*/
|
|
118
|
+
export function singleStringParameterSchema(options) {
|
|
119
|
+
// `SingleLiteral<Name>` is a deferred conditional type, so TypeScript cannot
|
|
120
|
+
// prove it reduces to `Name` inside the body. It does for every value that
|
|
121
|
+
// reaches here, because any other value is a compile error at the call.
|
|
122
|
+
const { name, description } = options;
|
|
123
|
+
// Built per call, never shared. `zodToJsonSchema` returned a fresh document
|
|
124
|
+
// every time, and `toAgentToolDescriptors` hands its result straight to the
|
|
125
|
+
// caller. A single shared object would let one consumer's in-place edit —
|
|
126
|
+
// stripping `$schema` for a provider that rejects it, say — silently change
|
|
127
|
+
// what every later turn in the process is shown.
|
|
128
|
+
const buildJsonSchema = () => ({
|
|
129
|
+
type: "object",
|
|
130
|
+
properties: {
|
|
131
|
+
[name]: { type: "string", minLength: 1, description },
|
|
132
|
+
},
|
|
133
|
+
required: [name],
|
|
134
|
+
additionalProperties: false,
|
|
135
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
136
|
+
});
|
|
137
|
+
function validate(value) {
|
|
138
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
139
|
+
return {
|
|
140
|
+
issues: [
|
|
141
|
+
{ message: "Expected object, received " + parsedTypeOf(value) },
|
|
142
|
+
],
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
const field = value[name];
|
|
146
|
+
// Zod reports a missing required key as "Required", not as a type
|
|
147
|
+
// mismatch against `undefined`. The agent reads this back when it calls
|
|
148
|
+
// the tool with no argument, which is the most common bad call there is.
|
|
149
|
+
if (field === undefined) {
|
|
150
|
+
return { issues: [{ message: "Required", path: [name] }] };
|
|
151
|
+
}
|
|
152
|
+
if (typeof field !== "string") {
|
|
153
|
+
return {
|
|
154
|
+
issues: [
|
|
155
|
+
{
|
|
156
|
+
message: "Expected string, received " + parsedTypeOf(field),
|
|
157
|
+
path: [name],
|
|
158
|
+
},
|
|
159
|
+
],
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
if (field.length < 1) {
|
|
163
|
+
return {
|
|
164
|
+
issues: [
|
|
165
|
+
{
|
|
166
|
+
message: "String must contain at least 1 character(s)",
|
|
167
|
+
path: [name],
|
|
168
|
+
},
|
|
169
|
+
],
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
// Rebuilt rather than returned as-is: this is what strips unknown keys.
|
|
173
|
+
return { value: { [name]: field } };
|
|
174
|
+
}
|
|
175
|
+
return {
|
|
176
|
+
"~standard": {
|
|
177
|
+
version: 1,
|
|
178
|
+
// The Standard Schema `vendor` names the library that produced the
|
|
179
|
+
// schema, and that library is this one whichever adapter calls it.
|
|
180
|
+
// Consumers branch on this tag — `isZodSchema` in `@copilotkit/runtime`
|
|
181
|
+
// is one — so three different tags for one implementation would be three
|
|
182
|
+
// things to teach such a branch about.
|
|
183
|
+
vendor: "@copilotkit/channels-core",
|
|
184
|
+
validate,
|
|
185
|
+
jsonSchema: {
|
|
186
|
+
input: buildJsonSchema,
|
|
187
|
+
output: buildJsonSchema,
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@copilotkit/channels-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Platform-agnostic JSX channel engine for CopilotKit (createChannel, Thread, PlatformAdapter, ActionStore).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -51,9 +51,9 @@
|
|
|
51
51
|
"@ag-ui/client": "0.0.59",
|
|
52
52
|
"@ag-ui/core": "0.0.59",
|
|
53
53
|
"zod-to-json-schema": "^3.24.1",
|
|
54
|
-
"@copilotkit/
|
|
55
|
-
"@copilotkit/
|
|
56
|
-
"@copilotkit/shared": "^1.
|
|
54
|
+
"@copilotkit/core": "^1.73.1",
|
|
55
|
+
"@copilotkit/channels-ui": "~0.11.0",
|
|
56
|
+
"@copilotkit/shared": "^1.73.1"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@types/node": "^22.10.0",
|