@m6d/cortex-cli 0.12.1 → 0.14.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 +193 -128
- package/package.json +16 -5
- package/src/cli.ts +19 -12
- package/src/commands/apply.ts +186 -0
- package/src/commands/{cc.ts → management.ts} +173 -112
- package/src/commands/new.ts +83 -84
- package/src/commands/setup.ts +610 -0
- package/src/contracts/charts/chart-spec.ts +1 -1
- package/src/contracts/client-tools/index.ts +3 -3
- package/src/contracts/{runtime → datasets}/datasets.ts +7 -42
- package/src/contracts/datasets/index.ts +3 -0
- package/src/contracts/egress-policy/index.ts +16 -0
- package/src/contracts/{egress → egress-policy}/scrub.ts +34 -5
- package/src/contracts/{egress → egress-policy}/url.ts +22 -9
- package/src/contracts/errors/index.ts +38 -0
- package/src/contracts/json/index.ts +5 -0
- package/src/contracts/manifest/index.ts +973 -0
- package/src/contracts/manifest-file/index.ts +16 -0
- package/src/contracts/markdown/index.ts +1 -1
- package/src/contracts/pattern/index.ts +276 -0
- package/src/contracts/server/index.ts +349 -0
- package/src/contracts/server/reserved-names.fixtures.json +18 -0
- package/src/contracts/triggers/index.ts +112 -0
- package/src/contracts/wire/index.ts +67 -33
- package/src/{cc → management}/client.ts +33 -7
- package/src/{cc → management}/flags.ts +2 -1
- package/src/{cc → management}/profiles.ts +10 -8
- package/src/scaffold/files.ts +448 -284
- package/src/scaffold/ports.ts +12 -24
- package/src/scaffold/templates/cspell.json.txt +41 -0
- package/src/scaffold/templates/datasets.ts.txt +52 -0
- package/src/scaffold/templates/dockerignore.txt +6 -0
- package/src/scaffold/templates/fallowrc.jsonc.txt +8 -12
- package/src/scaffold/templates/gitignore.txt +1 -1
- package/src/scaffold/templates/server.ts.txt +40 -0
- package/src/scaffold/templates/setup.ts.txt +44 -0
- package/src/ui/prompts.ts +24 -38
- package/src/ui/report.ts +5 -15
- package/tsconfig.json +2 -3
- package/src/commands/graph.ts +0 -228
- package/src/commands/swagger.ts +0 -247
- package/src/config/load.ts +0 -122
- package/src/config/validate.ts +0 -46
- package/src/contracts/credentials/index.ts +0 -183
- package/src/contracts/egress/index.ts +0 -120
- package/src/contracts/graph/clients/embed.ts +0 -62
- package/src/contracts/graph/clients/neo4j.ts +0 -85
- package/src/contracts/graph/helpers.ts +0 -55
- package/src/contracts/graph/index.ts +0 -30
- package/src/contracts/graph/schema.ts +0 -65
- package/src/contracts/graph/types.ts +0 -125
- package/src/contracts/rich-text/index.ts +0 -220
- package/src/contracts/runtime/api.ts +0 -345
- package/src/contracts/runtime/auth.ts +0 -41
- package/src/contracts/runtime/grammar.ts +0 -169
- package/src/contracts/runtime/index.ts +0 -15
- package/src/contracts/runtime/models.ts +0 -50
- package/src/contracts/runtime/signature.ts +0 -255
- package/src/contracts/runtime/sync.ts +0 -196
- package/src/contracts/runtime/triggers.ts +0 -267
- package/src/graph/expand-domains.ts +0 -286
- package/src/graph/generate-cypher.ts +0 -201
- package/src/graph/seed.ts +0 -199
- package/src/graph/validate.ts +0 -78
- package/src/scaffold/features.ts +0 -190
- package/src/scaffold/templates/domains-README.md.txt +0 -16
- package/src/scaffold/templates/index.ts.txt +0 -18
- package/src/swagger/extract-endpoints.ts +0 -269
- package/src/swagger/generated-block.ts +0 -74
- package/src/swagger/openapi-schema.ts +0 -168
- package/src/swagger/parse-response.ts +0 -88
- package/src/swagger/types.ts +0 -25
- /package/src/contracts/{runtime → datasets}/dataset-sql-guide.ts +0 -0
- /package/src/contracts/{runtime → datasets}/dataset-sql.ts +0 -0
- /package/src/contracts/{runtime → datasets}/datasets.fixtures.json +0 -0
- /package/src/{cc → management}/output.ts +0 -0
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import { MESSAGE_ROLES, type TokenUsage } from "../wire/index";
|
|
3
|
-
import { agentRefSchema, agentSlugSchema, variableDeclarationSchema } from "./grammar";
|
|
4
|
-
import { approvalRequestedEventSchema, TRIGGER_OUTCOMES, TRIGGER_SOURCES } from "./triggers";
|
|
5
|
-
import { DATASET_ERROR_KINDS } from "./datasets";
|
|
6
|
-
|
|
7
|
-
/*
|
|
8
|
-
* Fleet sync: `@m6d/cortex-server` mirrors thread/message/usage activity into
|
|
9
|
-
* cc via `POST /api/runtime/sync` batches. Upserts are idempotent on
|
|
10
|
-
* (serverId, id); an empty batch is the heartbeat.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
const tokenCountSchema = z.number().int().nonnegative();
|
|
14
|
-
|
|
15
|
-
export const tokenUsageSchema = z.object({
|
|
16
|
-
input: z.object({
|
|
17
|
-
noCache: tokenCountSchema,
|
|
18
|
-
cacheRead: tokenCountSchema,
|
|
19
|
-
cacheWrite: tokenCountSchema,
|
|
20
|
-
total: tokenCountSchema,
|
|
21
|
-
}),
|
|
22
|
-
output: z.object({
|
|
23
|
-
reasoning: tokenCountSchema,
|
|
24
|
-
text: tokenCountSchema,
|
|
25
|
-
total: tokenCountSchema,
|
|
26
|
-
}),
|
|
27
|
-
total: tokenCountSchema,
|
|
28
|
-
}) satisfies z.ZodType<TokenUsage>;
|
|
29
|
-
|
|
30
|
-
const componentNamesSchema = z.array(z.string().min(1).max(128)).max(1_000);
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* What a server offers every agent the Control Center creates for it, sent
|
|
34
|
-
* whole at boot in `server.declare`: the `{{variables}}` its session loader
|
|
35
|
-
* and request context fill, SDK ones included, and the names of the
|
|
36
|
-
* components its code declares at server level, which reach those agents
|
|
37
|
-
* too and which the Control Center therefore refuses on its own components.
|
|
38
|
-
* Agents in the server's own code never appear here; the Control Center is
|
|
39
|
-
* blind to them.
|
|
40
|
-
*/
|
|
41
|
-
export const serverDeclarationSchema = z.object({
|
|
42
|
-
variables: z.array(variableDeclarationSchema),
|
|
43
|
-
components: z.object({
|
|
44
|
-
tool: componentNamesSchema,
|
|
45
|
-
skill: componentNamesSchema,
|
|
46
|
-
trigger: componentNamesSchema,
|
|
47
|
-
dataset_host: componentNamesSchema,
|
|
48
|
-
}),
|
|
49
|
-
});
|
|
50
|
-
export type ServerDeclaration = z.infer<typeof serverDeclarationSchema>;
|
|
51
|
-
|
|
52
|
-
export const syncEventSchema = z.discriminatedUnion("type", [
|
|
53
|
-
z.object({
|
|
54
|
-
type: z.literal("thread.upsert"),
|
|
55
|
-
id: z.uuid(),
|
|
56
|
-
agentSlug: agentSlugSchema,
|
|
57
|
-
userId: z.string().max(255),
|
|
58
|
-
title: z.string().max(256).nullable(),
|
|
59
|
-
isTest: z.boolean(),
|
|
60
|
-
/** Set on headless threads a trigger owns; `userId` is then a sentinel. */
|
|
61
|
-
triggerName: z.string().max(64).nullable(),
|
|
62
|
-
triggerKey: z.string().max(256).nullable(),
|
|
63
|
-
createdAt: z.iso.datetime(),
|
|
64
|
-
updatedAt: z.iso.datetime(),
|
|
65
|
-
}),
|
|
66
|
-
z.object({
|
|
67
|
-
type: z.literal("thread.delete"),
|
|
68
|
-
id: z.uuid(),
|
|
69
|
-
}),
|
|
70
|
-
z.object({
|
|
71
|
-
type: z.literal("message.upsert"),
|
|
72
|
-
id: z.string().max(128),
|
|
73
|
-
threadId: z.uuid(),
|
|
74
|
-
role: z.enum(MESSAGE_ROLES),
|
|
75
|
-
text: z.string().nullable(),
|
|
76
|
-
ordinal: z.number().int(),
|
|
77
|
-
content: z.looseObject({}),
|
|
78
|
-
createdAt: z.iso.datetime(),
|
|
79
|
-
}),
|
|
80
|
-
z.object({
|
|
81
|
-
type: z.literal("usage.record"),
|
|
82
|
-
id: z.uuid(),
|
|
83
|
-
messageId: z.string().max(128),
|
|
84
|
-
threadId: z.uuid(),
|
|
85
|
-
stepNumber: z.number().int(),
|
|
86
|
-
tokenUsage: tokenUsageSchema,
|
|
87
|
-
/** Stamped by the event constructor: llm_requests has no timestamp column, but time-bucketed usage stats need one. */
|
|
88
|
-
createdAt: z.iso.datetime(),
|
|
89
|
-
}),
|
|
90
|
-
/** One loadSkill call, hit or miss, from either skill source. Bounded by construction (no body travels). */
|
|
91
|
-
z.object({
|
|
92
|
-
type: z.literal("skill.load"),
|
|
93
|
-
id: z.uuid(),
|
|
94
|
-
threadId: z.uuid(),
|
|
95
|
-
agentSlug: agentSlugSchema,
|
|
96
|
-
/** The ref cc issued for the agent that answered; a code-only agent or a miss has none. */
|
|
97
|
-
agentRef: agentRefSchema.optional(),
|
|
98
|
-
/** As the model asked for it, even when nothing answered. */
|
|
99
|
-
skillName: z.string().max(64),
|
|
100
|
-
source: z.enum(TRIGGER_SOURCES).nullable(),
|
|
101
|
-
hit: z.boolean(),
|
|
102
|
-
/** The user message this turn answers; the mirror joins it for the drill-down. */
|
|
103
|
-
messageId: z.string().max(128),
|
|
104
|
-
createdAt: z.iso.datetime(),
|
|
105
|
-
}),
|
|
106
|
-
/** One dataset read, refused or answered; never the rows. */
|
|
107
|
-
z.object({
|
|
108
|
-
type: z.literal("dataset.read"),
|
|
109
|
-
id: z.uuid(),
|
|
110
|
-
threadId: z.uuid(),
|
|
111
|
-
agentSlug: agentSlugSchema,
|
|
112
|
-
agentRef: agentRefSchema.optional(),
|
|
113
|
-
host: z.string().max(64),
|
|
114
|
-
/** Empty when the statement was refused before it named one. */
|
|
115
|
-
dataset: z.string().max(64),
|
|
116
|
-
rowCount: z.number().int().nonnegative(),
|
|
117
|
-
truncated: z.boolean(),
|
|
118
|
-
durationMs: z.number().int().nonnegative(),
|
|
119
|
-
status: z.enum(["ok", ...DATASET_ERROR_KINDS]),
|
|
120
|
-
/** The SQL the model wrote, when the read came from a statement. */
|
|
121
|
-
sql: z.string().max(4000).optional(),
|
|
122
|
-
/** Why a read did not answer: the parser's refusal, the validator's issues or the host's detail. */
|
|
123
|
-
detail: z.string().max(1000).optional(),
|
|
124
|
-
/** The user or trigger message this turn answers; the mirror joins it for the drill-down. */
|
|
125
|
-
messageId: z.string().max(128),
|
|
126
|
-
createdAt: z.iso.datetime(),
|
|
127
|
-
}),
|
|
128
|
-
/** One firing, upserted on start and again on its terminal outcome; the firing id is the event id so both land on one mirror row. */
|
|
129
|
-
z.object({
|
|
130
|
-
type: z.literal("trigger.firing"),
|
|
131
|
-
id: z.uuid(),
|
|
132
|
-
agentSlug: agentSlugSchema,
|
|
133
|
-
agentRef: agentRefSchema.optional(),
|
|
134
|
-
triggerName: z.string().max(64),
|
|
135
|
-
source: z.enum(TRIGGER_SOURCES),
|
|
136
|
-
threadId: z.uuid().nullable(),
|
|
137
|
-
runId: z.string().max(64).nullable(),
|
|
138
|
-
outcome: z.enum(TRIGGER_OUTCOMES),
|
|
139
|
-
reason: z.string().max(64).nullable(),
|
|
140
|
-
output: z.unknown(),
|
|
141
|
-
createdAt: z.iso.datetime(),
|
|
142
|
-
finishedAt: z.iso.datetime().nullable(),
|
|
143
|
-
}),
|
|
144
|
-
/**
|
|
145
|
-
* A run on a cc-backed agent parked on approval. cc delivers it to the
|
|
146
|
-
* published webhooks in the agent's audience; a code agent reacts in
|
|
147
|
-
* code and sends none.
|
|
148
|
-
*/
|
|
149
|
-
z.object({
|
|
150
|
-
type: z.literal("approval.requested"),
|
|
151
|
-
id: z.uuid(),
|
|
152
|
-
agentSlug: agentSlugSchema,
|
|
153
|
-
agentRef: agentRefSchema,
|
|
154
|
-
payload: approvalRequestedEventSchema,
|
|
155
|
-
createdAt: z.iso.datetime(),
|
|
156
|
-
}),
|
|
157
|
-
/** What the server offers console-created agents, sent whole at boot and replacing the previous declaration. */
|
|
158
|
-
z.object({
|
|
159
|
-
type: z.literal("server.declare"),
|
|
160
|
-
id: z.uuid(),
|
|
161
|
-
...serverDeclarationSchema.shape,
|
|
162
|
-
createdAt: z.iso.datetime(),
|
|
163
|
-
}),
|
|
164
|
-
]);
|
|
165
|
-
export type SyncEvent = z.infer<typeof syncEventSchema>;
|
|
166
|
-
|
|
167
|
-
/*
|
|
168
|
-
* `epoch` identifies the sending database's generation (a UUIDv7 minted into
|
|
169
|
-
* the server DB's `sync_meta` row): a recreated database gets a new epoch, so
|
|
170
|
-
* cc can tell a legitimately restarted outbox sequence from a stale batch.
|
|
171
|
-
* v7 uuids are time-ordered, so cc also rejects batches from a superseded
|
|
172
|
-
* (lexicographically lower) epoch outright.
|
|
173
|
-
* `seq` is the batch's highest outbox row id; batches are contiguous
|
|
174
|
-
* id-ordered outbox prefixes, so within one epoch cc keeps a per-server
|
|
175
|
-
* high-water mark and discards batches at or below it. A stale in-flight
|
|
176
|
-
* batch (an expired flusher lease, a replay after a lost ack) can never
|
|
177
|
-
* overwrite newer mirrored state. Heartbeats carry no events and nothing to
|
|
178
|
-
* fence, so `seq` exists only on the non-empty branch.
|
|
179
|
-
*/
|
|
180
|
-
export const syncRequestSchema = z.union([
|
|
181
|
-
z.object({
|
|
182
|
-
events: z.array(syncEventSchema).min(1).max(500),
|
|
183
|
-
epoch: z.uuid(),
|
|
184
|
-
seq: z.number().int().positive(),
|
|
185
|
-
}),
|
|
186
|
-
z.object({
|
|
187
|
-
events: z.array(syncEventSchema).length(0),
|
|
188
|
-
epoch: z.uuid(),
|
|
189
|
-
}),
|
|
190
|
-
]);
|
|
191
|
-
export type SyncRequest = z.input<typeof syncRequestSchema>;
|
|
192
|
-
|
|
193
|
-
export const syncResponseSchema = z.object({
|
|
194
|
-
accepted: z.number().int(),
|
|
195
|
-
});
|
|
196
|
-
export type SyncResponse = z.infer<typeof syncResponseSchema>;
|
|
@@ -1,267 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import { datasetIdentifierSchema } from "./datasets";
|
|
3
|
-
import { modelChoiceSchema } from "./models";
|
|
4
|
-
import {
|
|
5
|
-
agentRefSchema,
|
|
6
|
-
agentSlugSchema,
|
|
7
|
-
localizedTextSchema,
|
|
8
|
-
mentionedToolSchema,
|
|
9
|
-
sha256HexSchema,
|
|
10
|
-
slugSchema,
|
|
11
|
-
} from "./grammar";
|
|
12
|
-
|
|
13
|
-
/*
|
|
14
|
-
* Triggers: named entry points on an agent. A firing is one invocation with a
|
|
15
|
-
* payload and starts at most one run. The end user's message is the built-in
|
|
16
|
-
* `message` trigger; every other trigger is fired by an external caller over
|
|
17
|
-
* `POST /agents/:agentSlug/triggers/:name` on the server with the trigger's
|
|
18
|
-
* own secret. Two directions live here: what cc publishes to the server
|
|
19
|
-
* (declarations, secret checks) and what the server answers a caller.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
export const MESSAGE_TRIGGER_NAME = "message";
|
|
23
|
-
|
|
24
|
-
/** The tool a trigger run with an output schema answers through; no other tool may take its name. */
|
|
25
|
-
export const TRIGGER_ANSWER_TOOL_NAME = "submitAnswer";
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* The first characters of a fire bearer say what it is: the secret callers
|
|
29
|
-
* hold, or a one-shot test token the console minted. A test token is a JWT
|
|
30
|
-
* the Control Center signed, so a server verifies it against the Control
|
|
31
|
-
* Center's JWKS before saying a word to it, and the Control Center then
|
|
32
|
-
* consumes it so it fires once.
|
|
33
|
-
*/
|
|
34
|
-
export const TRIGGER_SECRET_PREFIXES = { live: "tr_live_", test: "tr_test_" } as const;
|
|
35
|
-
export const TRIGGER_TEST_TOKEN_AUDIENCE = "cortex:trigger-test";
|
|
36
|
-
|
|
37
|
-
/** The claims a test token carries beside the standard ones; the server checks them against the route it arrived on. */
|
|
38
|
-
export const triggerTestTokenClaimsSchema = z.object({
|
|
39
|
-
agent: agentSlugSchema,
|
|
40
|
-
trigger: slugSchema,
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
export const TRIGGER_OUTCOMES = [
|
|
44
|
-
"started",
|
|
45
|
-
/** The run parked on a tool that needs approval; `POST .../firings/:id/answer` resumes it. */
|
|
46
|
-
"awaiting_approval",
|
|
47
|
-
"completed",
|
|
48
|
-
"failed",
|
|
49
|
-
"rejected",
|
|
50
|
-
"dropped",
|
|
51
|
-
"disabled",
|
|
52
|
-
] as const;
|
|
53
|
-
export type TriggerOutcome = (typeof TRIGGER_OUTCOMES)[number];
|
|
54
|
-
|
|
55
|
-
/** Why a firing was dropped: the thread was busy, or the daily budget was spent. */
|
|
56
|
-
export const TRIGGER_DROP_REASONS = ["busy", "budget"] as const;
|
|
57
|
-
export type TriggerDropReason = (typeof TRIGGER_DROP_REASONS)[number];
|
|
58
|
-
|
|
59
|
-
export const TRIGGER_SOURCES = ["code", "cc"] as const;
|
|
60
|
-
export type TriggerSource = (typeof TRIGGER_SOURCES)[number];
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Which thread a firing lands in. `single`: one thread for the trigger.
|
|
64
|
-
* `per-firing`: a fresh thread every time. `ephemeral`: a fresh thread that
|
|
65
|
-
* is deleted once the run completes, for one-shot calls: the answer reaches
|
|
66
|
-
* the caller as the firing's output or through the live stream, and nothing
|
|
67
|
-
* else outlives the run; a failed run keeps its thread for inspection. `keyed`:
|
|
68
|
-
* one thread per distinct value at a JSON pointer into the payload (e.g.
|
|
69
|
-
* `/pull_request/number`).
|
|
70
|
-
*/
|
|
71
|
-
export const triggerThreadPolicySchema = z.discriminatedUnion("policy", [
|
|
72
|
-
z.object({ policy: z.literal("single") }),
|
|
73
|
-
z.object({ policy: z.literal("per-firing") }),
|
|
74
|
-
z.object({ policy: z.literal("ephemeral") }),
|
|
75
|
-
z.object({ policy: z.literal("keyed"), key: z.string().regex(/^\//).max(256) }),
|
|
76
|
-
]);
|
|
77
|
-
export type TriggerThreadPolicy = z.infer<typeof triggerThreadPolicySchema>;
|
|
78
|
-
|
|
79
|
-
/* cc publishes to the server. */
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* A tool a trigger's instructions mention. Most are sandbox bindings; one
|
|
83
|
-
* that parks for approval is declared to the model as a function call
|
|
84
|
-
* instead, so it carries what that takes, as a /resolve signature does: a run
|
|
85
|
-
* started by a trigger has no other way to learn it.
|
|
86
|
-
*/
|
|
87
|
-
const triggerMentionedToolSchema = z.discriminatedUnion("requiresApproval", [
|
|
88
|
-
mentionedToolSchema.extend({ requiresApproval: z.literal(false) }),
|
|
89
|
-
mentionedToolSchema.extend({
|
|
90
|
-
requiresApproval: z.literal(true),
|
|
91
|
-
signature: z.string(),
|
|
92
|
-
inputSchema: z.record(z.string(), z.unknown()),
|
|
93
|
-
approvalMessage: localizedTextSchema.optional(),
|
|
94
|
-
}),
|
|
95
|
-
]);
|
|
96
|
-
|
|
97
|
-
/** A trigger as both sides describe it. Secrets and credentials never cross this contract. */
|
|
98
|
-
export const triggerDeclarationSchema = z.object({
|
|
99
|
-
name: slugSchema,
|
|
100
|
-
description: z.string().max(500),
|
|
101
|
-
/** JSON Schema for the payload; cc triggers are validated from it on the server. */
|
|
102
|
-
input: z.record(z.string(), z.unknown()),
|
|
103
|
-
/**
|
|
104
|
-
* JSON Schema the run's answer must match, or null for a free-text run.
|
|
105
|
-
* The run submits it through an answer tool whose input is this schema,
|
|
106
|
-
* and the server stores it as the firing's `output`; a run that never
|
|
107
|
-
* submits fails with `no_output`, one whose answers the schema refused
|
|
108
|
-
* with `invalid_output`.
|
|
109
|
-
*/
|
|
110
|
-
output: z.record(z.string(), z.unknown()).nullable(),
|
|
111
|
-
/**
|
|
112
|
-
* The prompt the run starts from, mentions already rendered to names by
|
|
113
|
-
* the console; `{{variables}}` and `{{/json/pointer}}` payload fields
|
|
114
|
-
* are the server's to fill per firing.
|
|
115
|
-
*/
|
|
116
|
-
instructions: z.string().max(20_000),
|
|
117
|
-
/** Tools the instructions mention: sandbox bindings for the run, or declared to the model when they park for approval. */
|
|
118
|
-
mentionedTools: z.array(triggerMentionedToolSchema),
|
|
119
|
-
/** Datasets the instructions mention, listed in the run's context whatever the question. */
|
|
120
|
-
mentionedDatasets: z.array(datasetIdentifierSchema),
|
|
121
|
-
threadPolicy: triggerThreadPolicySchema,
|
|
122
|
-
budgetPerDay: z.number().int().positive().nullable(),
|
|
123
|
-
/** Consecutive failed or rejected firings before the trigger disables itself. */
|
|
124
|
-
disableAfterFailures: z.number().int().positive(),
|
|
125
|
-
hasCredential: z.boolean(),
|
|
126
|
-
/** What runs of this trigger talk to, over the agent's pick; read live like the credential. */
|
|
127
|
-
modelChoice: modelChoiceSchema,
|
|
128
|
-
/**
|
|
129
|
-
* sha256 of the fire secret, so a server checks a presented bearer in
|
|
130
|
-
* process; the Control Center hears only about console test secrets,
|
|
131
|
-
* which it alone can consume.
|
|
132
|
-
*/
|
|
133
|
-
secretHash: sha256HexSchema,
|
|
134
|
-
});
|
|
135
|
-
export type TriggerDeclaration = z.infer<typeof triggerDeclarationSchema>;
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* `POST /api/runtime/agents/:agentSlug/triggers/:name/auth`: a server holding a
|
|
139
|
-
* bearer for a cc trigger asks cc whether it is the trigger's secret. Only the
|
|
140
|
-
* hash travels; a positive answer carries the bearer the run acts with, if
|
|
141
|
-
* the trigger has a credential, resolved by cc (acquired, for an OAuth2 one).
|
|
142
|
-
*/
|
|
143
|
-
export const triggerAuthRequestSchema = z.object({
|
|
144
|
-
secretHash: sha256HexSchema,
|
|
145
|
-
});
|
|
146
|
-
export type TriggerAuthRequest = z.infer<typeof triggerAuthRequestSchema>;
|
|
147
|
-
|
|
148
|
-
export const triggerAuthResponseSchema = z.discriminatedUnion("ok", [
|
|
149
|
-
z.object({
|
|
150
|
-
ok: z.literal(true),
|
|
151
|
-
credential: z.string().nullable(),
|
|
152
|
-
/** When the bearer stops working, ISO 8601; null for one that does not expire or has no credential. */
|
|
153
|
-
expiresAt: z.iso.datetime().nullable(),
|
|
154
|
-
/** The bearer was a single-use test secret, now spent: the server must not cache this verdict. */
|
|
155
|
-
oneShot: z.boolean(),
|
|
156
|
-
}),
|
|
157
|
-
z.object({ ok: z.literal(false) }),
|
|
158
|
-
]);
|
|
159
|
-
export type TriggerAuthResponse = z.infer<typeof triggerAuthResponseSchema>;
|
|
160
|
-
|
|
161
|
-
/* The server answers a caller firing `POST /agents/:agentSlug/triggers/:name`. */
|
|
162
|
-
|
|
163
|
-
/** One server tool call a parked run waits on; `POST .../firings/:id/answer` decides it. */
|
|
164
|
-
const triggerApprovalSchema = z.object({
|
|
165
|
-
toolCallId: z.string(),
|
|
166
|
-
toolName: z.string(),
|
|
167
|
-
input: z.unknown(),
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
/** The host-reaction events a run reports. One so far; the shape is generic. */
|
|
171
|
-
export const HOST_EVENTS = ["approval_requested"] as const;
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* A run parked on server tools that need the user's approval, as every host
|
|
175
|
-
* hears of it: the code hook's argument and a webhook's body are this one
|
|
176
|
-
* object. `agentId` is the slug; `agentRef` is cc's id when cc backs the
|
|
177
|
-
* agent. `firingId` and `triggerName` are set when a trigger started the run,
|
|
178
|
-
* which is what a host answering through the firing route needs.
|
|
179
|
-
*/
|
|
180
|
-
export const approvalRequestedEventSchema = z.object({
|
|
181
|
-
event: z.literal("approval_requested"),
|
|
182
|
-
agentId: z.string(),
|
|
183
|
-
agentRef: agentRefSchema.optional(),
|
|
184
|
-
threadId: z.string(),
|
|
185
|
-
runId: z.string(),
|
|
186
|
-
userId: z.string(),
|
|
187
|
-
firingId: z.uuid().optional(),
|
|
188
|
-
triggerName: z.string().optional(),
|
|
189
|
-
/** The hook always gets each call's `input`; a webhook body leaves it out when the whole would be too large for the wire. */
|
|
190
|
-
approvals: z.array(triggerApprovalSchema.extend({ input: z.unknown().optional() })),
|
|
191
|
-
occurredAt: z.iso.datetime(),
|
|
192
|
-
});
|
|
193
|
-
export type ApprovalRequestedEvent = z.infer<typeof approvalRequestedEventSchema>;
|
|
194
|
-
|
|
195
|
-
export const triggerFiringResponseSchema = z.discriminatedUnion("outcome", [
|
|
196
|
-
z.object({
|
|
197
|
-
firingId: z.uuid(),
|
|
198
|
-
outcome: z.literal("started"),
|
|
199
|
-
threadId: z.uuid(),
|
|
200
|
-
runId: z.string(),
|
|
201
|
-
}),
|
|
202
|
-
/* The shapes a caller that waited (`?wait=`) gets instead of `started`: the run ended, or it parked for a decision. */
|
|
203
|
-
z.object({
|
|
204
|
-
firingId: z.uuid(),
|
|
205
|
-
outcome: z.literal("awaiting_approval"),
|
|
206
|
-
threadId: z.uuid(),
|
|
207
|
-
runId: z.string(),
|
|
208
|
-
approvals: z.array(triggerApprovalSchema),
|
|
209
|
-
}),
|
|
210
|
-
z.object({
|
|
211
|
-
firingId: z.uuid(),
|
|
212
|
-
outcome: z.literal("completed"),
|
|
213
|
-
threadId: z.uuid(),
|
|
214
|
-
runId: z.string(),
|
|
215
|
-
/** The validated answer when the trigger declares an output schema, else null. */
|
|
216
|
-
output: z.unknown(),
|
|
217
|
-
}),
|
|
218
|
-
z.object({
|
|
219
|
-
firingId: z.uuid(),
|
|
220
|
-
outcome: z.literal("failed"),
|
|
221
|
-
threadId: z.uuid(),
|
|
222
|
-
runId: z.string(),
|
|
223
|
-
reason: z.string().nullable(),
|
|
224
|
-
}),
|
|
225
|
-
z.object({
|
|
226
|
-
firingId: z.uuid(),
|
|
227
|
-
outcome: z.literal("dropped"),
|
|
228
|
-
reason: z.enum(TRIGGER_DROP_REASONS),
|
|
229
|
-
threadId: z.uuid().nullable(),
|
|
230
|
-
}),
|
|
231
|
-
z.object({ firingId: z.uuid(), outcome: z.literal("disabled") }),
|
|
232
|
-
z.object({
|
|
233
|
-
firingId: z.uuid(),
|
|
234
|
-
outcome: z.literal("rejected"),
|
|
235
|
-
issues: z.array(z.object({ path: z.string(), message: z.string() })),
|
|
236
|
-
}),
|
|
237
|
-
]);
|
|
238
|
-
export type TriggerFiringResponse = z.infer<typeof triggerFiringResponseSchema>;
|
|
239
|
-
|
|
240
|
-
/** `POST /agents/:agentSlug/triggers/:name/firings/:id/answer`: the decision on one parked call. */
|
|
241
|
-
export const triggerFiringAnswerSchema = z.object({
|
|
242
|
-
toolCallId: z.string().min(1).max(256),
|
|
243
|
-
approved: z.boolean(),
|
|
244
|
-
});
|
|
245
|
-
export type TriggerFiringAnswer = z.infer<typeof triggerFiringAnswerSchema>;
|
|
246
|
-
|
|
247
|
-
/** One row of `GET /agents/:agentSlug/triggers/:name/firings`, and the answer of `.../firings/:id`. */
|
|
248
|
-
export const triggerFiringRecordSchema = z.object({
|
|
249
|
-
id: z.uuid(),
|
|
250
|
-
triggerName: z.string(),
|
|
251
|
-
threadId: z.uuid().nullable(),
|
|
252
|
-
runId: z.string().nullable(),
|
|
253
|
-
outcome: z.enum(TRIGGER_OUTCOMES),
|
|
254
|
-
reason: z.string().nullable(),
|
|
255
|
-
/** Set once a run with an output schema completed; null otherwise. */
|
|
256
|
-
output: z.unknown(),
|
|
257
|
-
/** The calls an `awaiting_approval` firing waits on; filled by the single-firing read, empty in the list and for every other outcome. */
|
|
258
|
-
approvals: z.array(triggerApprovalSchema),
|
|
259
|
-
createdAt: z.iso.datetime(),
|
|
260
|
-
finishedAt: z.iso.datetime().nullable(),
|
|
261
|
-
});
|
|
262
|
-
export type TriggerFiringRecord = z.infer<typeof triggerFiringRecordSchema>;
|
|
263
|
-
|
|
264
|
-
export const triggerFiringListResponseSchema = z.object({
|
|
265
|
-
firings: z.array(triggerFiringRecordSchema),
|
|
266
|
-
});
|
|
267
|
-
export type TriggerFiringListResponse = z.infer<typeof triggerFiringListResponseSchema>;
|