@a5c-ai/babysitter-github 0.1.1-staging.0a3fc67d → 0.1.1-staging.1d2024f8

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,25 @@
1
+ {
2
+ "name": "babysitter",
3
+ "version": "0.1.0",
4
+ "description": "Orchestrate complex, multi-step workflows with event-sourced state management, hook-based extensibility, and human-in-the-loop approval -- powered by the Babysitter SDK",
5
+ "author": { "name": "a5c.ai", "email": "support@a5c.ai" },
6
+ "license": "MIT",
7
+ "skills": "skills/",
8
+ "hooks": "hooks.json",
9
+ "commands": "commands/",
10
+ "agents": "AGENTS.md",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "https://github.com/a5c-ai/babysitter"
14
+ },
15
+ "keywords": [
16
+ "orchestration",
17
+ "workflow",
18
+ "automation",
19
+ "event-sourced",
20
+ "hooks",
21
+ "github-copilot",
22
+ "agent",
23
+ "LLM"
24
+ ]
25
+ }
package/README.md CHANGED
@@ -1,6 +1,9 @@
1
1
  # @a5c-ai/babysitter-github
2
2
 
3
- Babysitter orchestration plugin for [GitHub Copilot CLI](https://docs.github.com/en/copilot/using-github-copilot/using-github-copilot-in-the-command-line).
3
+ Babysitter orchestration plugin for GitHub Copilot. It supports both:
4
+
5
+ - **GitHub Copilot CLI** via the local plugin and hook model
6
+ - **GitHub Copilot coding agent / cloud agent** via repository-installed skills and instructions
4
7
 
5
8
  This package ships a complete Copilot CLI plugin bundle -- skills, lifecycle
6
9
  hooks, and SDK integration -- that lets you run Babysitter's event-sourced,
@@ -19,6 +22,32 @@ directly.
19
22
 
20
23
  ## Installation
21
24
 
25
+ ### From marketplace (recommended)
26
+
27
+ Register the a5c.ai marketplace and install the plugin:
28
+
29
+ ```bash
30
+ # Register the marketplace
31
+ copilot plugin marketplace add a5c-ai/babysitter
32
+
33
+ # Install the plugin
34
+ copilot plugin install babysitter
35
+ ```
36
+
37
+ ### Direct GitHub install
38
+
39
+ Install directly from the Git repository using Copilot CLI. Copilot CLI
40
+ discovers the plugin via `.github/plugin/marketplace.json` at the repo root:
41
+
42
+ ```bash
43
+ copilot plugin install a5c-ai/babysitter
44
+ ```
45
+
46
+ ### Alternative Installation (npm / development)
47
+
48
+ For development or environments where the Copilot CLI plugin system is not
49
+ available, install via npm:
50
+
22
51
  Install the SDK CLI first:
23
52
 
24
53
  ```bash
@@ -45,6 +74,30 @@ Install into a specific workspace:
45
74
  babysitter-github install --workspace /path/to/repo
46
75
  ```
47
76
 
77
+ ### GitHub Copilot cloud agent installation
78
+
79
+ For GitHub Copilot's cloud-hosted coding agent, install repository-scoped
80
+ Babysitter support instead of the local `~/.copilot` CLI plugin surface:
81
+
82
+ ```bash
83
+ babysitter-github install --cloud-agent --workspace /path/to/repo
84
+ ```
85
+
86
+ This installs:
87
+
88
+ - a mirrored Babysitter GitHub plugin bundle under `.github/babysitter/github-plugin/`
89
+ - Babysitter skills under `.github/skills/`
90
+ - a managed Babysitter block in `AGENTS.md`
91
+ - a managed Babysitter block in `.github/copilot-instructions.md`
92
+ - a `copilot-setup-steps` workflow, or a generated merge candidate if the repo already has one
93
+
94
+ If the repository already has a custom `copilot-setup-steps.yml`, the
95
+ installer preserves it and writes a merge candidate to:
96
+
97
+ ```text
98
+ .github/workflows/copilot-setup-steps.babysitter.generated.yml
99
+ ```
100
+
48
101
  If the workspace does not already have an active process-library binding, the
49
102
  installer bootstraps the shared global SDK process library automatically:
50
103
 
@@ -54,6 +107,14 @@ babysitter process-library:active --json
54
107
 
55
108
  ## Uninstallation
56
109
 
110
+ Via Copilot CLI:
111
+
112
+ ```bash
113
+ copilot plugin uninstall babysitter
114
+ ```
115
+
116
+ Via npm:
117
+
57
118
  ```bash
58
119
  babysitter-github uninstall
59
120
  ```
@@ -64,8 +125,13 @@ The plugin provides:
64
125
 
65
126
  - `skills/babysit/SKILL.md` as the core orchestration entrypoint
66
127
  - Mode wrapper skills such as `$call`, `$plan`, and `$resume`
67
- - Plugin-level lifecycle hooks for `SessionStart`, `UserPromptSubmit`, and
68
- `Stop`
128
+ - Plugin-level lifecycle hooks for `sessionStart`, `sessionEnd`, and
129
+ `userPromptSubmitted`
130
+
131
+ For Copilot cloud agent, the hook scripts are mirrored into the repository as
132
+ part of the installed plugin bundle for reference and parity, but the hosted
133
+ agent path is driven by repository instructions, skills, and setup workflow
134
+ instead of local `~/.copilot/hooks.json`.
69
135
 
70
136
  The process library is fetched and bound through the SDK CLI in
71
137
  `~/.a5c/active/process-library.json`.
@@ -113,10 +179,10 @@ Fires when a new Copilot CLI session begins. The hook:
113
179
  `versions.json`)
114
180
  3. Creates baseline session state in the `.a5c` state directory
115
181
 
116
- ### Stop
182
+ ### SessionEnd
117
183
 
118
- The orchestration loop driver. When Copilot CLI attempts to end its turn,
119
- this hook intercepts the exit and:
184
+ The orchestration loop driver. Registered as `sessionEnd` in `hooks.json`,
185
+ this hook fires when the Copilot CLI session ends and:
120
186
 
121
187
  1. Checks whether the active run has completed or emitted a completion proof
122
188
  2. If the run is still in progress, re-injects the next orchestration step
@@ -128,7 +194,7 @@ This is what keeps Babysitter iterating autonomously within the Copilot CLI
128
194
  session -- each turn performs one orchestration phase, and the Stop hook
129
195
  decides whether to loop or yield.
130
196
 
131
- ### UserPromptSubmit
197
+ ### UserPromptSubmitted
132
198
 
133
199
  Fires before a user prompt reaches the model. The hook applies
134
200
  density-filter compression to long user prompts to reduce token usage while
@@ -139,9 +205,21 @@ preserving semantic content.
139
205
  ### AGENTS.md
140
206
 
141
207
  The plugin uses `AGENTS.md` (the Copilot CLI equivalent of `CLAUDE.md`) for
142
- custom agent instructions. This file is set via the `contextFileName` field
143
- in `plugin.json` and is read by Copilot CLI to configure agent behavior
144
- within sessions.
208
+ custom agent instructions. The cloud-agent installer appends a managed
209
+ Babysitter section to the repository root `AGENTS.md` so the hosted agent can
210
+ see the same orchestration guidance.
211
+
212
+ ### .github/copilot-instructions.md
213
+
214
+ The cloud-agent installer also appends a managed Babysitter block to
215
+ `.github/copilot-instructions.md`. This gives GitHub-hosted Copilot sessions a
216
+ repository-wide entrypoint for the Babysitter skills and setup workflow.
217
+
218
+ ### copilot-setup-steps workflow
219
+
220
+ The cloud-agent path seeds `.github/workflows/copilot-setup-steps.yml` with a
221
+ `copilot-setup-steps` job that installs the Babysitter SDK and initializes the
222
+ active process library before the cloud agent starts working.
145
223
 
146
224
  ### Environment Variables
147
225
 
@@ -174,6 +252,10 @@ Copilot CLI looks for the plugin manifest in these paths, checked in order:
174
252
 
175
253
  The first match wins. This plugin uses `plugin.json` at the package root.
176
254
 
255
+ For marketplace discovery, Copilot CLI looks for `.github/plugin/marketplace.json`
256
+ at the repository root. This file lists all available plugins in the repo and is
257
+ used when installing via `copilot plugin install OWNER/REPO`.
258
+
177
259
  ### plugin.json Schema
178
260
 
179
261
  The manifest declares metadata, skills, hooks, and optional integrations:
@@ -187,7 +269,7 @@ The manifest declares metadata, skills, hooks, and optional integrations:
187
269
  | `license` | No | `string` | SPDX license identifier |
188
270
  | `keywords` | No | `string[]` | Searchable tags for marketplace discovery |
189
271
  | `agents` | No | `string` | Path to agents directory |
190
- | `skills` | No | `array` | Array of skill directory paths (see below) |
272
+ | `skills` | No | `string` | Path to skills directory (auto-discovers SKILL.md files in subdirectories) |
191
273
  | `hooks` | No | `string` | Path to `hooks.json` |
192
274
  | `mcpServers` | No | `string` | Path to `.mcp.json` for MCP server configuration |
193
275
 
@@ -200,15 +282,9 @@ Example from this plugin:
200
282
  "description": "Orchestrate complex, multi-step workflows ...",
201
283
  "author": "a5c.ai",
202
284
  "license": "MIT",
203
- "hooks": {
204
- "sessionStart": "hooks/session-start.sh",
205
- "sessionEnd": "hooks/session-end.sh",
206
- "userPromptSubmitted": "hooks/user-prompt-submitted.sh"
207
- },
208
- "skills": [
209
- { "name": "babysit", "file": "skills/babysit/SKILL.md" },
210
- { "name": "call", "file": "skills/call/SKILL.md" }
211
- ],
285
+ "skills": "skills/",
286
+ "hooks": "hooks.json",
287
+ "commands": [],
212
288
  "keywords": ["orchestration", "workflow", "automation"]
213
289
  }
214
290
  ```
@@ -309,8 +385,8 @@ repositories that contain a manifest listing available plugins.
309
385
 
310
386
  ### Creating a Marketplace
311
387
 
312
- A marketplace is a Git repository with a `marketplace.json` file in
313
- `.github/plugin/` or `.claude-plugin/`:
388
+ A marketplace is a Git repository with a `marketplace.json` file at the
389
+ repository root in `.github/plugin/marketplace.json`:
314
390
 
315
391
  ```json
316
392
  {
@@ -387,6 +463,7 @@ These registries are available without running `marketplace add`.
387
463
  ```
388
464
  plugins/babysitter-github/
389
465
  plugin.json # Plugin manifest (skills, hooks, metadata)
466
+ .github/plugin.json # Plugin manifest (alternate discovery path)
390
467
  hooks.json # Hook configuration (sessionStart, sessionEnd, userPromptSubmitted)
391
468
  hooks/
392
469
  session-start.sh # SessionStart lifecycle hook
@@ -414,8 +491,30 @@ plugins/babysitter-github/
414
491
  AGENTS.md # Custom instructions for Copilot CLI
415
492
  ```
416
493
 
494
+ Cloud-agent installation additionally writes into the target repository:
495
+
496
+ ```
497
+ .github/
498
+ babysitter/github-plugin/ # Mirrored plugin bundle for repo-local visibility
499
+ skills/
500
+ babysitter-babysit/SKILL.md # Installed Babysitter cloud skills
501
+ babysitter-call/SKILL.md
502
+ ...
503
+ copilot-instructions.md # Managed Babysitter block appended
504
+ workflows/
505
+ copilot-setup-steps.yml # Managed workflow when no custom file exists
506
+ copilot-setup-steps.babysitter.generated.yml # Merge candidate when a custom file already exists
507
+ AGENTS.md # Managed Babysitter block appended
508
+ ```
509
+
417
510
  ## Verification
418
511
 
512
+ Verify marketplace registration:
513
+
514
+ ```bash
515
+ copilot plugin marketplace list
516
+ ```
517
+
419
518
  Verify the installed plugin:
420
519
 
421
520
  ```bash
package/bin/cli.js CHANGED
@@ -11,6 +11,7 @@ function printUsage() {
11
11
  'Usage:',
12
12
  ' babysitter-github install [--global]',
13
13
  ' babysitter-github install --workspace [path]',
14
+ ' babysitter-github install --cloud-agent [--workspace [path]]',
14
15
  ' babysitter-github uninstall',
15
16
  ].join('\n'));
16
17
  }
@@ -18,6 +19,7 @@ function printUsage() {
18
19
  function parseInstallArgs(argv) {
19
20
  let scope = 'global';
20
21
  let workspace = null;
22
+ let cloudAgent = false;
21
23
  const passthrough = [];
22
24
 
23
25
  for (let i = 0; i < argv.length; i += 1) {
@@ -43,10 +45,16 @@ function parseInstallArgs(argv) {
43
45
  }
44
46
  continue;
45
47
  }
48
+ if (arg === '--cloud-agent') {
49
+ cloudAgent = true;
50
+ passthrough.push(arg);
51
+ continue;
52
+ }
46
53
  passthrough.push(arg);
47
54
  }
48
55
 
49
56
  return {
57
+ cloudAgent,
50
58
  scope,
51
59
  workspace,
52
60
  passthrough,
@@ -75,6 +83,10 @@ function main() {
75
83
 
76
84
  if (command === 'install') {
77
85
  const parsed = parseInstallArgs(rest);
86
+ if (parsed.cloudAgent) {
87
+ runNodeScript(path.join(PACKAGE_ROOT, 'bin', 'install.js'), parsed.passthrough);
88
+ return;
89
+ }
78
90
  if (parsed.scope === 'workspace') {
79
91
  const args = [];
80
92
  if (parsed.workspace) {
@@ -5,7 +5,7 @@ const os = require('os');
5
5
  const path = require('path');
6
6
  const { spawnSync } = require('child_process');
7
7
 
8
- const PLUGIN_NAME = 'babysitter-github';
8
+ const PLUGIN_NAME = 'babysitter';
9
9
  const PLUGIN_CATEGORY = 'Coding';
10
10
  const LEGACY_HOOK_SCRIPT_NAMES = [
11
11
  'session-start.sh',
@@ -35,6 +35,22 @@ const PLUGIN_BUNDLE_ENTRIES = [
35
35
  'versions.json',
36
36
  'AGENTS.md',
37
37
  ];
38
+ const CLOUD_AGENT_BUNDLE_ENTRIES = [
39
+ '.github',
40
+ 'AGENTS.md',
41
+ 'README.md',
42
+ 'bin',
43
+ 'commands',
44
+ 'hooks',
45
+ 'hooks.json',
46
+ 'package.json',
47
+ 'plugin.json',
48
+ 'scripts',
49
+ 'skills',
50
+ 'versions.json',
51
+ ];
52
+ const MANAGED_BLOCK_START = '<!-- BEGIN BABYSITTER GITHUB CLOUD AGENT -->';
53
+ const MANAGED_BLOCK_END = '<!-- END BABYSITTER GITHUB CLOUD AGENT -->';
38
54
 
39
55
  function getCopilotHome() {
40
56
  if (process.env.COPILOT_HOME) return path.resolve(process.env.COPILOT_HOME);
@@ -145,6 +161,79 @@ function writeJson(filePath, value) {
145
161
  writeFileIfChanged(filePath, `${JSON.stringify(value, null, 2)}\n`);
146
162
  }
147
163
 
164
+ function replaceManagedMarkdownBlock(existing, block) {
165
+ const normalized = String(existing || '').replace(/\r\n/g, '\n');
166
+ const managedBlock = `${MANAGED_BLOCK_START}\n${block.trim()}\n${MANAGED_BLOCK_END}`;
167
+ const escapedStart = MANAGED_BLOCK_START.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
168
+ const escapedEnd = MANAGED_BLOCK_END.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
169
+ const managedPattern = new RegExp(`${escapedStart}[\\s\\S]*?${escapedEnd}`, 'm');
170
+
171
+ if (managedPattern.test(normalized)) {
172
+ return normalized.replace(managedPattern, managedBlock).replace(/\n{3,}/g, '\n\n').trimEnd() + '\n';
173
+ }
174
+
175
+ if (normalized.trim().length === 0) {
176
+ return `${managedBlock}\n`;
177
+ }
178
+
179
+ return `${normalized.trimEnd()}\n\n${managedBlock}\n`;
180
+ }
181
+
182
+ function writeManagedMarkdown(filePath, block) {
183
+ const existing = fs.existsSync(filePath) ? fs.readFileSync(filePath, 'utf8') : '';
184
+ return writeFileIfChanged(filePath, replaceManagedMarkdownBlock(existing, block));
185
+ }
186
+
187
+ function readSdkVersion(packageRoot) {
188
+ const versionsPath = path.join(packageRoot, 'versions.json');
189
+ if (!fs.existsSync(versionsPath)) {
190
+ return 'latest';
191
+ }
192
+ try {
193
+ const parsed = readJson(versionsPath);
194
+ return typeof parsed.sdkVersion === 'string' && parsed.sdkVersion.trim() !== ''
195
+ ? parsed.sdkVersion.trim()
196
+ : 'latest';
197
+ } catch {
198
+ return 'latest';
199
+ }
200
+ }
201
+
202
+ function toLowerHyphenName(name) {
203
+ return String(name)
204
+ .trim()
205
+ .toLowerCase()
206
+ .replace(/[^a-z0-9]+/g, '-')
207
+ .replace(/^-+|-+$/g, '');
208
+ }
209
+
210
+ function rewriteCloudSkill(skillId, contents) {
211
+ const normalized = String(contents).replace(/\r\n/g, '\n');
212
+ const prefixedName = `babysitter-${skillId}`;
213
+ let next = normalized;
214
+
215
+ if (next.startsWith('---\n')) {
216
+ next = next.replace(/^---\n([\s\S]*?)\n---\n?/, (_match, frontmatter) => {
217
+ const lines = String(frontmatter).split('\n');
218
+ let sawName = false;
219
+ const updatedLines = lines.map((line) => {
220
+ if (/^name:\s*/.test(line)) {
221
+ sawName = true;
222
+ return `name: ${prefixedName}`;
223
+ }
224
+ return line;
225
+ });
226
+ if (!sawName) {
227
+ updatedLines.push(`name: ${prefixedName}`);
228
+ }
229
+ return `---\n${updatedLines.join('\n')}\n---\n`;
230
+ });
231
+ }
232
+
233
+ next = next.replace(/^#\s+.+$/m, `# ${prefixedName}`);
234
+ return next.replace(/\n{3,}/g, '\n\n').trimEnd() + '\n';
235
+ }
236
+
148
237
  function ensureMarketplaceEntry(marketplacePath, pluginSourcePath) {
149
238
  const marketplace = fs.existsSync(marketplacePath)
150
239
  ? readJson(marketplacePath)
@@ -369,6 +458,167 @@ function installCopilotSurface(packageRoot, copilotHome) {
369
458
  installManagedHooks(packageRoot, copilotHome);
370
459
  }
371
460
 
461
+ function renderCloudAgentAgentsBlock() {
462
+ return [
463
+ '## Babysitter Cloud Agent',
464
+ '',
465
+ 'This repository is configured to let GitHub Copilot cloud agent use Babysitter orchestration assets.',
466
+ '',
467
+ '- For complex multi-step work, use the Babysitter skills installed under `.github/skills/` when relevant.',
468
+ '- The cloud-agent setup workflow installs the Babysitter SDK before work begins.',
469
+ '- If you need the full orchestration instructions, run `babysitter instructions:babysit-skill --harness github-copilot --json`.',
470
+ '- Execute requested shell and Node tasks directly and report the results instead of describing what should be done.',
471
+ '- Do not revert unrelated user changes.',
472
+ ].join('\n');
473
+ }
474
+
475
+ function renderCloudAgentCopilotInstructionsBlock() {
476
+ return [
477
+ '# Babysitter Copilot Cloud Agent Support',
478
+ '',
479
+ 'This repository includes Babysitter support for GitHub Copilot cloud agent.',
480
+ '',
481
+ '- Read the nearest `AGENTS.md` instructions before making changes.',
482
+ '- Consider the Babysitter skills under `.github/skills/` when the task is a multi-step workflow, orchestration run, diagnosis, planning, or retrospective.',
483
+ '- The `copilot-setup-steps` workflow installs the Babysitter SDK and initializes the active process library before the agent starts working.',
484
+ '- Add repository-specific build, test, and validation commands below this managed section if they are not already documented elsewhere in the repo.',
485
+ ].join('\n');
486
+ }
487
+
488
+ function renderCloudAgentSetupWorkflow(packageRoot) {
489
+ const sdkVersion = readSdkVersion(packageRoot);
490
+ return [
491
+ 'name: "Copilot Setup Steps"',
492
+ '',
493
+ 'on:',
494
+ ' workflow_dispatch:',
495
+ ' push:',
496
+ ' paths:',
497
+ ' - .github/workflows/copilot-setup-steps.yml',
498
+ ' - .github/copilot-instructions.md',
499
+ ' - .github/skills/**',
500
+ ' - AGENTS.md',
501
+ ' pull_request:',
502
+ ' paths:',
503
+ ' - .github/workflows/copilot-setup-steps.yml',
504
+ ' - .github/copilot-instructions.md',
505
+ ' - .github/skills/**',
506
+ ' - AGENTS.md',
507
+ '',
508
+ 'jobs:',
509
+ ' copilot-setup-steps:',
510
+ ' runs-on: ubuntu-latest',
511
+ ' permissions:',
512
+ ' contents: read',
513
+ ' steps:',
514
+ ' - name: Check out repository',
515
+ ' uses: actions/checkout@v4',
516
+ '',
517
+ ' - name: Set up Node.js',
518
+ ' uses: actions/setup-node@v4',
519
+ ' with:',
520
+ ' node-version: 22',
521
+ ' cache: npm',
522
+ '',
523
+ ' - name: Install Babysitter SDK',
524
+ ` run: npm install -g @a5c-ai/babysitter-sdk@${sdkVersion}`,
525
+ '',
526
+ ' - name: Initialize active process library',
527
+ ' run: babysitter process-library:active --json',
528
+ ].join('\n') + '\n';
529
+ }
530
+
531
+ function installCloudAgentBundle(packageRoot, workspaceRoot) {
532
+ const bundleRoot = path.join(workspaceRoot, '.github', 'babysitter', 'github-plugin');
533
+ fs.rmSync(bundleRoot, { recursive: true, force: true });
534
+ fs.mkdirSync(bundleRoot, { recursive: true });
535
+ for (const entry of CLOUD_AGENT_BUNDLE_ENTRIES) {
536
+ const sourcePath = path.join(packageRoot, entry);
537
+ if (!fs.existsSync(sourcePath)) {
538
+ continue;
539
+ }
540
+ copyRecursive(sourcePath, path.join(bundleRoot, entry));
541
+ }
542
+ return bundleRoot;
543
+ }
544
+
545
+ function installCloudAgentSkills(packageRoot, workspaceRoot) {
546
+ const sourceRoot = path.join(packageRoot, 'skills');
547
+ if (!fs.existsSync(sourceRoot)) return [];
548
+
549
+ const targetRoot = path.join(workspaceRoot, '.github', 'skills');
550
+ fs.mkdirSync(targetRoot, { recursive: true });
551
+ const installed = [];
552
+
553
+ for (const entry of fs.readdirSync(sourceRoot, { withFileTypes: true })) {
554
+ if (!entry.isDirectory()) continue;
555
+ const sourceDir = path.join(sourceRoot, entry.name);
556
+ const skillId = toLowerHyphenName(entry.name);
557
+ const targetDir = path.join(targetRoot, `babysitter-${skillId}`);
558
+ fs.rmSync(targetDir, { recursive: true, force: true });
559
+ copyRecursive(sourceDir, targetDir);
560
+ const skillPath = path.join(targetDir, 'SKILL.md');
561
+ if (fs.existsSync(skillPath)) {
562
+ const rewritten = rewriteCloudSkill(skillId, fs.readFileSync(skillPath, 'utf8'));
563
+ fs.writeFileSync(skillPath, rewritten, 'utf8');
564
+ }
565
+ installed.push(targetDir);
566
+ }
567
+
568
+ return installed;
569
+ }
570
+
571
+ function installCloudAgentInstructions(packageRoot, workspaceRoot) {
572
+ const agentsPath = path.join(workspaceRoot, 'AGENTS.md');
573
+ const copilotInstructionsPath = path.join(workspaceRoot, '.github', 'copilot-instructions.md');
574
+
575
+ writeManagedMarkdown(agentsPath, renderCloudAgentAgentsBlock(packageRoot));
576
+ writeManagedMarkdown(copilotInstructionsPath, renderCloudAgentCopilotInstructionsBlock(packageRoot));
577
+
578
+ return {
579
+ agentsPath,
580
+ copilotInstructionsPath,
581
+ };
582
+ }
583
+
584
+ function installCloudAgentSetupSteps(packageRoot, workspaceRoot) {
585
+ const workflowsDir = path.join(workspaceRoot, '.github', 'workflows');
586
+ const workflowPath = path.join(workflowsDir, 'copilot-setup-steps.yml');
587
+ const examplePath = path.join(workflowsDir, 'copilot-setup-steps.babysitter.generated.yml');
588
+ const contents = renderCloudAgentSetupWorkflow(packageRoot);
589
+
590
+ fs.mkdirSync(workflowsDir, { recursive: true });
591
+
592
+ if (!fs.existsSync(workflowPath)) {
593
+ writeFileIfChanged(workflowPath, contents);
594
+ fs.rmSync(examplePath, { force: true });
595
+ return { workflowPath, examplePath: null, managed: true, needsManualMerge: false };
596
+ }
597
+
598
+ const existing = fs.readFileSync(workflowPath, 'utf8');
599
+ if (existing.includes('copilot-setup-steps') && existing.includes('@a5c-ai/babysitter-sdk')) {
600
+ writeFileIfChanged(workflowPath, contents);
601
+ fs.rmSync(examplePath, { force: true });
602
+ return { workflowPath, examplePath: null, managed: true, needsManualMerge: false };
603
+ }
604
+
605
+ writeFileIfChanged(examplePath, contents);
606
+ return { workflowPath, examplePath, managed: false, needsManualMerge: true };
607
+ }
608
+
609
+ function installCloudAgentSurface(packageRoot, workspaceRoot) {
610
+ const bundleRoot = installCloudAgentBundle(packageRoot, workspaceRoot);
611
+ const skillDirs = installCloudAgentSkills(packageRoot, workspaceRoot);
612
+ const instructions = installCloudAgentInstructions(packageRoot, workspaceRoot);
613
+ const setupWorkflow = installCloudAgentSetupSteps(packageRoot, workspaceRoot);
614
+ return {
615
+ bundleRoot,
616
+ skillDirs,
617
+ ...instructions,
618
+ setupWorkflow,
619
+ };
620
+ }
621
+
372
622
  function resolveBabysitterCommand(packageRoot) {
373
623
  if (process.env.BABYSITTER_SDK_CLI) {
374
624
  return {
@@ -442,6 +692,7 @@ module.exports = {
442
692
  getHomeMarketplacePath,
443
693
  getHomePluginRoot,
444
694
  installCopilotSurface,
695
+ installCloudAgentSurface,
445
696
  registerCopilotPlugin,
446
697
  removeLegacyHooks,
447
698
  removeMarketplaceEntry,