@serviceme/devtools-core 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -4,8 +4,8 @@ import * as fs from 'node:fs/promises';
4
4
  export { A as AccessCheckResult, a as AccessControl, b as AccessControlOptions, c as AuthCore, d as AuthCoreOptions, e as AuthStateManager, f as AuthStateManagerOptions, C as CancellationCheck, D as DeviceFlowUiCallback, G as GitHubAuthProvider, g as GitHubAuthProviderConfig, I as IAuthProvider, h as IAuthProviderSession, i as IAuthProviderUserInfo, j as InMemoryKeychainAuthTokenStore, K as KeyValueStore, k as KeychainAccountKey, l as KeychainAuthTokenStore, m as KeychainTokenEnvelope, n as KeychainTokenMetadata, o as KeychainUnavailableError, M as MicrosoftAuthProvider, p as MicrosoftProviderNotHostedError, O as OrgMembershipFetcher, P as ProviderRegistry, S as ServiceMeLogger, q as buildGitHubLocalEmail, r as createConsoleLogger, s as isGitHubLocalEmail, t as noopLogger, u as resolvePrimaryEmail } from './index-PD135hlB.js';
5
5
  export { AtomicWriteResult, BuildSignedHeadersParams, DEVICE_JSON_SCHEMA_VERSION, DeviceAuthHeaders, DeviceCore, DeviceCoreOptions, DeviceReenrollRequiresAuthError, DeviceRequestSignatureParams, DeviceSecretVersionMismatchError, DeviceSignedHeaders, EnrollRequestFn, EnrollResponse, Enroller, EnrollerOptions, FsIdentityFileBackend, IdentityFileBackend, IdentityStore, IdentityStoreHooks, IdentityStoreOptions, PersistedDeviceIdentity, buildSignedHeaders, createDeviceRequestSignature, deriveInstallationId, fingerprintSource, randomInstallationId } from './device.js';
6
6
  import { c as SkillKind, b as SkillFile } from './types-B9gk3dXH.js';
7
- import { G as GitClient, P as PullResult } from './index-CR1hbAnO.js';
8
- export { a as GIT_PROXY_PATH_SUFFIX, b as GitError, N as NodeGitSpawner, S as StubGitSpawner, c as SubmitClient, d as SubmitClientOptions, e as SubmitError, f as SubmitOptions, g as SubmitResult, h as buildGitProxyBase, t as toFileUrl } from './index-CR1hbAnO.js';
7
+ import { G as GitClient, P as PullResult } from './index-CymN0x9Z.js';
8
+ export { a as GIT_PROXY_PATH_SUFFIX, b as GitError, N as NodeGitSpawner, S as StubGitSpawner, c as SubmitClient, d as SubmitClientOptions, e as SubmitError, f as SubmitOptions, g as SubmitResult, h as buildGitProxyBase, t as toFileUrl } from './index-CymN0x9Z.js';
9
9
  import * as fs$1 from 'node:fs';
10
10
  import { z } from 'zod';
11
11
  export { BUILTIN_DEFAULT_TOOLS, DefaultToolImmutableError, DefaultToolSeed, FsToolboxFileBackend, PersistedToolbox, ResolvedToolbox, TOOLBOX_JSON_SCHEMA_VERSION, ToolboxCore, ToolboxCoreOptions, ToolboxFileBackend, ToolboxPatch, ToolboxStore, ToolboxStoreHooks, ToolboxStoreOptions, WORKSPACE_TOOLBOX_RELATIVE_PATH, mergeWithDefaults, reindexOrder, sortByRecentFirst, sortByUserOrder, touchLastUsedAt } from './toolbox.js';
@@ -113,6 +113,32 @@ declare class AgentStore {
113
113
  writeAgentFiles(agentId: string, scope: "workspace" | "user", files: AgentDownloadFile[]): Promise<void>;
114
114
  private listAgentIds;
115
115
  }
116
+ /** One legacy content entry reported by {@link migrateLegacyUserContent}. */
117
+ interface LegacyUserContentEntry {
118
+ /** Legacy agent id derived from the file or directory name. */
119
+ id: string;
120
+ /** Absolute path of the legacy content under ~/.agents. */
121
+ legacyPath: string;
122
+ /** Target path under ~/.copilot the migration would create. */
123
+ targetPath: string;
124
+ /** Always `migration_available` until the user runs the migration. */
125
+ status: "migration_available";
126
+ }
127
+ interface LegacyUserContentMigrationResult {
128
+ entries: LegacyUserContentEntry[];
129
+ }
130
+ /**
131
+ * Detect ~/.agents agent content that can migrate to ~/.copilot.
132
+ *
133
+ * Read-only by design: legacy content stays untouched until the user
134
+ * explicitly invokes the migration, so a detection pass never destroys
135
+ * anything another tool still depends on.
136
+ */
137
+ declare function migrateLegacyUserContent(input: {
138
+ homeDir: string;
139
+ workspaceDir: string;
140
+ fileSystem?: AgentStoreFileSystem;
141
+ }): Promise<LegacyUserContentMigrationResult>;
116
142
 
117
143
  /**
118
144
  * Quick auth pre-flight check using `gh auth status`.
@@ -125,6 +151,1104 @@ declare function createCopilotAuthRequiredError(): _serviceme_devtools_protocol.
125
151
 
126
152
  declare function copilotPrompt(options: CopilotPromptOptions): Promise<CopilotPromptResult>;
127
153
 
154
+ /**
155
+ * Contracts for the declarative Copilot content lifecycle.
156
+ *
157
+ * Three layers (see docs/architecture/copilot-content-reconciliation.md):
158
+ * 1. content sources under ~/.serviceme/repos/<repo-id>
159
+ * 2. a shared, git-tracked workspace declaration
160
+ * 3. machine-local materialization state under ~/.serviceme/workspaces
161
+ */
162
+ /** Artifact kinds a logical plugin can contribute to Copilot. */
163
+ type CopilotArtifactKind = "agent" | "skill" | "instruction" | "prompt" | "hook" | "mcp";
164
+ /** A repository pinned to an exact commit for reproducible restoration. */
165
+ interface WorkspaceManifestRepository {
166
+ /** Stable id used in on-disk paths and plugin references. */
167
+ id: string;
168
+ /** Authoritative cross-machine source identity (HTTPS or git@ URL). */
169
+ url: string;
170
+ /** Full 40-character commit SHA; branch names are not allowed. */
171
+ commit: string;
172
+ }
173
+ /** A Git source in the v2 manifest syntax. */
174
+ interface WorkspaceManifestGitSource extends WorkspaceManifestRepository {
175
+ type: "git";
176
+ }
177
+ /** An immutable marketplace artifact materialized under ~/.serviceme/repos/<id>. */
178
+ interface WorkspaceManifestCatalogSource {
179
+ type: "catalog";
180
+ /** Stable local repository id used for the managed source directory. */
181
+ id: string;
182
+ /** Marketplace identity, independent of any transient download URL. */
183
+ catalogId: string;
184
+ /** Immutable catalog release selected by the workspace. */
185
+ revision: string;
186
+ /** SHA-256 of the complete catalog payload, prefixed with sha256:. */
187
+ digest: string;
188
+ }
189
+ /** A source that can be restored on each collaborator's machine. */
190
+ type WorkspaceManifestSource = WorkspaceManifestGitSource | WorkspaceManifestCatalogSource;
191
+ /** A logical plugin selection inside the workspace declaration. */
192
+ interface WorkspaceManifestPlugin {
193
+ /** Referenced repository id. */
194
+ repository: string;
195
+ /** Logical plugin id from plugin.json, or the legacy skill/agent name. */
196
+ id: string;
197
+ /** Legacy artifact-kind selection, retained for compatible workspace declarations. */
198
+ artifacts: Partial<Record<CopilotArtifactKind, boolean>>;
199
+ /** Exact resolver artifact identities selected for this package. */
200
+ artifactIds?: string[];
201
+ }
202
+ /** A v2 logical plugin selection references any supported source type. */
203
+ interface WorkspaceManifestPluginV2 {
204
+ /** Referenced source id. */
205
+ source: string;
206
+ /** Logical plugin id from plugin.json, or the legacy skill/agent name. */
207
+ id: string;
208
+ /** Legacy artifact-kind selection, retained for compatible workspace declarations. */
209
+ artifacts: Partial<Record<CopilotArtifactKind, boolean>>;
210
+ /** Exact resolver artifact identities selected for this package. */
211
+ artifactIds?: string[];
212
+ }
213
+ /** Root shape of .github/serviceme-plugins.json. */
214
+ interface WorkspaceCopilotManifestV1 {
215
+ version: 1;
216
+ repositories: WorkspaceManifestRepository[];
217
+ plugins: WorkspaceManifestPlugin[];
218
+ }
219
+ /** Root v2 shape: sources may be Git checkouts or immutable catalog artifacts. */
220
+ interface WorkspaceCopilotManifestV2 {
221
+ version: 2;
222
+ sources: WorkspaceManifestSource[];
223
+ plugins: WorkspaceManifestPluginV2[];
224
+ }
225
+ /** Root shape of .github/serviceme-plugins.json. */
226
+ type WorkspaceCopilotManifest = WorkspaceCopilotManifestV1 | WorkspaceCopilotManifestV2;
227
+ /** Normalize the versioned source list for consumers that do not care about syntax. */
228
+ declare function getWorkspaceManifestSources(manifest: WorkspaceCopilotManifest): WorkspaceManifestSource[];
229
+ /** Resolve a versioned plugin selection to its source id. */
230
+ declare function getWorkspaceManifestPluginSourceId(manifest: WorkspaceCopilotManifest, plugin: WorkspaceManifestPlugin | WorkspaceManifestPluginV2): string;
231
+ /** Materialization mode used when activating an entry on the current machine. */
232
+ type CopilotLinkMode = "symlink" | "junction" | "generated";
233
+ /** One materialized entry recorded in machine-local state. */
234
+ interface WorkspaceMaterializedEntry {
235
+ /** Stable identity: repository::plugin::kind[:name]. */
236
+ identity: string;
237
+ /** Owning repository id. */
238
+ repositoryId: string;
239
+ /** Owning logical plugin id. */
240
+ pluginId: string;
241
+ /** Artifact kind of this entry. */
242
+ kind: CopilotArtifactKind;
243
+ /** Absolute source path under ~/.serviceme/repos. */
244
+ sourcePath: string;
245
+ /** Workspace-relative link path. */
246
+ linkPath: string;
247
+ /** Link mode used on this machine. */
248
+ linkMode: CopilotLinkMode;
249
+ /** SHA-256 digest of the pinned source content. */
250
+ digest: string;
251
+ /** Whether the current machine approved risky content. */
252
+ approved: boolean;
253
+ }
254
+ /** Machine-local materialization state; never shared through git. */
255
+ interface WorkspaceContentState {
256
+ version: 1;
257
+ entries: WorkspaceMaterializedEntry[];
258
+ }
259
+
260
+ /** One immutable materialization step in a resolved content plan. */
261
+ interface PlannedContentEntry {
262
+ /** Stable identity: repository::plugin::kind[:name]. */
263
+ identity: string;
264
+ /** Owning repository id. */
265
+ repositoryId: string;
266
+ /** Owning logical plugin id. */
267
+ pluginId: string;
268
+ /** Artifact kind of this entry. */
269
+ kind: CopilotArtifactKind;
270
+ /** Absolute source path under the repository root. */
271
+ sourcePath: string;
272
+ /** Whether the source is a single file (agent/instruction) or a directory (skill). */
273
+ sourceIsFile: boolean;
274
+ /** Copilot-facing name used at the link target. */
275
+ name: string;
276
+ /** SHA-256 digest over the source content. */
277
+ digest: string;
278
+ /** Whether local approval is required before activation. */
279
+ requiresApproval: boolean;
280
+ }
281
+ /** Result of resolving a workspace declaration against local repositories. */
282
+ interface WorkspaceContentPlan {
283
+ entries: PlannedContentEntry[];
284
+ }
285
+
286
+ interface ResolvedPluginManifest {
287
+ name: string;
288
+ description?: string;
289
+ version?: string;
290
+ extensions: Record<string, Record<string, unknown>>;
291
+ }
292
+ interface ResolvedPluginEntry extends PlannedContentEntry {
293
+ /** Stable artifact identifier for consumers that do not need to parse identity. */
294
+ artifactId: string;
295
+ /** Stable package identifier for the logical repository/plugin pair. */
296
+ packageId: string;
297
+ /** Display metadata for the logical package. */
298
+ packageDisplayName: string;
299
+ packageDescription?: string;
300
+ packageVersion?: string;
301
+ }
302
+ /** Resolve a workspace declaration into an immutable content plan. */
303
+ declare function resolveWorkspaceContentPlan(input: {
304
+ manifest: WorkspaceCopilotManifest;
305
+ reposDir: string;
306
+ }): Promise<{
307
+ entries: ResolvedPluginEntry[];
308
+ }>;
309
+ /**
310
+ * Lenient variant for CATALOG BROWSING: resolve a single plugin's
311
+ * declared artifacts, skipping paths that are missing or
312
+ * unverifiable instead of throwing. Upstream plugin.json files in
313
+ * the wild carry typos (e.g. declaring `./agents/x.md` for a file
314
+ * that ships as `x.agent.md`); a strict throw hides the whole
315
+ * package from browse — while installs still go through the strict
316
+ * pipeline, so a listing here never guarantees a broken install.
317
+ *
318
+ * Only skills/agents/prompts/instructions path arrays are probed
319
+ * here; mcp.json/hooks stay install-pipeline-only (they materialize
320
+ * shared config and MUST pass the strict gate).
321
+ */
322
+ declare function resolvePluginEntriesLenient(input: {
323
+ repoRoot: string;
324
+ repositoryId: string;
325
+ pluginId: string;
326
+ manifest: ResolvedPluginManifest;
327
+ }): Promise<ResolvedPluginEntry[]>;
328
+
329
+ /** Personal artifact kinds materialized as managed links into host target directories. */
330
+ declare const allPersonalLinkKinds: readonly ["agent", "skill", "prompt", "instruction"];
331
+ /** One personal link kind. */
332
+ type PersonalLinkKind = (typeof allPersonalLinkKinds)[number];
333
+ /**
334
+ * Adapter that applies or removes one personal integration entry (mcp/hook)
335
+ * in host-owned user configuration. Implementations own their config format;
336
+ * callers own the digest approval rule.
337
+ */
338
+ interface CopilotIntegrationAdapter {
339
+ /** Apply one approved integration entry on this machine. */
340
+ applyEntry(input: {
341
+ entry: ResolvedPluginEntry;
342
+ }): Promise<void>;
343
+ /** Remove a previously applied entry; returns whether anything was removed. */
344
+ removeEntry(input: {
345
+ identity: string;
346
+ }): Promise<boolean>;
347
+ }
348
+ /** Host-verified personal materialization targets and integration adapters. */
349
+ interface CopilotHostCapabilities {
350
+ /** Absolute, host-verified target directory per personal link kind. */
351
+ personalTargets: Partial<Record<PersonalLinkKind, string>>;
352
+ /** Adapter for personal MCP configuration, when the host supports one. */
353
+ mcpAdapter?: CopilotIntegrationAdapter;
354
+ /** Adapter for personal hook registration, when the host supports one. */
355
+ hookAdapter?: CopilotIntegrationAdapter;
356
+ }
357
+ /** Whether the host verified a personal target directory for the kind. */
358
+ declare function supportsPersonalLinkKind(capabilities: CopilotHostCapabilities, kind: PersonalLinkKind): boolean;
359
+ /** Whether the host provides the adapter an integration kind requires. */
360
+ declare function supportsPersonalIntegrationKind(capabilities: CopilotHostCapabilities, kind: "mcp" | "hook"): boolean;
361
+ /**
362
+ * Conservative production capability provider.
363
+ *
364
+ * Only claims targets it can actually verify on this host: the canonical
365
+ * home '.copilot/agents' and '.copilot/skills' directories when they already
366
+ * exist. Prompt, instruction, MCP, and hook personal targets stay unclaimed
367
+ * until a verified provider wires them (Task 9); the reconciler reports those
368
+ * kinds as unsupported instead of inventing directories.
369
+ */
370
+ declare function createDefaultCopilotHostCapabilities(options?: {
371
+ copilotHomeDir?: string;
372
+ }): Promise<CopilotHostCapabilities>;
373
+
374
+ /** Status of one entry after a reconcile pass. */
375
+ type MaterializeEntryStatus = "restored" | "adopted" | "conflict" | "drifted" | "pending_approval";
376
+ interface MaterializeEntryResult {
377
+ identity: string;
378
+ status: MaterializeEntryStatus;
379
+ /** Secondary machine-local state, e.g. migration_available for legacy links. */
380
+ message?: string;
381
+ }
382
+ interface MaterializeResult {
383
+ changed: boolean;
384
+ entries: MaterializeEntryResult[];
385
+ /** Updated machine-local state (only successfully materialized entries). */
386
+ state: WorkspaceContentState;
387
+ }
388
+ /** Create and inspect Copilot links; never overwrite unowned content. */
389
+ declare class CopilotLinkMaterializer {
390
+ private pendingFailure;
391
+ /** Test seam: make the next reconcile throw, then clear the failure. */
392
+ failNext(error: Error): void;
393
+ /** Materialize planned entries with conflict/drift safety. */
394
+ reconcile(input: {
395
+ workspaceDir: string;
396
+ entries: PlannedContentEntry[];
397
+ previousState: WorkspaceContentState;
398
+ }): Promise<MaterializeResult>;
399
+ /** Adopt a matching legacy link without recreating it. */
400
+ adoptLegacyLink(input: {
401
+ workspaceDir: string;
402
+ entry: PlannedContentEntry;
403
+ }): Promise<MaterializeEntryResult>;
404
+ /** Inspect a legacy ~/.agents link; report without deleting. */
405
+ inspectLegacyUserLink(input: {
406
+ homeDir: string;
407
+ entry: PlannedContentEntry;
408
+ }): Promise<MaterializeEntryResult>;
409
+ private resolveLinkPath;
410
+ private createLinkAtomic;
411
+ private toStateEntry;
412
+ private toStateLinkPath;
413
+ }
414
+
415
+ /**
416
+ * Copilot plugin whole-package registration.
417
+ *
418
+ * Installs a plugin.json package by projecting its canonical checkout
419
+ * into SERVICEME's own registry location
420
+ * (`~/.serviceme/copilot-plugins/<repoId>:<pluginId>`), enabled through
421
+ * a path-keyed `chat.pluginLocations` entry (extension-owned).
422
+ *
423
+ * The projection is MATERIALIZED (see plugin-materializer.ts): a real
424
+ * directory whose entries symlink the resolved checkout content and
425
+ * whose layout matches what VS Code loads (content under the
426
+ * `com.github.copilot/` namespace, manifest at the root and under
427
+ * `.plugin/`).
428
+ *
429
+ * LOCATION HISTORY — everything under `~/.copilot` turned out to be VS
430
+ * Code territory whose reconciliation/uninstall flows DELETE
431
+ * hand-written projections (verified on-machine for both
432
+ * `installed-plugins/` and `serviceme-plugins/`). The registry therefore
433
+ * lives under the SERVICEME home, which VS Code never touches, and the
434
+ * constructor migrates surviving records/projections from the legacy
435
+ * locations.
436
+ *
437
+ * Scope note: plugin packages are PERSONAL-scope only — the
438
+ * projection is user-level and identical for every caller. The
439
+ * `scopes` record shape stays for compatibility; an omitted scope
440
+ * registers as personal.
441
+ *
442
+ * `chat.pluginLocations` (VS Code user settings) is intentionally
443
+ * NOT handled here — it can only be written by the extension layer.
444
+ */
445
+ interface CopilotPluginRegistrarOptions {
446
+ /** Projection root. Defaults to `${SERVICEME_HOME}/copilot-plugins`. */
447
+ pluginsDir?: string;
448
+ /** `~/.copilot` — migration source only (VS Code owns that tree). */
449
+ copilotDir?: string;
450
+ }
451
+ interface CopilotPluginRegisterInput {
452
+ repoId: string;
453
+ pluginId: string;
454
+ /** Canonical checkout plugin directory (the whole package root). */
455
+ pluginDir: string;
456
+ /** @deprecated Projection root comes from the constructor; ignored. */
457
+ copilotDir?: string;
458
+ scope?: "workspace" | "personal";
459
+ displayName?: string;
460
+ version?: string;
461
+ }
462
+ interface CopilotPluginRegistration {
463
+ /** `${repoId}:${pluginId}` — path-safe. */
464
+ registrationId: string;
465
+ repoId: string;
466
+ pluginId: string;
467
+ pluginDir: string;
468
+ displayName?: string;
469
+ version?: string;
470
+ scopes: Array<"workspace" | "personal">;
471
+ }
472
+ declare class CopilotPluginRegistrar {
473
+ private readonly pluginsDir;
474
+ private readonly copilotDir;
475
+ private migrated;
476
+ constructor(options?: CopilotPluginRegistrarOptions);
477
+ /** Registry root — resolved, used as the boundary for all path joins. */
478
+ private installedDir;
479
+ /** Projection path for an id, with an explicit containment check. */
480
+ private linkPath;
481
+ private registryPath;
482
+ /**
483
+ * One-shot migration away from `~/.copilot` (VS Code territory):
484
+ * carries over registry records and surviving projections from both
485
+ * legacy layouts and removes the old trees. Self-guarding when the
486
+ * source and destination coincide; safe to run repeatedly.
487
+ */
488
+ private migrateFromCopilotDir;
489
+ private readRegistry;
490
+ private writeRegistry;
491
+ register(input: CopilotPluginRegisterInput): Promise<CopilotPluginRegistration>;
492
+ unregister(input: {
493
+ registrationId: string;
494
+ /** @deprecated Projection root comes from the constructor; ignored. */
495
+ copilotDir?: string;
496
+ scope?: "workspace" | "personal";
497
+ }): Promise<void>;
498
+ list(_input?: {
499
+ copilotDir?: string;
500
+ }): Promise<CopilotPluginRegistration[]>;
501
+ }
502
+
503
+ type CopilotScope = "workspace" | "personal";
504
+ type CopilotInstallIntent = "available" | "selected" | "moving" | "removing";
505
+ type CopilotMaterializationHealth = "healthy" | "missing" | "drifted" | "conflict" | "source-unavailable" | "unsupported";
506
+ type CopilotLocalGate = "ready" | "approval-required" | "configuration-required";
507
+ type CopilotUserStatus = "healthy" | "action-required" | "blocked" | "not-enabled";
508
+ interface CopilotArtifactState {
509
+ intent: CopilotInstallIntent;
510
+ health: CopilotMaterializationHealth;
511
+ gate: CopilotLocalGate;
512
+ }
513
+ interface CopilotPackageInstallation {
514
+ packageId: string;
515
+ scope: CopilotScope;
516
+ selectedArtifactIds: string[];
517
+ pinnedVersion?: string;
518
+ }
519
+ interface CopilotArtifactSummary {
520
+ id: string;
521
+ packageId: string;
522
+ kind: CopilotArtifactKind;
523
+ displayName: string;
524
+ description?: string;
525
+ installStrategy: "link" | "generated-config" | "approval-gated";
526
+ risk: "none" | "review-required";
527
+ }
528
+ declare function deriveCopilotUserStatus(states: CopilotArtifactState[]): CopilotUserStatus;
529
+
530
+ interface CopilotSourceSummary {
531
+ id: string;
532
+ type: "marketplace" | "git" | "local";
533
+ displayName: string;
534
+ updateCapability: "pinned" | "live" | "none";
535
+ }
536
+ interface CopilotPackageDefinition {
537
+ id: string;
538
+ sourceId: string;
539
+ displayName: string;
540
+ description?: string;
541
+ version?: string;
542
+ artifacts: CopilotArtifactSummary[];
543
+ /** Whole-package registrar installation (Copilot-managed, both scopes) —
544
+ * the home package list shows these; per-artifact v1 manifest plugins
545
+ * stay in the enabled-content section instead. */
546
+ wholePackage?: boolean;
547
+ }
548
+ interface CopilotArtifactView {
549
+ artifact: CopilotArtifactSummary;
550
+ state: CopilotArtifactState;
551
+ }
552
+ interface CopilotPackageView {
553
+ definition: CopilotPackageDefinition;
554
+ installation: CopilotPackageInstallation;
555
+ artifacts: CopilotArtifactView[];
556
+ selectedArtifactCount: number;
557
+ status: CopilotUserStatus;
558
+ }
559
+ interface CopilotSourceView extends CopilotSourceSummary {
560
+ packages: CopilotPackageView[];
561
+ }
562
+ interface CopilotCustomizationView {
563
+ scope: CopilotScope;
564
+ generatedAt: string;
565
+ sources: CopilotSourceView[];
566
+ packages: CopilotPackageView[];
567
+ attention: CopilotArtifactView[];
568
+ summary: {
569
+ packageCount: number;
570
+ enabledArtifactCount: number;
571
+ attentionCount: number;
572
+ };
573
+ legacyMigration?: {
574
+ count: number;
575
+ sourceLabel: "~/.agents";
576
+ };
577
+ }
578
+ interface BuildCustomizationViewInput {
579
+ scope: CopilotScope;
580
+ sources: CopilotSourceSummary[];
581
+ packages: CopilotPackageDefinition[];
582
+ installations: CopilotPackageInstallation[];
583
+ statesByArtifactId: Record<string, CopilotArtifactState>;
584
+ legacyCount?: number;
585
+ generatedAt?: string;
586
+ }
587
+ declare function buildCopilotCustomizationView(input: BuildCustomizationViewInput): CopilotCustomizationView;
588
+
589
+ /**
590
+ * Machine-local disabled marks for per-artifact skills/agents.
591
+ *
592
+ * Disable keeps the installation declaration (workspace manifest) or
593
+ * the user's install decision intact, but removes the materialized
594
+ * link so neither the Copilot engine nor the renderer can see the
595
+ * entry. The mark prevents the reconciler from resurrecting the link
596
+ * on the next restore. Entries are keyed by scope + identity; a
597
+ * workspace-scope mark only applies to that workspace.
598
+ */
599
+ interface DisabledContentEntry {
600
+ scope: "workspace" | "user";
601
+ repoId: string;
602
+ name: string;
603
+ kind: "skill" | "agent";
604
+ /** Required for workspace-scope marks — disables are per workspace. */
605
+ workspaceDir?: string;
606
+ }
607
+ interface DisabledContentState {
608
+ version: 1;
609
+ entries: DisabledContentEntry[];
610
+ }
611
+ /** Match predicate scoped to one lookup entry. */
612
+ type DisabledContentMatcher = (entry: DisabledContentEntry) => boolean;
613
+ declare class DisabledContentStore {
614
+ private readonly homeDir;
615
+ constructor(options?: {
616
+ homeDir?: string;
617
+ });
618
+ /** Absolute store path: SERVICEME_HOME/copilot/disabled-content.json. */
619
+ path(): Promise<string>;
620
+ list(): Promise<DisabledContentEntry[]>;
621
+ has(matcher: DisabledContentMatcher): Promise<boolean>;
622
+ add(entry: DisabledContentEntry): Promise<void>;
623
+ remove(entry: DisabledContentEntry): Promise<void>;
624
+ private write;
625
+ }
626
+
627
+ /** MCP server definition as authored in a plugin's mcp.json. */
628
+ interface McpServerDefinition {
629
+ /** Server name used in the generated local configuration. */
630
+ name: string;
631
+ /** Transport type: stdio command servers today. */
632
+ type: string;
633
+ /** Executable command (validated, never a shell string). */
634
+ command: string;
635
+ /** Arguments passed to the command. */
636
+ args?: string[];
637
+ /** Environment variable names the server may read. */
638
+ env?: Record<string, string>;
639
+ /** Tool allowlist declared by the source. */
640
+ tools?: string[];
641
+ }
642
+ /** One lifecycle event registration from hooks.json. */
643
+ interface HookEventDefinition {
644
+ /** Hook executor type; only "command" is supported today. */
645
+ type: string;
646
+ /** Relative bash entry referenced after materialization. */
647
+ bash: string;
648
+ /** Working directory hint relative to the workspace root. */
649
+ cwd?: string;
650
+ /** Environment variable names the hook may read. */
651
+ env?: Record<string, string>;
652
+ /** Timeout in seconds. */
653
+ timeoutSec?: number;
654
+ }
655
+ /** Hook definition as authored in a repo's hooks/<name>/hooks.json. */
656
+ interface HookDefinition {
657
+ /** Lifecycle event -> registrations. */
658
+ hooks: Partial<Record<string, HookEventDefinition[]>>;
659
+ }
660
+ /** Result of applying one generated-config entry on this machine. */
661
+ interface IntegrationApplyResult {
662
+ identity: string;
663
+ /** Path of the machine-local config the adapter manages. */
664
+ configPath: string;
665
+ /** Server or hook names written into the config. */
666
+ names: string[];
667
+ changed: boolean;
668
+ }
669
+ /** Machine-local MCP config adapter (generated-config strategy). */
670
+ interface McpConfigAdapter {
671
+ /** Merge one server definition into the machine-local config. */
672
+ applyServer(input: {
673
+ workspaceDir: string;
674
+ entry: PlannedContentEntry;
675
+ server: McpServerDefinition;
676
+ }): Promise<IntegrationApplyResult>;
677
+ /** Remove servers previously written for this entry. */
678
+ removeEntry(input: {
679
+ workspaceDir: string;
680
+ identity: string;
681
+ }): Promise<boolean>;
682
+ }
683
+ /** Machine-local hook registration adapter (approval-gated strategy). */
684
+ interface HookConfigAdapter {
685
+ /** Materialize hook scripts and register lifecycle events. */
686
+ applyHook(input: {
687
+ workspaceDir: string;
688
+ entry: PlannedContentEntry;
689
+ hook: HookDefinition;
690
+ }): Promise<IntegrationApplyResult>;
691
+ /** Remove registrations previously written for this entry. */
692
+ removeEntry(input: {
693
+ workspaceDir: string;
694
+ identity: string;
695
+ }): Promise<boolean>;
696
+ }
697
+ /** Parse and validate a plugin mcp.json payload. */
698
+ declare function parseMcpJson(raw: string): McpServerDefinition[];
699
+ /** Parse and validate a hooks.json payload. */
700
+ declare function parseHooksJson(raw: string): HookDefinition;
701
+ /** Locate the mcp.json beside a plugin manifest. */
702
+ declare function findPluginMcpJson(repoRoot: string, pluginId: string): Promise<string | null>;
703
+ /** Locate hooks/<name>/hooks.json in a repository. */
704
+ declare function findRepoHooksJson(repoRoot: string, name: string): Promise<string | null>;
705
+
706
+ /** Adapter merging MCP servers into the workspace-local VS Code config. */
707
+ declare class FileMcpConfigAdapter implements McpConfigAdapter {
708
+ /** Merge one server definition under its entry identity. */
709
+ applyServer(input: {
710
+ workspaceDir: string;
711
+ entry: PlannedContentEntry;
712
+ server: McpServerDefinition;
713
+ }): Promise<IntegrationApplyResult>;
714
+ /** Remove only servers owned by the given identity. */
715
+ removeEntry(input: {
716
+ workspaceDir: string;
717
+ identity: string;
718
+ }): Promise<boolean>;
719
+ }
720
+ /** Adapter materializing hook scripts and event registrations. */
721
+ declare class FileHookConfigAdapter implements HookConfigAdapter {
722
+ /** Copy hook scripts and merge registrations under the entry identity. */
723
+ applyHook(input: {
724
+ workspaceDir: string;
725
+ entry: PlannedContentEntry;
726
+ hook: HookDefinition;
727
+ }): Promise<IntegrationApplyResult>;
728
+ /** Remove registrations owned by the identity and orphaned script copies. */
729
+ removeEntry(input: {
730
+ workspaceDir: string;
731
+ identity: string;
732
+ }): Promise<boolean>;
733
+ }
734
+
735
+ /** Machine-local materialization state for personal-scope content. */
736
+ interface PersonalContentState {
737
+ version: 1;
738
+ entries: WorkspaceMaterializedEntry[];
739
+ }
740
+ /** Reconcile result: artifact health keyed by artifact id. */
741
+ interface PersonalReconcileResult {
742
+ statesByArtifactId: Record<string, CopilotArtifactState>;
743
+ }
744
+ /** Resolves the artifact entries a package contributes. */
745
+ type PersonalPackageResolver = (packageId: string) => Promise<ResolvedPluginEntry[]>;
746
+ interface PersonalReconcilerOptions {
747
+ /** SERVICEME home directory holding intent and machine state. */
748
+ homeDir?: string;
749
+ /** Host-verified capabilities; tests inject per-kind presence. */
750
+ capabilities: CopilotHostCapabilities;
751
+ /** Resolves package definitions; defaults to no packages. */
752
+ resolvePackage?: PersonalPackageResolver;
753
+ }
754
+ /** Manage all six personal artifact kinds against host capabilities. */
755
+ declare class PersonalCopilotContentReconciler {
756
+ private readonly store;
757
+ private readonly capabilities;
758
+ private readonly resolvePackage;
759
+ private readonly statePath;
760
+ constructor(options: PersonalReconcilerOptions);
761
+ /** Read current machine state; empty state when not materialized yet. */
762
+ readState(): Promise<PersonalContentState>;
763
+ /** Inspect current personal state without materializing anything. */
764
+ inspect(): Promise<PersonalReconcileResult>;
765
+ /** Materialize personal intent for all supported kinds on this machine. */
766
+ reconcile(): Promise<PersonalReconcileResult>;
767
+ /** Record local approval for integration content, then re-reconcile. */
768
+ approve(input: {
769
+ artifactIds: string[];
770
+ }): Promise<PersonalReconcileResult>;
771
+ /** Write machine state atomically. */
772
+ private writeState;
773
+ private buildPlan;
774
+ private removeOwnedMaterialization;
775
+ private projectStates;
776
+ }
777
+
778
+ /** Persisted personal-scope installation intent. */
779
+ interface PersonalInstallationState {
780
+ version: 1;
781
+ installations: CopilotPackageInstallation[];
782
+ }
783
+ /** Atomically persist personal package installation intent under the SERVICEME home. */
784
+ declare class PersonalInstallationStore {
785
+ private readonly homeDir;
786
+ private cachedPath;
787
+ constructor(options?: {
788
+ homeDir?: string;
789
+ });
790
+ /** Absolute intent-file path: SERVICEME_HOME/copilot/personal-installations.json. */
791
+ path(): Promise<string>;
792
+ /** Read intent; empty intent when the file does not exist yet. */
793
+ read(): Promise<PersonalInstallationState>;
794
+ /** Atomically persist intent. */
795
+ write(state: PersonalInstallationState): Promise<void>;
796
+ }
797
+
798
+ /** Statuses surfaced to UI and CLI for each declared entry. */
799
+ type WorkspaceContentStatus = "restored" | "adopted" | "pending_approval" | "missing_source" | "conflict" | "drifted";
800
+ interface WorkspaceContentEntryResult {
801
+ identity: string;
802
+ status: WorkspaceContentStatus;
803
+ message?: string;
804
+ }
805
+ interface WorkspaceContentReconcileResult {
806
+ changed: boolean;
807
+ entries: WorkspaceContentEntryResult[];
808
+ }
809
+ interface RepositorySource {
810
+ ready: boolean;
811
+ localPath?: string;
812
+ error?: string;
813
+ }
814
+ /** Orchestrates declaration → pinned source → plan → safe links. */
815
+ declare class WorkspaceCopilotContentReconciler {
816
+ private readonly workspaceDir;
817
+ private readonly homeDir;
818
+ private readonly ensureRepository;
819
+ constructor(options: {
820
+ workspaceDir: string;
821
+ homeDir?: string;
822
+ /** Injectable repository ensure step (tests avoid real git). */
823
+ ensureRepository?: (manifest: WorkspaceCopilotManifest) => Promise<Map<string, RepositorySource>>;
824
+ /** Injectable link materializer (transactions share the test seam). */
825
+ materializer?: CopilotLinkMaterializer;
826
+ /** Machine-local disable marks: identities returning true are
827
+ * treated as NOT declared — their materialization is removed and
828
+ * never resurrected, while the manifest declaration itself stays. */
829
+ isDisabled?: (identity: string) => Promise<boolean>;
830
+ });
831
+ private readonly materializer;
832
+ private readonly isDisabled;
833
+ /** Restore declared content on this machine. */
834
+ reconcile(): Promise<WorkspaceContentReconcileResult>;
835
+ /**
836
+ * Reconcile mcp/hook entries through their generated-config adapters.
837
+ * Unapproved or digest-changed entries stay pending without touching
838
+ * host configuration; approved entries are (re)applied; previously
839
+ * materialized identities that left the declaration are removed.
840
+ */
841
+ private reconcileIntegrations;
842
+ /** Build the machine-local state entry for a generated-config integration. */
843
+ private toIntegrationStateEntry;
844
+ /** Record local approval for risky content, then re-reconcile. */
845
+ approve(input: {
846
+ identities: string[];
847
+ }): Promise<WorkspaceContentReconcileResult>;
848
+ private defaultEnsureRepository;
849
+ }
850
+
851
+ /** One legacy ~/.agents link considered for migration. */
852
+ interface LegacyMigrationEntry {
853
+ artifactId: string;
854
+ name: string;
855
+ kind: "skill" | "agent";
856
+ eligible: boolean;
857
+ sourcePath: string;
858
+ targetPath: string;
859
+ }
860
+ /** Read-only preview of legacy links; migration happens only on confirmation. */
861
+ interface LegacyMigrationPreview {
862
+ sourceLabel: "~/.agents";
863
+ entries: LegacyMigrationEntry[];
864
+ }
865
+ interface CopilotPackageInstallInput {
866
+ workspaceDir?: string;
867
+ scope: CopilotScope;
868
+ sourceId: string;
869
+ packageId: string;
870
+ artifactIds: string[];
871
+ pinnedVersion?: string;
872
+ localMode?: "live" | "private-workspace-override";
873
+ }
874
+ interface CopilotPackageUpdateInput {
875
+ workspaceDir?: string;
876
+ scope: CopilotScope;
877
+ packageId: string;
878
+ artifactIds: string[];
879
+ pinnedVersion?: string;
880
+ }
881
+ interface CopilotPackageUninstallInput {
882
+ workspaceDir?: string;
883
+ scope: CopilotScope;
884
+ packageId: string;
885
+ }
886
+ interface CopilotPackageMoveInput {
887
+ workspaceDir?: string;
888
+ packageId: string;
889
+ from: CopilotScope;
890
+ to: CopilotScope;
891
+ }
892
+ interface PackageInstallationServiceDeps {
893
+ personalStore: PersonalInstallationStore;
894
+ personalReconciler: PersonalCopilotContentReconciler;
895
+ /** Shared materializer so transaction tests can inject failures. */
896
+ materializer?: CopilotLinkMaterializer;
897
+ userHomeDir: string;
898
+ resolvePackage: (packageId: string) => Promise<ResolvedPluginEntry[]>;
899
+ resolveWorkspaceSource: (sourceId: string) => Promise<WorkspaceManifestRepository | undefined>;
900
+ createWorkspaceReconciler: (workspaceDir: string) => WorkspaceCopilotContentReconciler;
901
+ /** Resolve the local reconciliation state path for transaction rollback. */
902
+ getWorkspaceStatePath?: (workspaceDir: string) => Promise<string>;
903
+ readWorkspaceView: (workspaceDir: string) => Promise<CopilotCustomizationView>;
904
+ /** Exact selected workspace artifact identities for the active workspace. */
905
+ readWorkspaceInstallations: (workspaceDir: string) => Promise<CopilotPackageInstallation[]>;
906
+ }
907
+ /**
908
+ * Package lifecycle transactions over the Task 8 personal store /
909
+ * reconciler and the shared workspace manifest.
910
+ *
911
+ * Every mutation follows prepare → activate → commit: destination
912
+ * intent is validated and materialized first; source intent is
913
+ * removed only after every destination artifact succeeded. On
914
+ * activation failure the previous destination intent is restored and
915
+ * the source intent is left untouched.
916
+ */
917
+ declare class PackageInstallationService {
918
+ private readonly deps;
919
+ /** Last preview shown to the caller; migration re-verifies against it. */
920
+ private lastPreview;
921
+ constructor(deps: PackageInstallationServiceDeps);
922
+ install(input: CopilotPackageInstallInput): Promise<CopilotCustomizationView>;
923
+ update(input: CopilotPackageUpdateInput): Promise<CopilotCustomizationView>;
924
+ uninstall(input: CopilotPackageUninstallInput): Promise<CopilotCustomizationView>;
925
+ move(input: CopilotPackageMoveInput): Promise<CopilotCustomizationView>;
926
+ private moveIntoWorkspace;
927
+ private moveIntoPersonal;
928
+ previewLegacy(): Promise<LegacyMigrationPreview>;
929
+ migrateLegacy(input: {
930
+ artifactIds: string[];
931
+ }): Promise<CopilotCustomizationView>;
932
+ private readSourceSelection;
933
+ private assertArtifactsNotActiveElsewhere;
934
+ private assertArtifactIdsAbsentFromWorkspace;
935
+ private assertArtifactIdsAbsentFromInstallations;
936
+ private assertKindNameFree;
937
+ private writePersonalIntent;
938
+ private removePersonalIntent;
939
+ private upsertWorkspaceSelection;
940
+ private withWorkspaceActivationRollback;
941
+ private captureWorkspaceActivation;
942
+ private captureFile;
943
+ private restoreWorkspaceActivation;
944
+ private selectedEntries;
945
+ private selectEntries;
946
+ private assertNoActivationConflicts;
947
+ private assertNoActivationConflictsPersonal;
948
+ private resolveLegacyTarget;
949
+ private requireWorkspaceDir;
950
+ private readPersonalView;
951
+ }
952
+
953
+ /** A git source to enumerate. `id` is the managed repos dir entry name. */
954
+ interface PluginCatalogRepoInput {
955
+ id: string;
956
+ enabled?: boolean;
957
+ }
958
+ /**
959
+ * An installable plugin.json package found in a source — with the
960
+ * same artifact summaries an installed package would expose, so the
961
+ * install preview can select artifacts without a second resolution
962
+ * path.
963
+ */
964
+ interface PluginCatalogPackage {
965
+ packageId: string;
966
+ sourceId: string;
967
+ displayName: string;
968
+ description?: string;
969
+ version?: string;
970
+ artifacts: CopilotArtifactSummary[];
971
+ }
972
+ /**
973
+ * Enumerate plugin.json packages across the given git sources.
974
+ *
975
+ * Sources resolve under `reposDir/<id>` — the same managed checkout
976
+ * layout the workspace manifest restore uses — and each source's
977
+ * plugins are resolved through the shared workspace plan pipeline.
978
+ * Per-package failures (corrupt manifest, unreadable files) are
979
+ * skipped, not thrown — the catalog must stay usable when a single
980
+ * plugin is broken.
981
+ */
982
+ declare function listPluginCatalog(input: {
983
+ reposDir: string;
984
+ repos: PluginCatalogRepoInput[];
985
+ }): Promise<PluginCatalogPackage[]>;
986
+ interface PluginCatalogService {
987
+ list(input: {
988
+ reposDir: string;
989
+ repos: PluginCatalogRepoInput[];
990
+ }): Promise<PluginCatalogPackage[]>;
991
+ }
992
+ /** Factory: one cache per service instance (tests use fresh instances). */
993
+ declare function createPluginCatalogService(): PluginCatalogService;
994
+ /**
995
+ * Single source of truth for entry → artifact-summary mapping. The
996
+ * CLI bridge imports this for installed packages too, so the install
997
+ * preview's installStrategy/risk can never drift from what the
998
+ * catalog shows.
999
+ */
1000
+ declare function toArtifactSummary(entry: ResolvedPluginEntry): CopilotArtifactSummary;
1001
+
1002
+ /**
1003
+ * Verbatim wire contract for a read-only package update preview.
1004
+ * Field names are pinned by Task 10's brief and shared with the
1005
+ * protocol / webview layers.
1006
+ */
1007
+ interface CopilotPackageUpdatePreview {
1008
+ packageId: string;
1009
+ fromVersion?: string;
1010
+ toVersion: string;
1011
+ addedArtifactIds: string[];
1012
+ removedArtifactIds: string[];
1013
+ changedArtifactIds: string[];
1014
+ approvalInvalidatedArtifactIds: string[];
1015
+ }
1016
+ /** Normalized source record for diagnostics and the source manager UI. */
1017
+ interface CopilotSourceRecord {
1018
+ id: string;
1019
+ type: "marketplace" | "git" | "local";
1020
+ displayName: string;
1021
+ updateCapability: "pinned" | "live" | "none";
1022
+ /** Whether the source content is currently materialized on disk. */
1023
+ available: boolean;
1024
+ /** Where this source is declared: "workspace" (manifest), "personal" (intent), or both. */
1025
+ declaredIn: Array<"workspace" | "personal">;
1026
+ }
1027
+ interface CopilotSourceCatalogDeps {
1028
+ /** SERVICEME home; defaults to the real ~/.serviceme. */
1029
+ homeDir?: string;
1030
+ /** Personal installation intent; consulted by previewUpdate and removeSource. */
1031
+ personalStore: PersonalInstallationStore;
1032
+ /**
1033
+ * Task 9's transaction service owns installations. removeSource
1034
+ * coordinates with it only indirectly: it refuses while any
1035
+ * installation (workspace or personal) still uses the source.
1036
+ */
1037
+ installationService?: PackageInstallationService;
1038
+ /**
1039
+ * Resolves artifacts for a package at a revision; defaults to a
1040
+ * no-content resolver so an unresolvable source yields empty diff
1041
+ * lists rather than a crash.
1042
+ */
1043
+ resolvePackage?: (packageId: string, revision?: string) => Promise<ResolvedPluginEntry[]>;
1044
+ /**
1045
+ * Round 3: workspace declarations enable artifact kinds, not named
1046
+ * artifacts. This predicate reports whether a resolved entry matches a
1047
+ * selection marker produced for an enabled kind. Implementations may
1048
+ * match exact ids or kind prefixes; default behavior matches only
1049
+ * exact ids (personal-intent semantics).
1050
+ */
1051
+ artifactSelected?: (marker: string, artifactId: string) => boolean;
1052
+ /**
1053
+ * Finding 4 honesty: returns the revision actually resolved by
1054
+ * resolvePackage for a given requested revision. When a resolver can
1055
+ * only read the working tree, this lets previewUpdate label toVersion
1056
+ * with what was truly diffed instead of the requested target.
1057
+ */
1058
+ resolveActualRevision?: (packageId: string, revision: string) => Promise<string | undefined>;
1059
+ /** Source ids declared by the workspace manifest for a directory. */
1060
+ listWorkspaceSources: (workspaceDir: string) => Promise<string[]>;
1061
+ /**
1062
+ * Workspace-scope installations for a directory, read through Task 9's
1063
+ * view projection. Both previewUpdate and removeSource honor personal
1064
+ * AND workspace installations; without this a workspace-declared source
1065
+ * with no personal intent could be deleted while still in use.
1066
+ */
1067
+ readWorkspaceInstallations?: (workspaceDir: string) => Promise<CopilotPackageInstallation[]>;
1068
+ /** Classifies a source id as a marketplace catalog source. */
1069
+ isCatalogSource?: (sourceId: string, workspaceDir?: string) => boolean | Promise<boolean>;
1070
+ /**
1071
+ * Task 10 ruling #1: materialize a v2 catalog source under
1072
+ * repos/<sourceId> so availability is a plain directory check.
1073
+ * listSources invokes this for unavailable catalog sources before
1074
+ * reporting diagnostics.
1075
+ */
1076
+ ensureCatalogSource?: (sourceId: string) => Promise<{
1077
+ localPath: string;
1078
+ }>;
1079
+ /**
1080
+ * Round 2 / Minor 2: reports whether a staged catalog directory
1081
+ * actually contains payload. Staging only creates the directory; a
1082
+ * payload check must gate availability so an empty staged dir is
1083
+ * never reported as available.
1084
+ */
1085
+ hasCatalogPayload?: (localPath: string) => Promise<boolean>;
1086
+ /** Classifies a source id as a personal local source. */
1087
+ isLocalSource?: (sourceId: string) => boolean | Promise<boolean>;
1088
+ /**
1089
+ * ReposStore (repos.json) entries on this machine — built-in default
1090
+ * repos plus user-added git repos. The source manager is the single
1091
+ * repository management surface, so every store entry must appear in
1092
+ * the listing even when it is neither workspace-declared nor
1093
+ * personally installed. Entries with an empty declaredIn are
1094
+ * store-only. Also supplies human display names for store sources.
1095
+ */
1096
+ listStoreSources?: () => Promise<Array<{
1097
+ id: string;
1098
+ name?: string;
1099
+ enabled?: boolean;
1100
+ }>>;
1101
+ }
1102
+ interface CopilotSourceCatalogQuery {
1103
+ workspaceDir?: string;
1104
+ scope?: CopilotScope;
1105
+ }
1106
+ interface CopilotUpdatePreviewInput {
1107
+ workspaceDir?: string;
1108
+ scope?: CopilotScope;
1109
+ packageId: string;
1110
+ /** Target revision (full 40-char commit for git sources, immutable catalog revision otherwise). */
1111
+ revision: string;
1112
+ }
1113
+ /**
1114
+ * Normalized Marketplace / Git / local source discovery plus
1115
+ * deterministic, side-effect-free update previews.
1116
+ *
1117
+ * Marketplace sources are identified by an immutable catalog revision
1118
+ * plus digest (see WorkspaceManifestCatalogSource); Git sources by a
1119
+ * validated remote identity plus full commit; personal local sources
1120
+ * may run "live" while workspace local sources require a Git import
1121
+ * or the "private-workspace-override" mode enforced downstream by the
1122
+ * install transaction.
1123
+ */
1124
+ declare class CopilotSourceCatalogService {
1125
+ private readonly deps;
1126
+ private readonly reposDir;
1127
+ constructor(deps: CopilotSourceCatalogDeps);
1128
+ /**
1129
+ * List normalized sources for the query: every source declared by
1130
+ * the workspace manifest (when a workspaceDir is given) plus every
1131
+ * source referenced by personal installation intent, plus every
1132
+ * ReposStore entry on this machine (built-in default repos and
1133
+ * user-added git repos) so the source manager can manage them.
1134
+ */
1135
+ listSources(query: CopilotSourceCatalogQuery): Promise<CopilotSourceRecord[]>;
1136
+ /**
1137
+ * Confirms Task 4's materialization assumption for every source
1138
+ * kind: v2 catalog sources materialize under reposDir/<source-id>
1139
+ * exactly like git checkouts, so availability is a directory check.
1140
+ */
1141
+ isSourceAvailable(sourceId: string): Promise<boolean>;
1142
+ /**
1143
+ * Deterministic, side-effect-free update preview: compares the
1144
+ * currently-selected artifacts against what the target revision
1145
+ * resolves to, and reports which approval-gated artifacts would
1146
+ * need re-approval. Never writes intent; the pinned version stays
1147
+ * untouched until the caller runs the update transaction.
1148
+ */
1149
+ previewUpdate(input: CopilotUpdatePreviewInput): Promise<CopilotPackageUpdatePreview>;
1150
+ /**
1151
+ * Remove a source only when nothing references it: no workspace
1152
+ * declaration and no installation (workspace or personal) may still
1153
+ * use it. Refusals match /installed package/i and /workspace/ so
1154
+ * callers can surface distinct remediation paths.
1155
+ */
1156
+ removeSource(sourceId: string, workspaceDir?: string): Promise<void>;
1157
+ }
1158
+
1159
+ /**
1160
+ * Read the workspace manifest’s declared package selections without resolving
1161
+ * sources. Source resolution can fail (unavailable source, conflict), and
1162
+ * rendered snapshots then fall back to legacy kind maps that erase exact
1163
+ * artifactIds. Reverse-scope conflict checks must still see what the
1164
+ * manifest declares, so they read declarations directly. Corrupted
1165
+ * manifests surface the load error rather than pretending nothing is
1166
+ * declared.
1167
+ */
1168
+ declare function readDeclaredWorkspaceInstallations(workspaceDir: string): Promise<CopilotPackageInstallation[]>;
1169
+
1170
+ /** Manage the bounded SERVICEME block inside a git worktree's info/exclude. */
1171
+ declare class WorkspaceExcludeStore {
1172
+ private readonly workspaceDir;
1173
+ private readonly resolveGitExcludePath;
1174
+ constructor(options: {
1175
+ workspaceDir: string;
1176
+ /** Override exclude-path resolution (tests, linked-worktree handling). */
1177
+ resolveGitExcludePath?: (workspaceDir: string) => Promise<string>;
1178
+ });
1179
+ /** Resolve the worktree-aware exclude file managed by this store. */
1180
+ path(): Promise<string>;
1181
+ /** Replace the managed block so it contains exactly the given paths. */
1182
+ reconcile(paths: string[]): Promise<void>;
1183
+ }
1184
+
1185
+ /** Location of the shared declaration inside a workspace. */
1186
+ declare const WORKSPACE_MANIFEST_RELPATH: string;
1187
+ /** Absolute path of the declaration file inside a workspace. */
1188
+ declare function getWorkspaceManifestPath(workspaceDir: string): string;
1189
+ /** Read and validate the declaration; undefined when absent. */
1190
+ declare function loadWorkspaceCopilotManifest(workspaceDir: string): Promise<WorkspaceCopilotManifest | undefined>;
1191
+ /** Validate and atomically write the shared declaration. */
1192
+ declare function writeWorkspaceCopilotManifest(workspaceDir: string, manifest: WorkspaceCopilotManifest): Promise<void>;
1193
+ /**
1194
+ * Atomically replace one package selection with exact resolver artifact IDs.
1195
+ * New selections clear legacy kind maps so future resolution remains stable
1196
+ * if a package adds another artifact of an existing kind.
1197
+ */
1198
+ declare function replaceWorkspaceContentSelection(input: {
1199
+ workspaceDir: string;
1200
+ repository: WorkspaceManifestRepository;
1201
+ pluginId: string;
1202
+ artifactIds: string[];
1203
+ }): Promise<WorkspaceCopilotManifest>;
1204
+ /**
1205
+ * Add or update one artifact-kind selection (any of the six kinds) in the
1206
+ * shared declaration, creating the file when absent. Returns the new manifest.
1207
+ *
1208
+ * The repository entry must already exist (or be provided via
1209
+ * `repository`) with a full pinned commit; this helper only manages
1210
+ * the plugin selection so install flows never race a concurrent write
1211
+ * of unrelated selections.
1212
+ */
1213
+ declare function upsertWorkspaceContentSelection(input: {
1214
+ workspaceDir: string;
1215
+ repository: WorkspaceManifestRepository;
1216
+ pluginId: string;
1217
+ kind: CopilotArtifactKind;
1218
+ }): Promise<WorkspaceCopilotManifest>;
1219
+ /**
1220
+ * Remove one artifact kind from a plugin selection, dropping
1221
+ * the plugin entirely when no artifact kind remains enabled. Returns
1222
+ * the new manifest; a no-op when the selection does not exist.
1223
+ */
1224
+ declare function removeWorkspaceContentSelection(input: {
1225
+ workspaceDir: string;
1226
+ repositoryId: string;
1227
+ pluginId: string;
1228
+ kind: CopilotArtifactKind;
1229
+ }): Promise<WorkspaceCopilotManifest>;
1230
+
1231
+ /** Hash a canonical workspace path into a stable directory segment. */
1232
+ declare function hashWorkspaceDir(workspaceDir: string): Promise<string>;
1233
+ /** Directory holding machine-local state for one workspace. */
1234
+ declare function getWorkspaceStateDir(workspaceDir: string, homeDir?: string): Promise<string>;
1235
+ /** Store for machine-local Copilot content state; one file per workspace. */
1236
+ declare class WorkspaceContentStateStore {
1237
+ private readonly workspaceDir;
1238
+ private readonly homeDir;
1239
+ private cachedPath;
1240
+ constructor(options: {
1241
+ workspaceDir: string;
1242
+ homeDir?: string;
1243
+ });
1244
+ /** Absolute state-file path for this workspace. */
1245
+ path(): Promise<string>;
1246
+ /** Read state; an empty state when the file does not exist yet. */
1247
+ read(): Promise<WorkspaceContentState>;
1248
+ /** Atomically persist state. */
1249
+ write(state: WorkspaceContentState): Promise<void>;
1250
+ }
1251
+
128
1252
  /**
129
1253
  * Skill & Agent v2 — Drafts (M4)
130
1254
  *
@@ -341,6 +1465,8 @@ declare const DRAFTS_SUBDIR = "drafts";
341
1465
  declare const SKILL_DRAFTS_SUBDIR = "skills";
342
1466
  declare const AGENT_DRAFTS_SUBDIR = "agents";
343
1467
  declare const REPOS_CONFIG_FILENAME = "repos.json";
1468
+ declare const WORKSPACES_SUBDIR = "workspaces";
1469
+ declare const WORKSPACE_CONTENT_STATE_FILENAME = "copilot-content-state.json";
344
1470
  /** rev.20 — r7 BYOM Server Proxy toggle self-state (read by ext + CLI + server). */
345
1471
  declare const SERVER_PROXY_GLOBAL_FILENAME = "server-proxy.json";
346
1472
  /**
@@ -398,6 +1524,8 @@ declare function getAgentDraftsDir(): string;
398
1524
  * `SERVICEME_HOME` overrides too).
399
1525
  */
400
1526
  declare function getReposConfigPath(): string;
1527
+ /** `~/.serviceme/workspaces` — machine-local per-workspace state root. */
1528
+ declare function getWorkspacesDir(): string;
401
1529
  /**
402
1530
  * Convenience helper for callers that need to switch behaviour on platform
403
1531
  * (e.g. `SkillLinker` chooses symlink vs junction). Exported mostly so tests
@@ -682,8 +1810,8 @@ declare const defaultRepoSchema: z.ZodObject<{
682
1810
  lastSyncAt: z.ZodOptional<z.ZodString>;
683
1811
  lastSyncCommitSha: z.ZodOptional<z.ZodString>;
684
1812
  lastSyncStatus: z.ZodOptional<z.ZodEnum<{
685
- ok: "ok";
686
1813
  error: "error";
1814
+ ok: "ok";
687
1815
  }>>;
688
1816
  lastSyncError: z.ZodOptional<z.ZodString>;
689
1817
  }, z.core.$strip>;
@@ -700,8 +1828,8 @@ declare const userRepoSchema: z.ZodObject<{
700
1828
  lastSyncAt: z.ZodOptional<z.ZodString>;
701
1829
  lastSyncCommitSha: z.ZodOptional<z.ZodString>;
702
1830
  lastSyncStatus: z.ZodOptional<z.ZodEnum<{
703
- ok: "ok";
704
1831
  error: "error";
1832
+ ok: "ok";
705
1833
  }>>;
706
1834
  lastSyncError: z.ZodOptional<z.ZodString>;
707
1835
  }, z.core.$strip>;
@@ -719,8 +1847,8 @@ declare const repoSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
719
1847
  lastSyncAt: z.ZodOptional<z.ZodString>;
720
1848
  lastSyncCommitSha: z.ZodOptional<z.ZodString>;
721
1849
  lastSyncStatus: z.ZodOptional<z.ZodEnum<{
722
- ok: "ok";
723
1850
  error: "error";
1851
+ ok: "ok";
724
1852
  }>>;
725
1853
  lastSyncError: z.ZodOptional<z.ZodString>;
726
1854
  }, z.core.$strip>, z.ZodObject<{
@@ -736,8 +1864,8 @@ declare const repoSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
736
1864
  lastSyncAt: z.ZodOptional<z.ZodString>;
737
1865
  lastSyncCommitSha: z.ZodOptional<z.ZodString>;
738
1866
  lastSyncStatus: z.ZodOptional<z.ZodEnum<{
739
- ok: "ok";
740
1867
  error: "error";
1868
+ ok: "ok";
741
1869
  }>>;
742
1870
  lastSyncError: z.ZodOptional<z.ZodString>;
743
1871
  }, z.core.$strip>], "source">;
@@ -758,8 +1886,8 @@ declare const reposFileSchema: z.ZodObject<{
758
1886
  lastSyncAt: z.ZodOptional<z.ZodString>;
759
1887
  lastSyncCommitSha: z.ZodOptional<z.ZodString>;
760
1888
  lastSyncStatus: z.ZodOptional<z.ZodEnum<{
761
- ok: "ok";
762
1889
  error: "error";
1890
+ ok: "ok";
763
1891
  }>>;
764
1892
  lastSyncError: z.ZodOptional<z.ZodString>;
765
1893
  }, z.core.$strip>, z.ZodObject<{
@@ -775,8 +1903,8 @@ declare const reposFileSchema: z.ZodObject<{
775
1903
  lastSyncAt: z.ZodOptional<z.ZodString>;
776
1904
  lastSyncCommitSha: z.ZodOptional<z.ZodString>;
777
1905
  lastSyncStatus: z.ZodOptional<z.ZodEnum<{
778
- ok: "ok";
779
1906
  error: "error";
1907
+ ok: "ok";
780
1908
  }>>;
781
1909
  lastSyncError: z.ZodOptional<z.ZodString>;
782
1910
  }, z.core.$strip>], "source">>;
@@ -1130,10 +2258,63 @@ declare class RepoManager {
1130
2258
  pullOne(repoId: string): Promise<PullResult>;
1131
2259
  /** Pull every enabled repo. Per-repo failures don't abort the run. */
1132
2260
  pullAll(): Promise<SyncReport>;
2261
+ /**
2262
+ * Ensure a repository exists locally and is detached at an exact
2263
+ * commit. Used by Copilot content restoration: never pulls to a
2264
+ * branch head, so a declaration always resolves to the reviewed
2265
+ * content on every machine.
2266
+ */
2267
+ ensureAtCommit(input: {
2268
+ repository: Pick<RepoConfig, "id" | "url" | "useProxy">;
2269
+ commit: string;
2270
+ }): Promise<{
2271
+ localPath: string;
2272
+ commit: string;
2273
+ }>;
2274
+ /**
2275
+ * Ensure a v2 catalog source is materialized under repos/<sourceId>
2276
+ * exactly like a git checkout (Task 10, ruling #1).
2277
+ *
2278
+ * The catalog store (repos.json) never held catalog sources, so the
2279
+ * source-lifecycle task owns this path: content arrives from the
2280
+ * provider as an extracted tree, is unpacked under the managed
2281
+ * source directory, and is verified against the immutable digest
2282
+ * before the directory becomes visible to resolvers.
2283
+ *
2284
+ * Callers that only need the directory contract (source availability
2285
+ * is a reposDir/<source-id> directory check) can pass a provider
2286
+ * that stages the tree; the method itself never writes store
2287
+ * entries — marketplace sources stay manifest-only.
2288
+ */
2289
+ ensureCatalogSource(input: {
2290
+ sourceId: string;
2291
+ provider: {
2292
+ /** Stage the catalog payload into the target directory. */
2293
+ materialize: (targetDir: string) => Promise<void>;
2294
+ };
2295
+ }): Promise<{
2296
+ localPath: string;
2297
+ }>;
2298
+ /**
2299
+ * Resolve a unique store id for a repo being added.
2300
+ *
2301
+ * The base id derives from the URL (`owner-repo`). When it is taken
2302
+ * by the SAME url with a DIFFERENT branch — user repo or platform
2303
+ * default alike — derive `base-<branch>` so users can track several
2304
+ * branches of one repository side by side. Genuine duplicates (same
2305
+ * url + same branch) and cross-url id collisions still throw
2306
+ * RepoCloneConflictError.
2307
+ */
2308
+ private resolveUserRepoId;
1133
2309
  /**
1134
2310
  * Validate URL, derive an id, detect the branch via `git ls-remote`,
1135
2311
  * then add the entry to the store and trigger a clone.
1136
2312
  *
2313
+ * The base id derives from the URL. Re-adding the same URL with a
2314
+ * different branch is allowed — it gets a branch-suffixed id
2315
+ * (`owner-repo-<branch>`) so multiple branches of one repository can
2316
+ * be tracked side by side.
2317
+ *
1137
2318
  * Spec §5.3 says "branch detection" happens BEFORE the store write so
1138
2319
  * the resulting `repos.json` is fully populated. The clone is async
1139
2320
  * but the function returns synchronously once the store is updated
@@ -1608,8 +2789,34 @@ declare class SkillStore {
1608
2789
  private migrateLegacyUserSkillMarker;
1609
2790
  writeSkillFiles(skillId: string, scope: "workspace" | "user", files: SkillDownloadFile[]): Promise<void>;
1610
2791
  }
2792
+ /** One legacy skill directory reported by {@link migrateLegacyUserSkillContent}. */
2793
+ interface LegacyUserSkillEntry {
2794
+ /** Legacy skill id (directory name under ~/.agents/skills). */
2795
+ id: string;
2796
+ /** Absolute path of the legacy skill directory. */
2797
+ legacyPath: string;
2798
+ /** Target directory under ~/.copilot/skills the migration would create. */
2799
+ targetPath: string;
2800
+ /** Always `migration_available` until the user runs the migration. */
2801
+ status: "migration_available";
2802
+ }
2803
+ interface LegacyUserSkillMigrationResult {
2804
+ entries: LegacyUserSkillEntry[];
2805
+ }
2806
+ /**
2807
+ * Detect ~/.agents/skills content that can migrate to ~/.copilot/skills.
2808
+ *
2809
+ * Read-only: legacy directories stay in place until the user explicitly
2810
+ * invokes the migration, so detection never breaks tools that still
2811
+ * read the old layout.
2812
+ */
2813
+ declare function migrateLegacyUserSkillContent(input: {
2814
+ homeDir: string;
2815
+ workspaceDir: string;
2816
+ fileSystem?: SkillStoreFileSystem;
2817
+ }): Promise<LegacyUserSkillMigrationResult>;
1611
2818
 
1612
2819
  declare const unzipFile: (zipPath: string, dest: string) => Promise<void>;
1613
2820
  declare const moveFiles: (sourceDir: string, destDir: string, overwrite?: boolean) => Promise<void>;
1614
2821
 
1615
- export { AGENT_DRAFTS_SUBDIR, type AddUserRepoInput, type AddUserRepoResult, type AgentCatalog, AgentCatalogClient, type AgentCatalogClientOptions, type AgentDownloadFile, type AgentInstallScope, type AgentMutateResult, AgentReconciler, type AgentReconcilerDependencies, AgentStore, type AgentStoreFileSystem, type AgentStoreOptions, type AgentsStateFile, type AnyRepoConfig, type AppendLogInput, type BootstrapPhase5Result, CACHE_SUBDIR, CREDENTIALS_CONFIG_FILENAME, CannotRemoveDefaultRepoError, type CreateTaskInput, FIXED_ADDED_AT as DEFAULT_REPO_FIXED_ADDED_AT, DEFAULT_REPO_ID, DEVICE_JSON_FILENAME, DRAFTS_SUBDIR, DaemonLogger, type DefaultRepoConfig, type DraftDetail, DraftNotFoundError, type DraftSummary, DraftsError, DraftsStore, type EditTaskInput, EnvironmentInspector, type EnvironmentInspectorOptions, type ExecutorResult, type FsWatcherCallbacks, type FsWatcherHandle, GitClient, GithubCopilotCliExecutor, HttpRequestExecutor, ImageTools, type InstalledAgent, InvalidDraftError, InvalidRepoUrlError, type IsoTimestamp, type JsonTools, KNOWN_WORKSPACES_FILENAME, type LoadResult, MACHINE_ID_FILENAME, MIGRATION_FAILURES_FILENAME, type MigrateToGlobalOptions, type MigrationResult, type OutputEventCallback, PROFILES_JSON_FILENAME, PidManager, type ProbeError, type ProbeOptions, type ProbeResult, ProjectTools, REPOS_CONFIG_FILENAME, REPOS_SUBDIR, RepoAlreadyExistsError, RepoCloneConflictError, type RepoConfig, RepoManager, RepoManagerError, type RepoManagerOptions, RepoNotFoundError, RepoNotInStoreError, type RepoSource, type ReposFile, type ReposFileInput, ReposLoader, type ReposLoaderFileSystem, type ReposLoaderOptions, ReposStore, type ReposStoreChange, type ReposStoreFileSystem, type ReposStoreListener, type ReposStoreOptions, SAFE_REPO_ID_PATTERN, SCHEDULED_TASKS_CONFIG_FILENAME, SCHEDULED_TASKS_LOG_FILENAME, SCHEDULER_LOCK_FILENAME, SCHEDULER_LOG_FILENAME, SCHEDULER_PID_FILENAME, SERVER_PROXY_GLOBAL_FILENAME, SERVICEME_DIR_NAME, SERVICEME_HOME_ENV, SKILL_DRAFTS_SUBDIR, type SaveDraftOptions, SchedulerDaemonV2, type SchedulerDaemonV2Options, type ServerProxyGlobalPatch, type ServerProxyGlobalState, ShellExecutor, type SkillCatalog, SkillCatalogClient, type SkillCatalogClientOptions, type SkillDownloadFile, type SkillMutateResult, SkillReconciler, type SkillReconcilerDependencies, SkillStore, type SkillStoreFileSystem, type SkillStoreOptions, type StreamingExecutorHandle, type StreamingTaskExecutor, type SyncReport, type SyncStatus, TOOLBOX_JSON_FILENAME, TOOL_RISK_MAP, TaskConfigManager, type TaskEventListener, TaskExecutionEngine, type TaskExecutor, TaskLogManager, type UserRepoConfig, WorkspaceProbe, repoSchema as anyRepoConfigSchema, assertSafeRepoId, bootstrapDefaults, bootstrapPhase5Placeholders, buildDefaultReposFile, copilotDoctor, copilotPrompt, createCopilotAuthRequiredError, createCopilotNotInstalledError, createImageTools, createJsonTools, createProjectTools, createReposStore, defaultRepoSchema as defaultRepoConfigSchema, ensureDefaultsInstalled, generateDraftId, getAgentDraftsDir, getAllDefaultRepoConfigs, getCacheDir, getCredentialsConfigPath, getDefaultRepoConfig, getDeviceJsonPath, getDraftsDir, getExecutor, getHomeDir, getHomePlatform, getKnownWorkspacesPath, getMachineIdPath, getMigrationFailuresPath, getProfilesJsonPath, getRepoCacheDir, getRepoDir, getReposConfigPath, getReposDir, getScheduledTasksConfigPath, getScheduledTasksLogPath, getSchedulerLockPath, getSchedulerLogPath, getSchedulerPidPath, getServerProxyGlobalPath, getServicemeHome, getSkillDraftsDir, getToolboxJsonPath, isCopilotAuthenticated, isDefaultRepo, isStreamingTaskExecutor, isUserRepo, migrateLegacyServerProxyEnabled, migrateToGlobal, moveFiles, narrowRepoConfig, parseAgentToolPermissions, readServerProxyGlobal, reposFileSchema, resetUserHomeOverrides, resolveDraftDir, resolveTaskExecutionPayload, setUserHomeOverrides, unzipFile, userRepoSchema as userRepoConfigSchema, validateReposFile, validateTaskPayload, writeServerProxyGlobal };
2822
+ export { AGENT_DRAFTS_SUBDIR, type AddUserRepoInput, type AddUserRepoResult, type AgentCatalog, AgentCatalogClient, type AgentCatalogClientOptions, type AgentDownloadFile, type AgentInstallScope, type AgentMutateResult, AgentReconciler, type AgentReconcilerDependencies, AgentStore, type AgentStoreFileSystem, type AgentStoreOptions, type AgentsStateFile, type AnyRepoConfig, type AppendLogInput, type BootstrapPhase5Result, type BuildCustomizationViewInput, CACHE_SUBDIR, CREDENTIALS_CONFIG_FILENAME, CannotRemoveDefaultRepoError, type CopilotArtifactKind, type CopilotArtifactState, type CopilotArtifactSummary, type CopilotArtifactView, type CopilotCustomizationView, type CopilotHostCapabilities, type CopilotInstallIntent, type CopilotIntegrationAdapter, CopilotLinkMaterializer, type CopilotLinkMode, type CopilotLocalGate, type CopilotMaterializationHealth, type CopilotPackageDefinition, type CopilotPackageInstallInput, type CopilotPackageInstallation, type CopilotPackageMoveInput, type CopilotPackageUninstallInput, type CopilotPackageUpdateInput, type CopilotPackageUpdatePreview, type CopilotPackageView, type CopilotPluginRegisterInput, CopilotPluginRegistrar, type CopilotPluginRegistrarOptions, type CopilotPluginRegistration, type CopilotScope, type CopilotSourceCatalogDeps, type CopilotSourceCatalogQuery, CopilotSourceCatalogService, type CopilotSourceRecord, type CopilotSourceSummary, type CopilotSourceView, type CopilotUpdatePreviewInput, type CopilotUserStatus, type CreateTaskInput, FIXED_ADDED_AT as DEFAULT_REPO_FIXED_ADDED_AT, DEFAULT_REPO_ID, DEVICE_JSON_FILENAME, DRAFTS_SUBDIR, DaemonLogger, type DefaultRepoConfig, type DisabledContentEntry, type DisabledContentMatcher, type DisabledContentState, DisabledContentStore, type DraftDetail, DraftNotFoundError, type DraftSummary, DraftsError, DraftsStore, type EditTaskInput, EnvironmentInspector, type EnvironmentInspectorOptions, type ExecutorResult, FileHookConfigAdapter, FileMcpConfigAdapter, type FsWatcherCallbacks, type FsWatcherHandle, GitClient, GithubCopilotCliExecutor, type HookConfigAdapter, type HookDefinition, type HookEventDefinition, HttpRequestExecutor, ImageTools, type InstalledAgent, type IntegrationApplyResult, InvalidDraftError, InvalidRepoUrlError, type IsoTimestamp, type JsonTools, KNOWN_WORKSPACES_FILENAME, type LegacyMigrationEntry, type LegacyMigrationPreview, type LegacyUserContentEntry, type LegacyUserContentMigrationResult, type LegacyUserSkillEntry, type LegacyUserSkillMigrationResult, type LoadResult, MACHINE_ID_FILENAME, MIGRATION_FAILURES_FILENAME, type MaterializeEntryResult, type MaterializeEntryStatus, type MaterializeResult, type McpConfigAdapter, type McpServerDefinition, type MigrateToGlobalOptions, type MigrationResult, type OutputEventCallback, PROFILES_JSON_FILENAME, PackageInstallationService, type PackageInstallationServiceDeps, type PersonalContentState, PersonalCopilotContentReconciler, type PersonalInstallationState, PersonalInstallationStore, type PersonalLinkKind, type PersonalPackageResolver, type PersonalReconcileResult, PidManager, type PlannedContentEntry, type PluginCatalogPackage, type PluginCatalogRepoInput, type PluginCatalogService, type ProbeError, type ProbeOptions, type ProbeResult, ProjectTools, REPOS_CONFIG_FILENAME, REPOS_SUBDIR, RepoAlreadyExistsError, RepoCloneConflictError, type RepoConfig, RepoManager, RepoManagerError, type RepoManagerOptions, RepoNotFoundError, RepoNotInStoreError, type RepoSource, type ReposFile, type ReposFileInput, ReposLoader, type ReposLoaderFileSystem, type ReposLoaderOptions, ReposStore, type ReposStoreChange, type ReposStoreFileSystem, type ReposStoreListener, type ReposStoreOptions, type ResolvedPluginEntry, type ResolvedPluginManifest, SAFE_REPO_ID_PATTERN, SCHEDULED_TASKS_CONFIG_FILENAME, SCHEDULED_TASKS_LOG_FILENAME, SCHEDULER_LOCK_FILENAME, SCHEDULER_LOG_FILENAME, SCHEDULER_PID_FILENAME, SERVER_PROXY_GLOBAL_FILENAME, SERVICEME_DIR_NAME, SERVICEME_HOME_ENV, SKILL_DRAFTS_SUBDIR, type SaveDraftOptions, SchedulerDaemonV2, type SchedulerDaemonV2Options, type ServerProxyGlobalPatch, type ServerProxyGlobalState, ShellExecutor, type SkillCatalog, SkillCatalogClient, type SkillCatalogClientOptions, type SkillDownloadFile, type SkillMutateResult, SkillReconciler, type SkillReconcilerDependencies, SkillStore, type SkillStoreFileSystem, type SkillStoreOptions, type StreamingExecutorHandle, type StreamingTaskExecutor, type SyncReport, type SyncStatus, TOOLBOX_JSON_FILENAME, TOOL_RISK_MAP, TaskConfigManager, type TaskEventListener, TaskExecutionEngine, type TaskExecutor, TaskLogManager, type UserRepoConfig, WORKSPACES_SUBDIR, WORKSPACE_CONTENT_STATE_FILENAME, WORKSPACE_MANIFEST_RELPATH, type WorkspaceContentEntryResult, type WorkspaceContentPlan, type WorkspaceContentReconcileResult, type WorkspaceContentState, WorkspaceContentStateStore, type WorkspaceContentStatus, WorkspaceCopilotContentReconciler, type WorkspaceCopilotManifest, type WorkspaceCopilotManifestV1, type WorkspaceCopilotManifestV2, WorkspaceExcludeStore, type WorkspaceManifestCatalogSource, type WorkspaceManifestGitSource, type WorkspaceManifestPlugin, type WorkspaceManifestPluginV2, type WorkspaceManifestRepository, type WorkspaceManifestSource, type WorkspaceMaterializedEntry, WorkspaceProbe, allPersonalLinkKinds, repoSchema as anyRepoConfigSchema, assertSafeRepoId, bootstrapDefaults, bootstrapPhase5Placeholders, buildCopilotCustomizationView, buildDefaultReposFile, copilotDoctor, copilotPrompt, createCopilotAuthRequiredError, createCopilotNotInstalledError, createDefaultCopilotHostCapabilities, createImageTools, createJsonTools, createPluginCatalogService, createProjectTools, createReposStore, defaultRepoSchema as defaultRepoConfigSchema, deriveCopilotUserStatus, ensureDefaultsInstalled, findPluginMcpJson, findRepoHooksJson, generateDraftId, getAgentDraftsDir, getAllDefaultRepoConfigs, getCacheDir, getCredentialsConfigPath, getDefaultRepoConfig, getDeviceJsonPath, getDraftsDir, getExecutor, getHomeDir, getHomePlatform, getKnownWorkspacesPath, getMachineIdPath, getMigrationFailuresPath, getProfilesJsonPath, getRepoCacheDir, getRepoDir, getReposConfigPath, getReposDir, getScheduledTasksConfigPath, getScheduledTasksLogPath, getSchedulerLockPath, getSchedulerLogPath, getSchedulerPidPath, getServerProxyGlobalPath, getServicemeHome, getSkillDraftsDir, getToolboxJsonPath, getWorkspaceManifestPath, getWorkspaceManifestPluginSourceId, getWorkspaceManifestSources, getWorkspaceStateDir, getWorkspacesDir, hashWorkspaceDir, isCopilotAuthenticated, isDefaultRepo, isStreamingTaskExecutor, isUserRepo, listPluginCatalog, loadWorkspaceCopilotManifest, migrateLegacyServerProxyEnabled, migrateLegacyUserContent, migrateLegacyUserSkillContent, migrateToGlobal, moveFiles, narrowRepoConfig, parseAgentToolPermissions, parseHooksJson, parseMcpJson, readDeclaredWorkspaceInstallations, readServerProxyGlobal, removeWorkspaceContentSelection, replaceWorkspaceContentSelection, reposFileSchema, resetUserHomeOverrides, resolveDraftDir, resolvePluginEntriesLenient, resolveTaskExecutionPayload, resolveWorkspaceContentPlan, setUserHomeOverrides, supportsPersonalIntegrationKind, supportsPersonalLinkKind, toArtifactSummary, unzipFile, upsertWorkspaceContentSelection, userRepoSchema as userRepoConfigSchema, validateReposFile, validateTaskPayload, writeServerProxyGlobal, writeWorkspaceCopilotManifest };