@alpacakit/agents-conventions 0.1.0-beta.36 → 0.1.0-beta.39

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
package/dist/cli.js ADDED
@@ -0,0 +1,388 @@
1
+ /**
2
+ * `@alpacakit/agents-conventions/cli` — the `agent` command surface, as DATA.
3
+ *
4
+ * There is no `bin` or CLI runtime here: this module owns the vocabulary (the
5
+ * command path, flags, procedure input projection, shared procedure bridge,
6
+ * and result schema) so that `alpacaloop agent login`, `promptopt agent login`
7
+ * and `semantic-trigger agent login` are the same command. Each product mounts
8
+ * `AGENT_CLI_SURFACE.node`, supplies an invocation context after parsing, and
9
+ * owns presentation of the typed outcome.
10
+ *
11
+ * `@alpacakit/channels` and `zod` are peers: importing the procedures must not
12
+ * drag a CLI framework in.
13
+ */
14
+ import { BUILTIN_AGENT_ID, LOGIN_METHOD, } from "@alpacakit/agents";
15
+ import { OPENAI_COMPATIBLE_ENGINE } from "@alpacakit/agents/config";
16
+ import { codecs, createOutputContract, defineEntry, defineEntryEndpoint, defineEntryNode, defineParameter, optional, required, VALUE_SHAPE_KIND, } from "@alpacakit/channels";
17
+ import { bindCliEntry, CLI_BOOLEAN_MODE, overrideCliSegment, } from "@alpacakit/channels/cli";
18
+ import { z } from "zod";
19
+ import { agentAddOutputSchema, agentCredentialAddOutputSchema, agentListOutputSchema, agentLoginOutputSchema, agentRemoveOutputSchema, } from "./cli-output.js";
20
+ import { listAgentsHome, } from "./home.js";
21
+ import { AGENTS_HOME_RECORD_NAME_PATTERN, AGENTS_HOME_RECORD_NAME_RULE, } from "./names.js";
22
+ import { addAgentConfig, addApiKeyProfile, loginManagedHome, } from "./register.js";
23
+ import { removeAgentsHomeEntry, } from "./remove.js";
24
+ import { AGENT_ADD_KIND } from "./values.js";
25
+ export const AGENT_ENTRY_NAME = {
26
+ list: "agent-list",
27
+ login: "agent-login",
28
+ credentialAdd: "agent-credential-add",
29
+ add: "agent-add",
30
+ remove: "agent-remove",
31
+ };
32
+ const AGENT_CLI_TOKEN = {
33
+ agent: "agent",
34
+ list: "list",
35
+ login: "login",
36
+ credential: "credential",
37
+ add: "add",
38
+ remove: "remove",
39
+ };
40
+ const LOGIN_AGENT_IDS = [
41
+ BUILTIN_AGENT_ID.claude,
42
+ BUILTIN_AGENT_ID.codex,
43
+ ];
44
+ const LOGIN_METHODS = [LOGIN_METHOD.oauth, LOGIN_METHOD.device];
45
+ const ENGINES = [
46
+ OPENAI_COMPATIBLE_ENGINE.fetch,
47
+ OPENAI_COMPATIBLE_ENGINE.pi,
48
+ ];
49
+ const ADD_KINDS = [AGENT_ADD_KIND.openaiCompatible];
50
+ const AGENT_CLI_DESCRIPTION = {
51
+ agent: "Shared agents home: list, sign in, add, and remove agents.",
52
+ credential: "Agent credentials.",
53
+ list: "List registered agents and their execution readiness.",
54
+ login: "Sign in to an agent and register the credential as a profile.",
55
+ credentialAdd: "Store an API key for an agent and register it as a profile.",
56
+ add: "Add an agent that speaks an OpenAI-compatible endpoint.",
57
+ remove: "Remove a profile or an added agent by name.",
58
+ };
59
+ const AGENT_CLI_PARAMETER_DESCRIPTION = {
60
+ profileId: "Profile name to create.",
61
+ loginAgentId: `Agent to sign in: ${LOGIN_AGENT_IDS.join(", ")}.`,
62
+ credentialAgentId: "Agent the key authenticates; a built-in id or an added agent id.",
63
+ method: `Sign-in method: ${LOGIN_METHODS.join(", ")}. Defaults to ${LOGIN_METHOD.oauth}.`,
64
+ stdin: "Read the API key from standard input.",
65
+ addId: "Agent name to create; also the agent id runs refer to.",
66
+ addKind: `Agent kind: ${ADD_KINDS.join(", ")}.`,
67
+ baseUrl: "OpenAI-compatible endpoint base URL.",
68
+ model: "Model the agent requests.",
69
+ apiKeyEnv: "Environment variable holding the API key; stored as a template, never the key itself.",
70
+ engine: `Execution engine: ${ENGINES.join(", ")}. Defaults to ${OPENAI_COMPATIBLE_ENGINE.fetch}.`,
71
+ removeName: "Profile name, or the name of an added agent.",
72
+ };
73
+ /**
74
+ * Record names reach the filesystem and the keychain, so the surface refuses
75
+ * anything outside the family grammar here rather than letting a handler
76
+ * discover it. The procedures repeat the check for callers that skip the CLI.
77
+ */
78
+ function recordNameCodec() {
79
+ return codecs.define({
80
+ schema: z
81
+ .string()
82
+ .regex(AGENTS_HOME_RECORD_NAME_PATTERN, AGENTS_HOME_RECORD_NAME_RULE),
83
+ shape: { kind: VALUE_SHAPE_KIND.string },
84
+ });
85
+ }
86
+ /** `--stdin` is a source selection flag, so only its selected state is input. */
87
+ function stdinSelectionCodec() {
88
+ return codecs.define({
89
+ schema: z.literal(true),
90
+ shape: { kind: VALUE_SHAPE_KIND.boolean },
91
+ });
92
+ }
93
+ const AGENT_CLI_HELP = {
94
+ agent: {
95
+ examples: [
96
+ {
97
+ title: "Inspect the shared agents home",
98
+ useWhen: "checking which agents this machine can run",
99
+ command: "agent list",
100
+ },
101
+ ],
102
+ },
103
+ };
104
+ const listEntry = defineEntry({
105
+ name: AGENT_ENTRY_NAME.list,
106
+ parameters: [],
107
+ project: () => ({}),
108
+ output: createOutputContract(agentListOutputSchema),
109
+ });
110
+ const loginEntry = defineEntry({
111
+ name: AGENT_ENTRY_NAME.login,
112
+ parameters: [
113
+ defineParameter({
114
+ name: "profileId",
115
+ codec: recordNameCodec(),
116
+ requirement: required(),
117
+ description: AGENT_CLI_PARAMETER_DESCRIPTION.profileId,
118
+ }),
119
+ defineParameter({
120
+ name: "agentId",
121
+ codec: codecs.stringEnum(LOGIN_AGENT_IDS),
122
+ requirement: required(),
123
+ description: AGENT_CLI_PARAMETER_DESCRIPTION.loginAgentId,
124
+ }),
125
+ defineParameter({
126
+ name: "method",
127
+ codec: codecs.stringEnum(LOGIN_METHODS),
128
+ requirement: optional({ default: LOGIN_METHOD.oauth }),
129
+ description: AGENT_CLI_PARAMETER_DESCRIPTION.method,
130
+ }),
131
+ ],
132
+ project: ({ values }) => values,
133
+ output: createOutputContract(agentLoginOutputSchema),
134
+ });
135
+ const credentialAddEntry = defineEntry({
136
+ name: AGENT_ENTRY_NAME.credentialAdd,
137
+ parameters: [
138
+ defineParameter({
139
+ name: "profileId",
140
+ codec: recordNameCodec(),
141
+ requirement: required(),
142
+ description: AGENT_CLI_PARAMETER_DESCRIPTION.profileId,
143
+ }),
144
+ // Not an enum: `agent add` mints ids this command must be able to name.
145
+ defineParameter({
146
+ name: "agentId",
147
+ codec: codecs.string(),
148
+ requirement: required(),
149
+ description: AGENT_CLI_PARAMETER_DESCRIPTION.credentialAgentId,
150
+ }),
151
+ defineParameter({
152
+ // Required, not defaulted: stdin is the ONLY way in for the key, so
153
+ // `false` could never be a request this command can serve.
154
+ name: "stdin",
155
+ codec: stdinSelectionCodec(),
156
+ requirement: required(),
157
+ description: AGENT_CLI_PARAMETER_DESCRIPTION.stdin,
158
+ }),
159
+ ],
160
+ project: ({ values }) => values,
161
+ output: createOutputContract(agentCredentialAddOutputSchema),
162
+ });
163
+ const addEntry = defineEntry({
164
+ name: AGENT_ENTRY_NAME.add,
165
+ parameters: [
166
+ defineParameter({
167
+ name: "id",
168
+ codec: recordNameCodec(),
169
+ requirement: required(),
170
+ description: AGENT_CLI_PARAMETER_DESCRIPTION.addId,
171
+ }),
172
+ defineParameter({
173
+ name: "kind",
174
+ codec: codecs.stringEnum(ADD_KINDS),
175
+ requirement: required(),
176
+ description: AGENT_CLI_PARAMETER_DESCRIPTION.addKind,
177
+ }),
178
+ defineParameter({
179
+ name: "baseUrl",
180
+ codec: codecs.string(),
181
+ requirement: required(),
182
+ description: AGENT_CLI_PARAMETER_DESCRIPTION.baseUrl,
183
+ }),
184
+ defineParameter({
185
+ name: "model",
186
+ codec: codecs.string(),
187
+ requirement: required(),
188
+ description: AGENT_CLI_PARAMETER_DESCRIPTION.model,
189
+ }),
190
+ defineParameter({
191
+ name: "apiKeyEnv",
192
+ codec: codecs.string(),
193
+ requirement: optional(),
194
+ description: AGENT_CLI_PARAMETER_DESCRIPTION.apiKeyEnv,
195
+ }),
196
+ defineParameter({
197
+ // Optional with NO default: omitting `--engine` must reach
198
+ // `addAgentConfig` as an absent field, so the agent-config payload
199
+ // stays the one place that decides what "unset" means.
200
+ name: "engine",
201
+ codec: codecs.stringEnum(ENGINES),
202
+ requirement: optional(),
203
+ description: AGENT_CLI_PARAMETER_DESCRIPTION.engine,
204
+ }),
205
+ ],
206
+ project: ({ values }) => values,
207
+ output: createOutputContract(agentAddOutputSchema),
208
+ });
209
+ const removeEntry = defineEntry({
210
+ name: AGENT_ENTRY_NAME.remove,
211
+ parameters: [
212
+ defineParameter({
213
+ name: "name",
214
+ codec: recordNameCodec(),
215
+ requirement: required(),
216
+ description: AGENT_CLI_PARAMETER_DESCRIPTION.removeName,
217
+ }),
218
+ ],
219
+ project: ({ values }) => values,
220
+ output: createOutputContract(agentRemoveOutputSchema),
221
+ });
222
+ export async function executeAgentList(_input, context) {
223
+ const result = await listAgentsHome(context);
224
+ return { operation: AGENT_ENTRY_NAME.list, result };
225
+ }
226
+ export async function executeAgentLogin(input, context) {
227
+ const result = await loginManagedHome({
228
+ ...context,
229
+ ...input,
230
+ onEvent: context.onLoginEvent,
231
+ });
232
+ return { operation: AGENT_ENTRY_NAME.login, result };
233
+ }
234
+ export async function executeAgentCredentialAdd(input, context) {
235
+ const apiKey = await context.readCredentialSecret();
236
+ const result = await addApiKeyProfile({
237
+ ...context,
238
+ profileId: input.profileId,
239
+ agentId: input.agentId,
240
+ apiKey,
241
+ });
242
+ return { operation: AGENT_ENTRY_NAME.credentialAdd, result };
243
+ }
244
+ export async function executeAgentAdd(input, context) {
245
+ const result = await addAgentConfig({
246
+ ...context,
247
+ ...input,
248
+ });
249
+ return { operation: AGENT_ENTRY_NAME.add, result };
250
+ }
251
+ export async function executeAgentRemove(input, context) {
252
+ const result = await removeAgentsHomeEntry({
253
+ ...context,
254
+ ...input,
255
+ });
256
+ return { operation: AGENT_ENTRY_NAME.remove, result };
257
+ }
258
+ const listEndpoint = defineEntryEndpoint(listEntry, {
259
+ handler: executeAgentList,
260
+ channels: [bindCliEntry({ parameters: [] })],
261
+ });
262
+ const loginEndpoint = defineEntryEndpoint(loginEntry, {
263
+ handler: executeAgentLogin,
264
+ channels: [
265
+ bindCliEntry({
266
+ parameters: [
267
+ {
268
+ kind: "positional",
269
+ parameterName: "profileId",
270
+ valueName: "PROFILE",
271
+ },
272
+ { kind: "option", parameterName: "agentId", flags: ["--agent"] },
273
+ { kind: "option", parameterName: "method", flags: ["--method"] },
274
+ ],
275
+ }),
276
+ ],
277
+ });
278
+ const credentialAddEndpoint = defineEntryEndpoint(credentialAddEntry, {
279
+ handler: executeAgentCredentialAdd,
280
+ channels: [
281
+ bindCliEntry({
282
+ parameters: [
283
+ {
284
+ kind: "positional",
285
+ parameterName: "profileId",
286
+ valueName: "PROFILE",
287
+ },
288
+ { kind: "option", parameterName: "agentId", flags: ["--agent"] },
289
+ {
290
+ kind: "option",
291
+ parameterName: "stdin",
292
+ flags: ["--stdin"],
293
+ // A required boolean would otherwise take a value (`--stdin true`).
294
+ booleanMode: CLI_BOOLEAN_MODE.flag,
295
+ },
296
+ ],
297
+ }),
298
+ ],
299
+ });
300
+ const addEndpoint = defineEntryEndpoint(addEntry, {
301
+ handler: executeAgentAdd,
302
+ channels: [
303
+ bindCliEntry({
304
+ parameters: [
305
+ { kind: "positional", parameterName: "id", valueName: "ID" },
306
+ { kind: "option", parameterName: "kind", flags: ["--kind"] },
307
+ { kind: "option", parameterName: "baseUrl", flags: ["--base-url"] },
308
+ { kind: "option", parameterName: "model", flags: ["--model"] },
309
+ {
310
+ kind: "option",
311
+ parameterName: "apiKeyEnv",
312
+ flags: ["--api-key-env"],
313
+ },
314
+ { kind: "option", parameterName: "engine", flags: ["--engine"] },
315
+ ],
316
+ }),
317
+ ],
318
+ });
319
+ const removeEndpoint = defineEntryEndpoint(removeEntry, {
320
+ handler: executeAgentRemove,
321
+ channels: [
322
+ bindCliEntry({
323
+ parameters: [
324
+ { kind: "positional", parameterName: "name", valueName: "NAME" },
325
+ ],
326
+ }),
327
+ ],
328
+ });
329
+ const agentNode = defineEntryNode({
330
+ name: AGENT_CLI_TOKEN.agent,
331
+ description: AGENT_CLI_DESCRIPTION.agent,
332
+ segments: [
333
+ overrideCliSegment({
334
+ token: AGENT_CLI_TOKEN.agent,
335
+ help: AGENT_CLI_HELP.agent,
336
+ }),
337
+ ],
338
+ children: [
339
+ defineEntryNode({
340
+ name: AGENT_CLI_TOKEN.list,
341
+ description: AGENT_CLI_DESCRIPTION.list,
342
+ endpoints: [listEndpoint],
343
+ }),
344
+ defineEntryNode({
345
+ name: AGENT_CLI_TOKEN.login,
346
+ description: AGENT_CLI_DESCRIPTION.login,
347
+ endpoints: [loginEndpoint],
348
+ }),
349
+ defineEntryNode({
350
+ name: AGENT_CLI_TOKEN.credential,
351
+ description: AGENT_CLI_DESCRIPTION.credential,
352
+ children: [
353
+ defineEntryNode({
354
+ name: AGENT_CLI_TOKEN.add,
355
+ description: AGENT_CLI_DESCRIPTION.credentialAdd,
356
+ endpoints: [credentialAddEndpoint],
357
+ }),
358
+ ],
359
+ }),
360
+ defineEntryNode({
361
+ name: AGENT_CLI_TOKEN.add,
362
+ description: AGENT_CLI_DESCRIPTION.add,
363
+ endpoints: [addEndpoint],
364
+ }),
365
+ defineEntryNode({
366
+ name: AGENT_CLI_TOKEN.remove,
367
+ description: AGENT_CLI_DESCRIPTION.remove,
368
+ endpoints: [removeEndpoint],
369
+ }),
370
+ ],
371
+ });
372
+ export const AGENT_CLI_SURFACE = {
373
+ node: agentNode,
374
+ endpoints: {
375
+ list: listEndpoint,
376
+ login: loginEndpoint,
377
+ credentialAdd: credentialAddEndpoint,
378
+ add: addEndpoint,
379
+ remove: removeEndpoint,
380
+ },
381
+ outputs: {
382
+ list: listEntry.output,
383
+ login: loginEntry.output,
384
+ credentialAdd: credentialAddEntry.output,
385
+ add: addEntry.output,
386
+ remove: removeEntry.output,
387
+ },
388
+ };
package/dist/home.d.ts ADDED
@@ -0,0 +1,65 @@
1
+ /**
2
+ * The shared seam every family procedure opens: one `~/.alpaca/agents` home,
3
+ * one runtime bound to the caller's environment, and one keychain store.
4
+ * Nothing here reaches for ambient state — `homeDir`, `env`, ports and the
5
+ * keyring are all inbound, so a test drives the whole procedure against a
6
+ * temp directory and fakes.
7
+ */
8
+ import { type AgentAvailability, type AgentRuntime, type HostLocation, type Ports } from "@alpacakit/agents";
9
+ import { type AgentsConfig, type AgentsRuntimeConfig, type CandidateSource } from "@alpacakit/agents/config";
10
+ import { type KeyringSecretStore } from "@alpacakit/core/keyring";
11
+ import { type AgentsConfigOptionsInput } from "./paths.js";
12
+ /**
13
+ * What every procedure takes. `ports` and `keyring` exist so tests can drive
14
+ * the real code path without a subprocess or a real keychain; both default to
15
+ * the production implementations.
16
+ */
17
+ export type AgentsHomeInput = AgentsConfigOptionsInput & {
18
+ readonly ports?: Partial<Ports>;
19
+ readonly keyring?: KeyringSecretStore;
20
+ };
21
+ export type AgentsHomeEntry = {
22
+ readonly agentId: string;
23
+ readonly agentConfigId: string;
24
+ /** The agent config kind the entry comes from (`codex`, `openai-compatible`, …). */
25
+ readonly kind: string;
26
+ readonly source: CandidateSource;
27
+ readonly profileId: string | null;
28
+ /** `null` when the agent declares no availability probe (I3 `agent add` kinds). */
29
+ readonly availability: AgentAvailability | null;
30
+ };
31
+ export type AgentsHomeListing = {
32
+ readonly agentsHome: string;
33
+ readonly entries: readonly AgentsHomeEntry[];
34
+ };
35
+ export type OpenedAgentsHome = {
36
+ readonly agentsHome: string;
37
+ readonly config: AgentsConfig;
38
+ readonly location: HostLocation;
39
+ readonly keyring: KeyringSecretStore;
40
+ readonly ports: Partial<Ports>;
41
+ readonly baseEnv: Record<string, string>;
42
+ };
43
+ export declare function openAgentsHome(input: AgentsHomeInput): OpenedAgentsHome;
44
+ /**
45
+ * Every agent this machine can currently reach, in the home's own order, with
46
+ * the readiness each one actually has: a profile-backed candidate is probed
47
+ * with that profile's environment applied, exactly as `createFleet` applies it
48
+ * before a run — otherwise `agent list` would report the ambient login for a
49
+ * profile that has its own.
50
+ */
51
+ export declare function listAgentsHome(input: AgentsHomeInput): Promise<AgentsHomeListing>;
52
+ export type RuntimeFactory = {
53
+ /** The runtime bound to the caller's own environment. */
54
+ readonly ambient: AgentRuntime;
55
+ /** A runtime bound to the caller's environment plus one profile's patch. */
56
+ withEnvPatch(baseEnv: Record<string, string>): AgentRuntime;
57
+ readonly baseEnv: Record<string, string>;
58
+ };
59
+ /**
60
+ * Builds runtimes over the home's agents. The config's own secret resolvers
61
+ * are merged into `ports.secrets`, so an api-key profile resolves through the
62
+ * family keyring resolver rather than failing as an unknown resolver name.
63
+ */
64
+ export declare function createRuntimeFactory(home: OpenedAgentsHome, config: AgentsRuntimeConfig): RuntimeFactory;
65
+ //# sourceMappingURL=home.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"home.d.ts","sourceRoot":"","sources":["../src/home.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAIjB,KAAK,YAAY,EACjB,KAAK,KAAK,EAEX,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EAGrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,KAAK,kBAAkB,EAExB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,KAAK,wBAAwB,EAG9B,MAAM,YAAY,CAAC;AAGpB;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,wBAAwB,GAAG;IACvD,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAChC,QAAQ,CAAC,OAAO,CAAC,EAAE,kBAAkB,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,oFAAoF;IACpF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,mFAAmF;IACnF,QAAQ,CAAC,YAAY,EAAE,iBAAiB,GAAG,IAAI,CAAC;CACjD,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,CAAC;CAC9C,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C,CAAC;AAOF,wBAAgB,cAAc,CAAC,KAAK,EAAE,eAAe,GAAG,gBAAgB,CAUvE;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,eAAe,GACrB,OAAO,CAAC,iBAAiB,CAAC,CAgB5B;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,yDAAyD;IACzD,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,4EAA4E;IAC5E,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,YAAY,CAAC;IAC5D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,mBAAmB,GAC1B,cAAc,CAahB"}
package/dist/home.js ADDED
@@ -0,0 +1,105 @@
1
+ /**
2
+ * The shared seam every family procedure opens: one `~/.alpaca/agents` home,
3
+ * one runtime bound to the caller's environment, and one keychain store.
4
+ * Nothing here reaches for ambient state — `homeDir`, `env`, ports and the
5
+ * keyring are all inbound, so a test drives the whole procedure against a
6
+ * temp directory and fakes.
7
+ */
8
+ import { AGENT_AVAILABILITY_STATUS, AGENT_INDETERMINATE_REASON, applyEnvPatch, createAgentRuntime, resolvePorts, } from "@alpacakit/agents";
9
+ import { openAgentsConfig, secretsForRuntime, } from "@alpacakit/agents/config";
10
+ import { keyringSecretStore, } from "@alpacakit/core/keyring";
11
+ import { resolveAgentsConfigOptions, resolveAgentsHome, } from "./paths.js";
12
+ import { AGENTS_KEYRING_SERVICE } from "./values.js";
13
+ const AVAILABILITY_DETAIL = {
14
+ profileEnvUnresolved: "Profile credentials could not be resolved, so availability was not probed.",
15
+ };
16
+ export function openAgentsHome(input) {
17
+ return {
18
+ agentsHome: resolveAgentsHome(input),
19
+ config: openAgentsConfig(resolveAgentsConfigOptions(input)),
20
+ location: { homeDir: input.homeDir },
21
+ keyring: input.keyring ?? keyringSecretStore({ service: AGENTS_KEYRING_SERVICE }),
22
+ ports: input.ports ?? {},
23
+ baseEnv: definedEnv(input.env),
24
+ };
25
+ }
26
+ /**
27
+ * Every agent this machine can currently reach, in the home's own order, with
28
+ * the readiness each one actually has: a profile-backed candidate is probed
29
+ * with that profile's environment applied, exactly as `createFleet` applies it
30
+ * before a run — otherwise `agent list` would report the ambient login for a
31
+ * profile that has its own.
32
+ */
33
+ export async function listAgentsHome(input) {
34
+ const home = openAgentsHome(input);
35
+ const config = await home.config.loadRuntimeConfig();
36
+ const runtimes = createRuntimeFactory(home, config);
37
+ const entries = [];
38
+ for (const { candidate, source } of config.candidates) {
39
+ entries.push({
40
+ agentId: candidate.agentId,
41
+ agentConfigId: source.agentConfigId,
42
+ kind: source.agentConfigKind,
43
+ source: source.kind,
44
+ profileId: source.profileId,
45
+ availability: await probeCandidate(runtimes, home.location, candidate),
46
+ });
47
+ }
48
+ return { agentsHome: home.agentsHome, entries };
49
+ }
50
+ /**
51
+ * Builds runtimes over the home's agents. The config's own secret resolvers
52
+ * are merged into `ports.secrets`, so an api-key profile resolves through the
53
+ * family keyring resolver rather than failing as an unknown resolver name.
54
+ */
55
+ export function createRuntimeFactory(home, config) {
56
+ const resolved = resolvePorts(home.ports);
57
+ const ports = {
58
+ ...resolved,
59
+ secrets: { ...resolved.secrets, ...secretsForRuntime(config) },
60
+ };
61
+ const withEnvPatch = (baseEnv) => createAgentRuntime({ agents: config.agents, baseEnv, ports });
62
+ return {
63
+ ambient: withEnvPatch(home.baseEnv),
64
+ withEnvPatch,
65
+ baseEnv: home.baseEnv,
66
+ };
67
+ }
68
+ async function probeCandidate(runtimes, location, candidate) {
69
+ const agent = runtimes.ambient.agent(candidate.agentId);
70
+ if (agent.availability === null) {
71
+ return null;
72
+ }
73
+ const { profile } = candidate;
74
+ if (profile === undefined) {
75
+ return await agent.availability.probe(location);
76
+ }
77
+ if (agent.auth === null) {
78
+ return null;
79
+ }
80
+ let scoped;
81
+ try {
82
+ scoped = runtimes.withEnvPatch(applyEnvPatch(runtimes.baseEnv, await agent.auth.toEnv(profile.material)));
83
+ }
84
+ catch {
85
+ // A credential we cannot read is not an answer about the agent: report
86
+ // that the probe could not run rather than failing the whole listing or
87
+ // silently reporting the ambient login instead of the profile's.
88
+ return {
89
+ status: AGENT_AVAILABILITY_STATUS.indeterminate,
90
+ reason: AGENT_INDETERMINATE_REASON.probeFault,
91
+ detail: AVAILABILITY_DETAIL.profileEnvUnresolved,
92
+ };
93
+ }
94
+ return ((await scoped.agent(candidate.agentId).availability?.probe(location)) ??
95
+ null);
96
+ }
97
+ function definedEnv(env) {
98
+ const defined = {};
99
+ for (const [name, value] of Object.entries(env)) {
100
+ if (value !== undefined) {
101
+ defined[name] = value;
102
+ }
103
+ }
104
+ return defined;
105
+ }
package/dist/index.d.ts CHANGED
@@ -1,29 +1,27 @@
1
1
  /**
2
- * AlpacaLoop-family conventions for `@alpacakit/agents` machine-local
3
- * config. This lives OUTSIDE the neutral `@alpacakit/agents` package on
4
- * purpose: it encodes AlpacaLoop-specific paths, keyring service names, and
5
- * the managed-home layout that no general OSS consumer needs. It builds on
6
- * the agents package's PUBLIC API only, so it is a plain consumer — the
7
- * same shape any third party would write for their own family convention.
2
+ * AlpacaKit-family conventions for `@alpacakit/agents` machine-local config.
3
+ * This lives OUTSIDE the neutral `@alpacakit/agents` package on purpose: it
4
+ * encodes the family's shared home, keyring service names, managed-home
5
+ * layout, and the ORDER and FAILURE POLICY of registering an agent — none of
6
+ * which a general OSS consumer needs. It builds on the agents package's
7
+ * PUBLIC API only, so it is a plain consumer: the same shape any third party
8
+ * would write for their own family convention.
8
9
  *
9
- * Not published (`private`): the public source doubles as the worked
10
- * example, without adding org policy to the npm surface.
10
+ * Products call the procedures here and print the result; they never re-decide
11
+ * the order or the failure policy. The `agent` command surface that mounts
12
+ * them lives on `./cli` (data only), so importing the procedures never pulls
13
+ * in `@alpacakit/channels`.
11
14
  */
12
- import type { SecretRef } from "@alpacakit/agents";
13
- import type { OpenAgentsConfigOptions } from "@alpacakit/agents/config";
14
- export declare const ALPACA_LOOP_AGENTS_CONFIG_ENV_VAR = "ALPACA_AGENTS_HOME";
15
- export declare const ALPACA_LOOP_AGENTS_CONFIG_DIRECTORY = ".alpaca/agents";
16
- export declare const ALPACA_LOOP_AGENTS_CONFIG_KEYRING_SERVICE = "alpacaloop.agents-home";
17
- export declare const ALPACA_LOOP_AGENTS_CONFIG_KEYRING_RESOLVER = "agents-home-keyring";
18
- export type AgentsConfigOptionsInput = {
19
- readonly homeDir: string;
20
- readonly env: Readonly<Record<string, string | undefined>>;
21
- };
22
- export type ManagedHomePathInput = {
23
- readonly rootDir: string;
24
- readonly profileId: string;
25
- };
26
- export declare function resolveAgentsConfigOptions(input: AgentsConfigOptionsInput): OpenAgentsConfigOptions;
27
- export declare function createKeyringSecretRef(profileId: string): SecretRef;
28
- export declare function resolveManagedHomePath(input: ManagedHomePathInput): string;
15
+ export type { AgentsHomeEntry, AgentsHomeInput, AgentsHomeListing, OpenedAgentsHome, RuntimeFactory, } from "./home.js";
16
+ export { createRuntimeFactory, listAgentsHome, openAgentsHome, } from "./home.js";
17
+ export type { InvalidNameResult } from "./names.js";
18
+ export { AGENTS_HOME_RECORD_NAME_MAX_LENGTH, AGENTS_HOME_RECORD_NAME_PATTERN, AGENTS_HOME_RECORD_NAME_RULE, INVALID_NAME_RESULT_KIND, isAgentsHomeRecordName, rejectInvalidName, } from "./names.js";
19
+ export type { AgentsConfigOptionsInput, ManagedHomePathInput, } from "./paths.js";
20
+ export { createKeyringSecretRef, isManagedHomePath, resolveAgentsConfigOptions, resolveAgentsHome, resolveManagedHomePath, } from "./paths.js";
21
+ export type { AddAgentConfigInput, AddAgentConfigResult, AddApiKeyProfileInput, AddApiKeyProfileResult, AgentConfigRequest, LoginManagedHomeInput, LoginManagedHomeResult, OpenAiCompatibleAgentConfigRequest, } from "./register.js";
22
+ export { ADD_AGENT_CONFIG_RESULT, ADD_API_KEY_PROFILE_RESULT, addAgentConfig, addApiKeyProfile, LOGIN_MANAGED_HOME_RESULT, loginManagedHome, } from "./register.js";
23
+ export type { RemoveAgentsHomeEntryInput, RemoveAgentsHomeEntryResult, } from "./remove.js";
24
+ export { REMOVE_AGENTS_HOME_ENTRY_RESULT, removeAgentsHomeEntry, } from "./remove.js";
25
+ export type { AgentAddKind } from "./values.js";
26
+ export { AGENT_ADD_KIND, AGENTS_HOME_DIRECTORY, AGENTS_HOME_ENV_VAR, AGENTS_KEYRING_ACCOUNT, AGENTS_KEYRING_RESOLVER, AGENTS_KEYRING_SERVICE, AGENTS_MANAGED_HOMES_DIRECTORY, } from "./values.js";
29
27
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAEV,uBAAuB,EACxB,MAAM,0BAA0B,CAAC;AAGlC,eAAO,MAAM,iCAAiC,uBAAuB,CAAC;AACtE,eAAO,MAAM,mCAAmC,mBAAmB,CAAC;AACpE,eAAO,MAAM,yCAAyC,2BAC5B,CAAC;AAC3B,eAAO,MAAM,0CAA0C,wBAAwB,CAAC;AAQhF,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;CAC5D,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,wBAAwB,GAC9B,uBAAuB,CAKzB;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CASnE;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,CAM1E"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,YAAY,EACV,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,GACf,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,oBAAoB,EACpB,cAAc,EACd,cAAc,GACf,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EACL,kCAAkC,EAClC,+BAA+B,EAC/B,4BAA4B,EAC5B,wBAAwB,EACxB,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,0BAA0B,EAC1B,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,EACtB,kBAAkB,EAClB,qBAAqB,EACrB,sBAAsB,EACtB,kCAAkC,GACnC,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,uBAAuB,EACvB,0BAA0B,EAC1B,cAAc,EACd,gBAAgB,EAChB,yBAAyB,EACzB,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,+BAA+B,EAC/B,qBAAqB,GACtB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,mBAAmB,EACnB,sBAAsB,EACtB,uBAAuB,EACvB,sBAAsB,EACtB,8BAA8B,GAC/B,MAAM,aAAa,CAAC"}