@capybara-hq/kernel 0.1.0-rc.19 → 0.1.0-rc.20
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/bootstrap.json +25 -25
- package/dist/admin/admin-agents.controller.d.ts +28 -0
- package/dist/admin/admin-agents.controller.js +79 -0
- package/dist/admin/admin-connectors.controller.d.ts +29 -0
- package/dist/admin/admin-connectors.controller.js +79 -0
- package/dist/admin/admin-items.schemas.d.ts +42 -0
- package/dist/admin/admin-items.schemas.js +48 -0
- package/dist/admin/admin.controller.d.ts +11 -20
- package/dist/admin/admin.controller.js +28 -34
- package/dist/admin/admin.module.d.ts +4 -1
- package/dist/admin/admin.module.js +50 -4
- package/dist/admin/admin.schemas.d.ts +4 -0
- package/dist/admin/admin.schemas.js +4 -1
- package/dist/admin/audit.controller.d.ts +14 -0
- package/dist/admin/audit.controller.js +42 -0
- package/dist/admin/audit.schemas.d.ts +8 -0
- package/dist/admin/audit.schemas.js +17 -0
- package/dist/admin/health.service.d.ts +104 -0
- package/dist/admin/health.service.js +246 -0
- package/dist/admin/overview.controller.d.ts +31 -0
- package/dist/admin/overview.controller.js +78 -0
- package/dist/admin/overview.schemas.d.ts +8 -0
- package/dist/admin/overview.schemas.js +13 -0
- package/dist/admin/overview.service.d.ts +112 -0
- package/dist/admin/overview.service.js +223 -0
- package/dist/admin/platform-audit.service.d.ts +41 -0
- package/dist/admin/platform-audit.service.js +70 -0
- package/dist/admin/usage.service.d.ts +149 -0
- package/dist/admin/usage.service.js +321 -0
- package/dist/agents/admin-agents.d.ts +92 -0
- package/dist/agents/admin-agents.js +170 -0
- package/dist/agents/agents.module.d.ts +4 -3
- package/dist/agents/agents.module.js +7 -3
- package/dist/agents/agents.service.d.ts +41 -3
- package/dist/agents/agents.service.js +113 -27
- package/dist/agents/definition.d.ts +16 -0
- package/dist/agents/definition.js +32 -2
- package/dist/agents/org-templates.js +4 -0
- package/dist/background/launch.d.ts +1 -1
- package/dist/background/launch.js +3 -3
- package/dist/background/tasks.service.d.ts +35 -3
- package/dist/background/tasks.service.js +91 -36
- package/dist/catalog/catalog.module.js +8 -2
- package/dist/channels/channels.module.js +11 -2
- package/dist/channels/supervisor.d.ts +2 -0
- package/dist/channels/supervisor.js +4 -0
- package/dist/conversations/events.js +1 -1
- package/dist/conversations/titles.js +4 -8
- package/dist/db/kernel-schema.d.ts +8 -1
- package/dist/devices/devices.module.js +5 -2
- package/dist/errors.d.ts +22 -2
- package/dist/errors.js +22 -2
- package/dist/evals/evals.module.js +11 -2
- package/dist/extensions/permission-view.js +3 -3
- package/dist/http/api.module.js +10 -1
- package/dist/identity/settings.js +3 -2
- package/dist/identity/write-actor.d.ts +11 -0
- package/dist/identity/write-actor.js +7 -0
- package/dist/inbox/inbox.service.d.ts +2 -1
- package/dist/inbox/platform-inbox.service.d.ts +7 -1
- package/dist/inbox/platform-inbox.service.js +20 -2
- package/dist/infra/presence/presence.module.d.ts +6 -0
- package/dist/infra/presence/presence.module.js +22 -0
- package/dist/infra/presence/replica-presence.d.ts +87 -0
- package/dist/infra/presence/replica-presence.js +189 -0
- package/dist/kernel.module.js +3 -0
- package/dist/lifecycle/kernel-lifecycle.d.ts +3 -1
- package/dist/lifecycle/kernel-lifecycle.js +17 -3
- package/dist/local-devices/local-device-gateway.d.ts +6 -0
- package/dist/local-devices/local-device-gateway.js +12 -0
- package/dist/overrides.d.ts +7 -1
- package/dist/overrides.js +4 -0
- package/dist/platform/exclusions.js +15 -0
- package/dist/platform/operation.d.ts +1 -1
- package/dist/platform/operation.js +1 -1
- package/dist/platform/ops/admin-items.ops.d.ts +37 -0
- package/dist/platform/ops/admin-items.ops.js +278 -0
- package/dist/platform/ops/admin.ops.d.ts +10 -10
- package/dist/platform/ops/admin.ops.js +111 -42
- package/dist/platform/ops/agent-skills.ops.d.ts +29 -3
- package/dist/platform/ops/agent-skills.ops.js +290 -7
- package/dist/platform/ops/inbox.ops.js +7 -4
- package/dist/platform/ops/platform.ops.js +1 -1
- package/dist/platform/ops/skills.ops.js +1 -57
- package/dist/platform/platform-ops.module.d.ts +2 -1
- package/dist/platform/platform-ops.module.js +5 -0
- package/dist/platform/route-schemas.js +8 -0
- package/dist/roles/gateway-role.d.ts +4 -0
- package/dist/roles/gateway-role.js +8 -0
- package/dist/runtime/run-jobs.js +4 -2
- package/dist/sandbox/sandbox-file-reader.d.ts +35 -0
- package/dist/sandbox/sandbox-file-reader.js +98 -0
- package/dist/skills/agent-skills.controller.d.ts +48 -0
- package/dist/skills/agent-skills.controller.js +131 -0
- package/dist/skills/agent-skills.service.d.ts +262 -0
- package/dist/skills/agent-skills.service.js +996 -0
- package/dist/skills/catalog.d.ts +8 -6
- package/dist/skills/catalog.js +8 -4
- package/dist/skills/changes.controller.d.ts +5 -22
- package/dist/skills/changes.controller.js +7 -55
- package/dist/skills/changes.service.d.ts +69 -115
- package/dist/skills/changes.service.js +249 -599
- package/dist/skills/conversation-catalog.d.ts +53 -0
- package/dist/skills/conversation-catalog.js +149 -0
- package/dist/skills/invocation-keys.d.ts +1 -1
- package/dist/skills/invocation-keys.js +1 -1
- package/dist/skills/package.d.ts +0 -5
- package/dist/skills/package.js +0 -14
- package/dist/skills/skills.controller.js +1 -10
- package/dist/skills/skills.module.js +15 -2
- package/dist/skills/skills.schemas.d.ts +11 -15
- package/dist/skills/skills.schemas.js +27 -20
- package/dist/skills/skills.service.d.ts +37 -30
- package/dist/skills/skills.service.js +107 -59
- package/dist/skills/usable.d.ts +4 -3
- package/dist/skills/usable.js +13 -4
- package/dist/tools/admin-connectors.d.ts +69 -0
- package/dist/tools/admin-connectors.js +135 -0
- package/dist/tools/builtin-names.d.ts +9 -14
- package/dist/tools/builtin-names.js +13 -22
- package/dist/tools/builtins/builtin-tools.d.ts +2 -3
- package/dist/tools/builtins/builtin-tools.js +21 -26
- package/dist/tools/builtins/sandbox/bash.js +2 -2
- package/dist/tools/builtins/skill-load.js +1 -0
- package/dist/tools/connectors.controller.d.ts +5 -1
- package/dist/tools/connectors.controller.js +17 -3
- package/dist/tools/connectors.service.d.ts +20 -1
- package/dist/tools/connectors.service.js +61 -0
- package/dist/tools/legacy-keys.js +0 -1
- package/dist/tools/org-tool-switches.d.ts +3 -2
- package/dist/tools/org-tool-switches.js +4 -4
- package/dist/tools/policy.d.ts +7 -9
- package/dist/tools/policy.js +11 -22
- package/dist/tools/tools.module.js +3 -0
- package/package.json +1 -1
- package/src/migrations/0109_audit_platform_idx.sql +5 -0
- package/src/migrations/0110_usage_time_idx.sql +8 -0
- package/src/migrations/0111_agent_skill_sharing.sql +22 -0
- package/src/migrations/0112_skill_share_requests.sql +4 -0
- package/dist/tools/builtins/skill-write.d.ts +0 -59
- package/dist/tools/builtins/skill-write.js +0 -244
|
@@ -28,7 +28,6 @@ import { conversationTimeZone, RUN_CONTEXT_CLOCK } from "../../runtime/run-conte
|
|
|
28
28
|
import { StepLog } from "../../runtime/step-log.js";
|
|
29
29
|
import { UsageReporter } from "../../runtime/usage-report.js";
|
|
30
30
|
import { SandboxService } from "../../sandbox/sandbox.service.js";
|
|
31
|
-
import { SkillChangesService } from "../../skills/changes.service.js";
|
|
32
31
|
import { StorageService } from "../../storage/storage.service.js";
|
|
33
32
|
import { ToolOutputs } from "../outputs.js";
|
|
34
33
|
import { agentTool } from "./agent.js";
|
|
@@ -40,18 +39,17 @@ import { readToolOutputTool } from "./read-tool-output.js";
|
|
|
40
39
|
import { sandboxTools } from "./sandbox/index.js";
|
|
41
40
|
import { sendMessageTool } from "./send-message.js";
|
|
42
41
|
import { skillLoadTool } from "./skill-load.js";
|
|
43
|
-
import { skillWriteTool } from "./skill-write.js";
|
|
44
42
|
import { toolSearchTool } from "./tool-search.js";
|
|
45
43
|
import { extractAnswer, WebPages, webTools } from "./web/index.js";
|
|
46
44
|
/**
|
|
47
45
|
* The kernel's builtin tools, built once from the injected services (their specs: names,
|
|
48
46
|
* descriptions and schemas, are the factories' own and unchanged). `ToolSearch` and `Skill`
|
|
49
47
|
* are added to a run by the registry (`forAgent`: organization setting and threshold, a skills
|
|
50
|
-
* catalog snapshot), not by agent definitions
|
|
48
|
+
* catalog snapshot), not by agent definitions.
|
|
51
49
|
*/
|
|
52
50
|
let BuiltinTools = class BuiltinTools {
|
|
53
51
|
tools;
|
|
54
|
-
constructor(db, config, outputs, storage,
|
|
52
|
+
constructor(db, config, outputs, storage, attachments, eventLog, sandbox, devices, points, webPages,
|
|
55
53
|
/** The WebFetch extraction call: the `web_fetch` purpose, its hooks, usage and denials. */
|
|
56
54
|
purposes, host, usageReport, stepLog, log, background, finisher, stopper, platformOps, platformActor, agentDocs,
|
|
57
55
|
/** The clock `CurrentTime` reads (the run context's clock seam; `Date.now` by default). */
|
|
@@ -91,8 +89,6 @@ let BuiltinTools = class BuiltinTools {
|
|
|
91
89
|
return db.db;
|
|
92
90
|
},
|
|
93
91
|
}),
|
|
94
|
-
// 自写技能:agent 定义显式引用才可用
|
|
95
|
-
skillWriteTool({ changes: skillChanges }),
|
|
96
92
|
// web search / fetch through the org's default provider (web tools spec §3); WebFetch answers
|
|
97
93
|
// from the page with one call on the `web_fetch` purpose (§5), never returning the page
|
|
98
94
|
...webTools({
|
|
@@ -127,25 +123,24 @@ BuiltinTools = __decorate([
|
|
|
127
123
|
__param(1, Inject(KernelConfigService)),
|
|
128
124
|
__param(2, Inject(ToolOutputs)),
|
|
129
125
|
__param(3, Inject(StorageService)),
|
|
130
|
-
__param(4, Inject(
|
|
131
|
-
__param(5, Inject(
|
|
132
|
-
__param(6, Inject(
|
|
133
|
-
__param(7, Inject(
|
|
134
|
-
__param(8, Inject(
|
|
135
|
-
__param(9, Inject(
|
|
136
|
-
__param(10, Inject(
|
|
137
|
-
__param(11, Inject(
|
|
138
|
-
__param(12, Inject(
|
|
139
|
-
__param(13, Inject(
|
|
140
|
-
__param(14, Inject(
|
|
141
|
-
__param(15, Inject(
|
|
142
|
-
__param(16, Inject(
|
|
143
|
-
__param(17, Inject(
|
|
144
|
-
__param(18, Inject(
|
|
145
|
-
__param(19, Inject(
|
|
146
|
-
__param(20, Inject(
|
|
147
|
-
__param(21,
|
|
148
|
-
__param(
|
|
149
|
-
__param(22, Inject(RUN_CONTEXT_CLOCK))
|
|
126
|
+
__param(4, Inject(AttachmentsService)),
|
|
127
|
+
__param(5, Inject(EventLog)),
|
|
128
|
+
__param(6, Inject(SandboxService)),
|
|
129
|
+
__param(7, Inject(ConversationDevices)),
|
|
130
|
+
__param(8, Inject(ExtensionPointDefaults)),
|
|
131
|
+
__param(9, Inject(WebPages)),
|
|
132
|
+
__param(10, Inject(ModelPurposesService)),
|
|
133
|
+
__param(11, Inject(ExtensionHost)),
|
|
134
|
+
__param(12, Inject(UsageReporter)),
|
|
135
|
+
__param(13, Inject(StepLog)),
|
|
136
|
+
__param(14, Inject(KERNEL_LOGGER)),
|
|
137
|
+
__param(15, Inject(BackgroundTaskStore)),
|
|
138
|
+
__param(16, Inject(BackgroundTaskFinisher)),
|
|
139
|
+
__param(17, Inject(BackgroundTaskStopper)),
|
|
140
|
+
__param(18, Inject(PlatformOperations)),
|
|
141
|
+
__param(19, Inject(PlatformActor)),
|
|
142
|
+
__param(20, Inject(AgentDocs)),
|
|
143
|
+
__param(21, Optional()),
|
|
144
|
+
__param(21, Inject(RUN_CONTEXT_CLOCK))
|
|
150
145
|
], BuiltinTools);
|
|
151
146
|
export { BuiltinTools };
|
|
@@ -282,13 +282,13 @@ async function runInBackground(deps, ctx, input) {
|
|
|
282
282
|
await announce();
|
|
283
283
|
if (!isLarge || e instanceof ToolError)
|
|
284
284
|
throw e;
|
|
285
|
-
throw new ToolError(`The background task was not started: ${clip(why, 500).replace(/\.$/, "")}. Check the
|
|
285
|
+
throw new ToolError(`The background task was not started: ${clip(why, 500).replace(/\.$/, "")}. Check the environment, or call Bash without run_in_background.${largeText()}`);
|
|
286
286
|
}
|
|
287
287
|
}
|
|
288
288
|
if (launch.kind === "not_started") {
|
|
289
289
|
await background.failLaunch(id, launch.why);
|
|
290
290
|
await announce();
|
|
291
|
-
throw new ToolError(`The background task was not started: ${launch.why}. Check the
|
|
291
|
+
throw new ToolError(`The background task was not started: ${launch.why}. Check the environment, or call Bash without run_in_background.${largeText()}`);
|
|
292
292
|
}
|
|
293
293
|
if (launch.kind === "stopped") {
|
|
294
294
|
await announce();
|
|
@@ -220,6 +220,7 @@ export async function findSkillVersion(db, ctx, entry) {
|
|
|
220
220
|
.where("org_id", "=", ctx.orgId)
|
|
221
221
|
.where("requested_in_conversation", "=", ctx.conversationId)
|
|
222
222
|
.where("status", "=", "pending")
|
|
223
|
+
.where("kind", "=", "version")
|
|
223
224
|
.where("object_prefix", "=", entry.source)
|
|
224
225
|
.where(sql `proposed_version ->> 'skillId'`, "=", entry.id)
|
|
225
226
|
.executeTakeFirst();
|
|
@@ -2,6 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
import type { ConnectionGuideState } from "../extensions/plugin-guides.js";
|
|
3
3
|
import { PluginIcons } from "../extensions/plugin-icons.js";
|
|
4
4
|
import { type Principal } from "../identity/principal.js";
|
|
5
|
+
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
5
6
|
import { type OrgContext } from "../orgs/org.guard.js";
|
|
6
7
|
import { ConnectorAccountPolicies, type MemberToolPolicyView } from "./connector-account-policies.js";
|
|
7
8
|
import { ConnectorGuideAckSchema, CredentialValue, MemberToolPoliciesBody } from "./connectors.schemas.js";
|
|
@@ -177,6 +178,8 @@ declare const UpdateBody: z.ZodObject<{
|
|
|
177
178
|
*/
|
|
178
179
|
export type ConnectorPage<T extends ConnectorSummary = ConnectorDetail> = T & ConnectionGuideState & {
|
|
179
180
|
icon: string | null;
|
|
181
|
+
/** The one-connector read of an `oauth_code` connector, for managers: its redirect URI. */
|
|
182
|
+
oauthCallbackUrl?: string | null;
|
|
180
183
|
};
|
|
181
184
|
/**
|
|
182
185
|
* 连接器(`/api/v1/orgs/:orgId/connectors`):读与个人凭据用 `connectors.use`(访客起),安装 / 修改 / 删除 / 刷新 /
|
|
@@ -186,7 +189,8 @@ export declare class ConnectorsController {
|
|
|
186
189
|
private readonly connectors;
|
|
187
190
|
private readonly icons;
|
|
188
191
|
private readonly memberPolicies;
|
|
189
|
-
|
|
192
|
+
private readonly config;
|
|
193
|
+
constructor(connectors: ConnectorsService, icons: PluginIcons, memberPolicies: ConnectorAccountPolicies, config: Pick<KernelConfigService, "get">);
|
|
190
194
|
/**
|
|
191
195
|
* Each connector with `icon`: the icon of the plugin its template came from, on the org's catalog
|
|
192
196
|
* route (null for a custom connector, a plugin without an icon, or one the reader's catalog does
|
|
@@ -12,6 +12,7 @@ import { Controller, Delete, Get, HttpCode, Inject, Param, Patch, Post, Put } fr
|
|
|
12
12
|
import { z } from "zod";
|
|
13
13
|
import { orgIconScope, PluginIcons } from "../extensions/plugin-icons.js";
|
|
14
14
|
import { CurrentPrincipal, patTokenId, requireUser, } from "../identity/principal.js";
|
|
15
|
+
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
15
16
|
import { createZodDto } from "../infra/validation/create-zod-dto.js";
|
|
16
17
|
import { ZBody } from "../infra/validation/zod-params.js";
|
|
17
18
|
import { CurrentOrg, OrgAction } from "../orgs/org.guard.js";
|
|
@@ -20,6 +21,7 @@ import { ConnectorAccountPolicies, } from "./connector-account-policies.js";
|
|
|
20
21
|
import { ConnectorGuideAckSchema, CredentialValue, MemberToolPoliciesBody, } from "./connectors.schemas.js";
|
|
21
22
|
import { ConnectorsService, } from "./connectors.service.js";
|
|
22
23
|
import { publicEndpoint } from "./endpoint.js";
|
|
24
|
+
import { callbackUrl } from "./oauth/flow-paths.js";
|
|
23
25
|
/**
|
|
24
26
|
* 没有 `connectors.manage` 的读者只看到端点的公开部分(URL 不带 query、只有头名,见 endpoint.ts),
|
|
25
27
|
* 也看不到工具的连接器数据(可能含服务器地址)。
|
|
@@ -98,10 +100,12 @@ let ConnectorsController = class ConnectorsController {
|
|
|
98
100
|
connectors;
|
|
99
101
|
icons;
|
|
100
102
|
memberPolicies;
|
|
101
|
-
|
|
103
|
+
config;
|
|
104
|
+
constructor(connectors, icons, memberPolicies, config) {
|
|
102
105
|
this.connectors = connectors;
|
|
103
106
|
this.icons = icons;
|
|
104
107
|
this.memberPolicies = memberPolicies;
|
|
108
|
+
this.config = config;
|
|
105
109
|
}
|
|
106
110
|
/**
|
|
107
111
|
* Each connector with `icon`: the icon of the plugin its template came from, on the org's catalog
|
|
@@ -157,7 +161,16 @@ let ConnectorsController = class ConnectorsController {
|
|
|
157
161
|
async get(principal, org, connectorId) {
|
|
158
162
|
const p = requireUser(principal);
|
|
159
163
|
const view = forViewer(org, await this.connectors.get(org.orgId, connectorId, p.account.id));
|
|
160
|
-
|
|
164
|
+
const page = await this.withGuide(org, view);
|
|
165
|
+
// The redirect URI to register at the authorization server, for those who manage connectors
|
|
166
|
+
// (the credentials tab shows it next to the OAuth client); null without `http.publicUrl`.
|
|
167
|
+
if (page.auth.type !== "oauth_code" || !can(org.role, "connectors.manage")) {
|
|
168
|
+
return { connector: page };
|
|
169
|
+
}
|
|
170
|
+
const publicUrl = this.config.get().http.publicUrl;
|
|
171
|
+
return {
|
|
172
|
+
connector: { ...page, oauthCallbackUrl: publicUrl ? callbackUrl(publicUrl) : null },
|
|
173
|
+
};
|
|
161
174
|
}
|
|
162
175
|
async update(principal, org, connectorId, body) {
|
|
163
176
|
const p = requireUser(principal);
|
|
@@ -343,6 +356,7 @@ ConnectorsController = __decorate([
|
|
|
343
356
|
Controller("api/v1/orgs/:orgId/connectors"),
|
|
344
357
|
__param(0, Inject(ConnectorsService)),
|
|
345
358
|
__param(1, Inject(PluginIcons)),
|
|
346
|
-
__param(2, Inject(ConnectorAccountPolicies))
|
|
359
|
+
__param(2, Inject(ConnectorAccountPolicies)),
|
|
360
|
+
__param(3, Inject(KernelConfigService))
|
|
347
361
|
], ConnectorsController);
|
|
348
362
|
export { ConnectorsController };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type AuthHint, type ConnectorOperation, type ToolAnnotations } from "@capybara-hq/plugin-sdk";
|
|
2
2
|
import { type ConnectionGuideState, PluginGuides } from "../extensions/plugin-guides.js";
|
|
3
3
|
import { ExtensionRegistry } from "../extensions/registry.js";
|
|
4
|
+
import type { WriteActor } from "../identity/write-actor.js";
|
|
4
5
|
import { KernelConfigService } from "../infra/config/kernel-config.service.js";
|
|
5
6
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
6
7
|
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
@@ -220,7 +221,7 @@ export declare class ConnectorsService {
|
|
|
220
221
|
/** Extension manifests (a slug may not take an extension's name). */
|
|
221
222
|
extensions: Pick<ExtensionRegistry, "manifests">, credentials: Credentials, config: Pick<KernelConfigService, "get">, drift: ToolDrift,
|
|
222
223
|
/** The org row lock (orgs/org-lock.ts): joins the caller's transaction. */
|
|
223
|
-
orgLock: Pick<OrgLock, "lockAndAuthorize">, txHost: TransactionHost,
|
|
224
|
+
orgLock: Pick<OrgLock, "lock" | "lockAndAuthorize">, txHost: TransactionHost,
|
|
224
225
|
/** Setup guides of connector templates (spec 2026-11-09-setup-guides-v2-design.md §11). */
|
|
225
226
|
guides: Pick<PluginGuides, "templateAck" | "connectorStates">);
|
|
226
227
|
/** The kernel-schema handle of the current context (its transaction, else the pool). */
|
|
@@ -338,6 +339,24 @@ export declare class ConnectorsService {
|
|
|
338
339
|
get(orgId: string, connectorId: string, viewerAccountId: string): Promise<ConnectorDetail>;
|
|
339
340
|
/** 改名、启停连接器、工具启停与默认策略、批量把无注解工具改为 allow(`connectors.manage`)。 */
|
|
340
341
|
update(orgId: string, connectorId: string, actorAccountId: string, patch: UpdateConnectorInput, actorTokenId?: string): Promise<ConnectorDetail>;
|
|
342
|
+
/**
|
|
343
|
+
* The org id of a live connector of a live org (the platform paths address a connector by its
|
|
344
|
+
* global id); else `connector.not_found`.
|
|
345
|
+
*/
|
|
346
|
+
private liveOrgOf;
|
|
347
|
+
/**
|
|
348
|
+
* Disables or enables a connector on the platform's behalf (a super admin who need not be a
|
|
349
|
+
* member of the org; the caller checks the super admin): org row lock, the status update, audit
|
|
350
|
+
* `connector.updated` with `via: "platform"`. `auditDetail` (a Platform tool write's
|
|
351
|
+
* `viaAgent`) is merged into the detail; `via` stays `"platform"`.
|
|
352
|
+
*/
|
|
353
|
+
setStatusAsPlatform(connectorId: string, status: "active" | "disabled", actor: WriteActor, auditDetail?: Record<string, unknown>): Promise<void>;
|
|
354
|
+
/**
|
|
355
|
+
* Deletes a connector on the platform's behalf (see {@link setStatusAsPlatform}): org row lock,
|
|
356
|
+
* then {@link removeIn} with `via: "platform"` in the audit detail (merged over `auditDetail`,
|
|
357
|
+
* a Platform tool write's `viaAgent`).
|
|
358
|
+
*/
|
|
359
|
+
removeAsPlatform(connectorId: string, actor: WriteActor, auditDetail?: Record<string, unknown>): Promise<void>;
|
|
341
360
|
/** 软删除,并删除该连接器的全部凭据(`connectors.manage`)。 */
|
|
342
361
|
remove(orgId: string, connectorId: string, actorAccountId: string, actorTokenId?: string, auditDetail?: Record<string, unknown>): Promise<void>;
|
|
343
362
|
/**
|
|
@@ -1051,6 +1051,61 @@ let ConnectorsService = class ConnectorsService {
|
|
|
1051
1051
|
});
|
|
1052
1052
|
return this.detail(t, orgId, connectorId, actorAccountId);
|
|
1053
1053
|
}
|
|
1054
|
+
/**
|
|
1055
|
+
* The org id of a live connector of a live org (the platform paths address a connector by its
|
|
1056
|
+
* global id); else `connector.not_found`.
|
|
1057
|
+
*/
|
|
1058
|
+
async liveOrgOf(connectorId) {
|
|
1059
|
+
const r = await this.db
|
|
1060
|
+
.selectFrom("connectors as c")
|
|
1061
|
+
.innerJoin("orgs as o", "o.id", "c.org_id")
|
|
1062
|
+
.select("c.org_id")
|
|
1063
|
+
.where("c.id", "=", connectorId)
|
|
1064
|
+
.where("c.deleted_at", "is", null)
|
|
1065
|
+
.where("o.deleted_at", "is", null)
|
|
1066
|
+
.executeTakeFirst();
|
|
1067
|
+
if (!r)
|
|
1068
|
+
throw notFound();
|
|
1069
|
+
return r.org_id;
|
|
1070
|
+
}
|
|
1071
|
+
/**
|
|
1072
|
+
* Disables or enables a connector on the platform's behalf (a super admin who need not be a
|
|
1073
|
+
* member of the org; the caller checks the super admin): org row lock, the status update, audit
|
|
1074
|
+
* `connector.updated` with `via: "platform"`. `auditDetail` (a Platform tool write's
|
|
1075
|
+
* `viaAgent`) is merged into the detail; `via` stays `"platform"`.
|
|
1076
|
+
*/
|
|
1077
|
+
async setStatusAsPlatform(connectorId, status, actor, auditDetail) {
|
|
1078
|
+
const t = this.db;
|
|
1079
|
+
const orgId = await this.liveOrgOf(connectorId);
|
|
1080
|
+
await this.orgLock.lock(orgId);
|
|
1081
|
+
const app = await this.row(t, orgId, connectorId, true);
|
|
1082
|
+
await t
|
|
1083
|
+
.updateTable("connectors")
|
|
1084
|
+
.set({ status, updated_at: sql `now()` })
|
|
1085
|
+
.where("id", "=", connectorId)
|
|
1086
|
+
.execute();
|
|
1087
|
+
await audit(t, {
|
|
1088
|
+
actorAccountId: actor.accountId,
|
|
1089
|
+
...(actor.tokenId !== undefined && { actorTokenId: actor.tokenId }),
|
|
1090
|
+
orgId,
|
|
1091
|
+
action: "connector.updated",
|
|
1092
|
+
target: connectorId,
|
|
1093
|
+
detail: { ...auditDetail, status: { from: app.status, to: status }, via: "platform" },
|
|
1094
|
+
});
|
|
1095
|
+
}
|
|
1096
|
+
/**
|
|
1097
|
+
* Deletes a connector on the platform's behalf (see {@link setStatusAsPlatform}): org row lock,
|
|
1098
|
+
* then {@link removeIn} with `via: "platform"` in the audit detail (merged over `auditDetail`,
|
|
1099
|
+
* a Platform tool write's `viaAgent`).
|
|
1100
|
+
*/
|
|
1101
|
+
async removeAsPlatform(connectorId, actor, auditDetail) {
|
|
1102
|
+
const orgId = await this.liveOrgOf(connectorId);
|
|
1103
|
+
await this.orgLock.lock(orgId);
|
|
1104
|
+
await this.removeIn(orgId, connectorId, actor.accountId, actor.tokenId, undefined, {
|
|
1105
|
+
...auditDetail,
|
|
1106
|
+
via: "platform",
|
|
1107
|
+
});
|
|
1108
|
+
}
|
|
1054
1109
|
/** 软删除,并删除该连接器的全部凭据(`connectors.manage`)。 */
|
|
1055
1110
|
async remove(orgId, connectorId, actorAccountId, actorTokenId, auditDetail) {
|
|
1056
1111
|
await this.orgLock.lockAndAuthorize(orgId, actorAccountId, "connectors.manage");
|
|
@@ -1333,6 +1388,12 @@ __decorate([
|
|
|
1333
1388
|
__decorate([
|
|
1334
1389
|
Transactional()
|
|
1335
1390
|
], ConnectorsService.prototype, "update", null);
|
|
1391
|
+
__decorate([
|
|
1392
|
+
Transactional()
|
|
1393
|
+
], ConnectorsService.prototype, "setStatusAsPlatform", null);
|
|
1394
|
+
__decorate([
|
|
1395
|
+
Transactional()
|
|
1396
|
+
], ConnectorsService.prototype, "removeAsPlatform", null);
|
|
1336
1397
|
__decorate([
|
|
1337
1398
|
Transactional()
|
|
1338
1399
|
], ConnectorsService.prototype, "remove", null);
|
|
@@ -20,7 +20,6 @@ export const LEGACY_BUILTINS = Object.freeze({
|
|
|
20
20
|
sandbox_grep: { name: BUILTIN.Grep, params: { ignoreCase: "-i" } },
|
|
21
21
|
sandbox_deliver: { name: BUILTIN.Deliver, params: { path: "file_path" } },
|
|
22
22
|
skill_load: { name: BUILTIN.Skill, params: { name: "skill" } },
|
|
23
|
-
skill_write: { name: BUILTIN.SkillWrite, params: {} },
|
|
24
23
|
ask_user: { name: BUILTIN.AskUserQuestion, params: {} },
|
|
25
24
|
read_tool_output: { name: BUILTIN.ReadToolOutput, params: {} },
|
|
26
25
|
tool_search: { name: BUILTIN.ToolSearch, params: { limit: "max_results" } },
|
|
@@ -39,7 +39,7 @@ export declare class OrgToolSwitches {
|
|
|
39
39
|
private readonly host;
|
|
40
40
|
/** The org row lock: re-checks `org.extensions.manage` under the lock. */
|
|
41
41
|
private readonly orgLock;
|
|
42
|
-
constructor(kdb: KernelDb, txHost: TransactionHost, host: Pick<ExtensionHost, "tools">,
|
|
42
|
+
constructor(kdb: KernelDb, txHost: TransactionHost, host: Pick<ExtensionHost, "tools" | "current">,
|
|
43
43
|
/** The org row lock: re-checks `org.extensions.manage` under the lock. */
|
|
44
44
|
orgLock: Pick<OrgLock, "lockAndAuthorize">);
|
|
45
45
|
private get db();
|
|
@@ -47,7 +47,8 @@ export declare class OrgToolSwitches {
|
|
|
47
47
|
private registered;
|
|
48
48
|
/**
|
|
49
49
|
* The tools of an extension the org sees: running here and visible under plugin scope, else 404
|
|
50
|
-
* `extension.not_found` (an invisible one is answered like an unknown one).
|
|
50
|
+
* `extension.not_found` (an invisible one is answered like an unknown one). An extension that
|
|
51
|
+
* runs but registers no tools (a channel, a model provider) answers an empty list, not 404.
|
|
51
52
|
*/
|
|
52
53
|
private toolsFor;
|
|
53
54
|
/** The stored switches of the org (all extensions, or one), `false` ones only matter. */
|
|
@@ -63,14 +63,14 @@ let OrgToolSwitches = class OrgToolSwitches {
|
|
|
63
63
|
}
|
|
64
64
|
/**
|
|
65
65
|
* The tools of an extension the org sees: running here and visible under plugin scope, else 404
|
|
66
|
-
* `extension.not_found` (an invisible one is answered like an unknown one).
|
|
66
|
+
* `extension.not_found` (an invisible one is answered like an unknown one). An extension that
|
|
67
|
+
* runs but registers no tools (a channel, a model provider) answers an empty list, not 404.
|
|
67
68
|
*/
|
|
68
69
|
async toolsFor(orgId, plugin) {
|
|
69
|
-
|
|
70
|
-
if (tools.length === 0 || !(await extensionVisibleTo(this.db, orgId, plugin))) {
|
|
70
|
+
if (!this.host.current(plugin) || !(await extensionVisibleTo(this.db, orgId, plugin))) {
|
|
71
71
|
throw new ApiError("extension.not_found", `Extension ${plugin} is not installed`);
|
|
72
72
|
}
|
|
73
|
-
return
|
|
73
|
+
return this.registered(plugin);
|
|
74
74
|
}
|
|
75
75
|
/** The stored switches of the org (all extensions, or one), `false` ones only matter. */
|
|
76
76
|
async offRows(orgId, plugin) {
|
package/dist/tools/policy.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { KernelSchemaDb } from "../db/kernel-schema.js";
|
|
2
2
|
import type { DecidePolicy } from "./pipeline.js";
|
|
3
3
|
import type { ResolvedTool, ToolPolicy } from "./registry.js";
|
|
4
|
-
export { R3_FIXED_ASK_TOOL_KEYS, R3_SHARED_AGENT_ONLY_TOOL_KEYS } from "./builtin-names.js";
|
|
5
4
|
/** 取更严的策略(`allow < ask < deny`)。 */
|
|
6
5
|
export declare function stricter(a: ToolPolicy, b: ToolPolicy | undefined): ToolPolicy;
|
|
7
6
|
export interface PolicyInput {
|
|
@@ -9,22 +8,21 @@ export interface PolicyInput {
|
|
|
9
8
|
connectorDefault: ToolPolicy;
|
|
10
9
|
/** agent 负责人的收紧(`definition.toolPolicies[key]`)。 */
|
|
11
10
|
agentOverride?: "ask" | "deny";
|
|
12
|
-
/**
|
|
11
|
+
/** `requiresUserInteraction`。 */
|
|
13
12
|
fixedAsk: boolean;
|
|
14
13
|
/** 已记住且 specHash 与当前一致的授权。 */
|
|
15
14
|
grant: "session" | "always" | null;
|
|
16
15
|
}
|
|
17
16
|
/**
|
|
18
|
-
* 策略判定(纯函数):取组织默认、agent
|
|
19
|
-
* 记住的授权只能把 `ask` 放行为 `allow`,不能越过 `deny`,对
|
|
17
|
+
* 策略判定(纯函数):取组织默认、agent 收紧、固定询问三者中最严者;
|
|
18
|
+
* 记住的授权只能把 `ask` 放行为 `allow`,不能越过 `deny`,对 `requiresUserInteraction` 的工具无效。
|
|
20
19
|
*/
|
|
21
20
|
export declare function decide(input: PolicyInput): ToolPolicy;
|
|
22
21
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* 除非 agent 当前版本的 `skills.writePolicy` 为 `ask`(`skillWritePolicy`);不知道可见性时按共享处理(更严)。
|
|
22
|
+
* Whether the tool is a fixed ask: its spec declares `requiresUserInteraction`, so its policy is
|
|
23
|
+
* at least `ask` and remembered grants never let it through.
|
|
26
24
|
*/
|
|
27
|
-
export declare function isFixedAsk(tool: ResolvedTool
|
|
25
|
+
export declare function isFixedAsk(tool: ResolvedTool): boolean;
|
|
28
26
|
/** Which level decided a connector tool's policy ({@link connectorPolicy}). */
|
|
29
27
|
export type ConnectorPolicySource = "org" | "member" | "agent";
|
|
30
28
|
/**
|
|
@@ -37,7 +35,7 @@ export type ConnectorPolicySource = "org" | "member" | "agent";
|
|
|
37
35
|
* 4. the member's own `allow` / `ask`;
|
|
38
36
|
* 5. the org's default (`connector_tools.default_policy`, the annotation default unless an org
|
|
39
37
|
* admin changed it: `readOnlyHint: true` allows, anything else asks).
|
|
40
|
-
* Fixed asks (
|
|
38
|
+
* Fixed asks (`requiresUserInteraction`), role escalation and grants apply after this.
|
|
41
39
|
*/
|
|
42
40
|
export declare function connectorPolicy(input: {
|
|
43
41
|
orgDefault: ToolPolicy;
|
package/dist/tools/policy.js
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import { sql } from "kysely";
|
|
2
2
|
import { roleAtLeast } from "../orgs/roles.js";
|
|
3
3
|
import { readOrgSettings } from "../orgs/settings.service.js";
|
|
4
|
-
import {
|
|
4
|
+
import { SANDBOX_ASK_TOOL_NAMES } from "./builtin-names.js";
|
|
5
5
|
import { personalAuth } from "./connector-account-policies.js";
|
|
6
6
|
import { normalizeStoredDefinitionIn } from "./legacy-data.js";
|
|
7
|
-
export { R3_FIXED_ASK_TOOL_KEYS, R3_SHARED_AGENT_ONLY_TOOL_KEYS } from "./builtin-names.js";
|
|
8
7
|
const RANK = { allow: 0, ask: 1, deny: 2 };
|
|
9
8
|
/** 取更严的策略(`allow < ask < deny`)。 */
|
|
10
9
|
export function stricter(a, b) {
|
|
11
10
|
return b !== undefined && RANK[b] > RANK[a] ? b : a;
|
|
12
11
|
}
|
|
13
12
|
/**
|
|
14
|
-
* 策略判定(纯函数):取组织默认、agent
|
|
15
|
-
* 记住的授权只能把 `ask` 放行为 `allow`,不能越过 `deny`,对
|
|
13
|
+
* 策略判定(纯函数):取组织默认、agent 收紧、固定询问三者中最严者;
|
|
14
|
+
* 记住的授权只能把 `ask` 放行为 `allow`,不能越过 `deny`,对 `requiresUserInteraction` 的工具无效。
|
|
16
15
|
*/
|
|
17
16
|
export function decide(input) {
|
|
18
17
|
let p = stricter(input.connectorDefault, input.agentOverride);
|
|
@@ -23,18 +22,11 @@ export function decide(input) {
|
|
|
23
22
|
return p;
|
|
24
23
|
}
|
|
25
24
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* 除非 agent 当前版本的 `skills.writePolicy` 为 `ask`(`skillWritePolicy`);不知道可见性时按共享处理(更严)。
|
|
25
|
+
* Whether the tool is a fixed ask: its spec declares `requiresUserInteraction`, so its policy is
|
|
26
|
+
* at least `ask` and remembered grants never let it through.
|
|
29
27
|
*/
|
|
30
|
-
export function isFixedAsk(tool
|
|
31
|
-
|
|
32
|
-
return true;
|
|
33
|
-
if (!R3_FIXED_ASK_TOOL_KEYS.has(tool.key))
|
|
34
|
-
return false;
|
|
35
|
-
const builtinOnly = tool.source.kind === "builtin" && R3_SHARED_AGENT_ONLY_TOOL_KEYS.has(tool.key);
|
|
36
|
-
// 私有 agent:缺省 / allow 不问(R4),负责人设为 ask(D10)时与共享 agent 一样固定询问
|
|
37
|
-
return !(builtinOnly && visibility === "private" && skillWritePolicy !== "ask");
|
|
28
|
+
export function isFixedAsk(tool) {
|
|
29
|
+
return tool.spec.annotations?.requiresUserInteraction === true;
|
|
38
30
|
}
|
|
39
31
|
const asSetting = (v) => v === "allow" || v === "ask" || v === "deny" ? v : undefined;
|
|
40
32
|
/** The stricter of the settings that are set (none set: undefined). */
|
|
@@ -69,7 +61,7 @@ const tighteningOf = (s) => s === "ask" || s === "deny" ? s : undefined;
|
|
|
69
61
|
* 4. the member's own `allow` / `ask`;
|
|
70
62
|
* 5. the org's default (`connector_tools.default_policy`, the annotation default unless an org
|
|
71
63
|
* admin changed it: `readOnlyHint: true` allows, anything else asks).
|
|
72
|
-
* Fixed asks (
|
|
64
|
+
* Fixed asks (`requiresUserInteraction`), role escalation and grants apply after this.
|
|
73
65
|
*/
|
|
74
66
|
export function connectorPolicy(input) {
|
|
75
67
|
if (input.orgDefault === "deny")
|
|
@@ -174,7 +166,7 @@ export function createDecidePolicy(db) {
|
|
|
174
166
|
.innerJoin("agent_versions", (j) => j
|
|
175
167
|
.onRef("agent_versions.agent_id", "=", "agents.id")
|
|
176
168
|
.onRef("agent_versions.version", "=", "agents.current_version"))
|
|
177
|
-
.select(["agent_versions.definition"
|
|
169
|
+
.select(["agent_versions.definition"])
|
|
178
170
|
.where("agents.id", "=", ctx.agentId)
|
|
179
171
|
.executeTakeFirst();
|
|
180
172
|
// stored raw: an rc version's keys read as current keys, so its deny keeps applying (§8.3)
|
|
@@ -222,12 +214,9 @@ export function createDecidePolicy(db) {
|
|
|
222
214
|
if (!roleAtLeast(m.role, tool.requiredRole))
|
|
223
215
|
escalateTo = tool.requiredRole;
|
|
224
216
|
}
|
|
225
|
-
// 可见性实时读(R5):共享 agent 的 SkillWrite 固定 ask,私有 agent 不问(见 R3_SHARED_AGENT_ONLY_TOOL_KEYS)
|
|
226
|
-
// 当前版本的 skills.writePolicy 同样实时读(R5):运行中改为 ask,下一次调用即生效;固定 ask 时授权不放行
|
|
227
|
-
const writePolicy = currentDef?.skills?.writePolicy;
|
|
228
217
|
// `remember: false` on a call that is not a plain allow (an org / platform operation, or a read
|
|
229
218
|
// an agent tightened to ask): every call asks, grants never apply. A read (`allow`) never asks.
|
|
230
|
-
const fixedAsk = isFixedAsk(tool
|
|
219
|
+
const fixedAsk = isFixedAsk(tool) ||
|
|
231
220
|
(call !== null && !call.remember && (call.policy !== "allow" || agentOverride !== undefined));
|
|
232
221
|
const input = {
|
|
233
222
|
connectorDefault,
|
|
@@ -253,7 +242,7 @@ export function createDecidePolicy(db) {
|
|
|
253
242
|
requestedFor: escalateTo === null ? ctx.accountId : null,
|
|
254
243
|
approverRole: escalateTo,
|
|
255
244
|
// the most specific rule that asked: role escalation, the agent's tightening, the connector,
|
|
256
|
-
// a fixed ask (
|
|
245
|
+
// a fixed ask (requiresUserInteraction), the org's sandboxToolPolicy, else the tool's own
|
|
257
246
|
// default
|
|
258
247
|
policy: escalateTo !== null
|
|
259
248
|
? "role"
|
|
@@ -22,6 +22,7 @@ import { UsageReportModule } from "../runtime/usage-report.js";
|
|
|
22
22
|
import { SandboxModule } from "../sandbox/sandbox.module.js";
|
|
23
23
|
import { SkillsModule } from "../skills/skills.module.js";
|
|
24
24
|
import { StorageModule } from "../storage/storage.module.js";
|
|
25
|
+
import { AdminConnectors } from "./admin-connectors.js";
|
|
25
26
|
import { ApprovalsService } from "./approvals.service.js";
|
|
26
27
|
import { Breaker } from "./breaker.js";
|
|
27
28
|
import { BuiltinTools } from "./builtins/builtin-tools.js";
|
|
@@ -87,6 +88,7 @@ ToolsModule = __decorate([
|
|
|
87
88
|
ConnectorContent,
|
|
88
89
|
ToolPipeline,
|
|
89
90
|
ConnectorsService,
|
|
91
|
+
AdminConnectors,
|
|
90
92
|
ConnectorAccountPolicies,
|
|
91
93
|
OAuthFlow,
|
|
92
94
|
ConversationToolInfo,
|
|
@@ -105,6 +107,7 @@ ToolsModule = __decorate([
|
|
|
105
107
|
ConnectorContent,
|
|
106
108
|
ToolPipeline,
|
|
107
109
|
ConnectorsService,
|
|
110
|
+
AdminConnectors,
|
|
108
111
|
ConnectorAccountPolicies,
|
|
109
112
|
OAuthFlow,
|
|
110
113
|
ConversationToolInfo,
|
package/package.json
CHANGED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
-- Platform-level audit events (org_id null), newest first: the admin overview's recent platform
|
|
2
|
+
-- operations and /admin/audit page by keyset on id (admin overview spec §4.4, §5.4). A plain
|
|
3
|
+
-- CREATE INDEX: the migrator runs each file in a transaction.
|
|
4
|
+
CREATE INDEX IF NOT EXISTS audit_events_platform_idx
|
|
5
|
+
ON audit_events (id DESC) WHERE org_id IS NULL;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
-- The admin overview's seven-day usage aggregate (admin overview spec §4.3, §5.4) reads runs and
|
|
2
|
+
-- embedding usage of every org by time: runs by created_at (only (conversation_id, created_at)
|
|
3
|
+
-- existed) and model_usage by occurred_at (only (org_id, occurred_at) and a partial index on the
|
|
4
|
+
-- unreported rows existed). Chat usage events already have conversation_events_usage_idx (0040).
|
|
5
|
+
-- A plain CREATE INDEX: the migrator runs each file in a transaction, so not CONCURRENTLY; it
|
|
6
|
+
-- locks writes to the table while it builds (pre-0.1.0: no large deployments).
|
|
7
|
+
CREATE INDEX IF NOT EXISTS runs_created_idx ON runs (created_at);
|
|
8
|
+
CREATE INDEX IF NOT EXISTS model_usage_time_idx ON model_usage (occurred_at);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
-- Skill authoring via the Platform tool: an agent's owner shares an agent skill with the org. The
|
|
2
|
+
-- shared skill is an org skill (scope 'org') that remembers the agent it came from
|
|
3
|
+
-- (origin_agent_id, cleared when that agent is deleted; the skill stays) and the account that
|
|
4
|
+
-- maintains it (maintainer_account_id).
|
|
5
|
+
ALTER TABLE skills
|
|
6
|
+
ADD COLUMN IF NOT EXISTS origin_agent_id text REFERENCES agents(id) ON DELETE SET NULL;
|
|
7
|
+
ALTER TABLE skills
|
|
8
|
+
ADD COLUMN IF NOT EXISTS maintainer_account_id text REFERENCES accounts(id);
|
|
9
|
+
-- The skills an agent shared, for its skill list and for sharing again.
|
|
10
|
+
CREATE INDEX IF NOT EXISTS skills_origin_agent_idx
|
|
11
|
+
ON skills (origin_agent_id)
|
|
12
|
+
WHERE origin_agent_id IS NOT NULL AND deleted_at IS NULL;
|
|
13
|
+
|
|
14
|
+
-- A request is either a share of an agent skill with the org or a new version of a shared skill.
|
|
15
|
+
ALTER TABLE skill_change_requests
|
|
16
|
+
ADD COLUMN IF NOT EXISTS kind text NOT NULL DEFAULT 'version'
|
|
17
|
+
CHECK (kind IN ('share', 'version'));
|
|
18
|
+
|
|
19
|
+
-- The R4 owner-approved change flow ends. The draft objects of the cancelled rows are left to the
|
|
20
|
+
-- org data cleanup.
|
|
21
|
+
-- capybara:allow-destructive R4 owner-approved changes are removed; pending ones cannot be decided any more
|
|
22
|
+
UPDATE skill_change_requests SET status = 'cancelled', decided_at = now() WHERE status = 'pending';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
-- A share request of an agent skill comes from the agent page or the Platform operation and has
|
|
2
|
+
-- no trial, so it records no conversation; a version proposal registered on the web has none
|
|
3
|
+
-- either. requested_in_conversation becomes optional.
|
|
4
|
+
ALTER TABLE skill_change_requests ALTER COLUMN requested_in_conversation DROP NOT NULL;
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import type { SkillManifest } from "../../db/kernel-schema.js";
|
|
2
|
-
import type { SkillChangesService } from "../../skills/changes.service.js";
|
|
3
|
-
import type { BuiltinTool } from "../registry.js";
|
|
4
|
-
/**
|
|
5
|
-
* 内置工具 `SkillWrite`(M5 T15,R4):agent 新建或更新它自己的技能(`scope = agent`)。
|
|
6
|
-
* - 输入 `{ name, description, files: [{ path, content }] }`,只收文本文件,整个技能 ≤ {@link SKILL_WRITE_MAX_BYTES};
|
|
7
|
-
* - the kernel generates SKILL.md ({@link buildSkillWrite}): its frontmatter is `name` / `description`
|
|
8
|
-
* plus the invocation keys (`disable-model-invocation`, `context`, ... phase D) of the frontmatter
|
|
9
|
-
* of the `SKILL.md` entry in `files`, whose other keys are dropped; its body is that entry's body
|
|
10
|
-
* (empty without the entry);
|
|
11
|
-
* - 每次调用写一个完整的新版本(上一版有、这次没给的文件不再属于新版本);
|
|
12
|
-
* - 私有 agent 直接生成新版本并立即生效;共享 agent 由触发对话的人先确认这次调用(R3 固定 ask,见 tools/policy.ts),
|
|
13
|
-
* 再生成变更申请等负责人批准,期间只有本对话试用新版本(见 skills/changes.service.ts);
|
|
14
|
-
* - 成功后立即在日志追加技能目录快照(`skills_catalog`,Ruling M17),同一运行的下一步就能 `Skill`。
|
|
15
|
-
*/
|
|
16
|
-
/** 一个技能(含合成的 SKILL.md)的总大小上限(UTF-8 字节)。 */
|
|
17
|
-
export declare const SKILL_WRITE_MAX_BYTES: number;
|
|
18
|
-
/** 一次最多的文件数(含 SKILL.md)。 */
|
|
19
|
-
export declare const SKILL_WRITE_MAX_FILES = 200;
|
|
20
|
-
/** `SkillWrite` 的输入(已按 inputSchema 校验)。 */
|
|
21
|
-
export interface SkillWriteInput {
|
|
22
|
-
name: string;
|
|
23
|
-
description: string;
|
|
24
|
-
files: {
|
|
25
|
-
path: string;
|
|
26
|
-
content: string;
|
|
27
|
-
}[];
|
|
28
|
-
}
|
|
29
|
-
/** 一个待写入的文件。 */
|
|
30
|
-
export interface BuiltSkillFile {
|
|
31
|
-
path: string;
|
|
32
|
-
data: Uint8Array;
|
|
33
|
-
size: number;
|
|
34
|
-
sha256: string;
|
|
35
|
-
}
|
|
36
|
-
/** {@link buildSkillWrite} 成功的结果。 */
|
|
37
|
-
export interface BuiltSkill {
|
|
38
|
-
name: string;
|
|
39
|
-
description: string;
|
|
40
|
-
files: BuiltSkillFile[];
|
|
41
|
-
manifest: SkillManifest;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* 由工具输入合成技能文件(纯函数):
|
|
45
|
-
* - SKILL.md = `---\n<yaml name/description>---\n\n<正文>\n`,正文为 `files` 里 `SKILL.md` 的内容去掉 frontmatter、
|
|
46
|
-
* 去掉首尾空行;合成结果再用 `parseSkillMd` 校验(名字规则、描述长度、不含 XML 标签);
|
|
47
|
-
* - 其余文件按 `validateSkillPackage` 校验路径(不能越出 `/skills/<name>/`、不能重复、大小写冲突等);
|
|
48
|
-
* - 只收文本:内容含 NUL 视为二进制,拒绝;全部文件(含 SKILL.md)的 UTF-8 字节数之和 ≤ {@link SKILL_WRITE_MAX_BYTES}。
|
|
49
|
-
* 返回合成结果或全部问题(英文,直接给模型)。
|
|
50
|
-
*/
|
|
51
|
-
export declare function buildSkillWrite(input: SkillWriteInput): BuiltSkill | {
|
|
52
|
-
errors: string[];
|
|
53
|
-
};
|
|
54
|
-
/** 依赖:技能变更服务。 */
|
|
55
|
-
export interface SkillWriteDeps {
|
|
56
|
-
changes: Pick<SkillChangesService, "write">;
|
|
57
|
-
}
|
|
58
|
-
/** 内置工具 `SkillWrite`(见文件头)。 */
|
|
59
|
-
export declare function skillWriteTool(deps: SkillWriteDeps): BuiltinTool;
|