@ai-ecoverse/slicc-agent 3.8.0 → 3.10.0
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/README.md +69 -2
- package/dist/client.js +2 -1
- package/dist/client.js.map +2 -2
- package/dist/codemode/index.js +288 -0
- package/dist/codemode/index.js.map +7 -0
- package/dist/control.js +3 -2
- package/dist/control.js.map +2 -2
- package/dist/host.js +11 -2
- package/dist/host.js.map +2 -2
- package/dist/main.js +35 -4
- package/dist/main.js.map +2 -2
- package/dist/roles/frontmatter.js +61 -35
- package/dist/roles/frontmatter.js.map +3 -3
- package/dist/roles/roles.js +1 -0
- package/dist/roles/roles.js.map +2 -2
- package/dist/scoops/extension.js +11 -29
- package/dist/scoops/extension.js.map +2 -2
- package/dist/scoops/index.js +9 -4
- package/dist/scoops/index.js.map +2 -2
- package/dist/scoops/service.js.map +2 -2
- package/dist/services.js.map +2 -2
- package/dist/skills/index.js +172 -0
- package/dist/skills/index.js.map +7 -0
- package/dist/skills/skills.js +162 -0
- package/dist/skills/skills.js.map +7 -0
- package/dist/skills/templates.js +97 -0
- package/dist/skills/templates.js.map +7 -0
- package/dist/spectrum/agent-port.js +1 -1
- package/dist/spectrum/agent-port.js.map +2 -2
- package/dist/types/client.d.ts +2 -1
- package/dist/types/codemode/index.d.ts +37 -0
- package/dist/types/control.d.ts +2 -1
- package/dist/types/host.d.ts +2 -0
- package/dist/types/main.d.ts +2 -0
- package/dist/types/roles/roles.d.ts +1 -0
- package/dist/types/scoops/extension.d.ts +2 -8
- package/dist/types/scoops/index.d.ts +2 -1
- package/dist/types/scoops/service.d.ts +1 -0
- package/dist/types/services.d.ts +6 -0
- package/dist/types/skills/index.d.ts +45 -0
- package/dist/types/skills/skills.d.ts +32 -0
- package/dist/types/skills/templates.d.ts +18 -0
- package/package.json +4 -3
- package/packages/vfs-root/prompts/parallel-review.md +59 -0
- package/packages/vfs-root/prompts/review-loop.md +48 -0
- package/packages/vfs-root/skills/agent/SKILL.md +1 -1
- package/packages/vfs-root/skills/licks/SKILL.md +49 -0
- package/packages/vfs-root/skills/skill-authoring/SKILL.md +76 -0
package/dist/host.js
CHANGED
|
@@ -97,13 +97,21 @@ async function hostAgent(agent, options = {}) {
|
|
|
97
97
|
const deliveries = trackDeliveries(agent.harness, state, context);
|
|
98
98
|
provider.provide(
|
|
99
99
|
AgentControl,
|
|
100
|
-
createAgentControl(
|
|
100
|
+
createAgentControl(
|
|
101
|
+
agent.harness,
|
|
102
|
+
agent,
|
|
103
|
+
deliveries,
|
|
104
|
+
options.licks,
|
|
105
|
+
options.scoops,
|
|
106
|
+
options.skills
|
|
107
|
+
)
|
|
101
108
|
);
|
|
102
109
|
provider.provide(AgentTranscript, {
|
|
103
110
|
state,
|
|
104
111
|
deliveries: deliveries.state,
|
|
105
112
|
agents: mounted.agents,
|
|
106
|
-
views: mounted.views
|
|
113
|
+
views: mounted.views,
|
|
114
|
+
commands: options.skills?.commands ?? replicatedState([])
|
|
107
115
|
});
|
|
108
116
|
provider.provide(AgentSettings, options.settings ?? noSettings);
|
|
109
117
|
const host = {
|
|
@@ -127,6 +135,7 @@ async function hostAgent(agent, options = {}) {
|
|
|
127
135
|
deliveries.dispose();
|
|
128
136
|
transcript.dispose();
|
|
129
137
|
mounted.dispose();
|
|
138
|
+
await options.skills?.close(context);
|
|
130
139
|
await options.scoops?.runtime.close(context);
|
|
131
140
|
await options.licks?.sources.close(context);
|
|
132
141
|
await agent.close();
|
package/dist/host.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/host.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n type Context,\n createRemoteServiceEndpoint,\n RemoteServiceProvider,\n replicatedState,\n} from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { ConversationView } from '@earendil-works/pi-durable';\nimport {\n type RoutedServerServiceHost,\n type RoutedSessionAttachment,\n type RoutedSessionHandle,\n Server,\n type ServerHost,\n SessionNotFoundError,\n} from '@earendil-works/pi-server';\nimport type { Agent } from './agent.ts';\nimport { createAgentControl, type HostLicks, type HostScoops } from './control.ts';\nimport { trackDeliveries } from './deliveries.ts';\nimport { PortListener } from './listener.ts';\nimport {\n AGENT_SESSION,\n AgentControl,\n AgentSessions,\n AgentSettings,\n AgentTranscript,\n} from './services.ts';\nimport { agentViews } from './views.ts';\nimport type { PortEndpoint } from './wire.ts';\n\nexport interface AgentHost {\n readonly serverId: string;\n readonly agent: Agent;\n connect(endpoint: PortEndpoint): void;\n close(): Promise<void>;\n}\n\nfunction endpointFor(provider: RemoteServiceProvider): RoutedSessionAttachment {\n const endpoint = createRemoteServiceEndpoint(provider);\n return {\n invokeService: (call, publish, context) =>\n endpoint.invoke(call, (id, update) => publish(id, update, context), context),\n release: () => endpoint.dispose(),\n };\n}\n\nfunction sessionServices(provider: RemoteServiceProvider): RoutedSessionHandle {\n return {\n attachClient: () => endpointFor(provider),\n close: async () => {},\n };\n}\n\nfunction serverServices(): RoutedServerServiceHost {\n return {\n attachClient(presentation) {\n const provider = new RemoteServiceProvider([{ service: AgentSessions, mode: 'singleton' }]);\n provider.provide(AgentSessions, {\n attach: (sessionId, context) => presentation.attachSession(sessionId, context),\n detach: (context) => presentation.detachSession(context),\n });\n const attachment = endpointFor(provider);\n return {\n invokeService: attachment.invokeService,\n release(context) {\n attachment.release(context);\n provider.dispose();\n },\n };\n },\n };\n}\n\nconst noSettings: AgentSettings = {\n state: replicatedState({ models: [], accounts: [] }),\n connect: async () => {\n throw new Error('this agent has no accounts');\n },\n disconnect: async () => {},\n signIn: async () => null,\n};\n\nasync function follow(agent: Agent, context: Context) {\n let attached = await agent.cone().viewState(context);\n const state = replicatedState<ConversationView>(attached.value);\n const mirror = (value: ConversationView, from: Context) => state.replace(from, value);\n let off = attached.subscribe(mirror);\n const stop = agent.onCone(async (conversation) => {\n const next = await conversation.viewState(context);\n off();\n attached.dispose();\n attached = next;\n state.replace(context, next.value);\n off = next.subscribe(mirror);\n });\n return {\n state,\n dispose() {\n stop();\n off();\n attached.dispose();\n },\n };\n}\n\nexport async function hostAgent(\n agent: Agent,\n options: {\n serverId?: string;\n context?: Context;\n settings?: AgentSettings;\n licks?: HostLicks;\n scoops?: HostScoops;\n } = {}\n): Promise<AgentHost> {\n const context = options.context ?? BACKGROUND_CONTEXT;\n const serverId = options.serverId ?? crypto.randomUUID();\n const transcript = await follow(agent, context);\n const { state } = transcript;\n const mounted = await agentViews(agent, context);\n const provider = new RemoteServiceProvider([\n { service: AgentControl, mode: 'singleton' },\n { service: AgentTranscript, mode: 'singleton' },\n { service: AgentSettings, mode: 'singleton' },\n ]);\n const deliveries = trackDeliveries(agent.harness, state, context);\n provider.provide(\n AgentControl,\n createAgentControl(agent.harness
|
|
5
|
-
"mappings": "AAAA;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,0BAA0B;AAEnC;AAAA,EAIE;AAAA,EAEA;AAAA,OACK;AAEP,SAAS,0BAA2D;AACpE,SAAS,uBAAuB;AAChC,SAAS,oBAAoB;AAC7B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,
|
|
4
|
+
"sourcesContent": ["import {\n type Context,\n createRemoteServiceEndpoint,\n RemoteServiceProvider,\n replicatedState,\n} from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { ConversationView } from '@earendil-works/pi-durable';\nimport {\n type RoutedServerServiceHost,\n type RoutedSessionAttachment,\n type RoutedSessionHandle,\n Server,\n type ServerHost,\n SessionNotFoundError,\n} from '@earendil-works/pi-server';\nimport type { Agent } from './agent.ts';\nimport { createAgentControl, type HostLicks, type HostScoops } from './control.ts';\nimport { trackDeliveries } from './deliveries.ts';\nimport { PortListener } from './listener.ts';\nimport {\n AGENT_SESSION,\n AgentControl,\n AgentSessions,\n AgentSettings,\n AgentTranscript,\n type Command,\n} from './services.ts';\nimport type { SkillsRuntime } from './skills/index.ts';\nimport { agentViews } from './views.ts';\nimport type { PortEndpoint } from './wire.ts';\n\nexport interface AgentHost {\n readonly serverId: string;\n readonly agent: Agent;\n connect(endpoint: PortEndpoint): void;\n close(): Promise<void>;\n}\n\nfunction endpointFor(provider: RemoteServiceProvider): RoutedSessionAttachment {\n const endpoint = createRemoteServiceEndpoint(provider);\n return {\n invokeService: (call, publish, context) =>\n endpoint.invoke(call, (id, update) => publish(id, update, context), context),\n release: () => endpoint.dispose(),\n };\n}\n\nfunction sessionServices(provider: RemoteServiceProvider): RoutedSessionHandle {\n return {\n attachClient: () => endpointFor(provider),\n close: async () => {},\n };\n}\n\nfunction serverServices(): RoutedServerServiceHost {\n return {\n attachClient(presentation) {\n const provider = new RemoteServiceProvider([{ service: AgentSessions, mode: 'singleton' }]);\n provider.provide(AgentSessions, {\n attach: (sessionId, context) => presentation.attachSession(sessionId, context),\n detach: (context) => presentation.detachSession(context),\n });\n const attachment = endpointFor(provider);\n return {\n invokeService: attachment.invokeService,\n release(context) {\n attachment.release(context);\n provider.dispose();\n },\n };\n },\n };\n}\n\nconst noSettings: AgentSettings = {\n state: replicatedState({ models: [], accounts: [] }),\n connect: async () => {\n throw new Error('this agent has no accounts');\n },\n disconnect: async () => {},\n signIn: async () => null,\n};\n\nasync function follow(agent: Agent, context: Context) {\n let attached = await agent.cone().viewState(context);\n const state = replicatedState<ConversationView>(attached.value);\n const mirror = (value: ConversationView, from: Context) => state.replace(from, value);\n let off = attached.subscribe(mirror);\n const stop = agent.onCone(async (conversation) => {\n const next = await conversation.viewState(context);\n off();\n attached.dispose();\n attached = next;\n state.replace(context, next.value);\n off = next.subscribe(mirror);\n });\n return {\n state,\n dispose() {\n stop();\n off();\n attached.dispose();\n },\n };\n}\n\nexport async function hostAgent(\n agent: Agent,\n options: {\n serverId?: string;\n context?: Context;\n settings?: AgentSettings;\n licks?: HostLicks;\n scoops?: HostScoops;\n skills?: SkillsRuntime;\n } = {}\n): Promise<AgentHost> {\n const context = options.context ?? BACKGROUND_CONTEXT;\n const serverId = options.serverId ?? crypto.randomUUID();\n const transcript = await follow(agent, context);\n const { state } = transcript;\n const mounted = await agentViews(agent, context);\n const provider = new RemoteServiceProvider([\n { service: AgentControl, mode: 'singleton' },\n { service: AgentTranscript, mode: 'singleton' },\n { service: AgentSettings, mode: 'singleton' },\n ]);\n const deliveries = trackDeliveries(agent.harness, state, context);\n provider.provide(\n AgentControl,\n createAgentControl(\n agent.harness,\n agent,\n deliveries,\n options.licks,\n options.scoops,\n options.skills\n )\n );\n provider.provide(AgentTranscript, {\n state,\n deliveries: deliveries.state,\n agents: mounted.agents,\n views: mounted.views,\n commands: options.skills?.commands ?? replicatedState<Command[]>([]),\n });\n provider.provide(AgentSettings, options.settings ?? noSettings);\n const host: ServerHost = {\n serverServices: serverServices(),\n async resolveSession(sessionId) {\n if (sessionId !== AGENT_SESSION)\n throw new SessionNotFoundError(`unknown session ${sessionId}`);\n return { id: sessionId };\n },\n openSession: async () => sessionServices(provider),\n };\n const listener = new PortListener(serverId);\n const server = await new Server(host, { serverId, listeners: [listener] }).start();\n return {\n serverId,\n agent,\n connect: (endpoint) => listener.connect(endpoint),\n async close() {\n await server.close();\n provider.dispose();\n deliveries.dispose();\n transcript.dispose();\n mounted.dispose();\n await options.skills?.close(context);\n await options.scoops?.runtime.close(context);\n await options.licks?.sources.close(context);\n await agent.close();\n },\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/main.js
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
import { attachKernel } from "@ai-ecoverse/slicc-kernel";
|
|
2
2
|
import { BACKGROUND_CONTEXT } from "@earendil-works/chord/context";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
createRegistry
|
|
5
|
+
} from "@earendil-works/pi-durable";
|
|
4
6
|
import { CodingTools } from "@earendil-works/pi-durable/tools";
|
|
5
7
|
import { openAgent } from "./agent.js";
|
|
8
|
+
import {
|
|
9
|
+
codemodeExtension,
|
|
10
|
+
codemodeTool,
|
|
11
|
+
disabledBySettings,
|
|
12
|
+
locateWasm,
|
|
13
|
+
sandboxFactory
|
|
14
|
+
} from "./codemode/index.js";
|
|
6
15
|
import { EncryptedCredentialStore } from "./credentials.js";
|
|
7
16
|
import { hostAgent } from "./host.js";
|
|
8
17
|
import { createActivity } from "./kernel/activity.js";
|
|
@@ -12,13 +21,14 @@ import { setupLicks } from "./licks/index.js";
|
|
|
12
21
|
import { transportFetch } from "./net.js";
|
|
13
22
|
import { sliccPrompt } from "./prompt.js";
|
|
14
23
|
import { identity } from "./scoops/identity.js";
|
|
15
|
-
import { setupScoops } from "./scoops/index.js";
|
|
24
|
+
import { packageAssets, setupScoops } from "./scoops/index.js";
|
|
16
25
|
import {
|
|
17
26
|
createAgentSettings,
|
|
18
27
|
createSliccModels,
|
|
19
28
|
DEFAULT_MODEL,
|
|
20
29
|
sliccProviders
|
|
21
30
|
} from "./settings.js";
|
|
31
|
+
import { RELOAD_MS, setupSkills } from "./skills/index.js";
|
|
22
32
|
import { openOpfsSqliteStorage } from "./sqlite.js";
|
|
23
33
|
import { agentVersion, commandsOnPath, kernelBoot, transportName } from "./system.js";
|
|
24
34
|
import { kernelPort, serveConnections } from "./worker.js";
|
|
@@ -38,8 +48,23 @@ async function start(scope, port, options) {
|
|
|
38
48
|
const registry = createRegistry();
|
|
39
49
|
registry.install(CodingTools);
|
|
40
50
|
registry.install(sliccPrompt(facts));
|
|
51
|
+
const settings = await client.fs.readFile(`${HOME}/.pi/agent/settings.json`).catch(() => void 0);
|
|
52
|
+
const coding = CodingTools.tools;
|
|
53
|
+
const codemode = disabledBySettings(
|
|
54
|
+
settings === void 0 ? void 0 : new TextDecoder().decode(settings)
|
|
55
|
+
) ? [] : [
|
|
56
|
+
codemodeTool({
|
|
57
|
+
declared: coding,
|
|
58
|
+
sandbox: sandboxFactory(
|
|
59
|
+
options.codemodeWasm ?? (() => locateWasm(native, new URL(import.meta.url))),
|
|
60
|
+
options.codemodeWorker
|
|
61
|
+
)
|
|
62
|
+
})
|
|
63
|
+
];
|
|
64
|
+
registry.install(codemodeExtension(codemode));
|
|
41
65
|
const licks = setupLicks(registry);
|
|
42
|
-
const scoops = setupScoops(registry, licks.licks,
|
|
66
|
+
const scoops = setupScoops(registry, licks.licks, [...coding, ...codemode]);
|
|
67
|
+
const skills = setupSkills(registry, licks.licks);
|
|
43
68
|
const activity = createActivity();
|
|
44
69
|
const groups = processGroups(client);
|
|
45
70
|
const model = options.model ?? DEFAULT_MODEL;
|
|
@@ -64,6 +89,10 @@ async function start(scope, port, options) {
|
|
|
64
89
|
{ version: facts.version, boot: await kernelBoot(client) },
|
|
65
90
|
BACKGROUND_CONTEXT
|
|
66
91
|
);
|
|
92
|
+
const skillsRuntime = await skills.attach(
|
|
93
|
+
{ env: home, home: HOME, assets: options.assets ?? packageAssets(), reloadMs: RELOAD_MS },
|
|
94
|
+
BACKGROUND_CONTEXT
|
|
95
|
+
);
|
|
67
96
|
const runtime = await scoops.attach(
|
|
68
97
|
{
|
|
69
98
|
harness: agent.harness,
|
|
@@ -72,6 +101,7 @@ async function start(scope, port, options) {
|
|
|
72
101
|
env: home,
|
|
73
102
|
home: HOME,
|
|
74
103
|
alive: alive(client),
|
|
104
|
+
reads: skillsRuntime.dirs,
|
|
75
105
|
...options.assets ? { assets: options.assets } : {}
|
|
76
106
|
},
|
|
77
107
|
BACKGROUND_CONTEXT
|
|
@@ -79,7 +109,8 @@ async function start(scope, port, options) {
|
|
|
79
109
|
return hostAgent(agent, {
|
|
80
110
|
settings: await createAgentSettings(models, credentials, providers),
|
|
81
111
|
licks: { licks: licks.licks, sources },
|
|
82
|
-
scoops: { scoops: scoops.scoops, runtime }
|
|
112
|
+
scoops: { scoops: scoops.scoops, runtime },
|
|
113
|
+
skills: skillsRuntime
|
|
83
114
|
});
|
|
84
115
|
}
|
|
85
116
|
function alive(client) {
|
package/dist/main.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/main.ts"],
|
|
4
|
-
"sourcesContent": ["import { attachKernel } from '@ai-ecoverse/slicc-kernel';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { CredentialStore, Provider } from '@earendil-works/pi-ai';\nimport {
|
|
5
|
-
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,0BAA0B;AAEnC,
|
|
4
|
+
"sourcesContent": ["import { attachKernel } from '@ai-ecoverse/slicc-kernel';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { CredentialStore, Provider } from '@earendil-works/pi-ai';\nimport {\n createRegistry,\n type ModelRef,\n type Storage,\n type ToolRegistration,\n} from '@earendil-works/pi-durable';\nimport { CodingTools } from '@earendil-works/pi-durable/tools';\nimport { type Agent, openAgent } from './agent.ts';\nimport {\n codemodeExtension,\n codemodeTool,\n disabledBySettings,\n locateWasm,\n sandboxFactory,\n} from './codemode/index.ts';\nimport { EncryptedCredentialStore } from './credentials.ts';\nimport { type AgentHost, hostAgent } from './host.ts';\nimport { createActivity } from './kernel/activity.ts';\nimport type { KernelClient } from './kernel/client.ts';\nimport { HOME, kernelEnvironment, SliccKernelEnv } from './kernel/env.ts';\nimport { processGroups } from './kernel/groups.ts';\nimport { setupLicks } from './licks/index.ts';\nimport { type Transport, transportFetch } from './net.ts';\nimport { sliccPrompt } from './prompt.ts';\nimport { identity } from './scoops/identity.ts';\nimport { type Assets, packageAssets, setupScoops } from './scoops/index.ts';\nimport {\n createAgentSettings,\n createSliccModels,\n DEFAULT_MODEL,\n sliccProviders,\n} from './settings.ts';\nimport { RELOAD_MS, setupSkills } from './skills/index.ts';\nimport { openOpfsSqliteStorage } from './sqlite.ts';\nimport { agentVersion, commandsOnPath, kernelBoot, transportName } from './system.ts';\nimport { kernelPort, serveConnections, type WorkerScope } from './worker.ts';\n\nexport interface AgentWorkerScope extends WorkerScope {\n fetch: typeof fetch;\n location: { origin: string };\n}\n\nexport type KernelAttach = (port: MessagePort) => Promise<KernelClient & { transport: Transport }>;\n\nexport interface AgentWorkerOptions {\n model?: ModelRef;\n providers?: Provider[];\n attach?: KernelAttach;\n credentials?: () => Promise<CredentialStore>;\n storage?: () => Promise<Storage>;\n assets?: Assets;\n codemodeWasm?: () => Promise<WebAssembly.Module | undefined>;\n codemodeWorker?: string | URL;\n}\n\nasync function start(\n scope: AgentWorkerScope,\n port: Promise<MessagePort>,\n options: AgentWorkerOptions\n): Promise<AgentHost> {\n const attach: KernelAttach = options.attach ?? attachKernel;\n const client = await attach(await port);\n const native = scope.fetch.bind(scope);\n scope.fetch = transportFetch(client.transport, scope.location.origin, native);\n const facts = {\n version: await agentVersion((url) => native(url)),\n commands: await commandsOnPath(client),\n transport: transportName(client.transport),\n };\n const credentials = await (options.credentials ?? (() => EncryptedCredentialStore.open()))();\n const providers = options.providers ?? sliccProviders();\n const models = createSliccModels(credentials, providers);\n const registry = createRegistry();\n registry.install(CodingTools);\n registry.install(sliccPrompt(facts));\n const settings = await client.fs\n .readFile(`${HOME}/.pi/agent/settings.json`)\n .catch(() => undefined);\n const coding = CodingTools.tools as readonly ToolRegistration[];\n const codemode = disabledBySettings(\n settings === undefined ? undefined : new TextDecoder().decode(settings)\n )\n ? []\n : [\n codemodeTool({\n declared: coding,\n sandbox: sandboxFactory(\n options.codemodeWasm ?? (() => locateWasm(native, new URL(import.meta.url))),\n options.codemodeWorker\n ),\n }),\n ];\n registry.install(codemodeExtension(codemode));\n const licks = setupLicks(registry);\n const scoops = setupScoops(registry, licks.licks, [...coding, ...codemode]);\n const skills = setupSkills(registry, licks.licks);\n const activity = createActivity();\n const groups = processGroups(client);\n const model = options.model ?? DEFAULT_MODEL;\n let opened: Agent | undefined;\n const environment = kernelEnvironment(client, {\n activity,\n groups,\n identify: identity(() => opened?.agents, model),\n });\n const agent = await openAgent({\n models,\n model,\n storage: await (options.storage ?? (() => openOpfsSqliteStorage()))(),\n registry,\n env: environment,\n });\n opened = agent;\n const home = new SliccKernelEnv(client, { cwd: HOME });\n const sources = licks.attach(agent, { env: home, home: HOME, activity });\n await sources.start(BACKGROUND_CONTEXT);\n await sources.boot(\n { version: facts.version, boot: await kernelBoot(client) },\n BACKGROUND_CONTEXT\n );\n const skillsRuntime = await skills.attach(\n { env: home, home: HOME, assets: options.assets ?? packageAssets(), reloadMs: RELOAD_MS },\n BACKGROUND_CONTEXT\n );\n const runtime = await scoops.attach(\n {\n harness: agent.harness,\n agents: agent.agents,\n groups,\n env: home,\n home: HOME,\n alive: alive(client),\n reads: skillsRuntime.dirs,\n ...(options.assets ? { assets: options.assets } : {}),\n },\n BACKGROUND_CONTEXT\n );\n return hostAgent(agent, {\n settings: await createAgentSettings(models, credentials, providers),\n licks: { licks: licks.licks, sources },\n scoops: { scoops: scoops.scoops, runtime },\n skills: skillsRuntime,\n });\n}\n\nexport function alive(client: KernelClient) {\n return async (pid: number): Promise<boolean> => {\n if (!client.ps) return true;\n return (await client.ps()).some((process) => process.pid === pid);\n };\n}\n\nexport function runAgentWorker(\n scope: AgentWorkerScope,\n options: AgentWorkerOptions = {}\n): Promise<AgentHost> {\n const host = start(scope, kernelPort(scope), options);\n host.catch(() => undefined);\n serveConnections(scope, host);\n return host;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -11,47 +11,73 @@ function scalar(raw) {
|
|
|
11
11
|
if (/^-?\d+(\.\d+)?$/.test(value)) return Number(value);
|
|
12
12
|
return unquote(value);
|
|
13
13
|
}
|
|
14
|
+
const BLOCK = /^([|>])([+-]?)$/;
|
|
15
|
+
function blockValue(block) {
|
|
16
|
+
const indents = block.lines.filter((line2) => line2.trim()).map((line2) => /^\s*/.exec(line2)[0].length);
|
|
17
|
+
const indent = indents.length ? Math.min(...indents) : 0;
|
|
18
|
+
const lines = block.lines.map((line2) => line2.slice(indent));
|
|
19
|
+
while (lines.length && !lines.at(-1)?.trim()) lines.pop();
|
|
20
|
+
const text = block.folded ? lines.reduce(
|
|
21
|
+
(out, line2) => !line2.trim() ? `${out}
|
|
22
|
+
` : out && !out.endsWith("\n") ? `${out} ${line2}` : `${out}${line2}`,
|
|
23
|
+
""
|
|
24
|
+
) : lines.join("\n");
|
|
25
|
+
return block.strip || !text ? text : `${text}
|
|
26
|
+
`;
|
|
27
|
+
}
|
|
28
|
+
function pair(state, line2) {
|
|
29
|
+
const found = /^([A-Za-z][\w-]*):(?:\s+(.*))?$/.exec(line2);
|
|
30
|
+
state.list = void 0;
|
|
31
|
+
if (!found) {
|
|
32
|
+
state.problems.push(`can't read the line "${line2.trim()}"`);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const key = found[1];
|
|
36
|
+
const value = found[2]?.trim() ?? "";
|
|
37
|
+
const style = BLOCK.exec(value);
|
|
38
|
+
if (style) state.block = { key, folded: style[1] === ">", strip: style[2] === "-", lines: [] };
|
|
39
|
+
else if (value === "") {
|
|
40
|
+
state.fields[key] = [];
|
|
41
|
+
state.list = key;
|
|
42
|
+
} else state.fields[key] = scalar(value);
|
|
43
|
+
}
|
|
44
|
+
function line(state, text) {
|
|
45
|
+
const { block, list } = state;
|
|
46
|
+
if (block && (!text.trim() || /^\s/.test(text))) {
|
|
47
|
+
block.lines.push(text);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (block) state.fields[block.key] = blockValue(block);
|
|
51
|
+
state.block = void 0;
|
|
52
|
+
if (!text.trim() || text.trimStart().startsWith("#")) return;
|
|
53
|
+
const item = /^\s+-\s+(.*)$/.exec(text);
|
|
54
|
+
if (item && list) state.fields[list].push(unquote(item[1].trim()));
|
|
55
|
+
else if (/^\s/.test(text) && list) state.nested.add(list);
|
|
56
|
+
else pair(state, text);
|
|
57
|
+
}
|
|
14
58
|
function parseFrontmatter(text) {
|
|
15
59
|
const normalized = text.replace(/\r\n/g, "\n");
|
|
16
60
|
const match = /^---\n([\s\S]*?)\n---(?:\n|$)/.exec(normalized);
|
|
17
61
|
if (!match)
|
|
18
62
|
return { fields: {}, body: normalized.trim(), problems: ["no frontmatter between --- lines"] };
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
nested.add(list);
|
|
32
|
-
continue;
|
|
33
|
-
}
|
|
34
|
-
const pair = /^([A-Za-z][\w-]*):(?:\s+(.*))?$/.exec(line);
|
|
35
|
-
if (!pair) {
|
|
36
|
-
problems.push(`can't read the line "${line.trim()}"`);
|
|
37
|
-
list = void 0;
|
|
38
|
-
continue;
|
|
39
|
-
}
|
|
40
|
-
const key = pair[1];
|
|
41
|
-
const value = pair[2]?.trim() ?? "";
|
|
42
|
-
if (value === "") {
|
|
43
|
-
fields[key] = [];
|
|
44
|
-
list = key;
|
|
45
|
-
} else {
|
|
46
|
-
fields[key] = scalar(value);
|
|
47
|
-
list = void 0;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
for (const key of nested) {
|
|
51
|
-
delete fields[key];
|
|
52
|
-
problems.push(`"${key}" has nested values, which SLICC doesn't read`);
|
|
63
|
+
const state = {
|
|
64
|
+
fields: {},
|
|
65
|
+
problems: [],
|
|
66
|
+
nested: /* @__PURE__ */ new Set(),
|
|
67
|
+
list: void 0,
|
|
68
|
+
block: void 0
|
|
69
|
+
};
|
|
70
|
+
for (const text2 of match[1].split("\n")) line(state, text2);
|
|
71
|
+
if (state.block) state.fields[state.block.key] = blockValue(state.block);
|
|
72
|
+
for (const key of state.nested) {
|
|
73
|
+
delete state.fields[key];
|
|
74
|
+
state.problems.push(`"${key}" has nested values, which SLICC doesn't read`);
|
|
53
75
|
}
|
|
54
|
-
return {
|
|
76
|
+
return {
|
|
77
|
+
fields: state.fields,
|
|
78
|
+
body: normalized.slice(match[0].length).trim(),
|
|
79
|
+
problems: state.problems
|
|
80
|
+
};
|
|
55
81
|
}
|
|
56
82
|
export {
|
|
57
83
|
parseFrontmatter
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/roles/frontmatter.ts"],
|
|
4
|
-
"sourcesContent": ["export type FrontmatterValue = string | number | boolean | string[];\n\nexport interface Frontmatter {\n fields: Record<string, FrontmatterValue>;\n body: string;\n problems: string[];\n}\n\nfunction unquote(value: string): string {\n const quoted = /^([\"'])(.*)\\1$/s.exec(value);\n if (!quoted) return value;\n return quoted[1] === '\"'\n ? (quoted[2] as string).replace(/\\\\([\"\\\\])/g, '$1')\n : (quoted[2] as string).replace(/''/g, \"'\");\n}\n\nfunction scalar(raw: string): FrontmatterValue {\n const value = raw.trim();\n if (/^\\[.*\\]$/s.test(value))\n return value\n .slice(1, -1)\n .split(',')\n .map((item) => unquote(item.trim()))\n .filter(Boolean);\n if (value === 'true' || value === 'false') return value === 'true';\n if (/^-?\\d+(\\.\\d+)?$/.test(value)) return Number(value);\n return unquote(value);\n}\n\
|
|
5
|
-
"mappings": "AAQA,SAAS,QAAQ,OAAuB;AACtC,QAAM,SAAS,kBAAkB,KAAK,KAAK;AAC3C,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,OAAO,CAAC,MAAM,MAChB,OAAO,CAAC,EAAa,QAAQ,cAAc,IAAI,IAC/C,OAAO,CAAC,EAAa,QAAQ,OAAO,GAAG;AAC9C;AAEA,SAAS,OAAO,KAA+B;AAC7C,QAAM,QAAQ,IAAI,KAAK;AACvB,MAAI,YAAY,KAAK,KAAK;AACxB,WAAO,MACJ,MAAM,GAAG,EAAE,EACX,MAAM,GAAG,EACT,IAAI,CAAC,SAAS,QAAQ,KAAK,KAAK,CAAC,CAAC,EAClC,OAAO,OAAO;AACnB,MAAI,UAAU,UAAU,UAAU,QAAS,QAAO,UAAU;AAC5D,MAAI,kBAAkB,KAAK,KAAK,EAAG,QAAO,OAAO,KAAK;AACtD,SAAO,QAAQ,KAAK;AACtB;
|
|
6
|
-
"names": []
|
|
4
|
+
"sourcesContent": ["export type FrontmatterValue = string | number | boolean | string[];\n\nexport interface Frontmatter {\n fields: Record<string, FrontmatterValue>;\n body: string;\n problems: string[];\n}\n\nfunction unquote(value: string): string {\n const quoted = /^([\"'])(.*)\\1$/s.exec(value);\n if (!quoted) return value;\n return quoted[1] === '\"'\n ? (quoted[2] as string).replace(/\\\\([\"\\\\])/g, '$1')\n : (quoted[2] as string).replace(/''/g, \"'\");\n}\n\nfunction scalar(raw: string): FrontmatterValue {\n const value = raw.trim();\n if (/^\\[.*\\]$/s.test(value))\n return value\n .slice(1, -1)\n .split(',')\n .map((item) => unquote(item.trim()))\n .filter(Boolean);\n if (value === 'true' || value === 'false') return value === 'true';\n if (/^-?\\d+(\\.\\d+)?$/.test(value)) return Number(value);\n return unquote(value);\n}\n\ntype Block = { key: string; folded: boolean; strip: boolean; lines: string[] };\n\nconst BLOCK = /^([|>])([+-]?)$/;\n\nfunction blockValue(block: Block): string {\n const indents = block.lines\n .filter((line) => line.trim())\n .map((line) => (/^\\s*/.exec(line) as RegExpExecArray)[0].length);\n const indent = indents.length ? Math.min(...indents) : 0;\n const lines = block.lines.map((line) => line.slice(indent));\n while (lines.length && !lines.at(-1)?.trim()) lines.pop();\n const text = block.folded\n ? lines.reduce(\n (out, line) =>\n !line.trim()\n ? `${out}\\n`\n : out && !out.endsWith('\\n')\n ? `${out} ${line}`\n : `${out}${line}`,\n ''\n )\n : lines.join('\\n');\n return block.strip || !text ? text : `${text}\\n`;\n}\n\ntype State = {\n fields: Record<string, FrontmatterValue>;\n problems: string[];\n nested: Set<string>;\n list: string | undefined;\n block: Block | undefined;\n};\n\nfunction pair(state: State, line: string): void {\n const found = /^([A-Za-z][\\w-]*):(?:\\s+(.*))?$/.exec(line);\n state.list = undefined;\n if (!found) {\n state.problems.push(`can't read the line \"${line.trim()}\"`);\n return;\n }\n const key = found[1] as string;\n const value = found[2]?.trim() ?? '';\n const style = BLOCK.exec(value);\n if (style) state.block = { key, folded: style[1] === '>', strip: style[2] === '-', lines: [] };\n else if (value === '') {\n state.fields[key] = [];\n state.list = key;\n } else state.fields[key] = scalar(value);\n}\n\nfunction line(state: State, text: string): void {\n const { block, list } = state;\n if (block && (!text.trim() || /^\\s/.test(text))) {\n block.lines.push(text);\n return;\n }\n if (block) state.fields[block.key] = blockValue(block);\n state.block = undefined;\n if (!text.trim() || text.trimStart().startsWith('#')) return;\n const item = /^\\s+-\\s+(.*)$/.exec(text);\n if (item && list) (state.fields[list] as string[]).push(unquote((item[1] as string).trim()));\n else if (/^\\s/.test(text) && list) state.nested.add(list);\n else pair(state, text);\n}\n\nexport function parseFrontmatter(text: string): Frontmatter {\n const normalized = text.replace(/\\r\\n/g, '\\n');\n const match = /^---\\n([\\s\\S]*?)\\n---(?:\\n|$)/.exec(normalized);\n if (!match)\n return { fields: {}, body: normalized.trim(), problems: ['no frontmatter between --- lines'] };\n const state: State = {\n fields: {},\n problems: [],\n nested: new Set(),\n list: undefined,\n block: undefined,\n };\n for (const text of (match[1] as string).split('\\n')) line(state, text);\n if (state.block) state.fields[state.block.key] = blockValue(state.block);\n for (const key of state.nested) {\n delete state.fields[key];\n state.problems.push(`\"${key}\" has nested values, which SLICC doesn't read`);\n }\n return {\n fields: state.fields,\n body: normalized.slice(match[0].length).trim(),\n problems: state.problems,\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["line", "text"]
|
|
7
7
|
}
|
package/dist/roles/roles.js
CHANGED
package/dist/roles/roles.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/roles/roles.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport type { ExecutionEnv } from '@earendil-works/pi-durable/env';\nimport { type FrontmatterValue, parseFrontmatter } from './frontmatter.ts';\n\nexport type RoleSource = 'builtin' | 'package' | 'user' | 'project';\nexport type Thinking = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';\n\nexport interface Role {\n name: string;\n description: string;\n prompt: string;\n mode: 'replace' | 'append';\n tools?: string[];\n model?: string;\n thinking?: Thinking;\n aliases: string[];\n output?: string;\n source: RoleSource;\n path: string;\n}\n\nexport interface Roles {\n roles: Role[];\n warnings: string[];\n limits: { maxLiveScoops: number; maxPerTurn: number };\n}\n\nexport const DEFAULT_LIMITS = { maxLiveScoops: 16, maxPerTurn: 64 };\n\nconst TOOLS: Record<string, string> = {\n read: 'read',\n write: 'write',\n edit: 'edit',\n bash: 'bash',\n grep: 'bash',\n find: 'bash',\n ls: 'bash',\n};\n\nconst THINKING = new Set<string>(['off', 'minimal', 'low', 'medium', 'high', 'xhigh']);\n\nconst APPLIED = new Set([\n 'name',\n 'description',\n 'tools',\n 'model',\n 'thinking',\n 'systemPromptMode',\n 'aliases',\n 'output',\n 'package',\n 'advertise',\n 'inheritProjectContext',\n 'inheritSkills',\n 'skills',\n 'defaultReads',\n]);\n\nconst LATER: Record<string, string> = {\n memory: 'per-agent memory comes with SLICC\u2019s memory panel',\n};\n\nexport type RoleFiles = Pick<ExecutionEnv, 'readTextFile' | 'listDir'>;\n\nexport interface RoleSourceDir {\n source: RoleSource;\n dir: string;\n}\n\nfunction list(value: FrontmatterValue | undefined): string[] {\n if (Array.isArray(value)) return value;\n if (typeof value === 'string')\n return value\n .split(',')\n .map((item) => item.trim())\n .filter(Boolean);\n return [];\n}\n\nfunction tools(names: string[], where: string, warnings: string[]): string[] {\n const mapped: string[] = [];\n for (const name of names) {\n const tool = TOOLS[name];\n if (tool) {\n if (!mapped.includes(tool)) mapped.push(tool);\n } else warnings.push(`${where}: tool \"${name}\" isn't available in SLICC; it's left out`);\n }\n return mapped;\n}\n\nexport function parseRole(\n text: string,\n source: RoleSource,\n path: string,\n warnings: string[]\n): Role | undefined {\n const { fields, body, problems } = parseFrontmatter(text);\n for (const problem of problems) warnings.push(`${path}: ${problem}`);\n const name = fields.name;\n const description = fields.description;\n if (typeof name !== 'string' || typeof description !== 'string') {\n warnings.push(`${path}: an agent file needs a name and a description; skipped`);\n return undefined;\n }\n for (const key of Object.keys(fields))\n if (!APPLIED.has(key))\n warnings.push(\n `${path}: \"${key}\" ${LATER[key] ? `is not read yet (${LATER[key]})` : \"isn't supported in SLICC; it's ignored\"}`\n );\n const thinking =\n typeof fields.thinking === 'string' && THINKING.has(fields.thinking)\n ? (fields.thinking as Thinking)\n : undefined;\n if (fields.thinking !== undefined && !thinking)\n warnings.push(`${path}: thinking \"${String(fields.thinking)}\" is unknown; ignored`);\n const pkg = typeof fields.package === 'string' && fields.package ? `${fields.package}.` : '';\n return {\n name: `${pkg}${name}`,\n description,\n prompt: body,\n mode: fields.systemPromptMode === 'append' ? 'append' : 'replace',\n ...(fields.tools !== undefined ? { tools: tools(list(fields.tools), path, warnings) } : {}),\n ...(typeof fields.model === 'string' ? { model: fields.model } : {}),\n ...(thinking ? { thinking } : {}),\n aliases: list(fields.aliases),\n ...(typeof fields.output === 'string' ? { output: fields.output } : {}),\n source,\n path,\n };\n}\n\nasync function markdown(\n files: RoleFiles,\n dir: string,\n context: Context,\n depth = 0\n): Promise<string[]> {\n if (dir.endsWith('.md')) return [dir];\n const listed = await files.listDir(dir, context);\n if (!listed.ok || depth > 4) return [];\n const out: string[] = [];\n for (const info of listed.value) {\n const path = `${dir}/${info.name}`;\n if (info.kind === 'directory') out.push(...(await markdown(files, path, context, depth + 1)));\n else if (info.name.endsWith('.md') && !info.name.endsWith('.chain.md')) out.push(path);\n }\n return out.sort();\n}\n\ntype Override = {\n model?: unknown;\n thinking?: unknown;\n tools?: unknown;\n systemPrompt?: unknown;\n description?: unknown;\n disabled?: unknown;\n};\n\ninterface Settings {\n overrides: Record<string, Override>;\n limits: Roles['limits'];\n}\n\nfunction positive(value: unknown, fallback: number): number {\n return typeof value === 'number' && Number.isInteger(value) && value > 0 ? value : fallback;\n}\n\nasync function settings(\n files: RoleFiles,\n path: string,\n context: Context,\n warnings: string[]\n): Promise<Settings> {\n const read = await files.readTextFile(path, context);\n const empty = { overrides: {}, limits: { ...DEFAULT_LIMITS } };\n if (!read.ok) return empty;\n let parsed: {\n subagents?: {\n agentOverrides?: Record<string, Override>;\n maxLiveScoops?: unknown;\n maxPerTurn?: unknown;\n };\n };\n try {\n parsed = JSON.parse(read.value);\n } catch (error) {\n warnings.push(`${path}: not valid JSON (${(error as Error).message}); overrides ignored`);\n return empty;\n }\n const subagents = parsed.subagents ?? {};\n return {\n overrides: subagents.agentOverrides ?? {},\n limits: {\n maxLiveScoops: positive(subagents.maxLiveScoops, DEFAULT_LIMITS.maxLiveScoops),\n maxPerTurn: positive(subagents.maxPerTurn, DEFAULT_LIMITS.maxPerTurn),\n },\n };\n}\n\nfunction apply(role: Role, override: Override | undefined, warnings: string[]): Role | undefined {\n if (!override) return role;\n if (override.disabled === true) return undefined;\n const next: Role = { ...role };\n if (typeof override.model === 'string') next.model = override.model;\n if (typeof override.thinking === 'string' && THINKING.has(override.thinking))\n next.thinking = override.thinking as Thinking;\n if (typeof override.description === 'string') next.description = override.description;\n if (typeof override.systemPrompt === 'string') next.prompt = override.systemPrompt;\n if (Array.isArray(override.tools))\n next.tools = tools(override.tools.map(String), `override for ${role.name}`, warnings);\n return next;\n}\n\nexport interface LoadOptions {\n files: RoleFiles;\n builtin: () => Promise<{ path: string; text: string }[]>;\n dirs: RoleSourceDir[];\n settingsPath: string;\n}\n\nconst ORDER: RoleSource[] = ['builtin', 'package', 'user', 'project'];\n\nexport async function loadRoles(options: LoadOptions, context: Context): Promise<Roles> {\n const warnings: string[] = [];\n const byName = new Map<string, Role>();\n const add = (role: Role | undefined) => {\n if (role) byName.set(role.name, role);\n };\n for (const { path, text } of await options.builtin())\n add(parseRole(text, 'builtin', path, warnings));\n const dirs = [...options.dirs].sort((a, b) => ORDER.indexOf(a.source) - ORDER.indexOf(b.source));\n for (const { source, dir } of dirs)\n for (const path of await markdown(options.files, dir, context)) {\n const read = await options.files.readTextFile(path, context);\n if (read.ok) add(parseRole(read.value, source, path, warnings));\n }\n const { overrides, limits } = await settings(\n options.files,\n options.settingsPath,\n context,\n warnings\n );\n const roles: Role[] = [];\n for (const role of byName.values()) {\n const applied = apply(role, overrides[role.name], warnings);\n if (applied) roles.push(applied);\n }\n return { roles, warnings, limits };\n}\n\nexport function findRole(roles: readonly Role[], name: string): Role | undefined {\n return (\n roles.find((role) => role.name === name) ?? roles.find((role) => role.aliases.includes(name))\n );\n}\n\
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport type { ExecutionEnv } from '@earendil-works/pi-durable/env';\nimport { type FrontmatterValue, parseFrontmatter } from './frontmatter.ts';\n\nexport type RoleSource = 'builtin' | 'package' | 'user' | 'project';\nexport type Thinking = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';\n\nexport interface Role {\n name: string;\n description: string;\n prompt: string;\n mode: 'replace' | 'append';\n tools?: string[];\n model?: string;\n thinking?: Thinking;\n aliases: string[];\n output?: string;\n source: RoleSource;\n path: string;\n}\n\nexport interface Roles {\n roles: Role[];\n warnings: string[];\n limits: { maxLiveScoops: number; maxPerTurn: number };\n}\n\nexport const DEFAULT_LIMITS = { maxLiveScoops: 16, maxPerTurn: 64 };\n\nconst TOOLS: Record<string, string> = {\n read: 'read',\n write: 'write',\n edit: 'edit',\n bash: 'bash',\n grep: 'bash',\n find: 'bash',\n ls: 'bash',\n};\n\nconst THINKING = new Set<string>(['off', 'minimal', 'low', 'medium', 'high', 'xhigh']);\n\nconst APPLIED = new Set([\n 'name',\n 'description',\n 'tools',\n 'model',\n 'thinking',\n 'systemPromptMode',\n 'aliases',\n 'output',\n 'package',\n 'advertise',\n 'inheritProjectContext',\n 'inheritSkills',\n 'skills',\n 'defaultReads',\n]);\n\nconst LATER: Record<string, string> = {\n memory: 'per-agent memory comes with SLICC\u2019s memory panel',\n};\n\nexport type RoleFiles = Pick<ExecutionEnv, 'readTextFile' | 'listDir'>;\n\nexport interface RoleSourceDir {\n source: RoleSource;\n dir: string;\n}\n\nfunction list(value: FrontmatterValue | undefined): string[] {\n if (Array.isArray(value)) return value;\n if (typeof value === 'string')\n return value\n .split(',')\n .map((item) => item.trim())\n .filter(Boolean);\n return [];\n}\n\nfunction tools(names: string[], where: string, warnings: string[]): string[] {\n const mapped: string[] = [];\n for (const name of names) {\n const tool = TOOLS[name];\n if (tool) {\n if (!mapped.includes(tool)) mapped.push(tool);\n } else warnings.push(`${where}: tool \"${name}\" isn't available in SLICC; it's left out`);\n }\n return mapped;\n}\n\nexport function parseRole(\n text: string,\n source: RoleSource,\n path: string,\n warnings: string[]\n): Role | undefined {\n const { fields, body, problems } = parseFrontmatter(text);\n for (const problem of problems) warnings.push(`${path}: ${problem}`);\n const name = fields.name;\n const description = fields.description;\n if (typeof name !== 'string' || typeof description !== 'string') {\n warnings.push(`${path}: an agent file needs a name and a description; skipped`);\n return undefined;\n }\n for (const key of Object.keys(fields))\n if (!APPLIED.has(key))\n warnings.push(\n `${path}: \"${key}\" ${LATER[key] ? `is not read yet (${LATER[key]})` : \"isn't supported in SLICC; it's ignored\"}`\n );\n const thinking =\n typeof fields.thinking === 'string' && THINKING.has(fields.thinking)\n ? (fields.thinking as Thinking)\n : undefined;\n if (fields.thinking !== undefined && !thinking)\n warnings.push(`${path}: thinking \"${String(fields.thinking)}\" is unknown; ignored`);\n const pkg = typeof fields.package === 'string' && fields.package ? `${fields.package}.` : '';\n return {\n name: `${pkg}${name}`,\n description,\n prompt: body,\n mode: fields.systemPromptMode === 'append' ? 'append' : 'replace',\n ...(fields.tools !== undefined ? { tools: tools(list(fields.tools), path, warnings) } : {}),\n ...(typeof fields.model === 'string' ? { model: fields.model } : {}),\n ...(thinking ? { thinking } : {}),\n aliases: list(fields.aliases),\n ...(typeof fields.output === 'string' ? { output: fields.output } : {}),\n source,\n path,\n };\n}\n\nasync function markdown(\n files: RoleFiles,\n dir: string,\n context: Context,\n depth = 0\n): Promise<string[]> {\n if (dir.endsWith('.md')) return [dir];\n const listed = await files.listDir(dir, context);\n if (!listed.ok || depth > 4) return [];\n const out: string[] = [];\n for (const info of listed.value) {\n const path = `${dir}/${info.name}`;\n if (info.kind === 'directory') out.push(...(await markdown(files, path, context, depth + 1)));\n else if (info.name.endsWith('.md') && !info.name.endsWith('.chain.md')) out.push(path);\n }\n return out.sort();\n}\n\ntype Override = {\n model?: unknown;\n thinking?: unknown;\n tools?: unknown;\n systemPrompt?: unknown;\n description?: unknown;\n disabled?: unknown;\n};\n\ninterface Settings {\n overrides: Record<string, Override>;\n limits: Roles['limits'];\n}\n\nfunction positive(value: unknown, fallback: number): number {\n return typeof value === 'number' && Number.isInteger(value) && value > 0 ? value : fallback;\n}\n\nasync function settings(\n files: RoleFiles,\n path: string,\n context: Context,\n warnings: string[]\n): Promise<Settings> {\n const read = await files.readTextFile(path, context);\n const empty = { overrides: {}, limits: { ...DEFAULT_LIMITS } };\n if (!read.ok) return empty;\n let parsed: {\n subagents?: {\n agentOverrides?: Record<string, Override>;\n maxLiveScoops?: unknown;\n maxPerTurn?: unknown;\n };\n };\n try {\n parsed = JSON.parse(read.value);\n } catch (error) {\n warnings.push(`${path}: not valid JSON (${(error as Error).message}); overrides ignored`);\n return empty;\n }\n const subagents = parsed.subagents ?? {};\n return {\n overrides: subagents.agentOverrides ?? {},\n limits: {\n maxLiveScoops: positive(subagents.maxLiveScoops, DEFAULT_LIMITS.maxLiveScoops),\n maxPerTurn: positive(subagents.maxPerTurn, DEFAULT_LIMITS.maxPerTurn),\n },\n };\n}\n\nfunction apply(role: Role, override: Override | undefined, warnings: string[]): Role | undefined {\n if (!override) return role;\n if (override.disabled === true) return undefined;\n const next: Role = { ...role };\n if (typeof override.model === 'string') next.model = override.model;\n if (typeof override.thinking === 'string' && THINKING.has(override.thinking))\n next.thinking = override.thinking as Thinking;\n if (typeof override.description === 'string') next.description = override.description;\n if (typeof override.systemPrompt === 'string') next.prompt = override.systemPrompt;\n if (Array.isArray(override.tools))\n next.tools = tools(override.tools.map(String), `override for ${role.name}`, warnings);\n return next;\n}\n\nexport interface LoadOptions {\n files: RoleFiles;\n builtin: () => Promise<{ path: string; text: string }[]>;\n dirs: RoleSourceDir[];\n settingsPath: string;\n}\n\nconst ORDER: RoleSource[] = ['builtin', 'package', 'user', 'project'];\n\nexport async function loadRoles(options: LoadOptions, context: Context): Promise<Roles> {\n const warnings: string[] = [];\n const byName = new Map<string, Role>();\n const add = (role: Role | undefined) => {\n if (role) byName.set(role.name, role);\n };\n for (const { path, text } of await options.builtin())\n add(parseRole(text, 'builtin', path, warnings));\n const dirs = [...options.dirs].sort((a, b) => ORDER.indexOf(a.source) - ORDER.indexOf(b.source));\n for (const { source, dir } of dirs)\n for (const path of await markdown(options.files, dir, context)) {\n const read = await options.files.readTextFile(path, context);\n if (read.ok) add(parseRole(read.value, source, path, warnings));\n }\n const { overrides, limits } = await settings(\n options.files,\n options.settingsPath,\n context,\n warnings\n );\n const roles: Role[] = [];\n for (const role of byName.values()) {\n const applied = apply(role, overrides[role.name], warnings);\n if (applied) roles.push(applied);\n }\n return { roles, warnings, limits };\n}\n\nexport function findRole(roles: readonly Role[], name: string): Role | undefined {\n return (\n roles.find((role) => role.name === name) ?? roles.find((role) => role.aliases.includes(name))\n );\n}\n\nexport async function manifestDirs(\n files: RoleFiles,\n root: string,\n context: Context\n): Promise<string[]> {\n const top = await files.listDir(root, context);\n if (!top.ok) return [];\n const out: string[] = [];\n for (const entry of top.value) {\n if (entry.kind !== 'directory' || entry.name.startsWith('.')) continue;\n if (!entry.name.startsWith('@')) {\n out.push(`${root}/${entry.name}`);\n continue;\n }\n const scoped = await files.listDir(`${root}/${entry.name}`, context);\n if (scoped.ok)\n for (const inner of scoped.value)\n if (inner.kind === 'directory') out.push(`${root}/${entry.name}/${inner.name}`);\n }\n return out;\n}\n\ntype Manifest = {\n 'pi-subagents'?: { agents?: unknown };\n pi?: { subagents?: { agents?: unknown } };\n};\n\nexport function agentPaths(dir: string, text: string): string[] {\n let manifest: Manifest;\n try {\n manifest = JSON.parse(text) as Manifest;\n } catch {\n return [];\n }\n const agents = manifest['pi-subagents']?.agents ?? manifest.pi?.subagents?.agents;\n const listed = Array.isArray(agents) ? agents : typeof agents === 'string' ? [agents] : [];\n return listed\n .filter((path): path is string => typeof path === 'string')\n .map((path) => `${dir}/${path.replace(/^\\.\\//, '').replace(/\\/$/, '')}`);\n}\n\nexport async function packageDirs(\n files: RoleFiles,\n root: string,\n context: Context\n): Promise<string[]> {\n const out: string[] = [];\n for (const dir of await manifestDirs(files, root, context)) {\n const read = await files.readTextFile(`${dir}/package.json`, context);\n if (read.ok) out.push(...agentPaths(dir, read.value));\n }\n return out;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/scoops/extension.js
CHANGED
|
@@ -12,7 +12,6 @@ import { normalize, resolve } from "../kernel/paths.js";
|
|
|
12
12
|
import { FROM_KIND } from "./from.js";
|
|
13
13
|
import { SCOOPS_ROOT, ScoopWorkDoc, workspace } from "./service.js";
|
|
14
14
|
const PREVIEW = 1e3;
|
|
15
|
-
const ADVERTISED = 16;
|
|
16
15
|
function scoopFacts(record) {
|
|
17
16
|
return [
|
|
18
17
|
`You are the scoop "${record.name}"${record.role ? ` (role: ${record.role})` : ""}, a helper agent working for a cone. Messages come from the cone or from the user at a terminal; your final answer goes back to whoever asked, so end every task with a complete answer.`,
|
|
@@ -248,22 +247,9 @@ async function whose(input, context) {
|
|
|
248
247
|
const scoop = Object.values(state?.scoops ?? {}).find(
|
|
249
248
|
(record) => record.conversation === input.conversationId
|
|
250
249
|
);
|
|
251
|
-
|
|
252
|
-
(record) => record.conversation === input.conversationId
|
|
253
|
-
);
|
|
254
|
-
return { scoop, cone };
|
|
255
|
-
}
|
|
256
|
-
function rolesSection(roles) {
|
|
257
|
-
const shown = roles.slice(0, ADVERTISED);
|
|
258
|
-
return [
|
|
259
|
-
"Roles for `subagent spawn --agent <role>`:",
|
|
260
|
-
...shown.map(
|
|
261
|
-
(role) => `- ${role.name}${role.aliases.length ? ` (also ${role.aliases.join(", ")})` : ""}: ${role.description}`
|
|
262
|
-
),
|
|
263
|
-
...roles.length > shown.length ? [`\u2026 and ${roles.length - shown.length} more; \`subagent list --agents\` shows them all.`] : []
|
|
264
|
-
].join("\n");
|
|
250
|
+
return { scoop };
|
|
265
251
|
}
|
|
266
|
-
function scoopsExtension(tasks
|
|
252
|
+
function scoopsExtension(tasks) {
|
|
267
253
|
return defineExtension({
|
|
268
254
|
name: "slicc-scoops",
|
|
269
255
|
tasks: [tasks.anchor, tasks.reporter, tasks.wait],
|
|
@@ -271,20 +257,15 @@ function scoopsExtension(tasks, sections) {
|
|
|
271
257
|
section("scoop", async (input, context) => {
|
|
272
258
|
const { scoop } = await whose(input, context);
|
|
273
259
|
return scoop ? scoopFacts(scoop) : void 0;
|
|
274
|
-
}),
|
|
275
|
-
section("subagent", async (input, context) => {
|
|
276
|
-
const { cone } = await whose(input, context);
|
|
277
|
-
if (!cone) return void 0;
|
|
278
|
-
return [sections.skill(), rolesSection(sections.roles())].filter(Boolean).join("\n\n");
|
|
279
260
|
})
|
|
280
261
|
]
|
|
281
262
|
});
|
|
282
263
|
}
|
|
283
264
|
const WRITES = /* @__PURE__ */ new Set(["write", "edit"]);
|
|
284
|
-
function allowed(record, coneCwd, path, writing) {
|
|
265
|
+
function allowed(record, coneCwd, path, writing, reads = []) {
|
|
285
266
|
const own = `${SCOOPS_ROOT}/${record.folder}`;
|
|
286
267
|
const write = [own, "/tmp", ...record.roots?.write ?? []];
|
|
287
|
-
const roots = writing ? write : [...write, coneCwd, ...record.roots?.read ?? []];
|
|
268
|
+
const roots = writing ? write : [...write, coneCwd, ...record.roots?.read ?? [], ...reads];
|
|
288
269
|
return roots.some((root) => path === root || path.startsWith(`${root === "/" ? "" : root}/`));
|
|
289
270
|
}
|
|
290
271
|
function refusal(value) {
|
|
@@ -295,16 +276,18 @@ function guardExtension(lookup, tools) {
|
|
|
295
276
|
(tool) => wrapTool(tool, (inner) => ({
|
|
296
277
|
...inner,
|
|
297
278
|
async execute(args, api, context) {
|
|
298
|
-
const { agents } = await lookup();
|
|
279
|
+
const { agents, reads } = await lookup();
|
|
299
280
|
const record = Object.values(agents.state().scoops).find(
|
|
300
281
|
(scoop) => scoop.conversation === api.conversationId
|
|
301
282
|
);
|
|
302
283
|
if (!record) return inner.execute(args, api, context);
|
|
303
284
|
const path = String(args.path);
|
|
304
|
-
|
|
305
|
-
const canonical = await api.env?.canonicalPath(
|
|
306
|
-
|
|
307
|
-
|
|
285
|
+
const asked = normalize(resolve(workspace(record.folder), path));
|
|
286
|
+
const canonical = await api.env?.canonicalPath(asked, context);
|
|
287
|
+
const target = canonical?.ok ? canonical.value : asked;
|
|
288
|
+
const writing = WRITES.has(inner.name);
|
|
289
|
+
const skills = reads?.() ?? [];
|
|
290
|
+
if (allowed(record, HOME, target, writing, skills) || allowed(record, HOME, asked, writing, skills))
|
|
308
291
|
return inner.execute(args, api, context);
|
|
309
292
|
return refusal(
|
|
310
293
|
`${target} is outside this scoop's folders. ${inner.name} reaches ${SCOOPS_ROOT}/${record.folder} and /tmp${WRITES.has(inner.name) ? "" : `, and reads ${HOME}`}.`
|
|
@@ -321,7 +304,6 @@ export {
|
|
|
321
304
|
guardExtension,
|
|
322
305
|
noteWhenPlaced,
|
|
323
306
|
reportLick,
|
|
324
|
-
rolesSection,
|
|
325
307
|
scoopFacts,
|
|
326
308
|
scoopTasks,
|
|
327
309
|
scoopsExtension,
|