@ai-ecoverse/slicc-agent 3.52.0 → 4.0.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 +17 -13
- package/dist/client.js +1 -1
- package/dist/client.js.map +1 -1
- package/dist/host.js.map +1 -1
- package/dist/index.js +0 -3
- package/dist/index.js.map +2 -2
- package/dist/main.js +95 -22
- package/dist/main.js.map +2 -2
- package/dist/mcp/accounts.js +18 -14
- package/dist/mcp/accounts.js.map +2 -2
- package/dist/mcp/connection.js +0 -2
- package/dist/mcp/connection.js.map +2 -2
- package/dist/mcp/credentials.js +6 -15
- package/dist/mcp/credentials.js.map +2 -2
- package/dist/mcp/index.js +0 -1
- package/dist/mcp/index.js.map +2 -2
- package/dist/mcp/oauth.js +15 -20
- package/dist/mcp/oauth.js.map +2 -2
- package/dist/mcp/runtime.js +36 -14
- package/dist/mcp/runtime.js.map +2 -2
- package/dist/mcp/tools.js +4 -6
- package/dist/mcp/tools.js.map +2 -2
- package/dist/models/index.js +7 -4
- package/dist/models/index.js.map +2 -2
- package/dist/monitor/index.js +5 -10
- package/dist/monitor/index.js.map +2 -2
- package/dist/monitor/redact.js +4 -5
- package/dist/monitor/redact.js.map +2 -2
- package/dist/secrets/credentials.js +32 -0
- package/dist/secrets/credentials.js.map +7 -0
- package/dist/secrets/endpoints.js +111 -0
- package/dist/secrets/endpoints.js.map +7 -0
- package/dist/secrets/fetch.js +160 -0
- package/dist/secrets/fetch.js.map +7 -0
- package/dist/secrets/records.js +35 -0
- package/dist/secrets/records.js.map +7 -0
- package/dist/secrets/store.js +50 -0
- package/dist/secrets/store.js.map +7 -0
- package/dist/secrets/vault.js +58 -13
- package/dist/secrets/vault.js.map +2 -2
- package/dist/services.js.map +2 -2
- package/dist/settings.js +85 -23
- package/dist/settings.js.map +2 -2
- package/dist/skills/index.js +26 -3
- package/dist/skills/index.js.map +2 -2
- package/dist/spectrum/settings-port.js +24 -6
- package/dist/spectrum/settings-port.js.map +2 -2
- package/dist/types/host.d.ts +1 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/main.d.ts +7 -2
- package/dist/types/mcp/accounts.d.ts +10 -4
- package/dist/types/mcp/connection.d.ts +0 -2
- package/dist/types/mcp/credentials.d.ts +6 -4
- package/dist/types/mcp/oauth.d.ts +3 -2
- package/dist/types/mcp/runtime.d.ts +18 -4
- package/dist/types/models/index.d.ts +2 -0
- package/dist/types/monitor/index.d.ts +0 -1
- package/dist/types/monitor/redact.d.ts +2 -2
- package/dist/types/secrets/credentials.d.ts +5 -0
- package/dist/types/secrets/endpoints.d.ts +27 -0
- package/dist/types/secrets/fetch.d.ts +13 -0
- package/dist/types/secrets/records.d.ts +13 -0
- package/dist/types/secrets/store.d.ts +7 -0
- package/dist/types/secrets/vault.d.ts +31 -1
- package/dist/types/services.d.ts +8 -1
- package/dist/types/settings.d.ts +17 -2
- package/dist/types/spectrum/settings-port.d.ts +6 -4
- package/package.json +5 -3
- package/dist/credentials.js +0 -100
- package/dist/credentials.js.map +0 -7
- package/dist/types/credentials.d.ts +0 -12
package/dist/settings.js
CHANGED
|
@@ -14,6 +14,12 @@ import { MCP_ACCOUNT } from "./mcp/label.js";
|
|
|
14
14
|
const BEDROCK = "amazon-bedrock";
|
|
15
15
|
const DEFAULT_MODEL = { provider: BEDROCK, modelId: "us.anthropic.claude-sonnet-5-5" };
|
|
16
16
|
const DEFAULT_REGIONS = { [BEDROCK]: "us-west-2" };
|
|
17
|
+
const ACCOUNT_FIELDS = {
|
|
18
|
+
[BEDROCK]: [{ name: "region", label: "Region" }]
|
|
19
|
+
};
|
|
20
|
+
const FIELD_ENV = { region: "AWS_REGION" };
|
|
21
|
+
const SIGN_IN_NEEDS_VAULT = "Adobe sign-in needs seven's vault: update seven";
|
|
22
|
+
const KEY_NEEDS_VAULT = "API keys are kept in seven's vault: update seven";
|
|
17
23
|
const corsFree = /* @__PURE__ */ new Set([BEDROCK, ADOBE]);
|
|
18
24
|
const signIn = /* @__PURE__ */ new Set([ADOBE]);
|
|
19
25
|
const BUDGET_EVERY = 5 * 60 * 1e3;
|
|
@@ -53,15 +59,52 @@ function choices(models, providers, stored) {
|
|
|
53
59
|
}))
|
|
54
60
|
);
|
|
55
61
|
}
|
|
56
|
-
function accounts(
|
|
57
|
-
return providers.map((provider) =>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
function accounts(records, providers) {
|
|
63
|
+
return providers.map((provider) => {
|
|
64
|
+
const record = records.model(provider.id);
|
|
65
|
+
const fields = ACCOUNT_FIELDS[provider.id];
|
|
66
|
+
return {
|
|
67
|
+
id: provider.id,
|
|
68
|
+
provider: provider.name ?? provider.id,
|
|
69
|
+
identity: record ? signIn.has(provider.id) ? "Adobe ID" : "API key" : "",
|
|
70
|
+
status: !record ? "disconnected" : record.state === "expired" ? "expired" : "connected",
|
|
71
|
+
auth: signIn.has(provider.id) ? "oauth" : "api-key",
|
|
72
|
+
needs: corsFree.has(provider.id) ? "cors-free-transport" : null,
|
|
73
|
+
store: "vault",
|
|
74
|
+
...fields ? { fields: fields.map((field) => ({ ...field })) } : {}
|
|
75
|
+
};
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
async function providerFields(store, providers) {
|
|
79
|
+
const known = /* @__PURE__ */ new Map();
|
|
80
|
+
for (const provider of providers) {
|
|
81
|
+
const saved = await store.get(`model:${provider.id}`);
|
|
82
|
+
if (saved && typeof saved === "object") known.set(provider.id, saved);
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
get: (providerId) => known.get(providerId),
|
|
86
|
+
env(providerId) {
|
|
87
|
+
const fields = known.get(providerId);
|
|
88
|
+
if (!fields) return void 0;
|
|
89
|
+
return Object.fromEntries(
|
|
90
|
+
Object.entries(fields).flatMap(
|
|
91
|
+
([name, value]) => FIELD_ENV[name] ? [[FIELD_ENV[name], value]] : []
|
|
92
|
+
)
|
|
93
|
+
);
|
|
94
|
+
},
|
|
95
|
+
async set(providerId, fields) {
|
|
96
|
+
const allowed = new Set((ACCOUNT_FIELDS[providerId] ?? []).map((field) => field.name));
|
|
97
|
+
const kept = Object.fromEntries(
|
|
98
|
+
Object.entries(fields ?? {}).filter(
|
|
99
|
+
([name, value]) => allowed.has(name) && typeof value === "string" && value.trim() !== ""
|
|
100
|
+
)
|
|
101
|
+
);
|
|
102
|
+
const next = Object.keys(kept).length ? kept : void 0;
|
|
103
|
+
if (next) known.set(providerId, next);
|
|
104
|
+
else known.delete(providerId);
|
|
105
|
+
await store.set(`model:${providerId}`, next);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
65
108
|
}
|
|
66
109
|
async function shown(run) {
|
|
67
110
|
try {
|
|
@@ -73,25 +116,27 @@ async function shown(run) {
|
|
|
73
116
|
);
|
|
74
117
|
}
|
|
75
118
|
}
|
|
76
|
-
async function budget(
|
|
77
|
-
const
|
|
78
|
-
const key = credential?.type === "api_key" ? credential.key : void 0;
|
|
119
|
+
async function budget(records, usage) {
|
|
120
|
+
const key = records.model(ADOBE)?.placeholder;
|
|
79
121
|
const found = key ? await usage(key).catch(() => null) : null;
|
|
80
122
|
return found ? { provider: ADOBE, ...found } : null;
|
|
81
123
|
}
|
|
82
|
-
async function createAgentSettings(models,
|
|
124
|
+
async function createAgentSettings(models, sources, providers = sliccProviders(), options = {}) {
|
|
83
125
|
const { mcp } = options;
|
|
126
|
+
const { records, fields } = sources;
|
|
84
127
|
const routed = (providerId) => providerId.startsWith(MCP_ACCOUNT) ? mcp : void 0;
|
|
85
128
|
const adobe = providers.find((provider) => provider.id === ADOBE);
|
|
86
129
|
const endpoint = adobe?.baseUrl ?? ADOBE_PROXY;
|
|
87
130
|
const identity = adobe?.headers ?? adobeIdentity();
|
|
88
131
|
const usage = options.usage ?? ((token) => adobeUsage(token, { endpoint, identity }));
|
|
89
132
|
const snapshot = async () => {
|
|
90
|
-
const stored = new Set(
|
|
133
|
+
const stored = new Set(
|
|
134
|
+
providers.filter((provider) => records.model(provider.id)).map((provider) => provider.id)
|
|
135
|
+
);
|
|
91
136
|
return {
|
|
92
137
|
models: choices(models, providers, stored),
|
|
93
|
-
accounts: [...accounts(
|
|
94
|
-
budget: await budget(
|
|
138
|
+
accounts: [...accounts(records, providers), ...await mcp?.accounts() ?? []],
|
|
139
|
+
budget: await budget(records, usage)
|
|
95
140
|
};
|
|
96
141
|
};
|
|
97
142
|
const state = replicatedState(await snapshot());
|
|
@@ -113,20 +158,32 @@ async function createAgentSettings(models, credentials, providers = sliccProvide
|
|
|
113
158
|
timer.unref?.();
|
|
114
159
|
}
|
|
115
160
|
mcp?.onChange(() => void refresh(BACKGROUND_CONTEXT).catch(() => void 0));
|
|
161
|
+
const held = () => signedIn.filter((id) => records.model(id)).join(" ");
|
|
162
|
+
let seen = held();
|
|
163
|
+
records.state.subscribe(() => {
|
|
164
|
+
const now = held();
|
|
165
|
+
const added = now !== seen;
|
|
166
|
+
seen = now;
|
|
167
|
+
const discovered = added ? discover(signedIn) : Promise.resolve();
|
|
168
|
+
void discovered.then(() => refresh(BACKGROUND_CONTEXT)).catch(() => void 0);
|
|
169
|
+
});
|
|
170
|
+
const reread = (context) => records.refresh(context).catch(() => void 0);
|
|
116
171
|
return {
|
|
117
172
|
state,
|
|
118
|
-
async connect(providerId, secret,
|
|
173
|
+
async connect(providerId, secret, given, context) {
|
|
119
174
|
const server = routed(providerId);
|
|
120
175
|
if (server) {
|
|
121
176
|
await shown(() => server.connect(providerId, secret));
|
|
122
177
|
await refresh(context);
|
|
123
178
|
return;
|
|
124
179
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
180
|
+
if (secret !== null)
|
|
181
|
+
throw new RemoteServiceError(
|
|
182
|
+
"service_invalid_value",
|
|
183
|
+
signIn.has(providerId) ? SIGN_IN_NEEDS_VAULT : KEY_NEEDS_VAULT
|
|
184
|
+
);
|
|
185
|
+
if (given !== null) await fields.set(providerId, given);
|
|
186
|
+
await reread(context);
|
|
130
187
|
if (signIn.has(providerId)) await discover([providerId]);
|
|
131
188
|
await refresh(context);
|
|
132
189
|
},
|
|
@@ -144,17 +201,22 @@ async function createAgentSettings(models, credentials, providers = sliccProvide
|
|
|
144
201
|
async disconnect(providerId, context) {
|
|
145
202
|
const server = routed(providerId);
|
|
146
203
|
if (server) await server.disconnect(providerId);
|
|
147
|
-
else await
|
|
204
|
+
else await fields.set(providerId, void 0);
|
|
205
|
+
await reread(context);
|
|
148
206
|
await refresh(context);
|
|
149
207
|
}
|
|
150
208
|
};
|
|
151
209
|
}
|
|
152
210
|
export {
|
|
211
|
+
ACCOUNT_FIELDS,
|
|
153
212
|
BEDROCK,
|
|
154
213
|
DEFAULT_MODEL,
|
|
155
214
|
DEFAULT_REGIONS,
|
|
215
|
+
KEY_NEEDS_VAULT,
|
|
216
|
+
SIGN_IN_NEEDS_VAULT,
|
|
156
217
|
createAgentSettings,
|
|
157
218
|
createSliccModels,
|
|
219
|
+
providerFields,
|
|
158
220
|
shown,
|
|
159
221
|
sliccProviders,
|
|
160
222
|
withDefaultRegions
|
package/dist/settings.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/settings.ts"],
|
|
4
|
-
"sourcesContent": ["import { type Context, RemoteServiceError, replicatedState } from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { CredentialStore, Provider } from '@earendil-works/pi-ai';\nimport { createModels, type MutableModels } from '@earendil-works/pi-ai/models';\nimport { amazonBedrockProvider } from '@earendil-works/pi-ai/providers/amazon-bedrock';\nimport {\n ADOBE,\n ADOBE_PROXY,\n adobeConfig,\n adobeIdentity,\n adobeProvider,\n adobeUsage,\n type Budget,\n} from './adobe.ts';\nimport type { McpAccounts } from './mcp/index.ts';\nimport { MCP_ACCOUNT } from './mcp/label.ts';\nimport type { AccountState, AgentSettings, ModelChoice, SettingsState } from './services.ts';\n\nexport const BEDROCK = 'amazon-bedrock';\nexport const DEFAULT_MODEL = { provider: BEDROCK, modelId: 'us.anthropic.claude-sonnet-5-5' };\nexport const DEFAULT_REGIONS: Readonly<Record<string, string>> = { [BEDROCK]: 'us-west-2' };\n\nconst corsFree = new Set([BEDROCK, ADOBE]);\nconst signIn = new Set([ADOBE]);\nconst BUDGET_EVERY = 5 * 60 * 1000;\n\nexport function sliccProviders(version?: string): Provider[] {\n return [amazonBedrockProvider() as Provider, adobeProvider({ version })];\n}\n\nexport function withDefaultRegions(credentials: CredentialStore): CredentialStore {\n return {\n async read(providerId, options) {\n const credential = await credentials.read(providerId, options);\n const region = DEFAULT_REGIONS[providerId];\n if (credential?.type !== 'api_key' || !region || credential.env?.AWS_REGION) {\n return credential;\n }\n return { ...credential, env: { ...credential.env, AWS_REGION: region } };\n },\n list: (options) => credentials.list(options),\n modify: (providerId, fn, options) => credentials.modify(providerId, fn, options),\n delete: (providerId, options) => credentials.delete(providerId, options),\n };\n}\n\nexport function createSliccModels(\n credentials: CredentialStore,\n providers = sliccProviders()\n): MutableModels {\n const models = createModels({ credentials: withDefaultRegions(credentials) });\n for (const provider of providers) models.setProvider(provider);\n return models;\n}\n\nfunction choices(\n models: MutableModels,\n providers: Provider[],\n stored: ReadonlySet<string>\n): ModelChoice[] {\n return providers\n .filter((provider) => stored.has(provider.id))\n .flatMap((provider) =>\n models.getModels(provider.id).map((model) => ({\n id: `${provider.id}/${model.id}`,\n label: model.name,\n provider: provider.name ?? provider.id,\n kind: 'chat' as const,\n reasoning: Boolean(model.reasoning),\n images: model.input.includes('image'),\n contextWindow: model.contextWindow,\n }))\n );\n}\n\nfunction accounts(stored: ReadonlySet<string>, providers: Provider[]): AccountState[] {\n return providers.map((provider) => ({\n id: provider.id,\n provider: provider.name ?? provider.id,\n identity: stored.has(provider.id) ? (signIn.has(provider.id) ? 'Adobe ID' : 'API key') : '',\n status: stored.has(provider.id) ? 'connected' : 'disconnected',\n auth: signIn.has(provider.id) ? 'oauth' : 'api-key',\n needs: corsFree.has(provider.id) ? 'cors-free-transport' : null,\n }));\n}\n\nexport async function shown<T>(run: () => Promise<T>): Promise<T> {\n try {\n return await run();\n } catch (error) {\n throw new RemoteServiceError(\n 'service_invalid_value',\n error instanceof Error ? error.message : String(error)\n );\n }\n}\n\nexport type UsageReader = (token: string) => Promise<Budget | null>;\n\nasync function budget(credentials: CredentialStore, usage: UsageReader) {\n const credential = await credentials.read(ADOBE);\n const key = credential?.type === 'api_key' ? credential.key : undefined;\n const found = key ? await usage(key).catch(() => null) : null;\n return found ? { provider: ADOBE, ...found } : null;\n}\n\nexport async function createAgentSettings(\n models: MutableModels,\n credentials: CredentialStore,\n providers = sliccProviders(),\n options: { usage?: UsageReader; every?: number; mcp?: McpAccounts } = {}\n): Promise<AgentSettings> {\n const { mcp } = options;\n const routed = (providerId: string) => (providerId.startsWith(MCP_ACCOUNT) ? mcp : undefined);\n const adobe = providers.find((provider) => provider.id === ADOBE);\n const endpoint = adobe?.baseUrl ?? ADOBE_PROXY;\n const identity = (adobe?.headers as Record<string, string> | undefined) ?? adobeIdentity();\n const usage = options.usage ?? ((token: string) => adobeUsage(token, { endpoint, identity }));\n const snapshot = async (): Promise<SettingsState> => {\n const stored = new Set((await credentials.list()).map((info) => info.providerId));\n return {\n models: choices(models, providers, stored),\n accounts: [...accounts(stored, providers), ...((await mcp?.accounts()) ?? [])],\n budget: await budget(credentials, usage),\n };\n };\n const state = replicatedState<SettingsState>(await snapshot());\n let latest = Promise.resolve();\n const refresh = (context: Context) => {\n const next = latest.then(async () => state.replace(context, await snapshot()));\n latest = next.catch(() => undefined);\n return next;\n };\n const signedIn = providers\n .filter((provider) => signIn.has(provider.id))\n .map((provider) => provider.id);\n const discover = (ids: string[]) =>\n models.refresh({ providers: ids }).then(\n () => undefined,\n () => undefined\n );\n if (signedIn.length) {\n const cycle = () =>\n void discover(signedIn)\n .then(() => refresh(BACKGROUND_CONTEXT))\n .catch(() => undefined);\n cycle();\n const timer: unknown = setInterval(cycle, options.every ?? BUDGET_EVERY);\n (timer as { unref?: () => void }).unref?.();\n }\n mcp?.onChange(() => void refresh(BACKGROUND_CONTEXT).catch(() => undefined));\n return {\n state,\n async connect(providerId, secret, region, context) {\n const server = routed(providerId);\n if (server) {\n await shown(() => server.connect(providerId, secret));\n await refresh(context);\n return;\n }\n await credentials.modify(providerId, async () => ({\n type: 'api_key',\n key: secret,\n ...(region ? { env: { AWS_REGION: region } } : {}),\n }));\n if (signIn.has(providerId)) await discover([providerId]);\n await refresh(context);\n },\n async signIn(providerId) {\n const server = routed(providerId);\n if (server) return shown(() => server.signIn(providerId));\n if (providerId !== ADOBE) return null;\n const { clientId, scopes, imsEnvironment } = await adobeConfig(\n endpoint,\n (input, init) => globalThis.fetch(input, init),\n identity\n );\n return { clientId, scopes, imsEnvironment: imsEnvironment || 'prod' };\n },\n async disconnect(providerId, context) {\n const server = routed(providerId);\n if (server) await server.disconnect(providerId);\n else await credentials.delete(providerId);\n await refresh(context);\n },\n };\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAuB,oBAAoB,uBAAuB;AAClE,SAAS,0BAA0B;AAEnC,SAAS,oBAAwC;AACjD,SAAS,6BAA6B;AACtC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAEP,SAAS,mBAAmB;
|
|
4
|
+
"sourcesContent": ["import { type Context, RemoteServiceError, replicatedState } from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { CredentialStore, Provider } from '@earendil-works/pi-ai';\nimport { createModels, type MutableModels } from '@earendil-works/pi-ai/models';\nimport { amazonBedrockProvider } from '@earendil-works/pi-ai/providers/amazon-bedrock';\nimport {\n ADOBE,\n ADOBE_PROXY,\n adobeConfig,\n adobeIdentity,\n adobeProvider,\n adobeUsage,\n type Budget,\n} from './adobe.ts';\nimport type { McpAccounts } from './mcp/index.ts';\nimport { MCP_ACCOUNT } from './mcp/label.ts';\nimport type { VaultRecords } from './secrets/records.ts';\nimport type { PlainStore } from './secrets/store.ts';\nimport type {\n AccountField,\n AccountState,\n AgentSettings,\n ModelChoice,\n SettingsState,\n} from './services.ts';\n\nexport const BEDROCK = 'amazon-bedrock';\nexport const DEFAULT_MODEL = { provider: BEDROCK, modelId: 'us.anthropic.claude-sonnet-5-5' };\nexport const DEFAULT_REGIONS: Readonly<Record<string, string>> = { [BEDROCK]: 'us-west-2' };\n\nexport const ACCOUNT_FIELDS: Readonly<Record<string, readonly AccountField[]>> = {\n [BEDROCK]: [{ name: 'region', label: 'Region' }],\n};\nconst FIELD_ENV: Readonly<Record<string, string>> = { region: 'AWS_REGION' };\nexport const SIGN_IN_NEEDS_VAULT = \"Adobe sign-in needs seven's vault: update seven\";\nexport const KEY_NEEDS_VAULT = \"API keys are kept in seven's vault: update seven\";\n\nconst corsFree = new Set([BEDROCK, ADOBE]);\nconst signIn = new Set([ADOBE]);\nconst BUDGET_EVERY = 5 * 60 * 1000;\n\nexport function sliccProviders(version?: string): Provider[] {\n return [amazonBedrockProvider() as Provider, adobeProvider({ version })];\n}\n\nexport function withDefaultRegions(credentials: CredentialStore): CredentialStore {\n return {\n async read(providerId, options) {\n const credential = await credentials.read(providerId, options);\n const region = DEFAULT_REGIONS[providerId];\n if (credential?.type !== 'api_key' || !region || credential.env?.AWS_REGION) {\n return credential;\n }\n return { ...credential, env: { ...credential.env, AWS_REGION: region } };\n },\n list: (options) => credentials.list(options),\n modify: (providerId, fn, options) => credentials.modify(providerId, fn, options),\n delete: (providerId, options) => credentials.delete(providerId, options),\n };\n}\n\nexport function createSliccModels(\n credentials: CredentialStore,\n providers = sliccProviders()\n): MutableModels {\n const models = createModels({ credentials: withDefaultRegions(credentials) });\n for (const provider of providers) models.setProvider(provider);\n return models;\n}\n\nfunction choices(\n models: MutableModels,\n providers: Provider[],\n stored: ReadonlySet<string>\n): ModelChoice[] {\n return providers\n .filter((provider) => stored.has(provider.id))\n .flatMap((provider) =>\n models.getModels(provider.id).map((model) => ({\n id: `${provider.id}/${model.id}`,\n label: model.name,\n provider: provider.name ?? provider.id,\n kind: 'chat' as const,\n reasoning: Boolean(model.reasoning),\n images: model.input.includes('image'),\n contextWindow: model.contextWindow,\n }))\n );\n}\n\nfunction accounts(records: Pick<VaultRecords, 'model'>, providers: Provider[]): AccountState[] {\n return providers.map((provider) => {\n const record = records.model(provider.id);\n const fields = ACCOUNT_FIELDS[provider.id];\n return {\n id: provider.id,\n provider: provider.name ?? provider.id,\n identity: record ? (signIn.has(provider.id) ? 'Adobe ID' : 'API key') : '',\n status: !record ? 'disconnected' : record.state === 'expired' ? 'expired' : 'connected',\n auth: signIn.has(provider.id) ? 'oauth' : 'api-key',\n needs: corsFree.has(provider.id) ? 'cors-free-transport' : null,\n store: 'vault',\n ...(fields ? { fields: fields.map((field) => ({ ...field })) } : {}),\n };\n });\n}\n\nexport interface ProviderFields {\n get(providerId: string): Readonly<Record<string, string>> | undefined;\n env(providerId: string): Readonly<Record<string, string>> | undefined;\n set(providerId: string, fields: Record<string, string> | undefined): Promise<void>;\n}\n\nexport async function providerFields(\n store: PlainStore,\n providers: readonly Provider[]\n): Promise<ProviderFields> {\n const known = new Map<string, Record<string, string>>();\n for (const provider of providers) {\n const saved = (await store.get(`model:${provider.id}`)) as Record<string, string> | undefined;\n if (saved && typeof saved === 'object') known.set(provider.id, saved);\n }\n return {\n get: (providerId) => known.get(providerId),\n env(providerId) {\n const fields = known.get(providerId);\n if (!fields) return undefined;\n return Object.fromEntries(\n Object.entries(fields).flatMap(([name, value]) =>\n FIELD_ENV[name] ? [[FIELD_ENV[name], value]] : []\n )\n );\n },\n async set(providerId, fields) {\n const allowed = new Set((ACCOUNT_FIELDS[providerId] ?? []).map((field) => field.name));\n const kept = Object.fromEntries(\n Object.entries(fields ?? {}).filter(\n ([name, value]) => allowed.has(name) && typeof value === 'string' && value.trim() !== ''\n )\n );\n const next = Object.keys(kept).length ? kept : undefined;\n if (next) known.set(providerId, next);\n else known.delete(providerId);\n await store.set(`model:${providerId}`, next);\n },\n };\n}\n\nexport async function shown<T>(run: () => Promise<T>): Promise<T> {\n try {\n return await run();\n } catch (error) {\n throw new RemoteServiceError(\n 'service_invalid_value',\n error instanceof Error ? error.message : String(error)\n );\n }\n}\n\nexport type UsageReader = (token: string) => Promise<Budget | null>;\n\nasync function budget(records: Pick<VaultRecords, 'model'>, usage: UsageReader) {\n const key = records.model(ADOBE)?.placeholder;\n const found = key ? await usage(key).catch(() => null) : null;\n return found ? { provider: ADOBE, ...found } : null;\n}\n\nexport interface SettingsSources {\n records: VaultRecords;\n fields: ProviderFields;\n}\n\nexport async function createAgentSettings(\n models: MutableModels,\n sources: SettingsSources,\n providers = sliccProviders(),\n options: { usage?: UsageReader; every?: number; mcp?: McpAccounts } = {}\n): Promise<AgentSettings> {\n const { mcp } = options;\n const { records, fields } = sources;\n const routed = (providerId: string) => (providerId.startsWith(MCP_ACCOUNT) ? mcp : undefined);\n const adobe = providers.find((provider) => provider.id === ADOBE);\n const endpoint = adobe?.baseUrl ?? ADOBE_PROXY;\n const identity = (adobe?.headers as Record<string, string> | undefined) ?? adobeIdentity();\n const usage = options.usage ?? ((token: string) => adobeUsage(token, { endpoint, identity }));\n const snapshot = async (): Promise<SettingsState> => {\n const stored = new Set(\n providers.filter((provider) => records.model(provider.id)).map((provider) => provider.id)\n );\n return {\n models: choices(models, providers, stored),\n accounts: [...accounts(records, providers), ...((await mcp?.accounts()) ?? [])],\n budget: await budget(records, usage),\n };\n };\n const state = replicatedState<SettingsState>(await snapshot());\n let latest = Promise.resolve();\n const refresh = (context: Context) => {\n const next = latest.then(async () => state.replace(context, await snapshot()));\n latest = next.catch(() => undefined);\n return next;\n };\n const signedIn = providers\n .filter((provider) => signIn.has(provider.id))\n .map((provider) => provider.id);\n const discover = (ids: string[]) =>\n models.refresh({ providers: ids }).then(\n () => undefined,\n () => undefined\n );\n if (signedIn.length) {\n const cycle = () =>\n void discover(signedIn)\n .then(() => refresh(BACKGROUND_CONTEXT))\n .catch(() => undefined);\n cycle();\n const timer: unknown = setInterval(cycle, options.every ?? BUDGET_EVERY);\n (timer as { unref?: () => void }).unref?.();\n }\n mcp?.onChange(() => void refresh(BACKGROUND_CONTEXT).catch(() => undefined));\n const held = () => signedIn.filter((id) => records.model(id)).join(' ');\n let seen = held();\n records.state.subscribe(() => {\n const now = held();\n const added = now !== seen;\n seen = now;\n const discovered = added ? discover(signedIn) : Promise.resolve();\n void discovered.then(() => refresh(BACKGROUND_CONTEXT)).catch(() => undefined);\n });\n const reread = (context: Context) => records.refresh(context).catch(() => undefined);\n return {\n state,\n async connect(providerId, secret, given, context) {\n const server = routed(providerId);\n if (server) {\n await shown(() => server.connect(providerId, secret));\n await refresh(context);\n return;\n }\n if (secret !== null)\n throw new RemoteServiceError(\n 'service_invalid_value',\n signIn.has(providerId) ? SIGN_IN_NEEDS_VAULT : KEY_NEEDS_VAULT\n );\n if (given !== null) await fields.set(providerId, given);\n await reread(context);\n if (signIn.has(providerId)) await discover([providerId]);\n await refresh(context);\n },\n async signIn(providerId) {\n const server = routed(providerId);\n if (server) return shown(() => server.signIn(providerId));\n if (providerId !== ADOBE) return null;\n const { clientId, scopes, imsEnvironment } = await adobeConfig(\n endpoint,\n (input, init) => globalThis.fetch(input, init),\n identity\n );\n return { clientId, scopes, imsEnvironment: imsEnvironment || 'prod' };\n },\n async disconnect(providerId, context) {\n const server = routed(providerId);\n if (server) await server.disconnect(providerId);\n else await fields.set(providerId, undefined);\n await reread(context);\n await refresh(context);\n },\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/skills/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
defineExtension,
|
|
4
4
|
section
|
|
5
5
|
} from "@earendil-works/pi-durable";
|
|
6
|
+
import { dirname } from "../kernel/paths.js";
|
|
6
7
|
import { PACKAGE_ROOTS, piPackages } from "../roles/roles.js";
|
|
7
8
|
import {
|
|
8
9
|
expandSkillCommand,
|
|
@@ -25,6 +26,7 @@ const SKILLS_DIR = "/var/lib/slicc/agent/skills";
|
|
|
25
26
|
const PROMPTS_DIR = "/var/lib/slicc/agent/prompts";
|
|
26
27
|
const GLOBAL_DIR = "/usr/share/skills";
|
|
27
28
|
const RELOAD_MS = 300;
|
|
29
|
+
const USER_PACKAGES = "/opt/user/node_modules";
|
|
28
30
|
function userRoots(homes) {
|
|
29
31
|
return homes.flatMap((home) => [
|
|
30
32
|
{ dir: `${home}/.pi/agent/skills`, source: "user" },
|
|
@@ -167,23 +169,44 @@ ${problem.message}`;
|
|
|
167
169
|
};
|
|
168
170
|
await reload(context);
|
|
169
171
|
let timer;
|
|
172
|
+
const refresh = async () => {
|
|
173
|
+
await watch(context);
|
|
174
|
+
await reload(context);
|
|
175
|
+
};
|
|
170
176
|
const schedule = () => {
|
|
171
177
|
clearTimeout(timer);
|
|
172
|
-
timer = setTimeout(() => void
|
|
178
|
+
timer = setTimeout(() => void refresh().catch(() => void 0), options.reloadMs);
|
|
173
179
|
};
|
|
174
180
|
let watcher;
|
|
175
181
|
let seen = "";
|
|
182
|
+
const userPackageTargets = async (using) => {
|
|
183
|
+
const listed = await env.listDir(USER_PACKAGES, using);
|
|
184
|
+
if (listed.ok)
|
|
185
|
+
return [
|
|
186
|
+
{ path: USER_PACKAGES },
|
|
187
|
+
...listed.value.filter((entry) => entry.name.startsWith("@")).map((entry) => ({ path: `${USER_PACKAGES}/${entry.name}` }))
|
|
188
|
+
];
|
|
189
|
+
let path = dirname(USER_PACKAGES);
|
|
190
|
+
while (path !== "/" && !(await env.listDir(path, using)).ok) path = dirname(path);
|
|
191
|
+
return [{ path }];
|
|
192
|
+
};
|
|
176
193
|
const watch = async (using) => {
|
|
177
194
|
const extra = options.people ? userRoots(homes()).map((root) => ({ path: root.dir, recursive: true })) : [
|
|
178
195
|
{ path: `${dir}/skills`, recursive: true },
|
|
179
196
|
{ path: `${home}/.agents/skills`, recursive: true }
|
|
180
197
|
];
|
|
181
|
-
const
|
|
198
|
+
const packageTargets = await userPackageTargets(using);
|
|
199
|
+
const key = JSON.stringify([extra, packageTargets]);
|
|
182
200
|
if (key === seen) return;
|
|
183
201
|
seen = key;
|
|
184
202
|
await watcher?.close(using);
|
|
185
203
|
const watched = await env.watch(
|
|
186
|
-
[
|
|
204
|
+
[
|
|
205
|
+
{ path: GLOBAL_DIR, recursive: true },
|
|
206
|
+
{ path: `${dir}/prompts` },
|
|
207
|
+
...packageTargets,
|
|
208
|
+
...extra
|
|
209
|
+
],
|
|
187
210
|
schedule,
|
|
188
211
|
using
|
|
189
212
|
);
|
package/dist/skills/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/skills/index.ts"],
|
|
4
|
-
"sourcesContent": ["import { type Context, type ReplicatedState, replicatedState } from '@earendil-works/chord';\nimport {\n defineExtension,\n type Extension,\n type Registry,\n section,\n} from '@earendil-works/pi-durable';\nimport type { ExecutionEnv, FileWatcher } from '@earendil-works/pi-durable/env';\nimport type { Licks } from '../licks/licks.ts';\nimport { PACKAGE_ROOTS, type PiPackages, piPackages } from '../roles/roles.ts';\nimport type { Command } from '../services.ts';\nimport {\n type Diagnostic,\n expandSkillCommand,\n formatSkillsForPrompt,\n loadSkills,\n type Skill,\n type SkillRoot,\n} from './skills.ts';\nimport { expandPromptTemplate, loadTemplates, type PromptTemplate } from './templates.ts';\n\nexport const BUILTIN_SKILLS = [\n 'agent',\n 'browser',\n 'gelatiere',\n 'licks',\n 'memory',\n 'skill-authoring',\n 'sprinkles',\n 'welcome',\n];\nexport const BUILTIN_PROMPTS = ['parallel-review', 'review-loop'];\nexport const SKILLS_DIR = '/var/lib/slicc/agent/skills';\nexport const PROMPTS_DIR = '/var/lib/slicc/agent/prompts';\nexport const GLOBAL_DIR = '/usr/share/skills';\nexport const RELOAD_MS = 300;\n\nexport interface SkillsRuntime {\n readonly commands: ReplicatedState<Command[]>;\n skills(): readonly Skill[];\n dirs(): string[];\n templates(): readonly PromptTemplate[];\n expand(text: string, context: Context, conversationId?: number): Promise<string>;\n reload(context: Context): Promise<void>;\n close(context: Context): Promise<void>;\n}\n\nexport interface SkillsAttach {\n env: ExecutionEnv;\n home: string;\n agentDir?: string;\n assets?: (path: string) => Promise<string>;\n reloadMs: number;\n people?: SkillPeople;\n}\n\nexport interface SkillPeople {\n homes(): readonly string[];\n homeOf(conversationId: number | undefined): string | undefined;\n envOf(home: string): Promise<ExecutionEnv | undefined>;\n}\n\nexport function userRoots(homes: readonly string[]): SkillRoot[] {\n return homes.flatMap((home) => [\n { dir: `${home}/.pi/agent/skills`, source: 'user' as const },\n { dir: `${home}/.agents/skills`, source: 'user' as const },\n ]);\n}\n\nexport interface SkillsSetup {\n extension: Extension;\n attach(options: SkillsAttach, context: Context): Promise<SkillsRuntime>;\n}\n\ntype Manifest = { pi?: { skills?: unknown; prompts?: unknown } };\n\nexport function piResources(dir: string, text: string, kind: 'skills' | 'prompts'): string[] {\n let manifest: Manifest;\n try {\n manifest = JSON.parse(text) as Manifest;\n } catch {\n return [];\n }\n const listed = manifest.pi?.[kind];\n const paths = Array.isArray(listed) ? listed : typeof listed === 'string' ? [listed] : [];\n return paths\n .filter((path): path is string => typeof path === 'string')\n .map((path) => `${dir}/${path.replace(/^\\.\\//, '').replace(/\\/$/, '')}`);\n}\n\nfunction packaged(found: PiPackages, kind: 'skills' | 'prompts') {\n return found.packages.flatMap(({ dir, manifest }) => piResources(dir, manifest, kind));\n}\n\nasync function installBuiltins(\n env: ExecutionEnv,\n assets: (path: string) => Promise<string>,\n context: Context\n): Promise<void> {\n await env.remove(SKILLS_DIR, { recursive: true, force: true }, context);\n await env.remove(PROMPTS_DIR, { recursive: true, force: true }, context);\n for (const name of BUILTIN_SKILLS) {\n const text = await assets(`packages/vfs-root/skills/${name}/SKILL.md`).catch(() => undefined);\n if (text === undefined) continue;\n await env.createDir(`${SKILLS_DIR}/${name}`, { recursive: true }, context);\n await env.writeFile(`${SKILLS_DIR}/${name}/SKILL.md`, text, context);\n }\n await env.createDir(PROMPTS_DIR, { recursive: true }, context);\n for (const name of BUILTIN_PROMPTS) {\n const text = await assets(`packages/vfs-root/prompts/${name}.md`).catch(() => undefined);\n if (text !== undefined) await env.writeFile(`${PROMPTS_DIR}/${name}.md`, text, context);\n }\n}\n\nexport function problemLick(problem: Diagnostic, home: string) {\n const path = problem.path.startsWith(`${home}/`)\n ? `~${problem.path.slice(home.length)}`\n : problem.path;\n return {\n channel: 'fswatch' as const,\n source: `skills:${path}`,\n title: `Skill or prompt template problem: ${path}`,\n text: problem.message,\n body: 'The file is used with this problem, or skipped if it has no description.\\nThe rules are in the slicc-agent README.',\n target: 'cone' as const,\n severity: 'warn' as const,\n eventId: `${path}\\n${problem.message}`,\n };\n}\n\nexport const SECRETS_ACTION: Command = {\n name: 'secrets',\n description: 'List the secrets the agent can use, and where each works',\n kind: 'action',\n};\n\nexport function commandsOf(\n skills: readonly Skill[],\n templates: readonly PromptTemplate[]\n): Command[] {\n return [\n ...templates.map((template) => ({\n name: template.name,\n description: template.description,\n kind: 'prompt' as const,\n })),\n ...skills.map((skill) => ({\n name: `skill:${skill.name}`,\n description: skill.description,\n kind: 'skill' as const,\n })),\n SECRETS_ACTION,\n ];\n}\n\nexport function setupSkills(registry: Registry, licks: Licks): SkillsSetup {\n let current: Skill[] = [];\n let own = new Map<string, Skill[]>();\n let people: SkillPeople | undefined;\n const mine = (conversationId: number | undefined) => {\n const at = people?.homeOf(conversationId);\n return (at ? own.get(at) : undefined) ?? current;\n };\n const extension = defineExtension({\n name: 'slicc-skills',\n sections: [\n section('skills', async (input) => {\n return formatSkillsForPrompt(mine(input.conversationId)) || undefined;\n }),\n ],\n });\n registry.install(extension);\n return {\n extension,\n async attach(options, context) {\n const { env, home } = options;\n const dir = options.agentDir ?? `${home}/.pi/agent`;\n people = options.people;\n const homes = () => options.people?.homes() ?? [];\n if (options.assets)\n await installBuiltins(env, options.assets, context).catch(() => undefined);\n await env.exec(`mkdir -p ${GLOBAL_DIR} && chmod 755 ${GLOBAL_DIR}`, undefined, context);\n let templates: PromptTemplate[] = [];\n const commands = replicatedState<Command[]>([]);\n const reported = new Set<string>();\n const reload = async (using: Context) => {\n const packages = await piPackages(env, PACKAGE_ROOTS, using);\n const roots: SkillRoot[] = [\n ...(options.people\n ? [{ dir: GLOBAL_DIR, source: 'global' as const }]\n : [\n { dir: `${dir}/skills`, source: 'user' as const },\n { dir: `${home}/.agents/skills`, source: 'user' as const },\n { dir: GLOBAL_DIR, source: 'global' as const },\n ]),\n { dir: SKILLS_DIR, source: 'builtin' },\n ...packaged(packages, 'skills').map((dir) => ({ dir, source: 'package' as const })),\n ];\n const loaded = await loadSkills(env, roots, using);\n const homesLoaded = new Map<string, Skill[]>();\n for (const at of homes()) {\n const files = await options.people?.envOf(at);\n if (!files) continue;\n const found = await loadSkills(files, [...userRoots([at]), ...roots], using);\n homesLoaded.set(at, found.skills);\n loaded.diagnostics.push(...found.diagnostics);\n }\n own = homesLoaded;\n const prompts = await loadTemplates(\n env,\n [`${dir}/prompts`, PROMPTS_DIR, ...packaged(packages, 'prompts')],\n using\n );\n current = loaded.skills;\n templates = prompts.templates;\n commands.replace(using, commandsOf(current, templates));\n for (const problem of [\n ...packages.skipped,\n ...loaded.diagnostics,\n ...prompts.diagnostics,\n ]) {\n const key = `${problem.path}\\n${problem.message}`;\n if (reported.has(key)) continue;\n reported.add(key);\n await licks.deliver(problemLick(problem, home), using).catch(() => undefined);\n }\n };\n await reload(context);\n let timer: ReturnType<typeof setTimeout> | undefined;\n const schedule = () => {\n clearTimeout(timer);\n timer = setTimeout(() => void reload(context).catch(() => undefined), options.reloadMs);\n };\n let watcher: FileWatcher | undefined;\n let seen = '';\n const watch = async (using: Context) => {\n const extra = options.people\n ? userRoots(homes()).map((root) => ({ path: root.dir, recursive: true }))\n : [\n { path: `${dir}/skills`, recursive: true },\n { path: `${home}/.agents/skills`, recursive: true },\n ];\n const key = JSON.stringify(extra);\n if (key === seen) return;\n seen = key;\n await watcher?.close(using);\n const watched = await env.watch(\n [{ path: GLOBAL_DIR, recursive: true }, { path: `${dir}/prompts` }, ...extra],\n schedule,\n using\n );\n watcher = watched.ok ? watched.value : undefined;\n };\n await watch(context);\n return {\n commands,\n skills: () => current,\n dirs: () => current.map((skill) => skill.baseDir),\n templates: () => templates,\n async expand(text, using, conversationId) {\n const at = people?.homeOf(conversationId);\n const files = at ? await people?.envOf(at) : env;\n if (!files) return text;\n const expanded = await expandSkillCommand(text, mine(conversationId), files, using);\n return expanded === text ? expandPromptTemplate(text, templates) : expanded;\n },\n async reload(using) {\n await watch(using);\n await reload(using);\n },\n async close(using) {\n clearTimeout(timer);\n await watcher?.close(using);\n },\n };\n },\n };\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAA6C,uBAAuB;AACpE;AAAA,EACE;AAAA,EAGA;AAAA,OACK;
|
|
4
|
+
"sourcesContent": ["import { type Context, type ReplicatedState, replicatedState } from '@earendil-works/chord';\nimport {\n defineExtension,\n type Extension,\n type Registry,\n section,\n} from '@earendil-works/pi-durable';\nimport type { ExecutionEnv, FileWatcher } from '@earendil-works/pi-durable/env';\nimport { dirname } from '../kernel/paths.ts';\nimport type { Licks } from '../licks/licks.ts';\nimport { PACKAGE_ROOTS, type PiPackages, piPackages } from '../roles/roles.ts';\nimport type { Command } from '../services.ts';\nimport {\n type Diagnostic,\n expandSkillCommand,\n formatSkillsForPrompt,\n loadSkills,\n type Skill,\n type SkillRoot,\n} from './skills.ts';\nimport { expandPromptTemplate, loadTemplates, type PromptTemplate } from './templates.ts';\n\nexport const BUILTIN_SKILLS = [\n 'agent',\n 'browser',\n 'gelatiere',\n 'licks',\n 'memory',\n 'skill-authoring',\n 'sprinkles',\n 'welcome',\n];\nexport const BUILTIN_PROMPTS = ['parallel-review', 'review-loop'];\nexport const SKILLS_DIR = '/var/lib/slicc/agent/skills';\nexport const PROMPTS_DIR = '/var/lib/slicc/agent/prompts';\nexport const GLOBAL_DIR = '/usr/share/skills';\nexport const RELOAD_MS = 300;\nconst USER_PACKAGES = '/opt/user/node_modules';\n\nexport interface SkillsRuntime {\n readonly commands: ReplicatedState<Command[]>;\n skills(): readonly Skill[];\n dirs(): string[];\n templates(): readonly PromptTemplate[];\n expand(text: string, context: Context, conversationId?: number): Promise<string>;\n reload(context: Context): Promise<void>;\n close(context: Context): Promise<void>;\n}\n\nexport interface SkillsAttach {\n env: ExecutionEnv;\n home: string;\n agentDir?: string;\n assets?: (path: string) => Promise<string>;\n reloadMs: number;\n people?: SkillPeople;\n}\n\nexport interface SkillPeople {\n homes(): readonly string[];\n homeOf(conversationId: number | undefined): string | undefined;\n envOf(home: string): Promise<ExecutionEnv | undefined>;\n}\n\nexport function userRoots(homes: readonly string[]): SkillRoot[] {\n return homes.flatMap((home) => [\n { dir: `${home}/.pi/agent/skills`, source: 'user' as const },\n { dir: `${home}/.agents/skills`, source: 'user' as const },\n ]);\n}\n\nexport interface SkillsSetup {\n extension: Extension;\n attach(options: SkillsAttach, context: Context): Promise<SkillsRuntime>;\n}\n\ntype Manifest = { pi?: { skills?: unknown; prompts?: unknown } };\n\nexport function piResources(dir: string, text: string, kind: 'skills' | 'prompts'): string[] {\n let manifest: Manifest;\n try {\n manifest = JSON.parse(text) as Manifest;\n } catch {\n return [];\n }\n const listed = manifest.pi?.[kind];\n const paths = Array.isArray(listed) ? listed : typeof listed === 'string' ? [listed] : [];\n return paths\n .filter((path): path is string => typeof path === 'string')\n .map((path) => `${dir}/${path.replace(/^\\.\\//, '').replace(/\\/$/, '')}`);\n}\n\nfunction packaged(found: PiPackages, kind: 'skills' | 'prompts') {\n return found.packages.flatMap(({ dir, manifest }) => piResources(dir, manifest, kind));\n}\n\nasync function installBuiltins(\n env: ExecutionEnv,\n assets: (path: string) => Promise<string>,\n context: Context\n): Promise<void> {\n await env.remove(SKILLS_DIR, { recursive: true, force: true }, context);\n await env.remove(PROMPTS_DIR, { recursive: true, force: true }, context);\n for (const name of BUILTIN_SKILLS) {\n const text = await assets(`packages/vfs-root/skills/${name}/SKILL.md`).catch(() => undefined);\n if (text === undefined) continue;\n await env.createDir(`${SKILLS_DIR}/${name}`, { recursive: true }, context);\n await env.writeFile(`${SKILLS_DIR}/${name}/SKILL.md`, text, context);\n }\n await env.createDir(PROMPTS_DIR, { recursive: true }, context);\n for (const name of BUILTIN_PROMPTS) {\n const text = await assets(`packages/vfs-root/prompts/${name}.md`).catch(() => undefined);\n if (text !== undefined) await env.writeFile(`${PROMPTS_DIR}/${name}.md`, text, context);\n }\n}\n\nexport function problemLick(problem: Diagnostic, home: string) {\n const path = problem.path.startsWith(`${home}/`)\n ? `~${problem.path.slice(home.length)}`\n : problem.path;\n return {\n channel: 'fswatch' as const,\n source: `skills:${path}`,\n title: `Skill or prompt template problem: ${path}`,\n text: problem.message,\n body: 'The file is used with this problem, or skipped if it has no description.\\nThe rules are in the slicc-agent README.',\n target: 'cone' as const,\n severity: 'warn' as const,\n eventId: `${path}\\n${problem.message}`,\n };\n}\n\nexport const SECRETS_ACTION: Command = {\n name: 'secrets',\n description: 'List the secrets the agent can use, and where each works',\n kind: 'action',\n};\n\nexport function commandsOf(\n skills: readonly Skill[],\n templates: readonly PromptTemplate[]\n): Command[] {\n return [\n ...templates.map((template) => ({\n name: template.name,\n description: template.description,\n kind: 'prompt' as const,\n })),\n ...skills.map((skill) => ({\n name: `skill:${skill.name}`,\n description: skill.description,\n kind: 'skill' as const,\n })),\n SECRETS_ACTION,\n ];\n}\n\nexport function setupSkills(registry: Registry, licks: Licks): SkillsSetup {\n let current: Skill[] = [];\n let own = new Map<string, Skill[]>();\n let people: SkillPeople | undefined;\n const mine = (conversationId: number | undefined) => {\n const at = people?.homeOf(conversationId);\n return (at ? own.get(at) : undefined) ?? current;\n };\n const extension = defineExtension({\n name: 'slicc-skills',\n sections: [\n section('skills', async (input) => {\n return formatSkillsForPrompt(mine(input.conversationId)) || undefined;\n }),\n ],\n });\n registry.install(extension);\n return {\n extension,\n async attach(options, context) {\n const { env, home } = options;\n const dir = options.agentDir ?? `${home}/.pi/agent`;\n people = options.people;\n const homes = () => options.people?.homes() ?? [];\n if (options.assets)\n await installBuiltins(env, options.assets, context).catch(() => undefined);\n await env.exec(`mkdir -p ${GLOBAL_DIR} && chmod 755 ${GLOBAL_DIR}`, undefined, context);\n let templates: PromptTemplate[] = [];\n const commands = replicatedState<Command[]>([]);\n const reported = new Set<string>();\n const reload = async (using: Context) => {\n const packages = await piPackages(env, PACKAGE_ROOTS, using);\n const roots: SkillRoot[] = [\n ...(options.people\n ? [{ dir: GLOBAL_DIR, source: 'global' as const }]\n : [\n { dir: `${dir}/skills`, source: 'user' as const },\n { dir: `${home}/.agents/skills`, source: 'user' as const },\n { dir: GLOBAL_DIR, source: 'global' as const },\n ]),\n { dir: SKILLS_DIR, source: 'builtin' },\n ...packaged(packages, 'skills').map((dir) => ({ dir, source: 'package' as const })),\n ];\n const loaded = await loadSkills(env, roots, using);\n const homesLoaded = new Map<string, Skill[]>();\n for (const at of homes()) {\n const files = await options.people?.envOf(at);\n if (!files) continue;\n const found = await loadSkills(files, [...userRoots([at]), ...roots], using);\n homesLoaded.set(at, found.skills);\n loaded.diagnostics.push(...found.diagnostics);\n }\n own = homesLoaded;\n const prompts = await loadTemplates(\n env,\n [`${dir}/prompts`, PROMPTS_DIR, ...packaged(packages, 'prompts')],\n using\n );\n current = loaded.skills;\n templates = prompts.templates;\n commands.replace(using, commandsOf(current, templates));\n for (const problem of [\n ...packages.skipped,\n ...loaded.diagnostics,\n ...prompts.diagnostics,\n ]) {\n const key = `${problem.path}\\n${problem.message}`;\n if (reported.has(key)) continue;\n reported.add(key);\n await licks.deliver(problemLick(problem, home), using).catch(() => undefined);\n }\n };\n await reload(context);\n let timer: ReturnType<typeof setTimeout> | undefined;\n const refresh = async () => {\n await watch(context);\n await reload(context);\n };\n const schedule = () => {\n clearTimeout(timer);\n timer = setTimeout(() => void refresh().catch(() => undefined), options.reloadMs);\n };\n let watcher: FileWatcher | undefined;\n let seen = '';\n const userPackageTargets = async (using: Context) => {\n const listed = await env.listDir(USER_PACKAGES, using);\n if (listed.ok)\n return [\n { path: USER_PACKAGES },\n ...listed.value\n .filter((entry) => entry.name.startsWith('@'))\n .map((entry) => ({ path: `${USER_PACKAGES}/${entry.name}` })),\n ];\n let path = dirname(USER_PACKAGES);\n while (path !== '/' && !(await env.listDir(path, using)).ok) path = dirname(path);\n return [{ path }];\n };\n const watch = async (using: Context) => {\n const extra = options.people\n ? userRoots(homes()).map((root) => ({ path: root.dir, recursive: true }))\n : [\n { path: `${dir}/skills`, recursive: true },\n { path: `${home}/.agents/skills`, recursive: true },\n ];\n const packageTargets = await userPackageTargets(using);\n const key = JSON.stringify([extra, packageTargets]);\n if (key === seen) return;\n seen = key;\n await watcher?.close(using);\n const watched = await env.watch(\n [\n { path: GLOBAL_DIR, recursive: true },\n { path: `${dir}/prompts` },\n ...packageTargets,\n ...extra,\n ],\n schedule,\n using\n );\n watcher = watched.ok ? watched.value : undefined;\n };\n await watch(context);\n return {\n commands,\n skills: () => current,\n dirs: () => current.map((skill) => skill.baseDir),\n templates: () => templates,\n async expand(text, using, conversationId) {\n const at = people?.homeOf(conversationId);\n const files = at ? await people?.envOf(at) : env;\n if (!files) return text;\n const expanded = await expandSkillCommand(text, mine(conversationId), files, using);\n return expanded === text ? expandPromptTemplate(text, templates) : expanded;\n },\n async reload(using) {\n await watch(using);\n await reload(using);\n },\n async close(using) {\n clearTimeout(timer);\n await watcher?.close(using);\n },\n };\n },\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["dir"]
|
|
7
7
|
}
|
|
@@ -11,6 +11,7 @@ const defaults = {
|
|
|
11
11
|
showThinking: false,
|
|
12
12
|
diffStyle: "unified"
|
|
13
13
|
};
|
|
14
|
+
const SIGN_IN_NEEDS_VAULT = "Adobe sign-in needs seven's vault: update seven";
|
|
14
15
|
class SettingsAdapter extends Emitter {
|
|
15
16
|
#settings;
|
|
16
17
|
#agent;
|
|
@@ -67,13 +68,29 @@ class SettingsAdapter extends Emitter {
|
|
|
67
68
|
return needs ? { ...shown, needs } : shown;
|
|
68
69
|
});
|
|
69
70
|
}
|
|
70
|
-
async connect(id, secret,
|
|
71
|
+
async connect(id, secret, fields) {
|
|
71
72
|
const account = this.#state().accounts.find((candidate) => candidate.id === id);
|
|
72
|
-
const
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
const mcp = account?.group === "mcp";
|
|
74
|
+
const login = account?.auth !== "oauth" ? null : mcp ? this.#mcpLogin : this.#login;
|
|
75
|
+
const given = fields ? { ...fields } : null;
|
|
76
|
+
if (secret !== void 0) {
|
|
77
|
+
await this.#settings.connect(id, secret, given, BACKGROUND_CONTEXT);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (account?.auth === "oauth" && !login) throw new Error(`${id} needs a sign-in`);
|
|
81
|
+
if (!login) {
|
|
82
|
+
if (account?.store !== "vault") throw new Error(`${id} needs an API key`);
|
|
83
|
+
await this.#settings.connect(id, null, given, BACKGROUND_CONTEXT);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const answer = await this.#signIn(id, login);
|
|
87
|
+
if (typeof answer === "string") {
|
|
88
|
+
if (!mcp) throw new Error(SIGN_IN_NEEDS_VAULT);
|
|
89
|
+
await this.#settings.connect(id, answer, given, BACKGROUND_CONTEXT);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (answer?.sealed !== true) throw new Error(`${id}'s sign-in didn't finish`);
|
|
93
|
+
await this.#settings.connect(id, null, given, BACKGROUND_CONTEXT);
|
|
77
94
|
}
|
|
78
95
|
async #signIn(id, login) {
|
|
79
96
|
const controller = new AbortController();
|
|
@@ -112,6 +129,7 @@ class SettingsAdapter extends Emitter {
|
|
|
112
129
|
}
|
|
113
130
|
export {
|
|
114
131
|
SETTINGS_KEY,
|
|
132
|
+
SIGN_IN_NEEDS_VAULT,
|
|
115
133
|
SettingsAdapter
|
|
116
134
|
};
|
|
117
135
|
//# sourceMappingURL=settings-port.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/spectrum/settings-port.ts"],
|
|
4
|
-
"sourcesContent": ["import type {\n Account,\n ModelOption,\n Settings,\n SettingsEvents,\n SettingsPort,\n} from '@ai-ecoverse/slicc-spectrum/ui';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { AgentSettings, SettingsState, SignIn } from '../services.ts';\nimport type { AgentAdapter } from './agent-port.ts';\nimport { attempt } from './attempt.ts';\nimport { Emitter } from './emitter.ts';\nimport { mcpLogin } from './mcp-login.ts';\n\nexport const SETTINGS_KEY = 'slicc-agent.settings';\n\nconst defaults: Settings = {\n color: 'system',\n model: '',\n thinking: 'off',\n sendOnEnter: true,\n showThinking: false,\n diffStyle: 'unified',\n};\n\ntype Local = Omit<Settings, 'model' | 'thinking'>;\n\nexport type Login = (\n providerId: string,\n signIn: () => Promise<SignIn | null>,\n options: { signal: AbortSignal }\n) => Promise<string>;\n\nexport class SettingsAdapter extends Emitter<SettingsEvents> implements SettingsPort {\n readonly #settings: AgentSettings;\n readonly #agent: AgentAdapter;\n readonly #storage: Pick<Storage, 'getItem' | 'setItem'> | null;\n readonly #login: Login | null;\n readonly #mcpLogin: Login;\n readonly #signing = new Map<string, AbortController>();\n #local: Local;\n\n constructor(\n settings: AgentSettings,\n agent: AgentAdapter,\n storage: Pick<Storage, 'getItem' | 'setItem'> | null,\n login: Login | null = null,\n mcp: Login = mcpLogin() as Login\n ) {\n super();\n this.#mcpLogin = mcp;\n this.#settings = settings;\n this.#agent = agent;\n this.#storage = storage;\n this.#login = login;\n const saved = JSON.parse(storage?.getItem(SETTINGS_KEY) ?? '{}') as Partial<Local>;\n const { model: _model, thinking: _thinking, ...local } = { ...defaults, ...saved };\n this.#local = local;\n settings.state.subscribe(() => {\n this.emit('accounts', this.accounts());\n this.emit('settings', this.get());\n });\n agent.on('agents', () => this.emit('settings', this.get()));\n }\n\n #state(): SettingsState {\n return this.#settings.state.value ?? { models: [], accounts: [] };\n }\n\n get(): Settings {\n const cone = this.#agent.list()[0];\n return { ...this.#local, model: cone?.model ?? '', thinking: cone?.thinking ?? 'off' };\n }\n\n update(patch: Partial<Settings>): void {\n const { model, thinking, ...local } = patch;\n const id = this.#agent.active();\n if (model !== undefined) this.#agent.setModel(id, model);\n if (thinking !== undefined) this.#agent.setThinking(id, thinking);\n this.#local = { ...this.#local, ...local };\n this.#storage?.setItem(SETTINGS_KEY, JSON.stringify(this.#local));\n this.emit('settings', this.get());\n }\n\n models(): readonly ModelOption[] {\n return this.#state().models.map(({ id, label, provider, kind, reasoning, images }) => ({\n id,\n label,\n provider,\n kind,\n reasoning,\n ...(images === undefined ? {} : { images }),\n }));\n }\n\n accounts(): readonly Account[] {\n return this.#state().accounts.map(({ needs, ...account }) => {\n const shown = this.#signing.has(account.id)\n ? { ...account, status: 'signing-in' as const }\n : account;\n return needs ? { ...shown, needs } : shown;\n });\n }\n\n async connect(id: string, secret?: string,
|
|
5
|
-
"mappings": "AAOA,SAAS,0BAA0B;AAGnC,SAAS,eAAe;AACxB,SAAS,eAAe;AACxB,SAAS,gBAAgB;AAElB,MAAM,eAAe;AAE5B,MAAM,WAAqB;AAAA,EACzB,OAAO;AAAA,EACP,OAAO;AAAA,EACP,UAAU;AAAA,EACV,aAAa;AAAA,EACb,cAAc;AAAA,EACd,WAAW;AACb;
|
|
4
|
+
"sourcesContent": ["import type {\n Account,\n ModelOption,\n Settings,\n SettingsEvents,\n SettingsPort,\n} from '@ai-ecoverse/slicc-spectrum/ui';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { AgentSettings, SettingsState, SignIn } from '../services.ts';\nimport type { AgentAdapter } from './agent-port.ts';\nimport { attempt } from './attempt.ts';\nimport { Emitter } from './emitter.ts';\nimport { mcpLogin } from './mcp-login.ts';\n\nexport const SETTINGS_KEY = 'slicc-agent.settings';\n\nconst defaults: Settings = {\n color: 'system',\n model: '',\n thinking: 'off',\n sendOnEnter: true,\n showThinking: false,\n diffStyle: 'unified',\n};\n\ntype Local = Omit<Settings, 'model' | 'thinking'>;\n\nexport type Sealed = { sealed: true };\n\nexport type Login = (\n providerId: string,\n signIn: () => Promise<SignIn | null>,\n options: { signal: AbortSignal }\n) => Promise<string | Sealed>;\n\nexport const SIGN_IN_NEEDS_VAULT = \"Adobe sign-in needs seven's vault: update seven\";\n\nexport class SettingsAdapter extends Emitter<SettingsEvents> implements SettingsPort {\n readonly #settings: AgentSettings;\n readonly #agent: AgentAdapter;\n readonly #storage: Pick<Storage, 'getItem' | 'setItem'> | null;\n readonly #login: Login | null;\n readonly #mcpLogin: Login;\n readonly #signing = new Map<string, AbortController>();\n #local: Local;\n\n constructor(\n settings: AgentSettings,\n agent: AgentAdapter,\n storage: Pick<Storage, 'getItem' | 'setItem'> | null,\n login: Login | null = null,\n mcp: Login = mcpLogin() as Login\n ) {\n super();\n this.#mcpLogin = mcp;\n this.#settings = settings;\n this.#agent = agent;\n this.#storage = storage;\n this.#login = login;\n const saved = JSON.parse(storage?.getItem(SETTINGS_KEY) ?? '{}') as Partial<Local>;\n const { model: _model, thinking: _thinking, ...local } = { ...defaults, ...saved };\n this.#local = local;\n settings.state.subscribe(() => {\n this.emit('accounts', this.accounts());\n this.emit('settings', this.get());\n });\n agent.on('agents', () => this.emit('settings', this.get()));\n }\n\n #state(): SettingsState {\n return this.#settings.state.value ?? { models: [], accounts: [] };\n }\n\n get(): Settings {\n const cone = this.#agent.list()[0];\n return { ...this.#local, model: cone?.model ?? '', thinking: cone?.thinking ?? 'off' };\n }\n\n update(patch: Partial<Settings>): void {\n const { model, thinking, ...local } = patch;\n const id = this.#agent.active();\n if (model !== undefined) this.#agent.setModel(id, model);\n if (thinking !== undefined) this.#agent.setThinking(id, thinking);\n this.#local = { ...this.#local, ...local };\n this.#storage?.setItem(SETTINGS_KEY, JSON.stringify(this.#local));\n this.emit('settings', this.get());\n }\n\n models(): readonly ModelOption[] {\n return this.#state().models.map(({ id, label, provider, kind, reasoning, images }) => ({\n id,\n label,\n provider,\n kind,\n reasoning,\n ...(images === undefined ? {} : { images }),\n }));\n }\n\n accounts(): readonly Account[] {\n return this.#state().accounts.map(({ needs, ...account }) => {\n const shown = this.#signing.has(account.id)\n ? { ...account, status: 'signing-in' as const }\n : account;\n return needs ? { ...shown, needs } : shown;\n });\n }\n\n async connect(id: string, secret?: string, fields?: Record<string, string>): Promise<void> {\n const account = this.#state().accounts.find((candidate) => candidate.id === id);\n const mcp = account?.group === 'mcp';\n const login = account?.auth !== 'oauth' ? null : mcp ? this.#mcpLogin : this.#login;\n const given = fields ? { ...fields } : null;\n if (secret !== undefined) {\n await this.#settings.connect(id, secret, given, BACKGROUND_CONTEXT);\n return;\n }\n if (account?.auth === 'oauth' && !login) throw new Error(`${id} needs a sign-in`);\n if (!login) {\n if (account?.store !== 'vault') throw new Error(`${id} needs an API key`);\n await this.#settings.connect(id, null, given, BACKGROUND_CONTEXT);\n return;\n }\n const answer = await this.#signIn(id, login);\n if (typeof answer === 'string') {\n if (!mcp) throw new Error(SIGN_IN_NEEDS_VAULT);\n await this.#settings.connect(id, answer, given, BACKGROUND_CONTEXT);\n return;\n }\n if (answer?.sealed !== true) throw new Error(`${id}'s sign-in didn't finish`);\n await this.#settings.connect(id, null, given, BACKGROUND_CONTEXT);\n }\n\n async #signIn(id: string, login: Login): Promise<string | Sealed> {\n const controller = new AbortController();\n this.#signing\n .get(id)\n ?.abort(new DOMException('A newer sign-in replaced this one.', 'AbortError'));\n this.#signing.set(id, controller);\n this.emit('accounts', this.accounts());\n try {\n const key = await login(\n id,\n () => this.#settings.signIn(id, BACKGROUND_CONTEXT) as Promise<SignIn | null>,\n {\n signal: controller.signal,\n }\n );\n controller.signal.throwIfAborted();\n return key;\n } finally {\n if (this.#signing.get(id) === controller) this.#signing.delete(id);\n this.emit('accounts', this.accounts());\n }\n }\n\n cancel(id: string): void {\n const controller = this.#signing.get(id);\n if (!controller) return;\n this.#signing.delete(id);\n controller.abort(new DOMException('The sign-in was cancelled.', 'AbortError'));\n this.emit('accounts', this.accounts());\n }\n\n disconnect(id: string): void {\n attempt(this.#settings.disconnect(id, BACKGROUND_CONTEXT), 'disconnect accounts', (text) =>\n this.#agent.notify(text)\n );\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/types/host.d.ts
CHANGED
|
@@ -46,7 +46,7 @@ export declare function hostAgent(agent: Agent, options?: {
|
|
|
46
46
|
changes?: ChangesRuntime;
|
|
47
47
|
mcp?: Pick<McpRuntime, 'close'>;
|
|
48
48
|
users?: UserClients;
|
|
49
|
-
monitor?: Pick<MonitorOptions, 'kernel' | 'groups' | 'users'
|
|
49
|
+
monitor?: Pick<MonitorOptions, 'kernel' | 'groups' | 'users'>;
|
|
50
50
|
pages?: Pages;
|
|
51
51
|
secrets?: HostSecrets;
|
|
52
52
|
uploads?: Uploads;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -3,7 +3,6 @@ export { type Agent, type AgentOptions, answerText, openAgent } from './agent.ts
|
|
|
3
3
|
export { FILE_LIMIT, IMAGE_LIMIT, type SendAttachment, type ShownAttachment, splitUser, TOTAL_LIMIT, userParts, } from './attachments.ts';
|
|
4
4
|
export { type AgentConnection, connectAgent } from './client.ts';
|
|
5
5
|
export { createAgentControl } from './control.ts';
|
|
6
|
-
export { CREDENTIALS_DATABASE, EncryptedCredentialStore } from './credentials.ts';
|
|
7
6
|
export { type AgentHost, type ConnectOptions, hostAgent } from './host.ts';
|
|
8
7
|
export type { KernelClient, KernelFs, KernelProcess, KernelStat, SpawnOptions, } from './kernel/client.ts';
|
|
9
8
|
export { HOME, type KernelEnvOptions, kernelEnvironment, SliccKernelEnv } from './kernel/env.ts';
|
package/dist/types/main.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Provider } from '@earendil-works/pi-ai';
|
|
2
2
|
import type { Models } from '@earendil-works/pi-ai/models';
|
|
3
3
|
import { type ModelRef, type Storage } from '@earendil-works/pi-durable';
|
|
4
4
|
import { type AgentHost } from './host.ts';
|
|
@@ -6,6 +6,9 @@ import type { KernelClient } from './kernel/client.ts';
|
|
|
6
6
|
import { type UserClients } from './kernel/users.ts';
|
|
7
7
|
import { type Transport } from './net.ts';
|
|
8
8
|
import { type Assets } from './scoops/index.ts';
|
|
9
|
+
import { type ModelBases } from './secrets/endpoints.ts';
|
|
10
|
+
import { type PlainStore } from './secrets/store.ts';
|
|
11
|
+
import { createSliccModels } from './settings.ts';
|
|
9
12
|
import { type WorkerScope } from './worker.ts';
|
|
10
13
|
export interface AgentWorkerScope extends WorkerScope {
|
|
11
14
|
fetch: typeof fetch;
|
|
@@ -20,7 +23,7 @@ export interface AgentWorkerOptions {
|
|
|
20
23
|
model?: ModelRef;
|
|
21
24
|
providers?: Provider[];
|
|
22
25
|
attach?: KernelAttach;
|
|
23
|
-
|
|
26
|
+
store?: () => Promise<PlainStore>;
|
|
24
27
|
storage?: () => Promise<Storage>;
|
|
25
28
|
assets?: Assets;
|
|
26
29
|
codemodeWasm?: () => Promise<WebAssembly.Module | undefined>;
|
|
@@ -31,7 +34,9 @@ export interface AgentWorkerOptions {
|
|
|
31
34
|
}
|
|
32
35
|
export declare function usersOf(admin: MessagePort | undefined, wanted: boolean | undefined, attach: KernelAttach): UserClients | undefined;
|
|
33
36
|
export declare const STORE_DIR = "/.slicc";
|
|
37
|
+
export declare const ACCOUNTS_FILE = "/.slicc/accounts.json";
|
|
34
38
|
export declare function seesImages(models: Pick<Models, 'getModel'>, ref: ModelRef | undefined): boolean;
|
|
35
39
|
export declare const MCP_CALLBACK = "/oauth/mcp-callback";
|
|
40
|
+
export declare function modelBases(providers: readonly Provider[], models: Pick<ReturnType<typeof createSliccModels>, 'getModels'>): ModelBases[];
|
|
36
41
|
export declare function alive(client: KernelClient): (pid: number) => Promise<boolean>;
|
|
37
42
|
export declare function runAgentWorker(scope: AgentWorkerScope, options?: AgentWorkerOptions): Promise<AgentHost>;
|
|
@@ -1,20 +1,26 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Context } from '@earendil-works/chord';
|
|
2
2
|
import type { McpFetch } from '@earendil-works/pi-mcp';
|
|
3
3
|
import type { AccountState } from '../services.ts';
|
|
4
4
|
import type { McpCatalog } from './catalog.ts';
|
|
5
5
|
import type { McpServerEntry } from './config.ts';
|
|
6
6
|
import type { McpServerConnection } from './connection.ts';
|
|
7
|
+
import { type McpRecords } from './credentials.ts';
|
|
7
8
|
import { type McpSignIn, type StoredOAuth } from './oauth.ts';
|
|
9
|
+
export declare const TOKENS_IN_VAULT = "MCP tokens are kept in seven's vault: update seven";
|
|
8
10
|
export interface McpAccounts {
|
|
9
11
|
accounts(): Promise<AccountState[]>;
|
|
10
12
|
signIn(id: string): Promise<McpSignIn>;
|
|
11
|
-
connect(id: string, secret: string): Promise<void>;
|
|
13
|
+
connect(id: string, secret: string | null): Promise<void>;
|
|
12
14
|
disconnect(id: string): Promise<void>;
|
|
13
15
|
onChange(listener: () => void): () => void;
|
|
14
16
|
}
|
|
15
17
|
export interface AccountSources {
|
|
16
|
-
|
|
18
|
+
records: McpRecords & {
|
|
19
|
+
refresh(context: Context): Promise<void>;
|
|
20
|
+
};
|
|
17
21
|
oauth: (entry: McpServerEntry) => StoredOAuth;
|
|
18
|
-
fetch: McpFetch;
|
|
22
|
+
fetch: (server: string) => McpFetch;
|
|
23
|
+
grant: (server: string) => McpFetch;
|
|
24
|
+
register: (server: string, tokenUrl: string) => Promise<void>;
|
|
19
25
|
}
|
|
20
26
|
export declare function mcpAccounts(catalog: McpCatalog, sources: AccountSources, restart: (connection: McpServerConnection) => void, listeners: Set<() => void>): McpAccounts;
|
|
@@ -3,7 +3,6 @@ import { type McpServerEntry } from './config.ts';
|
|
|
3
3
|
export type ServerState = 'connecting' | 'connected' | 'needs-auth' | 'needs-secret' | 'failed' | 'closed';
|
|
4
4
|
export type TransportFactory = (entry: McpServerEntry) => Promise<{
|
|
5
5
|
transport: McpTransport;
|
|
6
|
-
secrets: string[];
|
|
7
6
|
} | {
|
|
8
7
|
missing: string[];
|
|
9
8
|
}>;
|
|
@@ -36,7 +35,6 @@ export declare class McpServerConnection {
|
|
|
36
35
|
resources: Resource[];
|
|
37
36
|
resourceTemplates: ResourceTemplate[];
|
|
38
37
|
instructions: string | undefined;
|
|
39
|
-
secrets: string[];
|
|
40
38
|
constructor(options: ConnectionOptions);
|
|
41
39
|
get name(): string;
|
|
42
40
|
get timeoutMs(): number;
|