@capybara-hq/kernel 0.1.0-rc.2 → 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 +20 -2
- 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 +49 -13
- package/dist/agents/definition.d.ts +35 -8
- package/dist/agents/definition.js +203 -17
- 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 +20 -5
- 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/catalog-content.js +4 -1
- package/dist/catalog/claude/agents.js +15 -10
- 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.d.ts +8 -2
- package/dist/channels/cards.js +17 -9
- 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 +104 -2
- package/dist/conversations/access.js +2 -0
- package/dist/conversations/artifacts.d.ts +1 -1
- package/dist/conversations/artifacts.js +1 -1
- 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 +12 -1
- package/dist/conversations/event-log.js +29 -1
- package/dist/conversations/events.d.ts +81 -3
- package/dist/conversations/events.js +83 -16
- 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 +60 -4
- 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/recorded-tools.d.ts +27 -1
- package/dist/evals/recorded-tools.js +85 -10
- package/dist/evals/run-replay.d.ts +10 -2
- package/dist/evals/run-replay.js +49 -12
- package/dist/evals/step-replay.js +12 -6
- package/dist/evals/trajectory.d.ts +2 -2
- 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/identity/settings.js +1 -1
- 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/lifecycle/kernel-lifecycle.js +5 -0
- 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 +7 -2
- package/dist/orgs/settings.service.js +15 -4
- package/dist/roles/worker.module.js +6 -0
- package/dist/runtime/context/build.d.ts +15 -13
- package/dist/runtime/context/build.js +45 -27
- package/dist/runtime/context/claude-tools.d.ts +3 -1
- package/dist/runtime/context/claude-tools.js +12 -12
- package/dist/runtime/context/compaction.js +4 -0
- package/dist/runtime/context/legacy-text.d.ts +22 -0
- package/dist/runtime/context/legacy-text.js +37 -0
- package/dist/runtime/context/skills.d.ts +29 -11
- package/dist/runtime/context/skills.js +37 -30
- package/dist/runtime/langgraph-loop.js +3 -2
- package/dist/runtime/loop.d.ts +5 -4
- 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 +4 -3
- package/dist/runtime/providers.d.ts +6 -0
- package/dist/runtime/providers.js +8 -0
- package/dist/runtime/run-finish.d.ts +1 -1
- package/dist/runtime/run-queue.d.ts +28 -5
- package/dist/runtime/run-queue.js +131 -35
- package/dist/runtime/run-worker.d.ts +2 -2
- package/dist/runtime/run-worker.js +20 -7
- 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.d.ts +1 -6
- package/dist/runtime/subagents/definition.js +14 -13
- package/dist/runtime/subagents/dispatch.d.ts +2 -2
- package/dist/runtime/subagents/dispatch.js +2 -2
- package/dist/runtime/subagents/org-agents.js +2 -1
- package/dist/runtime/subagents/roster.d.ts +1 -1
- package/dist/runtime/subagents/roster.js +1 -1
- package/dist/runtime/subagents/skill-fork.d.ts +2 -2
- package/dist/runtime/subagents/skill-fork.js +2 -2
- package/dist/runtime/subagents/subagents.service.d.ts +3 -3
- package/dist/runtime/subagents/subagents.service.js +3 -3
- package/dist/runtime/usage-report.d.ts +2 -1
- package/dist/runtime/usage-report.js +2 -1
- package/dist/runtime/waits.d.ts +13 -7
- package/dist/runtime/waits.js +42 -16
- 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/skills/catalog.d.ts +4 -4
- package/dist/skills/catalog.js +4 -4
- package/dist/skills/changes.service.d.ts +2 -2
- package/dist/skills/changes.service.js +5 -4
- package/dist/skills/invocation-keys.d.ts +1 -1
- package/dist/skills/invocation-keys.js +1 -1
- package/dist/skills/invoke.d.ts +1 -1
- package/dist/skills/invoke.js +5 -4
- package/dist/tools/approvals.service.d.ts +6 -0
- package/dist/tools/approvals.service.js +21 -1
- package/dist/tools/builtin-names.d.ts +91 -0
- package/dist/tools/builtin-names.js +143 -0
- package/dist/tools/builtins/agent.d.ts +7 -7
- package/dist/tools/builtins/agent.js +7 -11
- package/dist/tools/builtins/ask-user.d.ts +1 -1
- package/dist/tools/builtins/ask-user.js +2 -2
- package/dist/tools/builtins/builtin-tools.d.ts +17 -3
- package/dist/tools/builtins/builtin-tools.js +36 -4
- package/dist/tools/builtins/read-tool-output.d.ts +1 -1
- package/dist/tools/builtins/read-tool-output.js +2 -2
- package/dist/tools/builtins/sandbox/bash.d.ts +4 -4
- package/dist/tools/builtins/sandbox/bash.js +259 -29
- package/dist/tools/builtins/sandbox/common.d.ts +30 -7
- package/dist/tools/builtins/sandbox/common.js +9 -5
- package/dist/tools/builtins/sandbox/deliver.d.ts +1 -1
- package/dist/tools/builtins/sandbox/deliver.js +12 -12
- package/dist/tools/builtins/sandbox/edit.d.ts +1 -1
- package/dist/tools/builtins/sandbox/edit.js +41 -30
- package/dist/tools/builtins/sandbox/file-state.d.ts +34 -0
- package/dist/tools/builtins/sandbox/file-state.js +34 -0
- package/dist/tools/builtins/sandbox/glob-match.d.ts +1 -1
- package/dist/tools/builtins/sandbox/glob-match.js +1 -1
- package/dist/tools/builtins/sandbox/glob.d.ts +1 -1
- package/dist/tools/builtins/sandbox/glob.js +4 -4
- package/dist/tools/builtins/sandbox/grep.d.ts +7 -4
- package/dist/tools/builtins/sandbox/grep.js +147 -30
- package/dist/tools/builtins/sandbox/index.d.ts +3 -1
- package/dist/tools/builtins/sandbox/index.js +7 -1
- package/dist/tools/builtins/sandbox/read.d.ts +2 -2
- package/dist/tools/builtins/sandbox/read.js +21 -14
- 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/sandbox/write.d.ts +1 -1
- package/dist/tools/builtins/sandbox/write.js +37 -33
- package/dist/tools/builtins/skill-load.d.ts +3 -3
- package/dist/tools/builtins/skill-load.js +32 -16
- package/dist/tools/builtins/skill-write.d.ts +4 -4
- package/dist/tools/builtins/skill-write.js +10 -10
- package/dist/tools/builtins/tool-search.d.ts +13 -9
- package/dist/tools/builtins/tool-search.js +25 -14
- 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/connectors.service.js +4 -4
- package/dist/tools/display-names.d.ts +9 -0
- package/dist/tools/display-names.js +24 -0
- package/dist/tools/drift.js +5 -5
- package/dist/tools/elicitation.js +1 -1
- package/dist/tools/info.d.ts +20 -4
- package/dist/tools/info.js +55 -32
- package/dist/tools/legacy-data.d.ts +34 -0
- package/dist/tools/legacy-data.js +76 -0
- package/dist/tools/legacy-keys.d.ts +51 -0
- package/dist/tools/legacy-keys.js +115 -0
- package/dist/tools/naming.d.ts +1 -5
- package/dist/tools/naming.js +1 -7
- package/dist/tools/oauth/flow-paths.d.ts +1 -1
- package/dist/tools/oauth/flow-paths.js +1 -1
- package/dist/tools/outputs.js +1 -1
- package/dist/tools/pipeline.d.ts +13 -7
- package/dist/tools/pipeline.js +112 -39
- package/dist/tools/policy.d.ts +1 -14
- package/dist/tools/policy.js +13 -19
- package/dist/tools/questions.controller.d.ts +1 -1
- package/dist/tools/questions.controller.js +1 -1
- package/dist/tools/questions.service.d.ts +1 -1
- package/dist/tools/registry.d.ts +38 -24
- package/dist/tools/registry.js +54 -47
- package/dist/tools/resources.d.ts +1 -1
- package/dist/tools/resources.js +1 -1
- package/dist/tools/tools.module.js +13 -1
- package/dist/tools/validate.js +1 -1
- package/package.json +3 -3
- package/src/migrations/0063_tool_keys_claude_code.sql +220 -0
- 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
- package/dist/tools/builtins/sandbox/names.d.ts +0 -7
- package/dist/tools/builtins/sandbox/names.js +0 -20
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { KernelSchemaDb } from "../db/kernel-schema.js";
|
|
2
|
+
/**
|
|
3
|
+
* The wake rules of a finished background task (spec 2026-11-05-background-bash-design §3), read
|
|
4
|
+
* by `RunQueue.ensureRun` in its transaction: every path that may start a run (a finish, the end of
|
|
5
|
+
* a run, the delayed wake job, a page opening) applies the same rules. `BackgroundWake` is what
|
|
6
|
+
* calls `ensureRun` when a task finishes.
|
|
7
|
+
*/
|
|
8
|
+
/** No two wakes of one conversation start within this window. */
|
|
9
|
+
export declare const WAKE_WINDOW_MS = 60000;
|
|
10
|
+
/** The delayed job that wakes a conversation at the end of its window (`cap-kernel-maintenance`). */
|
|
11
|
+
export declare const BG_WAKE_JOB = "bg-wake";
|
|
12
|
+
/**
|
|
13
|
+
* Its job id: one job per conversation and window end (no `:`). `retry` > 0 is a job that fired
|
|
14
|
+
* before the window ended on the database's clock and scheduled itself again: a distinct id, since
|
|
15
|
+
* BullMQ ignores an add under the id of the job still running.
|
|
16
|
+
*/
|
|
17
|
+
export declare const bgWakeJobId: (conversationId: string, windowEnd: number, retry?: number) => string;
|
|
18
|
+
export interface BgWakeJobData {
|
|
19
|
+
conversationId: string;
|
|
20
|
+
/** How many times this window's wake fired early (absent: none). */
|
|
21
|
+
retry?: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* What a conversation's unconsumed finishes decide:
|
|
25
|
+
* - `wake`: start a run whose boundary is the finish at `seq`, as `triggerAccountId`;
|
|
26
|
+
* - `later`: a wake started less than {@link WAKE_WINDOW_MS} ago; the window ends at `windowEnd`
|
|
27
|
+
* (epoch ms, the database's clock), `delayMs` from now;
|
|
28
|
+
* - null: nothing wakes the conversation.
|
|
29
|
+
*/
|
|
30
|
+
export type WakeDecision = {
|
|
31
|
+
kind: "wake";
|
|
32
|
+
seq: number;
|
|
33
|
+
triggerAccountId: string;
|
|
34
|
+
} | {
|
|
35
|
+
kind: "later";
|
|
36
|
+
windowEnd: number;
|
|
37
|
+
delayMs: number;
|
|
38
|
+
} | null;
|
|
39
|
+
/**
|
|
40
|
+
* The wake decision for a chat conversation that is idle, whose queue is not paused and has no
|
|
41
|
+
* unconsumed message (the caller checked these under the conversation's row lock). A finish
|
|
42
|
+
* wakes it when:
|
|
43
|
+
* - it is after `consumed`, not `reported` (a tool call already told the model) and has no
|
|
44
|
+
* `stoppedBy` (`"person"`: that person is looking at the conversation; `"deletion"`: the
|
|
45
|
+
* conversation is being deleted);
|
|
46
|
+
* - it belongs to a task of this conversation (the join on `conversation_id` reads the task's
|
|
47
|
+
* trigger account). A sub-agent's task is excluded by the conversation's kind, not here: its
|
|
48
|
+
* finish is in the child's log, and `ensureRun` never wakes a non-chat conversation;
|
|
49
|
+
* - the wake setting is on (the org's override, else `deploymentOn`);
|
|
50
|
+
* - the task's trigger account can still send to the conversation (`canSend`);
|
|
51
|
+
* - no other wake started in the last {@link WAKE_WINDOW_MS} (else `later`).
|
|
52
|
+
* The boundary is the newest finish whose trigger account can send.
|
|
53
|
+
*/
|
|
54
|
+
export declare function wakeDecisionIn(t: KernelSchemaDb, conv: {
|
|
55
|
+
id: string;
|
|
56
|
+
orgId: string;
|
|
57
|
+
}, consumed: number, deploymentOn: boolean, canSend: (accountId: string) => Promise<boolean>): Promise<WakeDecision>;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { sql } from "kysely";
|
|
2
|
+
import { effectiveWakeOnBackgroundTask, readOrgSettings } from "../orgs/settings.service.js";
|
|
3
|
+
/**
|
|
4
|
+
* The wake rules of a finished background task (spec 2026-11-05-background-bash-design §3), read
|
|
5
|
+
* by `RunQueue.ensureRun` in its transaction: every path that may start a run (a finish, the end of
|
|
6
|
+
* a run, the delayed wake job, a page opening) applies the same rules. `BackgroundWake` is what
|
|
7
|
+
* calls `ensureRun` when a task finishes.
|
|
8
|
+
*/
|
|
9
|
+
/** No two wakes of one conversation start within this window. */
|
|
10
|
+
export const WAKE_WINDOW_MS = 60_000;
|
|
11
|
+
/** The delayed job that wakes a conversation at the end of its window (`cap-kernel-maintenance`). */
|
|
12
|
+
export const BG_WAKE_JOB = "bg-wake";
|
|
13
|
+
/**
|
|
14
|
+
* Its job id: one job per conversation and window end (no `:`). `retry` > 0 is a job that fired
|
|
15
|
+
* before the window ended on the database's clock and scheduled itself again: a distinct id, since
|
|
16
|
+
* BullMQ ignores an add under the id of the job still running.
|
|
17
|
+
*/
|
|
18
|
+
export const bgWakeJobId = (conversationId, windowEnd, retry = 0) => `bg-wake-${conversationId}-${windowEnd}${retry > 0 ? `-r${retry}` : ""}`;
|
|
19
|
+
/** How many unconsumed finishes are tried for a trigger account that can still send. */
|
|
20
|
+
const CANDIDATES = 20;
|
|
21
|
+
/**
|
|
22
|
+
* The wake decision for a chat conversation that is idle, whose queue is not paused and has no
|
|
23
|
+
* unconsumed message (the caller checked these under the conversation's row lock). A finish
|
|
24
|
+
* wakes it when:
|
|
25
|
+
* - it is after `consumed`, not `reported` (a tool call already told the model) and has no
|
|
26
|
+
* `stoppedBy` (`"person"`: that person is looking at the conversation; `"deletion"`: the
|
|
27
|
+
* conversation is being deleted);
|
|
28
|
+
* - it belongs to a task of this conversation (the join on `conversation_id` reads the task's
|
|
29
|
+
* trigger account). A sub-agent's task is excluded by the conversation's kind, not here: its
|
|
30
|
+
* finish is in the child's log, and `ensureRun` never wakes a non-chat conversation;
|
|
31
|
+
* - the wake setting is on (the org's override, else `deploymentOn`);
|
|
32
|
+
* - the task's trigger account can still send to the conversation (`canSend`);
|
|
33
|
+
* - no other wake started in the last {@link WAKE_WINDOW_MS} (else `later`).
|
|
34
|
+
* The boundary is the newest finish whose trigger account can send.
|
|
35
|
+
*/
|
|
36
|
+
export async function wakeDecisionIn(t, conv, consumed, deploymentOn, canSend) {
|
|
37
|
+
const candidates = await t
|
|
38
|
+
.selectFrom("conversation_events as e")
|
|
39
|
+
.innerJoin("background_tasks as b", (j) => j
|
|
40
|
+
.on(sql `b.id = e.payload ->> 'taskId'`)
|
|
41
|
+
.onRef("b.conversation_id", "=", "e.conversation_id"))
|
|
42
|
+
.select(["e.seq", "b.trigger_account_id"])
|
|
43
|
+
.where("e.conversation_id", "=", conv.id)
|
|
44
|
+
.where("e.type", "=", "background_task_finished")
|
|
45
|
+
.where("e.seq", ">", String(consumed))
|
|
46
|
+
.where(sql `(e.payload ->> 'reported')::boolean = false`)
|
|
47
|
+
.where(sql `e.payload ->> 'stoppedBy' IS NULL`)
|
|
48
|
+
.orderBy("e.seq", "desc")
|
|
49
|
+
.limit(CANDIDATES)
|
|
50
|
+
.execute();
|
|
51
|
+
if (candidates.length === 0)
|
|
52
|
+
return null;
|
|
53
|
+
const org = (await readOrgSettings(t, conv.orgId)).wakeOnBackgroundTask;
|
|
54
|
+
if (!effectiveWakeOnBackgroundTask(deploymentOn, org))
|
|
55
|
+
return null;
|
|
56
|
+
let boundary;
|
|
57
|
+
for (const c of candidates) {
|
|
58
|
+
if (await canSend(c.trigger_account_id)) {
|
|
59
|
+
boundary = { seq: Number(c.seq), triggerAccountId: c.trigger_account_id };
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (boundary === undefined)
|
|
64
|
+
return null;
|
|
65
|
+
// the window starts when the last wake run was created (PG, so every replica reads the same)
|
|
66
|
+
const last = await t
|
|
67
|
+
.selectFrom("runs as r")
|
|
68
|
+
.innerJoin("conversation_events as w", (j) => j.onRef("w.conversation_id", "=", "r.conversation_id").onRef("w.seq", "=", "r.trigger_seq"))
|
|
69
|
+
.select([
|
|
70
|
+
sql `floor(extract(epoch from max(r.created_at)) * 1000)::bigint`.as("started"),
|
|
71
|
+
sql `floor(extract(epoch from now()) * 1000)::bigint`.as("now"),
|
|
72
|
+
])
|
|
73
|
+
.where("r.conversation_id", "=", conv.id)
|
|
74
|
+
.where("w.type", "=", "background_task_finished")
|
|
75
|
+
.executeTakeFirst();
|
|
76
|
+
if (last?.started != null) {
|
|
77
|
+
const windowEnd = Number(last.started) + WAKE_WINDOW_MS;
|
|
78
|
+
const now = Number(last.now);
|
|
79
|
+
if (windowEnd > now)
|
|
80
|
+
return { kind: "later", windowEnd, delayMs: windowEnd - now };
|
|
81
|
+
}
|
|
82
|
+
return { kind: "wake", ...boundary };
|
|
83
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Logger } from "@capybara-hq/plugin-sdk";
|
|
2
|
+
import { type OnApplicationShutdown } from "@nestjs/common";
|
|
3
|
+
import { KernelEvents } from "../infra/events/kernel-events.js";
|
|
4
|
+
import { RunQueue } from "../runtime/run-queue.js";
|
|
5
|
+
/**
|
|
6
|
+
* Wakes an idle conversation when one of its background tasks finished (spec
|
|
7
|
+
* 2026-11-05-background-bash-design §3). {@link BackgroundTaskFinisher} announces the committed
|
|
8
|
+
* finish (`background_task.finished`, an in-process domain event: the finisher's module sits
|
|
9
|
+
* below the runtime); {@link onFinished} asks the run queue for a run. The wake rules themselves
|
|
10
|
+
* (own task, not reported, the wake setting, the queue not paused, the trigger account can still
|
|
11
|
+
* send, the 60 s window and its delayed `bg-wake` job) are applied by `RunQueue.ensureRun` in its
|
|
12
|
+
* transaction (`wakeDecisionIn`, ./wake-rules.ts), so a run's end, the delayed job and a page
|
|
13
|
+
* opening apply the same rules. Provided by `RuntimeModule`.
|
|
14
|
+
*/
|
|
15
|
+
export declare class BackgroundWake implements OnApplicationShutdown {
|
|
16
|
+
private readonly runs;
|
|
17
|
+
private readonly log;
|
|
18
|
+
/** Drops the subscription (the events may outlive this instance). */
|
|
19
|
+
private readonly unsubscribe;
|
|
20
|
+
constructor(runs: Pick<RunQueue, "ensureRun">, events: KernelEvents, log: Pick<Logger, "warn">);
|
|
21
|
+
/**
|
|
22
|
+
* A task of `conversationId` finished (after the commit): starts a wake run when the rules
|
|
23
|
+
* allow it, or schedules one at the end of the wake window. A run in progress absorbs the finish
|
|
24
|
+
* at its next step instead, or its end starts the wake. Never throws.
|
|
25
|
+
*/
|
|
26
|
+
onFinished(conversationId: string): Promise<void>;
|
|
27
|
+
onApplicationShutdown(): void;
|
|
28
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
8
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
9
|
+
};
|
|
10
|
+
import { Inject, Injectable } from "@nestjs/common";
|
|
11
|
+
import { KernelEvents } from "../infra/events/kernel-events.js";
|
|
12
|
+
import { KERNEL_LOGGER } from "../infra/tokens.js";
|
|
13
|
+
import { RunQueue } from "../runtime/run-queue.js";
|
|
14
|
+
/**
|
|
15
|
+
* Wakes an idle conversation when one of its background tasks finished (spec
|
|
16
|
+
* 2026-11-05-background-bash-design §3). {@link BackgroundTaskFinisher} announces the committed
|
|
17
|
+
* finish (`background_task.finished`, an in-process domain event: the finisher's module sits
|
|
18
|
+
* below the runtime); {@link onFinished} asks the run queue for a run. The wake rules themselves
|
|
19
|
+
* (own task, not reported, the wake setting, the queue not paused, the trigger account can still
|
|
20
|
+
* send, the 60 s window and its delayed `bg-wake` job) are applied by `RunQueue.ensureRun` in its
|
|
21
|
+
* transaction (`wakeDecisionIn`, ./wake-rules.ts), so a run's end, the delayed job and a page
|
|
22
|
+
* opening apply the same rules. Provided by `RuntimeModule`.
|
|
23
|
+
*/
|
|
24
|
+
let BackgroundWake = class BackgroundWake {
|
|
25
|
+
runs;
|
|
26
|
+
log;
|
|
27
|
+
/** Drops the subscription (the events may outlive this instance). */
|
|
28
|
+
unsubscribe;
|
|
29
|
+
constructor(runs, events, log) {
|
|
30
|
+
this.runs = runs;
|
|
31
|
+
this.log = log;
|
|
32
|
+
this.unsubscribe = events.on("background_task.finished", ({ conversationId }) => this.onFinished(conversationId));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* A task of `conversationId` finished (after the commit): starts a wake run when the rules
|
|
36
|
+
* allow it, or schedules one at the end of the wake window. A run in progress absorbs the finish
|
|
37
|
+
* at its next step instead, or its end starts the wake. Never throws.
|
|
38
|
+
*/
|
|
39
|
+
async onFinished(conversationId) {
|
|
40
|
+
try {
|
|
41
|
+
await this.runs.ensureRun(conversationId);
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
this.log.warn("background task wake failed", { conversationId, err });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
onApplicationShutdown() {
|
|
48
|
+
this.unsubscribe();
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
BackgroundWake = __decorate([
|
|
52
|
+
Injectable(),
|
|
53
|
+
__param(0, Inject(RunQueue)),
|
|
54
|
+
__param(1, Inject(KernelEvents)),
|
|
55
|
+
__param(2, Inject(KERNEL_LOGGER))
|
|
56
|
+
], BackgroundWake);
|
|
57
|
+
export { BackgroundWake };
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
// module whose provider injects PluginInstaller (an ESM import cycle would run decorators early).
|
|
5
5
|
import { createHash } from "node:crypto";
|
|
6
6
|
import { parseAgentTemplate, parseConnectorTemplateFile, } from "@capybara-hq/plugin-sdk";
|
|
7
|
+
import { normalizeToolKeys } from "../agents/definition.js";
|
|
7
8
|
import { ApiError } from "../errors.js";
|
|
8
9
|
import { can } from "../orgs/roles.js";
|
|
9
10
|
import { packagePath } from "../packages/tgz.js";
|
|
@@ -318,6 +319,8 @@ export async function readCatalogAgentTemplates(storage, v) {
|
|
|
318
319
|
if (!parsed || "errors" in parsed) {
|
|
319
320
|
throw new ApiError("internal", `Stored agent template ${path} is missing or invalid`);
|
|
320
321
|
}
|
|
321
|
-
|
|
322
|
+
// an rc package's template may name old builtins: read as the current names (tool naming
|
|
323
|
+
// spec §8.3); rc `<x>__<tool>` keys are read with the org's scope by `loadTemplates`
|
|
324
|
+
return { path, template: normalizeToolKeys(parsed.template) };
|
|
322
325
|
});
|
|
323
326
|
}
|
|
@@ -13,16 +13,21 @@ import { item } from "./report.js";
|
|
|
13
13
|
export const GENERATED_AGENTS_DIR = ".capybara-generated/agents";
|
|
14
14
|
/** Claude Code tool names -> Capybara tool keys (spec §16.4; anything else is dropped). */
|
|
15
15
|
const TOOL_MAP = {
|
|
16
|
-
Bash: "
|
|
17
|
-
Read: "
|
|
18
|
-
Write: "
|
|
19
|
-
Edit: "
|
|
20
|
-
MultiEdit: "
|
|
21
|
-
Glob: "
|
|
22
|
-
Grep: "
|
|
23
|
-
Skill: "
|
|
24
|
-
|
|
25
|
-
ToolSearch: "
|
|
16
|
+
Bash: "Bash",
|
|
17
|
+
Read: "Read",
|
|
18
|
+
Write: "Write",
|
|
19
|
+
Edit: "Edit",
|
|
20
|
+
MultiEdit: "Edit",
|
|
21
|
+
Glob: "Glob",
|
|
22
|
+
Grep: "Grep",
|
|
23
|
+
Skill: "Skill",
|
|
24
|
+
AskUserQuestion: "AskUserQuestion",
|
|
25
|
+
ToolSearch: "ToolSearch",
|
|
26
|
+
Agent: "Agent",
|
|
27
|
+
Task: "Agent",
|
|
28
|
+
TodoWrite: "plugin__todo__write",
|
|
29
|
+
WebFetch: "WebFetch",
|
|
30
|
+
WebSearch: "WebSearch",
|
|
26
31
|
};
|
|
27
32
|
/** Claude ignores these for plugin agents: `not_applicable`. */
|
|
28
33
|
const NOT_APPLICABLE = new Set(["permissionMode", "hooks", "mcpServers"]);
|
|
@@ -164,7 +164,7 @@ export declare function headsToResolve(entries: readonly MarketplaceEntry[], imp
|
|
|
164
164
|
/** The host versions (an entry's `minKernel` is judged against them). */
|
|
165
165
|
export declare const HOST_VERSIONS: {
|
|
166
166
|
readonly kernel: string;
|
|
167
|
-
readonly sdk: "0.1.0-rc.
|
|
167
|
+
readonly sdk: "0.1.0-rc.2";
|
|
168
168
|
};
|
|
169
169
|
/** Whether this deployment satisfies the entry's `minKernel`. */
|
|
170
170
|
export declare const entryCompatible: (e: Pick<MarketplaceEntry, "minKernel">) => boolean;
|
|
@@ -33,8 +33,8 @@ import { KERNEL_LOGGER } from "../infra/tokens.js";
|
|
|
33
33
|
import { packPackageTgz } from "../packages/tgz.js";
|
|
34
34
|
import { checkSkillFiles, SkillArchiveError } from "../skills/package.js";
|
|
35
35
|
import { StorageService } from "../storage/storage.service.js";
|
|
36
|
+
import { canonicalJson } from "../tools/canonical-json.js";
|
|
36
37
|
import { endpointCredentialIssues } from "../tools/endpoint.js";
|
|
37
|
-
import { canonicalJson } from "../tools/registry.js";
|
|
38
38
|
import { findConnectorIn } from "./catalog-content.js";
|
|
39
39
|
import { assertPluginNameOwner, catalogObjectPrefix, itemView, permissionsMismatch, precheckCatalogImport, putCatalogFiles, templateProblems, writeCatalogVersion, } from "./catalog-items.js";
|
|
40
40
|
import { CLAUDE_PLUGIN_FILE, claudeContentDigest, } from "./claude/manifest.js";
|
|
@@ -24,8 +24,8 @@ import { OrgLock } from "../orgs/org-lock.js";
|
|
|
24
24
|
import { packagePath } from "../packages/tgz.js";
|
|
25
25
|
import { SkillsService, skillConflictError } from "../skills/skills.service.js";
|
|
26
26
|
import { StorageService } from "../storage/storage.service.js";
|
|
27
|
+
import { canonicalJson } from "../tools/canonical-json.js";
|
|
27
28
|
import { ConnectorsService } from "../tools/connectors.service.js";
|
|
28
|
-
import { canonicalJson } from "../tools/registry.js";
|
|
29
29
|
import { getPath, lockOrgForActions, orgTemplateView, readCatalogAgentTemplates, readCatalogFiles, readCatalogTemplates, requiredActions, setPath, skillOf, templatePluginProblem, } from "./catalog-content.js";
|
|
30
30
|
import { catalogSkillNames, InstallFailure, journalEntries, missingTemplateInput, PluginInstaller, planActions, planSkillConflicts, resolveDependencies, under, } from "./plugin-install.js";
|
|
31
31
|
import { assertItemInstallable, CatalogRequestsService } from "./requests.service.js";
|
package/dist/channels/cards.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ChannelCard, type FormAnswer, type InputForm, type OutboundMessage } from "@capybara-hq/plugin-sdk";
|
|
2
2
|
import type { KernelSchemaDb } from "../db/kernel-schema.js";
|
|
3
|
-
import type { ApprovalsService } from "../tools/approvals.service.js";
|
|
3
|
+
import type { ApprovalsService, ApprovalView } from "../tools/approvals.service.js";
|
|
4
4
|
import { type ChannelLocale } from "./phrases.js";
|
|
5
5
|
/** 审批卡片里工具参数预览的最大长度(字符)。 */
|
|
6
6
|
export declare const INPUT_PREVIEW_MAX = 500;
|
|
@@ -23,6 +23,12 @@ export declare function webBase(publicUrl: string | undefined): string | undefin
|
|
|
23
23
|
export declare const conversationUrl: (base: string, conversationId: string) => string;
|
|
24
24
|
/** 个人连接页里某个连接器的位置(与网页 ConnectCard 的链接一致)。 */
|
|
25
25
|
export declare const connectUrl: (base: string, connectorId: string) => string;
|
|
26
|
+
/**
|
|
27
|
+
* The tool as the card names it (tool naming spec §7): a builtin by its name; a connector or
|
|
28
|
+
* extension tool as `<display name> [<tool>]` (the connector's name, the plugin's display name in
|
|
29
|
+
* the card's language), the way the web labels it.
|
|
30
|
+
*/
|
|
31
|
+
export declare function approvalToolName(v: Pick<ApprovalView, "toolKey" | "toolName" | "connector" | "extension">, locale: ChannelLocale): string;
|
|
26
32
|
export interface CardDeps {
|
|
27
33
|
db: KernelSchemaDb;
|
|
28
34
|
approvals: Pick<ApprovalsService, "describe">;
|
package/dist/channels/cards.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { parseToolKey, } from "@capybara-hq/plugin-sdk";
|
|
2
2
|
import { phrase } from "./phrases.js";
|
|
3
3
|
/** 审批卡片里工具参数预览的最大长度(字符)。 */
|
|
4
4
|
export const INPUT_PREVIEW_MAX = 500;
|
|
@@ -83,13 +83,21 @@ export function webBase(publicUrl) {
|
|
|
83
83
|
/** 会话的网页链接(与审批详情的 `conversationPath` 一致:`/chat/<id>`,不含语言前缀)。 */
|
|
84
84
|
export const conversationUrl = (base, conversationId) => `${base}/chat/${conversationId}`;
|
|
85
85
|
/** 个人连接页里某个连接器的位置(与网页 ConnectCard 的链接一致)。 */
|
|
86
|
-
export const connectUrl = (base, connectorId) => `${base}/
|
|
87
|
-
/**
|
|
88
|
-
|
|
86
|
+
export const connectUrl = (base, connectorId) => `${base}/account/connections#connector-${encodeURIComponent(connectorId)}`;
|
|
87
|
+
/**
|
|
88
|
+
* The tool as the card names it (tool naming spec §7): a builtin by its name; a connector or
|
|
89
|
+
* extension tool as `<display name> [<tool>]` (the connector's name, the plugin's display name in
|
|
90
|
+
* the card's language), the way the web labels it.
|
|
91
|
+
*/
|
|
92
|
+
export function approvalToolName(v, locale) {
|
|
93
|
+
// `toolName` is already the connector's own name for its tool
|
|
89
94
|
if (v.connector)
|
|
90
|
-
return v.toolName
|
|
91
|
-
const
|
|
92
|
-
|
|
95
|
+
return `${v.connector.name} [${v.toolName}]`;
|
|
96
|
+
const parsed = parseToolKey(v.toolKey);
|
|
97
|
+
const tool = parsed && parsed.kind !== "builtin" ? parsed.tool : v.toolName;
|
|
98
|
+
if (v.extension)
|
|
99
|
+
return `${v.extension.displayName[locale]} [${tool}]`;
|
|
100
|
+
return v.toolKey;
|
|
93
101
|
}
|
|
94
102
|
/** 账号显示名;不存在返回 undefined。 */
|
|
95
103
|
async function displayName(db, accountId) {
|
|
@@ -115,8 +123,8 @@ export async function approvalCard(d, approvalId, base, locale, redact) {
|
|
|
115
123
|
kind: "approval",
|
|
116
124
|
id: v.id,
|
|
117
125
|
title: phrase("approvalTitle", locale),
|
|
118
|
-
|
|
119
|
-
|
|
126
|
+
// the label carries the source, so no separate appName (renderers would repeat it)
|
|
127
|
+
toolName: approvalToolName(v, locale),
|
|
120
128
|
agentName: v.agent.name || "Agent",
|
|
121
129
|
inputPreview: inputPreview(v.input, redact),
|
|
122
130
|
scopes: v.requestedFor === null ? ["once"] : ["once", "session", "always"],
|
|
@@ -106,6 +106,8 @@ export declare class ChannelConnections implements OnApplicationShutdown {
|
|
|
106
106
|
private readonly log;
|
|
107
107
|
readonly txHost: TransactionHost;
|
|
108
108
|
private readonly unsubscribe;
|
|
109
|
+
/** `<plugin>@<version>` whose invalid connection hints were warned about (a log dedupe only). */
|
|
110
|
+
private readonly hintsWarned;
|
|
109
111
|
constructor(db: KernelDb,
|
|
110
112
|
/** The org row lock (orgs/org-lock.ts): joins the transaction of the write. */
|
|
111
113
|
orgLock: Pick<OrgLock, "lockAndAuthorize">, keyring: Keyring, registry: Pick<ExtensionRegistry, "list">, bus: ExtensionContext["bus"], redis: Pick<Redis, "del">,
|
|
@@ -122,8 +124,21 @@ export declare class ChannelConnections implements OnApplicationShutdown {
|
|
|
122
124
|
private channelEntry;
|
|
123
125
|
/** The extension is not enabled in this organization -> `extension.not_enabled`. */
|
|
124
126
|
private assertEnabled;
|
|
125
|
-
/**
|
|
127
|
+
/**
|
|
128
|
+
* The connection schema's form JSON Schema (secret fields carry `x-secret`, no values), a copy.
|
|
129
|
+
* Never throws: when even the plain conversion fails, an empty object schema (a save is still
|
|
130
|
+
* validated here).
|
|
131
|
+
*/
|
|
126
132
|
jsonSchema(plugin: string): JsonSchema;
|
|
133
|
+
/**
|
|
134
|
+
* The connection schema's form JSON Schema; invalid hints are stripped and warned about once per
|
|
135
|
+
* `<plugin>@<version>` on this replica (spec §4.1: the connection level is checked at its first
|
|
136
|
+
* conversion, not at load). Never throws: a hint conversion that throws serves the plain schema,
|
|
137
|
+
* else null, with one warning per schema.
|
|
138
|
+
*/
|
|
139
|
+
private formSchema;
|
|
140
|
+
/** The loaded version of a channel extension, for warnings ("unknown" when not provided). */
|
|
141
|
+
private versionOf;
|
|
127
142
|
private parse;
|
|
128
143
|
private verify;
|
|
129
144
|
private reportSecrets;
|
|
@@ -16,7 +16,7 @@ import { queryEnabledPlugins } from "../ctx/create-ctx.js";
|
|
|
16
16
|
import { createSecrets } from "../ctx/secrets.js";
|
|
17
17
|
import { ApiError } from "../errors.js";
|
|
18
18
|
import { toIssues } from "../extensions/config-issues.js";
|
|
19
|
-
import {
|
|
19
|
+
import { configMessages, describeConfigUiProblems, safeConfigFormSchema, } from "../extensions/config-json-schema.js";
|
|
20
20
|
import { enabledExtensionsByOrg } from "../extensions/enabled.js";
|
|
21
21
|
import { ExtensionRegistry } from "../extensions/registry.js";
|
|
22
22
|
import { audit } from "../identity/audit.js";
|
|
@@ -121,6 +121,8 @@ let ChannelConnections = class ChannelConnections {
|
|
|
121
121
|
log;
|
|
122
122
|
txHost;
|
|
123
123
|
unsubscribe;
|
|
124
|
+
/** `<plugin>@<version>` whose invalid connection hints were warned about (a log dedupe only). */
|
|
125
|
+
hintsWarned = new Set();
|
|
124
126
|
constructor(db,
|
|
125
127
|
/** The org row lock (orgs/org-lock.ts): joins the transaction of the write. */
|
|
126
128
|
orgLock, keyring, registry, bus, redis,
|
|
@@ -171,14 +173,46 @@ let ChannelConnections = class ChannelConnections {
|
|
|
171
173
|
throw new ApiError("extension.not_enabled", `Extension ${plugin} is not enabled for this organization`);
|
|
172
174
|
}
|
|
173
175
|
}
|
|
174
|
-
/**
|
|
176
|
+
/**
|
|
177
|
+
* The connection schema's form JSON Schema (secret fields carry `x-secret`, no values), a copy.
|
|
178
|
+
* Never throws: when even the plain conversion fails, an empty object schema (a save is still
|
|
179
|
+
* validated here).
|
|
180
|
+
*/
|
|
175
181
|
jsonSchema(plugin) {
|
|
176
|
-
|
|
182
|
+
const entry = this.channelEntry(plugin);
|
|
183
|
+
const r = this.formSchema(plugin, entry.version, entry.impl.connectionSchema);
|
|
184
|
+
return r ? structuredClone(r.schema) : { type: "object" };
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* The connection schema's form JSON Schema; invalid hints are stripped and warned about once per
|
|
188
|
+
* `<plugin>@<version>` on this replica (spec §4.1: the connection level is checked at its first
|
|
189
|
+
* conversion, not at load). Never throws: a hint conversion that throws serves the plain schema,
|
|
190
|
+
* else null, with one warning per schema.
|
|
191
|
+
*/
|
|
192
|
+
formSchema(plugin, version, schema) {
|
|
193
|
+
const r = safeConfigFormSchema(schema, "connection", (err, fallback) => this.log.warn("the channel connection form schema could not be built with its UI hints; hints dropped", { plugin, version, schema: fallback, err }));
|
|
194
|
+
const key = `${plugin}@${version}`;
|
|
195
|
+
if (r && r.problems.length > 0 && !this.hintsWarned.has(key)) {
|
|
196
|
+
this.hintsWarned.add(key);
|
|
197
|
+
this.log.warn("extension config UI hints are invalid and ignored", {
|
|
198
|
+
plugin,
|
|
199
|
+
version,
|
|
200
|
+
detail: describeConfigUiProblems("connection", r.problems),
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
return r;
|
|
204
|
+
}
|
|
205
|
+
/** The loaded version of a channel extension, for warnings ("unknown" when not provided). */
|
|
206
|
+
versionOf(plugin) {
|
|
207
|
+
return (this.registry
|
|
208
|
+
.list("channel")
|
|
209
|
+
.find((x) => x.plugin === plugin && x.capability === CHANNEL_EXTENSION_POINT)?.version ??
|
|
210
|
+
"unknown");
|
|
177
211
|
}
|
|
178
212
|
parse(plugin, schema, config) {
|
|
179
213
|
const r = schema.safeParse(config);
|
|
180
214
|
if (!r.success) {
|
|
181
|
-
throw new ApiError("extension.config_invalid", `Invalid channel connection config for extension ${plugin}`, toIssues(r.error));
|
|
215
|
+
throw new ApiError("extension.config_invalid", `Invalid channel connection config for extension ${plugin}`, toIssues(r.error, configMessages(this.formSchema(plugin, this.versionOf(plugin), schema)?.schema)));
|
|
182
216
|
}
|
|
183
217
|
return r.data;
|
|
184
218
|
}
|
|
@@ -48,3 +48,8 @@ export declare function findThread(db: KernelSchemaDb, k: ThreadKey): Promise<st
|
|
|
48
48
|
export declare function insertThread(db: KernelSchemaDb, k: ThreadKey, conversationId: string): Promise<string>;
|
|
49
49
|
/** 私聊 `/new`:归档当前话题行(下一条消息新建对话)。返回是否归档了一行。 */
|
|
50
50
|
export declare function archiveThread(db: KernelSchemaDb, k: ThreadKey): Promise<boolean>;
|
|
51
|
+
/**
|
|
52
|
+
* Drops a conversation's channel bindings (its thread rows and its delivery target), so a deleted
|
|
53
|
+
* conversation neither receives inbound messages nor posts to the chat any more.
|
|
54
|
+
*/
|
|
55
|
+
export declare function unbindConversation(db: KernelSchemaDb, conversationId: string): Promise<void>;
|
package/dist/channels/threads.js
CHANGED
|
@@ -160,3 +160,11 @@ export async function archiveThread(db, k) {
|
|
|
160
160
|
.executeTakeFirst();
|
|
161
161
|
return r.numUpdatedRows > 0n;
|
|
162
162
|
}
|
|
163
|
+
/**
|
|
164
|
+
* Drops a conversation's channel bindings (its thread rows and its delivery target), so a deleted
|
|
165
|
+
* conversation neither receives inbound messages nor posts to the chat any more.
|
|
166
|
+
*/
|
|
167
|
+
export async function unbindConversation(db, conversationId) {
|
|
168
|
+
await db.deleteFrom("channel_threads").where("conversation_id", "=", conversationId).execute();
|
|
169
|
+
await db.deleteFrom("channel_deliveries").where("conversation_id", "=", conversationId).execute();
|
|
170
|
+
}
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -51,6 +51,7 @@ export declare const KernelConfigSchema: z.ZodObject<{
|
|
|
51
51
|
url: z.ZodString;
|
|
52
52
|
poolMax: z.ZodDefault<z.ZodNumber>;
|
|
53
53
|
connectTimeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
54
|
+
idleTimeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
54
55
|
}, z.core.$strip>>;
|
|
55
56
|
redis: z.ZodPrefault<z.ZodObject<{
|
|
56
57
|
url: z.ZodString;
|
|
@@ -119,6 +120,7 @@ export declare const KernelConfigSchema: z.ZodObject<{
|
|
|
119
120
|
}, z.core.$strip>>;
|
|
120
121
|
runtime: z.ZodDefault<z.ZodObject<{
|
|
121
122
|
maxSteps: z.ZodDefault<z.ZodNumber>;
|
|
123
|
+
wakeOnBackgroundTask: z.ZodDefault<z.ZodBoolean>;
|
|
122
124
|
maxRunSeconds: z.ZodDefault<z.ZodNumber>;
|
|
123
125
|
streamIdleMs: z.ZodDefault<z.ZodNumber>;
|
|
124
126
|
maxOutputTokens: z.ZodDefault<z.ZodNumber>;
|
|
@@ -179,11 +181,27 @@ export declare const KernelConfigSchema: z.ZodObject<{
|
|
|
179
181
|
maxDispatchesPerRun: z.ZodDefault<z.ZodNumber>;
|
|
180
182
|
maxTokensPerRun: z.ZodDefault<z.ZodNumber>;
|
|
181
183
|
}, z.core.$strip>>;
|
|
184
|
+
web: z.ZodPrefault<z.ZodObject<{
|
|
185
|
+
search: z.ZodPrefault<z.ZodObject<{
|
|
186
|
+
maxResults: z.ZodDefault<z.ZodNumber>;
|
|
187
|
+
}, z.core.$strip>>;
|
|
188
|
+
fetch: z.ZodPrefault<z.ZodObject<{
|
|
189
|
+
maxPageChars: z.ZodDefault<z.ZodNumber>;
|
|
190
|
+
maxAnswerTokens: z.ZodDefault<z.ZodNumber>;
|
|
191
|
+
cacheSeconds: z.ZodDefault<z.ZodNumber>;
|
|
192
|
+
timeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
193
|
+
}, z.core.$strip>>;
|
|
194
|
+
}, z.core.$strip>>;
|
|
182
195
|
sandbox: z.ZodPrefault<z.ZodObject<{
|
|
183
196
|
image: z.ZodDefault<z.ZodString>;
|
|
184
197
|
lockWaitSeconds: z.ZodDefault<z.ZodNumber>;
|
|
185
198
|
maxConcurrentCommands: z.ZodDefault<z.ZodNumber>;
|
|
186
199
|
deliverMaxBytes: z.ZodDefault<z.ZodNumber>;
|
|
200
|
+
background: z.ZodPrefault<z.ZodObject<{
|
|
201
|
+
maxTasks: z.ZodDefault<z.ZodNumber>;
|
|
202
|
+
maxSeconds: z.ZodDefault<z.ZodNumber>;
|
|
203
|
+
pollSeconds: z.ZodDefault<z.ZodNumber>;
|
|
204
|
+
}, z.core.$strip>>;
|
|
187
205
|
limits: z.ZodPrefault<z.ZodObject<{
|
|
188
206
|
cpu: z.ZodDefault<z.ZodNumber>;
|
|
189
207
|
memoryMb: z.ZodDefault<z.ZodNumber>;
|