@anhlp/alp 0.0.1-beta.4 → 0.0.1-beta.6

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.
Files changed (199) hide show
  1. package/README.md +14 -412
  2. package/bin/alp.js +5 -0
  3. package/lib/launcher.js +136 -0
  4. package/package.json +18 -105
  5. package/dist/THIRD-PARTY-NOTICES.txt +0 -626
  6. package/dist/acp.js +0 -19936
  7. package/dist/alpd.js +0 -49562
  8. package/docs/modular-monorepo.md +0 -214
  9. package/packages/cli/README.md +0 -7
  10. package/packages/cli/dist/THIRD-PARTY-NOTICES.txt +0 -651
  11. package/packages/cli/dist/acp/agent.d.ts +0 -37
  12. package/packages/cli/dist/acp/agent.js +0 -489
  13. package/packages/cli/dist/acp/main.d.ts +0 -4
  14. package/packages/cli/dist/acp/main.js +0 -23
  15. package/packages/cli/dist/acp.js +0 -19936
  16. package/packages/cli/dist/alp-web/THIRD-PARTY-NOTICES.txt +0 -2590
  17. package/packages/cli/dist/alp-web/alp-boundary.json +0 -15
  18. package/packages/cli/dist/alp-web/apple-touch-icon.png +0 -0
  19. package/packages/cli/dist/alp-web/assets/TerminalPanel-DLuoa74B.css +0 -1
  20. package/packages/cli/dist/alp-web/assets/TerminalPanel-PrU2l3u5.js +0 -16
  21. package/packages/cli/dist/alp-web/assets/index-BJdBTDFX.css +0 -1
  22. package/packages/cli/dist/alp-web/assets/index-DpfiPv5s.js +0 -52
  23. package/packages/cli/dist/alp-web/favicon-attention.svg +0 -6
  24. package/packages/cli/dist/alp-web/favicon-running.svg +0 -6
  25. package/packages/cli/dist/alp-web/favicon.svg +0 -5
  26. package/packages/cli/dist/alp-web/index.html +0 -20
  27. package/packages/cli/dist/alp-web.js +0 -9640
  28. package/packages/cli/dist/alpd.js +0 -49562
  29. package/packages/cli/dist/backup.d.ts +0 -4
  30. package/packages/cli/dist/backup.js +0 -146
  31. package/packages/cli/dist/build-manifest.json +0 -240
  32. package/packages/cli/dist/cli.d.ts +0 -2
  33. package/packages/cli/dist/cli.js +0 -30
  34. package/packages/cli/dist/daemon.d.ts +0 -35
  35. package/packages/cli/dist/daemon.js +0 -126
  36. package/packages/cli/dist/index.d.ts +0 -1
  37. package/packages/cli/dist/index.js +0 -5
  38. package/packages/cli/dist/interfaces.d.ts +0 -24
  39. package/packages/cli/dist/interfaces.js +0 -156
  40. package/packages/cli/dist/library.d.ts +0 -140
  41. package/packages/cli/dist/library.js +0 -319
  42. package/packages/cli/dist/paths.d.ts +0 -3
  43. package/packages/cli/dist/paths.js +0 -18
  44. package/packages/cli/dist/projects.d.ts +0 -9
  45. package/packages/cli/dist/projects.js +0 -159
  46. package/packages/cli/dist/schedules.d.ts +0 -2
  47. package/packages/cli/dist/schedules.js +0 -45
  48. package/packages/cli/dist/sessions.d.ts +0 -43
  49. package/packages/cli/dist/sessions.js +0 -458
  50. package/packages/cli/dist/tasks.d.ts +0 -29
  51. package/packages/cli/dist/tasks.js +0 -345
  52. package/packages/cli/dist/terminal.d.ts +0 -8
  53. package/packages/cli/dist/terminal.js +0 -79
  54. package/packages/cli/dist/usage.d.ts +0 -3
  55. package/packages/cli/dist/usage.js +0 -78
  56. package/packages/cli/dist/web-service.d.ts +0 -38
  57. package/packages/cli/dist/web-service.js +0 -119
  58. package/packages/client/README.md +0 -29
  59. package/packages/client/dist/acp-probe.d.ts +0 -44
  60. package/packages/client/dist/acp-probe.js +0 -37
  61. package/packages/client/dist/antigravity-probe.d.ts +0 -34
  62. package/packages/client/dist/antigravity-probe.js +0 -95
  63. package/packages/client/dist/command.d.ts +0 -5
  64. package/packages/client/dist/command.js +0 -33
  65. package/packages/client/dist/doctor.d.ts +0 -13
  66. package/packages/client/dist/doctor.js +0 -587
  67. package/packages/client/dist/index.d.ts +0 -151
  68. package/packages/client/dist/index.js +0 -533
  69. package/packages/client/dist/integration-lock.d.ts +0 -35
  70. package/packages/client/dist/integration-lock.js +0 -179
  71. package/packages/client/dist/ipc.d.ts +0 -42
  72. package/packages/client/dist/ipc.js +0 -69
  73. package/packages/client/dist/library-test.d.ts +0 -94
  74. package/packages/client/dist/library-test.js +0 -37
  75. package/packages/client/dist/mcp-probe.d.ts +0 -24
  76. package/packages/client/dist/mcp-probe.js +0 -147
  77. package/packages/client/dist/portable.d.ts +0 -19
  78. package/packages/client/dist/portable.js +0 -33
  79. package/packages/client/dist/prompt.d.ts +0 -32
  80. package/packages/client/dist/prompt.js +0 -59
  81. package/packages/client/dist/render.d.ts +0 -6
  82. package/packages/client/dist/render.js +0 -120
  83. package/packages/client/dist/rpc/client.d.ts +0 -82
  84. package/packages/client/dist/rpc/client.js +0 -292
  85. package/packages/client/dist/rpc/errors.d.ts +0 -42
  86. package/packages/client/dist/rpc/errors.js +0 -34
  87. package/packages/client/dist/rpc/framing.d.ts +0 -21
  88. package/packages/client/dist/rpc/framing.js +0 -57
  89. package/packages/client/dist/rpc/handshake.d.ts +0 -19
  90. package/packages/client/dist/rpc/handshake.js +0 -8
  91. package/packages/client/dist/rpc/reconnect.d.ts +0 -97
  92. package/packages/client/dist/rpc/reconnect.js +0 -227
  93. package/packages/client/dist/rpc/registry.d.ts +0 -211
  94. package/packages/client/dist/rpc/registry.js +0 -145
  95. package/packages/client/dist/rpc/timers.d.ts +0 -11
  96. package/packages/client/dist/rpc/timers.js +0 -11
  97. package/packages/client/dist/service.d.ts +0 -50
  98. package/packages/client/dist/service.js +0 -143
  99. package/packages/client/dist/setup.d.ts +0 -2
  100. package/packages/client/dist/setup.js +0 -146
  101. package/packages/client/dist/supervise.d.ts +0 -14
  102. package/packages/client/dist/supervise.js +0 -87
  103. package/packages/client/dist/websocket.d.ts +0 -51
  104. package/packages/client/dist/websocket.js +0 -190
  105. package/packages/core/README.md +0 -7
  106. package/packages/core/dist/adapter.d.ts +0 -20
  107. package/packages/core/dist/adapter.js +0 -30
  108. package/packages/core/dist/atomic.d.ts +0 -2
  109. package/packages/core/dist/atomic.js +0 -28
  110. package/packages/core/dist/backup.d.ts +0 -27
  111. package/packages/core/dist/backup.js +0 -681
  112. package/packages/core/dist/beads.d.ts +0 -65
  113. package/packages/core/dist/beads.js +0 -213
  114. package/packages/core/dist/delegation.d.ts +0 -2
  115. package/packages/core/dist/delegation.js +0 -32
  116. package/packages/core/dist/errors.d.ts +0 -4
  117. package/packages/core/dist/errors.js +0 -11
  118. package/packages/core/dist/formulas.d.ts +0 -25
  119. package/packages/core/dist/formulas.js +0 -201
  120. package/packages/core/dist/hook-run.d.ts +0 -44
  121. package/packages/core/dist/hook-run.js +0 -60
  122. package/packages/core/dist/hooks.d.ts +0 -35
  123. package/packages/core/dist/hooks.js +0 -30
  124. package/packages/core/dist/index.d.ts +0 -31
  125. package/packages/core/dist/index.js +0 -65
  126. package/packages/core/dist/init.d.ts +0 -30
  127. package/packages/core/dist/init.js +0 -89
  128. package/packages/core/dist/library-edit.d.ts +0 -93
  129. package/packages/core/dist/library-edit.js +0 -368
  130. package/packages/core/dist/library.d.ts +0 -28
  131. package/packages/core/dist/library.js +0 -108
  132. package/packages/core/dist/log.d.ts +0 -37
  133. package/packages/core/dist/log.js +0 -156
  134. package/packages/core/dist/migrations.d.ts +0 -9
  135. package/packages/core/dist/migrations.js +0 -95
  136. package/packages/core/dist/models.d.ts +0 -11
  137. package/packages/core/dist/models.js +0 -44
  138. package/packages/core/dist/permissions.d.ts +0 -14
  139. package/packages/core/dist/permissions.js +0 -229
  140. package/packages/core/dist/profiles.d.ts +0 -27
  141. package/packages/core/dist/profiles.js +0 -122
  142. package/packages/core/dist/promptsafe.d.ts +0 -1
  143. package/packages/core/dist/promptsafe.js +0 -13
  144. package/packages/core/dist/providers.d.ts +0 -90
  145. package/packages/core/dist/providers.js +0 -101
  146. package/packages/core/dist/resolver.d.ts +0 -41
  147. package/packages/core/dist/resolver.js +0 -240
  148. package/packages/core/dist/safe-path.d.ts +0 -2
  149. package/packages/core/dist/safe-path.js +0 -24
  150. package/packages/core/dist/shell.d.ts +0 -16
  151. package/packages/core/dist/shell.js +0 -22
  152. package/packages/core/dist/state-schema.d.ts +0 -9
  153. package/packages/core/dist/state-schema.js +0 -54
  154. package/packages/core/dist/task-rows.d.ts +0 -47
  155. package/packages/core/dist/task-rows.js +0 -45
  156. package/packages/core/dist/tasks.d.ts +0 -128
  157. package/packages/core/dist/tasks.js +0 -835
  158. package/packages/core/dist/teams.d.ts +0 -80
  159. package/packages/core/dist/teams.js +0 -159
  160. package/packages/core/dist/template-path.d.ts +0 -2
  161. package/packages/core/dist/template-path.js +0 -10
  162. package/packages/core/dist/trust.d.ts +0 -8
  163. package/packages/core/dist/trust.js +0 -47
  164. package/packages/core/dist/types.d.ts +0 -51
  165. package/packages/core/dist/upgrade.d.ts +0 -10
  166. package/packages/core/dist/upgrade.js +0 -200
  167. package/packages/core/dist/user-settings.d.ts +0 -6
  168. package/packages/core/dist/user-settings.js +0 -72
  169. package/packages/core/dist/user-worktree.d.ts +0 -29
  170. package/packages/core/dist/user-worktree.js +0 -242
  171. package/packages/core/dist/validation.d.ts +0 -17
  172. package/packages/core/dist/validation.js +0 -296
  173. package/packages/core/dist/verify.d.ts +0 -15
  174. package/packages/core/dist/verify.js +0 -123
  175. package/packages/core/dist/workflow.d.ts +0 -45
  176. package/packages/core/dist/workflow.js +0 -33
  177. package/templates/ALP.md +0 -52
  178. package/templates/agents/lead/AGENT.md +0 -90
  179. package/templates/agents/main/AGENT.md +0 -150
  180. package/templates/agents/oracle/AGENT.md +0 -44
  181. package/templates/agents/peer/AGENT.md +0 -55
  182. package/templates/agents/reviewer/AGENT.md +0 -80
  183. package/templates/agents/supervisor/AGENT.md +0 -72
  184. package/templates/providers/antigravity.json +0 -6
  185. package/templates/providers/opencode.json +0 -7
  186. package/templates/role-skills.json +0 -8
  187. package/templates/skills/bug-loop/SKILL.md +0 -44
  188. package/templates/skills/bug-loop/references/test-proof.md +0 -25
  189. package/templates/skills/goal-griller/SKILL.md +0 -49
  190. package/templates/skills/prompt-leverage/SKILL.md +0 -37
  191. package/templates/skills/prompt-leverage/references/brief-template.md +0 -27
  192. package/templates/skills/sequence-execution-plan/SKILL.md +0 -42
  193. package/templates/skills/sequence-execution-plan/references/plan-template.md +0 -22
  194. package/templates/skills/smart-commits/SKILL.md +0 -40
  195. package/templates/skills/xia/SKILL.md +0 -42
  196. package/templates/teams/cafe/HOUSE_RULES.md +0 -1
  197. package/templates/teams/cafe/team.json +0 -15
  198. package/templates/teams/pho/HOUSE_RULES.md +0 -1
  199. package/templates/teams/pho/team.json +0 -14
@@ -1,122 +0,0 @@
1
- // packages/core/src/profiles.js
2
- import path from "node:path";
3
- import os from "node:os";
4
- import { createHash } from "node:crypto";
5
- import { MODELS } from "./models.js";
6
- import { resolveTeam, teamSources } from "./teams.js";
7
- var userLibrary = () => process.env.ALP_HOME ?? path.join(os.homedir(), ".alp");
8
- var oracleProfiles = (config) => config?.profiles ?? [config?.claude, config?.codex].filter(Boolean);
9
- var agentProfiles = (config, name) => {
10
- if (!config) return [];
11
- if (name === "oracle") return oracleProfiles(config).map(parseProfile);
12
- const { autocompact, ...legacy } = config;
13
- return (config.profiles ?? [legacy]).map(parseProfile);
14
- };
15
- var parseProfile = (profile) => {
16
- if (typeof profile !== "string") return profile;
17
- const [provider, model, effort] = profile.split(":");
18
- return { provider, model, ...effort ? { effort } : {} };
19
- };
20
- var profileString = (profile) => `${profileModel(profile)}${profile.effort ? `:${profile.effort}` : ""}`;
21
- var modelEfforts = (id) => MODELS.find((model) => `${model.runtime}:${model.id}` === id)?.efforts;
22
- var fitEffort = (id, effort) => {
23
- const efforts = modelEfforts(id);
24
- if (!efforts?.length || efforts.includes(effort)) return effort;
25
- return MODELS.find((model) => `${model.runtime}:${model.id}` === id)?.effort ?? efforts[0];
26
- };
27
- var anyModel = (profile) => profile?.model === "*";
28
- var offers = (profiles, model) => profiles.some((profile) => anyModel(profile) ? model.startsWith(`${profile.provider}:`) && model.length > profile.provider.length + 1 : profileModel(profile) === model);
29
- var selectedProfile = (profiles, model) => model === void 0 ? profiles.find((config) => !anyModel(config)) : profiles.find((config) => !anyModel(config) && (!config.model || profileModel(config) === model || !model.includes(":") && config.model === model));
30
- function normalizeAgentProfiles(config, name) {
31
- if (config.profiles) return { ...config, profiles: config.profiles.map((profile) => typeof profile === "string" ? profile : profileString(profile)), autocompact: config.autocompact ?? "auto" };
32
- const profiles = agentProfiles(config, name);
33
- if (!profiles.length || profiles.some((profile) => !profile.model)) return config;
34
- return { profiles: profiles.map((profile) => profileString({ ...profile, provider: profile.provider ?? profile.model.split(":")[0] })), autocompact: config.autocompact ?? "auto" };
35
- }
36
- var profileModel = (config) => config?.model ? config.model.includes(":") ? config.model : `${config.provider}:${config.model}` : void 0;
37
- var withEffort = (model, effort) => {
38
- if (model.startsWith("acp:") || model.startsWith("antigravity:")) return model;
39
- const fitted = fitEffort(model, effort);
40
- return fitted ? `${model}:${fitted}` : model;
41
- };
42
- async function projectProfiles({ root, library = userLibrary(), templates, runtime, teamIds } = {}) {
43
- const profiles = {};
44
- for (const id of (await teamSources(root, { library, templates })).keys()) {
45
- if (teamIds && !teamIds.includes(id)) continue;
46
- const team = await resolveTeam(root, id, { library, templates });
47
- const fallback = team.members[team.main].model ?? "codex:gpt-6.1-sol";
48
- const profile = {};
49
- for (const [name, member] of Object.entries(team.members)) {
50
- if (name === "oracle") continue;
51
- const chosen = runtime?.model ? runtime.model.includes(":") ? runtime.model : `${runtime.provider ?? "codex"}:${runtime.model}` : runtime?.provider ? runtime.provider === "claude" ? "claude:claude-opus-5-5" : "codex:gpt-6.1-sol" : member.model ?? fallback;
52
- profile[name] = { profiles: [withEffort(chosen, runtime?.reasoning ?? member.thinking ?? team.members[team.main].thinking ?? "medium")], autocompact: "auto" };
53
- }
54
- if (team.supervisor) profile[team.supervisor.agent] = { profiles: [withEffort(team.supervisor.model ?? fallback, team.supervisor.thinking ?? "medium")], autocompact: "auto" };
55
- if (team.members.oracle) profile.oracle = { profiles: (team.oracleModels ?? ["claude:claude-fable-5-1", "codex:gpt-6-astra"]).map((model) => withEffort(model, team.oracleThinking?.[model] ?? team.oracleThinking?.[model.split(":")[0]] ?? "high")), autocompact: "auto" };
56
- profiles[id] = profile;
57
- }
58
- return profiles;
59
- }
60
- function applyProfile(team, profile) {
61
- if (!profile) return team;
62
- const next = structuredClone(team);
63
- for (const [name, config] of Object.entries(profile)) {
64
- if (name === "oracle") {
65
- const lenses = oracleProfiles(config).map(parseProfile);
66
- next.oracleModels = lenses.map(profileModel);
67
- const efforts = lenses.filter((lens) => lens.effort);
68
- if (efforts.length) next.oracleThinking = { ...next.oracleThinking, ...Object.fromEntries(efforts.map((lens) => [profileModel(lens), lens.effort])) };
69
- } else {
70
- const target = next.members[name] ?? (next.supervisor && next.supervisor.agent === name ? next.supervisor : void 0);
71
- if (!target) throw new Error(`team.${team.id}.${name}: agent is not in this team`);
72
- const first = agentProfiles(config, name).find((profile2) => !anyModel(profile2));
73
- if (first?.model) target.model = profileModel(first);
74
- if (first?.effort) target.thinking = first.effort;
75
- }
76
- }
77
- return next;
78
- }
79
- var profileFingerprint = (config, name) => createHash("sha256").update(JSON.stringify(agentProfiles(config, name).map(profileString))).digest("hex");
80
- var profileDefaults = (profiles) => Object.fromEntries(Object.entries(profiles).map(([team, agents]) => [team, Object.fromEntries(Object.entries(agents).map(([name, config]) => [name, profileFingerprint(config, name)]))]));
81
- async function syncTemplateProfiles(settings, options = {}) {
82
- const defaults = await projectProfiles({ ...options, runtime: options.replaceModels ? void 0 : settings.runtime });
83
- const legacy = settings.templateDefaults ? void 0 : await projectProfiles({ templates: options.templates, library: "", runtime: settings.runtime });
84
- const previous = settings.templateDefaults ?? profileDefaults(legacy);
85
- const next = structuredClone(settings);
86
- next.team = { ...next.profile ?? {}, ...next.team ?? {} };
87
- delete next.profile;
88
- for (const id of /* @__PURE__ */ new Set([...Object.keys(previous), ...Object.keys(defaults)])) {
89
- if (options.teamIds && !options.teamIds.includes(id)) continue;
90
- const desired = defaults[id] ?? {};
91
- const current = next.team[id] ?? {};
92
- for (const name of /* @__PURE__ */ new Set([...Object.keys(previous[id] ?? {}), ...options.replaceModels ? Object.keys(current) : [], ...Object.keys(desired)])) {
93
- const config = current[name];
94
- if (!options.replaceModels && config && profileFingerprint(config, name) !== previous[id]?.[name]) continue;
95
- if (desired[name]) current[name] = { ...desired[name], autocompact: config?.autocompact ?? desired[name].autocompact };
96
- else delete current[name];
97
- }
98
- if (Object.keys(current).length) next.team[id] = current;
99
- else delete next.team[id];
100
- }
101
- next.templateDefaults = options.teamIds ? { ...previous, ...profileDefaults(defaults) } : profileDefaults(defaults);
102
- return next;
103
- }
104
- export {
105
- agentProfiles,
106
- anyModel,
107
- applyProfile,
108
- fitEffort,
109
- modelEfforts,
110
- normalizeAgentProfiles,
111
- offers,
112
- oracleProfiles,
113
- parseProfile,
114
- profileDefaults,
115
- profileFingerprint,
116
- profileModel,
117
- profileString,
118
- projectProfiles,
119
- selectedProfile,
120
- syncTemplateProfiles,
121
- userLibrary
122
- };
@@ -1 +0,0 @@
1
- export function promptSafe<T>(text: T): T;
@@ -1,13 +0,0 @@
1
- // packages/core/src/promptsafe.js
2
- var TAG = /<\s*\/?\s*system-reminder\b[^>]*>/gi;
3
- function promptSafe(text) {
4
- if (typeof text !== "string") return text;
5
- for (let current = text; ; ) {
6
- const next = current.replace(TAG, "");
7
- if (next === current) return next;
8
- current = next;
9
- }
10
- }
11
- export {
12
- promptSafe
13
- };
@@ -1,90 +0,0 @@
1
- /** Checks a provider definition. */
2
- export function validateProvider(config: any, source: any, id: any): any;
3
- /**
4
- * A provider of the library, with its id; undefined when there is none.
5
- * @returns {Promise<{ id: string, kind: 'acp' | 'antigravity', label: string, description?: string, command: string, args: string[], env: Record<string, string>, models?: Array<{ id: string, label?: string, description?: string }>, additionalModels?: Array<{ id: string, label?: string, description?: string }>, enabled?: boolean, params?: Record<string, unknown>, readOnlyMode?: 'instructions' | 'reject' } | undefined>}
6
- */
7
- export function loadProvider(library: any, id: any): Promise<{
8
- id: string;
9
- kind: "acp" | "antigravity";
10
- label: string;
11
- description?: string;
12
- command: string;
13
- args: string[];
14
- env: Record<string, string>;
15
- models?: Array<{
16
- id: string;
17
- label?: string;
18
- description?: string;
19
- }>;
20
- additionalModels?: Array<{
21
- id: string;
22
- label?: string;
23
- description?: string;
24
- }>;
25
- enabled?: boolean;
26
- params?: Record<string, unknown>;
27
- readOnlyMode?: "instructions" | "reject";
28
- } | undefined>;
29
- /** Every provider of the library, by id. */
30
- export function listProviders(library: any): Promise<{
31
- id: string;
32
- kind: "acp" | "antigravity";
33
- label: string;
34
- description?: string;
35
- command: string;
36
- args: string[];
37
- env: Record<string, string>;
38
- models?: Array<{
39
- id: string;
40
- label?: string;
41
- description?: string;
42
- }>;
43
- additionalModels?: Array<{
44
- id: string;
45
- label?: string;
46
- description?: string;
47
- }>;
48
- enabled?: boolean;
49
- params?: Record<string, unknown>;
50
- readOnlyMode?: "instructions" | "reject";
51
- }[]>;
52
- /**
53
- * Splits an ACP model id, `<provider>` or `<provider>/<model>`, as resolveSession keeps it
54
- * after the `acp:` prefix.
55
- */
56
- export function acpModel(model: any): {
57
- provider: any;
58
- model: any;
59
- };
60
- /**
61
- * How to start a command without a shell. On Windows a bare name installed with npm is a
62
- * `<name>.cmd` shim, which spawn refuses to run without one; its target runs instead: the
63
- * native executable it calls, or the Node script, under this Node. A bare name with an .exe or
64
- * .com on PATH, any other command, and every command elsewhere are returned as they are.
65
- * @param {string} command @param {string[]} [args] @param {Record<string, string | undefined>} [env]
66
- * @returns {{ command: string, args: string[] }}
67
- */
68
- export function launchCommand(command: string, args?: string[], env?: Record<string, string | undefined>): {
69
- command: string;
70
- args: string[];
71
- };
72
- /**
73
- * ACP providers (ALPD §46): agents that speak the Agent Client Protocol, such as Gemini
74
- * CLI or opencode, defined in the user's library as providers/<id>.json. An agent runs
75
- * on one with `provider: "<id>"` in its agent.json, or with the model `acp:<id>` or
76
- * `acp:<id>/<model>`. Providers live only in the library: a project's would run a
77
- * command from its repository on the user's machine.
78
- *
79
- * { "kind": "acp", "label": "Gemini", "command": "gemini", "args": ["--experimental-acp"],
80
- * "env": {}, "models": [{ "id": "gemini-2.5-pro" }] }
81
- *
82
- * The web app's Providers screen (ALPD §65) adds `enabled` (false turns it off), `additionalModels`
83
- * (added to the models the agent reports, where `models` replaces them) and `params`, which
84
- * Paseo's catalog carries and ALP keeps without using.
85
- */
86
- export const PROVIDER_SETTINGS: string[];
87
- /** Runtimes ALP has built in; no provider takes their names. */
88
- export const BUILTIN_RUNTIMES: string[];
89
- /** Names no provider takes: the runtimes, and `alp`, which the web app lists ALP's teams under. */
90
- export const RESERVED_PROVIDERS: string[];
@@ -1,101 +0,0 @@
1
- // packages/core/src/providers.js
2
- import { existsSync, readFileSync } from "node:fs";
3
- import { readdir, readFile } from "node:fs/promises";
4
- import path from "node:path";
5
- import { AlpError } from "./errors.js";
6
- import { settingsKeys, unknownMessage } from "./validation.js";
7
- var PROVIDER_SETTINGS = ["$schema", "kind", "label", "description", "command", "args", "env", "models", "additionalModels", "enabled", "params", "readOnlyMode"];
8
- var BUILTIN_RUNTIMES = ["codex", "claude", "acp", "antigravity"];
9
- var RESERVED_PROVIDERS = [...BUILTIN_RUNTIMES, "alp"];
10
- var object = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
11
- var nonempty = (value) => typeof value === "string" && value.trim().length > 0;
12
- var validId = (id) => typeof id === "string" && /^[\w.-]+$/.test(id) && id !== "." && id !== "..";
13
- function validateProvider(config, source, id) {
14
- const check = (ok, message) => {
15
- if (!ok) throw new AlpError("INVALID_PROVIDER", `${source}: ${message}`);
16
- };
17
- if (id !== void 0) check(validId(id) && (!RESERVED_PROVIDERS.includes(id) || id === "antigravity" && config?.kind === "antigravity"), `'${id}' cannot name a provider: ${RESERVED_PROVIDERS.join(", ")} are taken`);
18
- check(object(config), "expected an object");
19
- const { unknown } = settingsKeys(config, PROVIDER_SETTINGS);
20
- check(!unknown.length, unknown.length ? unknownMessage(unknown[0], PROVIDER_SETTINGS) : "");
21
- check(["acp", "antigravity"].includes(config.kind), 'kind must be "acp" or "antigravity"');
22
- if (config.kind === "antigravity" && id !== void 0) check(id === "antigravity", "Antigravity must use provider ID antigravity");
23
- if (config.readOnlyMode !== void 0) check(config.kind === "antigravity" && ["instructions", "reject"].includes(config.readOnlyMode), 'readOnlyMode is only for Antigravity and must be "instructions" or "reject"');
24
- for (const key of ["label", "description"]) if (config[key] !== void 0) check(typeof config[key] === "string", `${key} must be a string`);
25
- check(nonempty(config.command), "command must be a nonempty string");
26
- if (config.args !== void 0) check(Array.isArray(config.args) && config.args.every((arg) => typeof arg === "string"), "args must be a list of strings");
27
- if (config.env !== void 0) check(object(config.env) && Object.values(config.env).every((value) => typeof value === "string"), "env must map names to strings");
28
- for (const key of ["models", "additionalModels"]) {
29
- if (config[key] === void 0) continue;
30
- check(Array.isArray(config[key]) && config[key].every((model) => object(model) && nonempty(model.id) && !/\s/.test(model.id) && Object.keys(model).every((field) => ["id", "label", "description"].includes(field)) && ["label", "description"].every((field) => model[field] === void 0 || typeof model[field] === "string")), `${key} must list { id, label?, description? }`);
31
- check(new Set(config[key].map((model) => model.id)).size === config[key].length, `${key} lists an id twice`);
32
- }
33
- if (config.enabled !== void 0) check(typeof config.enabled === "boolean", "enabled must be true or false");
34
- if (config.params !== void 0) check(object(config.params), "params must be an object");
35
- return config;
36
- }
37
- async function loadProvider(library, id) {
38
- if (!library || !validId(id) || RESERVED_PROVIDERS.includes(id) && id !== "antigravity") return void 0;
39
- const file = path.join(library, "providers", `${id}.json`);
40
- let text;
41
- try {
42
- text = await readFile(file, "utf8");
43
- } catch (error) {
44
- if (error.code === "ENOENT") return void 0;
45
- throw error;
46
- }
47
- let config;
48
- try {
49
- config = JSON.parse(text);
50
- } catch (cause) {
51
- throw new AlpError("INVALID_PROVIDER", `${file}: ${cause.message}`, { cause });
52
- }
53
- validateProvider(config, file, id);
54
- const command = /[\\/]/.test(config.command) ? path.resolve(path.dirname(file), config.command) : config.command;
55
- return { id, ...config, label: config.label ?? id, command, args: config.args ?? [], env: config.env ?? {} };
56
- }
57
- async function listProviders(library) {
58
- if (!library) return [];
59
- let names = [];
60
- try {
61
- names = await readdir(path.join(library, "providers"));
62
- } catch (error) {
63
- if (error.code !== "ENOENT") throw error;
64
- }
65
- const providers = [];
66
- for (const name of names.filter((name2) => name2.endsWith(".json")).sort()) {
67
- const provider = await loadProvider(library, name.slice(0, -5));
68
- if (provider) providers.push(provider);
69
- }
70
- return providers;
71
- }
72
- function acpModel(model) {
73
- const slash = model.indexOf("/");
74
- return slash < 0 ? { provider: model, model: void 0 } : { provider: model.slice(0, slash), model: model.slice(slash + 1) || void 0 };
75
- }
76
- function launchCommand(command, args = [], env = process.env) {
77
- if (process.platform !== "win32" || /[\\/]/.test(command) || path.extname(command)) return { command, args };
78
- const key = Object.keys(env).find((name) => name.toUpperCase() === "PATH");
79
- for (const directory of (key ? env[key] ?? "" : "").split(";").filter(Boolean)) {
80
- if ([".exe", ".com"].some((extension) => existsSync(path.join(directory, command + extension)))) break;
81
- const shim = path.join(directory, `${command}.cmd`);
82
- if (!existsSync(shim)) continue;
83
- const text = readFileSync(shim, "utf8");
84
- const script = /"%_prog%"((?:\s+[^\s"]+)*)\s+"%~?dp0%\\?([^"]+)"\s+%\*/i.exec(text);
85
- if (script) return { command: process.execPath, args: [...script[1].split(/\s+/).filter(Boolean), path.join(directory, script[2]), ...args] };
86
- const native = /^\s*"%~?dp0%\\?([^"]+\.(?:exe|com))"\s+%\*/im.exec(text);
87
- if (native) return { command: path.join(directory, native[1]), args };
88
- break;
89
- }
90
- return { command, args };
91
- }
92
- export {
93
- BUILTIN_RUNTIMES,
94
- PROVIDER_SETTINGS,
95
- RESERVED_PROVIDERS,
96
- acpModel,
97
- launchCommand,
98
- listProviders,
99
- loadProvider,
100
- validateProvider
101
- };
@@ -1,41 +0,0 @@
1
- export function optionalText(file: any): Promise<string | undefined>;
2
- export function jsonObject(file: any, code: any): Promise<any>;
3
- /** A shipped template file, from `templates` when given (bundles embed them), else from the package. */
4
- export function builtinText(relative: any, templates: any): Promise<any>;
5
- /**
6
- * Where each agent comes from (ALPD §41): ALP's built-ins, then the user's library
7
- * (`library`, ALP_HOME), then the project's `.alp/agents`. A later layer replaces an
8
- * agent of the same name entirely.
9
- * @returns {Promise<Map<string, { source: 'builtin' | 'library' | 'project', directory?: string, overrides?: 'builtin' | 'library' }>>}
10
- */
11
- export function agentSources(root: any, { library, templates }?: {}): Promise<Map<string, {
12
- source: "builtin" | "library" | "project";
13
- directory?: string;
14
- overrides?: "builtin" | "library";
15
- }>>;
16
- export function discoverAgents(root: any, options?: {}): Promise<string[]>;
17
- /**
18
- * Every entry of one kind with where it comes from (ALPD §41): `agents`, `skills`, `mcp`
19
- * or `hooks`. A project entry overrides a library one of the same name. `usedBy` lists
20
- * the agents that name a skill, MCP server or hook; for skills it includes the roles
21
- * role-skills.json gives it.
22
- * @returns {Promise<Array<{ name: string, source: 'builtin' | 'library' | 'project', path?: string, overrides?: 'builtin' | 'library', description?: string, usedBy?: string[] }>>}
23
- */
24
- export function libraryEntries(kind: any, projectRoot: any, { library, templates }?: {}): Promise<Array<{
25
- name: string;
26
- source: "builtin" | "library" | "project";
27
- path?: string;
28
- overrides?: "builtin" | "library";
29
- description?: string;
30
- usedBy?: string[];
31
- }>>;
32
- /**
33
- * `library` is the user's library (ALP_HOME): its agents and the skills, MCP servers and
34
- * hooks agents name. The agent's own skills/ directory replaces a skill of the same name.
35
- * @returns {Promise<import('./types.js').ResolvedAgent>}
36
- */
37
- export function resolveAgent(projectRoot: any, { agent, library, templates }?: {}): Promise<import("./types.js").ResolvedAgent>;
38
- export { AlpError } from "./errors.js";
39
- /** The agents ALP ships; their files come from the package's templates. */
40
- export const BUILTIN_AGENTS: string[];
41
- export const LIBRARY_KINDS: string[];
@@ -1,240 +0,0 @@
1
- // packages/core/src/resolver.js
2
- import { shippedTemplateRoot } from "./template-path.js";
3
- import { readFile, readdir, stat } from "node:fs/promises";
4
- import path from "node:path";
5
- import { AlpError } from "./errors.js";
6
- import { validateAgentConfig, validateHook, validateSettings, normalizeMcp, validateResolvedAgent } from "./validation.js";
7
- import { librarySkills } from "./library.js";
8
- import { AlpError as AlpError2 } from "./errors.js";
9
- async function optionalText(file) {
10
- try {
11
- return await readFile(file, "utf8");
12
- } catch (error) {
13
- if (error.code === "ENOENT") return void 0;
14
- throw error;
15
- }
16
- }
17
- async function jsonObject(file, code) {
18
- const text = await optionalText(file);
19
- if (text === void 0) return {};
20
- try {
21
- const value = JSON.parse(text);
22
- if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("expected a JSON object");
23
- return value;
24
- } catch (cause) {
25
- throw new AlpError(code, `${file}: ${cause.message}`, { cause });
26
- }
27
- }
28
- async function entries(directory) {
29
- try {
30
- return (await readdir(directory, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name));
31
- } catch (error) {
32
- if (error.code === "ENOENT") return [];
33
- throw error;
34
- }
35
- }
36
- var BUILTIN_AGENTS = ["main", "lead", "peer", "oracle", "reviewer", "supervisor"];
37
- var templateRoot = () => {
38
- try {
39
- return shippedTemplateRoot();
40
- } catch {
41
- return void 0;
42
- }
43
- };
44
- var validName = (name) => typeof name === "string" && /^[\w.-]+$/.test(name) && name !== "." && name !== "..";
45
- async function builtinText(relative, templates) {
46
- if (templates) return templates[relative];
47
- const root = templateRoot();
48
- if (!root) return void 0;
49
- try {
50
- return await readFile(new URL(relative, root), "utf8");
51
- } catch (error) {
52
- if (error.code === "ENOENT" || error.code === "ENOTDIR") return void 0;
53
- throw error;
54
- }
55
- }
56
- async function agentSources(root, { library, templates } = {}) {
57
- const found = /* @__PURE__ */ new Map();
58
- for (const name of BUILTIN_AGENTS) if (await builtinText(`agents/${name}/AGENT.md`, templates) !== void 0) found.set(name, { source: "builtin" });
59
- const layer = async (directory, source) => {
60
- for (const entry of await entries(directory)) {
61
- if (!entry.isDirectory() || !validName(entry.name)) continue;
62
- if (source === "library" && await optionalText(path.join(directory, entry.name, "AGENT.md")) === void 0) continue;
63
- const previous = found.get(entry.name);
64
- found.set(entry.name, { source, directory: path.join(directory, entry.name), ...previous ? { overrides: previous.source } : {} });
65
- }
66
- };
67
- if (library) await layer(path.join(library, "agents"), "library");
68
- if (root !== void 0) await layer(path.join(path.resolve(root), ".alp", "agents"), "project");
69
- return found;
70
- }
71
- async function discoverAgents(root, options = {}) {
72
- return [...(await agentSources(root, options)).keys()].sort((a, b) => a.localeCompare(b));
73
- }
74
- var KINDS = {
75
- skills: (name) => path.join(name, "SKILL.md"),
76
- mcp: (name) => `${name}.json`,
77
- hooks: (name) => `${name}.json`,
78
- // ACP providers (ALPD §46) live only in the library.
79
- providers: (name) => `${name}.json`
80
- };
81
- var LIBRARY_KINDS = ["agents", ...Object.keys(KINDS)];
82
- async function libraryEntries(kind, projectRoot, { library, templates } = {}) {
83
- const root = projectRoot === void 0 ? void 0 : path.resolve(projectRoot);
84
- if (kind === "agents") {
85
- const rows = [];
86
- for (const [name, source] of await agentSources(root, { library, templates })) {
87
- const text = source.directory ? await optionalText(path.join(source.directory, "agent.json")) : await builtinText(`agents/${name}/agent.json`, templates);
88
- let description;
89
- try {
90
- description = text === void 0 ? void 0 : JSON.parse(text).description;
91
- } catch {
92
- }
93
- rows.push({ name, source: source.source, ...source.directory ? { path: source.directory } : {}, ...source.overrides ? { overrides: source.overrides } : {}, ...typeof description === "string" ? { description } : {} });
94
- }
95
- return rows.sort((a, b) => a.name.localeCompare(b.name));
96
- }
97
- const file = KINDS[kind];
98
- if (!file) throw new AlpError("INVALID_KIND", `Unknown library kind '${kind}'; use one of ${LIBRARY_KINDS.join(", ")}`);
99
- const found = /* @__PURE__ */ new Map();
100
- const layer = async (directory, source) => {
101
- for (const entry of await entries(directory)) {
102
- const name = kind === "skills" ? entry.isDirectory() ? entry.name : void 0 : entry.isFile() && entry.name.endsWith(".json") ? entry.name.slice(0, -5) : void 0;
103
- if (!name || !validName(name)) continue;
104
- const entryPath = path.join(directory, file(name));
105
- if (!await stat(entryPath).then((info) => info.isFile(), () => false)) continue;
106
- const previous = found.get(name);
107
- found.set(name, { name, source, path: entryPath, ...previous ? { overrides: previous.source } : {} });
108
- }
109
- };
110
- if (library) await layer(path.join(library, kind), "library");
111
- if (root !== void 0 && kind !== "providers") await layer(path.join(root, ".alp", kind), "project");
112
- const users = /* @__PURE__ */ new Map();
113
- const use = (name, agent) => users.set(name, [.../* @__PURE__ */ new Set([...users.get(name) ?? [], agent])]);
114
- for (const [agent, source] of await agentSources(root, { library, templates })) {
115
- const text = source.directory ? await optionalText(path.join(source.directory, "agent.json")) : await builtinText(`agents/${agent}/agent.json`, templates);
116
- try {
117
- const config = text === void 0 ? {} : JSON.parse(text);
118
- for (const name of kind === "providers" ? [config.provider].filter(Boolean) : config[kind] ?? []) use(name, agent);
119
- } catch {
120
- }
121
- }
122
- if (kind === "skills" && library) {
123
- try {
124
- for (const [role, names] of Object.entries(JSON.parse(await optionalText(path.join(library, "role-skills.json")) ?? "{}"))) for (const name of Array.isArray(names) ? names : []) use(name, role);
125
- } catch {
126
- }
127
- }
128
- return [...found.values()].map((row) => ({ ...row, ...users.has(row.name) ? { usedBy: users.get(row.name).sort() } : {} })).sort((a, b) => a.name.localeCompare(b.name));
129
- }
130
- async function namedEntry(root, library, kind, name, file) {
131
- const candidates = [path.join(root, ".alp", kind, file(name)), ...library ? [path.join(library, kind, file(name))] : []];
132
- for (const candidate of candidates) if (await stat(candidate).then((info) => info.isFile(), () => false)) return candidate;
133
- return void 0;
134
- }
135
- async function resolveAgent(projectRoot, { agent, library, templates } = {}) {
136
- const root = path.resolve(projectRoot);
137
- const settingsPath = path.join(root, ".alp", "settings.json");
138
- const settings = await jsonObject(settingsPath, "INVALID_SETTINGS");
139
- const projectRuntime = validateSettings(settings, settingsPath);
140
- const name = agent ?? settings.defaultAgent ?? "main";
141
- if (typeof name !== "string" || !name.trim() || name === "." || name === ".." || /[\\/\x00]/.test(name)) {
142
- throw new AlpError("INVALID_AGENT", "Agent name must be a single nonempty directory name");
143
- }
144
- const source = (await agentSources(root, { library, templates })).get(name);
145
- if (!source) throw new AlpError("AGENT_NOT_FOUND", `Agent '${name}' not found: it is not built in, nor under ${library ? `${path.join(library, "agents")} or ` : ""}${path.join(root, ".alp", "agents")}`);
146
- const directory = source.directory;
147
- const agentPath = directory ? path.join(directory, "AGENT.md") : `built-in agents/${name}/AGENT.md`;
148
- const instructions = directory ? await optionalText(agentPath) : await builtinText(`agents/${name}/AGENT.md`, templates);
149
- if (instructions === void 0) throw new AlpError("AGENT_INSTRUCTIONS_MISSING", `Missing ${agentPath}`);
150
- const configPath = directory ? path.join(directory, "agent.json") : `built-in agents/${name}/agent.json`;
151
- const configText = directory ? await optionalText(configPath) : await builtinText(`agents/${name}/agent.json`, templates);
152
- let config = {};
153
- if (configText !== void 0) {
154
- try {
155
- config = JSON.parse(configText);
156
- } catch (cause) {
157
- throw new AlpError("INVALID_AGENT_CONFIG", `${configPath}: ${cause.message}`, { cause });
158
- }
159
- }
160
- validateAgentConfig(config, configPath);
161
- const skills = [];
162
- for (const skill of library ? await librarySkills(library, name) : []) {
163
- skills.push({ name: skill.name, path: await namedEntry(root, void 0, "skills", skill.name, (entry) => path.join(entry, "SKILL.md")) ?? skill.path });
164
- }
165
- const addSkill = (skillName, skillPath) => {
166
- const shadowed = skills.findIndex((skill) => skill.name === skillName);
167
- if (shadowed >= 0) skills.splice(shadowed, 1);
168
- skills.push({ name: skillName, path: skillPath });
169
- };
170
- for (const skillName of config.skills ?? []) {
171
- const skillPath = await namedEntry(root, library, "skills", skillName, (entry) => path.join(entry, "SKILL.md"));
172
- if (!skillPath) throw new AlpError("SKILL_NOT_FOUND", `${configPath}: skill '${skillName}' is neither in ${path.join(root, ".alp", "skills")} nor in the library`);
173
- addSkill(skillName, skillPath);
174
- }
175
- if (directory) {
176
- for (const entry of await entries(path.join(directory, "skills"))) {
177
- if (!entry.isDirectory()) continue;
178
- const skillPath = path.join(directory, "skills", entry.name, "SKILL.md");
179
- try {
180
- if ((await stat(skillPath)).isFile()) addSkill(entry.name, skillPath);
181
- } catch (error) {
182
- if (error.code !== "ENOENT") throw error;
183
- }
184
- }
185
- }
186
- skills.sort((a, b) => a.name.localeCompare(b.name));
187
- const hooks = directory ? (await entries(path.join(directory, "hooks"))).filter((e) => e.isFile()).map((e) => ({ name: e.name, path: path.join(directory, "hooks", e.name) })) : [];
188
- for (const hookName of config.hooks ?? []) {
189
- const hookPath = await namedEntry(root, library, "hooks", hookName, (entry) => `${entry}.json`);
190
- if (!hookPath) throw new AlpError("HOOK_NOT_FOUND", `${configPath}: hook '${hookName}' is neither in ${path.join(root, ".alp", "hooks")} nor in the library`);
191
- validateHook(await jsonObject(hookPath, "INVALID_HOOK"), hookPath);
192
- hooks.push({ name: hookName, path: hookPath });
193
- }
194
- const servers = {};
195
- for (const serverName of config.mcp ?? []) {
196
- const serverPath = await namedEntry(root, library, "mcp", serverName, (entry) => `${entry}.json`);
197
- if (!serverPath) throw new AlpError("MCP_NOT_FOUND", `${configPath}: MCP server '${serverName}' is neither in ${path.join(root, ".alp", "mcp")} nor in the library`);
198
- const definition = await jsonObject(serverPath, "INVALID_MCP");
199
- Object.assign(servers, normalizeMcp({ mcpServers: { [serverName]: definition } }, path.dirname(serverPath), serverPath).mcpServers);
200
- }
201
- const mcpPath = directory ? path.join(directory, ".mcp.json") : void 0;
202
- const own = mcpPath ? normalizeMcp(await jsonObject(mcpPath, "INVALID_MCP"), directory, mcpPath).mcpServers : {};
203
- for (const [serverName, server] of Object.entries(own)) {
204
- if (Object.hasOwn(servers, serverName)) throw new AlpError("INVALID_MCP", `${mcpPath}: MCP server '${serverName}' is also named in ${configPath}`);
205
- servers[serverName] = server;
206
- }
207
- const runtime = {
208
- ...config.provider !== void 0 ? { provider: config.provider } : {},
209
- ...config.model !== void 0 ? { model: config.model } : {},
210
- ...config.thinking !== void 0 ? { reasoning: config.thinking } : {},
211
- ...projectRuntime
212
- };
213
- return validateResolvedAgent({
214
- name,
215
- projectRoot: root,
216
- source: source.source,
217
- instructions: { project: await optionalText(path.join(root, "ALP.md")) ?? "", agent: instructions },
218
- skills,
219
- hooks,
220
- runtime,
221
- projectRuntime: { ...projectRuntime },
222
- ...config.mode !== void 0 ? { mode: config.mode } : {},
223
- ...config.description !== void 0 ? { description: config.description } : {},
224
- ...typeof config.context === "number" ? { context: config.context } : {},
225
- ...config.autocompact !== void 0 ? { autocompact: config.autocompact } : {},
226
- mcp: { mcpServers: servers }
227
- });
228
- }
229
- export {
230
- AlpError2 as AlpError,
231
- BUILTIN_AGENTS,
232
- LIBRARY_KINDS,
233
- agentSources,
234
- builtinText,
235
- discoverAgents,
236
- jsonObject,
237
- libraryEntries,
238
- optionalText,
239
- resolveAgent
240
- };
@@ -1,2 +0,0 @@
1
- /** Preflight static repository paths. Does not isolate concurrent same-user processes. */
2
- export function assertNoSymlinks(directory: any, relative: any): Promise<void>;
@@ -1,24 +0,0 @@
1
- // packages/core/src/safe-path.js
2
- import { lstat } from "node:fs/promises";
3
- import path from "node:path";
4
- import { AlpError } from "./errors.js";
5
- async function assertNoSymlinks(directory, relative) {
6
- const root = path.resolve(directory);
7
- const target = path.resolve(root, relative);
8
- const tail = path.relative(root, target);
9
- if (tail === ".." || tail.startsWith(`..${path.sep}`) || path.isAbsolute(tail)) {
10
- throw new AlpError("UNSAFE_PATH", "Path escapes its scope");
11
- }
12
- let current = root;
13
- for (const part of ["", ...tail.split(path.sep).filter(Boolean)]) {
14
- if (part) current = path.join(current, part);
15
- const info = await lstat(current).catch((error) => {
16
- if (error.code !== "ENOENT") throw error;
17
- });
18
- if (!info) return;
19
- if (info.isSymbolicLink()) throw new AlpError("UNSAFE_PATH", `Refusing symlink in scoped path: ${current}`);
20
- }
21
- }
22
- export {
23
- assertNoSymlinks
24
- };
@@ -1,16 +0,0 @@
1
- /**
2
- * Starts `command` through the platform's shell: /bin/sh -c in its own process group, or on
3
- * Windows cmd.exe /d /s /c with the line quoted whole (cmd strips only the outermost quotes,
4
- * and Node would otherwise escape the quotes inside it).
5
- * @param {string} command
6
- * @param {import('node:child_process').SpawnOptions} options
7
- */
8
- export function spawnShell(command: string, options: import("node:child_process").SpawnOptions): import("child_process").ChildProcess;
9
- /**
10
- * Signals a command `spawnShell` started and everything it started. Windows has no signals and
11
- * cmd.exe's children outlive it, so there the whole tree is ended at once by the first signal
12
- * and no cleanup runs.
13
- * @param {import('node:child_process').ChildProcess} child
14
- * @param {NodeJS.Signals} name
15
- */
16
- export function signalShell(child: import("node:child_process").ChildProcess, name: NodeJS.Signals): void;