@m6d/cortex-cli 1.1.0 → 1.3.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/package.json +2 -2
- package/src/contracts/client-tools/index.ts +56 -0
- package/src/contracts/graph/index.ts +30 -0
- package/src/contracts/{runtime.ts → runtime/index.ts} +18 -0
- package/src/contracts/{wire.ts → wire/index.ts} +44 -0
- package/tsconfig.json +1 -1
- package/src/contracts/README.md +0 -23
- package/src/contracts/graph.ts +0 -36
- /package/src/contracts/graph/{embed.ts → clients/embed.ts} +0 -0
- /package/src/contracts/graph/{neo4j.ts → clients/neo4j.ts} +0 -0
- /package/src/contracts/{rich-text.ts → rich-text/index.ts} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@m6d/cortex-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Scaffold and operate Cortex servers",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
],
|
|
17
17
|
"scripts": {
|
|
18
18
|
"check": "tsc --noEmit",
|
|
19
|
-
"prepack": "
|
|
19
|
+
"prepack": "rm -rf src/contracts && cp -R ../../internal/contracts/src src/contracts",
|
|
20
20
|
"postpack": "rm -rf src/contracts",
|
|
21
21
|
"test": "bun test"
|
|
22
22
|
},
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The embed ↔ widget handshake for client tools.
|
|
3
|
+
*
|
|
4
|
+
* A page embedded by the chat widget (a hosted checkout, signing page, …)
|
|
5
|
+
* reports its outcome with:
|
|
6
|
+
*
|
|
7
|
+
* window.parent.postMessage(
|
|
8
|
+
* { type: "cortex:client-tool", status: "completed", reference: "session_123" },
|
|
9
|
+
* "*",
|
|
10
|
+
* );
|
|
11
|
+
*
|
|
12
|
+
* The widget accepts the message only when the event's origin matches the
|
|
13
|
+
* tool's configured `embedOrigin`. The payload is the page's claim, relayed to
|
|
14
|
+
* the agent as-is: cortex does not verify it, and anything that must actually
|
|
15
|
+
* be true lives in the integrating backend's own records.
|
|
16
|
+
*
|
|
17
|
+
* Like the wire seam, this file is compiled into the client SDKs and must stay
|
|
18
|
+
* free of runtime dependencies. It is also the spec any future SDK (Flutter)
|
|
19
|
+
* reimplements against.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
export const CLIENT_TOOL_MESSAGE_TYPE = "cortex:client-tool";
|
|
23
|
+
|
|
24
|
+
export const CLIENT_TOOL_STATUSES = ["completed", "cancelled", "failed"] as const;
|
|
25
|
+
|
|
26
|
+
export type ClientToolStatus = (typeof CLIENT_TOOL_STATUSES)[number];
|
|
27
|
+
|
|
28
|
+
export type ClientToolHandshake = {
|
|
29
|
+
type: typeof CLIENT_TOOL_MESSAGE_TYPE;
|
|
30
|
+
status: ClientToolStatus;
|
|
31
|
+
/** Opaque id for the integrating backend's own bookkeeping (session id, envelope id, …). */
|
|
32
|
+
reference?: string;
|
|
33
|
+
/** Optional payload passed through to the agent as part of the tool result. */
|
|
34
|
+
result?: unknown;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Parse a `message` event into a handshake, or null when the origin doesn't
|
|
39
|
+
* match the tool's `embedOrigin` or the payload isn't a well-formed handshake.
|
|
40
|
+
* Call from the widget's `message` listener with `event.data` / `event.origin`.
|
|
41
|
+
*/
|
|
42
|
+
export function parseClientToolHandshake(data: unknown, origin: string, embedOrigin: string) {
|
|
43
|
+
if (origin !== embedOrigin) return null;
|
|
44
|
+
if (typeof data !== "object" || data === null) return null;
|
|
45
|
+
const message = data as Record<string, unknown>;
|
|
46
|
+
if (message["type"] !== CLIENT_TOOL_MESSAGE_TYPE) return null;
|
|
47
|
+
const status = CLIENT_TOOL_STATUSES.find((known) => known === message["status"]);
|
|
48
|
+
if (!status) return null;
|
|
49
|
+
const reference = message["reference"];
|
|
50
|
+
return {
|
|
51
|
+
type: CLIENT_TOOL_MESSAGE_TYPE,
|
|
52
|
+
status,
|
|
53
|
+
...(typeof reference === "string" ? { reference } : {}),
|
|
54
|
+
...(message["result"] !== undefined ? { result: message["result"] } : {}),
|
|
55
|
+
} satisfies ClientToolHandshake;
|
|
56
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The graph contract — the knowledge-graph vocabulary, authoring types and
|
|
3
|
+
* clients that `@m6d/cortex-cli` writes with and `@m6d/cortex-server` reads
|
|
4
|
+
* with. `@m6d/cortex-server` re-exports all of it, so a project authoring
|
|
5
|
+
* domains still has exactly one import path.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export type { GraphSchema } from "./schema";
|
|
9
|
+
export { GRAPH_SCHEMA, GRAPH_SCHEMA_VERSION } from "./schema";
|
|
10
|
+
|
|
11
|
+
export type {
|
|
12
|
+
EndpointScalarType,
|
|
13
|
+
EndpointProperty,
|
|
14
|
+
ResponseKind,
|
|
15
|
+
AutoGenerated,
|
|
16
|
+
ConceptDef,
|
|
17
|
+
EndpointDef,
|
|
18
|
+
EndpointInput,
|
|
19
|
+
ServiceDef,
|
|
20
|
+
RuleDef,
|
|
21
|
+
DomainDef,
|
|
22
|
+
} from "./types";
|
|
23
|
+
|
|
24
|
+
export { defineConcept, defineRule, defineService, defineDomain, defineEndpoint } from "./helpers";
|
|
25
|
+
|
|
26
|
+
export type { Neo4jConfig, Neo4jClient } from "./clients/neo4j";
|
|
27
|
+
export { createNeo4jClient } from "./clients/neo4j";
|
|
28
|
+
|
|
29
|
+
export type { EmbedFn, EmbeddingProviderConfig } from "./clients/embed";
|
|
30
|
+
export { createEmbedder } from "./clients/embed";
|
|
@@ -89,6 +89,18 @@ export const knowledgeChunkSchema = z.object({
|
|
|
89
89
|
}),
|
|
90
90
|
});
|
|
91
91
|
|
|
92
|
+
/**
|
|
93
|
+
* Runtime contract §5.4: present on signatures of `embedded` tools — flows
|
|
94
|
+
* the end user completes in an embedded surface inside the chat widget. The
|
|
95
|
+
* tool's endpoint fields act as the *initiate* call (returns the embed URL);
|
|
96
|
+
* the result the page reports back is relayed as-is — verifying it is the
|
|
97
|
+
* integrating backend's job.
|
|
98
|
+
*/
|
|
99
|
+
export const toolEmbedSchema = z.object({
|
|
100
|
+
surface: z.enum(["inline", "modal"]),
|
|
101
|
+
embedOrigin: z.url(),
|
|
102
|
+
});
|
|
103
|
+
|
|
92
104
|
export const toolSignatureSchema = z.object({
|
|
93
105
|
toolId: z.uuid(),
|
|
94
106
|
name: z.string().regex(TOOL_NAME_PATTERN),
|
|
@@ -98,6 +110,11 @@ export const toolSignatureSchema = z.object({
|
|
|
98
110
|
signature: z.string(),
|
|
99
111
|
score: z.number().nullable(),
|
|
100
112
|
pinned: z.boolean(),
|
|
113
|
+
embed: toolEmbedSchema.optional(),
|
|
114
|
+
/** Client tools only: the published input JSON Schema, verbatim.
|
|
115
|
+
* Client-executed declarations need a real schema — the rendered
|
|
116
|
+
* `signature` text alone is not enough for function calling. */
|
|
117
|
+
inputSchema: z.record(z.string(), z.unknown()).optional(),
|
|
101
118
|
});
|
|
102
119
|
|
|
103
120
|
export const serviceCardSchema = z.object({
|
|
@@ -236,6 +253,7 @@ export const runtimeErrorSchema = z.object({
|
|
|
236
253
|
}),
|
|
237
254
|
});
|
|
238
255
|
|
|
256
|
+
export type ToolEmbed = z.infer<typeof toolEmbedSchema>;
|
|
239
257
|
export type RuntimeAgentConfig = z.infer<typeof runtimeAgentConfigSchema>;
|
|
240
258
|
export type ResolveRequest = z.input<typeof resolveRequestSchema>;
|
|
241
259
|
export type ResolveResponse = z.infer<typeof resolveResponseSchema>;
|
|
@@ -70,12 +70,24 @@ export type TokenUsage = {
|
|
|
70
70
|
total: number;
|
|
71
71
|
};
|
|
72
72
|
|
|
73
|
+
/**
|
|
74
|
+
* How to launch one client tool: stamped by the server, per tool name, on
|
|
75
|
+
* the metadata of an assistant message that may carry its pending call. Kept in
|
|
76
|
+
* the message so the binding survives server restarts while a run is parked.
|
|
77
|
+
*/
|
|
78
|
+
export type ClientToolBinding = {
|
|
79
|
+
toolId: string;
|
|
80
|
+
surface: "inline" | "modal";
|
|
81
|
+
embedOrigin: string;
|
|
82
|
+
};
|
|
83
|
+
|
|
73
84
|
export type MessageMetadata = {
|
|
74
85
|
modelId?: string;
|
|
75
86
|
providerMetadata?: unknown;
|
|
76
87
|
isAborted?: boolean;
|
|
77
88
|
tokenUsage?: TokenUsage;
|
|
78
89
|
attachments?: AttachmentSummary[];
|
|
90
|
+
clientTools?: Record<string, ClientToolBinding>;
|
|
79
91
|
};
|
|
80
92
|
|
|
81
93
|
/**
|
|
@@ -93,6 +105,38 @@ export type CortexMessage<TPart = unknown> = {
|
|
|
93
105
|
metadata?: MessageMetadata;
|
|
94
106
|
};
|
|
95
107
|
|
|
108
|
+
/**
|
|
109
|
+
* Key under the AG-UI request's `forwardedProps` carrying the answers to
|
|
110
|
+
* parked client tool calls on a continuation request. The server owns the
|
|
111
|
+
* transcript (a continuation sends `messages: []`), so the answered assistant
|
|
112
|
+
* message itself never crosses the wire — the SDK's park-boundary snapshot
|
|
113
|
+
* does not preserve its id, and round-tripping it duplicated the stored
|
|
114
|
+
* message.
|
|
115
|
+
*/
|
|
116
|
+
export const CLIENT_TOOL_ANSWERS_KEY = "clientToolAnswers";
|
|
117
|
+
|
|
118
|
+
/** One answered client tool call, applied to the stored transcript server-side. */
|
|
119
|
+
export type ClientToolAnswer = {
|
|
120
|
+
toolCallId: string;
|
|
121
|
+
output: unknown;
|
|
122
|
+
state: "complete" | "error";
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Response of `POST /chat/:chatId/tools/:toolCallId/initiate`. `embed:
|
|
127
|
+
* false` means the pending call is not a CC client tool — the widget
|
|
128
|
+
* falls back to its default rendering for the call. The payload is for the
|
|
129
|
+
* widget only; it never reaches the LLM.
|
|
130
|
+
*/
|
|
131
|
+
export type ClientToolInitiateResult =
|
|
132
|
+
| { embed: false }
|
|
133
|
+
| {
|
|
134
|
+
embed: true;
|
|
135
|
+
embedUrl: string;
|
|
136
|
+
surface: "inline" | "modal";
|
|
137
|
+
embedOrigin: string;
|
|
138
|
+
};
|
|
139
|
+
|
|
96
140
|
export type ThreadCreatedEvent = {
|
|
97
141
|
type: "thread:created";
|
|
98
142
|
payload: { thread: ThreadSummary };
|
package/tsconfig.json
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
// vendors it into src/contracts, where the first candidate finds it in
|
|
23
23
|
// the published tarball. Inside the repo that copy doesn't exist and
|
|
24
24
|
// resolution falls through to the workspace source.
|
|
25
|
-
"@cortex/contracts/*": ["./src/contracts/*", "../../internal/contracts/*"],
|
|
25
|
+
"@cortex/contracts/*": ["./src/contracts/*", "../../internal/contracts/src/*"],
|
|
26
26
|
// Internal-only, and the reason this file ships in package.json `files`:
|
|
27
27
|
// the CLI runs as raw TypeScript from inside node_modules, so Bun has to
|
|
28
28
|
// read this config to resolve `@/`.
|
package/src/contracts/README.md
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# @cortex/contracts
|
|
2
|
-
|
|
3
|
-
The shapes both sides of a cortex boundary must agree on. Private on purpose —
|
|
4
|
-
it never publishes; each publishable package carries its own copy:
|
|
5
|
-
|
|
6
|
-
- `@m6d/cortex-server` and `@m6d/cortex-cli` publish raw source, so their
|
|
7
|
-
`prepack` vendors a copy of this directory into the tarball (`contracts/` and
|
|
8
|
-
`src/contracts/` respectively), resolved there by their shipped tsconfig paths.
|
|
9
|
-
- `@m6d/cortex-angular` and `@m6d/cortex-react` compile the parts they import
|
|
10
|
-
into their build artifacts.
|
|
11
|
-
|
|
12
|
-
Three boundaries, one subpath each:
|
|
13
|
-
|
|
14
|
-
| import | boundary |
|
|
15
|
-
| --------------------------- | ------------------------------------------------------------- |
|
|
16
|
-
| `@cortex/contracts/wire` | chat client ↔ server (HTTP/WebSocket types) |
|
|
17
|
-
| `@cortex/contracts/runtime` | cortex-cc console ↔ server runtime API (zod schemas) |
|
|
18
|
-
| `@cortex/contracts/graph` | graph authoring (cli) ↔ server (vocabulary, helpers, clients) |
|
|
19
|
-
|
|
20
|
-
Everything is consumed as TypeScript source — no build, no dist. Nothing here
|
|
21
|
-
has a runtime dependency beyond zod (for `/runtime`), and nothing here may grow
|
|
22
|
-
one: these files are compiled into an Angular library, a React library, a CLI
|
|
23
|
-
and a Bun server alike.
|
package/src/contracts/graph.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The graph contract — the knowledge-graph vocabulary, authoring types and
|
|
3
|
-
* clients that `@m6d/cortex-cli` writes with and `@m6d/cortex-server` reads
|
|
4
|
-
* with. `@m6d/cortex-server` re-exports all of it, so a project authoring
|
|
5
|
-
* domains still has exactly one import path.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
export type { GraphSchema } from "./graph/schema";
|
|
9
|
-
export { GRAPH_SCHEMA, GRAPH_SCHEMA_VERSION } from "./graph/schema";
|
|
10
|
-
|
|
11
|
-
export type {
|
|
12
|
-
EndpointScalarType,
|
|
13
|
-
EndpointProperty,
|
|
14
|
-
ResponseKind,
|
|
15
|
-
AutoGenerated,
|
|
16
|
-
ConceptDef,
|
|
17
|
-
EndpointDef,
|
|
18
|
-
EndpointInput,
|
|
19
|
-
ServiceDef,
|
|
20
|
-
RuleDef,
|
|
21
|
-
DomainDef,
|
|
22
|
-
} from "./graph/types";
|
|
23
|
-
|
|
24
|
-
export {
|
|
25
|
-
defineConcept,
|
|
26
|
-
defineRule,
|
|
27
|
-
defineService,
|
|
28
|
-
defineDomain,
|
|
29
|
-
defineEndpoint,
|
|
30
|
-
} from "./graph/helpers";
|
|
31
|
-
|
|
32
|
-
export type { Neo4jConfig, Neo4jClient } from "./graph/neo4j";
|
|
33
|
-
export { createNeo4jClient } from "./graph/neo4j";
|
|
34
|
-
|
|
35
|
-
export type { EmbedFn, EmbeddingProviderConfig } from "./graph/embed";
|
|
36
|
-
export { createEmbedder } from "./graph/embed";
|
|
File without changes
|
|
File without changes
|
|
File without changes
|