@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
|
@@ -16,19 +16,22 @@ import { PLATFORM_OWNER } from "../catalog/ownership.js";
|
|
|
16
16
|
import { PlatformComponents } from "../catalog/platform-components.js";
|
|
17
17
|
import { assertItemInstallable } from "../catalog/request-rules.js";
|
|
18
18
|
import { AttachmentsService, SKILL_PACKAGE_CONTENT_TYPE, skillFilesPrefix, } from "../conversations/attachments.service.js";
|
|
19
|
+
import { EventLog } from "../conversations/event-log.js";
|
|
19
20
|
import { ApiError } from "../errors.js";
|
|
20
21
|
import { audit } from "../identity/audit.js";
|
|
21
22
|
import { assertCustomAllowed } from "../identity/settings.js";
|
|
22
23
|
import { notifySharedUpdate } from "../inbox/org-notices.js";
|
|
24
|
+
import { afterCommit } from "../infra/database/after-commit.js";
|
|
23
25
|
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
24
26
|
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
25
27
|
import { Transactional } from "../infra/database/transactional.decorator.js";
|
|
28
|
+
import { KERNEL_LOGGER } from "../infra/tokens.js";
|
|
26
29
|
import { OrgLock } from "../orgs/org-lock.js";
|
|
27
30
|
import { textBytesTokens } from "../runtime/context/tokens.js";
|
|
28
31
|
import { StorageService } from "../storage/storage.service.js";
|
|
29
|
-
import { buildSkillWrite } from "../tools/builtins/skill-write.js";
|
|
30
32
|
import { invocationOf, PINNED_SKILLS_LIMITS } from "./catalog.js";
|
|
31
|
-
import {
|
|
33
|
+
import { cancelRequestIn, } from "./conversation-catalog.js";
|
|
34
|
+
import { readSkillPackage, skillManifest, } from "./package.js";
|
|
32
35
|
import { PLATFORM_SOURCE, platformSkillsOn, platformSource, skillFileStore, skillVersionsById, usableSkills, } from "./usable.js";
|
|
33
36
|
/**
|
|
34
37
|
* The skills named in `skillNames` an org would see twice if catalog item `itemId` brought its
|
|
@@ -126,19 +129,6 @@ const PUT_CONCURRENCY = 4;
|
|
|
126
129
|
/** 详情里读取 SKILL.md 正文的上限。 */
|
|
127
130
|
export const SKILL_BODY_MAX_BYTES = 1024 * 1024;
|
|
128
131
|
const notFound = () => new ApiError("skill.not_found", "Skill not found");
|
|
129
|
-
const nameExists = (name) => new ApiError("skill.name_exists", `A skill named "${name}" already exists in this organization. Choose another name.`);
|
|
130
|
-
/** The checked files of a skill written as text (a built `SKILL.md`); `validation_failed` if not. */
|
|
131
|
-
function textSkillFiles(input) {
|
|
132
|
-
const built = buildSkillWrite({
|
|
133
|
-
name: input.name,
|
|
134
|
-
description: input.description,
|
|
135
|
-
files: [{ path: SKILL_ENTRY_FILE, content: input.body }],
|
|
136
|
-
});
|
|
137
|
-
if ("errors" in built) {
|
|
138
|
-
throw new ApiError("validation_failed", `Invalid skill: ${built.errors[0] ?? "unknown problem"}`, built.errors.map((message) => ({ path: "body", message })));
|
|
139
|
-
}
|
|
140
|
-
return checkBuiltSkillFiles(built.files);
|
|
141
|
-
}
|
|
142
132
|
/**
|
|
143
133
|
* 在调用方事务里核对 agent 定义引用的组织技能:每个 id 都必须是该组织未删除的 `scope=org` 技能
|
|
144
134
|
* (or, phase 2, a platform skill on in the org: skills/usable.ts),
|
|
@@ -348,16 +338,22 @@ let SkillsService = class SkillsService {
|
|
|
348
338
|
txHost;
|
|
349
339
|
orgLock;
|
|
350
340
|
platform;
|
|
341
|
+
eventLog;
|
|
342
|
+
log;
|
|
351
343
|
constructor(db, storage, attachments, txHost, orgLock,
|
|
352
344
|
/** The owner's new versions of a skill it promoted go to the platform row (ruling P3-4). */
|
|
353
|
-
platform) {
|
|
345
|
+
platform, eventLog, log) {
|
|
354
346
|
this.db = db;
|
|
355
347
|
this.storage = storage;
|
|
356
348
|
this.attachments = attachments;
|
|
357
349
|
this.txHost = txHost;
|
|
358
350
|
this.orgLock = orgLock;
|
|
359
351
|
this.platform = platform;
|
|
352
|
+
this.eventLog = eventLog;
|
|
353
|
+
this.log = log;
|
|
354
|
+
this.catalogDeps = { db, log, eventLog };
|
|
360
355
|
}
|
|
356
|
+
catalogDeps;
|
|
361
357
|
/**
|
|
362
358
|
* Writes a package's files where its version will live: for a new version of a skill the org
|
|
363
359
|
* promoted (ruling P3-3: a live org skill of the name linked without a pin to a platform skill
|
|
@@ -462,45 +458,6 @@ let SkillsService = class SkillsService {
|
|
|
462
458
|
...(owner !== undefined && { owner }),
|
|
463
459
|
});
|
|
464
460
|
}
|
|
465
|
-
/**
|
|
466
|
-
* The read-only checks of {@link createFromText}, for the `Platform` tool's precheck (before the
|
|
467
|
-
* card): custom skills allowed, a valid `SKILL.md`, and no live org skill of the name. Throws the
|
|
468
|
-
* same `ApiError` the create would; the create checks the name again under its lock.
|
|
469
|
-
*/
|
|
470
|
-
async checkCreateFromText(orgId, input) {
|
|
471
|
-
await assertCustomAllowed(this.db.db, "customSkills");
|
|
472
|
-
const pkg = textSkillFiles(input);
|
|
473
|
-
const existing = await this.db
|
|
474
|
-
.selectFrom("skills")
|
|
475
|
-
.select("id")
|
|
476
|
-
.where("org_id", "=", orgId)
|
|
477
|
-
.where("scope", "=", "org")
|
|
478
|
-
.where("name", "=", pkg.name)
|
|
479
|
-
.where("deleted_at", "is", null)
|
|
480
|
-
.executeTakeFirst();
|
|
481
|
-
if (existing)
|
|
482
|
-
throw nameExists(pkg.name);
|
|
483
|
-
}
|
|
484
|
-
/**
|
|
485
|
-
* Creates an org skill from text (spec §14, P3-24): `SKILL.md` is built from the name,
|
|
486
|
-
* description and body ({@link buildSkillWrite}, the description a YAML string) and checked like
|
|
487
|
-
* an uploaded package. The same policy and name rules as an upload, except that a live org skill
|
|
488
|
-
* of that name is `skill.name_exists` (409) instead of a new version.
|
|
489
|
-
*/
|
|
490
|
-
async createFromText(orgId, actorAccountId, input) {
|
|
491
|
-
this.storage.assertAvailable();
|
|
492
|
-
await assertCustomAllowed(this.db.db, "customSkills");
|
|
493
|
-
const pkg = textSkillFiles(input);
|
|
494
|
-
const prefix = skillFilesPrefix(randomUUID());
|
|
495
|
-
await this.putFiles(orgId, prefix, pkg.files);
|
|
496
|
-
return this.createVersionIn(orgId, actorAccountId, pkg, skillManifest(pkg), prefix, {
|
|
497
|
-
prefix,
|
|
498
|
-
failIfExists: true,
|
|
499
|
-
...(input.actorTokenId !== undefined && { actorTokenId: input.actorTokenId }),
|
|
500
|
-
...(input.auditDetail !== undefined && { auditDetail: input.auditDetail }),
|
|
501
|
-
...(input.shareable !== undefined && { shareable: input.shareable }),
|
|
502
|
-
});
|
|
503
|
-
}
|
|
504
461
|
/**
|
|
505
462
|
* 用一组已校验的技能文件创建组织技能或给同名技能新增版本(上传与平台目录安装共用):
|
|
506
463
|
* 1. 把文件写到 `kernel/<orgId>/<prefix>`(缺省 `skills/<新 id>/`);
|
|
@@ -514,6 +471,13 @@ let SkillsService = class SkillsService {
|
|
|
514
471
|
actorAccountId, pkg, opts = {}) {
|
|
515
472
|
this.storage.assertAvailable();
|
|
516
473
|
const prefix = opts.prefix ?? skillFilesPrefix(randomUUID());
|
|
474
|
+
if (opts.stored !== undefined) {
|
|
475
|
+
const { stored, ...rest } = opts;
|
|
476
|
+
return this.createVersionIn(orgId, actorAccountId, pkg, skillManifest(pkg), prefix, {
|
|
477
|
+
...rest,
|
|
478
|
+
...(stored.owner !== undefined && { owner: stored.owner }),
|
|
479
|
+
});
|
|
480
|
+
}
|
|
517
481
|
const owner = await this.putVersionFiles(orgId, pkg, prefix, opts.catalog !== undefined);
|
|
518
482
|
try {
|
|
519
483
|
return await this.createVersionIn(orgId, actorAccountId, pkg, skillManifest(pkg), prefix, {
|
|
@@ -528,6 +492,22 @@ let SkillsService = class SkillsService {
|
|
|
528
492
|
throw e;
|
|
529
493
|
}
|
|
530
494
|
}
|
|
495
|
+
/**
|
|
496
|
+
* For a new version whose files are already in `kernel/<orgId>/` (a proposed version's draft):
|
|
497
|
+
* when the org skill of that name is one the org promoted, writes the files as the platform
|
|
498
|
+
* row's next version (never inside a transaction) and returns it for
|
|
499
|
+
* `createVersionFromFiles({ stored: { owner } })`; else nothing is written.
|
|
500
|
+
*/
|
|
501
|
+
async prepareStoredVersion(orgId, pkg) {
|
|
502
|
+
const promoted = await promotedSkillNamed(this.db.db, orgId, pkg.name);
|
|
503
|
+
return promoted === undefined
|
|
504
|
+
? undefined
|
|
505
|
+
: this.platform.prepareOwnerVersion(promoted, pkg.files);
|
|
506
|
+
}
|
|
507
|
+
/** Deletes a platform version {@link prepareStoredVersion} wrote that was not used. */
|
|
508
|
+
async discardStoredVersion(owner) {
|
|
509
|
+
await this.platform.discardPrefix(owner.prefix);
|
|
510
|
+
}
|
|
531
511
|
/** Writes a skill package's files to `kernel/<orgId>/<prefix>` (a few at a time). */
|
|
532
512
|
async putFiles(orgId, prefix, files) {
|
|
533
513
|
const store = this.storage.kernel(orgId);
|
|
@@ -557,8 +537,6 @@ let SkillsService = class SkillsService {
|
|
|
557
537
|
.where("deleted_at", "is", null)
|
|
558
538
|
.forUpdate()
|
|
559
539
|
.executeTakeFirst();
|
|
560
|
-
if (existing && opts.failIfExists)
|
|
561
|
-
throw nameExists(pkg.name);
|
|
562
540
|
// The org's own skill it promoted (ruling P3-3): its new version goes to the platform row and
|
|
563
541
|
// reaches every org using it (ruling P3-4); the files were written there before this
|
|
564
542
|
// transaction, for the platform version current then
|
|
@@ -788,6 +766,38 @@ let SkillsService = class SkillsService {
|
|
|
788
766
|
const platform = (await platformSummaryQuery(this.db.db).where("p.id", "in", platformIds).execute()).map((r) => ({ ...platformSummary(r), linkedIds: linked.get(r.id) ?? [] }));
|
|
789
767
|
return [...own, ...platform].sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : a.id < b.id ? -1 : 1);
|
|
790
768
|
}
|
|
769
|
+
/**
|
|
770
|
+
* The agent's skills as the agent page lists them, by name: {@link listForAgent} (`shared:
|
|
771
|
+
* false`) plus `sharePending`, true while a share request of the skill waits for an org admin,
|
|
772
|
+
* and the org skills the agent shared (`origin_agent_id`; `scope: 'org'`, `shared: true`, same
|
|
773
|
+
* id as before sharing): the agent keeps them without selecting them.
|
|
774
|
+
*/
|
|
775
|
+
async listOwnForAgent(orgId, agentId) {
|
|
776
|
+
const [skills, shared] = await Promise.all([
|
|
777
|
+
this.listForAgent(orgId, agentId),
|
|
778
|
+
summaryQuery(this.db.db)
|
|
779
|
+
.where("s.org_id", "=", orgId)
|
|
780
|
+
.where("s.scope", "=", "org")
|
|
781
|
+
.where("s.origin_agent_id", "=", agentId)
|
|
782
|
+
.where("s.deleted_at", "is", null)
|
|
783
|
+
.execute(),
|
|
784
|
+
]);
|
|
785
|
+
const pending = skills.length === 0
|
|
786
|
+
? []
|
|
787
|
+
: await this.db
|
|
788
|
+
.selectFrom("skill_change_requests")
|
|
789
|
+
.select("skill_id")
|
|
790
|
+
.where("org_id", "=", orgId)
|
|
791
|
+
.where("kind", "=", "share")
|
|
792
|
+
.where("status", "=", "pending")
|
|
793
|
+
.where("skill_id", "in", skills.map((s) => s.id))
|
|
794
|
+
.execute();
|
|
795
|
+
const ids = new Set(pending.map((r) => r.skill_id));
|
|
796
|
+
return [
|
|
797
|
+
...skills.map((s) => ({ ...s, sharePending: ids.has(s.id), shared: false })),
|
|
798
|
+
...shared.map((r) => ({ ...summary(r), sharePending: false, shared: true })),
|
|
799
|
+
].sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : a.id < b.id ? -1 : 1));
|
|
800
|
+
}
|
|
791
801
|
/** 对该 agent 自动生效的技能(`scope=agent`、未删除),按名字排序。 */
|
|
792
802
|
async listForAgent(orgId, agentId) {
|
|
793
803
|
const rows = await summaryQuery(this.db.db)
|
|
@@ -924,7 +934,9 @@ let SkillsService = class SkillsService {
|
|
|
924
934
|
/**
|
|
925
935
|
* In the caller's transaction (`mandatory`: the caller holds the org row lock and checked
|
|
926
936
|
* `skills.manage`), soft-deletes an org-scope skill of the org: what {@link softDelete} writes
|
|
927
|
-
* (audit `skill.deleted`); missing or deleted -> `skill.not_found`.
|
|
937
|
+
* (audit `skill.deleted`); missing or deleted -> `skill.not_found`. Its pending version
|
|
938
|
+
* proposals are cancelled in the same transaction (trials reverted; drafts deleted and events
|
|
939
|
+
* published after the commit). The owner delete of a
|
|
928
940
|
* promoted skill (`OwnedItems.deleteSkill`) calls it after its platform row was dealt with.
|
|
929
941
|
*/
|
|
930
942
|
async deleteOrgSkillIn(orgId, skillId, actorAccountId, actorTokenId, auditDetail) {
|
|
@@ -939,6 +951,26 @@ let SkillsService = class SkillsService {
|
|
|
939
951
|
.executeTakeFirst();
|
|
940
952
|
if (!r)
|
|
941
953
|
throw notFound();
|
|
954
|
+
// its pending version proposals go with it: cancelled, their trials reverted; after the
|
|
955
|
+
// commit the events are published and the drafts deleted (a share request has no draft)
|
|
956
|
+
const pending = await this.db
|
|
957
|
+
.selectFrom("skill_change_requests")
|
|
958
|
+
.selectAll()
|
|
959
|
+
.where("org_id", "=", orgId)
|
|
960
|
+
.where("skill_id", "=", skillId)
|
|
961
|
+
.where("kind", "=", "version")
|
|
962
|
+
.where("status", "=", "pending")
|
|
963
|
+
.orderBy("created_at")
|
|
964
|
+
.forUpdate()
|
|
965
|
+
.execute();
|
|
966
|
+
const cancelled = { prefixes: [], seqs: [] };
|
|
967
|
+
for (const p of pending) {
|
|
968
|
+
await cancelRequestIn(this.catalogDeps, p, cancelled, {
|
|
969
|
+
actorAccountId,
|
|
970
|
+
...(actorTokenId !== undefined && { actorTokenId }),
|
|
971
|
+
reason: "skill_deleted",
|
|
972
|
+
});
|
|
973
|
+
}
|
|
942
974
|
await audit(this.db.db, {
|
|
943
975
|
actorAccountId,
|
|
944
976
|
...(actorTokenId !== undefined && { actorTokenId }),
|
|
@@ -947,6 +979,20 @@ let SkillsService = class SkillsService {
|
|
|
947
979
|
target: skillId,
|
|
948
980
|
detail: { name: r.name, ...auditDetail },
|
|
949
981
|
});
|
|
982
|
+
if (pending.length > 0) {
|
|
983
|
+
afterCommit(async () => {
|
|
984
|
+
for (const [conv, seq] of cancelled.seqs)
|
|
985
|
+
await this.eventLog.notify(conv, seq);
|
|
986
|
+
for (const prefix of cancelled.prefixes) {
|
|
987
|
+
try {
|
|
988
|
+
await this.storage.kernel(orgId).deletePrefix(prefix);
|
|
989
|
+
}
|
|
990
|
+
catch (err) {
|
|
991
|
+
this.log.warn("skill draft cleanup failed", { orgId, prefix, err });
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
});
|
|
995
|
+
}
|
|
950
996
|
}
|
|
951
997
|
};
|
|
952
998
|
__decorate([
|
|
@@ -974,7 +1020,9 @@ SkillsService = __decorate([
|
|
|
974
1020
|
__param(2, Inject(AttachmentsService)),
|
|
975
1021
|
__param(3, Inject(TransactionHost)),
|
|
976
1022
|
__param(4, Inject(OrgLock)),
|
|
977
|
-
__param(5, Inject(PlatformComponents))
|
|
1023
|
+
__param(5, Inject(PlatformComponents)),
|
|
1024
|
+
__param(6, Inject(EventLog)),
|
|
1025
|
+
__param(7, Inject(KERNEL_LOGGER))
|
|
978
1026
|
], SkillsService);
|
|
979
1027
|
export { SkillsService };
|
|
980
1028
|
/**
|
package/dist/skills/usable.d.ts
CHANGED
|
@@ -59,9 +59,10 @@ export declare function pinnedSkillLinksServed(db: KernelSchemaDb, orgId: string
|
|
|
59
59
|
*/
|
|
60
60
|
export declare function skillVersionsById(db: KernelSchemaDb, orgId: string, ids: readonly string[], log?: Pick<Logger, "warn">): Promise<Map<string, SkillVersionRow>>;
|
|
61
61
|
/**
|
|
62
|
-
* The skills an agent selects, sorted by id: its own skills (`scope = 'agent'`)
|
|
63
|
-
* `
|
|
64
|
-
*
|
|
62
|
+
* The skills an agent selects, sorted by id: its own skills (`scope = 'agent'`), the org skills
|
|
63
|
+
* it shared (`origin_agent_id`: the agent keeps a shared skill without a definition change) and
|
|
64
|
+
* the ids of `orgSkills` that resolve ({@link skillVersionsById}: org skills, linked copies,
|
|
65
|
+
* platform skills on in the org). Not deduplicated by name.
|
|
65
66
|
*/
|
|
66
67
|
export declare function selectedSkills(db: KernelSchemaDb, a: {
|
|
67
68
|
orgId: string;
|
package/dist/skills/usable.js
CHANGED
|
@@ -285,9 +285,10 @@ async function ownedPlatformIds(db, orgId, platformIds) {
|
|
|
285
285
|
return new Set(rows.map((r) => r.id));
|
|
286
286
|
}
|
|
287
287
|
/**
|
|
288
|
-
* The skills an agent selects, sorted by id: its own skills (`scope = 'agent'`)
|
|
289
|
-
* `
|
|
290
|
-
*
|
|
288
|
+
* The skills an agent selects, sorted by id: its own skills (`scope = 'agent'`), the org skills
|
|
289
|
+
* it shared (`origin_agent_id`: the agent keeps a shared skill without a definition change) and
|
|
290
|
+
* the ids of `orgSkills` that resolve ({@link skillVersionsById}: org skills, linked copies,
|
|
291
|
+
* platform skills on in the org). Not deduplicated by name.
|
|
291
292
|
*/
|
|
292
293
|
export async function selectedSkills(db, a, log) {
|
|
293
294
|
const agentOwn = await db
|
|
@@ -298,7 +299,15 @@ export async function selectedSkills(db, a, log) {
|
|
|
298
299
|
.where("agent_id", "=", a.agentId)
|
|
299
300
|
.where("deleted_at", "is", null)
|
|
300
301
|
.execute();
|
|
301
|
-
const
|
|
302
|
+
const shared = await db
|
|
303
|
+
.selectFrom("skills")
|
|
304
|
+
.select("id")
|
|
305
|
+
.where("org_id", "=", a.orgId)
|
|
306
|
+
.where("scope", "=", "org")
|
|
307
|
+
.where("origin_agent_id", "=", a.agentId)
|
|
308
|
+
.where("deleted_at", "is", null)
|
|
309
|
+
.execute();
|
|
310
|
+
const orgSkills = new Set([...a.orgSkills, ...shared.map((r) => r.id)]);
|
|
302
311
|
const byId = await skillVersionsById(db, a.orgId, [...agentOwn.map((r) => r.id), ...orgSkills], log);
|
|
303
312
|
return [...byId.values()]
|
|
304
313
|
.filter((r) => (r.scope === "agent" ? r.agentId === a.agentId : orgSkills.has(r.id)))
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
2
|
+
import type { ToolPolicy } from "./registry.js";
|
|
3
|
+
/** One connector in the super admin's cross-org list (no endpoint, auth or credential). */
|
|
4
|
+
export interface AdminConnectorRow {
|
|
5
|
+
id: string;
|
|
6
|
+
orgId: string;
|
|
7
|
+
orgName: string;
|
|
8
|
+
name: string;
|
|
9
|
+
slug: string;
|
|
10
|
+
/** The connector extension (e.g. `mcp`, `openapi`). */
|
|
11
|
+
connector: string;
|
|
12
|
+
status: "active" | "disabled";
|
|
13
|
+
platformTemplateId: string | null;
|
|
14
|
+
/** The platform connector template's name (its template id in the plugin), when it exists. */
|
|
15
|
+
templateName: string | null;
|
|
16
|
+
catalogItemId: string | null;
|
|
17
|
+
/** Counts every tool row of the connector, pending and missing ones included. */
|
|
18
|
+
toolCount: number;
|
|
19
|
+
toolsSyncedAt: Date | null;
|
|
20
|
+
createdBy: string;
|
|
21
|
+
createdByName: string;
|
|
22
|
+
createdAt: Date;
|
|
23
|
+
updatedAt: Date;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The super admin's read-only connector detail. Never a credential, token or secret value, and
|
|
27
|
+
* not whether any member has a credential: `auth` is the type and ownership only.
|
|
28
|
+
*/
|
|
29
|
+
export interface AdminConnectorDetail extends AdminConnectorRow {
|
|
30
|
+
/** Through {@link endpointView}: large text fields as their size and sha256 only. */
|
|
31
|
+
endpoint: unknown;
|
|
32
|
+
auth: {
|
|
33
|
+
type: string;
|
|
34
|
+
ownership: "org" | "personal" | null;
|
|
35
|
+
};
|
|
36
|
+
tools: {
|
|
37
|
+
name: string;
|
|
38
|
+
title: string | null;
|
|
39
|
+
status: "enabled" | "disabled" | "pending_review";
|
|
40
|
+
defaultPolicy: ToolPolicy;
|
|
41
|
+
}[];
|
|
42
|
+
}
|
|
43
|
+
export interface AdminConnectorQuery {
|
|
44
|
+
orgId?: string | undefined;
|
|
45
|
+
status?: "active" | "disabled" | undefined;
|
|
46
|
+
/** A case-insensitive substring of the connector name. */
|
|
47
|
+
q?: string | undefined;
|
|
48
|
+
/** The last id of the previous page. */
|
|
49
|
+
after?: string | undefined;
|
|
50
|
+
limit: number;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Cross-org reads of connectors for the super admin (spec
|
|
54
|
+
* 2026-11-10-admin-agents-connectors-design.md §3.4, §3.5). Only live connectors of live orgs;
|
|
55
|
+
* the caller checks the super admin.
|
|
56
|
+
*/
|
|
57
|
+
export declare class AdminConnectors {
|
|
58
|
+
private readonly kdb;
|
|
59
|
+
constructor(kdb: KernelDb);
|
|
60
|
+
private get db();
|
|
61
|
+
private base;
|
|
62
|
+
/** Live connectors of every live org by id, filtered; `next` is the last id when more follow. */
|
|
63
|
+
list(q: AdminConnectorQuery): Promise<{
|
|
64
|
+
connectors: AdminConnectorRow[];
|
|
65
|
+
next: string | null;
|
|
66
|
+
}>;
|
|
67
|
+
/** One live connector of a live org; else `connector.not_found`. */
|
|
68
|
+
get(connectorId: string): Promise<AdminConnectorDetail>;
|
|
69
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
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 { sql } from "kysely";
|
|
12
|
+
import { ApiError } from "../errors.js";
|
|
13
|
+
import { KernelDb } from "../infra/database/kernel-db.js";
|
|
14
|
+
import { endpointView } from "./endpoint.js";
|
|
15
|
+
const notFound = () => new ApiError("connector.not_found", "Connector not found");
|
|
16
|
+
/**
|
|
17
|
+
* Cross-org reads of connectors for the super admin (spec
|
|
18
|
+
* 2026-11-10-admin-agents-connectors-design.md §3.4, §3.5). Only live connectors of live orgs;
|
|
19
|
+
* the caller checks the super admin.
|
|
20
|
+
*/
|
|
21
|
+
let AdminConnectors = class AdminConnectors {
|
|
22
|
+
kdb;
|
|
23
|
+
constructor(kdb) {
|
|
24
|
+
this.kdb = kdb;
|
|
25
|
+
}
|
|
26
|
+
get db() {
|
|
27
|
+
return this.kdb.db;
|
|
28
|
+
}
|
|
29
|
+
base() {
|
|
30
|
+
return this.db
|
|
31
|
+
.selectFrom("connectors as c")
|
|
32
|
+
.innerJoin("orgs as o", "o.id", "c.org_id")
|
|
33
|
+
.innerJoin("accounts as a", "a.id", "c.created_by")
|
|
34
|
+
.leftJoin("platform_connector_templates as pt", "pt.id", "c.platform_template_id")
|
|
35
|
+
.select([
|
|
36
|
+
"c.id",
|
|
37
|
+
"c.org_id",
|
|
38
|
+
"o.name as org_name",
|
|
39
|
+
"c.name",
|
|
40
|
+
"c.slug",
|
|
41
|
+
"c.connector",
|
|
42
|
+
"c.status",
|
|
43
|
+
"c.platform_template_id",
|
|
44
|
+
"pt.template_id as template_name",
|
|
45
|
+
"c.catalog_item_id",
|
|
46
|
+
"c.tools_synced_at",
|
|
47
|
+
"c.created_by",
|
|
48
|
+
"a.display_name as created_by_name",
|
|
49
|
+
"c.created_at",
|
|
50
|
+
"c.updated_at",
|
|
51
|
+
sql `(SELECT count(*)::int FROM capybara.connector_tools t
|
|
52
|
+
WHERE t.connector_id = c.id)`.as("tool_count"),
|
|
53
|
+
])
|
|
54
|
+
.where("c.deleted_at", "is", null)
|
|
55
|
+
.where("o.deleted_at", "is", null);
|
|
56
|
+
}
|
|
57
|
+
/** Live connectors of every live org by id, filtered; `next` is the last id when more follow. */
|
|
58
|
+
async list(q) {
|
|
59
|
+
let query = this.base();
|
|
60
|
+
if (q.orgId !== undefined)
|
|
61
|
+
query = query.where("c.org_id", "=", q.orgId);
|
|
62
|
+
if (q.status !== undefined)
|
|
63
|
+
query = query.where("c.status", "=", q.status);
|
|
64
|
+
if (q.q !== undefined && q.q !== "") {
|
|
65
|
+
const like = `%${q.q.replace(/[\\%_]/g, (ch) => `\\${ch}`)}%`;
|
|
66
|
+
query = query.where(sql `c.name ILIKE ${like} ESCAPE '\\'`);
|
|
67
|
+
}
|
|
68
|
+
if (q.after !== undefined)
|
|
69
|
+
query = query.where("c.id", ">", q.after);
|
|
70
|
+
const rows = await query
|
|
71
|
+
.orderBy("c.id")
|
|
72
|
+
.limit(q.limit + 1)
|
|
73
|
+
.execute();
|
|
74
|
+
const page = rows.slice(0, q.limit).map(toRow);
|
|
75
|
+
return {
|
|
76
|
+
connectors: page,
|
|
77
|
+
next: rows.length > q.limit ? (page[page.length - 1]?.id ?? null) : null,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/** One live connector of a live org; else `connector.not_found`. */
|
|
81
|
+
async get(connectorId) {
|
|
82
|
+
const r = await this.base()
|
|
83
|
+
.select(["c.endpoint", "c.auth"])
|
|
84
|
+
.where("c.id", "=", connectorId)
|
|
85
|
+
.executeTakeFirst();
|
|
86
|
+
if (!r)
|
|
87
|
+
throw notFound();
|
|
88
|
+
const tools = await this.db
|
|
89
|
+
.selectFrom("connector_tools")
|
|
90
|
+
.select(["name", "spec", "status", "default_policy"])
|
|
91
|
+
.where("connector_id", "=", connectorId)
|
|
92
|
+
.orderBy("name")
|
|
93
|
+
.execute();
|
|
94
|
+
const auth = r.auth;
|
|
95
|
+
return {
|
|
96
|
+
...toRow(r),
|
|
97
|
+
endpoint: endpointView(r.endpoint),
|
|
98
|
+
auth: { type: auth.type, ownership: auth.type === "none" ? null : auth.ownership },
|
|
99
|
+
tools: tools.map((t) => {
|
|
100
|
+
const title = t.spec.title;
|
|
101
|
+
return {
|
|
102
|
+
name: t.name,
|
|
103
|
+
title: typeof title === "string" ? title : null,
|
|
104
|
+
status: t.status,
|
|
105
|
+
defaultPolicy: t.default_policy,
|
|
106
|
+
};
|
|
107
|
+
}),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
AdminConnectors = __decorate([
|
|
112
|
+
Injectable(),
|
|
113
|
+
__param(0, Inject(KernelDb))
|
|
114
|
+
], AdminConnectors);
|
|
115
|
+
export { AdminConnectors };
|
|
116
|
+
function toRow(r) {
|
|
117
|
+
return {
|
|
118
|
+
id: r.id,
|
|
119
|
+
orgId: r.org_id,
|
|
120
|
+
orgName: r.org_name,
|
|
121
|
+
name: r.name,
|
|
122
|
+
slug: r.slug,
|
|
123
|
+
connector: r.connector,
|
|
124
|
+
status: r.status,
|
|
125
|
+
platformTemplateId: r.platform_template_id ?? null,
|
|
126
|
+
templateName: r.template_name ?? null,
|
|
127
|
+
catalogItemId: r.catalog_item_id ?? null,
|
|
128
|
+
toolCount: r.tool_count,
|
|
129
|
+
toolsSyncedAt: r.tools_synced_at,
|
|
130
|
+
createdBy: r.created_by,
|
|
131
|
+
createdByName: r.created_by_name,
|
|
132
|
+
createdAt: r.created_at,
|
|
133
|
+
updatedAt: r.updated_at,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
@@ -15,7 +15,6 @@ export declare const BUILTIN: {
|
|
|
15
15
|
readonly Grep: "Grep";
|
|
16
16
|
readonly Deliver: "Deliver";
|
|
17
17
|
readonly Skill: "Skill";
|
|
18
|
-
readonly SkillWrite: "SkillWrite";
|
|
19
18
|
readonly AskUserQuestion: "AskUserQuestion";
|
|
20
19
|
readonly ReadToolOutput: "ReadToolOutput";
|
|
21
20
|
readonly ToolSearch: "ToolSearch";
|
|
@@ -58,6 +57,13 @@ export declare const SANDBOX_ASK_TOOL_NAMES: ReadonlySet<string>;
|
|
|
58
57
|
* `CurrentTime` reads the clock (the run context carries only the date).
|
|
59
58
|
*/
|
|
60
59
|
export declare const BUILTIN_TOOL_NAMES: readonly BuiltinName[];
|
|
60
|
+
/**
|
|
61
|
+
* Is `key` a builtin-shaped key (a bare name, no `mcp__` / `plugin__` prefix) that names no
|
|
62
|
+
* builtin the kernel has now, e.g. the removed `SkillWrite`? Saving an agent or an org template
|
|
63
|
+
* drops such a `toolPolicies` key instead of refusing the save: a stored definition may still
|
|
64
|
+
* carry it, and the web sends the whole definition back.
|
|
65
|
+
*/
|
|
66
|
+
export declare function isRemovedBuiltinKey(key: string): boolean;
|
|
61
67
|
/** The builtin that loads a skill (added by the registry when the log has a skills catalog). */
|
|
62
68
|
export declare const SKILL_LOAD: "Skill";
|
|
63
69
|
/** The builtin that searches the tool catalog (added by the registry by org setting and threshold). */
|
|
@@ -74,23 +80,12 @@ export declare const SUBAGENT_HANDBACK: "SubagentHandback";
|
|
|
74
80
|
* `SubagentHandback` to a sub-agent. A definition's ref to either is ignored.
|
|
75
81
|
*/
|
|
76
82
|
export declare const SUBAGENT_MESSAGE_TOOLS: ReadonlySet<string>;
|
|
77
|
-
/**
|
|
78
|
-
* Tool keys on the spec 3.6 R3 fixed list ("allowed is not confirmed"): their policy is at least
|
|
79
|
-
* `ask` and remembered grants never let them through. `SkillWrite` changes shared skills.
|
|
80
|
-
* Connector and extension tools express the same rule with `annotations.requiresUserInteraction`.
|
|
81
|
-
*/
|
|
82
|
-
export declare const R3_FIXED_ASK_TOOL_KEYS: ReadonlySet<string>;
|
|
83
|
-
/**
|
|
84
|
-
* R3 keys that apply only to shared agents: a private agent's skills are not shared, so its
|
|
85
|
-
* `SkillWrite` takes effect without asking (R4).
|
|
86
|
-
*/
|
|
87
|
-
export declare const R3_SHARED_AGENT_ONLY_TOOL_KEYS: ReadonlySet<string>;
|
|
88
83
|
/**
|
|
89
84
|
* Tools a sub-agent never gets (sub-agents spec §5.3, §5.5): `AskUserQuestion` (the person does
|
|
90
|
-
* not see the child)
|
|
85
|
+
* not see the child) and `Deliver` (delivering files is the parent's job). `Agent`
|
|
91
86
|
* is removed only from a child at `subagents.maxDepth` (agent map spec §4.1, `effectiveDefinition`).
|
|
92
87
|
*/
|
|
93
|
-
export declare const CHILD_REMOVED_TOOLS: readonly ["AskUserQuestion", "Deliver"
|
|
88
|
+
export declare const CHILD_REMOVED_TOOLS: readonly ["AskUserQuestion", "Deliver"];
|
|
94
89
|
/**
|
|
95
90
|
* The builtins every agent has unless it turns them off (tools default-on spec §4), in this
|
|
96
91
|
* order: {@link BUILTIN_TOOL_NAMES} without the ones the registry manages by rule (`ToolSearch`,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { parseToolKey } from "@capybara-hq/plugin-sdk";
|
|
1
2
|
/**
|
|
2
3
|
* The names (model-visible keys) of the kernel's builtin tools, following Claude Code (tool naming
|
|
3
4
|
* spec §4.1). Plain constants: `BuiltinTools`, the tool factories, the registry, policy and the
|
|
@@ -14,7 +15,6 @@ export const BUILTIN = {
|
|
|
14
15
|
Grep: "Grep",
|
|
15
16
|
Deliver: "Deliver",
|
|
16
17
|
Skill: "Skill",
|
|
17
|
-
SkillWrite: "SkillWrite",
|
|
18
18
|
AskUserQuestion: "AskUserQuestion",
|
|
19
19
|
ReadToolOutput: "ReadToolOutput",
|
|
20
20
|
ToolSearch: "ToolSearch",
|
|
@@ -75,7 +75,6 @@ export const BUILTIN_TOOL_NAMES = [
|
|
|
75
75
|
BUILTIN.ReadToolOutput,
|
|
76
76
|
BUILTIN.ToolSearch,
|
|
77
77
|
BUILTIN.Skill,
|
|
78
|
-
BUILTIN.SkillWrite,
|
|
79
78
|
...SANDBOX_TOOL_NAMES,
|
|
80
79
|
BUILTIN.Agent,
|
|
81
80
|
BUILTIN.SendMessage,
|
|
@@ -84,6 +83,16 @@ export const BUILTIN_TOOL_NAMES = [
|
|
|
84
83
|
BUILTIN.Platform,
|
|
85
84
|
BUILTIN.CurrentTime,
|
|
86
85
|
];
|
|
86
|
+
const BUILTIN_NAME_SET = new Set(Object.values(BUILTIN));
|
|
87
|
+
/**
|
|
88
|
+
* Is `key` a builtin-shaped key (a bare name, no `mcp__` / `plugin__` prefix) that names no
|
|
89
|
+
* builtin the kernel has now, e.g. the removed `SkillWrite`? Saving an agent or an org template
|
|
90
|
+
* drops such a `toolPolicies` key instead of refusing the save: a stored definition may still
|
|
91
|
+
* carry it, and the web sends the whole definition back.
|
|
92
|
+
*/
|
|
93
|
+
export function isRemovedBuiltinKey(key) {
|
|
94
|
+
return parseToolKey(key)?.kind === "builtin" && !BUILTIN_NAME_SET.has(key);
|
|
95
|
+
}
|
|
87
96
|
/** The builtin that loads a skill (added by the registry when the log has a skills catalog). */
|
|
88
97
|
export const SKILL_LOAD = BUILTIN.Skill;
|
|
89
98
|
/** The builtin that searches the tool catalog (added by the registry by org setting and threshold). */
|
|
@@ -103,29 +112,12 @@ export const SUBAGENT_MESSAGE_TOOLS = new Set([
|
|
|
103
112
|
SEND_MESSAGE,
|
|
104
113
|
SUBAGENT_HANDBACK,
|
|
105
114
|
]);
|
|
106
|
-
/**
|
|
107
|
-
* Tool keys on the spec 3.6 R3 fixed list ("allowed is not confirmed"): their policy is at least
|
|
108
|
-
* `ask` and remembered grants never let them through. `SkillWrite` changes shared skills.
|
|
109
|
-
* Connector and extension tools express the same rule with `annotations.requiresUserInteraction`.
|
|
110
|
-
*/
|
|
111
|
-
export const R3_FIXED_ASK_TOOL_KEYS = new Set([BUILTIN.SkillWrite]);
|
|
112
|
-
/**
|
|
113
|
-
* R3 keys that apply only to shared agents: a private agent's skills are not shared, so its
|
|
114
|
-
* `SkillWrite` takes effect without asking (R4).
|
|
115
|
-
*/
|
|
116
|
-
export const R3_SHARED_AGENT_ONLY_TOOL_KEYS = new Set([
|
|
117
|
-
BUILTIN.SkillWrite,
|
|
118
|
-
]);
|
|
119
115
|
/**
|
|
120
116
|
* Tools a sub-agent never gets (sub-agents spec §5.3, §5.5): `AskUserQuestion` (the person does
|
|
121
|
-
* not see the child)
|
|
117
|
+
* not see the child) and `Deliver` (delivering files is the parent's job). `Agent`
|
|
122
118
|
* is removed only from a child at `subagents.maxDepth` (agent map spec §4.1, `effectiveDefinition`).
|
|
123
119
|
*/
|
|
124
|
-
export const CHILD_REMOVED_TOOLS = [
|
|
125
|
-
BUILTIN.AskUserQuestion,
|
|
126
|
-
BUILTIN.Deliver,
|
|
127
|
-
BUILTIN.SkillWrite,
|
|
128
|
-
];
|
|
120
|
+
export const CHILD_REMOVED_TOOLS = [BUILTIN.AskUserQuestion, BUILTIN.Deliver];
|
|
129
121
|
/**
|
|
130
122
|
* The builtins every agent has unless it turns them off (tools default-on spec §4), in this
|
|
131
123
|
* order: {@link BUILTIN_TOOL_NAMES} without the ones the registry manages by rule (`ToolSearch`,
|
|
@@ -150,7 +142,6 @@ export const BUILTIN_TOOL_KINDS = {
|
|
|
150
142
|
[BUILTIN.TaskStop]: "command",
|
|
151
143
|
[BUILTIN.ToolSearch]: "meta",
|
|
152
144
|
[BUILTIN.Skill]: "meta",
|
|
153
|
-
[BUILTIN.SkillWrite]: "meta",
|
|
154
145
|
[BUILTIN.ReadToolOutput]: "meta",
|
|
155
146
|
[BUILTIN.AskUserQuestion]: "meta",
|
|
156
147
|
[BUILTIN.SendMessage]: "meta",
|
|
@@ -16,7 +16,6 @@ import type { HookRunner } from "../../runtime/hook-calls.js";
|
|
|
16
16
|
import { StepLog } from "../../runtime/step-log.js";
|
|
17
17
|
import { UsageReporter } from "../../runtime/usage-report.js";
|
|
18
18
|
import { SandboxService } from "../../sandbox/sandbox.service.js";
|
|
19
|
-
import { SkillChangesService } from "../../skills/changes.service.js";
|
|
20
19
|
import { StorageService } from "../../storage/storage.service.js";
|
|
21
20
|
import { ToolOutputs } from "../outputs.js";
|
|
22
21
|
import type { BuiltinTool } from "../registry.js";
|
|
@@ -25,11 +24,11 @@ import { WebPages } from "./web/index.js";
|
|
|
25
24
|
* The kernel's builtin tools, built once from the injected services (their specs: names,
|
|
26
25
|
* descriptions and schemas, are the factories' own and unchanged). `ToolSearch` and `Skill`
|
|
27
26
|
* are added to a run by the registry (`forAgent`: organization setting and threshold, a skills
|
|
28
|
-
* catalog snapshot), not by agent definitions
|
|
27
|
+
* catalog snapshot), not by agent definitions.
|
|
29
28
|
*/
|
|
30
29
|
export declare class BuiltinTools {
|
|
31
30
|
private readonly tools;
|
|
32
|
-
constructor(db: KernelDb, config: KernelConfigService, outputs: ToolOutputs, storage: StorageService,
|
|
31
|
+
constructor(db: KernelDb, config: KernelConfigService, outputs: ToolOutputs, storage: StorageService, attachments: AttachmentsService, eventLog: EventLog, sandbox: SandboxService, devices: ConversationDevices, points: ExtensionPointDefaults, webPages: WebPages,
|
|
33
32
|
/** The WebFetch extraction call: the `web_fetch` purpose, its hooks, usage and denials. */
|
|
34
33
|
purposes: ModelPurposesService, host: {
|
|
35
34
|
readonly hooks?: HookRunner;
|