@capybara-hq/kernel 0.1.0-rc.21 → 0.1.0-rc.23
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 +3 -3
- package/dist/admin/admin.controller.js +6 -2
- package/dist/admin/admin.schemas.d.ts +13 -0
- package/dist/agents/admin-agents.d.ts +16 -3
- package/dist/agents/admin-agents.js +65 -7
- package/dist/agents/agents.schemas.d.ts +24 -6
- package/dist/agents/agents.service.d.ts +4 -3
- package/dist/agents/agents.service.js +39 -26
- package/dist/agents/definition.d.ts +44 -6
- package/dist/agents/definition.js +86 -18
- package/dist/agents/from-template.d.ts +6 -3
- package/dist/agents/from-template.js +57 -44
- package/dist/agents/org-templates.js +97 -41
- package/dist/agents/templates.d.ts +6 -0
- package/dist/agents/templates.js +15 -1
- package/dist/background/launch.d.ts +43 -5
- package/dist/background/launch.js +88 -8
- package/dist/background/session.d.ts +14 -2
- package/dist/background/session.js +26 -4
- package/dist/background/status.d.ts +1 -1
- package/dist/background/status.js +3 -3
- package/dist/background/stop.d.ts +0 -2
- package/dist/background/stop.js +1 -21
- package/dist/catalog/admin-catalog.controller.d.ts +2 -4
- package/dist/catalog/admin-catalog.controller.js +2 -6
- package/dist/catalog/catalog-content.d.ts +5 -0
- package/dist/catalog/catalog-content.js +1 -0
- package/dist/catalog/catalog.module.js +3 -0
- package/dist/catalog/claude/report.d.ts +9 -2
- package/dist/catalog/claude/report.js +1 -0
- package/dist/catalog/claude/translate.js +1 -1
- package/dist/catalog/component-promotion.js +1 -2
- package/dist/catalog/component-state.d.ts +13 -1
- package/dist/catalog/component-state.js +14 -5
- package/dist/catalog/marketplaces.service.d.ts +1 -1
- package/dist/catalog/marketplaces.service.js +2 -1
- package/dist/catalog/org-catalog.controller.d.ts +13 -3
- package/dist/catalog/org-catalog.controller.js +26 -4
- package/dist/catalog/org-catalog.schemas.d.ts +13 -0
- package/dist/catalog/org-catalog.schemas.js +34 -0
- package/dist/catalog/org-plugin-uploads.controller.js +0 -1
- package/dist/catalog/org-plugin-uploads.d.ts +0 -1
- package/dist/catalog/org-plugin-uploads.js +0 -3
- package/dist/catalog/org-plugin-uploads.schemas.d.ts +0 -1
- package/dist/catalog/org-plugin-uploads.schemas.js +0 -2
- package/dist/catalog/platform-components.d.ts +0 -1
- package/dist/catalog/platform-components.js +3 -8
- package/dist/catalog/plugin-import.d.ts +0 -8
- package/dist/catalog/plugin-import.js +4 -35
- package/dist/catalog/plugin-install.d.ts +2 -2
- package/dist/catalog/plugin-install.js +2 -2
- package/dist/catalog/plugin-package.d.ts +7 -0
- package/dist/catalog/plugin-package.js +27 -1
- package/dist/catalog/plugin-upgrade.d.ts +5 -6
- package/dist/catalog/plugin-upgrade.js +5 -23
- package/dist/catalog/requests.service.d.ts +66 -10
- package/dist/catalog/requests.service.js +196 -15
- package/dist/channels/actions.d.ts +2 -0
- package/dist/channels/actions.js +19 -4
- package/dist/channels/cards.d.ts +16 -2
- package/dist/channels/cards.js +40 -7
- package/dist/channels/channels.module.js +3 -0
- package/dist/channels/outbound.d.ts +22 -1
- package/dist/channels/outbound.js +116 -7
- package/dist/channels/phrases.d.ts +25 -0
- package/dist/channels/phrases.js +19 -0
- package/dist/channels/threads.d.ts +12 -0
- package/dist/channels/threads.js +34 -0
- package/dist/config/schema.d.ts +23 -1
- package/dist/config/schema.js +107 -5
- package/dist/conversations/conversations.service.d.ts +42 -9
- package/dist/conversations/conversations.service.js +57 -25
- package/dist/conversations/events.d.ts +106 -11
- package/dist/conversations/events.js +121 -18
- package/dist/conversations/message-context.d.ts +6 -3
- package/dist/conversations/message-context.js +14 -10
- package/dist/conversations/queue.d.ts +15 -2
- package/dist/conversations/queue.js +22 -3
- package/dist/conversations/queue.service.d.ts +12 -6
- package/dist/conversations/queue.service.js +36 -13
- package/dist/db/kernel-schema.d.ts +105 -3
- package/dist/devices/conversation-devices.d.ts +8 -1
- package/dist/devices/conversation-devices.js +8 -0
- package/dist/devices/devices.controller.d.ts +21 -4
- package/dist/devices/devices.controller.js +46 -8
- package/dist/devices/devices.schemas.d.ts +9 -1
- package/dist/devices/devices.schemas.js +11 -3
- package/dist/devices/devices.service.d.ts +176 -4
- package/dist/devices/devices.service.js +347 -6
- package/dist/devices/dto.d.ts +56 -3
- package/dist/devices/dto.js +51 -1
- package/dist/devices/public-suffix.d.ts +6 -0
- package/dist/devices/public-suffix.js +79 -0
- package/dist/errors.d.ts +50 -5
- package/dist/errors.js +50 -5
- package/dist/evals/reconstruct.d.ts +18 -13
- package/dist/evals/reconstruct.js +50 -36
- package/dist/evals/recorded-tools.d.ts +7 -7
- package/dist/evals/recorded-tools.js +4 -3
- package/dist/evals/trajectory.d.ts +6 -1
- package/dist/evals/trajectory.js +7 -0
- package/dist/extensions/package.js +2 -2
- package/dist/http/api.module.js +5 -0
- package/dist/identity/settings.d.ts +53 -3
- package/dist/identity/settings.js +92 -9
- package/dist/inbox/inbox.module.js +2 -1
- package/dist/inbox/inbox.service.d.ts +19 -4
- package/dist/inbox/inbox.service.js +14 -3
- package/dist/infra/config/kernel-config.service.d.ts +7 -0
- package/dist/infra/config/kernel-config.service.js +31 -0
- package/dist/infra/events/kernel-events.d.ts +2 -1
- package/dist/local-devices/device-policy.service.d.ts +65 -0
- package/dist/local-devices/device-policy.service.js +217 -0
- package/dist/local-devices/local-device-gateway.d.ts +4 -2
- package/dist/local-devices/local-device-gateway.js +39 -11
- package/dist/local-devices/local-device-provider.d.ts +40 -3
- package/dist/local-devices/local-device-provider.js +109 -7
- package/dist/local-devices/local-devices.module.d.ts +2 -1
- package/dist/local-devices/local-devices.module.js +19 -3
- package/dist/local-devices/machines.d.ts +30 -3
- package/dist/local-devices/machines.js +79 -3
- package/dist/local-devices/network-grants.d.ts +104 -0
- package/dist/local-devices/network-grants.js +288 -0
- package/dist/local-devices/policy-summary.d.ts +20 -0
- package/dist/local-devices/policy-summary.js +63 -0
- package/dist/orgs/orgs.module.js +4 -10
- package/dist/orgs/roles.d.ts +1 -1
- package/dist/orgs/roles.js +4 -0
- package/dist/orgs/settings.controller.js +4 -3
- package/dist/orgs/settings.service.d.ts +172 -14
- package/dist/orgs/settings.service.js +229 -27
- package/dist/platform/exclusions.js +11 -1
- package/dist/platform/operation.js +4 -0
- package/dist/platform/ops/admin-items.ops.js +1 -1
- package/dist/platform/ops/admin.ops.js +32 -7
- package/dist/platform/ops/agent-skills.ops.js +2 -2
- package/dist/platform/ops/agent-templates.ops.js +2 -2
- package/dist/platform/ops/agents.ops.js +11 -15
- package/dist/platform/ops/devices.ops.js +3 -1
- package/dist/platform/ops/inbox.ops.js +19 -0
- package/dist/platform/ops/org-settings.ops.js +15 -6
- package/dist/platform/ops/orgs.ops.js +1 -0
- package/dist/platform/ops/platform.ops.d.ts +9 -1
- package/dist/platform/ops/platform.ops.js +34 -12
- package/dist/platform/ops/requests.ops.js +3 -2
- package/dist/platform/ops/schedules.ops.d.ts +21 -0
- package/dist/platform/ops/schedules.ops.js +470 -0
- package/dist/platform/ops/skills.ops.js +3 -3
- 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 +3 -0
- package/dist/roles/worker.module.js +3 -0
- package/dist/runtime/context/build.js +13 -4
- package/dist/runtime/context/compaction.js +6 -3
- package/dist/runtime/context/device-paths.d.ts +43 -21
- package/dist/runtime/context/device-paths.js +104 -21
- package/dist/runtime/context/run-context.d.ts +9 -0
- package/dist/runtime/context/run-context.js +8 -0
- package/dist/runtime/context/skills.d.ts +14 -1
- package/dist/runtime/context/skills.js +36 -5
- package/dist/runtime/maintenance.d.ts +4 -2
- package/dist/runtime/maintenance.js +16 -5
- package/dist/runtime/run-finish.d.ts +6 -1
- package/dist/runtime/run-finish.js +16 -2
- package/dist/runtime/run-queue.js +21 -2
- package/dist/runtime/run-worker.js +14 -33
- package/dist/runtime/runtime.module.js +3 -0
- package/dist/runtime/subagents/definition.d.ts +32 -14
- package/dist/runtime/subagents/definition.js +106 -109
- package/dist/runtime/subagents/dispatch.js +4 -3
- package/dist/runtime/subagents/preamble.d.ts +2 -1
- package/dist/runtime/subagents/preamble.js +2 -1
- package/dist/runtime/waits.js +14 -4
- package/dist/sandbox/platform-tiers.d.ts +86 -0
- package/dist/sandbox/platform-tiers.js +97 -0
- package/dist/sandbox/sandbox.service.d.ts +121 -11
- package/dist/sandbox/sandbox.service.js +351 -30
- package/dist/sandbox/tiers.d.ts +98 -0
- package/dist/sandbox/tiers.js +104 -0
- package/dist/schedules/effective-settings.d.ts +16 -0
- package/dist/schedules/effective-settings.js +17 -0
- package/dist/schedules/errors.d.ts +8 -0
- package/dist/schedules/errors.js +8 -0
- package/dist/schedules/fire.d.ts +118 -0
- package/dist/schedules/fire.js +625 -0
- package/dist/schedules/grant-rules.d.ts +94 -0
- package/dist/schedules/grant-rules.js +126 -0
- package/dist/schedules/job-ids.d.ts +32 -0
- package/dist/schedules/job-ids.js +27 -0
- package/dist/schedules/pause.d.ts +9 -0
- package/dist/schedules/pause.js +33 -0
- package/dist/schedules/run-tracker.d.ts +81 -0
- package/dist/schedules/run-tracker.js +333 -0
- package/dist/schedules/scan.job.d.ts +64 -0
- package/dist/schedules/scan.job.js +303 -0
- package/dist/schedules/schedule-math.d.ts +31 -0
- package/dist/schedules/schedule-math.js +223 -0
- package/dist/schedules/scheduled-tasks.service.d.ts +351 -0
- package/dist/schedules/scheduled-tasks.service.js +1193 -0
- package/dist/schedules/schedules.controller.d.ts +68 -0
- package/dist/schedules/schedules.controller.js +242 -0
- package/dist/schedules/schedules.module.d.ts +16 -0
- package/dist/schedules/schedules.module.js +65 -0
- package/dist/schedules/schedules.schemas.d.ts +316 -0
- package/dist/schedules/schedules.schemas.js +186 -0
- package/dist/schedules/store.d.ts +81 -0
- package/dist/schedules/store.js +390 -0
- package/dist/schedules/store.module.d.ts +6 -0
- package/dist/schedules/store.module.js +21 -0
- package/dist/schedules/types.d.ts +108 -0
- package/dist/schedules/types.js +1 -0
- package/dist/schedules/unattended.d.ts +117 -0
- package/dist/schedules/unattended.js +228 -0
- package/dist/setup/oauth-token-probe.js +8 -4
- package/dist/skills/agent-skills.service.d.ts +4 -8
- package/dist/skills/agent-skills.service.js +18 -53
- package/dist/skills/catalog.d.ts +65 -62
- package/dist/skills/catalog.js +109 -206
- package/dist/skills/conversation-catalog.d.ts +3 -3
- package/dist/skills/conversation-catalog.js +5 -12
- package/dist/skills/invoke.d.ts +2 -2
- package/dist/skills/skills.controller.d.ts +3 -1
- package/dist/skills/skills.service.d.ts +38 -37
- package/dist/skills/skills.service.js +168 -107
- package/dist/skills/usable.d.ts +57 -8
- package/dist/skills/usable.js +172 -38
- package/dist/tools/approvals.controller.d.ts +4 -2
- package/dist/tools/approvals.controller.js +17 -2
- package/dist/tools/approvals.schemas.d.ts +1 -0
- package/dist/tools/approvals.schemas.js +3 -1
- package/dist/tools/approvals.service.d.ts +182 -7
- package/dist/tools/approvals.service.js +597 -13
- package/dist/tools/builtin-names.d.ts +25 -4
- package/dist/tools/builtin-names.js +45 -4
- package/dist/tools/builtins/builtin-tools.d.ts +8 -0
- package/dist/tools/builtins/builtin-tools.js +23 -2
- package/dist/tools/builtins/sandbox/bash.js +16 -7
- package/dist/tools/builtins/sandbox/common.d.ts +1 -1
- package/dist/tools/builtins/sandbox/common.js +33 -10
- package/dist/tools/builtins/sandbox/edit.js +7 -3
- package/dist/tools/builtins/sandbox/file-state.d.ts +31 -1
- package/dist/tools/builtins/sandbox/file-state.js +33 -3
- package/dist/tools/builtins/sandbox/write.js +8 -4
- package/dist/tools/builtins/schedules.d.ts +107 -0
- package/dist/tools/builtins/schedules.js +789 -0
- package/dist/tools/elicitation.d.ts +2 -0
- package/dist/tools/elicitation.js +1 -1
- package/dist/tools/fixed-ask.d.ts +7 -0
- package/dist/tools/fixed-ask.js +9 -0
- package/dist/tools/network-asks.d.ts +109 -0
- package/dist/tools/network-asks.js +221 -0
- package/dist/tools/pipeline.d.ts +53 -6
- package/dist/tools/pipeline.js +202 -13
- package/dist/tools/policy.d.ts +21 -8
- package/dist/tools/policy.js +63 -9
- package/dist/tools/registry.d.ts +10 -1
- package/dist/tools/tools.module.js +12 -0
- package/package.json +2 -2
- package/src/migrations/0113_scheduled_tasks.sql +108 -0
- package/src/migrations/0114_network_asks.sql +23 -0
- package/src/migrations/0115_network_requests.sql +28 -0
- package/src/migrations/0116_skills_default_on.sql +37 -0
- package/src/migrations/0117_sandbox_tiers.sql +11 -0
|
@@ -66,6 +66,69 @@ export function canonicalDisabledTools(disabled) {
|
|
|
66
66
|
}
|
|
67
67
|
return out;
|
|
68
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* A skill an agent turns off (skills default-on spec §4): a plugin's skills by name, or `"all"` to
|
|
71
|
+
* turn the plugin off as a unit (skills it gains later included); a skill without a plugin (the
|
|
72
|
+
* org's own, shared or promoted ones) by id, since its name may change under the same id.
|
|
73
|
+
*/
|
|
74
|
+
export const DisabledSkillRef = z.discriminatedUnion("kind", [
|
|
75
|
+
z
|
|
76
|
+
.object({
|
|
77
|
+
kind: z.literal("plugin"),
|
|
78
|
+
plugin: z.string().min(1).max(200),
|
|
79
|
+
skills: z.union([z.literal("all"), z.array(z.string().min(1).max(64)).min(1).max(500)]),
|
|
80
|
+
})
|
|
81
|
+
.strict(),
|
|
82
|
+
z.object({ kind: z.literal("skill"), skillId: z.string().min(1).max(100) }).strict(),
|
|
83
|
+
]);
|
|
84
|
+
/**
|
|
85
|
+
* Is a skill turned off by `disabled`? `plugin` and `name` match a plugin entry; `ids` (the
|
|
86
|
+
* skill's id and, for a linked or promoted copy, the platform skill it serves) a skill entry.
|
|
87
|
+
*/
|
|
88
|
+
export function skillDisabled(disabled, skill) {
|
|
89
|
+
return (disabled ?? []).some((r) => r.kind === "plugin"
|
|
90
|
+
? skill.plugin !== null &&
|
|
91
|
+
r.plugin === skill.plugin &&
|
|
92
|
+
(r.skills === "all" || r.skills.includes(skill.name))
|
|
93
|
+
: skill.ids.includes(r.skillId));
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* `disabled` in its canonical form: one entry per plugin (sorted by plugin, `"all"` absorbing
|
|
97
|
+
* names, names deduplicated and sorted, an empty list dropped), then the skill entries deduplicated
|
|
98
|
+
* and sorted by id. Saving stores this form, so two lists that turn off the same skills compare
|
|
99
|
+
* equal.
|
|
100
|
+
*/
|
|
101
|
+
export function canonicalDisabledSkills(disabled) {
|
|
102
|
+
const plugins = [];
|
|
103
|
+
const ids = new Set();
|
|
104
|
+
for (const r of disabled) {
|
|
105
|
+
if (r.kind === "skill") {
|
|
106
|
+
ids.add(r.skillId);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
const names = r.skills;
|
|
110
|
+
const prev = plugins.find((x) => x.plugin === r.plugin);
|
|
111
|
+
if (prev) {
|
|
112
|
+
prev.skills =
|
|
113
|
+
prev.skills === "all" || names === "all"
|
|
114
|
+
? "all"
|
|
115
|
+
: [...new Set([...prev.skills, ...names])].sort();
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
plugins.push({
|
|
119
|
+
kind: "plugin",
|
|
120
|
+
plugin: r.plugin,
|
|
121
|
+
skills: names === "all" ? "all" : [...new Set(names)].sort(),
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return [
|
|
126
|
+
...plugins
|
|
127
|
+
.filter((p) => p.skills === "all" || p.skills.length > 0)
|
|
128
|
+
.sort((a, b) => (a.plugin < b.plugin ? -1 : a.plugin > b.plugin ? 1 : 0)),
|
|
129
|
+
...[...ids].sort().map((skillId) => ({ kind: "skill", skillId })),
|
|
130
|
+
];
|
|
131
|
+
}
|
|
69
132
|
/**
|
|
70
133
|
* A sub-agent's tool filter by tool key (tools default-on spec §4): written only into a child's
|
|
71
134
|
* effective definition at dispatch (never accepted on save). `deny` removes keys (the child-removed
|
|
@@ -83,8 +146,8 @@ export const SubagentToolsSchema = z
|
|
|
83
146
|
export const SUBAGENT_NAME_RE = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
84
147
|
/**
|
|
85
148
|
* A sub-agent template written in the agent definition (phase C, spec §5.2): the fields of a
|
|
86
|
-
* plugin agent template (`AgentTemplate`, spec §16.1), with `skills` as skill ids (
|
|
87
|
-
*
|
|
149
|
+
* plugin agent template (`AgentTemplate`, spec §16.1), with `skills` as skill ids (skills the agent
|
|
150
|
+
* has, skills default-on spec §6.1) instead of names. Names and skills are checked on save
|
|
88
151
|
* (`agent.subagents_invalid`); the schema only bounds the input.
|
|
89
152
|
*/
|
|
90
153
|
export const InlineAgentTemplate = z
|
|
@@ -217,25 +280,19 @@ export const AgentDefinitionSchema = z.object({
|
|
|
217
280
|
*/
|
|
218
281
|
toolPolicies: z.record(z.string(), z.enum(["allow", "ask", "deny"])).default({}),
|
|
219
282
|
/**
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
*
|
|
283
|
+
* The skills this agent turns off (skills default-on spec §4); every other skill on in the org
|
|
284
|
+
* is on for it, and its own and shared skills always are. Saved in canonical form
|
|
285
|
+
* ({@link canonicalDisabledSkills}); checked on save.
|
|
286
|
+
*/
|
|
287
|
+
disabledSkills: z.array(DisabledSkillRef).max(500).default([]),
|
|
288
|
+
/**
|
|
223
289
|
* `writePolicy`: whether registering a skill on a private agent (`agents.register-skill`) needs
|
|
224
|
-
* the person's confirmation; absent means `allow
|
|
225
|
-
*
|
|
290
|
+
* the person's confirmation; absent means `allow`. On a shared agent a registration is always
|
|
291
|
+
* confirmed at the org level. No default: definitions without it gain no version.
|
|
226
292
|
*/
|
|
227
293
|
skills: z
|
|
228
294
|
.object({
|
|
229
|
-
orgSkills: z.array(z.string().min(1).max(100)).max(100).default([]),
|
|
230
295
|
writePolicy: z.enum(["allow", "ask"]).optional(),
|
|
231
|
-
/**
|
|
232
|
-
* Pinned skills (phase B, spec §9.1): ids of selected org skills or of the agent's own
|
|
233
|
-
* skills, whose bodies apply throughout every conversation, in this order. At most
|
|
234
|
-
* `PINNED_SKILLS_LIMITS.count` (checked with the other rules by `assertPinnedSkills`, as
|
|
235
|
-
* `agent.pinned_invalid`; the schema only bounds the input). No default: definitions
|
|
236
|
-
* without it are unchanged.
|
|
237
|
-
*/
|
|
238
|
-
pinned: z.array(z.string().min(1).max(100)).max(100).optional(),
|
|
239
296
|
})
|
|
240
297
|
.strict()
|
|
241
298
|
.optional(),
|
|
@@ -478,8 +535,10 @@ function normalizeToolRef(v) {
|
|
|
478
535
|
* current keys ({@link normalizeToolKeys}: builtins always, `<x>__<tool>` keys with `scope`), and
|
|
479
536
|
* a definition from before tools were on by default (an enabled `tools` list, history only: the
|
|
480
537
|
* migration rewrote stored versions) reads as nothing turned off, which is what the migration
|
|
481
|
-
* writes (tools default-on spec §2, §3).
|
|
482
|
-
*
|
|
538
|
+
* writes (tools default-on spec §2, §3). Likewise a definition from before skills were on by
|
|
539
|
+
* default (`skills.orgSkills` / `skills.pinned`) reads as no skill turned off (skills default-on
|
|
540
|
+
* spec §4; migration 0116 rewrote stored versions). Other fields are kept; without old forms the
|
|
541
|
+
* same object is returned.
|
|
483
542
|
*/
|
|
484
543
|
export function normalizeStoredDefinition(def, scope) {
|
|
485
544
|
let d = def;
|
|
@@ -495,6 +554,15 @@ export function normalizeStoredDefinition(def, scope) {
|
|
|
495
554
|
else if (!Array.isArray(d.disabledTools)) {
|
|
496
555
|
d = { ...d, disabledTools: [] };
|
|
497
556
|
}
|
|
557
|
+
// before skills were on by default (skills default-on spec §4, §5): selected and pinned skills
|
|
558
|
+
// read as nothing turned off, which is what migration 0116 writes
|
|
559
|
+
if (isRecord(d.skills) && ("orgSkills" in d.skills || "pinned" in d.skills)) {
|
|
560
|
+
const { orgSkills: _o, pinned: _p, ...keep } = d.skills;
|
|
561
|
+
const { skills: _s, ...rest } = d;
|
|
562
|
+
d = Object.keys(keep).length > 0 ? { ...rest, skills: keep } : rest;
|
|
563
|
+
}
|
|
564
|
+
if (!Array.isArray(d.disabledSkills))
|
|
565
|
+
d = { ...d, disabledSkills: [] };
|
|
498
566
|
return d;
|
|
499
567
|
}
|
|
500
568
|
/** 按模型声明严格校验一组参数,返回 `{ path: "<field>.<key>", message }[]`(评测候选也用它)。 */
|
|
@@ -16,8 +16,10 @@ export type PlanItemKind = "instruction_file" | "description" | "quick_action" |
|
|
|
16
16
|
* describes sub-agents, though its allowlist leaves it out); unavailable `plugin_unavailable`
|
|
17
17
|
* (its plugin is not enabled in the org or not loaded), `unknown_tool`, `connector_key` (a
|
|
18
18
|
* connector tool key: connectors carry over only through `connectors` entries);
|
|
19
|
-
* - skill
|
|
20
|
-
* inline sub-agent
|
|
19
|
+
* - skill (a name of `skills` or an inline sub-agent's `skills`, or a `disallowedSkills` entry): a
|
|
20
|
+
* carried name is on for the new agent, `subagent` when only an inline sub-agent names it;
|
|
21
|
+
* `disallowed` for a `disallowedSkills` entry turned off; unavailable `not_found` (the org does
|
|
22
|
+
* not have it);
|
|
21
23
|
* - connector: `several` (the first of several connectors made from the template was bound);
|
|
22
24
|
* pending `no_connector`, `tools_missing` (the connector made from the template lacks every
|
|
23
25
|
* named tool), `needs`; unavailable `template_not_found` (also for a template the org may not
|
|
@@ -56,7 +58,8 @@ export interface TemplatePlan {
|
|
|
56
58
|
* What has no place in the agent or was cut to its limits: `maxSteps`, `effort` when the model
|
|
57
59
|
* does not declare it, `description` / `instructions` / `quickActions.<i>.title|body` /
|
|
58
60
|
* `instructionFiles.<i>.content` / `subagents.inline.<name>.description|instructions` when cut to
|
|
59
|
-
* the kernel's limits (UTF-16 units), `
|
|
61
|
+
* the kernel's limits (UTF-16 units), `disallowedSkills.<entry>` for an entry that names no skill
|
|
62
|
+
* the org has, `subagents.inline.<name>.tools.<key>` for a key the agent
|
|
60
63
|
* does not have, `connectors.<key>.tools.<name>` / `connectors.<key>.policies.<name>` for a tool
|
|
61
64
|
* the bound connector does not offer.
|
|
62
65
|
*/
|
|
@@ -3,14 +3,13 @@
|
|
|
3
3
|
// create. Pure resolution over read snapshots: the database reads go through `db`, the replica's
|
|
4
4
|
// extension state and the model lookups through `opts`; nothing is written here.
|
|
5
5
|
import { createHash } from "node:crypto";
|
|
6
|
-
import { connectorToolKey, extensionToolKey, parseToolKey,
|
|
6
|
+
import { connectorToolKey, extensionToolKey, parseToolKey, validateParams, } from "@capybara-hq/plugin-sdk";
|
|
7
7
|
import { connectorTemplateState } from "../catalog/component-state.js";
|
|
8
|
-
import {
|
|
9
|
-
import { usableSkillVersions } from "../skills/usable.js";
|
|
8
|
+
import { builtinSkillIds, builtinSkillPlugins, usableSkillVersions, } from "../skills/usable.js";
|
|
10
9
|
import { CONTROL_OR_HIDDEN_RE } from "../text.js";
|
|
11
10
|
import { AGENT_BUILTIN_NAMES, AGENT_TOOL, BASH_COMPANION_TOOLS, BUILTIN, BUILTIN_TOOL_NAMES, } from "../tools/builtin-names.js";
|
|
12
11
|
import { canonicalJson } from "../tools/canonical-json.js";
|
|
13
|
-
import { AgentDefinitionSchema, builtinDisabled, canonicalDisabledTools, connectorToolDisabled, extensionToolDisabled, SUBAGENT_NAME_RE, SUBAGENT_ROSTER_MAX, } from "./definition.js";
|
|
12
|
+
import { AgentDefinitionSchema, builtinDisabled, canonicalDisabledSkills, canonicalDisabledTools, connectorToolDisabled, extensionToolDisabled, SUBAGENT_NAME_RE, SUBAGENT_ROSTER_MAX, } from "./definition.js";
|
|
14
13
|
import { INSTRUCTION_FILE_LIMITS, INSTRUCTION_FILE_NAME_RE, joinInstructionFiles, } from "./instruction-files.js";
|
|
15
14
|
import { sanitizeEndpoint } from "./org-templates.js";
|
|
16
15
|
import { PROFILE_LIMITS, ProfileInputSchema } from "./profile.js";
|
|
@@ -81,6 +80,34 @@ function skillByName(skills, ref, ownPlugin) {
|
|
|
81
80
|
const rank = (s) => (ownPlugin !== null && s.plugin === ownPlugin ? 0 : 1);
|
|
82
81
|
return [...found].sort((a, b) => rank(a) - rank(b) || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0))[0];
|
|
83
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* A template's `disallowedSkills` entry as an agent's disabled skill entry (skills default-on spec
|
|
85
|
+
* §6.2): `<plugin>:*` the whole plugin (skills it gains later included), `<plugin>:<name>` that
|
|
86
|
+
* plugin's skill, a bare `<name>` the org's usable skill of that name without a plugin. Null when
|
|
87
|
+
* the agent's save check would refuse it: it names nothing the org has, a builtin plugin
|
|
88
|
+
* (`builtin.plugins`) or a builtin skill (`builtin.ids`, which cannot be turned off).
|
|
89
|
+
*/
|
|
90
|
+
function disallowedSkillRef(skills, ref, builtin) {
|
|
91
|
+
const isBuiltin = (s) => builtin.ids.has(s.id) ||
|
|
92
|
+
(s.platformSkillId !== undefined && builtin.ids.has(s.platformSkillId));
|
|
93
|
+
const i = ref.indexOf(":");
|
|
94
|
+
if (i >= 0) {
|
|
95
|
+
const plugin = ref.slice(0, i);
|
|
96
|
+
const name = ref.slice(i + 1);
|
|
97
|
+
if (builtin.plugins.has(plugin))
|
|
98
|
+
return null;
|
|
99
|
+
const ofPlugin = skills.filter((s) => s.plugin === plugin);
|
|
100
|
+
if (name === "*") {
|
|
101
|
+
return ofPlugin.length === 0 ? null : { kind: "plugin", plugin, skills: "all" };
|
|
102
|
+
}
|
|
103
|
+
const s = ofPlugin.find((x) => x.name === name);
|
|
104
|
+
return s === undefined || isBuiltin(s) ? null : { kind: "plugin", plugin, skills: [name] };
|
|
105
|
+
}
|
|
106
|
+
const s = skills
|
|
107
|
+
.filter((x) => x.plugin === null && x.name === ref)
|
|
108
|
+
.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0))[0];
|
|
109
|
+
return s === undefined || isBuiltin(s) ? null : { kind: "skill", skillId: s.id };
|
|
110
|
+
}
|
|
84
111
|
/**
|
|
85
112
|
* Whether the org may see platform connector template `row`: usable (on) or offered in the org,
|
|
86
113
|
* owned by it, or one it has made connectors from (they stay its own, also after the template is
|
|
@@ -315,45 +342,34 @@ export async function planFromTemplate(db, orgId, row, opts) {
|
|
|
315
342
|
offExtensionTool(parsed.plugin, parsed.tool);
|
|
316
343
|
// a connector key is matched against the bound connectors below
|
|
317
344
|
}
|
|
318
|
-
// skills
|
|
345
|
+
// skills (skills default-on spec §6.2): the new agent has every skill on in the org. Each name
|
|
346
|
+
// in `skills` (and in an inline sub-agent's, below) is checked against the org's usable skills
|
|
347
|
+
// and listed `carried` or `unavailable` (`not_found`); it narrows nothing.
|
|
319
348
|
const usable = await usableSkillVersions(db, orgId);
|
|
320
|
-
const
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
};
|
|
325
|
-
const pinned = [];
|
|
326
|
-
let pinnedBytes = 0;
|
|
327
|
-
const preloaded = new Set(t.skills ?? []);
|
|
328
|
-
const skillNames = [...new Set([...(t.skills ?? []), ...(t.selectedSkills ?? [])])];
|
|
329
|
-
for (const name of skillNames) {
|
|
330
|
-
const s = skillByName(usable, name, row.plugin);
|
|
331
|
-
if (!s) {
|
|
349
|
+
for (const name of new Set(t.skills ?? [])) {
|
|
350
|
+
if (skillByName(usable, name, row.plugin))
|
|
351
|
+
item("skill", name, "carried");
|
|
352
|
+
else
|
|
332
353
|
item("skill", name, "unavailable", "not_found");
|
|
354
|
+
}
|
|
355
|
+
// `disallowedSkills` turns skills off: `<plugin>:*` the whole plugin, `<plugin>:<name>` a
|
|
356
|
+
// plugin's skill, a bare `<name>` the org's skill without a plugin; an entry that names nothing
|
|
357
|
+
// the org has, or a builtin plugin or skill (always on), is dropped
|
|
358
|
+
const disabledSkills = [];
|
|
359
|
+
const builtin = (t.disallowedSkills ?? []).length === 0
|
|
360
|
+
? { plugins: new Set(), ids: new Set() }
|
|
361
|
+
: {
|
|
362
|
+
plugins: await builtinSkillPlugins(db),
|
|
363
|
+
ids: new Set(await builtinSkillIds(db, orgId)),
|
|
364
|
+
};
|
|
365
|
+
for (const ref of new Set(t.disallowedSkills ?? [])) {
|
|
366
|
+
const off = disallowedSkillRef(usable, ref, builtin);
|
|
367
|
+
if (off === null) {
|
|
368
|
+
dropped.push(`disallowedSkills.${ref}`);
|
|
333
369
|
continue;
|
|
334
370
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
item("skill", name, "carried", pinned.includes(s.id) ? "pinned" : undefined);
|
|
338
|
-
continue;
|
|
339
|
-
}
|
|
340
|
-
if (pinned.includes(s.id)) {
|
|
341
|
-
item("skill", name, "carried", "pinned");
|
|
342
|
-
continue;
|
|
343
|
-
}
|
|
344
|
-
const bytes = s.manifest.files.find((f) => f.path === SKILL_ENTRY_FILE)?.size ?? 0;
|
|
345
|
-
if (!invocationOf(s.manifest).model) {
|
|
346
|
-
item("skill", name, "carried", "not_pinned_manual_only");
|
|
347
|
-
}
|
|
348
|
-
else if (pinned.length >= PINNED_SKILLS_LIMITS.count ||
|
|
349
|
-
pinnedBytes + bytes > PINNED_SKILLS_LIMITS.totalBytes) {
|
|
350
|
-
item("skill", name, "carried", "not_pinned_too_large");
|
|
351
|
-
}
|
|
352
|
-
else {
|
|
353
|
-
pinned.push(s.id);
|
|
354
|
-
pinnedBytes += bytes;
|
|
355
|
-
item("skill", name, "carried", "pinned");
|
|
356
|
-
}
|
|
371
|
+
disabledSkills.push(off);
|
|
372
|
+
item("skill", ref, "carried", "disallowed");
|
|
357
373
|
}
|
|
358
374
|
// connectors (P4-5, P4-6)
|
|
359
375
|
const pendingConnectors = [];
|
|
@@ -530,8 +546,7 @@ export async function planFromTemplate(db, orgId, row, opts) {
|
|
|
530
546
|
}
|
|
531
547
|
if (!skillIds.includes(s.id))
|
|
532
548
|
skillIds.push(s.id);
|
|
533
|
-
if (!
|
|
534
|
-
select(s.id);
|
|
549
|
+
if (!items.some((i) => i.kind === "skill" && i.name === name)) {
|
|
535
550
|
item("skill", name, "carried", "subagent");
|
|
536
551
|
}
|
|
537
552
|
}
|
|
@@ -617,9 +632,7 @@ export async function planFromTemplate(db, orgId, row, opts) {
|
|
|
617
632
|
fallbackParams: {},
|
|
618
633
|
disabledTools: canonicalDisabledTools(disabled),
|
|
619
634
|
toolPolicies,
|
|
620
|
-
|
|
621
|
-
skills: { orgSkills, ...(pinned.length > 0 && { pinned }) },
|
|
622
|
-
}),
|
|
635
|
+
disabledSkills: canonicalDisabledSkills(disabledSkills),
|
|
623
636
|
...(subagents !== undefined && { subagents }),
|
|
624
637
|
...(pendingConnectors.length > 0 && { pendingConnectors }),
|
|
625
638
|
};
|
|
@@ -11,7 +11,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
11
11
|
// an org row (`agent_templates`, no plugin, a bare `<name>`, version 1) from an agent, the template
|
|
12
12
|
// detail reads any template usable in the org, and the owner org's admins write new versions.
|
|
13
13
|
// Deleting and 可共享 are `OwnedItems`' (the P3 owner rules). No in-process state.
|
|
14
|
-
import { AGENT_TEMPLATE_LIMITS, extensionToolKey, parseAgentTemplate, parseToolKey, } from "@capybara-hq/plugin-sdk";
|
|
14
|
+
import { AGENT_TEMPLATE_LIMITS, extensionToolKey, isDisallowedSkillRef, parseAgentTemplate, parseToolKey, } from "@capybara-hq/plugin-sdk";
|
|
15
15
|
import { Inject, Injectable } from "@nestjs/common";
|
|
16
16
|
import { offeredNamed } from "../catalog/component-state.js";
|
|
17
17
|
import { ownerOf, ownersOf } from "../catalog/ownership.js";
|
|
@@ -22,12 +22,13 @@ import { KernelDb } from "../infra/database/kernel-db.js";
|
|
|
22
22
|
import { TransactionHost } from "../infra/database/transaction-host.js";
|
|
23
23
|
import { Transactional } from "../infra/database/transactional.decorator.js";
|
|
24
24
|
import { OrgLock } from "../orgs/org-lock.js";
|
|
25
|
-
import { skillVersionsById } from "../skills/usable.js";
|
|
25
|
+
import { builtinSkillIds, builtinSkillPlugins, linkedCopyIds, skillIdsOf, skillVersionsById, usableSkillVersions, } from "../skills/usable.js";
|
|
26
26
|
import { isRemovedBuiltinKey } from "../tools/builtin-names.js";
|
|
27
27
|
import { canonicalJson } from "../tools/canonical-json.js";
|
|
28
28
|
import { ToolRegistry } from "../tools/registry.js";
|
|
29
29
|
import { AgentLookup } from "./agent-lookup.js";
|
|
30
|
-
import {
|
|
30
|
+
import { canonicalDisabledSkills, } from "./definition.js";
|
|
31
|
+
import { loadTemplates, putTemplateVersionIn, readOwnTemplate, storedTemplate, templateTypeOf, templateViewOf, usableTemplates, } from "./templates.js";
|
|
31
32
|
/**
|
|
32
33
|
* Roster names no template may take (ruling T4-R15): `general-purpose`, always the roster's first
|
|
33
34
|
* entry. Claude Code's other built-in types (`Explore`, `Plan`) are capitalized, which the
|
|
@@ -127,6 +128,68 @@ export function canonicalEndpoints(template) {
|
|
|
127
128
|
}
|
|
128
129
|
return template.connectors === undefined ? template : { ...template, connectors };
|
|
129
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* An agent's `disabledSkills` as a template's `disallowedSkills` (skills default-on spec §6.2): a
|
|
133
|
+
* plugin entry of `"all"` as `<plugin>:*` while the org has skills of that plugin, its names as
|
|
134
|
+
* `<plugin>:<name>` while the org has that skill, a skill entry as the current name of the usable skill it names (`<plugin>:<name>` for a
|
|
135
|
+
* plugin's skill). What no longer resolves, or is past the template's limit, goes to `omitted`.
|
|
136
|
+
*/
|
|
137
|
+
async function disallowedSkillsOf(db, orgId, disabled, omitted) {
|
|
138
|
+
const out = [];
|
|
139
|
+
if (disabled.length === 0)
|
|
140
|
+
return out;
|
|
141
|
+
const usable = await usableSkillVersions(db, orgId);
|
|
142
|
+
const linked = await linkedCopyIds(db, orgId, usable.flatMap((r) => (r.origin === "platform" ? [r.id] : [])));
|
|
143
|
+
// builtin plugins and skills are always on: never in an off-list (the agent save refuses them)
|
|
144
|
+
const builtinPlugins = await builtinSkillPlugins(db);
|
|
145
|
+
const builtinIds = new Set(await builtinSkillIds(db, orgId));
|
|
146
|
+
const isBuiltin = (s) => builtinIds.has(s.id) || (s.platformSkillId !== undefined && builtinIds.has(s.platformSkillId));
|
|
147
|
+
const push = (ref, id) => {
|
|
148
|
+
if (out.includes(ref))
|
|
149
|
+
return;
|
|
150
|
+
if (out.length >= AGENT_TEMPLATE_LIMITS.disallowedSkills) {
|
|
151
|
+
omitted.push({ kind: "skill", name: ref, ...(id !== undefined && { id }), reason: "limit" });
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
out.push(ref);
|
|
155
|
+
};
|
|
156
|
+
for (const r of canonicalDisabledSkills(disabled)) {
|
|
157
|
+
if (r.kind === "plugin" && builtinPlugins.has(r.plugin))
|
|
158
|
+
continue;
|
|
159
|
+
if (r.kind === "plugin") {
|
|
160
|
+
if (r.skills === "all") {
|
|
161
|
+
const ref = `${r.plugin}:*`;
|
|
162
|
+
const ok = isDisallowedSkillRef(ref) && usable.some((s) => s.plugin === r.plugin);
|
|
163
|
+
if (ok)
|
|
164
|
+
push(ref);
|
|
165
|
+
else
|
|
166
|
+
omitted.push({ kind: "skill", name: ref, reason: "unavailable" });
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
for (const name of r.skills) {
|
|
170
|
+
const ref = `${r.plugin}:${name}`;
|
|
171
|
+
const s = usable.find((u) => u.plugin === r.plugin && u.name === name);
|
|
172
|
+
const ok = isDisallowedSkillRef(ref) && s !== undefined && !isBuiltin(s);
|
|
173
|
+
if (ok)
|
|
174
|
+
push(ref);
|
|
175
|
+
else
|
|
176
|
+
omitted.push({ kind: "skill", name: ref, reason: "unavailable" });
|
|
177
|
+
}
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
const s = usable.find((u) => skillIdsOf(u, linked).includes(r.skillId));
|
|
181
|
+
const ref = s === undefined || isBuiltin(s) || (s.plugin !== null && builtinPlugins.has(s.plugin))
|
|
182
|
+
? null
|
|
183
|
+
: s.plugin === null
|
|
184
|
+
? s.name
|
|
185
|
+
: `${s.plugin}:${s.name}`;
|
|
186
|
+
if (ref !== null && isDisallowedSkillRef(ref))
|
|
187
|
+
push(ref, r.skillId);
|
|
188
|
+
else
|
|
189
|
+
omitted.push({ kind: "skill", name: r.skillId, id: r.skillId, reason: "unavailable" });
|
|
190
|
+
}
|
|
191
|
+
return out;
|
|
192
|
+
}
|
|
130
193
|
/**
|
|
131
194
|
* The template an agent is saved as (rulings P4-10, P4-11), with what was left out. Pure reads of
|
|
132
195
|
* the org's state through `db`.
|
|
@@ -229,50 +292,44 @@ extensionTools = []) {
|
|
|
229
292
|
// capped with the entry's tools when it is pushed
|
|
230
293
|
return { policies: Object.fromEntries(list.map((p) => [p.tool, p.policy])) };
|
|
231
294
|
};
|
|
232
|
-
// Skills
|
|
233
|
-
|
|
234
|
-
|
|
295
|
+
// Skills (skills default-on spec §6.2): the agent has every skill on in the org; its
|
|
296
|
+
// `disabledSkills` become `disallowedSkills` (a whole plugin as `<plugin>:*`, a plugin's skill
|
|
297
|
+
// as `<plugin>:<name>`, a skill entry by its current name); entries that no longer resolve to a
|
|
298
|
+
// usable skill are listed. The agent's own skills are not in the org library: listed.
|
|
299
|
+
const disallowedSkills = await disallowedSkillsOf(db, orgId, def.disabledSkills ?? [], omitted);
|
|
235
300
|
const inlineSkillIds = (def.subagents?.inline ?? []).flatMap((t) => t.skills ?? []);
|
|
236
|
-
const byId = await skillVersionsById(db, orgId,
|
|
237
|
-
const
|
|
301
|
+
const byId = await skillVersionsById(db, orgId, inlineSkillIds);
|
|
302
|
+
const ownSkills = await db
|
|
238
303
|
.selectFrom("skills")
|
|
239
|
-
.select(["id", "name"])
|
|
304
|
+
.select(["id", "name", "agent_id", "deleted_at"])
|
|
240
305
|
.where("org_id", "=", orgId)
|
|
241
306
|
.where("scope", "=", "agent")
|
|
242
|
-
.where("
|
|
243
|
-
.
|
|
307
|
+
.where((eb) => eb.or([eb("agent_id", "=", agent.id), eb("id", "in", ["", ...inlineSkillIds])]))
|
|
308
|
+
.orderBy("name")
|
|
309
|
+
.orderBy("id")
|
|
310
|
+
.execute();
|
|
311
|
+
const agentSkillNames = new Map(ownSkills.map((r) => [r.id, r.name]));
|
|
244
312
|
const reportedSkills = new Set();
|
|
245
|
-
const
|
|
313
|
+
const reportSkill = (id) => {
|
|
314
|
+
if (reportedSkills.has(id))
|
|
315
|
+
return;
|
|
316
|
+
reportedSkills.add(id);
|
|
317
|
+
const own = agentSkillNames.get(id) ?? byId.get(id)?.name;
|
|
318
|
+
omitted.push(own !== undefined
|
|
319
|
+
? { kind: "skill", name: own, id, reason: "agent_skill" }
|
|
320
|
+
: { kind: "skill", name: id, id, reason: "unavailable" });
|
|
321
|
+
};
|
|
322
|
+
const skillName = (id) => {
|
|
246
323
|
const s = byId.get(id);
|
|
247
324
|
if (s && s.scope === "org")
|
|
248
325
|
return s.name;
|
|
249
|
-
|
|
250
|
-
reportedSkills.add(id);
|
|
251
|
-
const own = agentSkillNames.get(id) ?? s?.name;
|
|
252
|
-
omitted.push(own !== undefined
|
|
253
|
-
? { kind: "skill", name: own, id, reason: "agent_skill" }
|
|
254
|
-
: { kind: "skill", name: id, id, reason: "unavailable" });
|
|
255
|
-
}
|
|
326
|
+
reportSkill(id);
|
|
256
327
|
return null;
|
|
257
328
|
};
|
|
258
|
-
|
|
259
|
-
for (const
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
skills.push(n);
|
|
263
|
-
}
|
|
264
|
-
const selectedSkills = [];
|
|
265
|
-
for (const id of selected) {
|
|
266
|
-
if (pinned.includes(id))
|
|
267
|
-
continue;
|
|
268
|
-
const n = skillName(id, true);
|
|
269
|
-
if (n === null || skills.includes(n) || selectedSkills.includes(n))
|
|
270
|
-
continue;
|
|
271
|
-
if (selectedSkills.length >= L.selectedSkills) {
|
|
272
|
-
omitted.push({ kind: "skill", name: n, id, reason: "limit" });
|
|
273
|
-
continue;
|
|
274
|
-
}
|
|
275
|
-
selectedSkills.push(n);
|
|
329
|
+
// the agent's own live skills (on for it whatever `disabledSkills` say)
|
|
330
|
+
for (const r of ownSkills) {
|
|
331
|
+
if (r.agent_id === agent.id && r.deleted_at === null)
|
|
332
|
+
reportSkill(r.id);
|
|
276
333
|
}
|
|
277
334
|
// Connectors (P4-11), then the agent's pending connectors as they are
|
|
278
335
|
const connectors = [];
|
|
@@ -468,7 +525,7 @@ extensionTools = []) {
|
|
|
468
525
|
}
|
|
469
526
|
const inlineSkills = [];
|
|
470
527
|
for (const id of t.skills ?? []) {
|
|
471
|
-
const n = skillName(id
|
|
528
|
+
const n = skillName(id);
|
|
472
529
|
if (n === null || inlineSkills.includes(n))
|
|
473
530
|
continue;
|
|
474
531
|
if (inlineSkills.length >= L.skills) {
|
|
@@ -512,8 +569,7 @@ extensionTools = []) {
|
|
|
512
569
|
model: "standard",
|
|
513
570
|
modelRef: `${def.model.provider}/${def.model.model}`,
|
|
514
571
|
...(effort !== undefined && { effort }),
|
|
515
|
-
...(
|
|
516
|
-
...(selectedSkills.length > 0 && { selectedSkills }),
|
|
572
|
+
...(disallowedSkills.length > 0 && { disallowedSkills }),
|
|
517
573
|
...(connectors.length > 0 && { connectors }),
|
|
518
574
|
...(subagents !== undefined && { subagents }),
|
|
519
575
|
...(quickActions.length > 0 && { quickActions }),
|
|
@@ -806,7 +862,7 @@ let OrgAgentTemplates = class OrgAgentTemplates {
|
|
|
806
862
|
name: own.name,
|
|
807
863
|
plugin: null,
|
|
808
864
|
version: row.current_version,
|
|
809
|
-
template: row.definition,
|
|
865
|
+
template: storedTemplate(row.definition),
|
|
810
866
|
sourceFormat: row.source_format,
|
|
811
867
|
catalogItemId: null,
|
|
812
868
|
catalogVersion: null,
|
|
@@ -61,6 +61,12 @@ export interface TemplateRow {
|
|
|
61
61
|
}
|
|
62
62
|
/** The roster type of a template: `<plugin>:<name>`, the bare `<name>` without a plugin. */
|
|
63
63
|
export declare const templateTypeOf: (plugin: string | null, name: string) => string;
|
|
64
|
+
/**
|
|
65
|
+
* A stored template definition as the current format reads it: `selectedSkills` (removed with
|
|
66
|
+
* skills on by default, spec §6.2) is dropped. Migration 0116 removed it from org-made versions;
|
|
67
|
+
* versions written from a plugin package keep it as the package wrote it, so every read drops it.
|
|
68
|
+
*/
|
|
69
|
+
export declare function storedTemplate(definition: unknown): AgentTemplate;
|
|
64
70
|
/**
|
|
65
71
|
* The ids among `ids` of the platform templates on in the org (see {@link platformOn}), whatever
|
|
66
72
|
* the org's own templates are.
|
package/dist/agents/templates.js
CHANGED
|
@@ -53,6 +53,20 @@ async function ownedPlatformIds(db, orgId, platformIds) {
|
|
|
53
53
|
.execute();
|
|
54
54
|
return new Set(rows.map((r) => r.id));
|
|
55
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* A stored template definition as the current format reads it: `selectedSkills` (removed with
|
|
58
|
+
* skills on by default, spec §6.2) is dropped. Migration 0116 removed it from org-made versions;
|
|
59
|
+
* versions written from a plugin package keep it as the package wrote it, so every read drops it.
|
|
60
|
+
*/
|
|
61
|
+
export function storedTemplate(definition) {
|
|
62
|
+
if (definition === null || typeof definition !== "object" || Array.isArray(definition)) {
|
|
63
|
+
return definition;
|
|
64
|
+
}
|
|
65
|
+
if (!("selectedSkills" in definition))
|
|
66
|
+
return definition;
|
|
67
|
+
const { selectedSkills: _s, ...rest } = definition;
|
|
68
|
+
return rest;
|
|
69
|
+
}
|
|
56
70
|
/**
|
|
57
71
|
* Stored rows as {@link TemplateRow}s; tool keys read as current keys (tool naming spec §8.3): old
|
|
58
72
|
* builtin names always, rc `<x>__<tool>` keys with the org's legacy scope, read once when needed.
|
|
@@ -63,7 +77,7 @@ async function normalized(db, orgId, rows) {
|
|
|
63
77
|
: undefined;
|
|
64
78
|
return rows.map(({ definition, ...r }) => ({
|
|
65
79
|
...r,
|
|
66
|
-
template: normalizeToolKeys(definition, scope),
|
|
80
|
+
template: storedTemplate(normalizeToolKeys(definition, scope)),
|
|
67
81
|
}));
|
|
68
82
|
}
|
|
69
83
|
const orgRaw = (r) => ({
|
|
@@ -28,14 +28,52 @@ export declare const taskSidPath: (id: string) => string;
|
|
|
28
28
|
export declare function newTaskId(): string;
|
|
29
29
|
/** A task id ({@link newTaskId}). */
|
|
30
30
|
export declare const TASK_ID_RE: RegExp;
|
|
31
|
+
/**
|
|
32
|
+
* A shell fragment that sets how a task's processes are found and signalled by its sid, defining
|
|
33
|
+
* `tk_alive <sid>` (status 0 while the task has a process) and `tk_kill <SIGNAL> <sid>` (0: sent,
|
|
34
|
+
* 1: no process left, anything else: a failure), and `pg` to the mode:
|
|
35
|
+
* - `-s`, the session, where `pgrep` has `-s` (Linux procps and busybox, the sandbox-fake shims:
|
|
36
|
+
* `pgrep -s 0`, the own session, exits 0 or 1): `pgrep -s` and `pkill -s`;
|
|
37
|
+
* - `-g`, the process group, elsewhere (macOS). Its `pgrep` has no `-s`, and inside the OS sandbox
|
|
38
|
+
* (Seatbelt) a command can neither list processes nor signal those of another command. So the
|
|
39
|
+
* task's process group (its id is the sid) is watched by its launcher ({@link GROUP_LAUNCHER}),
|
|
40
|
+
* which signals it on request: `tk_kill` appends the signal to `.capybara/tasks/g<sid>.ctl`, and
|
|
41
|
+
* `tk_alive` asks `kill(0, -sid)`, where "not permitted" (another command's group) still means
|
|
42
|
+
* the group exists. A group signal is one system call, so it misses no process forked meanwhile.
|
|
43
|
+
* Relative to the workspace root. Every script that asks for or signals a task's processes starts
|
|
44
|
+
* with it; the launch picks its launcher with the same test.
|
|
45
|
+
*/
|
|
46
|
+
export declare const SESSION_MODE_SCRIPT: string;
|
|
47
|
+
/**
|
|
48
|
+
* The process group launcher (macOS: {@link SESSION_MODE_SCRIPT}'s `-g`), a perl program run as
|
|
49
|
+
* `perl -e <this> <seconds> <task path>` from the workspace root. It makes a session of its own
|
|
50
|
+
* (leaving the launch exec's process group), starts `bash <task>.sh` as the leader of a new process
|
|
51
|
+
* group (the task; its id, the sid, goes to `<task>.sid` through a rename) and watches it every
|
|
52
|
+
* 0.1 s, outside the group:
|
|
53
|
+
* - the command exits: its status as the shell gives it (`128 + signal` when killed) goes to
|
|
54
|
+
* `<task>.exit`, and what it left running in the group is SIGKILLed (the task ends when its
|
|
55
|
+
* command exits, as the poll does on Linux);
|
|
56
|
+
* - the time limit passes: 137 goes to `<task>.exit`, then the group is SIGKILLed (as
|
|
57
|
+
* `timeout -s KILL`);
|
|
58
|
+
* - a signal is requested in `g<sid>.ctl` ({@link SESSION_MODE_SCRIPT}'s `tk_kill`, read through
|
|
59
|
+
* a rename): the group gets it, and no exit file is written any more (a stop, as on Linux).
|
|
60
|
+
* It exits once the group is empty. Contains no single quote (it goes between single quotes).
|
|
61
|
+
*/
|
|
62
|
+
export declare const GROUP_LAUNCHER: string;
|
|
31
63
|
/**
|
|
32
64
|
* The shell of the launch exec: writes `command` (base64 in the script, so nothing is quoted by
|
|
33
65
|
* hand) to `.capybara/tasks/<id>.sh` and starts it with bash (the shell a foreground `Bash` call
|
|
34
|
-
* runs its command in)
|
|
35
|
-
* status written to `<id>.exit` and its output to
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
66
|
+
* runs its command in), detached from the exec under a hard time limit of `seconds` that SIGKILLs
|
|
67
|
+
* every process of the task, with its exit status written to `<id>.exit` and its output to
|
|
68
|
+
* `<id>.out`; the task's sid goes to `<id>.sid` and is printed. Where `pgrep` has `-s`
|
|
69
|
+
* ({@link SESSION_MODE_SCRIPT}) the command runs in a session of its own under
|
|
70
|
+
* `setsid nohup sh -c 'timeout -s KILL <seconds> …'` and the sid is `$!`, the pid `setsid` started;
|
|
71
|
+
* elsewhere (macOS: no `setsid`, no `timeout`, no `pgrep -s`) {@link GROUP_LAUNCHER} runs it in a
|
|
72
|
+
* process group of its own, watched by the launcher, and writes the sid (the group id) itself,
|
|
73
|
+
* which the launch waits for (up to 10 s). An
|
|
74
|
+
* environment without one of the needed programs fails with a readable error on stderr and exit
|
|
75
|
+
* code 127, before anything starts. `id` must be a task id and `seconds` a positive integer (both
|
|
76
|
+
* go into the script unquoted).
|
|
39
77
|
*/
|
|
40
78
|
export declare function launchScript(id: string, command: string, seconds: number): string;
|
|
41
79
|
/** The model-visible result of a launch (spec §2.1); `workspace`: the instance's workspace root. */
|