@capybara-hq/kernel 0.1.0-rc.3 → 0.1.0-rc.4
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/admin/admin.controller.d.ts +9 -4
- package/dist/admin/admin.controller.js +13 -4
- package/dist/admin/extensions.controller.d.ts +8 -1
- package/dist/admin/extensions.controller.js +22 -2
- package/dist/agents/agent-lookup.d.ts +3 -0
- package/dist/agents/agent-lookup.js +10 -0
- package/dist/agents/agent-profile.service.d.ts +29 -0
- package/dist/agents/agent-profile.service.js +117 -0
- package/dist/agents/agents.controller.d.ts +93 -3
- package/dist/agents/agents.controller.js +114 -4
- package/dist/agents/agents.module.js +6 -2
- package/dist/agents/agents.service.d.ts +13 -5
- package/dist/agents/agents.service.js +30 -7
- package/dist/agents/definition.d.ts +4 -0
- package/dist/agents/definition.js +10 -0
- package/dist/agents/instruction-files.d.ts +60 -0
- package/dist/agents/instruction-files.js +111 -0
- package/dist/agents/models.controller.d.ts +9 -3
- package/dist/agents/models.controller.js +19 -4
- package/dist/agents/profile.d.ts +96 -0
- package/dist/agents/profile.js +51 -0
- package/dist/agents/readiness.controller.d.ts +26 -0
- package/dist/agents/readiness.controller.js +56 -0
- package/dist/agents/templates.js +1 -1
- package/dist/background/background.controller.d.ts +38 -0
- package/dist/background/background.controller.js +87 -0
- package/dist/background/background.module.d.ts +10 -0
- package/dist/background/background.module.js +32 -0
- package/dist/background/finish.d.ts +43 -0
- package/dist/background/finish.js +94 -0
- package/dist/background/launch-lock.d.ts +14 -0
- package/dist/background/launch-lock.js +39 -0
- package/dist/background/launch.d.ts +36 -0
- package/dist/background/launch.js +70 -0
- package/dist/background/poll.job.d.ts +53 -0
- package/dist/background/poll.job.js +182 -0
- package/dist/background/render.d.ts +23 -0
- package/dist/background/render.js +48 -0
- package/dist/background/session.d.ts +37 -0
- package/dist/background/session.js +66 -0
- package/dist/background/status.d.ts +35 -0
- package/dist/background/status.js +57 -0
- package/dist/background/stop.d.ts +62 -0
- package/dist/background/stop.js +225 -0
- package/dist/background/store.d.ts +150 -0
- package/dist/background/store.js +351 -0
- package/dist/background/store.module.d.ts +6 -0
- package/dist/background/store.module.js +22 -0
- package/dist/background/tasks.service.d.ts +67 -0
- package/dist/background/tasks.service.js +186 -0
- package/dist/background/wake-rules.d.ts +57 -0
- package/dist/background/wake-rules.js +83 -0
- package/dist/background/wake.d.ts +28 -0
- package/dist/background/wake.js +57 -0
- package/dist/catalog/claude/agents.js +2 -0
- package/dist/catalog/marketplaces.service.d.ts +1 -1
- package/dist/catalog/plugin-import.js +1 -1
- package/dist/catalog/plugin-upgrade.js +1 -1
- package/dist/channels/cards.js +1 -1
- package/dist/channels/connections.service.d.ts +16 -1
- package/dist/channels/connections.service.js +38 -4
- package/dist/channels/threads.d.ts +5 -0
- package/dist/channels/threads.js +8 -0
- package/dist/config/schema.d.ts +18 -0
- package/dist/config/schema.js +102 -0
- package/dist/conversations/access.js +2 -0
- package/dist/conversations/attachments.service.d.ts +30 -0
- package/dist/conversations/attachments.service.js +130 -5
- package/dist/conversations/conversations.controller.d.ts +36 -5
- package/dist/conversations/conversations.controller.js +62 -12
- package/dist/conversations/conversations.module.js +3 -0
- package/dist/conversations/conversations.service.d.ts +44 -2
- package/dist/conversations/conversations.service.js +140 -12
- package/dist/conversations/event-log.d.ts +1 -1
- package/dist/conversations/event-log.js +10 -1
- package/dist/conversations/events.d.ts +58 -0
- package/dist/conversations/events.js +57 -2
- package/dist/conversations/queue.d.ts +3 -1
- package/dist/conversations/queue.js +13 -2
- package/dist/conversations/queue.service.js +3 -1
- package/dist/conversations/titles.d.ts +7 -0
- package/dist/conversations/titles.js +15 -0
- package/dist/db/kernel-schema.d.ts +58 -2
- package/dist/db/pool.d.ts +5 -0
- package/dist/db/pool.js +3 -0
- package/dist/errors.d.ts +8 -0
- package/dist/errors.js +8 -0
- package/dist/evals/run-replay.d.ts +5 -2
- package/dist/evals/run-replay.js +30 -7
- package/dist/evals/step-replay.js +12 -6
- package/dist/evals/trajectory.js +1 -1
- package/dist/extensions/admin-ops.js +2 -0
- package/dist/extensions/admin-view.d.ts +3 -1
- package/dist/extensions/admin-view.js +10 -2
- package/dist/extensions/blobs.js +1 -0
- package/dist/extensions/config-issues.d.ts +13 -1
- package/dist/extensions/config-issues.js +22 -5
- package/dist/extensions/config-json-schema.d.ts +43 -7
- package/dist/extensions/config-json-schema.js +124 -58
- package/dist/extensions/deployment-config-store.d.ts +6 -0
- package/dist/extensions/deployment-config.d.ts +50 -3
- package/dist/extensions/deployment-config.js +125 -28
- package/dist/extensions/display-name.d.ts +22 -0
- package/dist/extensions/display-name.js +77 -0
- package/dist/extensions/extensions.module.js +6 -0
- package/dist/extensions/host.d.ts +26 -1
- package/dist/extensions/host.js +82 -9
- package/dist/extensions/org-config.controller.d.ts +11 -3
- package/dist/extensions/org-config.controller.js +14 -6
- package/dist/extensions/org-config.d.ts +6 -0
- package/dist/extensions/org-config.js +12 -13
- package/dist/extensions/package.d.ts +14 -1
- package/dist/extensions/package.js +51 -2
- package/dist/extensions/permission-view.d.ts +3 -0
- package/dist/extensions/point-defaults.controller.d.ts +34 -0
- package/dist/extensions/point-defaults.controller.js +71 -0
- package/dist/extensions/point-defaults.d.ts +64 -0
- package/dist/extensions/point-defaults.js +206 -0
- package/dist/extensions/registry.d.ts +1 -1
- package/dist/extensions/registry.js +2 -0
- package/dist/http/api.module.js +8 -0
- package/dist/http/nest-logger.d.ts +6 -5
- package/dist/http/nest-logger.js +24 -10
- package/dist/identity/auth.controller.js +9 -5
- package/dist/identity/cookies.d.ts +20 -5
- package/dist/identity/cookies.js +44 -6
- package/dist/identity/me.controller.d.ts +5 -1
- package/dist/identity/me.controller.js +12 -3
- package/dist/identity/sessions.d.ts +12 -0
- package/dist/identity/sessions.js +45 -0
- package/dist/index.d.ts +1 -1
- package/dist/infra/config/kernel-config.service.js +6 -0
- package/dist/infra/database/database.module.js +1 -0
- package/dist/infra/events/kernel-events.d.ts +8 -0
- package/dist/infra/lifecycle/process-guards.js +4 -0
- package/dist/infra/logging/logging.module.d.ts +4 -2
- package/dist/infra/logging/logging.module.js +24 -6
- package/dist/infra/queue/redis-connection.d.ts +6 -0
- package/dist/infra/queue/redis-connection.js +7 -0
- package/dist/infra/redis/redis.module.js +6 -2
- package/dist/infra/tokens.d.ts +6 -1
- package/dist/infra/tokens.js +6 -1
- package/dist/log.d.ts +13 -1
- package/dist/log.js +93 -17
- package/dist/models/purposes.d.ts +23 -0
- package/dist/models/purposes.js +31 -10
- package/dist/orgs/offboarding.d.ts +3 -1
- package/dist/orgs/offboarding.js +26 -16
- package/dist/orgs/settings.service.d.ts +5 -0
- package/dist/orgs/settings.service.js +13 -2
- package/dist/roles/worker.module.js +6 -0
- package/dist/runtime/context/build.d.ts +9 -7
- package/dist/runtime/context/build.js +27 -19
- package/dist/runtime/context/claude-tools.d.ts +2 -1
- package/dist/runtime/context/claude-tools.js +5 -4
- package/dist/runtime/context/compaction.js +4 -0
- package/dist/runtime/langgraph-loop.js +3 -2
- package/dist/runtime/loop.d.ts +4 -3
- package/dist/runtime/maintenance.d.ts +4 -2
- package/dist/runtime/maintenance.js +17 -5
- package/dist/runtime/model-call.d.ts +17 -1
- package/dist/runtime/model-call.js +3 -2
- package/dist/runtime/providers.d.ts +6 -0
- package/dist/runtime/providers.js +8 -0
- package/dist/runtime/run-queue.d.ts +25 -2
- package/dist/runtime/run-queue.js +129 -33
- package/dist/runtime/run-worker.js +16 -3
- package/dist/runtime/runtime.module.js +8 -3
- package/dist/runtime/step-log.d.ts +6 -0
- package/dist/runtime/step-log.js +16 -2
- package/dist/runtime/subagents/definition.js +3 -1
- package/dist/runtime/usage-report.d.ts +2 -1
- package/dist/runtime/usage-report.js +2 -1
- package/dist/runtime/waits.d.ts +8 -2
- package/dist/runtime/waits.js +37 -11
- package/dist/sandbox/sandbox.module.js +6 -1
- package/dist/sandbox/sandbox.service.d.ts +61 -3
- package/dist/sandbox/sandbox.service.js +141 -7
- package/dist/tools/approvals.service.js +2 -0
- package/dist/tools/builtin-names.d.ts +20 -2
- package/dist/tools/builtin-names.js +29 -2
- package/dist/tools/builtins/builtin-tools.d.ts +15 -1
- package/dist/tools/builtins/builtin-tools.js +34 -2
- package/dist/tools/builtins/sandbox/bash.d.ts +1 -1
- package/dist/tools/builtins/sandbox/bash.js +230 -3
- package/dist/tools/builtins/sandbox/common.d.ts +27 -4
- package/dist/tools/builtins/sandbox/common.js +7 -3
- package/dist/tools/builtins/sandbox/deliver.js +1 -1
- package/dist/tools/builtins/sandbox/index.d.ts +2 -0
- package/dist/tools/builtins/sandbox/index.js +6 -0
- package/dist/tools/builtins/sandbox/task-output.d.ts +63 -0
- package/dist/tools/builtins/sandbox/task-output.js +304 -0
- package/dist/tools/builtins/sandbox/task-stop.d.ts +10 -0
- package/dist/tools/builtins/sandbox/task-stop.js +112 -0
- package/dist/tools/builtins/web/errors.d.ts +8 -0
- package/dist/tools/builtins/web/errors.js +53 -0
- package/dist/tools/builtins/web/extract.d.ts +62 -0
- package/dist/tools/builtins/web/extract.js +267 -0
- package/dist/tools/builtins/web/fetch.d.ts +55 -0
- package/dist/tools/builtins/web/fetch.js +174 -0
- package/dist/tools/builtins/web/index.d.ts +13 -0
- package/dist/tools/builtins/web/index.js +12 -0
- package/dist/tools/builtins/web/page-cache.d.ts +25 -0
- package/dist/tools/builtins/web/page-cache.js +77 -0
- package/dist/tools/builtins/web/search.d.ts +25 -0
- package/dist/tools/builtins/web/search.js +209 -0
- package/dist/tools/builtins/web/url.d.ts +17 -0
- package/dist/tools/builtins/web/url.js +43 -0
- package/dist/tools/oauth/flow-paths.d.ts +1 -1
- package/dist/tools/oauth/flow-paths.js +1 -1
- package/dist/tools/pipeline.js +15 -0
- package/dist/tools/registry.d.ts +22 -3
- package/dist/tools/registry.js +26 -11
- package/dist/tools/tools.module.js +12 -0
- package/dist/tools/validate.js +1 -1
- package/package.json +3 -3
- package/src/migrations/0064_account_last_org.sql +7 -0
- package/src/migrations/0065_conversation_archive.sql +8 -0
- package/src/migrations/0066_extension_display_name.sql +4 -0
- package/src/migrations/0067_agent_profiles.sql +20 -0
- package/src/migrations/0068_agent_avatar_uploads.sql +7 -0
- package/src/migrations/0069_attachments_agent_idx.sql +3 -0
- package/src/migrations/0070_background_tasks.sql +37 -0
- package/src/migrations/0071_background_tasks_reserve.sql +6 -0
- package/src/migrations/0072_background_tasks_stopping.sql +5 -0
- package/src/migrations/0073_org_extension_point_defaults.sql +11 -0
|
@@ -33,6 +33,13 @@ export declare const TITLE_MAX_OUTPUT_TOKENS = 32;
|
|
|
33
33
|
export declare const TITLE_MAX_CHARS = 120;
|
|
34
34
|
/** Each side of the excerpt is cut to this many characters. */
|
|
35
35
|
export declare const TITLE_EXCERPT_CHARS = 1000;
|
|
36
|
+
/**
|
|
37
|
+
* Parameters of the title call where the target model declares them and the `title` purpose does
|
|
38
|
+
* not set them: no thinking, so the {@link TITLE_MAX_OUTPUT_TOKENS} budget goes to the title.
|
|
39
|
+
*/
|
|
40
|
+
export declare const TITLE_PARAM_DEFAULTS: {
|
|
41
|
+
readonly thinking: "off";
|
|
42
|
+
};
|
|
36
43
|
/** Time limit of one title call. */
|
|
37
44
|
export declare const TITLE_TIMEOUT_MS = 60000;
|
|
38
45
|
/** The system prompt of the title call (model-facing, English). */
|
|
@@ -51,6 +51,11 @@ export const TITLE_MAX_OUTPUT_TOKENS = 32;
|
|
|
51
51
|
export const TITLE_MAX_CHARS = 120;
|
|
52
52
|
/** Each side of the excerpt is cut to this many characters. */
|
|
53
53
|
export const TITLE_EXCERPT_CHARS = 1000;
|
|
54
|
+
/**
|
|
55
|
+
* Parameters of the title call where the target model declares them and the `title` purpose does
|
|
56
|
+
* not set them: no thinking, so the {@link TITLE_MAX_OUTPUT_TOKENS} budget goes to the title.
|
|
57
|
+
*/
|
|
58
|
+
export const TITLE_PARAM_DEFAULTS = { thinking: "off" };
|
|
54
59
|
/** Time limit of one title call. */
|
|
55
60
|
export const TITLE_TIMEOUT_MS = 60_000;
|
|
56
61
|
/** How far into the log the excerpt is looked for (events). */
|
|
@@ -204,6 +209,8 @@ export async function runTitleJob(d, conversationId, attempt) {
|
|
|
204
209
|
maxOutputTokens: TITLE_MAX_OUTPUT_TOKENS,
|
|
205
210
|
}, signal, {
|
|
206
211
|
...(fallback && { fallback: { model: fallback, params: {} } }),
|
|
212
|
+
// a thinking model spends the small output budget on thinking and returns no text
|
|
213
|
+
paramDefaults: TITLE_PARAM_DEFAULTS,
|
|
207
214
|
beforeSend: async (target, request) => {
|
|
208
215
|
await checkTitleHooks(d, scope, target, request, signal);
|
|
209
216
|
sent = { ...target, at: Date.now() };
|
|
@@ -246,6 +253,14 @@ export async function runTitleJob(d, conversationId, attempt) {
|
|
|
246
253
|
if (sent && d.hooks)
|
|
247
254
|
observeTitle(d, scope, sent, out, null, signal);
|
|
248
255
|
const title = cleanTitle(textOf(out.content));
|
|
256
|
+
if (title === null) {
|
|
257
|
+
d.log.warn("conversation title call returned no title", {
|
|
258
|
+
conversationId,
|
|
259
|
+
attempt,
|
|
260
|
+
stopReason: out.stopReason,
|
|
261
|
+
outputTokens: out.usage.outputTokens,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
249
264
|
const { written, usage } = await d.writes.writeResult(conversationId, attempt, out, title);
|
|
250
265
|
if (usage) {
|
|
251
266
|
await d.eventLog.notify(conversationId, usage.seq);
|
|
@@ -14,6 +14,8 @@ export interface AccountsTable {
|
|
|
14
14
|
is_enterprise_admin: Generated<boolean>;
|
|
15
15
|
created_at: Ts;
|
|
16
16
|
updated_at: Ts;
|
|
17
|
+
/** 0064: the org the account last chose as current; a new session starts in it. */
|
|
18
|
+
last_org_id: ColumnType<string | null, string | null | undefined, string | null>;
|
|
17
19
|
}
|
|
18
20
|
export interface IdentitiesTable {
|
|
19
21
|
source: string;
|
|
@@ -149,6 +151,11 @@ export interface AgentsTable {
|
|
|
149
151
|
org_role: Generated<"admin" | "member" | "guest">;
|
|
150
152
|
current_version: number;
|
|
151
153
|
needs_reassignment: Generated<boolean>;
|
|
154
|
+
/** 0067: the profile (display data, outside the versions). */
|
|
155
|
+
profile_avatar: ColumnType<Record<string, unknown> | null, string | null | undefined, string | null>;
|
|
156
|
+
profile_description: Generated<string>;
|
|
157
|
+
profile_quick_actions: ColumnType<unknown[], string | undefined, string>;
|
|
158
|
+
profile_updated_at: Ts;
|
|
152
159
|
created_at: Ts;
|
|
153
160
|
updated_at: Ts;
|
|
154
161
|
deleted_at: TsNullable;
|
|
@@ -199,6 +206,10 @@ export interface ConversationsTable {
|
|
|
199
206
|
queue_paused: ColumnType<boolean, boolean | undefined, boolean>;
|
|
200
207
|
/** 0062: why the queue paused (`QueuePauseReason`); null when not paused or not recorded. */
|
|
201
208
|
queue_pause_reason: ColumnType<string | null, string | null | undefined, string | null>;
|
|
209
|
+
/** 0065: when the owner archived it (hidden from the default lists); null = not archived. */
|
|
210
|
+
archived_at: ColumnType<Date | null, Date | string | null | undefined, Date | string | null>;
|
|
211
|
+
/** 0065: when the owner deleted it (soft delete: hidden everywhere for the owner); null = live. */
|
|
212
|
+
deleted_at: ColumnType<Date | null, Date | string | null | undefined, Date | string | null>;
|
|
202
213
|
}
|
|
203
214
|
/** 0060: an org's order of file-preview@1 previewers (UI refresh B Task 11). */
|
|
204
215
|
export interface FilePreviewersTable {
|
|
@@ -208,6 +219,15 @@ export interface FilePreviewersTable {
|
|
|
208
219
|
position: number;
|
|
209
220
|
disabled: ColumnType<boolean, boolean | undefined, boolean>;
|
|
210
221
|
}
|
|
222
|
+
/** 0073: an org's default provider of an `org-default` extension point. */
|
|
223
|
+
export interface OrgExtensionPointDefaultsTable {
|
|
224
|
+
org_id: string;
|
|
225
|
+
/** The extension point name without the major (`web-search`). */
|
|
226
|
+
point: string;
|
|
227
|
+
extension: string;
|
|
228
|
+
updated_at: Ts;
|
|
229
|
+
updated_by: string | null;
|
|
230
|
+
}
|
|
211
231
|
/** 0059: a queued message (not in the event log until sent). */
|
|
212
232
|
export interface ConversationQueueTable {
|
|
213
233
|
id: string;
|
|
@@ -547,9 +567,11 @@ export interface AttachmentsTable {
|
|
|
547
567
|
expires_at: TsNullable;
|
|
548
568
|
/** 0024:上传用途(技能包不能绑定到消息)。 */
|
|
549
569
|
purpose: ColumnType<AttachmentPurpose, AttachmentPurpose | undefined, AttachmentPurpose>;
|
|
570
|
+
/** 0068: the agent whose profile uses this avatar upload (set once, when it is saved). */
|
|
571
|
+
agent_id: ColumnType<string | null, string | null | undefined, string | null>;
|
|
550
572
|
}
|
|
551
|
-
/** 预签名上传的用途:对话附件 / 技能包 zip
|
|
552
|
-
export type AttachmentPurpose = "chat" | "skill-package";
|
|
573
|
+
/** 预签名上传的用途:对话附件 / 技能包 zip / agent avatar image. */
|
|
574
|
+
export type AttachmentPurpose = "chat" | "skill-package" | "agent-avatar";
|
|
553
575
|
/** 技能版本的清单(`skill_versions.manifest`)。 */
|
|
554
576
|
export interface SkillManifest {
|
|
555
577
|
name: string;
|
|
@@ -630,6 +652,33 @@ export interface SkillChangeRequestsTable {
|
|
|
630
652
|
decided_at: TsNullable;
|
|
631
653
|
created_at: Ts;
|
|
632
654
|
}
|
|
655
|
+
/** 0070_background_tasks.sql: a Bash command running in the background in a conversation's sandbox. */
|
|
656
|
+
export interface BackgroundTasksTable {
|
|
657
|
+
id: string;
|
|
658
|
+
org_id: string;
|
|
659
|
+
conversation_id: string;
|
|
660
|
+
sandbox_conversation_id: string;
|
|
661
|
+
run_id: string;
|
|
662
|
+
call_id: string;
|
|
663
|
+
trigger_account_id: string;
|
|
664
|
+
description: string;
|
|
665
|
+
command: string;
|
|
666
|
+
/** NULL while the launch is reserved but not started (0071). */
|
|
667
|
+
sid: string | null;
|
|
668
|
+
output_path: string;
|
|
669
|
+
status: ColumnType<"running" | "completed" | "failed" | "stopped" | "timed_out" | "lost", string | undefined, string>;
|
|
670
|
+
lost_reason: ColumnType<string | null, string | null | undefined, string | null>;
|
|
671
|
+
exit_code: ColumnType<number | null, number | null | undefined, number | null>;
|
|
672
|
+
started_at: Ts;
|
|
673
|
+
finished_at: TsNullable;
|
|
674
|
+
deadline_at: Date | string;
|
|
675
|
+
/** NULL while the launch is reserved but not started (0071). */
|
|
676
|
+
sandbox_created_at: Date | string | null;
|
|
677
|
+
kill_pending: ColumnType<boolean, boolean | undefined, boolean>;
|
|
678
|
+
read_offset: ColumnType<string, number | string | undefined, number | string>;
|
|
679
|
+
/** Set while a stop is under way (0072); the poller skips such a task. */
|
|
680
|
+
stopping_at: ColumnType<Date | null, Date | string | null | undefined, Date | string | null>;
|
|
681
|
+
}
|
|
633
682
|
/** 0023_sandboxes.sql:按对话的沙箱(见 sandbox/sandbox.service.ts)。 */
|
|
634
683
|
export interface SandboxesTable {
|
|
635
684
|
conversation_id: string;
|
|
@@ -788,6 +837,11 @@ export interface ExtensionPackagesTable {
|
|
|
788
837
|
source_ref: string;
|
|
789
838
|
uploaded_by: string | null;
|
|
790
839
|
created_at: Ts;
|
|
840
|
+
/** 0066: the plugin.json `displayName`; null without one and for packages stored before 0066. */
|
|
841
|
+
display_name: ColumnType<{
|
|
842
|
+
zh: string;
|
|
843
|
+
en: string;
|
|
844
|
+
} | null, string | null | undefined, string | null>;
|
|
791
845
|
}
|
|
792
846
|
/** 0030, renamed in 0041: package bytes when there is no object storage. */
|
|
793
847
|
export interface ExtensionBlobsTable {
|
|
@@ -867,6 +921,7 @@ export interface KernelDatabase {
|
|
|
867
921
|
conversation_events: ConversationEventsTable;
|
|
868
922
|
conversation_queue: ConversationQueueTable;
|
|
869
923
|
file_previewers: FilePreviewersTable;
|
|
924
|
+
org_extension_point_defaults: OrgExtensionPointDefaultsTable;
|
|
870
925
|
runs: RunsTable;
|
|
871
926
|
subagent_dispatches: SubagentDispatchesTable;
|
|
872
927
|
agent_templates: AgentTemplatesTable;
|
|
@@ -890,6 +945,7 @@ export interface KernelDatabase {
|
|
|
890
945
|
directory_exclusions: DirectoryExclusionsTable;
|
|
891
946
|
attachments: AttachmentsTable;
|
|
892
947
|
sandboxes: SandboxesTable;
|
|
948
|
+
background_tasks: BackgroundTasksTable;
|
|
893
949
|
skills: SkillsTable;
|
|
894
950
|
skill_versions: SkillVersionsTable;
|
|
895
951
|
skill_change_requests: SkillChangeRequestsTable;
|
package/dist/db/pool.d.ts
CHANGED
|
@@ -18,6 +18,11 @@ export declare function pgConnectOptions(cfg: {
|
|
|
18
18
|
*/
|
|
19
19
|
export declare function createDb(url: string, poolMax: number, onError?: (err: Error) => void, opts?: {
|
|
20
20
|
connectTimeoutMs?: number | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* How long an idle client stays in the pool (pg's `idleTimeoutMillis`; unset = pg's 10 s).
|
|
23
|
+
* Every new client costs a TCP + auth handshake, several round trips to a distant database.
|
|
24
|
+
*/
|
|
25
|
+
idleTimeoutMs?: number | undefined;
|
|
21
26
|
/**
|
|
22
27
|
* Error of a client while it is checked out: pg-pool drops its own listener on checkout, so
|
|
23
28
|
* without this a backend killed between two statements is an uncaught exception.
|
package/dist/db/pool.js
CHANGED
|
@@ -22,6 +22,9 @@ export function createDb(url, poolMax, onError = (err) => console.error("[db] id
|
|
|
22
22
|
connectionString: url,
|
|
23
23
|
max: poolMax,
|
|
24
24
|
...pgConnectOptions(opts),
|
|
25
|
+
...(opts.idleTimeoutMs !== undefined && { idleTimeoutMillis: opts.idleTimeoutMs }),
|
|
26
|
+
// a client kept idle longer must notice a dead peer (a dropped VPN, a NAT timeout) by itself
|
|
27
|
+
keepAlive: true,
|
|
25
28
|
});
|
|
26
29
|
pool.on("error", onError);
|
|
27
30
|
pool.on("connect", (client) => client.on("error", opts.onClientError ?? onError));
|
package/dist/errors.d.ts
CHANGED
|
@@ -110,7 +110,11 @@ export declare const ERROR_CODES: {
|
|
|
110
110
|
readonly "setup.token_invalid": 403;
|
|
111
111
|
readonly "agent.not_found": 404;
|
|
112
112
|
readonly "agent.version_conflict": 409;
|
|
113
|
+
/** The profile was changed since the client read it (`expectedUpdatedAt` is stale). */
|
|
114
|
+
readonly "agent.profile_conflict": 409;
|
|
113
115
|
readonly "agent.model_unavailable": 400;
|
|
116
|
+
/** A save gave `instructionFiles` and an `instructions` that is not their join. */
|
|
117
|
+
readonly "agent.instructions_mismatch": 400;
|
|
114
118
|
/**
|
|
115
119
|
* `skills.pinned` of an agent definition is refused (details: `{ skill, reason, totalBytes? }`;
|
|
116
120
|
* reasons `not_selected`, `not_found`, `duplicate`, `too_many`, `too_large`, `manual_only`).
|
|
@@ -130,6 +134,10 @@ export declare const ERROR_CODES: {
|
|
|
130
134
|
/** A sub-agent's conversation takes no messages from people (sub-agents spec §6.1). */
|
|
131
135
|
readonly "conversation.read_only": 409;
|
|
132
136
|
readonly "run.not_active": 409;
|
|
137
|
+
/** A background task that is not in this conversation (or its sub-agents), or does not exist. */
|
|
138
|
+
readonly "background_task.not_found": 404;
|
|
139
|
+
/** The task's output cannot be read now (its sandbox is not running and no finish recorded it). */
|
|
140
|
+
readonly "background_task.output_unavailable": 409;
|
|
133
141
|
readonly "connector.not_found": 404;
|
|
134
142
|
readonly "connector.slug_taken": 409;
|
|
135
143
|
readonly "connector.connect_failed": 502;
|
package/dist/errors.js
CHANGED
|
@@ -110,7 +110,11 @@ export const ERROR_CODES = {
|
|
|
110
110
|
"setup.token_invalid": 403,
|
|
111
111
|
"agent.not_found": 404,
|
|
112
112
|
"agent.version_conflict": 409,
|
|
113
|
+
/** The profile was changed since the client read it (`expectedUpdatedAt` is stale). */
|
|
114
|
+
"agent.profile_conflict": 409,
|
|
113
115
|
"agent.model_unavailable": 400,
|
|
116
|
+
/** A save gave `instructionFiles` and an `instructions` that is not their join. */
|
|
117
|
+
"agent.instructions_mismatch": 400,
|
|
114
118
|
/**
|
|
115
119
|
* `skills.pinned` of an agent definition is refused (details: `{ skill, reason, totalBytes? }`;
|
|
116
120
|
* reasons `not_selected`, `not_found`, `duplicate`, `too_many`, `too_large`, `manual_only`).
|
|
@@ -130,6 +134,10 @@ export const ERROR_CODES = {
|
|
|
130
134
|
/** A sub-agent's conversation takes no messages from people (sub-agents spec §6.1). */
|
|
131
135
|
"conversation.read_only": 409,
|
|
132
136
|
"run.not_active": 409,
|
|
137
|
+
/** A background task that is not in this conversation (or its sub-agents), or does not exist. */
|
|
138
|
+
"background_task.not_found": 404,
|
|
139
|
+
/** The task's output cannot be read now (its sandbox is not running and no finish recorded it). */
|
|
140
|
+
"background_task.output_unavailable": 409,
|
|
133
141
|
"connector.not_found": 404,
|
|
134
142
|
"connector.slug_taken": 409,
|
|
135
143
|
"connector.connect_failed": 502,
|
|
@@ -19,7 +19,10 @@ import type { ResolvedCandidate } from "./step-replay.js";
|
|
|
19
19
|
*
|
|
20
20
|
* - 种子:原运行 `run_started` 之前的事件按原 seq 插入(`last_seq` 停在其前一位,新的 `run_started` 因此与原来同 seq),
|
|
21
21
|
* 原运行开始时的 `skills_catalog` 照抄;然后写 `runs` 行与 `run_started`,`agent` 用候选定义。
|
|
22
|
-
* -
|
|
22
|
+
* - 插话:原运行中途吸收的可吸收事件(user_message, and finished background tasks: background Bash
|
|
23
|
+
* spec §4.4),在「原吸收步骤 ≤ 当前步骤」时追加进评测对话并交给 loop(a recorded finish is
|
|
24
|
+
* appended as recorded: no task starts, polls or stops)。
|
|
25
|
+
* - A wake run (its boundary a finished background task, not a message) is seeded from that event.
|
|
23
26
|
* - 计费(C7,与单步回放同一套):每次模型请求(含压缩、重试、兜底)发出前查运行仍在执行、仍持有认领;
|
|
24
27
|
* 收完按真实用量、没收完按估算 `consumeTokens`(越限即 `capped`,下一次请求前停下)。
|
|
25
28
|
* - 附件按快照自己的组织与原对话取(C3)。
|
|
@@ -101,7 +104,7 @@ export interface ReplaySeed {
|
|
|
101
104
|
/** The conversation's `consumed_seq` when the original run started. */
|
|
102
105
|
consumed: number;
|
|
103
106
|
seeds: SnapshotEvent[];
|
|
104
|
-
/** The run's trigger seq (the last
|
|
107
|
+
/** The run's trigger seq (its boundary: the last unconsumed message, or the waking finish). */
|
|
105
108
|
trigger: number;
|
|
106
109
|
agentVersion: number;
|
|
107
110
|
model: ModelRef;
|
package/dist/evals/run-replay.js
CHANGED
|
@@ -13,6 +13,7 @@ import { Inject, Injectable } from "@nestjs/common";
|
|
|
13
13
|
import { sql } from "kysely";
|
|
14
14
|
import { normalizeStoredDefinition } from "../agents/definition.js";
|
|
15
15
|
import { EventLog } from "../conversations/event-log.js";
|
|
16
|
+
import { isAbsorbable, } from "../conversations/events.js";
|
|
16
17
|
import { ApiError } from "../errors.js";
|
|
17
18
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
18
19
|
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
@@ -260,6 +261,28 @@ function absorbedByStep(s) {
|
|
|
260
261
|
}
|
|
261
262
|
return out;
|
|
262
263
|
}
|
|
264
|
+
/**
|
|
265
|
+
* The replayed run's boundary (`trigger_seq`): a wake run's recorded one (`run_started.triggerSeq`,
|
|
266
|
+
* background Bash spec §3); otherwise the newest message after `consumed`, else the newest finish
|
|
267
|
+
* after it that could have woken the run (not reported, no `stoppedBy`), else the last
|
|
268
|
+
* message (old logs, as before).
|
|
269
|
+
*/
|
|
270
|
+
function replayTrigger(started, seeds, consumed) {
|
|
271
|
+
const recorded = started;
|
|
272
|
+
if (recorded.trigger === "background_task" && recorded.triggerSeq !== undefined) {
|
|
273
|
+
return recorded.triggerSeq;
|
|
274
|
+
}
|
|
275
|
+
const lastMessage = seeds.findLast((e) => e.type === "user_message")?.seq;
|
|
276
|
+
if (lastMessage !== undefined && lastMessage > consumed)
|
|
277
|
+
return lastMessage;
|
|
278
|
+
const wake = seeds.findLast((e) => {
|
|
279
|
+
if (e.type !== "background_task_finished" || e.seq <= consumed)
|
|
280
|
+
return false;
|
|
281
|
+
const p = e.payload;
|
|
282
|
+
return !p.reported && p.stoppedBy === undefined;
|
|
283
|
+
})?.seq;
|
|
284
|
+
return wake ?? lastMessage ?? 0;
|
|
285
|
+
}
|
|
263
286
|
const readAll = async (eventLog, conversationId) => {
|
|
264
287
|
const out = [];
|
|
265
288
|
let after = 0;
|
|
@@ -294,7 +317,7 @@ export async function replayRun(d, s, candidate, evalRunId, signal) {
|
|
|
294
317
|
consumed = Math.max(consumed, e.payload.consumedUpToSeq);
|
|
295
318
|
}
|
|
296
319
|
}
|
|
297
|
-
const trigger =
|
|
320
|
+
const trigger = replayTrigger(start.payload, seeds, consumed);
|
|
298
321
|
const catalog = s.events.find((e) => e.runId === s.runId && e.type === "skills_catalog" && e.seq > R);
|
|
299
322
|
// a sub-agent's case (spec §15.3) runs the effective definition frozen in its subagent_started
|
|
300
323
|
// (the request renders that event's preamble and instructions; its tools come from it too), with
|
|
@@ -427,7 +450,7 @@ export async function replayRun(d, s, candidate, evalRunId, signal) {
|
|
|
427
450
|
return "stop";
|
|
428
451
|
},
|
|
429
452
|
});
|
|
430
|
-
//
|
|
453
|
+
// 插话:原运行开始之后到达、且被原运行某一步吸收的可吸收事件(user_message / background_task_finished)
|
|
431
454
|
const absorbed = absorbedByStep(s);
|
|
432
455
|
const stepsInOrder = [...absorbed.keys()].sort((a, b) => a - b);
|
|
433
456
|
/** 第 k 步(含)之前原运行吸收到的最大位置;原运行没有模型调用时不设限。 */
|
|
@@ -442,7 +465,7 @@ export async function replayRun(d, s, candidate, evalRunId, signal) {
|
|
|
442
465
|
return cap;
|
|
443
466
|
};
|
|
444
467
|
const interjections = s.events
|
|
445
|
-
.filter((e) => e.type === "user_message" && e.seq > R)
|
|
468
|
+
.filter((e) => (e.type === "user_message" || e.type === "background_task_finished") && e.seq > R)
|
|
446
469
|
.flatMap((e) => {
|
|
447
470
|
const step = stepsInOrder.find((k) => absorbed.get(k) >= e.seq);
|
|
448
471
|
return step === undefined ? [] : [{ event: e, step }];
|
|
@@ -450,7 +473,7 @@ export async function replayRun(d, s, candidate, evalRunId, signal) {
|
|
|
450
473
|
/** 已追加的插话:原 seq → 评测对话里的 seq。 */
|
|
451
474
|
const fed = new Map();
|
|
452
475
|
let prepared = 0;
|
|
453
|
-
const
|
|
476
|
+
const pendingAbsorbable = async (afterSeq) => {
|
|
454
477
|
prepared++;
|
|
455
478
|
// loop 的步骤从 1 起(与运行时相同),每步的 prepare 调用一次:第 n 次调用即第 n 步
|
|
456
479
|
const k = prepared;
|
|
@@ -459,7 +482,7 @@ export async function replayRun(d, s, candidate, evalRunId, signal) {
|
|
|
459
482
|
continue;
|
|
460
483
|
const [w] = await eventLog.append(conversationId, [
|
|
461
484
|
{
|
|
462
|
-
type:
|
|
485
|
+
type: x.event.type,
|
|
463
486
|
idemKey: `replay_interjection:${runId}:${x.event.seq}`,
|
|
464
487
|
payload: x.event.payload,
|
|
465
488
|
},
|
|
@@ -471,7 +494,7 @@ export async function replayRun(d, s, candidate, evalRunId, signal) {
|
|
|
471
494
|
const fedSeqs = new Set(fed.values());
|
|
472
495
|
const out = [];
|
|
473
496
|
for (const e of await readAll(eventLog, conversationId)) {
|
|
474
|
-
if (e
|
|
497
|
+
if (!isAbsorbable(e) || e.seq <= afterSeq)
|
|
475
498
|
continue;
|
|
476
499
|
if (fedSeqs.has(e.seq) || (e.seq < R && e.seq <= cap))
|
|
477
500
|
out.push(e);
|
|
@@ -502,7 +525,7 @@ export async function replayRun(d, s, candidate, evalRunId, signal) {
|
|
|
502
525
|
signal: loopSignal,
|
|
503
526
|
shutdown: new AbortController().signal,
|
|
504
527
|
sink: () => { },
|
|
505
|
-
|
|
528
|
+
pendingAbsorbable,
|
|
506
529
|
limits: {
|
|
507
530
|
maxSteps: subagent === undefined ? runtime.maxSteps : Math.min(subagent.maxSteps, runtime.maxSteps),
|
|
508
531
|
deadline,
|
|
@@ -54,10 +54,9 @@ subagent) {
|
|
|
54
54
|
? { ...(from.modelParams ?? {}) }
|
|
55
55
|
: {});
|
|
56
56
|
const definition = {
|
|
57
|
-
...from,
|
|
57
|
+
...withInstructions(from, c.instructions),
|
|
58
58
|
model,
|
|
59
59
|
modelParams: params,
|
|
60
|
-
...(c.instructions !== undefined && { instructions: c.instructions }),
|
|
61
60
|
};
|
|
62
61
|
const changed = agentVersion !== base.agentVersion ||
|
|
63
62
|
!sameModel(model, base.definition.model) ||
|
|
@@ -73,13 +72,20 @@ subagent) {
|
|
|
73
72
|
changed,
|
|
74
73
|
overridesSwitch,
|
|
75
74
|
...(otherVersion && {
|
|
76
|
-
subagentVersion:
|
|
77
|
-
...versionDef,
|
|
78
|
-
...(c.instructions !== undefined && { instructions: c.instructions }),
|
|
79
|
-
},
|
|
75
|
+
subagentVersion: withInstructions(versionDef, c.instructions),
|
|
80
76
|
}),
|
|
81
77
|
};
|
|
82
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* A candidate's `instructions` override: the prompt files it was joined from no longer describe
|
|
81
|
+
* it, so they are dropped (never model-visible either way).
|
|
82
|
+
*/
|
|
83
|
+
function withInstructions(def, instructions) {
|
|
84
|
+
if (instructions === undefined)
|
|
85
|
+
return def;
|
|
86
|
+
const { instructionFiles: _files, ...rest } = def;
|
|
87
|
+
return { ...rest, instructions };
|
|
88
|
+
}
|
|
83
89
|
/**
|
|
84
90
|
* 候选请求已经发出、但没有正常收完(出错、超时、中止):`tokens` 是这次尝试应计入预算的估算用量,
|
|
85
91
|
* `cause` 是原始错误(调用方按它分类重试)。请求发出之前的失败(解析模型、取附件)原样抛出,不计费。
|
package/dist/evals/trajectory.js
CHANGED
|
@@ -130,7 +130,7 @@ function buildRun({ started, events }, prices, forks) {
|
|
|
130
130
|
assistants.set(e.payload.step, [...(assistants.get(e.payload.step) ?? []), e]);
|
|
131
131
|
break;
|
|
132
132
|
case "usage":
|
|
133
|
-
// a compaction or
|
|
133
|
+
// a compaction, title or web_fetch call's usage is not a step call's: counted in the totals only (I-1)
|
|
134
134
|
if (e.payload.purpose !== undefined) {
|
|
135
135
|
compactions.push(e);
|
|
136
136
|
break;
|
|
@@ -396,6 +396,8 @@ export { ExtensionAdminOps };
|
|
|
396
396
|
function fallbackView(name, known, err) {
|
|
397
397
|
return {
|
|
398
398
|
name,
|
|
399
|
+
// the degraded item reads nothing more (the read that failed may be the database)
|
|
400
|
+
displayName: null,
|
|
399
401
|
version: known.version,
|
|
400
402
|
source: "install",
|
|
401
403
|
sha256: known.sha256,
|
|
@@ -5,6 +5,7 @@ import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
|
5
5
|
import type { KernelLogger } from "../log.js";
|
|
6
6
|
import { ExtensionApprovals } from "./approvals.js";
|
|
7
7
|
import { ExtensionBlobs } from "./blobs.js";
|
|
8
|
+
import { ExtensionDisplayNames } from "./display-name.js";
|
|
8
9
|
import { ExtensionHost } from "./host.js";
|
|
9
10
|
import { ExtensionInstalls } from "./installs.js";
|
|
10
11
|
import { ExtensionLifecycle, PLUGINS_CHANGED_TOPIC } from "./lifecycle.js";
|
|
@@ -41,6 +42,7 @@ export declare class ExtensionAdmin {
|
|
|
41
42
|
private readonly config;
|
|
42
43
|
private readonly bus;
|
|
43
44
|
private readonly log;
|
|
45
|
+
private readonly displayNames;
|
|
44
46
|
private readonly packageSets;
|
|
45
47
|
constructor(kdb: KernelDb, txHost: TransactionHost,
|
|
46
48
|
/** The enterprise admin lock (identity/enterprise-admin.ts): joins the transaction. */
|
|
@@ -48,7 +50,7 @@ export declare class ExtensionAdmin {
|
|
|
48
50
|
/** The config-declared extensions (this replica's host; the CLI fills it from its inspection). */
|
|
49
51
|
host: ExtensionHost,
|
|
50
52
|
/** This replica's reconcile after an approval (a no-op where the lifecycle never started: the CLI). */
|
|
51
|
-
lifecycle: ExtensionLifecycle, config: KernelConfigService, bus: PublishBus, log: KernelLogger);
|
|
53
|
+
lifecycle: ExtensionLifecycle, config: KernelConfigService, bus: PublishBus, log: KernelLogger, displayNames: ExtensionDisplayNames);
|
|
52
54
|
private get db();
|
|
53
55
|
/** 全部插件(配置声明 → 安装记录,各自按名字)。 */
|
|
54
56
|
list(): Promise<AdminExtensionView[]>;
|
|
@@ -19,6 +19,7 @@ import { Transactional } from "../infra/database/transactional.decorator.js";
|
|
|
19
19
|
import { KERNEL_BUS, KERNEL_LOGGER } from "../infra/tokens.js";
|
|
20
20
|
import { ExtensionApprovals, snapshotCovers, writeSnapshot, } from "./approvals.js";
|
|
21
21
|
import { ExtensionBlobs } from "./blobs.js";
|
|
22
|
+
import { ExtensionDisplayNames } from "./display-name.js";
|
|
22
23
|
import { ExtensionHost } from "./host.js";
|
|
23
24
|
import { ExtensionInstalls } from "./installs.js";
|
|
24
25
|
import { ExtensionLifecycle, PLUGINS_CHANGED_TOPIC, STALE_RECONCILE_PERIODS } from "./lifecycle.js";
|
|
@@ -63,6 +64,7 @@ let ExtensionAdmin = class ExtensionAdmin {
|
|
|
63
64
|
config;
|
|
64
65
|
bus;
|
|
65
66
|
log;
|
|
67
|
+
displayNames;
|
|
66
68
|
packageSets = new Map();
|
|
67
69
|
constructor(kdb, txHost,
|
|
68
70
|
/** The enterprise admin lock (identity/enterprise-admin.ts): joins the transaction. */
|
|
@@ -70,7 +72,7 @@ let ExtensionAdmin = class ExtensionAdmin {
|
|
|
70
72
|
/** The config-declared extensions (this replica's host; the CLI fills it from its inspection). */
|
|
71
73
|
host,
|
|
72
74
|
/** This replica's reconcile after an approval (a no-op where the lifecycle never started: the CLI). */
|
|
73
|
-
lifecycle, config, bus, log) {
|
|
75
|
+
lifecycle, config, bus, log, displayNames) {
|
|
74
76
|
this.kdb = kdb;
|
|
75
77
|
this.txHost = txHost;
|
|
76
78
|
this.adminLock = adminLock;
|
|
@@ -83,6 +85,7 @@ let ExtensionAdmin = class ExtensionAdmin {
|
|
|
83
85
|
this.config = config;
|
|
84
86
|
this.bus = bus;
|
|
85
87
|
this.log = log;
|
|
88
|
+
this.displayNames = displayNames;
|
|
86
89
|
}
|
|
87
90
|
get db() {
|
|
88
91
|
return this.kdb.db;
|
|
@@ -278,6 +281,7 @@ let ExtensionAdmin = class ExtensionAdmin {
|
|
|
278
281
|
return [];
|
|
279
282
|
const names = subjects.map((s) => s.name);
|
|
280
283
|
const snapshots = await this.approvals.all();
|
|
284
|
+
const displayNames = await this.displayNames.many(names);
|
|
281
285
|
const staleSeconds = STALE_RECONCILE_PERIODS * this.config.get().extensionHost.reconcileIntervalSeconds;
|
|
282
286
|
const rows = await this.db
|
|
283
287
|
.selectFrom("extension_replica_status")
|
|
@@ -294,9 +298,11 @@ let ExtensionAdmin = class ExtensionAdmin {
|
|
|
294
298
|
const configValid = s.configValid ??
|
|
295
299
|
!replicas.some((r) => r.state === "pending" && r.reason === "config" && r.sha256 === target);
|
|
296
300
|
const install = s.install;
|
|
301
|
+
const displayName = displayNames.get(s.name) ?? null;
|
|
297
302
|
if (s.broken !== undefined) {
|
|
298
303
|
return {
|
|
299
304
|
name: s.name,
|
|
305
|
+
displayName,
|
|
300
306
|
version: s.version,
|
|
301
307
|
source: s.source,
|
|
302
308
|
sha256: target,
|
|
@@ -326,6 +332,7 @@ let ExtensionAdmin = class ExtensionAdmin {
|
|
|
326
332
|
const permissions = permissionGroups(s.set);
|
|
327
333
|
return {
|
|
328
334
|
name: s.name,
|
|
335
|
+
displayName,
|
|
329
336
|
version: s.version,
|
|
330
337
|
source: s.source,
|
|
331
338
|
sha256: target,
|
|
@@ -376,7 +383,8 @@ ExtensionAdmin = __decorate([
|
|
|
376
383
|
__param(8, Inject(ExtensionLifecycle)),
|
|
377
384
|
__param(9, Inject(KernelConfigService)),
|
|
378
385
|
__param(10, Inject(KERNEL_BUS)),
|
|
379
|
-
__param(11, Inject(KERNEL_LOGGER))
|
|
386
|
+
__param(11, Inject(KERNEL_LOGGER)),
|
|
387
|
+
__param(12, Inject(ExtensionDisplayNames))
|
|
380
388
|
], ExtensionAdmin);
|
|
381
389
|
export { ExtensionAdmin };
|
|
382
390
|
const replicaView = (r) => ({
|
package/dist/extensions/blobs.js
CHANGED
|
@@ -123,6 +123,7 @@ let ExtensionBlobs = class ExtensionBlobs {
|
|
|
123
123
|
source: src.source,
|
|
124
124
|
source_ref: src.ref,
|
|
125
125
|
uploaded_by: src.actor,
|
|
126
|
+
display_name: p.displayName === undefined ? null : JSON.stringify(p.displayName),
|
|
126
127
|
})
|
|
127
128
|
.onConflict((oc) => oc.column("sha256").doNothing())
|
|
128
129
|
.returning("sha256")
|
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
import type { z } from "zod";
|
|
2
2
|
/** 校验失败的单条原因:只含路径与按 issue 类型生成的说明,不回显字段值。 */
|
|
3
3
|
export interface ConfigIssue {
|
|
4
|
+
/** The path joined with dots (`""` = the root); ambiguous when a key contains a dot. */
|
|
4
5
|
path: string;
|
|
6
|
+
/** The zod path unjoined (record keys such as endpoint names may contain dots). */
|
|
7
|
+
segments: (string | number)[];
|
|
5
8
|
message: string;
|
|
9
|
+
/**
|
|
10
|
+
* A custom issue whose `params.ui` names a key of the schema's root `x-ui.messages`: the form
|
|
11
|
+
* shows that localized message (spec §4.4). Never zod's own custom text.
|
|
12
|
+
*/
|
|
13
|
+
messageKey?: string;
|
|
6
14
|
}
|
|
7
|
-
|
|
15
|
+
/**
|
|
16
|
+
* The issues of a failed config parse. `messages` is the root `x-ui.messages` of the schema's
|
|
17
|
+
* form JSON Schema (`configMessages`): custom issues naming one of its keys get `messageKey`.
|
|
18
|
+
*/
|
|
19
|
+
export declare function toIssues(error: z.ZodError, messages?: Record<string, unknown>): ConfigIssue[];
|
|
@@ -23,9 +23,26 @@ function issueMessage(i) {
|
|
|
23
23
|
return "invalid value";
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
/** The `params.ui` of a custom issue when it names one of `messages` (own keys only). */
|
|
27
|
+
function messageKeyOf(i, messages) {
|
|
28
|
+
if (i.code !== "custom" || messages === undefined)
|
|
29
|
+
return undefined;
|
|
30
|
+
const key = i.params?.ui;
|
|
31
|
+
return typeof key === "string" && Object.hasOwn(messages, key) ? key : undefined;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The issues of a failed config parse. `messages` is the root `x-ui.messages` of the schema's
|
|
35
|
+
* form JSON Schema (`configMessages`): custom issues naming one of its keys get `messageKey`.
|
|
36
|
+
*/
|
|
37
|
+
export function toIssues(error, messages) {
|
|
38
|
+
return error.issues.map((i) => {
|
|
39
|
+
const segments = i.path.map((s) => (typeof s === "number" ? s : String(s)));
|
|
40
|
+
const messageKey = messageKeyOf(i, messages);
|
|
41
|
+
return {
|
|
42
|
+
path: segments.join("."),
|
|
43
|
+
segments,
|
|
44
|
+
message: issueMessage(i),
|
|
45
|
+
...(messageKey !== undefined && { messageKey }),
|
|
46
|
+
};
|
|
47
|
+
});
|
|
31
48
|
}
|
|
@@ -1,9 +1,45 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
export type JsonSchema = Record<string, unknown>;
|
|
3
1
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* - 以输入侧形态输出(含 default),不带 `$schema`。
|
|
2
|
+
* Config schema → JSON Schema for forms. The conversion (and the secret scrub) lives in the SDK
|
|
3
|
+
* (`configJsonSchema`, extension config forms spec §4.1) so the packer, the checks and the kernel
|
|
4
|
+
* share one implementation; the kernel keeps no copy.
|
|
8
5
|
*/
|
|
9
|
-
|
|
6
|
+
import { type ConfigUiProblem, type JsonSchema } from "@capybara-hq/plugin-sdk";
|
|
7
|
+
import type { z } from "zod";
|
|
8
|
+
export { configJsonSchema as configToJsonSchema, type JsonSchema } from "@capybara-hq/plugin-sdk";
|
|
9
|
+
/** The config level a schema belongs to (which hints `validateConfigUi` allows). */
|
|
10
|
+
export type ConfigLevel = "deployment" | "org" | "connection";
|
|
11
|
+
/** A config schema as served to forms, with the problems of its hints (empty = kept). */
|
|
12
|
+
export interface ConfigFormSchema {
|
|
13
|
+
/** Shared by every caller: clone it before handing it out or changing it. */
|
|
14
|
+
readonly schema: JsonSchema;
|
|
15
|
+
readonly problems: ConfigUiProblem[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Removes every `x-ui` from a JSON Schema in place (a property named `x-ui` is kept, and so are
|
|
19
|
+
* values: `default`, `const`, `enum` and `examples` are left as they are).
|
|
20
|
+
*/
|
|
21
|
+
export declare function stripConfigUi(node: unknown): void;
|
|
22
|
+
/**
|
|
23
|
+
* Validates the hints of a JSON Schema at a level and strips every `x-ui` when there is any
|
|
24
|
+
* problem (in place): invalid hints never reach a form, and never fail a load (spec §4.1).
|
|
25
|
+
*/
|
|
26
|
+
export declare function checkConfigUi(schema: JsonSchema, level: ConfigLevel): ConfigUiProblem[];
|
|
27
|
+
/** A config schema's form JSON Schema ({@link checkConfigUi} applied), cached per schema object. */
|
|
28
|
+
export declare function configFormSchema(schema: z.ZodTypeAny, level: ConfigLevel): ConfigFormSchema;
|
|
29
|
+
/**
|
|
30
|
+
* {@link configFormSchema} that never throws, for every caller that serves a form schema or reads
|
|
31
|
+
* its messages (deployment, org, connection, issues). A hint conversion that throws (a hand-made
|
|
32
|
+
* package, e.g. hints that won't serialize as JSON) drops the hints: the plain schema with every
|
|
33
|
+
* `x-ui` stripped, else `null` when even the plain conversion fails. `onFallback` runs once per
|
|
34
|
+
* schema object and level on this replica (the caller's one warning); later calls reuse the result.
|
|
35
|
+
*/
|
|
36
|
+
export declare function safeConfigFormSchema(schema: z.ZodTypeAny, level: ConfigLevel, onFallback: (err: unknown, fallback: "plain" | "none") => void): ConfigFormSchema | null;
|
|
37
|
+
/**
|
|
38
|
+
* The secret record paths some `x-ui.secrets[].path` of a form schema names (spec §4.3), anywhere in
|
|
39
|
+
* the schema. Read from a checked schema: one whose hints were invalid was stripped and names none.
|
|
40
|
+
*/
|
|
41
|
+
export declare function hintedSecretPaths(node: unknown, out?: Set<string>): Set<string>;
|
|
42
|
+
/** The root `x-ui.messages` of a form schema (the localized texts of custom issues), if any. */
|
|
43
|
+
export declare function configMessages(schema: JsonSchema | null | undefined): Record<string, unknown> | undefined;
|
|
44
|
+
/** A short text of hint problems for a status detail or a log (the first few). */
|
|
45
|
+
export declare function describeConfigUiProblems(level: ConfigLevel, problems: ConfigUiProblem[]): string;
|