@m6d/cortex-cli 0.1.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 +175 -0
- package/bin/cortex.js +52 -0
- package/package.json +41 -0
- package/src/cc/client.ts +295 -0
- package/src/cc/flags.ts +135 -0
- package/src/cc/output.ts +77 -0
- package/src/cc/profiles.ts +105 -0
- package/src/cli.ts +56 -0
- package/src/commands/cc.ts +504 -0
- package/src/commands/graph.ts +229 -0
- package/src/commands/new.ts +333 -0
- package/src/commands/swagger.ts +261 -0
- package/src/config/load.ts +122 -0
- package/src/config/validate.ts +46 -0
- package/src/contracts/charts/chart-spec.ts +201 -0
- package/src/contracts/charts/index.ts +7 -0
- package/src/contracts/client-tools/index.ts +82 -0
- package/src/contracts/egress/index.ts +161 -0
- package/src/contracts/egress/scrub.ts +59 -0
- package/src/contracts/graph/clients/embed.ts +45 -0
- package/src/contracts/graph/clients/neo4j.ts +85 -0
- package/src/contracts/graph/helpers.ts +57 -0
- package/src/contracts/graph/index.ts +30 -0
- package/src/contracts/graph/schema.ts +65 -0
- package/src/contracts/graph/types.ts +125 -0
- package/src/contracts/markdown/index.ts +39 -0
- package/src/contracts/rich-text/index.ts +220 -0
- package/src/contracts/runtime/api.ts +328 -0
- package/src/contracts/runtime/auth.ts +41 -0
- package/src/contracts/runtime/dataset-sql-guide.ts +67 -0
- package/src/contracts/runtime/dataset-sql.ts +2522 -0
- package/src/contracts/runtime/datasets.fixtures.json +2849 -0
- package/src/contracts/runtime/datasets.ts +1391 -0
- package/src/contracts/runtime/grammar.ts +161 -0
- package/src/contracts/runtime/index.ts +14 -0
- package/src/contracts/runtime/signature.ts +237 -0
- package/src/contracts/runtime/sync.ts +172 -0
- package/src/contracts/runtime/triggers.ts +224 -0
- package/src/contracts/wire/index.ts +264 -0
- package/src/graph/expand-domains.ts +288 -0
- package/src/graph/generate-cypher.ts +201 -0
- package/src/graph/seed.ts +207 -0
- package/src/graph/validate.ts +78 -0
- package/src/scaffold/features.ts +190 -0
- package/src/scaffold/files.ts +411 -0
- package/src/scaffold/ports.ts +86 -0
- package/src/scaffold/templates/domains-README.md.txt +16 -0
- package/src/scaffold/templates/eslint.config.mjs.txt +20 -0
- package/src/scaffold/templates/fallowrc.jsonc.txt +42 -0
- package/src/scaffold/templates/gitignore.txt +19 -0
- package/src/scaffold/templates/index.ts.txt +18 -0
- package/src/scaffold/templates/prettier.config.mjs.txt +5 -0
- package/src/scaffold/templates/tsconfig.json.txt +25 -0
- package/src/swagger/extract-endpoints.ts +266 -0
- package/src/swagger/generated-block.ts +74 -0
- package/src/swagger/openapi-schema.ts +161 -0
- package/src/swagger/parse-response.ts +88 -0
- package/src/swagger/types.ts +25 -0
- package/src/ui/prompts.ts +125 -0
- package/src/ui/report.ts +107 -0
- package/tsconfig.json +46 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { datasetIdentifierSchema } from "./datasets";
|
|
3
|
+
import {
|
|
4
|
+
agentSlugSchema,
|
|
5
|
+
localizedTextSchema,
|
|
6
|
+
mentionedToolSchema,
|
|
7
|
+
sha256HexSchema,
|
|
8
|
+
slugSchema,
|
|
9
|
+
} from "./grammar";
|
|
10
|
+
|
|
11
|
+
/*
|
|
12
|
+
* Triggers: named entry points on an agent. A firing is one invocation with a
|
|
13
|
+
* payload and starts at most one run. The end user's message is the built-in
|
|
14
|
+
* `message` trigger; every other trigger is fired by an external caller over
|
|
15
|
+
* `POST /agents/:agentSlug/triggers/:name` on the server with the trigger's
|
|
16
|
+
* own secret. Two directions live here: what cc publishes to the server
|
|
17
|
+
* (declarations, secret checks) and what the server answers a caller.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
export const MESSAGE_TRIGGER_NAME = "message";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The first characters of a fire bearer say what it is: the secret callers
|
|
24
|
+
* hold, or a one-shot test token the console minted. A test token is a JWT
|
|
25
|
+
* the Control Center signed, so a server verifies it against the Control
|
|
26
|
+
* Center's JWKS before saying a word to it, and the Control Center then
|
|
27
|
+
* consumes it so it fires once.
|
|
28
|
+
*/
|
|
29
|
+
export const TRIGGER_SECRET_PREFIXES = { live: "tr_live_", test: "tr_test_" } as const;
|
|
30
|
+
export const TRIGGER_TEST_TOKEN_AUDIENCE = "cortex:trigger-test";
|
|
31
|
+
|
|
32
|
+
/** The claims a test token carries beside the standard ones; the server checks them against the route it arrived on. */
|
|
33
|
+
export const triggerTestTokenClaimsSchema = z.object({
|
|
34
|
+
agent: agentSlugSchema,
|
|
35
|
+
trigger: slugSchema,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export const TRIGGER_OUTCOMES = [
|
|
39
|
+
"started",
|
|
40
|
+
/** The run parked on a tool that needs approval; `POST .../firings/:id/answer` resumes it. */
|
|
41
|
+
"awaiting_approval",
|
|
42
|
+
"completed",
|
|
43
|
+
"failed",
|
|
44
|
+
"rejected",
|
|
45
|
+
"dropped",
|
|
46
|
+
"disabled",
|
|
47
|
+
] as const;
|
|
48
|
+
export type TriggerOutcome = (typeof TRIGGER_OUTCOMES)[number];
|
|
49
|
+
|
|
50
|
+
/** Why a firing was dropped: the thread was busy, or the daily budget was spent. */
|
|
51
|
+
export const TRIGGER_DROP_REASONS = ["busy", "budget"] as const;
|
|
52
|
+
export type TriggerDropReason = (typeof TRIGGER_DROP_REASONS)[number];
|
|
53
|
+
|
|
54
|
+
export const TRIGGER_SOURCES = ["code", "cc"] as const;
|
|
55
|
+
export type TriggerSource = (typeof TRIGGER_SOURCES)[number];
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Which thread a firing lands in. `single`: one thread for the trigger.
|
|
59
|
+
* `per-firing`: a fresh thread every time. `ephemeral`: a fresh thread that
|
|
60
|
+
* is deleted once the run completes, for one-shot calls: the answer reaches
|
|
61
|
+
* the caller as the firing's output or through the live stream, and nothing
|
|
62
|
+
* else outlives the run; a failed run keeps its thread for inspection. `keyed`:
|
|
63
|
+
* one thread per distinct value at a JSON pointer into the payload (e.g.
|
|
64
|
+
* `/pull_request/number`).
|
|
65
|
+
*/
|
|
66
|
+
export const triggerThreadPolicySchema = z.discriminatedUnion("policy", [
|
|
67
|
+
z.object({ policy: z.literal("single") }),
|
|
68
|
+
z.object({ policy: z.literal("per-firing") }),
|
|
69
|
+
z.object({ policy: z.literal("ephemeral") }),
|
|
70
|
+
z.object({ policy: z.literal("keyed"), key: z.string().regex(/^\//).max(256) }),
|
|
71
|
+
]);
|
|
72
|
+
export type TriggerThreadPolicy = z.infer<typeof triggerThreadPolicySchema>;
|
|
73
|
+
|
|
74
|
+
/* cc publishes to the server. */
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* A tool a trigger's instructions mention. Most are sandbox bindings; one
|
|
78
|
+
* that parks for approval is declared to the model as a function call
|
|
79
|
+
* instead, so it carries what that takes, as a /resolve signature does: a run
|
|
80
|
+
* started by a trigger has no other way to learn it.
|
|
81
|
+
*/
|
|
82
|
+
const triggerMentionedToolSchema = z.discriminatedUnion("requiresApproval", [
|
|
83
|
+
mentionedToolSchema.extend({ requiresApproval: z.literal(false) }),
|
|
84
|
+
mentionedToolSchema.extend({
|
|
85
|
+
requiresApproval: z.literal(true),
|
|
86
|
+
signature: z.string(),
|
|
87
|
+
inputSchema: z.record(z.string(), z.unknown()),
|
|
88
|
+
approvalMessage: localizedTextSchema.optional(),
|
|
89
|
+
}),
|
|
90
|
+
]);
|
|
91
|
+
|
|
92
|
+
/** A trigger as both sides describe it. Secrets and credentials never cross this contract. */
|
|
93
|
+
export const triggerDeclarationSchema = z.object({
|
|
94
|
+
name: slugSchema,
|
|
95
|
+
description: z.string().max(500),
|
|
96
|
+
/** JSON Schema for the payload; cc triggers are validated from it on the server. */
|
|
97
|
+
input: z.record(z.string(), z.unknown()),
|
|
98
|
+
/**
|
|
99
|
+
* JSON Schema the run's answer must match, or null for a free-text run.
|
|
100
|
+
* The server asks the model for that shape, validates what comes back,
|
|
101
|
+
* and stores it as the firing's `output`; a run whose answer does not
|
|
102
|
+
* parse fails with reason `invalid_output`.
|
|
103
|
+
*/
|
|
104
|
+
output: z.record(z.string(), z.unknown()).nullable(),
|
|
105
|
+
/**
|
|
106
|
+
* The prompt the run starts from, mentions already rendered to names by
|
|
107
|
+
* the console; `{{variables}}` and `{{/json/pointer}}` payload fields
|
|
108
|
+
* are the server's to fill per firing.
|
|
109
|
+
*/
|
|
110
|
+
instructions: z.string().max(20_000),
|
|
111
|
+
/** Tools the instructions mention: sandbox bindings for the run, or declared to the model when they park for approval. */
|
|
112
|
+
mentionedTools: z.array(triggerMentionedToolSchema),
|
|
113
|
+
/** Datasets the instructions mention, listed in the run's context whatever the question. */
|
|
114
|
+
mentionedDatasets: z.array(datasetIdentifierSchema),
|
|
115
|
+
threadPolicy: triggerThreadPolicySchema,
|
|
116
|
+
budgetPerDay: z.number().int().positive().nullable(),
|
|
117
|
+
/** Consecutive failed or rejected firings before the trigger disables itself. */
|
|
118
|
+
disableAfterFailures: z.number().int().positive(),
|
|
119
|
+
hasCredential: z.boolean(),
|
|
120
|
+
/**
|
|
121
|
+
* sha256 of the fire secret, so a server checks a presented bearer in
|
|
122
|
+
* process; the Control Center hears only about console test secrets,
|
|
123
|
+
* which it alone can consume.
|
|
124
|
+
*/
|
|
125
|
+
secretHash: sha256HexSchema,
|
|
126
|
+
});
|
|
127
|
+
export type TriggerDeclaration = z.infer<typeof triggerDeclarationSchema>;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* `POST /api/runtime/agents/:agentSlug/triggers/:name/auth`: a server holding a
|
|
131
|
+
* bearer for a cc trigger asks cc whether it is the trigger's secret. Only the
|
|
132
|
+
* hash travels; a positive answer carries the trigger's credential, if any.
|
|
133
|
+
*/
|
|
134
|
+
export const triggerAuthRequestSchema = z.object({
|
|
135
|
+
secretHash: sha256HexSchema,
|
|
136
|
+
});
|
|
137
|
+
export type TriggerAuthRequest = z.infer<typeof triggerAuthRequestSchema>;
|
|
138
|
+
|
|
139
|
+
export const triggerAuthResponseSchema = z.discriminatedUnion("ok", [
|
|
140
|
+
z.object({
|
|
141
|
+
ok: z.literal(true),
|
|
142
|
+
credential: z.string().nullable(),
|
|
143
|
+
/** The bearer was a single-use test secret, now spent: the server must not cache this verdict. */
|
|
144
|
+
oneShot: z.boolean(),
|
|
145
|
+
}),
|
|
146
|
+
z.object({ ok: z.literal(false) }),
|
|
147
|
+
]);
|
|
148
|
+
export type TriggerAuthResponse = z.infer<typeof triggerAuthResponseSchema>;
|
|
149
|
+
|
|
150
|
+
/* The server answers a caller firing `POST /agents/:agentSlug/triggers/:name`. */
|
|
151
|
+
|
|
152
|
+
export const triggerFiringResponseSchema = z.discriminatedUnion("outcome", [
|
|
153
|
+
z.object({
|
|
154
|
+
firingId: z.uuid(),
|
|
155
|
+
outcome: z.literal("started"),
|
|
156
|
+
threadId: z.uuid(),
|
|
157
|
+
runId: z.string(),
|
|
158
|
+
}),
|
|
159
|
+
/* The shapes a caller that waited (`?wait=`) gets instead of `started`: the run ended, or it parked for a decision. */
|
|
160
|
+
z.object({
|
|
161
|
+
firingId: z.uuid(),
|
|
162
|
+
outcome: z.literal("awaiting_approval"),
|
|
163
|
+
threadId: z.uuid(),
|
|
164
|
+
runId: z.string(),
|
|
165
|
+
approvals: z.array(
|
|
166
|
+
z.object({ toolCallId: z.string(), toolName: z.string(), input: z.unknown() }),
|
|
167
|
+
),
|
|
168
|
+
}),
|
|
169
|
+
z.object({
|
|
170
|
+
firingId: z.uuid(),
|
|
171
|
+
outcome: z.literal("completed"),
|
|
172
|
+
threadId: z.uuid(),
|
|
173
|
+
runId: z.string(),
|
|
174
|
+
/** The validated answer when the trigger declares an output schema, else null. */
|
|
175
|
+
output: z.unknown(),
|
|
176
|
+
}),
|
|
177
|
+
z.object({
|
|
178
|
+
firingId: z.uuid(),
|
|
179
|
+
outcome: z.literal("failed"),
|
|
180
|
+
threadId: z.uuid(),
|
|
181
|
+
runId: z.string(),
|
|
182
|
+
reason: z.string().nullable(),
|
|
183
|
+
}),
|
|
184
|
+
z.object({
|
|
185
|
+
firingId: z.uuid(),
|
|
186
|
+
outcome: z.literal("dropped"),
|
|
187
|
+
reason: z.enum(TRIGGER_DROP_REASONS),
|
|
188
|
+
threadId: z.uuid().nullable(),
|
|
189
|
+
}),
|
|
190
|
+
z.object({ firingId: z.uuid(), outcome: z.literal("disabled") }),
|
|
191
|
+
z.object({
|
|
192
|
+
firingId: z.uuid(),
|
|
193
|
+
outcome: z.literal("rejected"),
|
|
194
|
+
issues: z.array(z.object({ path: z.string(), message: z.string() })),
|
|
195
|
+
}),
|
|
196
|
+
]);
|
|
197
|
+
export type TriggerFiringResponse = z.infer<typeof triggerFiringResponseSchema>;
|
|
198
|
+
|
|
199
|
+
/** `POST /agents/:agentSlug/triggers/:name/firings/:id/answer`: the decision on one parked call. */
|
|
200
|
+
export const triggerFiringAnswerSchema = z.object({
|
|
201
|
+
toolCallId: z.string().min(1).max(256),
|
|
202
|
+
approved: z.boolean(),
|
|
203
|
+
});
|
|
204
|
+
export type TriggerFiringAnswer = z.infer<typeof triggerFiringAnswerSchema>;
|
|
205
|
+
|
|
206
|
+
/** One row of `GET /agents/:agentSlug/triggers/:name/firings`, and the answer of `.../firings/:id`. */
|
|
207
|
+
export const triggerFiringRecordSchema = z.object({
|
|
208
|
+
id: z.uuid(),
|
|
209
|
+
triggerName: z.string(),
|
|
210
|
+
threadId: z.uuid().nullable(),
|
|
211
|
+
runId: z.string().nullable(),
|
|
212
|
+
outcome: z.enum(TRIGGER_OUTCOMES),
|
|
213
|
+
reason: z.string().nullable(),
|
|
214
|
+
/** Set once a run with an output schema completed; null otherwise. */
|
|
215
|
+
output: z.unknown(),
|
|
216
|
+
createdAt: z.iso.datetime(),
|
|
217
|
+
finishedAt: z.iso.datetime().nullable(),
|
|
218
|
+
});
|
|
219
|
+
export type TriggerFiringRecord = z.infer<typeof triggerFiringRecordSchema>;
|
|
220
|
+
|
|
221
|
+
export const triggerFiringListResponseSchema = z.object({
|
|
222
|
+
firings: z.array(triggerFiringRecordSchema),
|
|
223
|
+
});
|
|
224
|
+
export type TriggerFiringListResponse = z.infer<typeof triggerFiringListResponseSchema>;
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The wire contract — every shape that crosses the HTTP/WebSocket boundary
|
|
3
|
+
* between `@m6d/cortex-server` and the client SDKs (`@m6d/cortex-angular`,
|
|
4
|
+
* `@m6d/cortex-react`).
|
|
5
|
+
*
|
|
6
|
+
* Nothing here has a runtime dependency, and nothing here may grow one: this
|
|
7
|
+
* file is compiled into an Angular library, a React library and a Bun server
|
|
8
|
+
* alike.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/** The UI locales every localized value is keyed by. */
|
|
12
|
+
export const LOCALES = ["en", "ar"] as const;
|
|
13
|
+
export type Locale = (typeof LOCALES)[number];
|
|
14
|
+
|
|
15
|
+
/** Where an embedded client tool renders: in the message flow or in a modal. */
|
|
16
|
+
export const TOOL_SURFACES = ["inline", "modal"] as const;
|
|
17
|
+
export type ToolSurface = (typeof TOOL_SURFACES)[number];
|
|
18
|
+
|
|
19
|
+
/** `trigger` rows hold a firing's rendered instructions; the model sees them as `user` turns. */
|
|
20
|
+
export const MESSAGE_ROLES = ["system", "user", "assistant", "trigger"] as const;
|
|
21
|
+
export type MessageRole = (typeof MESSAGE_ROLES)[number];
|
|
22
|
+
|
|
23
|
+
export const ATTACHMENT_MIME_TYPES = [
|
|
24
|
+
"image/png",
|
|
25
|
+
"image/jpeg",
|
|
26
|
+
"image/webp",
|
|
27
|
+
"application/pdf",
|
|
28
|
+
] as const;
|
|
29
|
+
|
|
30
|
+
export const ATTACHMENT_MAX_BYTES = 10 * 1024 * 1024;
|
|
31
|
+
|
|
32
|
+
export const MAX_ATTACHMENTS_PER_MESSAGE = 5;
|
|
33
|
+
|
|
34
|
+
export const ATTACHMENT_STATUSES = ["pending", "described", "failed", "skipped"] as const;
|
|
35
|
+
|
|
36
|
+
/** Who put the file in the thread: the user through the composer, or a tool mid-turn. */
|
|
37
|
+
export const ATTACHMENT_ORIGINS = ["upload", "tool"] as const;
|
|
38
|
+
|
|
39
|
+
export function checkAttachmentPolicy(contentType: string, sizeBytes: number) {
|
|
40
|
+
if (!ATTACHMENT_MIME_TYPES.some((type) => type === contentType)) return "type";
|
|
41
|
+
if (sizeBytes > ATTACHMENT_MAX_BYTES) return "size";
|
|
42
|
+
return "ok";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export type AttachmentStatus = (typeof ATTACHMENT_STATUSES)[number];
|
|
46
|
+
|
|
47
|
+
export type AttachmentOrigin = (typeof ATTACHMENT_ORIGINS)[number];
|
|
48
|
+
|
|
49
|
+
export type AttachmentSummary = {
|
|
50
|
+
id: string;
|
|
51
|
+
filename: string;
|
|
52
|
+
contentType: string;
|
|
53
|
+
sizeBytes: number;
|
|
54
|
+
status: AttachmentStatus;
|
|
55
|
+
origin: AttachmentOrigin;
|
|
56
|
+
description: string | null;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export type ThreadSummary = {
|
|
60
|
+
id: string;
|
|
61
|
+
title: string | null;
|
|
62
|
+
createdAt: string;
|
|
63
|
+
updatedAt: string;
|
|
64
|
+
isRunning: boolean;
|
|
65
|
+
/** Present on a headless thread a trigger owns. Widgets never list these. */
|
|
66
|
+
trigger?: { name: string };
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Response of `POST /chat/:threadId/abort`. `aborted: false` means there was no
|
|
71
|
+
* live run to abort — the turn had already committed — so the caller must not
|
|
72
|
+
* present the turn as aborted and should read the settled state back instead.
|
|
73
|
+
*/
|
|
74
|
+
export type AbortRunResult = {
|
|
75
|
+
aborted: boolean;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export type TokenUsage = {
|
|
79
|
+
input: {
|
|
80
|
+
noCache: number;
|
|
81
|
+
cacheRead: number;
|
|
82
|
+
cacheWrite: number;
|
|
83
|
+
total: number;
|
|
84
|
+
};
|
|
85
|
+
output: {
|
|
86
|
+
reasoning: number;
|
|
87
|
+
text: number;
|
|
88
|
+
total: number;
|
|
89
|
+
};
|
|
90
|
+
total: number;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* How to launch one client tool: stamped by the server, per tool name, on
|
|
95
|
+
* the metadata of an assistant message that may carry its pending call. Kept in
|
|
96
|
+
* the message so the binding survives server restarts while a run is parked.
|
|
97
|
+
*/
|
|
98
|
+
export type ClientToolBinding = {
|
|
99
|
+
toolId: string;
|
|
100
|
+
surface: ToolSurface;
|
|
101
|
+
embedOrigin: string;
|
|
102
|
+
/** Variables the initiate call's input reads. */
|
|
103
|
+
variables: string[];
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* What the server offers this agent's clients, fetched once at widget startup.
|
|
108
|
+
* The widget hides UI for anything absent; enforcement stays server-side.
|
|
109
|
+
*/
|
|
110
|
+
export type AgentCapabilities = {
|
|
111
|
+
attachments: boolean;
|
|
112
|
+
/** False when the agent's `message` trigger is off: the widget hides its composer. */
|
|
113
|
+
messages: boolean;
|
|
114
|
+
/** Prompt chips on the blank-chat landing per locale; clicking one sends its `prompt` as the first message. */
|
|
115
|
+
suggestions: Suggestions;
|
|
116
|
+
/** Headline of the blank-chat landing per locale; "" falls back to the widget's built-in copy. */
|
|
117
|
+
greeting: Greeting;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export type MessageMetadata = {
|
|
121
|
+
/** ISO time the server stored the message; stamped from the row when a transcript is served. */
|
|
122
|
+
createdAt?: string;
|
|
123
|
+
modelId?: string;
|
|
124
|
+
providerMetadata?: unknown;
|
|
125
|
+
isAborted?: boolean;
|
|
126
|
+
tokenUsage?: TokenUsage;
|
|
127
|
+
attachments?: AttachmentSummary[];
|
|
128
|
+
clientTools?: Record<string, ClientToolBinding>;
|
|
129
|
+
/** Set on `trigger` messages: the firing that wrote them. */
|
|
130
|
+
trigger?: TriggerFiringSummary;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* One landing-page chip: the widget shows `title` and sends `prompt` as the
|
|
135
|
+
* first message when clicked. The two may be the same text.
|
|
136
|
+
*/
|
|
137
|
+
export type Suggestion = { title: string; prompt: string };
|
|
138
|
+
|
|
139
|
+
/** The runtime contract's `suggestionsSchema` and `greetingSchema` are built from these. */
|
|
140
|
+
export type Suggestions = Record<Locale, Suggestion[]>;
|
|
141
|
+
export type Greeting = Record<Locale, string>;
|
|
142
|
+
|
|
143
|
+
/** Author-written copy the widget shows verbatim, one string per locale. */
|
|
144
|
+
export type LocalizedText = Record<Locale, string>;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* What cortex stamps on a tool-call part's `metadata.cortex`: the sentence
|
|
148
|
+
* the widget asks with when the call needs the user's approval, in the
|
|
149
|
+
* author's words rather than the function's name.
|
|
150
|
+
*/
|
|
151
|
+
export type ToolCallMetadata = {
|
|
152
|
+
approval?: LocalizedText;
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
export type TriggerFiringSummary = {
|
|
156
|
+
name: string;
|
|
157
|
+
firingId: string;
|
|
158
|
+
firedAt: string;
|
|
159
|
+
payload: unknown;
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* A stored message as it is persisted and served. TanStack AI's `UIMessage`
|
|
164
|
+
* has no metadata field, so cortex owns the envelope: the SDK's parts plus the
|
|
165
|
+
* server-derived metadata the UI renders on settled messages.
|
|
166
|
+
*
|
|
167
|
+
* `TPart` stays generic so this file keeps its zero dependencies — both
|
|
168
|
+
* sides substitute the SDK's `MessagePart`.
|
|
169
|
+
*/
|
|
170
|
+
export type CortexMessage<TPart = unknown> = {
|
|
171
|
+
id: string;
|
|
172
|
+
/** `trigger` rows carry a firing's instructions; the UIs render them as an event, not a bubble. */
|
|
173
|
+
role: MessageRole;
|
|
174
|
+
parts: TPart[];
|
|
175
|
+
metadata?: MessageMetadata;
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Key under the AG-UI request's `forwardedProps` carrying the answers to
|
|
180
|
+
* parked client tool calls on a continuation request. The server owns the
|
|
181
|
+
* transcript (a continuation sends `messages: []`), so the answered assistant
|
|
182
|
+
* message itself never crosses the wire — the SDK's park-boundary snapshot
|
|
183
|
+
* does not preserve its id, and round-tripping it duplicated the stored
|
|
184
|
+
* message.
|
|
185
|
+
*/
|
|
186
|
+
export const CLIENT_TOOL_ANSWERS_KEY = "clientToolAnswers";
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* One answered call, applied to the stored transcript server-side: a client
|
|
190
|
+
* tool's output (`complete` / `error`), or the user's decision on a server
|
|
191
|
+
* tool that asked for approval (`approved` / `denied`, output null).
|
|
192
|
+
*/
|
|
193
|
+
export type ClientToolAnswer = {
|
|
194
|
+
toolCallId: string;
|
|
195
|
+
output: unknown;
|
|
196
|
+
state: "complete" | "error" | "approved" | "denied";
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Response of `POST /chat/:threadId/tools/:toolCallId/initiate`. `embed:
|
|
201
|
+
* false` means the pending call is not a CC client tool — the widget
|
|
202
|
+
* falls back to its default rendering for the call. The payload is for the
|
|
203
|
+
* widget only; it never reaches the LLM.
|
|
204
|
+
*/
|
|
205
|
+
export type ClientToolInitiateResult =
|
|
206
|
+
| { embed: false }
|
|
207
|
+
| {
|
|
208
|
+
embed: true;
|
|
209
|
+
embedUrl: string;
|
|
210
|
+
surface: ToolSurface;
|
|
211
|
+
embedOrigin: string;
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
export type ThreadCreatedEvent = {
|
|
215
|
+
type: "thread:created";
|
|
216
|
+
payload: { thread: ThreadSummary };
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
export type ThreadDeletedEvent = {
|
|
220
|
+
type: "thread:deleted";
|
|
221
|
+
payload: { threadId: string };
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
export type ThreadTitleUpdatedEvent = {
|
|
225
|
+
type: "thread:title-updated";
|
|
226
|
+
payload: { thread: ThreadSummary };
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
export type ThreadRunStartedEvent = {
|
|
230
|
+
type: "thread:run-started";
|
|
231
|
+
payload: { thread: ThreadSummary };
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
export type ThreadRunFinishedEvent = {
|
|
235
|
+
type: "thread:run-finished";
|
|
236
|
+
payload: { thread: ThreadSummary };
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
export type ThreadMessagesUpdatedEvent = {
|
|
240
|
+
type: "thread:messages-updated";
|
|
241
|
+
payload: { thread: ThreadSummary };
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
export type ToolProgressEvent = {
|
|
245
|
+
type: "thread:tool-progress";
|
|
246
|
+
payload: {
|
|
247
|
+
threadId: string;
|
|
248
|
+
toolCallId: string;
|
|
249
|
+
toolName: string;
|
|
250
|
+
status: "started" | "finished";
|
|
251
|
+
};
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
export type WsEvent =
|
|
255
|
+
| ThreadCreatedEvent
|
|
256
|
+
| ThreadDeletedEvent
|
|
257
|
+
| ThreadTitleUpdatedEvent
|
|
258
|
+
| ThreadRunStartedEvent
|
|
259
|
+
| ThreadRunFinishedEvent
|
|
260
|
+
| ThreadMessagesUpdatedEvent
|
|
261
|
+
| ToolProgressEvent;
|
|
262
|
+
|
|
263
|
+
/** The header the widget sends the browser's IANA time zone in; the turn reasons in that clock. */
|
|
264
|
+
export const TIMEZONE_HEADER = "X-Cortex-Timezone";
|