@serviceme/devtools-core 2.0.0 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/auth-Bzss8zOv.mjs +995 -0
  2. package/dist/auth-Bzss8zOv.mjs.map +1 -0
  3. package/dist/auth-DXam3c4S.js +1078 -0
  4. package/dist/auth-DXam3c4S.js.map +1 -0
  5. package/dist/auth.d.mts +2 -2
  6. package/dist/auth.d.ts +2 -2
  7. package/dist/auth.js +14 -1029
  8. package/dist/auth.mjs +2 -991
  9. package/dist/device-CDDcwDY6.mjs +758 -0
  10. package/dist/device-CDDcwDY6.mjs.map +1 -0
  11. package/dist/device-DuAYH8bk.js +839 -0
  12. package/dist/device-DuAYH8bk.js.map +1 -0
  13. package/dist/device.d.mts +2 -455
  14. package/dist/device.d.ts +2 -455
  15. package/dist/device.js +15 -728
  16. package/dist/device.mjs +2 -679
  17. package/dist/index-2rX86yMq.d.mts +331 -0
  18. package/dist/index-BI11AfMH.d.mts +377 -0
  19. package/dist/index-BI11AfMH.d.ts +377 -0
  20. package/dist/index-CoA6y0MP.d.mts +498 -0
  21. package/dist/index-CoA6y0MP.d.ts +498 -0
  22. package/dist/index-DaW7IYA-.d.mts +185 -0
  23. package/dist/index-DaW7IYA-.d.ts +185 -0
  24. package/dist/index-Dp6FwWKh.d.ts +331 -0
  25. package/dist/index.d.mts +2340 -2101
  26. package/dist/index.d.ts +2340 -2101
  27. package/dist/index.js +8117 -10538
  28. package/dist/index.js.map +1 -1
  29. package/dist/index.mjs +7895 -10318
  30. package/dist/index.mjs.map +1 -1
  31. package/dist/rolldown-runtime-VH7oDXx4.js +28 -0
  32. package/dist/skill-linker.d.mts +82 -81
  33. package/dist/skill-linker.d.ts +82 -81
  34. package/dist/skill-linker.js +359 -402
  35. package/dist/skill-linker.js.map +1 -1
  36. package/dist/skill-linker.mjs +345 -357
  37. package/dist/skill-linker.mjs.map +1 -1
  38. package/dist/skill-store-Bym2yinU.mjs +388 -0
  39. package/dist/skill-store-Bym2yinU.mjs.map +1 -0
  40. package/dist/skill-store-CJdYyyxu.js +408 -0
  41. package/dist/skill-store-CJdYyyxu.js.map +1 -0
  42. package/dist/skill-store.d.mts +41 -42
  43. package/dist/skill-store.d.ts +41 -42
  44. package/dist/skill-store.js +5 -338
  45. package/dist/skill-store.mjs +2 -301
  46. package/dist/submit-Cg7wSa3x.mjs +84 -0
  47. package/dist/submit-Cg7wSa3x.mjs.map +1 -0
  48. package/dist/submit-CltE6YOZ.js +98 -0
  49. package/dist/submit-CltE6YOZ.js.map +1 -0
  50. package/dist/submit.d.mts +2 -3
  51. package/dist/submit.d.ts +2 -3
  52. package/dist/submit.js +4 -166
  53. package/dist/submit.mjs +2 -130
  54. package/dist/toolbox-CbfxpNg-.mjs +540 -0
  55. package/dist/toolbox-CbfxpNg-.mjs.map +1 -0
  56. package/dist/toolbox-CxnOr-FY.js +614 -0
  57. package/dist/toolbox-CxnOr-FY.js.map +1 -0
  58. package/dist/toolbox.d.mts +2 -244
  59. package/dist/toolbox.d.ts +2 -244
  60. package/dist/toolbox.js +14 -584
  61. package/dist/toolbox.mjs +2 -536
  62. package/dist/{types-B9gk3dXH.d.ts → types-BCV3IedE.d.mts} +25 -23
  63. package/dist/{types-B9gk3dXH.d.mts → types-BCV3IedE.d.ts} +25 -23
  64. package/dist/userHome-BquDeFVE.js +526 -0
  65. package/dist/userHome-BquDeFVE.js.map +1 -0
  66. package/dist/userHome-CcnAQPG1.mjs +212 -0
  67. package/dist/userHome-CcnAQPG1.mjs.map +1 -0
  68. package/package.json +10 -10
  69. package/dist/auth.js.map +0 -1
  70. package/dist/auth.mjs.map +0 -1
  71. package/dist/device.js.map +0 -1
  72. package/dist/device.mjs.map +0 -1
  73. package/dist/index-BMk4tqIT.d.mts +0 -328
  74. package/dist/index-CymN0x9Z.d.ts +0 -328
  75. package/dist/index-PD135hlB.d.mts +0 -626
  76. package/dist/index-PD135hlB.d.ts +0 -626
  77. package/dist/skill-store.js.map +0 -1
  78. package/dist/skill-store.mjs.map +0 -1
  79. package/dist/submit.js.map +0 -1
  80. package/dist/submit.mjs.map +0 -1
  81. package/dist/toolbox.js.map +0 -1
  82. package/dist/toolbox.mjs.map +0 -1
package/dist/index.d.ts CHANGED
@@ -1,131 +1,131 @@
1
- import * as _serviceme_devtools_protocol from '@serviceme/devtools-protocol';
2
- import { AgentMarketplaceEntry, AgentMutationRequest, AgentPermissionSummary, CopilotDoctorResult, CopilotPromptOptions, CopilotPromptResult, EnvironmentCheckResult, KnownEnvironmentTool, ToolCheckResult, ServiceMeImageValidationResult, ServiceMeImageInfo, ServiceMeImageCompressOptions, ServiceMeImageCompressResult, JsonSortOptions, JsonValidationResult, AgentToolRiskLevel, AgentToolPermission, ServiceMeProjectExtractTemplateInput, ServiceMeProjectExtractTemplateResult, ServiceMeProjectInstallDepsResult, ServiceMeProjectMakeScriptsExecutableResult, ServiceMeProjectGitInitResult, ServiceMeProjectScaffoldPruneResult, TaskExecutionStatus, ScheduledTaskType, TaskPayload, TaskWorkspaceRef, ScheduledTasksConfig, ScheduledTask, TaskExecutionLog, TaskStartedEventParams, TaskOutputEventParams, TaskCompletedEventParams, TaskFailedEventParams, TaskCancelledEventParams, TaskExecutionSnapshot, RunningTaskInfo, SkillMarketplaceEntry, SkillMutationRequest } from '@serviceme/devtools-protocol';
3
- import * as fs from 'node:fs/promises';
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
- 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
- import { c as SkillKind, b as SkillFile } from './types-B9gk3dXH.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
- import * as fs$1 from 'node:fs';
10
- import { z } from 'zod';
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';
12
- import 'node:child_process';
13
-
14
- type AgentInstallScope = "workspace" | "user";
15
- interface InstalledAgent {
16
- id: string;
17
- name: string;
18
- scope: AgentInstallScope;
19
- installedAt: string;
20
- }
21
- interface AgentsStateFile {
22
- schemaVersion: number;
23
- installedAgents: InstalledAgent[];
24
- }
25
- interface AgentDownloadFile {
26
- path: string;
27
- content: string;
28
- executable?: boolean;
29
- }
30
- interface AgentStoreFileSystem {
31
- readdir: typeof fs.readdir;
32
- readFile: typeof fs.readFile;
33
- writeFile: typeof fs.writeFile;
34
- mkdir: typeof fs.mkdir;
35
- chmod: typeof fs.chmod;
36
- }
37
- interface AgentStoreOptions {
38
- workspacePath: string;
39
- userAgentsRoot: string;
40
- fileSystem?: AgentStoreFileSystem;
41
- schemaVersion?: number;
42
- }
43
-
44
- interface AgentCatalog {
45
- agents: AgentMarketplaceEntry[];
46
- fetchedAt: string;
47
- }
48
- interface AgentCatalogClientOptions {
49
- fetchImpl?: typeof fetch;
50
- baseUrl?: string;
51
- }
52
- declare class AgentCatalogClient {
53
- private readonly fetchImpl;
54
- private readonly baseUrl?;
55
- constructor(options?: AgentCatalogClientOptions);
56
- getCatalog(): Promise<AgentCatalog>;
57
- downloadAgent(remoteId: string): Promise<AgentDownloadFile[]>;
58
- }
59
-
1
+ import { A as KeyValueStore, C as AuthStateManagerOptions, D as AccessCheckResult, E as noopLogger, O as AccessControl, S as AuthStateManager, T as createConsoleLogger, _ as KeychainAccountKey, a as MicrosoftProviderNotHostedError, b as KeychainTokenMetadata, c as AuthCore, d as DeviceFlowUiCallback, f as ProviderRegistry, g as InMemoryKeychainAuthTokenStore, h as IAuthProviderUserInfo, i as MicrosoftAuthProvider, j as OrgMembershipFetcher, k as AccessControlOptions, l as AuthCoreOptions, m as IAuthProviderSession, n as isGitHubLocalEmail, o as GitHubAuthProvider, p as IAuthProvider, r as resolvePrimaryEmail, s as GitHubAuthProviderConfig, t as buildGitHubLocalEmail, u as CancellationCheck, v as KeychainAuthTokenStore, w as ServiceMeLogger, x as KeychainUnavailableError, y as KeychainTokenEnvelope } from "./index-CoA6y0MP.js";
2
+ import { C as DeviceSignedHeaders, S as DeviceRequestSignatureParams, T as createDeviceRequestSignature, _ as DEVICE_JSON_SCHEMA_VERSION, a as DeviceCoreOptions, b as BuildSignedHeadersParams, c as EnrollRequestFn, d as EnrollerOptions, f as FsIdentityFileBackend, g as AtomicWriteResult, h as IdentityStoreOptions, i as DeviceCore, l as EnrollResponse, m as IdentityStore, n as fingerprintSource, o as DeviceReenrollRequiresAuthError, p as IdentityFileBackend, r as randomInstallationId, s as DeviceSecretVersionMismatchError, t as deriveInstallationId, u as Enroller, v as IdentityStoreHooks, w as buildSignedHeaders, x as DeviceAuthHeaders, y as PersistedDeviceIdentity } from "./index-BI11AfMH.js";
3
+ import { i as SkillKind, r as SkillFile } from "./types-BCV3IedE.js";
4
+ import { a as SubmitError, c as NodeGitSpawner, d as toFileUrl, f as GitError, i as SubmitResult, l as StubGitSpawner, n as SubmitClientOptions, o as GIT_PROXY_PATH_SUFFIX, p as PullResult, r as SubmitOptions, s as GitClient, t as SubmitClient, u as buildGitProxyBase } from "./index-Dp6FwWKh.js";
5
+ import { _ as reindexOrder, a as ToolboxFileBackend, b as touchLastUsedAt, c as ToolboxStoreOptions, d as DefaultToolSeed, f as PersistedToolbox, g as mergeWithDefaults, h as ToolboxPatch, i as FsToolboxFileBackend, l as WORKSPACE_TOOLBOX_RELATIVE_PATH, m as TOOLBOX_JSON_SCHEMA_VERSION, n as ToolboxCore, o as ToolboxStore, p as ResolvedToolbox, r as ToolboxCoreOptions, s as ToolboxStoreHooks, t as DefaultToolImmutableError, u as BUILTIN_DEFAULT_TOOLS, v as sortByRecentFirst, y as sortByUserOrder } from "./index-DaW7IYA-.js";
6
+ import { AgentMarketplaceEntry, AgentMutationRequest, AgentPermissionSummary, AgentToolPermission, AgentToolRiskLevel, CopilotDoctorResult, CopilotPromptOptions, CopilotPromptResult, EnvironmentCheckResult, JsonSortOptions, JsonValidationResult, KnownEnvironmentTool, RunningTaskInfo, ScheduledTask, ScheduledTaskType, ScheduledTasksConfig, ServiceMeImageCompressOptions, ServiceMeImageCompressResult, ServiceMeImageInfo, ServiceMeImageValidationResult, ServiceMeProjectExtractTemplateInput, ServiceMeProjectExtractTemplateResult, ServiceMeProjectGitInitResult, ServiceMeProjectInstallDepsResult, ServiceMeProjectMakeScriptsExecutableResult, ServiceMeProjectScaffoldPruneResult, SkillMarketplaceEntry, SkillMutationRequest, TaskCancelledEventParams, TaskCompletedEventParams, TaskExecutionLog, TaskExecutionSnapshot, TaskExecutionStatus, TaskFailedEventParams, TaskOutputEventParams, TaskPayload, TaskStartedEventParams, TaskWorkspaceRef, ToolCheckResult } from "@serviceme/devtools-protocol";
7
+ import * as fs$1 from "node:fs/promises";
8
+ import * as fs from "node:fs";
9
+ import { z } from "zod";
10
+ //#region src/agents/types.d.ts
11
+ export type AgentInstallScope = "workspace" | "user";
12
+ export interface InstalledAgent {
13
+ id: string;
14
+ name: string;
15
+ scope: AgentInstallScope;
16
+ installedAt: string;
17
+ }
18
+ export interface AgentsStateFile {
19
+ schemaVersion: number;
20
+ installedAgents: InstalledAgent[];
21
+ }
22
+ export interface AgentDownloadFile {
23
+ path: string;
24
+ content: string;
25
+ executable?: boolean;
26
+ }
27
+ export interface AgentStoreFileSystem {
28
+ readdir: typeof fs$1.readdir;
29
+ readFile: typeof fs$1.readFile;
30
+ writeFile: typeof fs$1.writeFile;
31
+ mkdir: typeof fs$1.mkdir;
32
+ chmod: typeof fs$1.chmod;
33
+ }
34
+ export interface AgentStoreOptions {
35
+ workspacePath: string;
36
+ userAgentsRoot: string;
37
+ fileSystem?: AgentStoreFileSystem;
38
+ schemaVersion?: number;
39
+ }
40
+ //#endregion
41
+ //#region src/agents/AgentCatalogClient.d.ts
42
+ export interface AgentCatalog {
43
+ agents: AgentMarketplaceEntry[];
44
+ fetchedAt: string;
45
+ }
46
+ export interface AgentCatalogClientOptions {
47
+ fetchImpl?: typeof fetch;
48
+ baseUrl?: string;
49
+ }
50
+ export declare class AgentCatalogClient {
51
+ private readonly fetchImpl;
52
+ private readonly baseUrl?;
53
+ constructor(options?: AgentCatalogClientOptions);
54
+ getCatalog(): Promise<AgentCatalog>;
55
+ downloadAgent(remoteId: string): Promise<AgentDownloadFile[]>;
56
+ }
57
+ //#endregion
58
+ //#region src/agents/AgentReconciler.d.ts
60
59
  interface AgentStoreLike {
61
- normalizeRemoteAgentId(remoteId: string): string;
62
- listWorkspaceAgentIds(): Promise<string[]>;
63
- listUserAgentIds(): Promise<string[]>;
60
+ normalizeRemoteAgentId(remoteId: string): string;
61
+ listWorkspaceAgentIds(): Promise<string[]>;
62
+ listUserAgentIds(): Promise<string[]>;
64
63
  }
65
64
  interface AgentCatalogLike {
66
- agents: AgentMarketplaceEntry[];
67
- fetchedAt: string;
65
+ agents: AgentMarketplaceEntry[];
66
+ fetchedAt: string;
68
67
  }
69
68
  interface AgentCatalogClientLike {
70
- getCatalog(): Promise<AgentCatalogLike>;
71
- }
72
- interface AgentReconcilerDependencies {
73
- agentStore: AgentStoreLike;
74
- catalogClient: AgentCatalogClientLike;
75
- }
76
- interface AgentMutateResult {
77
- status: "success" | "blocked" | "requires_confirmation";
78
- changed: boolean;
79
- message?: string;
80
- tools?: string[];
81
- }
82
- declare class AgentReconciler {
83
- private readonly deps;
84
- constructor(deps: AgentReconcilerDependencies);
85
- mutate(request: AgentMutationRequest): Promise<AgentMutateResult>;
86
- getPermissionSummary(agentId: string, agentName: string, content: string): AgentPermissionSummary;
87
- private hasHighRiskTool;
88
- }
89
-
90
- declare class AgentStore {
91
- private readonly workspacePath;
92
- private readonly userAgentsRoot;
93
- private readonly fileSystem;
94
- private readonly schemaVersion;
95
- constructor(options: AgentStoreOptions);
96
- normalizeRemoteAgentId(remoteId: string): string;
97
- getWorkspaceAgentsRootPath(): string;
98
- getWorkspaceStateFilePath(): string;
99
- getUserAgentsRootPath(): string;
100
- listWorkspaceAgentIds(): Promise<string[]>;
101
- listUserAgentIds(): Promise<string[]>;
102
- readState(): Promise<AgentsStateFile | null>;
103
- /**
104
- * One-time migration: the workspace agents state file used to be named
105
- * `.github/.ms-devtools-agents.yml`. If the new `.serviceme-agents.yml`
106
- * doesn't exist yet but the legacy file does, copy its content forward
107
- * so existing installed-agent state isn't silently lost.
108
- */
109
- private migrateLegacyState;
110
- writeState(state: AgentsStateFile): Promise<void>;
111
- addInstalledAgent(entry: InstalledAgent): Promise<void>;
112
- removeInstalledAgent(agentId: string): Promise<void>;
113
- writeAgentFiles(agentId: string, scope: "workspace" | "user", files: AgentDownloadFile[]): Promise<void>;
114
- private listAgentIds;
69
+ getCatalog(): Promise<AgentCatalogLike>;
70
+ }
71
+ export interface AgentReconcilerDependencies {
72
+ agentStore: AgentStoreLike;
73
+ catalogClient: AgentCatalogClientLike;
74
+ }
75
+ export interface AgentMutateResult {
76
+ status: "success" | "blocked" | "requires_confirmation";
77
+ changed: boolean;
78
+ message?: string;
79
+ tools?: string[];
80
+ }
81
+ export declare class AgentReconciler {
82
+ private readonly deps;
83
+ constructor(deps: AgentReconcilerDependencies);
84
+ mutate(request: AgentMutationRequest): Promise<AgentMutateResult>;
85
+ getPermissionSummary(agentId: string, agentName: string, content: string): AgentPermissionSummary;
86
+ private hasHighRiskTool;
87
+ }
88
+ //#endregion
89
+ //#region src/agents/AgentStore.d.ts
90
+ export declare class AgentStore {
91
+ private readonly workspacePath;
92
+ private readonly userAgentsRoot;
93
+ private readonly fileSystem;
94
+ private readonly schemaVersion;
95
+ constructor(options: AgentStoreOptions);
96
+ normalizeRemoteAgentId(remoteId: string): string;
97
+ getWorkspaceAgentsRootPath(): string;
98
+ getWorkspaceStateFilePath(): string;
99
+ getUserAgentsRootPath(): string;
100
+ listWorkspaceAgentIds(): Promise<string[]>;
101
+ listUserAgentIds(): Promise<string[]>;
102
+ readState(): Promise<AgentsStateFile | null>;
103
+ /**
104
+ * One-time migration: the workspace agents state file used to be named
105
+ * `.github/.ms-devtools-agents.yml`. If the new `.serviceme-agents.yml`
106
+ * doesn't exist yet but the legacy file does, copy its content forward
107
+ * so existing installed-agent state isn't silently lost.
108
+ */
109
+ private migrateLegacyState;
110
+ writeState(state: AgentsStateFile): Promise<void>;
111
+ addInstalledAgent(entry: InstalledAgent): Promise<void>;
112
+ removeInstalledAgent(agentId: string): Promise<void>;
113
+ writeAgentFiles(agentId: string, scope: "workspace" | "user", files: AgentDownloadFile[]): Promise<void>;
114
+ private listAgentIds;
115
115
  }
116
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[];
117
+ export 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
+ export interface LegacyUserContentMigrationResult {
128
+ entries: LegacyUserContentEntry[];
129
129
  }
130
130
  /**
131
131
  * Detect ~/.agents agent content that can migrate to ~/.copilot.
@@ -134,23 +134,26 @@ interface LegacyUserContentMigrationResult {
134
134
  * explicitly invokes the migration, so a detection pass never destroys
135
135
  * anything another tool still depends on.
136
136
  */
137
- declare function migrateLegacyUserContent(input: {
138
- homeDir: string;
139
- workspaceDir: string;
140
- fileSystem?: AgentStoreFileSystem;
137
+ export declare function migrateLegacyUserContent(input: {
138
+ homeDir: string;
139
+ workspaceDir: string;
140
+ fileSystem?: AgentStoreFileSystem;
141
141
  }): Promise<LegacyUserContentMigrationResult>;
142
-
142
+ //#endregion
143
+ //#region src/copilot/doctor.d.ts
143
144
  /**
144
145
  * Quick auth pre-flight check using `gh auth status`.
145
146
  * Returns true if gh is authenticated; false otherwise.
146
147
  */
147
- declare function isCopilotAuthenticated(): Promise<boolean>;
148
- declare function copilotDoctor(): Promise<CopilotDoctorResult>;
149
- declare function createCopilotNotInstalledError(): _serviceme_devtools_protocol.ServicemeProtocolError;
150
- declare function createCopilotAuthRequiredError(): _serviceme_devtools_protocol.ServicemeProtocolError;
151
-
152
- declare function copilotPrompt(options: CopilotPromptOptions): Promise<CopilotPromptResult>;
153
-
148
+ export declare function isCopilotAuthenticated(): Promise<boolean>;
149
+ export declare function copilotDoctor(): Promise<CopilotDoctorResult>;
150
+ export declare function createCopilotNotInstalledError(): import("@serviceme/devtools-protocol").ServicemeProtocolError;
151
+ export declare function createCopilotAuthRequiredError(): import("@serviceme/devtools-protocol").ServicemeProtocolError;
152
+ //#endregion
153
+ //#region src/copilot/prompt.d.ts
154
+ export declare function copilotPrompt(options: CopilotPromptOptions): Promise<CopilotPromptResult>;
155
+ //#endregion
156
+ //#region src/copilot-content/types.d.ts
154
157
  /**
155
158
  * Contracts for the declarative Copilot content lifecycle.
156
159
  *
@@ -160,151 +163,189 @@ declare function copilotPrompt(options: CopilotPromptOptions): Promise<CopilotPr
160
163
  * 3. machine-local materialization state under ~/.serviceme/workspaces
161
164
  */
162
165
  /** Artifact kinds a logical plugin can contribute to Copilot. */
163
- type CopilotArtifactKind = "agent" | "skill" | "instruction" | "prompt" | "hook" | "mcp";
166
+ export type CopilotArtifactKind = "agent" | "skill" | "instruction" | "prompt" | "hook" | "mcp";
167
+ /** Parsed form of a content identity (see {@link buildContentIdentity}). */
168
+ export interface ContentIdentity {
169
+ repoId: string;
170
+ pluginId: string;
171
+ kind: string;
172
+ name: string;
173
+ }
174
+ /**
175
+ * Build the stable content identity `${repoId}::${pluginId}::${kind}:${name}`.
176
+ * New code should always construct it through this helper; a few
177
+ * pre-existing sites (plugin-resolver, workspace-declaration-reader)
178
+ * still inline the same shape.
179
+ */
180
+ export declare function buildContentIdentity(identity: ContentIdentity): string;
181
+ /**
182
+ * Parse a content identity back into its parts. Returns null for
183
+ * anything that does not match the `${repoId}::${pluginId}::${kind}:${name}`
184
+ * shape (e.g. integration identities without a name tail are handled
185
+ * by their callers and should not be passed here).
186
+ */
187
+ export declare function parseContentIdentity(value: string): ContentIdentity | null;
164
188
  /** 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;
189
+ export interface WorkspaceManifestRepository {
190
+ /** Stable id used in on-disk paths and plugin references. */
191
+ id: string;
192
+ /** Authoritative cross-machine source identity (HTTPS or git@ URL). */
193
+ url: string;
194
+ /** Full 40-character commit SHA; branch names are not allowed. */
195
+ commit: string;
172
196
  }
173
197
  /** A Git source in the v2 manifest syntax. */
174
- interface WorkspaceManifestGitSource extends WorkspaceManifestRepository {
175
- type: "git";
198
+ export interface WorkspaceManifestGitSource extends WorkspaceManifestRepository {
199
+ type: "git";
176
200
  }
177
201
  /** 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;
202
+ export interface WorkspaceManifestCatalogSource {
203
+ type: "catalog";
204
+ /** Stable local repository id used for the managed source directory. */
205
+ id: string;
206
+ /** Marketplace identity, independent of any transient download URL. */
207
+ catalogId: string;
208
+ /** Immutable catalog release selected by the workspace. */
209
+ revision: string;
210
+ /** SHA-256 of the complete catalog payload, prefixed with sha256:. */
211
+ digest: string;
188
212
  }
189
213
  /** A source that can be restored on each collaborator's machine. */
190
- type WorkspaceManifestSource = WorkspaceManifestGitSource | WorkspaceManifestCatalogSource;
214
+ export type WorkspaceManifestSource = WorkspaceManifestGitSource | WorkspaceManifestCatalogSource;
191
215
  /** 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[];
216
+ export interface WorkspaceManifestPlugin {
217
+ /** Referenced repository id. */
218
+ repository: string;
219
+ /** Logical plugin id from plugin.json, or the legacy skill/agent name. */
220
+ id: string;
221
+ /** Legacy artifact-kind selection, retained for compatible workspace declarations. */
222
+ artifacts: Partial<Record<CopilotArtifactKind, boolean>>;
223
+ /** Exact resolver artifact identities selected for this package. */
224
+ artifactIds?: string[];
225
+ /** Content targets (`kind:name`) deliberately disabled on installs of
226
+ * this package — part of the shared declaration so the disabled state
227
+ * survives extension reloads and machine-local state loss. */
228
+ disabledArtifacts?: string[];
201
229
  }
202
230
  /** 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[];
231
+ export interface WorkspaceManifestPluginV2 {
232
+ /** Referenced source id. */
233
+ source: string;
234
+ /** Logical plugin id from plugin.json, or the legacy skill/agent name. */
235
+ id: string;
236
+ /** Legacy artifact-kind selection, retained for compatible workspace declarations. */
237
+ artifacts: Partial<Record<CopilotArtifactKind, boolean>>;
238
+ /** Exact resolver artifact identities selected for this package. */
239
+ artifactIds?: string[];
240
+ /** Content targets (`kind:name`) deliberately disabled on installs of
241
+ * this package — part of the shared declaration so the disabled state
242
+ * survives extension reloads and machine-local state loss. */
243
+ disabledArtifacts?: string[];
212
244
  }
213
245
  /** Root shape of .github/serviceme-plugins.json. */
214
- interface WorkspaceCopilotManifestV1 {
215
- version: 1;
216
- repositories: WorkspaceManifestRepository[];
217
- plugins: WorkspaceManifestPlugin[];
246
+ export interface WorkspaceCopilotManifestV1 {
247
+ version: 1;
248
+ repositories: WorkspaceManifestRepository[];
249
+ plugins: WorkspaceManifestPlugin[];
218
250
  }
219
251
  /** Root v2 shape: sources may be Git checkouts or immutable catalog artifacts. */
220
- interface WorkspaceCopilotManifestV2 {
221
- version: 2;
222
- sources: WorkspaceManifestSource[];
223
- plugins: WorkspaceManifestPluginV2[];
252
+ export interface WorkspaceCopilotManifestV2 {
253
+ version: 2;
254
+ sources: WorkspaceManifestSource[];
255
+ plugins: WorkspaceManifestPluginV2[];
224
256
  }
225
257
  /** Root shape of .github/serviceme-plugins.json. */
226
- type WorkspaceCopilotManifest = WorkspaceCopilotManifestV1 | WorkspaceCopilotManifestV2;
258
+ export type WorkspaceCopilotManifest = WorkspaceCopilotManifestV1 | WorkspaceCopilotManifestV2;
227
259
  /** Normalize the versioned source list for consumers that do not care about syntax. */
228
- declare function getWorkspaceManifestSources(manifest: WorkspaceCopilotManifest): WorkspaceManifestSource[];
260
+ export declare function getWorkspaceManifestSources(manifest: WorkspaceCopilotManifest): WorkspaceManifestSource[];
229
261
  /** Resolve a versioned plugin selection to its source id. */
230
- declare function getWorkspaceManifestPluginSourceId(manifest: WorkspaceCopilotManifest, plugin: WorkspaceManifestPlugin | WorkspaceManifestPluginV2): string;
262
+ export declare function getWorkspaceManifestPluginSourceId(manifest: WorkspaceCopilotManifest, plugin: WorkspaceManifestPlugin | WorkspaceManifestPluginV2): string;
231
263
  /** Materialization mode used when activating an entry on the current machine. */
232
- type CopilotLinkMode = "symlink" | "junction" | "generated";
264
+ export type CopilotLinkMode = "symlink" | "junction" | "generated";
233
265
  /** 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;
266
+ export interface WorkspaceMaterializedEntry {
267
+ /** Stable identity: repository::plugin::kind[:name]. */
268
+ identity: string;
269
+ /** Owning repository id. */
270
+ repositoryId: string;
271
+ /** Owning logical plugin id. */
272
+ pluginId: string;
273
+ /** Artifact kind of this entry. */
274
+ kind: CopilotArtifactKind;
275
+ /** Absolute source path under ~/.serviceme/repos. */
276
+ sourcePath: string;
277
+ /** Workspace-relative link path. */
278
+ linkPath: string;
279
+ /** Link mode used on this machine. */
280
+ linkMode: CopilotLinkMode;
281
+ /** SHA-256 digest of the pinned source content. */
282
+ digest: string;
283
+ /** Whether the current machine approved risky content. */
284
+ approved: boolean;
253
285
  }
254
286
  /** Machine-local materialization state; never shared through git. */
255
- interface WorkspaceContentState {
256
- version: 1;
257
- entries: WorkspaceMaterializedEntry[];
287
+ export interface WorkspaceContentState {
288
+ version: 1;
289
+ entries: WorkspaceMaterializedEntry[];
258
290
  }
259
-
291
+ //#endregion
292
+ //#region src/copilot-content/content-plan.d.ts
260
293
  /** 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;
294
+ export interface PlannedContentEntry {
295
+ /** Stable identity: repository::plugin::kind[:name]. */
296
+ identity: string;
297
+ /** Owning repository id. */
298
+ repositoryId: string;
299
+ /** Owning logical plugin id. */
300
+ pluginId: string;
301
+ /** Artifact kind of this entry. */
302
+ kind: CopilotArtifactKind;
303
+ /** Absolute source path under the repository root. */
304
+ sourcePath: string;
305
+ /** Whether the source is a single file (agent/instruction) or a directory (skill). */
306
+ sourceIsFile: boolean;
307
+ /** Copilot-facing name used at the link target. */
308
+ name: string;
309
+ /** SHA-256 digest over the source content. */
310
+ digest: string;
311
+ /** Whether local approval is required before activation. */
312
+ requiresApproval: boolean;
280
313
  }
281
314
  /** 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;
315
+ export interface WorkspaceContentPlan {
316
+ entries: PlannedContentEntry[];
317
+ }
318
+ //#endregion
319
+ //#region src/copilot-content/plugin-resolver.d.ts
320
+ export interface ResolvedPluginManifest {
321
+ name: string;
322
+ description?: string;
323
+ version?: string;
324
+ extensions: Record<string, Record<string, unknown>>;
325
+ }
326
+ export interface ResolvedPluginEntry extends PlannedContentEntry {
327
+ /** Stable artifact identifier for consumers that do not need to parse identity. */
328
+ artifactId: string;
329
+ /** Stable package identifier for the logical repository/plugin pair. */
330
+ packageId: string;
331
+ /** Display metadata for the logical package. */
332
+ packageDisplayName: string;
333
+ packageDescription?: string;
334
+ packageVersion?: string;
301
335
  }
302
336
  /** Resolve a workspace declaration into an immutable content plan. */
303
- declare function resolveWorkspaceContentPlan(input: {
304
- manifest: WorkspaceCopilotManifest;
305
- reposDir: string;
337
+ export interface WorkspacePlanConflict {
338
+ /** Identity of the dropped (later) entry. */
339
+ identity: string;
340
+ /** Human-readable remediation hint naming both plugins. */
341
+ message: string;
342
+ }
343
+ export declare function resolveWorkspaceContentPlan(input: {
344
+ manifest: WorkspaceCopilotManifest;
345
+ reposDir: string;
306
346
  }): Promise<{
307
- entries: ResolvedPluginEntry[];
347
+ entries: ResolvedPluginEntry[];
348
+ conflicts: WorkspacePlanConflict[];
308
349
  }>;
309
350
  /**
310
351
  * Lenient variant for CATALOG BROWSING: resolve a single plugin's
@@ -319,45 +360,46 @@ declare function resolveWorkspaceContentPlan(input: {
319
360
  * here; mcp.json/hooks stay install-pipeline-only (they materialize
320
361
  * shared config and MUST pass the strict gate).
321
362
  */
322
- declare function resolvePluginEntriesLenient(input: {
323
- repoRoot: string;
324
- repositoryId: string;
325
- pluginId: string;
326
- manifest: ResolvedPluginManifest;
363
+ export declare function resolvePluginEntriesLenient(input: {
364
+ repoRoot: string;
365
+ repositoryId: string;
366
+ pluginId: string;
367
+ manifest: ResolvedPluginManifest;
327
368
  }): Promise<ResolvedPluginEntry[]>;
328
-
369
+ //#endregion
370
+ //#region src/copilot-content/copilot-host-capabilities.d.ts
329
371
  /** Personal artifact kinds materialized as managed links into host target directories. */
330
- declare const allPersonalLinkKinds: readonly ["agent", "skill", "prompt", "instruction"];
372
+ export declare const allPersonalLinkKinds: readonly ["agent", "skill", "prompt", "instruction"];
331
373
  /** One personal link kind. */
332
- type PersonalLinkKind = (typeof allPersonalLinkKinds)[number];
374
+ export type PersonalLinkKind = (typeof allPersonalLinkKinds)[number];
333
375
  /**
334
376
  * Adapter that applies or removes one personal integration entry (mcp/hook)
335
377
  * in host-owned user configuration. Implementations own their config format;
336
378
  * callers own the digest approval rule.
337
379
  */
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>;
380
+ export interface CopilotIntegrationAdapter {
381
+ /** Apply one approved integration entry on this machine. */
382
+ applyEntry(input: {
383
+ entry: ResolvedPluginEntry;
384
+ }): Promise<void>;
385
+ /** Remove a previously applied entry; returns whether anything was removed. */
386
+ removeEntry(input: {
387
+ identity: string;
388
+ }): Promise<boolean>;
347
389
  }
348
390
  /** 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;
391
+ export interface CopilotHostCapabilities {
392
+ /** Absolute, host-verified target directory per personal link kind. */
393
+ personalTargets: Partial<Record<PersonalLinkKind, string>>;
394
+ /** Adapter for personal MCP configuration, when the host supports one. */
395
+ mcpAdapter?: CopilotIntegrationAdapter;
396
+ /** Adapter for personal hook registration, when the host supports one. */
397
+ hookAdapter?: CopilotIntegrationAdapter;
356
398
  }
357
399
  /** Whether the host verified a personal target directory for the kind. */
358
- declare function supportsPersonalLinkKind(capabilities: CopilotHostCapabilities, kind: PersonalLinkKind): boolean;
400
+ export declare function supportsPersonalLinkKind(capabilities: CopilotHostCapabilities, kind: PersonalLinkKind): boolean;
359
401
  /** Whether the host provides the adapter an integration kind requires. */
360
- declare function supportsPersonalIntegrationKind(capabilities: CopilotHostCapabilities, kind: "mcp" | "hook"): boolean;
402
+ export declare function supportsPersonalIntegrationKind(capabilities: CopilotHostCapabilities, kind: "mcp" | "hook"): boolean;
361
403
  /**
362
404
  * Conservative production capability provider.
363
405
  *
@@ -367,51 +409,53 @@ declare function supportsPersonalIntegrationKind(capabilities: CopilotHostCapabi
367
409
  * until a verified provider wires them (Task 9); the reconciler reports those
368
410
  * kinds as unsupported instead of inventing directories.
369
411
  */
370
- declare function createDefaultCopilotHostCapabilities(options?: {
371
- copilotHomeDir?: string;
412
+ export declare function createDefaultCopilotHostCapabilities(options?: {
413
+ copilotHomeDir?: string;
372
414
  }): Promise<CopilotHostCapabilities>;
373
-
415
+ //#endregion
416
+ //#region src/copilot-content/copilot-link-materializer.d.ts
374
417
  /** 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;
418
+ export type MaterializeEntryStatus = "restored" | "adopted" | "conflict" | "drifted" | "pending_approval";
419
+ export interface MaterializeEntryResult {
420
+ identity: string;
421
+ status: MaterializeEntryStatus;
422
+ /** Secondary machine-local state, e.g. migration_available for legacy links. */
423
+ message?: string;
424
+ }
425
+ export interface MaterializeResult {
426
+ changed: boolean;
427
+ entries: MaterializeEntryResult[];
428
+ /** Updated machine-local state (only successfully materialized entries). */
429
+ state: WorkspaceContentState;
387
430
  }
388
431
  /** 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
-
432
+ export declare class CopilotLinkMaterializer {
433
+ private pendingFailure;
434
+ /** Test seam: make the next reconcile throw, then clear the failure. */
435
+ failNext(error: Error): void;
436
+ /** Materialize planned entries with conflict/drift safety. */
437
+ reconcile(input: {
438
+ workspaceDir: string;
439
+ entries: PlannedContentEntry[];
440
+ previousState: WorkspaceContentState;
441
+ }): Promise<MaterializeResult>;
442
+ /** Adopt a matching legacy link without recreating it. */
443
+ adoptLegacyLink(input: {
444
+ workspaceDir: string;
445
+ entry: PlannedContentEntry;
446
+ }): Promise<MaterializeEntryResult>;
447
+ /** Inspect a legacy ~/.agents link; report without deleting. */
448
+ inspectLegacyUserLink(input: {
449
+ homeDir: string;
450
+ entry: PlannedContentEntry;
451
+ }): Promise<MaterializeEntryResult>;
452
+ private resolveLinkPath;
453
+ private createLinkAtomic;
454
+ private toStateEntry;
455
+ private toStateLinkPath;
456
+ }
457
+ //#endregion
458
+ //#region src/copilot-content/copilot-plugin-registrar.d.ts
415
459
  /**
416
460
  * Copilot plugin whole-package registration.
417
461
  *
@@ -442,150 +486,158 @@ declare class CopilotLinkMaterializer {
442
486
  * `chat.pluginLocations` (VS Code user settings) is intentionally
443
487
  * NOT handled here — it can only be written by the extension layer.
444
488
  */
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;
489
+ export interface CopilotPluginRegistrarOptions {
490
+ /** Projection root. Defaults to `${SERVICEME_HOME}/copilot-plugins`. */
491
+ pluginsDir?: string;
492
+ /** `~/.copilot` — migration source only (VS Code owns that tree). */
493
+ copilotDir?: string;
494
+ }
495
+ export interface CopilotPluginRegisterInput {
496
+ repoId: string;
497
+ pluginId: string;
498
+ /** Canonical checkout plugin directory (the whole package root). */
499
+ pluginDir: string;
500
+ /** @deprecated Projection root comes from the constructor; ignored. */
501
+ copilotDir?: string;
502
+ scope?: "workspace" | "personal";
503
+ displayName?: string;
504
+ version?: string;
505
+ }
506
+ export interface CopilotPluginRegistration {
507
+ /** `${repoId}:${pluginId}` — path-safe. */
508
+ registrationId: string;
509
+ repoId: string;
510
+ pluginId: string;
511
+ pluginDir: string;
512
+ displayName?: string;
513
+ version?: string;
514
+ scopes: Array<"workspace" | "personal">;
515
+ }
516
+ export declare class CopilotPluginRegistrar {
517
+ private readonly pluginsDir;
518
+ private readonly copilotDir;
519
+ private migrated;
520
+ constructor(options?: CopilotPluginRegistrarOptions);
521
+ /** Registry root — resolved, used as the boundary for all path joins. */
522
+ private installedDir;
523
+ /** Projection path for an id, with an explicit containment check. */
524
+ private linkPath;
525
+ private registryPath;
526
+ /**
527
+ * One-shot migration away from `~/.copilot` (VS Code territory):
528
+ * carries over registry records and surviving projections from both
529
+ * legacy layouts and removes the old trees. Self-guarding when the
530
+ * source and destination coincide; safe to run repeatedly.
531
+ */
532
+ private migrateFromCopilotDir;
533
+ private readRegistry;
534
+ private writeRegistry;
535
+ register(input: CopilotPluginRegisterInput): Promise<CopilotPluginRegistration>;
536
+ unregister(input: {
537
+ registrationId: string;
456
538
  /** @deprecated Projection root comes from the constructor; ignored. */
457
539
  copilotDir?: string;
458
540
  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
-
541
+ }): Promise<void>;
542
+ list(_input?: {
543
+ copilotDir?: string;
544
+ }): Promise<CopilotPluginRegistration[]>;
545
+ }
546
+ //#endregion
547
+ //#region src/copilot-content/customization-model.d.ts
548
+ export type CopilotScope = "workspace" | "personal";
549
+ export type CopilotInstallIntent = "available" | "selected" | "moving" | "removing";
550
+ export type CopilotMaterializationHealth = "healthy" | "missing" | "drifted" | "conflict" | "source-unavailable" | "unsupported";
551
+ export type CopilotLocalGate = "ready" | "approval-required" | "configuration-required";
552
+ export type CopilotUserStatus = "healthy" | "action-required" | "blocked" | "not-enabled";
553
+ export interface CopilotArtifactState {
554
+ intent: CopilotInstallIntent;
555
+ health: CopilotMaterializationHealth;
556
+ gate: CopilotLocalGate;
557
+ }
558
+ export interface CopilotPackageInstallation {
559
+ packageId: string;
560
+ scope: CopilotScope;
561
+ selectedArtifactIds: string[];
562
+ pinnedVersion?: string;
563
+ }
564
+ export interface CopilotArtifactSummary {
565
+ id: string;
566
+ packageId: string;
567
+ kind: CopilotArtifactKind;
568
+ displayName: string;
569
+ description?: string;
570
+ installStrategy: "link" | "generated-config" | "approval-gated";
571
+ risk: "none" | "review-required";
572
+ }
573
+ export declare function deriveCopilotUserStatus(states: CopilotArtifactState[]): CopilotUserStatus;
574
+ //#endregion
575
+ //#region src/copilot-content/customization-view.d.ts
576
+ export interface CopilotSourceSummary {
577
+ id: string;
578
+ type: "marketplace" | "git" | "local";
579
+ displayName: string;
580
+ updateCapability: "pinned" | "live" | "none";
581
+ }
582
+ export interface CopilotPackageDefinition {
583
+ id: string;
584
+ sourceId: string;
585
+ displayName: string;
586
+ description?: string;
587
+ version?: string;
588
+ artifacts: CopilotArtifactSummary[];
589
+ /** Whole-package registrar installation (Copilot-managed, both scopes)
590
+ * the home package list shows these; per-artifact v1 manifest plugins
591
+ * stay in the enabled-content section instead. */
592
+ wholePackage?: boolean;
593
+ }
594
+ export interface CopilotArtifactView {
595
+ artifact: CopilotArtifactSummary;
596
+ state: CopilotArtifactState;
597
+ }
598
+ export interface CopilotPackageView {
599
+ definition: CopilotPackageDefinition;
600
+ installation: CopilotPackageInstallation;
601
+ artifacts: CopilotArtifactView[];
602
+ selectedArtifactCount: number;
603
+ status: CopilotUserStatus;
604
+ }
605
+ export interface CopilotSourceView extends CopilotSourceSummary {
606
+ packages: CopilotPackageView[];
607
+ }
608
+ export interface CopilotCustomizationView {
609
+ scope: CopilotScope;
610
+ generatedAt: string;
611
+ sources: CopilotSourceView[];
612
+ packages: CopilotPackageView[];
613
+ attention: CopilotArtifactView[];
614
+ summary: {
615
+ packageCount: number;
616
+ enabledArtifactCount: number;
617
+ attentionCount: number;
618
+ };
619
+ legacyMigration?: {
620
+ count: number;
621
+ sourceLabel: "~/.agents";
622
+ };
623
+ }
624
+ export interface BuildCustomizationViewInput {
625
+ scope: CopilotScope;
626
+ sources: CopilotSourceSummary[];
627
+ packages: CopilotPackageDefinition[];
628
+ installations: CopilotPackageInstallation[];
629
+ statesByArtifactId: Record<string, CopilotArtifactState>;
630
+ legacyCount?: number;
631
+ generatedAt?: string;
632
+ /** Content identities deliberately disabled on this machine (or in
633
+ * the shared declaration). They stay in the projection (so the UI can
634
+ * still render disabled rows) but no longer count as "enabled" in the
635
+ * health-card summary. */
636
+ disabledArtifactIds?: string[];
637
+ }
638
+ export declare function buildCopilotCustomizationView(input: BuildCustomizationViewInput): CopilotCustomizationView;
639
+ //#endregion
640
+ //#region src/copilot-content/disabled-content-store.d.ts
589
641
  /**
590
642
  * Machine-local disabled marks for per-artifact skills/agents.
591
643
  *
@@ -596,313 +648,337 @@ declare function buildCopilotCustomizationView(input: BuildCustomizationViewInpu
596
648
  * on the next restore. Entries are keyed by scope + identity; a
597
649
  * workspace-scope mark only applies to that workspace.
598
650
  */
599
- interface DisabledContentEntry {
600
- scope: "workspace" | "user";
651
+ export interface DisabledContentEntry {
652
+ scope: "workspace" | "user";
653
+ repoId: string;
654
+ name: string;
655
+ kind: "skill" | "agent";
656
+ /** Required for workspace-scope marks — disables are per workspace. */
657
+ workspaceDir?: string;
658
+ }
659
+ export interface DisabledContentState {
660
+ version: 1;
661
+ entries: DisabledContentEntry[];
662
+ }
663
+ /**
664
+ * Identity matcher for the workspace reconciler's `isDisabled` seam.
665
+ * The mark's `name` is the ENTRY name (hello-skill), not the plugin id
666
+ * (hello), so the match keys on repoId + kind + entry name. User marks
667
+ * apply to any workspace; workspace marks only to their own.
668
+ */
669
+ export declare function buildDisabledIdentityMatcher(workspaceDir: string, marks: DisabledContentEntry[]): (identity: string) => boolean;
670
+ export declare class DisabledContentStore {
671
+ private readonly homeDir;
672
+ constructor(options?: {
673
+ homeDir?: string;
674
+ });
675
+ /** Absolute store path: SERVICEME_HOME/copilot/disabled-content.json. */
676
+ path(): Promise<string>;
677
+ list(): Promise<DisabledContentEntry[]>;
678
+ add(entry: DisabledContentEntry): Promise<void>;
679
+ remove(entry: DisabledContentEntry): Promise<void>;
680
+ /**
681
+ * Lifecycle cleanup: installing or uninstalling an artifact clears
682
+ * its disable marks for that scope — a mark without its artifact is
683
+ * stale garbage that keeps the home page showing a disabled row for
684
+ * content the catalog already reports as gone. User scope matches
685
+ * any workspace; workspace scope matches the exact workspace.
686
+ */
687
+ removeForArtifact(input: {
601
688
  repoId: string;
602
689
  name: string;
603
690
  kind: "skill" | "agent";
604
- /** Required for workspace-scope marks — disables are per workspace. */
691
+ scope: "workspace" | "user";
605
692
  workspaceDir?: string;
693
+ }): Promise<void>;
694
+ private write;
606
695
  }
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
-
696
+ //#endregion
697
+ //#region src/copilot-content/integration-adapters.d.ts
627
698
  /** 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[];
699
+ export interface McpServerDefinition {
700
+ /** Server name used in the generated local configuration. */
701
+ name: string;
702
+ /** Transport type: stdio command servers today. */
703
+ type: string;
704
+ /** Executable command (validated, never a shell string). */
705
+ command: string;
706
+ /** Arguments passed to the command. */
707
+ args?: string[];
708
+ /** Environment variable names the server may read. */
709
+ env?: Record<string, string>;
710
+ /** Tool allowlist declared by the source. */
711
+ tools?: string[];
641
712
  }
642
713
  /** 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;
714
+ export interface HookEventDefinition {
715
+ /** Hook executor type; only "command" is supported today. */
716
+ type: string;
717
+ /** Relative bash entry referenced after materialization. */
718
+ bash: string;
719
+ /** Working directory hint relative to the workspace root. */
720
+ cwd?: string;
721
+ /** Environment variable names the hook may read. */
722
+ env?: Record<string, string>;
723
+ /** Timeout in seconds. */
724
+ timeoutSec?: number;
654
725
  }
655
726
  /** 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[]>>;
727
+ export interface HookDefinition {
728
+ /** Lifecycle event -> registrations. */
729
+ hooks: Partial<Record<string, HookEventDefinition[]>>;
659
730
  }
660
731
  /** 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;
732
+ export interface IntegrationApplyResult {
733
+ identity: string;
734
+ /** Path of the machine-local config the adapter manages. */
735
+ configPath: string;
736
+ /** Server or hook names written into the config. */
737
+ names: string[];
738
+ changed: boolean;
668
739
  }
669
740
  /** 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>;
741
+ export interface McpConfigAdapter {
742
+ /** Merge one server definition into the machine-local config. */
743
+ applyServer(input: {
744
+ workspaceDir: string;
745
+ entry: PlannedContentEntry;
746
+ server: McpServerDefinition;
747
+ }): Promise<IntegrationApplyResult>;
748
+ /** Remove servers previously written for this entry. */
749
+ removeEntry(input: {
750
+ workspaceDir: string;
751
+ identity: string;
752
+ }): Promise<boolean>;
682
753
  }
683
754
  /** 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>;
755
+ export interface HookConfigAdapter {
756
+ /** Materialize hook scripts and register lifecycle events. */
757
+ applyHook(input: {
758
+ workspaceDir: string;
759
+ entry: PlannedContentEntry;
760
+ hook: HookDefinition;
761
+ }): Promise<IntegrationApplyResult>;
762
+ /** Remove registrations previously written for this entry. */
763
+ removeEntry(input: {
764
+ workspaceDir: string;
765
+ identity: string;
766
+ }): Promise<boolean>;
696
767
  }
697
768
  /** Parse and validate a plugin mcp.json payload. */
698
- declare function parseMcpJson(raw: string): McpServerDefinition[];
769
+ export declare function parseMcpJson(raw: string): McpServerDefinition[];
699
770
  /** Parse and validate a hooks.json payload. */
700
- declare function parseHooksJson(raw: string): HookDefinition;
771
+ export declare function parseHooksJson(raw: string): HookDefinition;
701
772
  /** Locate the mcp.json beside a plugin manifest. */
702
- declare function findPluginMcpJson(repoRoot: string, pluginId: string): Promise<string | null>;
773
+ export declare function findPluginMcpJson(repoRoot: string, pluginId: string): Promise<string | null>;
703
774
  /** Locate hooks/<name>/hooks.json in a repository. */
704
- declare function findRepoHooksJson(repoRoot: string, name: string): Promise<string | null>;
705
-
775
+ export declare function findRepoHooksJson(repoRoot: string, name: string): Promise<string | null>;
776
+ //#endregion
777
+ //#region src/copilot-content/filesystem-integration-adapters.d.ts
706
778
  /** 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>;
779
+ export declare class FileMcpConfigAdapter implements McpConfigAdapter {
780
+ /** Merge one server definition under its entry identity. */
781
+ applyServer(input: {
782
+ workspaceDir: string;
783
+ entry: PlannedContentEntry;
784
+ server: McpServerDefinition;
785
+ }): Promise<IntegrationApplyResult>;
786
+ /** Remove only servers owned by the given identity. */
787
+ removeEntry(input: {
788
+ workspaceDir: string;
789
+ identity: string;
790
+ }): Promise<boolean>;
719
791
  }
720
792
  /** 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
-
793
+ export declare class FileHookConfigAdapter implements HookConfigAdapter {
794
+ /** Copy hook scripts and merge registrations under the entry identity. */
795
+ applyHook(input: {
796
+ workspaceDir: string;
797
+ entry: PlannedContentEntry;
798
+ hook: HookDefinition;
799
+ }): Promise<IntegrationApplyResult>;
800
+ /** Remove registrations owned by the identity and orphaned script copies. */
801
+ removeEntry(input: {
802
+ workspaceDir: string;
803
+ identity: string;
804
+ }): Promise<boolean>;
805
+ }
806
+ //#endregion
807
+ //#region src/copilot-content/personal-copilot-content-reconciler.d.ts
735
808
  /** Machine-local materialization state for personal-scope content. */
736
- interface PersonalContentState {
737
- version: 1;
738
- entries: WorkspaceMaterializedEntry[];
809
+ export interface PersonalContentState {
810
+ version: 1;
811
+ entries: WorkspaceMaterializedEntry[];
739
812
  }
740
813
  /** Reconcile result: artifact health keyed by artifact id. */
741
- interface PersonalReconcileResult {
742
- statesByArtifactId: Record<string, CopilotArtifactState>;
814
+ export interface PersonalReconcileResult {
815
+ statesByArtifactId: Record<string, CopilotArtifactState>;
743
816
  }
744
817
  /** Resolves the artifact entries a package contributes. */
745
- type PersonalPackageResolver = (packageId: string) => Promise<ResolvedPluginEntry[]>;
818
+ export type PersonalPackageResolver = (packageId: string) => Promise<ResolvedPluginEntry[]>;
746
819
  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;
820
+ /** SERVICEME home directory holding intent and machine state. */
821
+ homeDir?: string;
822
+ /** Host-verified capabilities; tests inject per-kind presence. */
823
+ capabilities: CopilotHostCapabilities;
824
+ /** Resolves package definitions; defaults to no packages. */
825
+ resolvePackage?: PersonalPackageResolver;
753
826
  }
754
827
  /** 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
-
828
+ export declare class PersonalCopilotContentReconciler {
829
+ private readonly store;
830
+ private readonly capabilities;
831
+ private readonly resolvePackage;
832
+ private readonly statePath;
833
+ constructor(options: PersonalReconcilerOptions);
834
+ /** Read current machine state; empty state when not materialized yet. */
835
+ readState(): Promise<PersonalContentState>;
836
+ /** Inspect current personal state without materializing anything. */
837
+ inspect(): Promise<PersonalReconcileResult>;
838
+ /** Materialize personal intent for all supported kinds on this machine. */
839
+ reconcile(): Promise<PersonalReconcileResult>;
840
+ /** Record local approval for integration content, then re-reconcile. */
841
+ approve(input: {
842
+ artifactIds: string[];
843
+ }): Promise<PersonalReconcileResult>;
844
+ /** Write machine state atomically. */
845
+ private writeState;
846
+ private buildPlan;
847
+ private removeOwnedMaterialization;
848
+ private projectStates;
849
+ }
850
+ //#endregion
851
+ //#region src/copilot-content/personal-installation-store.d.ts
778
852
  /** Persisted personal-scope installation intent. */
779
- interface PersonalInstallationState {
780
- version: 1;
781
- installations: CopilotPackageInstallation[];
853
+ export interface PersonalInstallationState {
854
+ version: 1;
855
+ installations: CopilotPackageInstallation[];
782
856
  }
783
857
  /** 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
-
858
+ export declare class PersonalInstallationStore {
859
+ private readonly homeDir;
860
+ private cachedPath;
861
+ constructor(options?: {
862
+ homeDir?: string;
863
+ });
864
+ /** Absolute intent-file path: SERVICEME_HOME/copilot/personal-installations.json. */
865
+ path(): Promise<string>;
866
+ /** Read intent; empty intent when the file does not exist yet. */
867
+ read(): Promise<PersonalInstallationState>;
868
+ /** Atomically persist intent. */
869
+ write(state: PersonalInstallationState): Promise<void>;
870
+ }
871
+ //#endregion
872
+ //#region src/copilot-content/workspace-copilot-content-reconciler.d.ts
798
873
  /** 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;
874
+ export type WorkspaceContentStatus = "restored" | "adopted" | "pending_approval" | "missing_source" | "conflict" | "drifted";
875
+ export interface WorkspaceContentEntryResult {
876
+ identity: string;
877
+ status: WorkspaceContentStatus;
878
+ message?: string;
804
879
  }
805
- interface WorkspaceContentReconcileResult {
806
- changed: boolean;
807
- entries: WorkspaceContentEntryResult[];
880
+ export interface WorkspaceContentReconcileResult {
881
+ changed: boolean;
882
+ entries: WorkspaceContentEntryResult[];
808
883
  }
809
884
  interface RepositorySource {
810
- ready: boolean;
811
- localPath?: string;
812
- error?: string;
885
+ ready: boolean;
886
+ localPath?: string;
887
+ error?: string;
813
888
  }
814
889
  /** 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
-
890
+ export declare class WorkspaceCopilotContentReconciler {
891
+ private readonly workspaceDir;
892
+ private readonly homeDir;
893
+ private readonly ensureRepository;
894
+ constructor(options: {
895
+ workspaceDir: string;
896
+ homeDir?: string;
897
+ /** Injectable repository ensure step (tests avoid real git). */
898
+ ensureRepository?: (manifest: WorkspaceCopilotManifest) => Promise<Map<string, RepositorySource>>;
899
+ /** Injectable link materializer (transactions share the test seam). */
900
+ materializer?: CopilotLinkMaterializer;
901
+ /** Machine-local disable marks: identities returning true are
902
+ * treated as NOT declared — their materialization is removed and
903
+ * never resurrected, while the manifest declaration itself stays. */
904
+ isDisabled?: (identity: string) => Promise<boolean>;
905
+ });
906
+ private readonly materializer;
907
+ private readonly isDisabled;
908
+ /** Restore declared content on this machine. */
909
+ reconcile(): Promise<WorkspaceContentReconcileResult>;
910
+ /**
911
+ * Reconcile mcp/hook entries through their generated-config adapters.
912
+ * Unapproved or digest-changed entries stay pending without touching
913
+ * host configuration; approved entries are (re)applied; previously
914
+ * materialized identities that left the declaration are removed.
915
+ */
916
+ private reconcileIntegrations;
917
+ /** Build the machine-local state entry for a generated-config integration. */
918
+ private toIntegrationStateEntry;
919
+ /** Record local approval for risky content, then re-reconcile. */
920
+ approve(input: {
921
+ identities: string[];
922
+ }): Promise<WorkspaceContentReconcileResult>;
923
+ private defaultEnsureRepository;
924
+ }
925
+ //#endregion
926
+ //#region src/copilot-content/package-installation-service.d.ts
851
927
  /** 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;
928
+ export interface LegacyMigrationEntry {
929
+ artifactId: string;
930
+ name: string;
931
+ kind: "skill" | "agent";
932
+ eligible: boolean;
933
+ sourcePath: string;
934
+ targetPath: string;
859
935
  }
860
936
  /** 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[]>;
937
+ export interface LegacyMigrationPreview {
938
+ sourceLabel: "~/.agents";
939
+ entries: LegacyMigrationEntry[];
940
+ }
941
+ export interface CopilotPackageInstallInput {
942
+ workspaceDir?: string;
943
+ scope: CopilotScope;
944
+ sourceId: string;
945
+ packageId: string;
946
+ artifactIds: string[];
947
+ pinnedVersion?: string;
948
+ localMode?: "live" | "private-workspace-override";
949
+ }
950
+ export interface CopilotPackageUpdateInput {
951
+ workspaceDir?: string;
952
+ scope: CopilotScope;
953
+ packageId: string;
954
+ artifactIds: string[];
955
+ pinnedVersion?: string;
956
+ }
957
+ export interface CopilotPackageUninstallInput {
958
+ workspaceDir?: string;
959
+ scope: CopilotScope;
960
+ packageId: string;
961
+ }
962
+ export interface CopilotPackageMoveInput {
963
+ workspaceDir?: string;
964
+ packageId: string;
965
+ from: CopilotScope;
966
+ to: CopilotScope;
967
+ }
968
+ export interface PackageInstallationServiceDeps {
969
+ personalStore: PersonalInstallationStore;
970
+ personalReconciler: PersonalCopilotContentReconciler;
971
+ /** Shared materializer so transaction tests can inject failures. */
972
+ materializer?: CopilotLinkMaterializer;
973
+ userHomeDir: string;
974
+ resolvePackage: (packageId: string) => Promise<ResolvedPluginEntry[]>;
975
+ resolveWorkspaceSource: (sourceId: string) => Promise<WorkspaceManifestRepository | undefined>;
976
+ createWorkspaceReconciler: (workspaceDir: string) => WorkspaceCopilotContentReconciler;
977
+ /** Resolve the local reconciliation state path for transaction rollback. */
978
+ getWorkspaceStatePath?: (workspaceDir: string) => Promise<string>;
979
+ readWorkspaceView: (workspaceDir: string) => Promise<CopilotCustomizationView>;
980
+ /** Exact selected workspace artifact identities for the active workspace. */
981
+ readWorkspaceInstallations: (workspaceDir: string) => Promise<CopilotPackageInstallation[]>;
906
982
  }
907
983
  /**
908
984
  * Package lifecycle transactions over the Task 8 personal store /
@@ -914,46 +990,47 @@ interface PackageInstallationServiceDeps {
914
990
  * activation failure the previous destination intent is restored and
915
991
  * the source intent is left untouched.
916
992
  */
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
-
993
+ export declare class PackageInstallationService {
994
+ private readonly deps;
995
+ /** Last preview shown to the caller; migration re-verifies against it. */
996
+ private lastPreview;
997
+ constructor(deps: PackageInstallationServiceDeps);
998
+ install(input: CopilotPackageInstallInput): Promise<CopilotCustomizationView>;
999
+ update(input: CopilotPackageUpdateInput): Promise<CopilotCustomizationView>;
1000
+ uninstall(input: CopilotPackageUninstallInput): Promise<CopilotCustomizationView>;
1001
+ move(input: CopilotPackageMoveInput): Promise<CopilotCustomizationView>;
1002
+ private moveIntoWorkspace;
1003
+ private moveIntoPersonal;
1004
+ previewLegacy(): Promise<LegacyMigrationPreview>;
1005
+ migrateLegacy(input: {
1006
+ artifactIds: string[];
1007
+ }): Promise<CopilotCustomizationView>;
1008
+ private readSourceSelection;
1009
+ private assertArtifactsNotActiveElsewhere;
1010
+ private assertArtifactIdsAbsentFromWorkspace;
1011
+ private assertArtifactIdsAbsentFromInstallations;
1012
+ private assertKindNameFree;
1013
+ private writePersonalIntent;
1014
+ private removePersonalIntent;
1015
+ private upsertWorkspaceSelection;
1016
+ private withWorkspaceActivationRollback;
1017
+ private captureWorkspaceActivation;
1018
+ private captureFile;
1019
+ private restoreWorkspaceActivation;
1020
+ private selectedEntries;
1021
+ private selectEntries;
1022
+ private assertNoActivationConflicts;
1023
+ private assertNoActivationConflictsPersonal;
1024
+ private resolveLegacyTarget;
1025
+ private requireWorkspaceDir;
1026
+ private readPersonalView;
1027
+ }
1028
+ //#endregion
1029
+ //#region src/copilot-content/plugin-catalog-service.d.ts
953
1030
  /** A git source to enumerate. `id` is the managed repos dir entry name. */
954
- interface PluginCatalogRepoInput {
955
- id: string;
956
- enabled?: boolean;
1031
+ export interface PluginCatalogRepoInput {
1032
+ id: string;
1033
+ enabled?: boolean;
957
1034
  }
958
1035
  /**
959
1036
  * An installable plugin.json package found in a source — with the
@@ -961,13 +1038,13 @@ interface PluginCatalogRepoInput {
961
1038
  * install preview can select artifacts without a second resolution
962
1039
  * path.
963
1040
  */
964
- interface PluginCatalogPackage {
965
- packageId: string;
966
- sourceId: string;
967
- displayName: string;
968
- description?: string;
969
- version?: string;
970
- artifacts: CopilotArtifactSummary[];
1041
+ export interface PluginCatalogPackage {
1042
+ packageId: string;
1043
+ sourceId: string;
1044
+ displayName: string;
1045
+ description?: string;
1046
+ version?: string;
1047
+ artifacts: CopilotArtifactSummary[];
971
1048
  }
972
1049
  /**
973
1050
  * Enumerate plugin.json packages across the given git sources.
@@ -979,136 +1056,137 @@ interface PluginCatalogPackage {
979
1056
  * skipped, not thrown — the catalog must stay usable when a single
980
1057
  * plugin is broken.
981
1058
  */
982
- declare function listPluginCatalog(input: {
1059
+ export declare function listPluginCatalog(input: {
1060
+ reposDir: string;
1061
+ repos: PluginCatalogRepoInput[];
1062
+ }): Promise<PluginCatalogPackage[]>;
1063
+ export interface PluginCatalogService {
1064
+ list(input: {
983
1065
  reposDir: string;
984
1066
  repos: PluginCatalogRepoInput[];
985
- }): Promise<PluginCatalogPackage[]>;
986
- interface PluginCatalogService {
987
- list(input: {
988
- reposDir: string;
989
- repos: PluginCatalogRepoInput[];
990
- }): Promise<PluginCatalogPackage[]>;
1067
+ }): Promise<PluginCatalogPackage[]>;
991
1068
  }
992
1069
  /** Factory: one cache per service instance (tests use fresh instances). */
993
- declare function createPluginCatalogService(): PluginCatalogService;
1070
+ export declare function createPluginCatalogService(): PluginCatalogService;
994
1071
  /**
995
1072
  * Single source of truth for entry → artifact-summary mapping. The
996
1073
  * CLI bridge imports this for installed packages too, so the install
997
1074
  * preview's installStrategy/risk can never drift from what the
998
1075
  * catalog shows.
999
1076
  */
1000
- declare function toArtifactSummary(entry: ResolvedPluginEntry): CopilotArtifactSummary;
1001
-
1077
+ export declare function toArtifactSummary(entry: ResolvedPluginEntry): CopilotArtifactSummary;
1078
+ //#endregion
1079
+ //#region src/copilot-content/source-catalog-service.d.ts
1002
1080
  /**
1003
1081
  * Verbatim wire contract for a read-only package update preview.
1004
1082
  * Field names are pinned by Task 10's brief and shared with the
1005
1083
  * protocol / webview layers.
1006
1084
  */
1007
- interface CopilotPackageUpdatePreview {
1008
- packageId: string;
1009
- fromVersion?: string;
1010
- toVersion: string;
1011
- addedArtifactIds: string[];
1012
- removedArtifactIds: string[];
1013
- changedArtifactIds: string[];
1014
- approvalInvalidatedArtifactIds: string[];
1085
+ export interface CopilotPackageUpdatePreview {
1086
+ packageId: string;
1087
+ fromVersion?: string;
1088
+ toVersion: string;
1089
+ addedArtifactIds: string[];
1090
+ removedArtifactIds: string[];
1091
+ changedArtifactIds: string[];
1092
+ approvalInvalidatedArtifactIds: string[];
1015
1093
  }
1016
1094
  /** Normalized source record for diagnostics and the source manager UI. */
1017
- interface CopilotSourceRecord {
1095
+ export interface CopilotSourceRecord {
1096
+ id: string;
1097
+ type: "marketplace" | "git" | "local";
1098
+ displayName: string;
1099
+ updateCapability: "pinned" | "live" | "none";
1100
+ /** Whether the source content is currently materialized on disk. */
1101
+ available: boolean;
1102
+ /** Where this source is declared: "workspace" (manifest), "personal" (intent), or both. */
1103
+ declaredIn: Array<"workspace" | "personal">;
1104
+ }
1105
+ export interface CopilotSourceCatalogDeps {
1106
+ /** SERVICEME home; defaults to the real ~/.serviceme. */
1107
+ homeDir?: string;
1108
+ /** Personal installation intent; consulted by previewUpdate and removeSource. */
1109
+ personalStore: PersonalInstallationStore;
1110
+ /**
1111
+ * Task 9's transaction service owns installations. removeSource
1112
+ * coordinates with it only indirectly: it refuses while any
1113
+ * installation (workspace or personal) still uses the source.
1114
+ */
1115
+ installationService?: PackageInstallationService;
1116
+ /**
1117
+ * Resolves artifacts for a package at a revision; defaults to a
1118
+ * no-content resolver so an unresolvable source yields empty diff
1119
+ * lists rather than a crash.
1120
+ */
1121
+ resolvePackage?: (packageId: string, revision?: string) => Promise<ResolvedPluginEntry[]>;
1122
+ /**
1123
+ * Round 3: workspace declarations enable artifact kinds, not named
1124
+ * artifacts. This predicate reports whether a resolved entry matches a
1125
+ * selection marker produced for an enabled kind. Implementations may
1126
+ * match exact ids or kind prefixes; default behavior matches only
1127
+ * exact ids (personal-intent semantics).
1128
+ */
1129
+ artifactSelected?: (marker: string, artifactId: string) => boolean;
1130
+ /**
1131
+ * Finding 4 honesty: returns the revision actually resolved by
1132
+ * resolvePackage for a given requested revision. When a resolver can
1133
+ * only read the working tree, this lets previewUpdate label toVersion
1134
+ * with what was truly diffed instead of the requested target.
1135
+ */
1136
+ resolveActualRevision?: (packageId: string, revision: string) => Promise<string | undefined>;
1137
+ /** Source ids declared by the workspace manifest for a directory. */
1138
+ listWorkspaceSources: (workspaceDir: string) => Promise<string[]>;
1139
+ /**
1140
+ * Workspace-scope installations for a directory, read through Task 9's
1141
+ * view projection. Both previewUpdate and removeSource honor personal
1142
+ * AND workspace installations; without this a workspace-declared source
1143
+ * with no personal intent could be deleted while still in use.
1144
+ */
1145
+ readWorkspaceInstallations?: (workspaceDir: string) => Promise<CopilotPackageInstallation[]>;
1146
+ /** Classifies a source id as a marketplace catalog source. */
1147
+ isCatalogSource?: (sourceId: string, workspaceDir?: string) => boolean | Promise<boolean>;
1148
+ /**
1149
+ * Task 10 ruling #1: materialize a v2 catalog source under
1150
+ * repos/<sourceId> so availability is a plain directory check.
1151
+ * listSources invokes this for unavailable catalog sources before
1152
+ * reporting diagnostics.
1153
+ */
1154
+ ensureCatalogSource?: (sourceId: string) => Promise<{
1155
+ localPath: string;
1156
+ }>;
1157
+ /**
1158
+ * Round 2 / Minor 2: reports whether a staged catalog directory
1159
+ * actually contains payload. Staging only creates the directory; a
1160
+ * payload check must gate availability so an empty staged dir is
1161
+ * never reported as available.
1162
+ */
1163
+ hasCatalogPayload?: (localPath: string) => Promise<boolean>;
1164
+ /** Classifies a source id as a personal local source. */
1165
+ isLocalSource?: (sourceId: string) => boolean | Promise<boolean>;
1166
+ /**
1167
+ * ReposStore (repos.json) entries on this machine — built-in default
1168
+ * repos plus user-added git repos. The source manager is the single
1169
+ * repository management surface, so every store entry must appear in
1170
+ * the listing even when it is neither workspace-declared nor
1171
+ * personally installed. Entries with an empty declaredIn are
1172
+ * store-only. Also supplies human display names for store sources.
1173
+ */
1174
+ listStoreSources?: () => Promise<Array<{
1018
1175
  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
- }>>;
1176
+ name?: string;
1177
+ enabled?: boolean;
1178
+ }>>;
1101
1179
  }
1102
- interface CopilotSourceCatalogQuery {
1103
- workspaceDir?: string;
1104
- scope?: CopilotScope;
1180
+ export interface CopilotSourceCatalogQuery {
1181
+ workspaceDir?: string;
1182
+ scope?: CopilotScope;
1105
1183
  }
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;
1184
+ export interface CopilotUpdatePreviewInput {
1185
+ workspaceDir?: string;
1186
+ scope?: CopilotScope;
1187
+ packageId: string;
1188
+ /** Target revision (full 40-char commit for git sources, immutable catalog revision otherwise). */
1189
+ revision: string;
1112
1190
  }
1113
1191
  /**
1114
1192
  * Normalized Marketplace / Git / local source discovery plus
@@ -1121,41 +1199,152 @@ interface CopilotUpdatePreviewInput {
1121
1199
  * or the "private-workspace-override" mode enforced downstream by the
1122
1200
  * install transaction.
1123
1201
  */
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
-
1202
+ export declare class CopilotSourceCatalogService {
1203
+ private readonly deps;
1204
+ private readonly reposDir;
1205
+ constructor(deps: CopilotSourceCatalogDeps);
1206
+ /**
1207
+ * List normalized sources for the query: every source declared by
1208
+ * the workspace manifest (when a workspaceDir is given) plus every
1209
+ * source referenced by personal installation intent, plus every
1210
+ * ReposStore entry on this machine (built-in default repos and
1211
+ * user-added git repos) so the source manager can manage them.
1212
+ */
1213
+ listSources(query: CopilotSourceCatalogQuery): Promise<CopilotSourceRecord[]>;
1214
+ /**
1215
+ * Confirms Task 4's materialization assumption for every source
1216
+ * kind: v2 catalog sources materialize under reposDir/<source-id>
1217
+ * exactly like git checkouts, so availability is a directory check.
1218
+ */
1219
+ isSourceAvailable(sourceId: string): Promise<boolean>;
1220
+ /**
1221
+ * Deterministic, side-effect-free update preview: compares the
1222
+ * currently-selected artifacts against what the target revision
1223
+ * resolves to, and reports which approval-gated artifacts would
1224
+ * need re-approval. Never writes intent; the pinned version stays
1225
+ * untouched until the caller runs the update transaction.
1226
+ */
1227
+ previewUpdate(input: CopilotUpdatePreviewInput): Promise<CopilotPackageUpdatePreview>;
1228
+ /**
1229
+ * Remove a source only when nothing references it: no workspace
1230
+ * declaration and no installation (workspace or personal) may still
1231
+ * use it. Refusals match /installed package/i and /workspace/ so
1232
+ * callers can surface distinct remediation paths.
1233
+ */
1234
+ removeSource(sourceId: string, workspaceDir?: string): Promise<void>;
1235
+ }
1236
+ //#endregion
1237
+ //#region src/copilot-content/workspace-content-detector.d.ts
1238
+ /**
1239
+ * Workspace content detection — the adoption inverse of the restore
1240
+ * flow. When a workspace carries Copilot content (`.github` skill/agent
1241
+ * entries, generated hook/MCP configuration) but has NO
1242
+ * `.github/serviceme-plugins.json` declaration, this module derives
1243
+ * what is there and where it came from, so the user can initialize the
1244
+ * declaration from existing content instead of reinstalling by hand.
1245
+ *
1246
+ * Provenance rules:
1247
+ * - symlinks under `.github/{skills,agents}` resolve their repo from
1248
+ * the target path (`<reposDir>/<repoId>/...`) — exact;
1249
+ * - real (non-symlink) copies are fingerprinted (deterministic
1250
+ * SHA-256 over the sorted tree/file bytes) and matched against the
1251
+ * repo catalog by name: a unique content match is adoptable,
1252
+ * several matching repos need a user pick, none is unmatched;
1253
+ * - `.vscode/{hooks,mcp}.serviceme.json` carry the generating
1254
+ * identity map under `_serviceme`, which is parsed directly.
1255
+ */
1256
+ /** Minimal catalog row the detector matches fingerprints against. */
1257
+ export interface DetectorCatalogEntry {
1258
+ repoId: string;
1259
+ name: string;
1260
+ kind: "skill" | "agent";
1261
+ /** Directory of the entry, or the manifest path itself for flat files. */
1262
+ dir: string;
1263
+ manifestPath: string;
1264
+ }
1265
+ /** A skill/agent whose source repo is known and can be adopted as-is. */
1266
+ export interface UnmanagedAdoption {
1267
+ repoId: string;
1268
+ name: string;
1269
+ kind: "skill" | "agent";
1270
+ /** "symlink" — provenance exact from the link target;
1271
+ * "fingerprint" — real copy with a unique catalog content match. */
1272
+ source: "symlink" | "fingerprint";
1273
+ }
1274
+ /** A real copy whose content matches several repos — needs a pick. */
1275
+ export interface UnmanagedAmbiguous {
1276
+ name: string;
1277
+ kind: "skill" | "agent";
1278
+ /** Repo ids whose catalog content is byte-identical. */
1279
+ candidates: string[];
1280
+ }
1281
+ /** A hook/MCP integration recorded in a generated serviceme config. */
1282
+ export interface UnmanagedIntegration {
1283
+ repoId: string;
1284
+ pluginId: string;
1285
+ kind: "hook" | "mcp";
1286
+ }
1287
+ export interface UnmanagedDetection {
1288
+ adoptions: UnmanagedAdoption[];
1289
+ ambiguous: UnmanagedAmbiguous[];
1290
+ integrations: UnmanagedIntegration[];
1291
+ /** Present but not adoptable — surfaced for transparency only. The
1292
+ * reason is a plain string so protocol-wire results are assignable. */
1293
+ unmatched: Array<{
1294
+ name: string;
1295
+ kind: string;
1296
+ reason: string;
1297
+ }>;
1298
+ }
1299
+ /** Stable signature of a detection — powers the dismissal memory. */
1300
+ export declare function unmanagedDetectionSignature(detection: UnmanagedDetection): string;
1301
+ /** `skill:hello-skill`-style targets a plugin manifest declares. */
1302
+ export declare function coveredTargetsOf(manifest: Record<string, unknown>): Set<string>;
1303
+ /**
1304
+ * Find the plugin under `<repoRoot>/plugins/` whose plugin.json
1305
+ * already declares `kind:name` — e.g. plugin `hello` covering
1306
+ * skill `hello-skill`. Per-artifact installs of covered content must
1307
+ * declare through the COVERING plugin, otherwise the standalone
1308
+ * selection collides with the plugin on the next reconcile.
1309
+ * Coverage comes from EITHER the manifest's extension path arrays OR
1310
+ * (for namespace-less "Create Plugin" manifests, where the resolver derives
1311
+ * content from directory conventions) the plugin dir's own
1312
+ * skills/agents subdirs. Returns null when no plugin covers it.
1313
+ */
1314
+ export declare function findPluginCoveringArtifact(repoRoot: string, kind: "skill" | "agent", name: string): Promise<string | null>;
1315
+ /**
1316
+ * Drop adoption entries whose target a sibling entry's plugin.json
1317
+ * already declares. Adopting `agent hello` registers plugin `hello`,
1318
+ * whose manifest also covers `skill hello-skill` — keeping the
1319
+ * standalone skill entry would create a duplicate-target conflict on
1320
+ * the next reconcile. Pure: manifests are passed in by the caller.
1321
+ */
1322
+ export declare function dedupeAdoptionsByPluginManifests<T extends {
1323
+ repoId: string;
1324
+ name: string;
1325
+ kind: "skill" | "agent";
1326
+ }>(entries: T[], pluginManifests: Map<string, Record<string, unknown>>): {
1327
+ kept: T[];
1328
+ dropped: Array<{
1329
+ entry: T;
1330
+ coveredBy: string;
1331
+ }>;
1332
+ };
1333
+ /**
1334
+ * Detect unmanaged Copilot content in a workspace. Read-only: nothing
1335
+ * is written or linked; the caller decides what to adopt.
1336
+ */
1337
+ export declare function detectUnmanagedWorkspaceContent(input: {
1338
+ workspaceDir: string;
1339
+ /** SERVICEME repos root (`~/.serviceme/repos`). */
1340
+ reposDir: string;
1341
+ /** Catalog rows (from SkillStore.listAll()). */
1342
+ catalog: DetectorCatalogEntry[];
1343
+ /** Enabled repo ids — targets/integrations outside them are unmatched. */
1344
+ knownRepoIds: Set<string>;
1345
+ }): Promise<UnmanagedDetection>;
1346
+ //#endregion
1347
+ //#region src/copilot-content/workspace-declaration-reader.d.ts
1159
1348
  /**
1160
1349
  * Read the workspace manifest’s declared package selections without resolving
1161
1350
  * sources. Source resolution can fail (unavailable source, conflict), and
@@ -1165,41 +1354,43 @@ declare class CopilotSourceCatalogService {
1165
1354
  * manifests surface the load error rather than pretending nothing is
1166
1355
  * declared.
1167
1356
  */
1168
- declare function readDeclaredWorkspaceInstallations(workspaceDir: string): Promise<CopilotPackageInstallation[]>;
1169
-
1357
+ export declare function readDeclaredWorkspaceInstallations(workspaceDir: string): Promise<CopilotPackageInstallation[]>;
1358
+ //#endregion
1359
+ //#region src/copilot-content/workspace-exclude-store.d.ts
1170
1360
  /** 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
-
1361
+ export declare class WorkspaceExcludeStore {
1362
+ private readonly workspaceDir;
1363
+ private readonly resolveGitExcludePath;
1364
+ constructor(options: {
1365
+ workspaceDir: string;
1366
+ /** Override exclude-path resolution (tests, linked-worktree handling). */
1367
+ resolveGitExcludePath?: (workspaceDir: string) => Promise<string>;
1368
+ });
1369
+ /** Resolve the worktree-aware exclude file managed by this store. */
1370
+ path(): Promise<string>;
1371
+ /** Replace the managed block so it contains exactly the given paths. */
1372
+ reconcile(paths: string[]): Promise<void>;
1373
+ }
1374
+ //#endregion
1375
+ //#region src/copilot-content/workspace-manifest.d.ts
1185
1376
  /** Location of the shared declaration inside a workspace. */
1186
- declare const WORKSPACE_MANIFEST_RELPATH: string;
1377
+ export declare const WORKSPACE_MANIFEST_RELPATH: string;
1187
1378
  /** Absolute path of the declaration file inside a workspace. */
1188
- declare function getWorkspaceManifestPath(workspaceDir: string): string;
1379
+ export declare function getWorkspaceManifestPath(workspaceDir: string): string;
1189
1380
  /** Read and validate the declaration; undefined when absent. */
1190
- declare function loadWorkspaceCopilotManifest(workspaceDir: string): Promise<WorkspaceCopilotManifest | undefined>;
1381
+ export declare function loadWorkspaceCopilotManifest(workspaceDir: string): Promise<WorkspaceCopilotManifest | undefined>;
1191
1382
  /** Validate and atomically write the shared declaration. */
1192
- declare function writeWorkspaceCopilotManifest(workspaceDir: string, manifest: WorkspaceCopilotManifest): Promise<void>;
1383
+ export declare function writeWorkspaceCopilotManifest(workspaceDir: string, manifest: WorkspaceCopilotManifest): Promise<void>;
1193
1384
  /**
1194
1385
  * Atomically replace one package selection with exact resolver artifact IDs.
1195
1386
  * New selections clear legacy kind maps so future resolution remains stable
1196
1387
  * if a package adds another artifact of an existing kind.
1197
1388
  */
1198
- declare function replaceWorkspaceContentSelection(input: {
1199
- workspaceDir: string;
1200
- repository: WorkspaceManifestRepository;
1201
- pluginId: string;
1202
- artifactIds: string[];
1389
+ export declare function replaceWorkspaceContentSelection(input: {
1390
+ workspaceDir: string;
1391
+ repository: WorkspaceManifestRepository;
1392
+ pluginId: string;
1393
+ artifactIds: string[];
1203
1394
  }): Promise<WorkspaceCopilotManifest>;
1204
1395
  /**
1205
1396
  * Add or update one artifact-kind selection (any of the six kinds) in the
@@ -1210,45 +1401,64 @@ declare function replaceWorkspaceContentSelection(input: {
1210
1401
  * the plugin selection so install flows never race a concurrent write
1211
1402
  * of unrelated selections.
1212
1403
  */
1213
- declare function upsertWorkspaceContentSelection(input: {
1214
- workspaceDir: string;
1215
- repository: WorkspaceManifestRepository;
1216
- pluginId: string;
1217
- kind: CopilotArtifactKind;
1404
+ export declare function upsertWorkspaceContentSelection(input: {
1405
+ workspaceDir: string;
1406
+ repository: WorkspaceManifestRepository;
1407
+ pluginId: string;
1408
+ kind: CopilotArtifactKind;
1218
1409
  }): Promise<WorkspaceCopilotManifest>;
1219
1410
  /**
1220
1411
  * Remove one artifact kind from a plugin selection, dropping
1221
1412
  * the plugin entirely when no artifact kind remains enabled. Returns
1222
1413
  * the new manifest; a no-op when the selection does not exist.
1223
1414
  */
1224
- declare function removeWorkspaceContentSelection(input: {
1225
- workspaceDir: string;
1226
- repositoryId: string;
1227
- pluginId: string;
1228
- kind: CopilotArtifactKind;
1415
+ export declare function removeWorkspaceContentSelection(input: {
1416
+ workspaceDir: string;
1417
+ repositoryId: string;
1418
+ pluginId: string;
1419
+ kind: CopilotArtifactKind;
1229
1420
  }): Promise<WorkspaceCopilotManifest>;
1230
-
1421
+ /**
1422
+ * Record or clear one content target (`kind:name`) in a plugin
1423
+ * selection's `disabledArtifacts` — the shared-declaration form of the
1424
+ * per-artifact enable switch. Unlike the machine-local disable marks,
1425
+ * this survives extension reloads and machine-local state loss, so the
1426
+ * package/entry badges stay consistent with what the user disabled.
1427
+ * No-op (returns the loaded manifest unchanged) when the selection
1428
+ * does not exist.
1429
+ */
1430
+ export declare function setWorkspacePluginArtifactsDisabled(input: {
1431
+ workspaceDir: string;
1432
+ repositoryId: string;
1433
+ pluginId: string;
1434
+ /** Content target, e.g. `agent:hello`. */
1435
+ target: string;
1436
+ disabled: boolean;
1437
+ }): Promise<WorkspaceCopilotManifest | undefined>;
1438
+ //#endregion
1439
+ //#region src/copilot-content/workspace-state-store.d.ts
1231
1440
  /** Hash a canonical workspace path into a stable directory segment. */
1232
- declare function hashWorkspaceDir(workspaceDir: string): Promise<string>;
1441
+ export declare function hashWorkspaceDir(workspaceDir: string): Promise<string>;
1233
1442
  /** Directory holding machine-local state for one workspace. */
1234
- declare function getWorkspaceStateDir(workspaceDir: string, homeDir?: string): Promise<string>;
1443
+ export declare function getWorkspaceStateDir(workspaceDir: string, homeDir?: string): Promise<string>;
1235
1444
  /** 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
-
1445
+ export declare class WorkspaceContentStateStore {
1446
+ private readonly workspaceDir;
1447
+ private readonly homeDir;
1448
+ private cachedPath;
1449
+ constructor(options: {
1450
+ workspaceDir: string;
1451
+ homeDir?: string;
1452
+ });
1453
+ /** Absolute state-file path for this workspace. */
1454
+ path(): Promise<string>;
1455
+ /** Read state; an empty state when the file does not exist yet. */
1456
+ read(): Promise<WorkspaceContentState>;
1457
+ /** Atomically persist state. */
1458
+ write(state: WorkspaceContentState): Promise<void>;
1459
+ }
1460
+ //#endregion
1461
+ //#region src/drafts/index.d.ts
1252
1462
  /**
1253
1463
  * Skill & Agent v2 — Drafts (M4)
1254
1464
  *
@@ -1272,42 +1482,42 @@ declare class WorkspaceContentStateStore {
1272
1482
  * @see docs/architecture/skill-agent-v2-repo.md §2.1 (drafts layout),
1273
1483
  * §5.7 SubmitClient (consumer).
1274
1484
  */
1275
- interface DraftSummary {
1276
- /** Random id (16 hex chars). */
1277
- id: string;
1278
- kind: SkillKind;
1279
- /** Path to the manifest file (SKILL.md or AGENT.md). */
1280
- manifestPath: string;
1281
- /** Path to the directory containing the draft's files. */
1282
- dir: string;
1283
- /** Best-effort name from the frontmatter (empty string when absent). */
1284
- name: string;
1285
- /** Best-effort description from the frontmatter (empty string when absent). */
1286
- description: string;
1287
- /** ISO timestamp of the manifest file's mtime. */
1288
- modifiedAt: string;
1289
- }
1290
- interface DraftDetail extends DraftSummary {
1291
- files: SkillFile[];
1292
- }
1293
- interface SaveDraftOptions {
1294
- kind: SkillKind;
1295
- /** Existing draft id; omit to create a new draft. */
1296
- id?: string;
1297
- /** Files to write. Must include a manifest (SKILL.md or AGENT.md). */
1298
- files: SkillFile[];
1485
+ export interface DraftSummary {
1486
+ /** Random id (16 hex chars). */
1487
+ id: string;
1488
+ kind: SkillKind;
1489
+ /** Path to the manifest file (SKILL.md or AGENT.md). */
1490
+ manifestPath: string;
1491
+ /** Path to the directory containing the draft's files. */
1492
+ dir: string;
1493
+ /** Best-effort name from the frontmatter (empty string when absent). */
1494
+ name: string;
1495
+ /** Best-effort description from the frontmatter (empty string when absent). */
1496
+ description: string;
1497
+ /** ISO timestamp of the manifest file's mtime. */
1498
+ modifiedAt: string;
1499
+ }
1500
+ export interface DraftDetail extends DraftSummary {
1501
+ files: SkillFile[];
1502
+ }
1503
+ export interface SaveDraftOptions {
1504
+ kind: SkillKind;
1505
+ /** Existing draft id; omit to create a new draft. */
1506
+ id?: string;
1507
+ /** Files to write. Must include a manifest (SKILL.md or AGENT.md). */
1508
+ files: SkillFile[];
1299
1509
  }
1300
1510
  /** Sentinel errors. */
1301
- declare class DraftsError extends Error {
1302
- constructor(message: string);
1511
+ export declare class DraftsError extends Error {
1512
+ constructor(message: string);
1303
1513
  }
1304
- declare class DraftNotFoundError extends DraftsError {
1305
- readonly kind: SkillKind;
1306
- readonly id: string;
1307
- constructor(kind: SkillKind, id: string);
1514
+ export declare class DraftNotFoundError extends DraftsError {
1515
+ readonly kind: SkillKind;
1516
+ readonly id: string;
1517
+ constructor(kind: SkillKind, id: string);
1308
1518
  }
1309
- declare class InvalidDraftError extends DraftsError {
1310
- constructor(message: string);
1519
+ export declare class InvalidDraftError extends DraftsError {
1520
+ constructor(message: string);
1311
1521
  }
1312
1522
  /**
1313
1523
  * Generate a short random hex id. Uses Node's `crypto.randomBytes` so
@@ -1315,137 +1525,142 @@ declare class InvalidDraftError extends DraftsError {
1315
1525
  * entropy. We don't promise uniqueness (collisions exist with
1316
1526
  * astronomically low probability) — callers must treat ids as opaque.
1317
1527
  */
1318
- declare function generateDraftId(): string;
1528
+ export declare function generateDraftId(): string;
1319
1529
  /**
1320
1530
  * Resolve the on-disk directory for a draft of a given kind + id.
1321
1531
  * Exported for tests + the SubmitClient which writes the committed
1322
1532
  * files into the repo.
1323
1533
  */
1324
- declare function resolveDraftDir(kind: SkillKind, id: string): string;
1534
+ export declare function resolveDraftDir(kind: SkillKind, id: string): string;
1325
1535
  /**
1326
1536
  * Persistent draft store backed by the local filesystem. Pure local —
1327
1537
  * no network, no git, no DB.
1328
1538
  */
1329
- declare class DraftsStore {
1330
- /**
1331
- * List every draft of the given kind. Returns [] when the drafts
1332
- * directory doesn't exist (cold start, never-saved state).
1333
- */
1334
- list(kind: SkillKind): Promise<DraftSummary[]>;
1335
- /** Single draft summary (manifest + metadata). Returns null when missing. */
1336
- tryReadSummary(kind: SkillKind, id: string): Promise<DraftSummary | null>;
1337
- /** Single draft detail (summary + all files). Throws when missing. */
1338
- get(kind: SkillKind, id: string): Promise<DraftDetail>;
1339
- /** All files in a draft (manifest + extras), recursively. */
1340
- getFiles(kind: SkillKind, id: string): Promise<SkillFile[]>;
1341
- /**
1342
- * Create-or-update a draft. Returns the (possibly new) draft id.
1343
- * Throws `InvalidDraftError` when the file list does not include
1344
- * a manifest.
1345
- */
1346
- save(opts: SaveDraftOptions): Promise<string>;
1347
- /** Delete a draft. ENOENT is silently ignored (idempotent). */
1348
- delete(kind: SkillKind, id: string): Promise<void>;
1349
- /** Best-effort cleanup of `.tmp-*` orphan files in the draft dir. */
1350
- private sweepTmp;
1351
- }
1352
-
1539
+ export declare class DraftsStore {
1540
+ /**
1541
+ * List every draft of the given kind. Returns [] when the drafts
1542
+ * directory doesn't exist (cold start, never-saved state).
1543
+ */
1544
+ list(kind: SkillKind): Promise<DraftSummary[]>;
1545
+ /** Single draft summary (manifest + metadata). Returns null when missing. */
1546
+ tryReadSummary(kind: SkillKind, id: string): Promise<DraftSummary | null>;
1547
+ /** Single draft detail (summary + all files). Throws when missing. */
1548
+ get(kind: SkillKind, id: string): Promise<DraftDetail>;
1549
+ /** All files in a draft (manifest + extras), recursively. */
1550
+ getFiles(kind: SkillKind, id: string): Promise<SkillFile[]>;
1551
+ /**
1552
+ * Create-or-update a draft. Returns the (possibly new) draft id.
1553
+ * Throws `InvalidDraftError` when the file list does not include
1554
+ * a manifest.
1555
+ */
1556
+ save(opts: SaveDraftOptions): Promise<string>;
1557
+ /** Delete a draft. ENOENT is silently ignored (idempotent). */
1558
+ delete(kind: SkillKind, id: string): Promise<void>;
1559
+ /** Best-effort cleanup of `.tmp-*` orphan files in the draft dir. */
1560
+ private sweepTmp;
1561
+ }
1562
+ //#endregion
1563
+ //#region src/process/runCommand.d.ts
1353
1564
  interface RunCommandOptions {
1354
- args?: string[];
1355
- cwd?: string;
1356
- env?: NodeJS.ProcessEnv;
1357
- timeoutMs?: number;
1358
- stdin?: string;
1359
- shell?: boolean;
1565
+ args?: string[];
1566
+ cwd?: string;
1567
+ env?: NodeJS.ProcessEnv;
1568
+ timeoutMs?: number;
1569
+ stdin?: string;
1570
+ shell?: boolean;
1360
1571
  }
1361
1572
  interface RunCommandResult {
1362
- stdout: string;
1363
- stderr: string;
1364
- code: number;
1573
+ stdout: string;
1574
+ stderr: string;
1575
+ code: number;
1365
1576
  }
1366
1577
  declare function runCommand(command: string, options?: RunCommandOptions): Promise<RunCommandResult>;
1367
-
1368
- interface EnvironmentInspectorOptions {
1369
- /**
1370
- * Override the command runner. Production callers should leave this
1371
- * undefined and rely on the default `runCommand` from `../process/runCommand`;
1372
- * tests inject a fake to drive error/edge branches without spawning
1373
- * real subprocesses.
1374
- */
1375
- runCommand?: typeof runCommand;
1376
- /**
1377
- * Override the detected platform. Defaults to `process.platform`. Tests
1378
- * use this to exercise the Windows-specific branches of the inspector.
1379
- */
1380
- platform?: NodeJS.Platform;
1381
- /**
1382
- * Override the value returned by `$SHELL` for POSIX login-shell
1383
- * fallbacks. Defaults to `process.env.SHELL`. Tests pin this so the
1384
- * fallback chain stays deterministic regardless of the developer's
1385
- * host machine.
1386
- */
1387
- shell?: string;
1388
- }
1389
- declare class EnvironmentInspector {
1390
- private readonly runCommandFn;
1391
- private readonly platform;
1392
- private readonly shell;
1393
- /**
1394
- * Per-check-cycle result cache. `checkEnvironment()` clears it before
1395
- * probing so a fresh cycle never returns stale results, while concurrent
1396
- * or repeated `checkTool()` calls within the same cycle share one probe
1397
- * (deduplicating expensive login-shell fallbacks).
1398
- */
1399
- private readonly toolCheckCache;
1400
- constructor(options?: EnvironmentInspectorOptions);
1401
- checkEnvironment(): Promise<EnvironmentCheckResult>;
1402
- checkTool(toolName: KnownEnvironmentTool): Promise<ToolCheckResult>;
1403
- private performToolCheck;
1404
- private getToolPath;
1405
- private getToolPathFromLoginShell;
1406
- /**
1407
- * On Windows, prefer the `.cmd` shim for npm/pnpm/nrm. nvm4w registers
1408
- * BOTH an extensionless entry (pointing to node.exe) and a `<tool>.cmd`
1409
- * wrapper; `where` returns them in that order, and the extensionless one
1410
- * would just print node's own version.
1411
- */
1412
- private getToolShimPath;
1413
- private getToolVersion;
1414
- private shouldUsePosixLoginShellFallback;
1415
- private checkNvm;
1416
- /**
1417
- * Resolve `nvm.sh` from `$NVM_DIR` and the known install roots without
1418
- * spawning a shell. Returns undefined when nvm is not installed in any
1419
- * well-known location, letting callers skip a login-shell probe.
1420
- */
1421
- private resolveNvmShPath;
1422
- private checkNuget;
1423
- private getVersionInvocation;
1424
- private getToolTimeout;
1425
- private parseVersion;
1426
- private handleToolCheckError;
1427
- }
1428
-
1429
- declare class ImageTools {
1430
- getSupportedFormats(): string[];
1431
- validate(filePath: string, sharpModulePath?: string): Promise<ServiceMeImageValidationResult>;
1432
- getInfo(imagePath: string, sharpModulePath?: string): Promise<ServiceMeImageInfo>;
1433
- compress(imagePath: string, options: ServiceMeImageCompressOptions): Promise<ServiceMeImageCompressResult>;
1434
- private compressWithSharp;
1435
- private getOutputPath;
1436
- private pathExists;
1437
- private loadSharp;
1438
- }
1439
- declare function createImageTools(): ImageTools;
1440
-
1441
- interface JsonTools {
1442
- sort(text: string, options?: Partial<JsonSortOptions>): string;
1443
- format(text: string, indent?: number): string;
1444
- validate(text: string): JsonValidationResult;
1445
- minify(text: string): string;
1446
- }
1447
- declare function createJsonTools(): JsonTools;
1448
-
1578
+ //#endregion
1579
+ //#region src/env/environmentInspector.d.ts
1580
+ export interface EnvironmentInspectorOptions {
1581
+ /**
1582
+ * Override the command runner. Production callers should leave this
1583
+ * undefined and rely on the default `runCommand` from `../process/runCommand`;
1584
+ * tests inject a fake to drive error/edge branches without spawning
1585
+ * real subprocesses.
1586
+ */
1587
+ runCommand?: typeof runCommand;
1588
+ /**
1589
+ * Override the detected platform. Defaults to `process.platform`. Tests
1590
+ * use this to exercise the Windows-specific branches of the inspector.
1591
+ */
1592
+ platform?: NodeJS.Platform;
1593
+ /**
1594
+ * Override the value returned by `$SHELL` for POSIX login-shell
1595
+ * fallbacks. Defaults to `process.env.SHELL`. Tests pin this so the
1596
+ * fallback chain stays deterministic regardless of the developer's
1597
+ * host machine.
1598
+ */
1599
+ shell?: string;
1600
+ }
1601
+ export declare class EnvironmentInspector {
1602
+ private readonly runCommandFn;
1603
+ private readonly platform;
1604
+ private readonly shell;
1605
+ /**
1606
+ * Per-check-cycle result cache. `checkEnvironment()` clears it before
1607
+ * probing so a fresh cycle never returns stale results, while concurrent
1608
+ * or repeated `checkTool()` calls within the same cycle share one probe
1609
+ * (deduplicating expensive login-shell fallbacks).
1610
+ */
1611
+ private readonly toolCheckCache;
1612
+ constructor(options?: EnvironmentInspectorOptions);
1613
+ checkEnvironment(): Promise<EnvironmentCheckResult>;
1614
+ checkTool(toolName: KnownEnvironmentTool): Promise<ToolCheckResult>;
1615
+ private performToolCheck;
1616
+ private getToolPath;
1617
+ private getToolPathFromLoginShell;
1618
+ /**
1619
+ * On Windows, prefer the `.cmd` shim for npm/pnpm/nrm. nvm4w registers
1620
+ * BOTH an extensionless entry (pointing to node.exe) and a `<tool>.cmd`
1621
+ * wrapper; `where` returns them in that order, and the extensionless one
1622
+ * would just print node's own version.
1623
+ */
1624
+ private getToolShimPath;
1625
+ private getToolVersion;
1626
+ private shouldUsePosixLoginShellFallback;
1627
+ private checkNvm;
1628
+ /**
1629
+ * Resolve `nvm.sh` from `$NVM_DIR` and the known install roots without
1630
+ * spawning a shell. Returns undefined when nvm is not installed in any
1631
+ * well-known location, letting callers skip a login-shell probe.
1632
+ */
1633
+ private resolveNvmShPath;
1634
+ private checkNuget;
1635
+ private getVersionInvocation;
1636
+ private getToolTimeout;
1637
+ private parseVersion;
1638
+ private handleToolCheckError;
1639
+ }
1640
+ //#endregion
1641
+ //#region src/image/imageTools.d.ts
1642
+ export declare class ImageTools {
1643
+ getSupportedFormats(): string[];
1644
+ validate(filePath: string, sharpModulePath?: string): Promise<ServiceMeImageValidationResult>;
1645
+ getInfo(imagePath: string, sharpModulePath?: string): Promise<ServiceMeImageInfo>;
1646
+ compress(imagePath: string, options: ServiceMeImageCompressOptions): Promise<ServiceMeImageCompressResult>;
1647
+ private compressWithSharp;
1648
+ private getOutputPath;
1649
+ private pathExists;
1650
+ private loadSharp;
1651
+ }
1652
+ export declare function createImageTools(): ImageTools;
1653
+ //#endregion
1654
+ //#region src/json/jsonTools.d.ts
1655
+ export interface JsonTools {
1656
+ sort(text: string, options?: Partial<JsonSortOptions>): string;
1657
+ format(text: string, indent?: number): string;
1658
+ validate(text: string): JsonValidationResult;
1659
+ minify(text: string): string;
1660
+ }
1661
+ export declare function createJsonTools(): JsonTools;
1662
+ //#endregion
1663
+ //#region src/paths/userHome.d.ts
1449
1664
  /**
1450
1665
  * SERVICEME user home directory helpers.
1451
1666
  *
@@ -1458,38 +1673,38 @@ declare function createJsonTools(): JsonTools;
1458
1673
  * exercise the path logic without touching the real user environment.
1459
1674
  */
1460
1675
  /** Layout constants — kept in one place so other modules can reuse them. */
1461
- declare const SERVICEME_DIR_NAME = ".serviceme";
1462
- declare const REPOS_SUBDIR = "repos";
1463
- declare const CACHE_SUBDIR = "cache";
1464
- declare const DRAFTS_SUBDIR = "drafts";
1465
- declare const SKILL_DRAFTS_SUBDIR = "skills";
1466
- declare const AGENT_DRAFTS_SUBDIR = "agents";
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";
1676
+ export declare const SERVICEME_DIR_NAME = ".serviceme";
1677
+ export declare const REPOS_SUBDIR = "repos";
1678
+ export declare const CACHE_SUBDIR = "cache";
1679
+ export declare const DRAFTS_SUBDIR = "drafts";
1680
+ export declare const SKILL_DRAFTS_SUBDIR = "skills";
1681
+ export declare const AGENT_DRAFTS_SUBDIR = "agents";
1682
+ export declare const REPOS_CONFIG_FILENAME = "repos.json";
1683
+ export declare const WORKSPACES_SUBDIR = "workspaces";
1684
+ export declare const WORKSPACE_CONTENT_STATE_FILENAME = "copilot-content-state.json";
1470
1685
  /** rev.20 — r7 BYOM Server Proxy toggle self-state (read by ext + CLI + server). */
1471
- declare const SERVER_PROXY_GLOBAL_FILENAME = "server-proxy.json";
1686
+ export declare const SERVER_PROXY_GLOBAL_FILENAME = "server-proxy.json";
1472
1687
  /**
1473
1688
  * Repo id regex — used to validate any `repoId` argument before it is joined
1474
1689
  * into a filesystem path. Keeps path traversal attempts out and gives us a
1475
1690
  * predictable on-disk shape.
1476
1691
  */
1477
- declare const SAFE_REPO_ID_PATTERN: RegExp;
1692
+ export declare const SAFE_REPO_ID_PATTERN: RegExp;
1478
1693
  /** Environment variable that overrides the user-home root directory. */
1479
- declare const SERVICEME_HOME_ENV = "SERVICEME_HOME";
1694
+ export declare const SERVICEME_HOME_ENV = "SERVICEME_HOME";
1480
1695
  /**
1481
1696
  * Test seam: lets unit tests inject deterministic values for `os.homedir()`
1482
1697
  * and the `SERVICEME_HOME` env override without actually mutating
1483
1698
  * `process.env` (which would leak into other tests).
1484
1699
  */
1485
1700
  interface UserHomeOverrides {
1486
- homeDir?: string | undefined;
1487
- servicemeHomeEnv?: string | undefined;
1488
- platform?: NodeJS.Platform | undefined;
1701
+ homeDir?: string | undefined;
1702
+ servicemeHomeEnv?: string | undefined;
1703
+ platform?: NodeJS.Platform | undefined;
1489
1704
  }
1490
- declare function setUserHomeOverrides(overrides: UserHomeOverrides): void;
1491
- declare function resetUserHomeOverrides(): void;
1492
- declare function assertSafeRepoId(repoId: string): string;
1705
+ export declare function setUserHomeOverrides(overrides: UserHomeOverrides): void;
1706
+ export declare function resetUserHomeOverrides(): void;
1707
+ export declare function assertSafeRepoId(repoId: string): string;
1493
1708
  /**
1494
1709
  * The raw OS home directory (`os.homedir()`), honoring test overrides
1495
1710
  * ({@link setUserHomeOverrides}). Exported for callers that need a
@@ -1497,64 +1712,64 @@ declare function assertSafeRepoId(repoId: string): string;
1497
1712
  * `~/.agents/{skills,agents}` convention used by `SkillLinker` for
1498
1713
  * user-scope links.
1499
1714
  */
1500
- declare function getHomeDir(): string;
1715
+ export declare function getHomeDir(): string;
1501
1716
  /**
1502
1717
  * Root directory for all SERVICEME user-level state. Resolves to
1503
1718
  * `${SERVICEME_HOME}` when that env var is set, otherwise `${HOME}/.serviceme`
1504
1719
  * (POSIX) or `%USERPROFILE%\.serviceme` (Windows via `os.homedir`).
1505
1720
  */
1506
- declare function getServicemeHome(): string;
1721
+ export declare function getServicemeHome(): string;
1507
1722
  /** `$HOME/.serviceme/repos` (or `${SERVICEME_HOME}/repos`). */
1508
- declare function getReposDir(): string;
1723
+ export declare function getReposDir(): string;
1509
1724
  /** `$HOME/.serviceme/repos/<repoId>` — validates `repoId` first. */
1510
- declare function getRepoDir(repoId: string): string;
1725
+ export declare function getRepoDir(repoId: string): string;
1511
1726
  /** `$HOME/.serviceme/cache` — generic per-user cache. */
1512
- declare function getCacheDir(): string;
1727
+ export declare function getCacheDir(): string;
1513
1728
  /** `$HOME/.serviceme/cache/<repoId>` — per-repo sync state lives here. */
1514
- declare function getRepoCacheDir(repoId: string): string;
1729
+ export declare function getRepoCacheDir(repoId: string): string;
1515
1730
  /** `$HOME/.serviceme/drafts` — local edits not yet pushed upstream. */
1516
- declare function getDraftsDir(): string;
1731
+ export declare function getDraftsDir(): string;
1517
1732
  /** `$HOME/.serviceme/drafts/skills` — local skill drafts. */
1518
- declare function getSkillDraftsDir(): string;
1733
+ export declare function getSkillDraftsDir(): string;
1519
1734
  /** `$HOME/.serviceme/drafts/agents` — local agent drafts. */
1520
- declare function getAgentDraftsDir(): string;
1735
+ export declare function getAgentDraftsDir(): string;
1521
1736
  /**
1522
1737
  * `$HOME/.serviceme/repos.json` — the single config entry point for repo
1523
1738
  * metadata. Always under the resolved home root (i.e. follows
1524
1739
  * `SERVICEME_HOME` overrides too).
1525
1740
  */
1526
- declare function getReposConfigPath(): string;
1741
+ export declare function getReposConfigPath(): string;
1527
1742
  /** `~/.serviceme/workspaces` — machine-local per-workspace state root. */
1528
- declare function getWorkspacesDir(): string;
1743
+ export declare function getWorkspacesDir(): string;
1529
1744
  /**
1530
1745
  * Convenience helper for callers that need to switch behaviour on platform
1531
1746
  * (e.g. `SkillLinker` chooses symlink vs junction). Exported mostly so tests
1532
1747
  * can pin the value without touching `process.platform` directly.
1533
1748
  */
1534
- declare function getHomePlatform(): NodeJS.Platform;
1749
+ export declare function getHomePlatform(): NodeJS.Platform;
1535
1750
  /** Layout constants for scheduled-tasks files. Kept here so other modules
1536
1751
  * can reuse them and the names stay in sync with the design doc. */
1537
- declare const SCHEDULED_TASKS_CONFIG_FILENAME = "scheduled-tasks.json";
1538
- declare const SCHEDULED_TASKS_LOG_FILENAME = "scheduled-tasks-log.json";
1539
- declare const SCHEDULER_PID_FILENAME = "scheduler.pid";
1540
- declare const SCHEDULER_LOCK_FILENAME = "scheduler.lock";
1541
- declare const SCHEDULER_LOG_FILENAME = "scheduler.log";
1542
- declare const MIGRATION_FAILURES_FILENAME = "migration-failures.json";
1543
- declare const KNOWN_WORKSPACES_FILENAME = "known-workspaces.json";
1752
+ export declare const SCHEDULED_TASKS_CONFIG_FILENAME = "scheduled-tasks.json";
1753
+ export declare const SCHEDULED_TASKS_LOG_FILENAME = "scheduled-tasks-log.json";
1754
+ export declare const SCHEDULER_PID_FILENAME = "scheduler.pid";
1755
+ export declare const SCHEDULER_LOCK_FILENAME = "scheduler.lock";
1756
+ export declare const SCHEDULER_LOG_FILENAME = "scheduler.log";
1757
+ export declare const MIGRATION_FAILURES_FILENAME = "migration-failures.json";
1758
+ export declare const KNOWN_WORKSPACES_FILENAME = "known-workspaces.json";
1544
1759
  /** `~/.serviceme/scheduled-tasks.json` — the global v2 task list. */
1545
- declare function getScheduledTasksConfigPath(): string;
1760
+ export declare function getScheduledTasksConfigPath(): string;
1546
1761
  /** `~/.serviceme/scheduled-tasks-log.json` — the global execution log (200 LRU). */
1547
- declare function getScheduledTasksLogPath(): string;
1762
+ export declare function getScheduledTasksLogPath(): string;
1548
1763
  /** `~/.serviceme/scheduler.pid` — global daemon PID file. */
1549
- declare function getSchedulerPidPath(): string;
1764
+ export declare function getSchedulerPidPath(): string;
1550
1765
  /** `~/.serviceme/scheduler.lock` — global daemon startup flock. */
1551
- declare function getSchedulerLockPath(): string;
1766
+ export declare function getSchedulerLockPath(): string;
1552
1767
  /** `~/.serviceme/scheduler.log` — global daemon log (daemon lifecycle, not task execution). */
1553
- declare function getSchedulerLogPath(): string;
1768
+ export declare function getSchedulerLogPath(): string;
1554
1769
  /** `~/.serviceme/migration-failures.json` — diagnostics for failed v1→v2 imports. */
1555
- declare function getMigrationFailuresPath(): string;
1770
+ export declare function getMigrationFailuresPath(): string;
1556
1771
  /** `~/.serviceme/known-workspaces.json` — workspace list the extension has seen. */
1557
- declare function getKnownWorkspacesPath(): string;
1772
+ export declare function getKnownWorkspacesPath(): string;
1558
1773
  /**
1559
1774
  * `~/.serviceme/server-proxy.json` — r7 BYOM Server Proxy toggle
1560
1775
  * self-state. Written by the extension's `ProxyConfigService`, readable
@@ -1566,51 +1781,52 @@ declare function getKnownWorkspacesPath(): string;
1566
1781
  * machine A should be able to rely on it on machine B after sync, not
1567
1782
  * have it disappear when they switch repos.
1568
1783
  */
1569
- declare function getServerProxyGlobalPath(): string;
1784
+ export declare function getServerProxyGlobalPath(): string;
1570
1785
  /** Layout constants for the Phase 5 client-side state files. The server
1571
1786
  * already has the corresponding routes (`/api/v1/auth/...`,
1572
1787
  * `/api/v1/device/...`, etc.) — the client just needs the on-disk
1573
1788
  * file paths + a first-run bootstrap so the auth/device/toolbox
1574
1789
  * services can open + read them without a per-call existence check. */
1575
- declare const CREDENTIALS_CONFIG_FILENAME = "credentials.json";
1576
- declare const DEVICE_JSON_FILENAME = "device.json";
1577
- declare const TOOLBOX_JSON_FILENAME = "toolbox.json";
1578
- declare const MACHINE_ID_FILENAME = "machine-id";
1579
- declare const PROFILES_JSON_FILENAME = "profiles.json";
1790
+ export declare const CREDENTIALS_CONFIG_FILENAME = "credentials.json";
1791
+ export declare const DEVICE_JSON_FILENAME = "device.json";
1792
+ export declare const TOOLBOX_JSON_FILENAME = "toolbox.json";
1793
+ export declare const MACHINE_ID_FILENAME = "machine-id";
1794
+ export declare const PROFILES_JSON_FILENAME = "profiles.json";
1580
1795
  /** `~/.serviceme/credentials.json` — better-auth session tokens + refresh state (client-side cache). */
1581
- declare function getCredentialsConfigPath(): string;
1796
+ export declare function getCredentialsConfigPath(): string;
1582
1797
  /** `~/.serviceme/device.json` — device enrollment payload (id, public key fingerprint, claimed-by). */
1583
- declare function getDeviceJsonPath(): string;
1798
+ export declare function getDeviceJsonPath(): string;
1584
1799
  /** `~/.serviceme/toolbox.json` — local toolbox state (installed tool refs, per-user prefs). */
1585
- declare function getToolboxJsonPath(): string;
1800
+ export declare function getToolboxJsonPath(): string;
1586
1801
  /** `~/.serviceme/machine-id` — opaque stable per-install id (uuid v4 string, no JSON wrapper). */
1587
- declare function getMachineIdPath(): string;
1802
+ export declare function getMachineIdPath(): string;
1588
1803
  /** `~/.serviceme/profiles.json` — cached projection of server-side profile rows; refresh on demand. */
1589
- declare function getProfilesJsonPath(): string;
1590
-
1804
+ export declare function getProfilesJsonPath(): string;
1805
+ //#endregion
1806
+ //#region src/paths/serverProxyGlobal.d.ts
1591
1807
  /** On-disk shape for `~/.serviceme/server-proxy.json`. */
1592
- interface ServerProxyGlobalState {
1593
- /** Whether the user has previously enabled Server Proxy. */
1594
- enabled: boolean;
1595
- /** Last server URL we toggled ON with. Used for re-toggling and UI hint. */
1596
- lastServerUrl: string | undefined;
1597
- /**
1598
- * rev.21 — explicit opt-in to enable Server Proxy even when
1599
- * `http.proxySupport === "override"`. `override` mode forces ALL
1600
- * extensions to route through `http.proxy`; defaulting to `false`
1601
- * keeps the legacy defensive guard against accidental global
1602
- * hijack. Power users (e.g. corp environments that WANT all
1603
- * extensions including GitHub Copilot Chat to route through the
1604
- * corp tunnel) can flip this on via the Webview's "Allow under
1605
- * proxySupport=override" affordance.
1606
- *
1607
- * Note: stored in the global file alongside `enabled` because
1608
- * this is *our* self-flag — it has nothing to do with VS Code's
1609
- * `http.*` schema.
1610
- */
1611
- allowOverride: boolean;
1612
- /** ISO 8601 timestamp of the most recent write. Diagnostic only. */
1613
- updatedAt: string;
1808
+ export interface ServerProxyGlobalState {
1809
+ /** Whether the user has previously enabled Server Proxy. */
1810
+ enabled: boolean;
1811
+ /** Last server URL we toggled ON with. Used for re-toggling and UI hint. */
1812
+ lastServerUrl: string | undefined;
1813
+ /**
1814
+ * rev.21 — explicit opt-in to enable Server Proxy even when
1815
+ * `http.proxySupport === "override"`. `override` mode forces ALL
1816
+ * extensions to route through `http.proxy`; defaulting to `false`
1817
+ * keeps the legacy defensive guard against accidental global
1818
+ * hijack. Power users (e.g. corp environments that WANT all
1819
+ * extensions including GitHub Copilot Chat to route through the
1820
+ * corp tunnel) can flip this on via the Webview's "Allow under
1821
+ * proxySupport=override" affordance.
1822
+ *
1823
+ * Note: stored in the global file alongside `enabled` because
1824
+ * this is *our* self-flag — it has nothing to do with VS Code's
1825
+ * `http.*` schema.
1826
+ */
1827
+ allowOverride: boolean;
1828
+ /** ISO 8601 timestamp of the most recent write. Diagnostic only. */
1829
+ updatedAt: string;
1614
1830
  }
1615
1831
  /**
1616
1832
  * Patch semantics (mirrors `vscode.workspace.getConfiguration().update(...)`):
@@ -1621,24 +1837,24 @@ interface ServerProxyGlobalState {
1621
1837
  * and `allowOverride` are plain `boolean | undefined` because boolean is
1622
1838
  * the natural unit (false = "the user disabled it").
1623
1839
  */
1624
- interface ServerProxyGlobalPatch {
1625
- enabled?: boolean;
1626
- allowOverride?: boolean;
1627
- lastServerUrl?: string | null;
1840
+ export interface ServerProxyGlobalPatch {
1841
+ enabled?: boolean;
1842
+ allowOverride?: boolean;
1843
+ lastServerUrl?: string | null;
1628
1844
  }
1629
1845
  /**
1630
1846
  * Reads the global config file. Returns `null` if the file does not
1631
1847
  * exist (first-run case) — does NOT throw. Throws on parse errors or
1632
1848
  * permission issues, so callers can surface those to the user.
1633
1849
  */
1634
- declare function readServerProxyGlobal(): Promise<ServerProxyGlobalState | null>;
1850
+ export declare function readServerProxyGlobal(): Promise<ServerProxyGlobalState | null>;
1635
1851
  /**
1636
1852
  * Merges a partial patch into the existing state and writes back
1637
1853
  * atomically. Creates `~/.serviceme/` if missing.
1638
1854
  *
1639
1855
  * Returns the post-write state. Throws on IO/JSON errors.
1640
1856
  */
1641
- declare function writeServerProxyGlobal(patch: ServerProxyGlobalPatch): Promise<ServerProxyGlobalState>;
1857
+ export declare function writeServerProxyGlobal(patch: ServerProxyGlobalPatch): Promise<ServerProxyGlobalState>;
1642
1858
  /**
1643
1859
  * Best-effort migration of a legacy `enabled` flag (typically read from
1644
1860
  * VS Code's `settings.json` at `serverProxy.enabled`) into the global
@@ -1651,11 +1867,13 @@ declare function writeServerProxyGlobal(patch: ServerProxyGlobalPatch): Promise<
1651
1867
  * Returns the migrated state, or `null` if no migration was needed
1652
1868
  * (legacy flag absent OR global config already up to date).
1653
1869
  */
1654
- declare function migrateLegacyServerProxyEnabled(readLegacy: () => boolean | undefined, clearLegacy: () => Promise<void>): Promise<ServerProxyGlobalState | null>;
1655
-
1656
- declare const TOOL_RISK_MAP: Record<string, AgentToolRiskLevel>;
1657
- declare function parseAgentToolPermissions(content: string): AgentToolPermission[];
1658
-
1870
+ export declare function migrateLegacyServerProxyEnabled(readLegacy: () => boolean | undefined, clearLegacy: () => Promise<void>): Promise<ServerProxyGlobalState | null>;
1871
+ //#endregion
1872
+ //#region src/permissions/agent-permissions.d.ts
1873
+ export declare const TOOL_RISK_MAP: Record<string, AgentToolRiskLevel>;
1874
+ export declare function parseAgentToolPermissions(content: string): AgentToolPermission[];
1875
+ //#endregion
1876
+ //#region src/phase5/bootstrap.d.ts
1659
1877
  /**
1660
1878
  * Spec §11.12 — Phase 5 client-side state bootstrap.
1661
1879
  *
@@ -1679,37 +1897,39 @@ declare function parseAgentToolPermissions(content: string): AgentToolPermission
1679
1897
  * @see docs/architecture/skill-agent-v2-repo.md §11.12
1680
1898
  */
1681
1899
  interface BootstrapPhase5Result {
1682
- /** Files that were created by this run (already-existing files excluded). */
1683
- created: string[];
1684
- /** Files that were already present and left untouched. */
1685
- skipped: string[];
1686
- /** Files where the write attempt failed (e.g. read-only home). */
1687
- failed: Array<{
1688
- path: string;
1689
- reason: string;
1690
- }>;
1900
+ /** Files that were created by this run (already-existing files excluded). */
1901
+ created: string[];
1902
+ /** Files that were already present and left untouched. */
1903
+ skipped: string[];
1904
+ /** Files where the write attempt failed (e.g. read-only home). */
1905
+ failed: Array<{
1906
+ path: string;
1907
+ reason: string;
1908
+ }>;
1691
1909
  }
1692
1910
  /**
1693
1911
  * Idempotently create the Phase 5 placeholder files under
1694
1912
  * `~/.serviceme/`. Safe to call on every extension activation —
1695
1913
  * existing files are detected via `access` and skipped.
1696
1914
  */
1697
- declare function bootstrapPhase5Placeholders(): Promise<BootstrapPhase5Result>;
1698
-
1699
- declare class ProjectTools {
1700
- extractTemplate(zipPath: string, workspacePath: string, tempExtractDir: string, input: ServiceMeProjectExtractTemplateInput): Promise<ServiceMeProjectExtractTemplateResult>;
1701
- installDependencies(workspacePath: string, command?: string): Promise<ServiceMeProjectInstallDepsResult>;
1702
- makeScriptsExecutable(workspacePath: string): Promise<ServiceMeProjectMakeScriptsExecutableResult>;
1703
- initializeGit(workspacePath: string): Promise<ServiceMeProjectGitInitResult>;
1704
- runScaffoldPrune(workspacePath: string, preset?: string): Promise<ServiceMeProjectScaffoldPruneResult>;
1705
- private ensurePresetManifest;
1706
- private findScripts;
1707
- private pathExists;
1708
- private selectExtractedDirectory;
1709
- private directoryMatchesProjectPattern;
1710
- }
1711
- declare function createProjectTools(): ProjectTools;
1712
-
1915
+ export declare function bootstrapPhase5Placeholders(): Promise<BootstrapPhase5Result>;
1916
+ //#endregion
1917
+ //#region src/project/projectTools.d.ts
1918
+ export declare class ProjectTools {
1919
+ extractTemplate(zipPath: string, workspacePath: string, tempExtractDir: string, input: ServiceMeProjectExtractTemplateInput): Promise<ServiceMeProjectExtractTemplateResult>;
1920
+ installDependencies(workspacePath: string, command?: string): Promise<ServiceMeProjectInstallDepsResult>;
1921
+ makeScriptsExecutable(workspacePath: string): Promise<ServiceMeProjectMakeScriptsExecutableResult>;
1922
+ initializeGit(workspacePath: string): Promise<ServiceMeProjectGitInitResult>;
1923
+ runScaffoldPrune(workspacePath: string, preset?: string): Promise<ServiceMeProjectScaffoldPruneResult>;
1924
+ private ensurePresetManifest;
1925
+ private findScripts;
1926
+ private pathExists;
1927
+ private selectExtractedDirectory;
1928
+ private directoryMatchesProjectPattern;
1929
+ }
1930
+ export declare function createProjectTools(): ProjectTools;
1931
+ //#endregion
1932
+ //#region src/repos/types.d.ts
1713
1933
  /**
1714
1934
  * `repos.json` schema — mirrors §3 of docs/architecture/skill-agent-v2-repo.md.
1715
1935
  *
@@ -1729,94 +1949,151 @@ declare function createProjectTools(): ProjectTools;
1729
1949
  * fields.
1730
1950
  */
1731
1951
  /** ISO 8601 timestamp. */
1732
- type IsoTimestamp = string;
1952
+ export type IsoTimestamp = string;
1733
1953
  /** Per-repo sync health — surfaced in the UI alongside the repo entry. */
1734
- type SyncStatus = "ok" | "error";
1954
+ export type SyncStatus = "ok" | "error";
1735
1955
  /** Discriminant on `RepoConfig.source` — narrow with a literal check. */
1736
- type RepoSource = "default" | "user";
1956
+ export type RepoSource = "default" | "user";
1737
1957
  /**
1738
1958
  * Common shape shared by both default and user-added repos. Source lives on
1739
1959
  * the type so we can keep the loader schema flat while still letting
1740
1960
  * `DefaultRepoConfig` carry a `description`.
1741
1961
  */
1742
- interface RepoConfig {
1743
- /** Stable id used in on-disk paths (must match `SAFE_REPO_ID_PATTERN`). */
1744
- id: string;
1745
- /** Display name shown in UI. */
1746
- name: string;
1747
- /** Upstream git URL (typically github.com/<owner>/<repo>.git). */
1748
- url: string;
1749
- /** Default branch to track (e.g. "v2", "main"). */
1750
- branch: string;
1751
- /** Whether this repo participates in scheduled syncs. */
1752
- enabled: boolean;
1753
- /** Whether git traffic should go through the local server proxy (default true). */
1754
- useProxy?: boolean;
1755
- /** Whether the user is allowed to push back to this repo. */
1756
- writeEnabled: boolean;
1757
- /** When the user (or first-run installer) added this repo. */
1758
- addedAt: IsoTimestamp;
1759
- /** Last successful sync timestamp. */
1760
- lastSyncAt?: IsoTimestamp;
1761
- /** Commit SHA at the time of the last successful sync. */
1762
- lastSyncCommitSha?: string;
1763
- /** Result of the most recent sync attempt. */
1764
- lastSyncStatus?: SyncStatus;
1765
- /** Error message from the most recent sync attempt (when `lastSyncStatus === 'error'`). */
1766
- lastSyncError?: string;
1767
- /** Whether this repo is a default or a user-added repo. */
1768
- source: RepoSource;
1962
+ export interface RepoConfig {
1963
+ /** Stable id used in on-disk paths (must match `SAFE_REPO_ID_PATTERN`). */
1964
+ id: string;
1965
+ /** Display name shown in UI. */
1966
+ name: string;
1967
+ /** Upstream git URL (typically github.com/<owner>/<repo>.git). */
1968
+ url: string;
1969
+ /** Default branch to track (e.g. "v2", "main"). */
1970
+ branch: string;
1971
+ /** Whether this repo participates in scheduled syncs. */
1972
+ enabled: boolean;
1973
+ /** Whether git traffic should go through the local server proxy (default true). */
1974
+ useProxy?: boolean;
1975
+ /** Whether the user is allowed to push back to this repo. */
1976
+ writeEnabled: boolean;
1977
+ /** When the user (or first-run installer) added this repo. */
1978
+ addedAt: IsoTimestamp;
1979
+ /** Last successful sync timestamp. */
1980
+ lastSyncAt?: IsoTimestamp;
1981
+ /** Commit SHA at the time of the last successful sync. */
1982
+ lastSyncCommitSha?: string;
1983
+ /** Result of the most recent sync attempt. */
1984
+ lastSyncStatus?: SyncStatus;
1985
+ /** Error message from the most recent sync attempt (when `lastSyncStatus === 'error'`). */
1986
+ lastSyncError?: string;
1987
+ /** Whether this repo is a default or a user-added repo. */
1988
+ source: RepoSource;
1769
1989
  }
1770
1990
  /** A default (bundled) repo — has a UI-facing description, cannot be removed. */
1771
- interface DefaultRepoConfig extends RepoConfig {
1772
- source: "default";
1773
- description: string;
1991
+ export interface DefaultRepoConfig extends RepoConfig {
1992
+ source: "default";
1993
+ description: string;
1774
1994
  }
1775
1995
  /** A user-added repo — can be added, removed, disabled freely. */
1776
- interface UserRepoConfig extends RepoConfig {
1777
- source: "user";
1996
+ export interface UserRepoConfig extends RepoConfig {
1997
+ source: "user";
1778
1998
  }
1779
1999
  /** Any repo, regardless of source. */
1780
- type AnyRepoConfig = DefaultRepoConfig | UserRepoConfig;
2000
+ export type AnyRepoConfig = DefaultRepoConfig | UserRepoConfig;
1781
2001
  /**
1782
2002
  * Root shape of `repos.json`. `version` lets us evolve the schema later
1783
2003
  * without colliding with hand-edited files.
1784
2004
  */
1785
- interface ReposFile {
1786
- version: 1;
1787
- /** Id of the repo currently surfaced as the default selection in the UI. */
1788
- defaultRepoId: string;
1789
- repos: AnyRepoConfig[];
2005
+ export interface ReposFile {
2006
+ version: 1;
2007
+ /** Id of the repo currently surfaced as the default selection in the UI. */
2008
+ defaultRepoId: string;
2009
+ repos: AnyRepoConfig[];
1790
2010
  }
1791
2011
  /**
1792
2012
  * Convenience type-guard — narrows to `DefaultRepoConfig`. Useful when callers
1793
2013
  * want to render `repo.description` or reject `removeRepo(repo)` for defaults.
1794
2014
  */
1795
- declare function isDefaultRepo(repo: RepoConfig): repo is DefaultRepoConfig;
2015
+ export declare function isDefaultRepo(repo: RepoConfig): repo is DefaultRepoConfig;
1796
2016
  /** Convenience type-guard — narrows to `UserRepoConfig`. */
1797
- declare function isUserRepo(repo: RepoConfig): repo is UserRepoConfig;
1798
-
2017
+ export declare function isUserRepo(repo: RepoConfig): repo is UserRepoConfig;
2018
+ //#endregion
2019
+ //#region src/repos/loader.d.ts
1799
2020
  declare const defaultRepoSchema: z.ZodObject<{
1800
- source: z.ZodLiteral<"default">;
1801
- description: z.ZodString;
1802
- id: z.ZodString;
1803
- name: z.ZodString;
1804
- url: z.ZodString;
1805
- branch: z.ZodString;
1806
- enabled: z.ZodBoolean;
1807
- useProxy: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
1808
- writeEnabled: z.ZodBoolean;
1809
- addedAt: z.ZodString;
1810
- lastSyncAt: z.ZodOptional<z.ZodString>;
1811
- lastSyncCommitSha: z.ZodOptional<z.ZodString>;
1812
- lastSyncStatus: z.ZodOptional<z.ZodEnum<{
1813
- error: "error";
1814
- ok: "ok";
1815
- }>>;
1816
- lastSyncError: z.ZodOptional<z.ZodString>;
2021
+ id: z.ZodString;
2022
+ name: z.ZodString;
2023
+ url: z.ZodString;
2024
+ branch: z.ZodString;
2025
+ enabled: z.ZodBoolean;
2026
+ useProxy: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
2027
+ writeEnabled: z.ZodBoolean;
2028
+ addedAt: z.ZodString;
2029
+ lastSyncAt: z.ZodOptional<z.ZodString>;
2030
+ lastSyncCommitSha: z.ZodOptional<z.ZodString>;
2031
+ lastSyncStatus: z.ZodOptional<z.ZodEnum<{
2032
+ error: "error";
2033
+ ok: "ok";
2034
+ }>>;
2035
+ lastSyncError: z.ZodOptional<z.ZodString>;
2036
+ source: z.ZodLiteral<"default">;
2037
+ description: z.ZodString;
1817
2038
  }, z.core.$strip>;
1818
2039
  declare const userRepoSchema: z.ZodObject<{
1819
- source: z.ZodLiteral<"user">;
2040
+ id: z.ZodString;
2041
+ name: z.ZodString;
2042
+ url: z.ZodString;
2043
+ branch: z.ZodString;
2044
+ enabled: z.ZodBoolean;
2045
+ useProxy: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
2046
+ writeEnabled: z.ZodBoolean;
2047
+ addedAt: z.ZodString;
2048
+ lastSyncAt: z.ZodOptional<z.ZodString>;
2049
+ lastSyncCommitSha: z.ZodOptional<z.ZodString>;
2050
+ lastSyncStatus: z.ZodOptional<z.ZodEnum<{
2051
+ error: "error";
2052
+ ok: "ok";
2053
+ }>>;
2054
+ lastSyncError: z.ZodOptional<z.ZodString>;
2055
+ source: z.ZodLiteral<"user">;
2056
+ }, z.core.$strip>;
2057
+ declare const repoSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
2058
+ id: z.ZodString;
2059
+ name: z.ZodString;
2060
+ url: z.ZodString;
2061
+ branch: z.ZodString;
2062
+ enabled: z.ZodBoolean;
2063
+ useProxy: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
2064
+ writeEnabled: z.ZodBoolean;
2065
+ addedAt: z.ZodString;
2066
+ lastSyncAt: z.ZodOptional<z.ZodString>;
2067
+ lastSyncCommitSha: z.ZodOptional<z.ZodString>;
2068
+ lastSyncStatus: z.ZodOptional<z.ZodEnum<{
2069
+ error: "error";
2070
+ ok: "ok";
2071
+ }>>;
2072
+ lastSyncError: z.ZodOptional<z.ZodString>;
2073
+ source: z.ZodLiteral<"default">;
2074
+ description: z.ZodString;
2075
+ }, z.core.$strip>, z.ZodObject<{
2076
+ id: z.ZodString;
2077
+ name: z.ZodString;
2078
+ url: z.ZodString;
2079
+ branch: z.ZodString;
2080
+ enabled: z.ZodBoolean;
2081
+ useProxy: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
2082
+ writeEnabled: z.ZodBoolean;
2083
+ addedAt: z.ZodString;
2084
+ lastSyncAt: z.ZodOptional<z.ZodString>;
2085
+ lastSyncCommitSha: z.ZodOptional<z.ZodString>;
2086
+ lastSyncStatus: z.ZodOptional<z.ZodEnum<{
2087
+ error: "error";
2088
+ ok: "ok";
2089
+ }>>;
2090
+ lastSyncError: z.ZodOptional<z.ZodString>;
2091
+ source: z.ZodLiteral<"user">;
2092
+ }, z.core.$strip>], "source">;
2093
+ export declare const reposFileSchema: z.ZodObject<{
2094
+ version: z.ZodLiteral<1>;
2095
+ defaultRepoId: z.ZodString;
2096
+ repos: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
1820
2097
  id: z.ZodString;
1821
2098
  name: z.ZodString;
1822
2099
  url: z.ZodString;
@@ -1828,14 +2105,13 @@ declare const userRepoSchema: z.ZodObject<{
1828
2105
  lastSyncAt: z.ZodOptional<z.ZodString>;
1829
2106
  lastSyncCommitSha: z.ZodOptional<z.ZodString>;
1830
2107
  lastSyncStatus: z.ZodOptional<z.ZodEnum<{
1831
- error: "error";
1832
- ok: "ok";
2108
+ error: "error";
2109
+ ok: "ok";
1833
2110
  }>>;
1834
2111
  lastSyncError: z.ZodOptional<z.ZodString>;
1835
- }, z.core.$strip>;
1836
- declare const repoSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1837
2112
  source: z.ZodLiteral<"default">;
1838
2113
  description: z.ZodString;
2114
+ }, z.core.$strip>, z.ZodObject<{
1839
2115
  id: z.ZodString;
1840
2116
  name: z.ZodString;
1841
2117
  url: z.ZodString;
@@ -1847,140 +2123,85 @@ declare const repoSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1847
2123
  lastSyncAt: z.ZodOptional<z.ZodString>;
1848
2124
  lastSyncCommitSha: z.ZodOptional<z.ZodString>;
1849
2125
  lastSyncStatus: z.ZodOptional<z.ZodEnum<{
1850
- error: "error";
1851
- ok: "ok";
2126
+ error: "error";
2127
+ ok: "ok";
1852
2128
  }>>;
1853
2129
  lastSyncError: z.ZodOptional<z.ZodString>;
1854
- }, z.core.$strip>, z.ZodObject<{
1855
2130
  source: z.ZodLiteral<"user">;
1856
- id: z.ZodString;
1857
- name: z.ZodString;
1858
- url: z.ZodString;
1859
- branch: z.ZodString;
1860
- enabled: z.ZodBoolean;
1861
- useProxy: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
1862
- writeEnabled: z.ZodBoolean;
1863
- addedAt: z.ZodString;
1864
- lastSyncAt: z.ZodOptional<z.ZodString>;
1865
- lastSyncCommitSha: z.ZodOptional<z.ZodString>;
1866
- lastSyncStatus: z.ZodOptional<z.ZodEnum<{
1867
- error: "error";
1868
- ok: "ok";
1869
- }>>;
1870
- lastSyncError: z.ZodOptional<z.ZodString>;
1871
- }, z.core.$strip>], "source">;
1872
- declare const reposFileSchema: z.ZodObject<{
1873
- version: z.ZodLiteral<1>;
1874
- defaultRepoId: z.ZodString;
1875
- repos: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
1876
- source: z.ZodLiteral<"default">;
1877
- description: z.ZodString;
1878
- id: z.ZodString;
1879
- name: z.ZodString;
1880
- url: z.ZodString;
1881
- branch: z.ZodString;
1882
- enabled: z.ZodBoolean;
1883
- useProxy: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
1884
- writeEnabled: z.ZodBoolean;
1885
- addedAt: z.ZodString;
1886
- lastSyncAt: z.ZodOptional<z.ZodString>;
1887
- lastSyncCommitSha: z.ZodOptional<z.ZodString>;
1888
- lastSyncStatus: z.ZodOptional<z.ZodEnum<{
1889
- error: "error";
1890
- ok: "ok";
1891
- }>>;
1892
- lastSyncError: z.ZodOptional<z.ZodString>;
1893
- }, z.core.$strip>, z.ZodObject<{
1894
- source: z.ZodLiteral<"user">;
1895
- id: z.ZodString;
1896
- name: z.ZodString;
1897
- url: z.ZodString;
1898
- branch: z.ZodString;
1899
- enabled: z.ZodBoolean;
1900
- useProxy: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
1901
- writeEnabled: z.ZodBoolean;
1902
- addedAt: z.ZodString;
1903
- lastSyncAt: z.ZodOptional<z.ZodString>;
1904
- lastSyncCommitSha: z.ZodOptional<z.ZodString>;
1905
- lastSyncStatus: z.ZodOptional<z.ZodEnum<{
1906
- error: "error";
1907
- ok: "ok";
1908
- }>>;
1909
- lastSyncError: z.ZodOptional<z.ZodString>;
1910
- }, z.core.$strip>], "source">>;
2131
+ }, z.core.$strip>], "source">>;
1911
2132
  }, z.core.$strip>;
1912
2133
  /** Inferred Zod type — identical to our hand-written `ReposFile`. */
1913
- type ReposFileInput = z.infer<typeof reposFileSchema>;
2134
+ export type ReposFileInput = z.infer<typeof reposFileSchema>;
1914
2135
  /** Result of a load attempt — either a parsed file or a recovery notice. */
1915
- interface LoadResult {
1916
- /** Parsed + validated repos file (always populated, even on recovery). */
1917
- config: ReposFile;
1918
- /**
1919
- * Non-null when the existing file on disk was unreadable / invalid and
1920
- * was moved aside as a `.bak`. The store can use this to surface a
1921
- * warning in the UI.
1922
- */
1923
- recoveredFromBackup: string | null;
2136
+ export interface LoadResult {
2137
+ /** Parsed + validated repos file (always populated, even on recovery). */
2138
+ config: ReposFile;
2139
+ /**
2140
+ * Non-null when the existing file on disk was unreadable / invalid and
2141
+ * was moved aside as a `.bak`. The store can use this to surface a
2142
+ * warning in the UI.
2143
+ */
2144
+ recoveredFromBackup: string | null;
1924
2145
  }
1925
2146
  /** Dependencies — defaults to the real fs, tests inject a fake. */
1926
- interface ReposLoaderFileSystem {
1927
- readFile: typeof fs.readFile;
1928
- writeFile: typeof fs.writeFile;
1929
- rename: typeof fs.rename;
1930
- mkdir: typeof fs.mkdir;
1931
- stat: typeof fs.stat;
1932
- unlink?: typeof fs.unlink;
1933
- }
1934
- interface ReposLoaderOptions {
1935
- /** Absolute path of the `repos.json` file. */
1936
- configPath: string;
1937
- /** Custom time provider — defaults to `() => new Date().toISOString()`. */
1938
- now?: () => string;
1939
- /** Random suffix provider for atomic-write temp files. */
1940
- randomSuffix?: () => string;
1941
- /** Filesystem shim for tests. */
1942
- fileSystem?: ReposLoaderFileSystem;
1943
- }
1944
- declare class ReposLoader {
1945
- private readonly configPath;
1946
- private readonly now;
1947
- private readonly randomSuffix;
1948
- private readonly fileSystem;
1949
- constructor(options: ReposLoaderOptions);
1950
- /** Absolute path of the file this loader reads/writes. */
1951
- getConfigPath(): string;
1952
- /**
1953
- * Read + validate the on-disk config. When the file is missing, returns a
1954
- * sentinel empty config (no backup is taken — that's expected on first
1955
- * run). When the file is corrupted, moves it to `<name>.<ts>.bak` and
1956
- * returns an empty config with `recoveredFromBackup` populated.
1957
- */
1958
- load(): Promise<LoadResult>;
1959
- /**
1960
- * Write the config to disk atomically. Writes to
1961
- * `<target>.tmp-<random>` then `rename`s over the target. The parent
1962
- * directory is created on demand.
1963
- */
1964
- save(config: ReposFile): Promise<void>;
1965
- /**
1966
- * Move the existing file to a timestamped `.bak` sibling and return the
1967
- * backup path. Used when we detect a corrupted / unparseable file and
1968
- * need to make room for a fresh write.
1969
- */
1970
- private quarantine;
1971
- /**
1972
- * Empty config used when no file exists or the existing file is corrupt.
1973
- * The caller (e.g. `ensureDefaultsInstalled`) is expected to populate the
1974
- * real default repo set before persisting.
1975
- */
1976
- private buildEmptyConfig;
1977
- }
1978
-
2147
+ export interface ReposLoaderFileSystem {
2148
+ readFile: typeof fs$1.readFile;
2149
+ writeFile: typeof fs$1.writeFile;
2150
+ rename: typeof fs$1.rename;
2151
+ mkdir: typeof fs$1.mkdir;
2152
+ stat: typeof fs$1.stat;
2153
+ unlink?: typeof fs$1.unlink;
2154
+ }
2155
+ export interface ReposLoaderOptions {
2156
+ /** Absolute path of the `repos.json` file. */
2157
+ configPath: string;
2158
+ /** Custom time provider — defaults to `() => new Date().toISOString()`. */
2159
+ now?: () => string;
2160
+ /** Random suffix provider for atomic-write temp files. */
2161
+ randomSuffix?: () => string;
2162
+ /** Filesystem shim for tests. */
2163
+ fileSystem?: ReposLoaderFileSystem;
2164
+ }
2165
+ export declare class ReposLoader {
2166
+ private readonly configPath;
2167
+ private readonly now;
2168
+ private readonly randomSuffix;
2169
+ private readonly fileSystem;
2170
+ constructor(options: ReposLoaderOptions);
2171
+ /** Absolute path of the file this loader reads/writes. */
2172
+ getConfigPath(): string;
2173
+ /**
2174
+ * Read + validate the on-disk config. When the file is missing, returns a
2175
+ * sentinel empty config (no backup is taken — that's expected on first
2176
+ * run). When the file is corrupted, moves it to `<name>.<ts>.bak` and
2177
+ * returns an empty config with `recoveredFromBackup` populated.
2178
+ */
2179
+ load(): Promise<LoadResult>;
2180
+ /**
2181
+ * Write the config to disk atomically. Writes to
2182
+ * `<target>.tmp-<random>` then `rename`s over the target. The parent
2183
+ * directory is created on demand.
2184
+ */
2185
+ save(config: ReposFile): Promise<void>;
2186
+ /**
2187
+ * Move the existing file to a timestamped `.bak` sibling and return the
2188
+ * backup path. Used when we detect a corrupted / unparseable file and
2189
+ * need to make room for a fresh write.
2190
+ */
2191
+ private quarantine;
2192
+ /**
2193
+ * Empty config used when no file exists or the existing file is corrupt.
2194
+ * The caller (e.g. `ensureDefaultsInstalled`) is expected to populate the
2195
+ * real default repo set before persisting.
2196
+ */
2197
+ private buildEmptyConfig;
2198
+ }
1979
2199
  /** Helper: parse + validate a config object (e.g. freshly built in memory). */
1980
- declare function validateReposFile(input: unknown): ReposFile;
2200
+ export declare function validateReposFile(input: unknown): ReposFile;
1981
2201
  /** Helper: discriminate a `RepoConfig` between default and user flavours. */
1982
- declare function narrowRepoConfig(repo: AnyRepoConfig): DefaultRepoConfig | UserRepoConfig;
1983
-
2202
+ export declare function narrowRepoConfig(repo: AnyRepoConfig): DefaultRepoConfig | UserRepoConfig;
2203
+ //#endregion
2204
+ //#region src/repos/store.d.ts
1984
2205
  /**
1985
2206
  * In-memory CRUD store for `repos.json`.
1986
2207
  *
@@ -1997,167 +2218,167 @@ declare function narrowRepoConfig(repo: AnyRepoConfig): DefaultRepoConfig | User
1997
2218
  * so tests can run without lingering watchers.
1998
2219
  */
1999
2220
  /** Mutating event from the store. */
2000
- type ReposStoreChange = {
2001
- kind: "load";
2002
- config: ReposFile;
2221
+ export type ReposStoreChange = {
2222
+ kind: "load";
2223
+ config: ReposFile;
2003
2224
  } | {
2004
- kind: "add";
2005
- repo: AnyRepoConfig;
2225
+ kind: "add";
2226
+ repo: AnyRepoConfig;
2006
2227
  } | {
2007
- kind: "update";
2008
- repo: AnyRepoConfig;
2228
+ kind: "update";
2229
+ repo: AnyRepoConfig;
2009
2230
  } | {
2010
- kind: "remove";
2011
- repoId: string;
2231
+ kind: "remove";
2232
+ repoId: string;
2012
2233
  } | {
2013
- kind: "default-change";
2014
- defaultRepoId: string;
2234
+ kind: "default-change";
2235
+ defaultRepoId: string;
2015
2236
  } | {
2016
- kind: "error";
2017
- error: Error;
2237
+ kind: "error";
2238
+ error: Error;
2018
2239
  };
2019
2240
  /** Subscriber callback. */
2020
- type ReposStoreListener = (change: ReposStoreChange) => void;
2241
+ export type ReposStoreListener = (change: ReposStoreChange) => void;
2021
2242
  /** Dependencies — defaults to the real fs, tests inject a fake. */
2022
- interface ReposStoreFileSystem {
2023
- watch: typeof fs$1.watch;
2024
- }
2025
- interface ReposStoreOptions {
2026
- /** Use an explicit loader (defaults to one wrapping the resolved configPath). */
2027
- loader?: ReposLoader;
2028
- /** File-system watch implementation — defaults to `fs.watch`. */
2029
- fileSystem?: ReposStoreFileSystem;
2030
- /** Time provider for `addedAt` stamping. */
2031
- now?: () => string;
2032
- /**
2033
- * Debounce window for `fs.watch` callbacks. Editors sometimes emit
2034
- * multiple `change` events for a single logical write — coalesce them.
2035
- * Defaults to 50ms.
2036
- */
2037
- debounceMs?: number;
2038
- /**
2039
- * Watch implementation factory — defaults to a no-deps wrapper around
2040
- * `fs.watch`. Tests inject a fake watcher here. The store wires the
2041
- * returned handle to its own schedule/error flow via the supplied
2042
- * callbacks.
2043
- */
2044
- createFsWatcher?: (configPath: string, callbacks: FsWatcherCallbacks) => FsWatcherHandle;
2243
+ export interface ReposStoreFileSystem {
2244
+ watch: typeof fs.watch;
2245
+ }
2246
+ export interface ReposStoreOptions {
2247
+ /** Use an explicit loader (defaults to one wrapping the resolved configPath). */
2248
+ loader?: ReposLoader;
2249
+ /** File-system watch implementation — defaults to `fs.watch`. */
2250
+ fileSystem?: ReposStoreFileSystem;
2251
+ /** Time provider for `addedAt` stamping. */
2252
+ now?: () => string;
2253
+ /**
2254
+ * Debounce window for `fs.watch` callbacks. Editors sometimes emit
2255
+ * multiple `change` events for a single logical write — coalesce them.
2256
+ * Defaults to 50ms.
2257
+ */
2258
+ debounceMs?: number;
2259
+ /**
2260
+ * Watch implementation factory — defaults to a no-deps wrapper around
2261
+ * `fs.watch`. Tests inject a fake watcher here. The store wires the
2262
+ * returned handle to its own schedule/error flow via the supplied
2263
+ * callbacks.
2264
+ */
2265
+ createFsWatcher?: (configPath: string, callbacks: FsWatcherCallbacks) => FsWatcherHandle;
2045
2266
  }
2046
2267
  /**
2047
2268
  * Minimal subset of `fs.FSWatcher` that the store depends on. Defining our
2048
2269
  * own type lets tests inject a fake without dragging in real fs handles.
2049
2270
  */
2050
- interface FsWatcherHandle {
2051
- close(): void;
2271
+ export interface FsWatcherHandle {
2272
+ close(): void;
2052
2273
  }
2053
2274
  /**
2054
2275
  * Callbacks the store wires to a watcher. The default `fs.watch` factory
2055
2276
  * uses these to forward events into `scheduleReload` / `error` emission;
2056
2277
  * tests can ignore them when they only care about lifecycle.
2057
2278
  */
2058
- interface FsWatcherCallbacks {
2059
- onChange?: () => void;
2060
- onRename?: () => void;
2061
- onError?: (err: Error) => void;
2062
- }
2063
- declare class ReposStore {
2064
- private readonly loader;
2065
- private readonly fileSystem;
2066
- private readonly now;
2067
- private readonly debounceMs;
2068
- private readonly createFsWatcher;
2069
- private config;
2070
- private readonly emitter;
2071
- private watcher;
2072
- private reloadTimer;
2073
- private lastLoadResult;
2074
- constructor(options?: ReposStoreOptions);
2075
- /** Currently held config, or `null` if `load()` has not been called yet. */
2076
- getConfig(): ReposFile | null;
2077
- /** Path of the underlying `repos.json` file (via the loader). */
2078
- getConfigPath(): string;
2079
- /** Subscribe to store mutations. Returns an unsubscribe function. */
2080
- subscribe(listener: ReposStoreListener): () => void;
2081
- /**
2082
- * Read the config from disk (delegating to the loader) and seed the
2083
- * in-memory state. Safe to call repeatedly.
2084
- */
2085
- load(): Promise<LoadResult>;
2086
- /** Convenience getter — wraps `load()` and returns the config. */
2087
- ensureLoaded(): Promise<ReposFile>;
2088
- /** The most recent `LoadResult`, useful for surfacing recovery warnings. */
2089
- getLastLoadResult(): LoadResult | null;
2090
- /**
2091
- * Start watching the config file for external changes. Subsequent writes
2092
- * (or edits from another process) trigger a debounced re-load.
2093
- *
2094
- * No-op when already watching.
2095
- */
2096
- startWatching(): void;
2097
- /** Stop watching and release any pending reload timers. */
2098
- stopWatching(): void;
2099
- list(): AnyRepoConfig[];
2100
- listDefault(): AnyRepoConfig[];
2101
- listUser(): UserRepoConfig[];
2102
- get(repoId: string): AnyRepoConfig | undefined;
2103
- /**
2104
- * Add a user repo. Throws when the id already exists. The `addedAt`
2105
- * timestamp defaults to `now()` when not provided. Persists to disk.
2106
- */
2107
- addUserRepo(input: Omit<UserRepoConfig, "source">): Promise<UserRepoConfig>;
2108
- /**
2109
- * Update an existing repo by id (partial). Throws when not found.
2110
- * Persists to disk.
2111
- */
2112
- updateRepo(repoId: string, patch: Partial<RepoConfig>): Promise<AnyRepoConfig>;
2113
- /**
2114
- * Remove a user repo. Throws when the repo is a default or does not exist.
2115
- * Persists to disk.
2116
- */
2117
- removeUserRepo(repoId: string): Promise<void>;
2118
- /**
2119
- * Disable a repo (any source). Useful for the "Disable" button on default
2120
- * repos. Persists to disk.
2121
- */
2122
- disableRepo(repoId: string): Promise<AnyRepoConfig>;
2123
- /** Inverse of {@link disableRepo}. */
2124
- enableRepo(repoId: string): Promise<AnyRepoConfig>;
2125
- /** Change which repo the UI surfaces as the default. Persists to disk. */
2126
- setDefaultRepoId(repoId: string): Promise<void>;
2127
- getDefaultRepoId(): string | null;
2128
- /** Returns the configured `now` provider — exposed for `bootstrapDefaults`. */
2129
- getNow(): () => string;
2130
- /**
2131
- * Replace the in-memory config and persist it. Used by helpers like
2132
- * `bootstrapDefaults` that build a new config wholesale (rather than
2133
- * mutating a single field).
2134
- */
2135
- replaceConfig(next: ReposFile): Promise<ReposFile>;
2136
- private mutate;
2137
- private emit;
2138
- /**
2139
- * Default `fs.watch` adapter. Public so tests can wrap a real watcher
2140
- * with a debounce trampoline if they need to.
2141
- */
2142
- private defaultCreateFsWatcher;
2143
- private scheduleReload;
2279
+ export interface FsWatcherCallbacks {
2280
+ onChange?: () => void;
2281
+ onRename?: () => void;
2282
+ onError?: (err: Error) => void;
2283
+ }
2284
+ export declare class ReposStore {
2285
+ private readonly loader;
2286
+ private readonly fileSystem;
2287
+ private readonly now;
2288
+ private readonly debounceMs;
2289
+ private readonly createFsWatcher;
2290
+ private config;
2291
+ private readonly emitter;
2292
+ private watcher;
2293
+ private reloadTimer;
2294
+ private lastLoadResult;
2295
+ constructor(options?: ReposStoreOptions);
2296
+ /** Currently held config, or `null` if `load()` has not been called yet. */
2297
+ getConfig(): ReposFile | null;
2298
+ /** Path of the underlying `repos.json` file (via the loader). */
2299
+ getConfigPath(): string;
2300
+ /** Subscribe to store mutations. Returns an unsubscribe function. */
2301
+ subscribe(listener: ReposStoreListener): () => void;
2302
+ /**
2303
+ * Read the config from disk (delegating to the loader) and seed the
2304
+ * in-memory state. Safe to call repeatedly.
2305
+ */
2306
+ load(): Promise<LoadResult>;
2307
+ /** Convenience getter — wraps `load()` and returns the config. */
2308
+ ensureLoaded(): Promise<ReposFile>;
2309
+ /** The most recent `LoadResult`, useful for surfacing recovery warnings. */
2310
+ getLastLoadResult(): LoadResult | null;
2311
+ /**
2312
+ * Start watching the config file for external changes. Subsequent writes
2313
+ * (or edits from another process) trigger a debounced re-load.
2314
+ *
2315
+ * No-op when already watching.
2316
+ */
2317
+ startWatching(): void;
2318
+ /** Stop watching and release any pending reload timers. */
2319
+ stopWatching(): void;
2320
+ list(): AnyRepoConfig[];
2321
+ listDefault(): AnyRepoConfig[];
2322
+ listUser(): UserRepoConfig[];
2323
+ get(repoId: string): AnyRepoConfig | undefined;
2324
+ /**
2325
+ * Add a user repo. Throws when the id already exists. The `addedAt`
2326
+ * timestamp defaults to `now()` when not provided. Persists to disk.
2327
+ */
2328
+ addUserRepo(input: Omit<UserRepoConfig, "source">): Promise<UserRepoConfig>;
2329
+ /**
2330
+ * Update an existing repo by id (partial). Throws when not found.
2331
+ * Persists to disk.
2332
+ */
2333
+ updateRepo(repoId: string, patch: Partial<RepoConfig>): Promise<AnyRepoConfig>;
2334
+ /**
2335
+ * Remove a user repo. Throws when the repo is a default or does not exist.
2336
+ * Persists to disk.
2337
+ */
2338
+ removeUserRepo(repoId: string): Promise<void>;
2339
+ /**
2340
+ * Disable a repo (any source). Useful for the "Disable" button on default
2341
+ * repos. Persists to disk.
2342
+ */
2343
+ disableRepo(repoId: string): Promise<AnyRepoConfig>;
2344
+ /** Inverse of {@link disableRepo}. */
2345
+ enableRepo(repoId: string): Promise<AnyRepoConfig>;
2346
+ /** Change which repo the UI surfaces as the default. Persists to disk. */
2347
+ setDefaultRepoId(repoId: string): Promise<void>;
2348
+ getDefaultRepoId(): string | null;
2349
+ /** Returns the configured `now` provider — exposed for `bootstrapDefaults`. */
2350
+ getNow(): () => string;
2351
+ /**
2352
+ * Replace the in-memory config and persist it. Used by helpers like
2353
+ * `bootstrapDefaults` that build a new config wholesale (rather than
2354
+ * mutating a single field).
2355
+ */
2356
+ replaceConfig(next: ReposFile): Promise<ReposFile>;
2357
+ private mutate;
2358
+ private emit;
2359
+ /**
2360
+ * Default `fs.watch` adapter. Public so tests can wrap a real watcher
2361
+ * with a debounce trampoline if they need to.
2362
+ */
2363
+ private defaultCreateFsWatcher;
2364
+ private scheduleReload;
2144
2365
  }
2145
2366
  /** Factory: creates a `ReposStore` bound to a specific config path. */
2146
- declare function createReposStore(configPath: string, options?: Omit<ReposStoreOptions, "loader">): ReposStore;
2367
+ export declare function createReposStore(configPath: string, options?: Omit<ReposStoreOptions, "loader">): ReposStore;
2147
2368
  /** Error: tried to add a repo whose id already exists. */
2148
- declare class RepoAlreadyExistsError extends Error {
2149
- readonly repoId: string;
2150
- constructor(repoId: string);
2369
+ export declare class RepoAlreadyExistsError extends Error {
2370
+ readonly repoId: string;
2371
+ constructor(repoId: string);
2151
2372
  }
2152
2373
  /** Error: looked up a repo id that isn't present in the current config. */
2153
- declare class RepoNotFoundError extends Error {
2154
- readonly repoId: string;
2155
- constructor(repoId: string);
2374
+ export declare class RepoNotFoundError extends Error {
2375
+ readonly repoId: string;
2376
+ constructor(repoId: string);
2156
2377
  }
2157
2378
  /** Error: tried to remove a default repo (defaults are disable-only). */
2158
- declare class CannotRemoveDefaultRepoError extends Error {
2159
- readonly repoId: string;
2160
- constructor(repoId: string);
2379
+ export declare class CannotRemoveDefaultRepoError extends Error {
2380
+ readonly repoId: string;
2381
+ constructor(repoId: string);
2161
2382
  }
2162
2383
  /**
2163
2384
  * Bootstrap helper — invokes `ensureDefaultsInstalled` on the store to
@@ -2166,8 +2387,9 @@ declare class CannotRemoveDefaultRepoError extends Error {
2166
2387
  * Lives here (not in `default-repos.ts`) to keep the default-repo module
2167
2388
  * free of store concerns.
2168
2389
  */
2169
- declare function bootstrapDefaults(store: ReposStore): Promise<ReposFile>;
2170
-
2390
+ export declare function bootstrapDefaults(store: ReposStore): Promise<ReposFile>;
2391
+ //#endregion
2392
+ //#region src/repo-manager/index.d.ts
2171
2393
  /**
2172
2394
  * Skill & Agent v2 — Client RepoManager (M3)
2173
2395
  *
@@ -2190,181 +2412,179 @@ declare function bootstrapDefaults(store: ReposStore): Promise<ReposFile>;
2190
2412
  *
2191
2413
  * @see docs/architecture/skill-agent-v2-repo.md §5.3 RepoManager
2192
2414
  */
2193
- interface RepoManagerOptions {
2194
- store: ReposStore;
2195
- gitClient: GitClient;
2196
- /** Override the clock for deterministic tests. */
2197
- now?: () => string;
2198
- /** Skip the actual git clone (used by tests). When true, the
2199
- * filesystem-side mkdir is the only side effect. */
2200
- skipClone?: boolean;
2201
- }
2202
- interface AddUserRepoInput {
2203
- /** Upstream URL the user pasted in. */
2204
- url: string;
2205
- /** Branch to track. Auto-detected from upstream when omitted. */
2206
- branch?: string;
2207
- /** Optional display name (defaults to id). */
2208
- name?: string;
2209
- /** Whether this repo participates in scheduled syncs. Defaults to true. */
2210
- enabled?: boolean;
2211
- /** Route git traffic via the server proxy (default true). */
2212
- useProxy?: boolean;
2213
- }
2214
- interface AddUserRepoResult {
2215
- repo: UserRepoConfig;
2216
- branch: string;
2217
- cloned: boolean;
2415
+ export interface RepoManagerOptions {
2416
+ store: ReposStore;
2417
+ gitClient: GitClient;
2418
+ /** Override the clock for deterministic tests. */
2419
+ now?: () => string;
2420
+ /** Skip the actual git clone (used by tests). When true, the
2421
+ * filesystem-side mkdir is the only side effect. */
2422
+ skipClone?: boolean;
2423
+ }
2424
+ export interface AddUserRepoInput {
2425
+ /** Upstream URL the user pasted in. */
2426
+ url: string;
2427
+ /** Branch to track. Auto-detected from upstream when omitted. */
2428
+ branch?: string;
2429
+ /** Optional display name (defaults to id). */
2430
+ name?: string;
2431
+ /** Whether this repo participates in scheduled syncs. Defaults to true. */
2432
+ enabled?: boolean;
2433
+ /** Route git traffic via the server proxy (default true). */
2434
+ useProxy?: boolean;
2435
+ }
2436
+ export interface AddUserRepoResult {
2437
+ repo: UserRepoConfig;
2438
+ branch: string;
2439
+ cloned: boolean;
2218
2440
  }
2219
2441
  /** Snapshot of a sync run, suitable for UI rendering. */
2220
- interface SyncReport {
2221
- pulls: Array<{
2222
- repoId: string;
2223
- status: "ok" | "error";
2224
- result?: PullResult;
2225
- error?: string;
2226
- }>;
2442
+ export interface SyncReport {
2443
+ pulls: Array<{
2444
+ repoId: string;
2445
+ status: "ok" | "error";
2446
+ result?: PullResult;
2447
+ error?: string;
2448
+ }>;
2227
2449
  }
2228
2450
  /** Sentinel errors. */
2229
- declare class RepoManagerError extends Error {
2230
- constructor(message: string);
2231
- }
2232
- declare class InvalidRepoUrlError extends RepoManagerError {
2233
- }
2234
- declare class RepoCloneConflictError extends RepoManagerError {
2235
- }
2236
- declare class RepoNotInStoreError extends RepoManagerError {
2237
- }
2238
- declare class RepoManager {
2239
- private readonly store;
2240
- private readonly git;
2241
- private readonly now;
2242
- private readonly skipClone;
2243
- constructor(opts: RepoManagerOptions);
2244
- /**
2245
- * Clone every enabled default repo that doesn't have a local clone
2246
- * yet. Failures on individual repos are recorded in `lastSyncStatus`
2247
- * but do NOT abort the loop the UI surfaces per-repo state and the
2248
- * user can retry.
2249
- *
2250
- * Per spec §3.1: iterate all default repos; the loop honors `enabled=false` and
2251
- * disables (rather than removes) repos the user has turned off.
2252
- */
2253
- ensureDefaults(): Promise<SyncReport>;
2254
- /**
2255
- * Pull a single repo. Updates `lastSync*` fields on success or failure.
2256
- * Returns the raw `PullResult` so callers can surface fetch progress.
2257
- */
2258
- pullOne(repoId: string): Promise<PullResult>;
2259
- /** Pull every enabled repo. Per-repo failures don't abort the run. */
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;
2309
- /**
2310
- * Validate URL, derive an id, detect the branch via `git ls-remote`,
2311
- * then add the entry to the store and trigger a clone.
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
- *
2318
- * Spec §5.3 says "branch detection" happens BEFORE the store write so
2319
- * the resulting `repos.json` is fully populated. The clone is async
2320
- * but the function returns synchronously once the store is updated
2321
- * (cloning happens via `ensureDefaults`-style background fire).
2322
- *
2323
- * For tests with `skipClone: true`, the clone is skipped entirely.
2324
- */
2325
- addUserRepo(input: AddUserRepoInput): Promise<AddUserRepoResult>;
2326
- /**
2327
- * Remove a user-added repo. Throws when:
2328
- * - the repo is unknown
2329
- * - the repo is a default (use `disableRepo` instead — store enforces)
2330
- *
2331
- * The local clone is deleted via `fs.rm`. If the local dir is
2332
- * already gone we silently succeed (idempotent re-remove).
2333
- */
2334
- removeUserRepo(repoId: string): Promise<void>;
2335
- disableRepo(repoId: string): Promise<AnyRepoConfig>;
2336
- enableRepo(repoId: string): Promise<AnyRepoConfig>;
2337
- /** `true` when `~/.serviceme/repos/<id>/` exists on disk. */
2338
- hasLocalClone(repoId: string): Promise<boolean>;
2339
- /** Force-create the SERVICEME home directory tree (idempotent). */
2340
- ensureHome(): Promise<void>;
2341
- /**
2342
- * Returns `true` when `p` contains a `.git` entry — i.e. it is an
2343
- * initialised git repository and safe to `pull`. Empty directories
2344
- * (e.g. from an interrupted clone) return `false`.
2345
- */
2346
- private isValidGitRepo;
2347
- private pathExists;
2348
- }
2349
-
2451
+ export declare class RepoManagerError extends Error {
2452
+ constructor(message: string);
2453
+ }
2454
+ export declare class InvalidRepoUrlError extends RepoManagerError {}
2455
+ export declare class RepoCloneConflictError extends RepoManagerError {}
2456
+ export declare class RepoNotInStoreError extends RepoManagerError {}
2457
+ export declare class RepoManager {
2458
+ private readonly store;
2459
+ private readonly git;
2460
+ private readonly now;
2461
+ private readonly skipClone;
2462
+ constructor(opts: RepoManagerOptions);
2463
+ /**
2464
+ * Clone every enabled default repo that doesn't have a local clone
2465
+ * yet. Failures on individual repos are recorded in `lastSyncStatus`
2466
+ * but do NOT abort the loop — the UI surfaces per-repo state and the
2467
+ * user can retry.
2468
+ *
2469
+ * Per spec §3.1: iterate all default repos; the loop honors `enabled=false` and
2470
+ * disables (rather than removes) repos the user has turned off.
2471
+ */
2472
+ ensureDefaults(): Promise<SyncReport>;
2473
+ /**
2474
+ * Pull a single repo. Updates `lastSync*` fields on success or failure.
2475
+ * Returns the raw `PullResult` so callers can surface fetch progress.
2476
+ */
2477
+ pullOne(repoId: string): Promise<PullResult>;
2478
+ /** Pull every enabled repo. Per-repo failures don't abort the run. */
2479
+ pullAll(): Promise<SyncReport>;
2480
+ /**
2481
+ * Ensure a repository exists locally and is detached at an exact
2482
+ * commit. Used by Copilot content restoration: never pulls to a
2483
+ * branch head, so a declaration always resolves to the reviewed
2484
+ * content on every machine.
2485
+ */
2486
+ ensureAtCommit(input: {
2487
+ repository: Pick<RepoConfig, "id" | "url" | "useProxy">;
2488
+ commit: string;
2489
+ }): Promise<{
2490
+ localPath: string;
2491
+ commit: string;
2492
+ }>;
2493
+ /**
2494
+ * Ensure a v2 catalog source is materialized under repos/<sourceId>
2495
+ * exactly like a git checkout (Task 10, ruling #1).
2496
+ *
2497
+ * The catalog store (repos.json) never held catalog sources, so the
2498
+ * source-lifecycle task owns this path: content arrives from the
2499
+ * provider as an extracted tree, is unpacked under the managed
2500
+ * source directory, and is verified against the immutable digest
2501
+ * before the directory becomes visible to resolvers.
2502
+ *
2503
+ * Callers that only need the directory contract (source availability
2504
+ * is a reposDir/<source-id> directory check) can pass a provider
2505
+ * that stages the tree; the method itself never writes store
2506
+ * entries marketplace sources stay manifest-only.
2507
+ */
2508
+ ensureCatalogSource(input: {
2509
+ sourceId: string;
2510
+ provider: {
2511
+ /** Stage the catalog payload into the target directory. */
2512
+ materialize: (targetDir: string) => Promise<void>;
2513
+ };
2514
+ }): Promise<{
2515
+ localPath: string;
2516
+ }>;
2517
+ /**
2518
+ * Resolve a unique store id for a repo being added.
2519
+ *
2520
+ * The base id derives from the URL (`owner-repo`). When it is taken
2521
+ * by the SAME url with a DIFFERENT branch user repo or platform
2522
+ * default alike — derive `base-<branch>` so users can track several
2523
+ * branches of one repository side by side. Genuine duplicates (same
2524
+ * url + same branch) and cross-url id collisions still throw
2525
+ * RepoCloneConflictError.
2526
+ */
2527
+ private resolveUserRepoId;
2528
+ /**
2529
+ * Validate URL, derive an id, detect the branch via `git ls-remote`,
2530
+ * then add the entry to the store and trigger a clone.
2531
+ *
2532
+ * The base id derives from the URL. Re-adding the same URL with a
2533
+ * different branch is allowed it gets a branch-suffixed id
2534
+ * (`owner-repo-<branch>`) so multiple branches of one repository can
2535
+ * be tracked side by side.
2536
+ *
2537
+ * Spec §5.3 says "branch detection" happens BEFORE the store write so
2538
+ * the resulting `repos.json` is fully populated. The clone is async
2539
+ * but the function returns synchronously once the store is updated
2540
+ * (cloning happens via `ensureDefaults`-style background fire).
2541
+ *
2542
+ * For tests with `skipClone: true`, the clone is skipped entirely.
2543
+ */
2544
+ addUserRepo(input: AddUserRepoInput): Promise<AddUserRepoResult>;
2545
+ /**
2546
+ * Remove a user-added repo. Throws when:
2547
+ * - the repo is unknown
2548
+ * - the repo is a default (use `disableRepo` instead — store enforces)
2549
+ *
2550
+ * The local clone is deleted via `fs.rm`. If the local dir is
2551
+ * already gone we silently succeed (idempotent re-remove).
2552
+ */
2553
+ removeUserRepo(repoId: string): Promise<void>;
2554
+ disableRepo(repoId: string): Promise<AnyRepoConfig>;
2555
+ enableRepo(repoId: string): Promise<AnyRepoConfig>;
2556
+ /** `true` when `~/.serviceme/repos/<id>/` exists on disk. */
2557
+ hasLocalClone(repoId: string): Promise<boolean>;
2558
+ /** Force-create the SERVICEME home directory tree (idempotent). */
2559
+ ensureHome(): Promise<void>;
2560
+ /**
2561
+ * Returns `true` when `p` contains a `.git` entry — i.e. it is an
2562
+ * initialised git repository and safe to `pull`. Empty directories
2563
+ * (e.g. from an interrupted clone) return `false`.
2564
+ */
2565
+ private isValidGitRepo;
2566
+ private pathExists;
2567
+ }
2568
+ //#endregion
2569
+ //#region src/repos/default-repos.d.ts
2350
2570
  /**
2351
2571
  * Hard-coded catalog of repositories SERVICEME ships with. The id, URL and
2352
2572
  * branch are pinned by the design doc (§12) and **must not** change without
2353
2573
  * an owner-approved migration. The order here mirrors the on-disk
2354
2574
  * `repos.json` order (§3.1) which the UI relies on.
2355
2575
  */
2356
- declare const DEFAULT_REPO_ID = "medalsoftchina-ms-skills";
2576
+ export declare const DEFAULT_REPO_ID = "medalsoftchina-ms-skills";
2357
2577
  declare const FIXED_ADDED_AT = "2026-06-29T00:00:00.000Z";
2358
2578
  /** Returns a deep-ish clone of every default repo with a fresh `addedAt`. */
2359
- declare function getAllDefaultRepoConfigs(now?: () => string): DefaultRepoConfig[];
2579
+ export declare function getAllDefaultRepoConfigs(now?: () => string): DefaultRepoConfig[];
2360
2580
  /** Returns a single default repo by id, or `undefined` when not in the catalog. */
2361
- declare function getDefaultRepoConfig(id: string, now?: () => string): DefaultRepoConfig | undefined;
2581
+ export declare function getDefaultRepoConfig(id: string, now?: () => string): DefaultRepoConfig | undefined;
2362
2582
  /**
2363
2583
  * Idempotent: returns a fresh `ReposFile` containing the default set, or —
2364
2584
  * when `existing` already has all defaults — returns it untouched (still cloned
2365
2585
  * to keep callers from accidentally mutating shared state).
2366
2586
  */
2367
- declare function buildDefaultReposFile(now?: () => string, existing?: ReposFile): ReposFile;
2587
+ export declare function buildDefaultReposFile(now?: () => string, existing?: ReposFile): ReposFile;
2368
2588
  /**
2369
2589
  * `ensureDefaultsInstalled(existing)` — pure helper that returns either
2370
2590
  * `existing` (when defaults are already present and up to date) or a merged
@@ -2372,318 +2592,331 @@ declare function buildDefaultReposFile(now?: () => string, existing?: ReposFile)
2372
2592
  * existing ones. The companion `ensureDefaultsInstalledInStore` below is the
2373
2593
  * mutating, store-bound counterpart.
2374
2594
  */
2375
- declare function ensureDefaultsInstalled(existing: ReposFile, now?: () => string): {
2376
- config: ReposFile;
2377
- installed: string[];
2595
+ export declare function ensureDefaultsInstalled(existing: ReposFile, now?: () => string): {
2596
+ config: ReposFile;
2597
+ installed: string[];
2378
2598
  };
2379
-
2380
- declare class DaemonLogger {
2381
- private readonly logPath;
2382
- constructor(workspacePath: string, options?: {
2383
- logPath?: string;
2384
- });
2385
- getLogPath(): string;
2386
- log(level: "info" | "warn" | "error", message: string): void;
2387
- private rotateIfNeeded;
2388
- }
2389
-
2599
+ //#endregion
2600
+ //#region src/scheduled-tasks/daemon/DaemonLogger.d.ts
2601
+ export declare class DaemonLogger {
2602
+ private readonly logPath;
2603
+ constructor(workspacePath: string, options?: {
2604
+ logPath?: string;
2605
+ });
2606
+ getLogPath(): string;
2607
+ log(level: "info" | "warn" | "error", message: string): void;
2608
+ private rotateIfNeeded;
2609
+ }
2610
+ //#endregion
2611
+ //#region src/scheduled-tasks/daemon/PidManager.d.ts
2390
2612
  interface PidManagerOptions {
2391
- /**
2392
- * Override the on-disk PID path. Defaults to
2393
- * `<workspacePath>/.serviceme/scheduler.pid` for backward compat.
2394
- * V2 callers pass an absolute path (e.g. `getSchedulerPidPath()`)
2395
- * to read the global daemon PID file.
2396
- */
2397
- pidPath?: string;
2398
- }
2399
- declare class PidManager {
2400
- private readonly pidPath;
2401
- constructor(workspacePath: string, options?: PidManagerOptions);
2402
- getPidPath(): string;
2403
- writePid(pid: number): void;
2404
- readPid(): number | null;
2405
- removePid(): void;
2406
- isProcessRunning(pid: number): boolean;
2407
- getRunningPid(): number | null;
2408
- }
2409
-
2613
+ /**
2614
+ * Override the on-disk PID path. Defaults to
2615
+ * `<workspacePath>/.serviceme/scheduler.pid` for backward compat.
2616
+ * V2 callers pass an absolute path (e.g. `getSchedulerPidPath()`)
2617
+ * to read the global daemon PID file.
2618
+ */
2619
+ pidPath?: string;
2620
+ }
2621
+ export declare class PidManager {
2622
+ private readonly pidPath;
2623
+ constructor(workspacePath: string, options?: PidManagerOptions);
2624
+ getPidPath(): string;
2625
+ writePid(pid: number): void;
2626
+ readPid(): number | null;
2627
+ removePid(): void;
2628
+ isProcessRunning(pid: number): boolean;
2629
+ getRunningPid(): number | null;
2630
+ }
2631
+ //#endregion
2632
+ //#region src/scheduled-tasks/executors/types.d.ts
2410
2633
  interface ExecutorResult {
2411
- status: TaskExecutionStatus;
2412
- output?: string;
2413
- error?: string;
2634
+ status: TaskExecutionStatus;
2635
+ output?: string;
2636
+ error?: string;
2414
2637
  }
2415
2638
  interface TaskExecutor {
2416
- execute(payload: unknown, abortSignal?: AbortSignal): Promise<ExecutorResult>;
2639
+ execute(payload: unknown, abortSignal?: AbortSignal): Promise<ExecutorResult>;
2417
2640
  }
2418
2641
  type OutputEventCallback = (stream: "stdout" | "stderr", data: string) => void;
2419
2642
  interface StreamingExecutorHandle {
2420
- result: Promise<ExecutorResult>;
2421
- cancel: () => void;
2643
+ result: Promise<ExecutorResult>;
2644
+ cancel: () => void;
2422
2645
  }
2423
2646
  interface StreamingTaskExecutor extends TaskExecutor {
2424
- executeStreaming(payload: unknown, onOutput: OutputEventCallback, abortSignal?: AbortSignal): StreamingExecutorHandle;
2425
- }
2426
- declare function isStreamingTaskExecutor(executor: TaskExecutor): executor is StreamingTaskExecutor;
2427
-
2428
- declare class GithubCopilotCliExecutor implements StreamingTaskExecutor {
2429
- execute(payload: unknown, abortSignal?: AbortSignal): Promise<ExecutorResult>;
2430
- executeStreaming(payload: unknown, onOutput: OutputEventCallback, abortSignal?: AbortSignal): StreamingExecutorHandle;
2431
- }
2432
-
2433
- declare class HttpRequestExecutor implements TaskExecutor {
2434
- execute(payload: unknown, abortSignal?: AbortSignal): Promise<ExecutorResult>;
2435
- }
2436
-
2437
- declare class ShellExecutor implements StreamingTaskExecutor {
2438
- execute(payload: unknown, abortSignal?: AbortSignal): Promise<ExecutorResult>;
2439
- executeStreaming(payload: unknown, onOutput: OutputEventCallback, abortSignal?: AbortSignal): StreamingExecutorHandle;
2440
- }
2441
-
2442
- declare function getExecutor(taskType: ScheduledTaskType): TaskExecutor;
2443
-
2444
- declare function validateTaskPayload(taskType: ScheduledTaskType, payload: TaskPayload): void;
2647
+ executeStreaming(payload: unknown, onOutput: OutputEventCallback, abortSignal?: AbortSignal): StreamingExecutorHandle;
2648
+ }
2649
+ export declare function isStreamingTaskExecutor(executor: TaskExecutor): executor is StreamingTaskExecutor;
2650
+ //#endregion
2651
+ //#region src/scheduled-tasks/executors/GithubCopilotCliExecutor.d.ts
2652
+ export declare class GithubCopilotCliExecutor implements StreamingTaskExecutor {
2653
+ execute(payload: unknown, abortSignal?: AbortSignal): Promise<ExecutorResult>;
2654
+ executeStreaming(payload: unknown, onOutput: OutputEventCallback, abortSignal?: AbortSignal): StreamingExecutorHandle;
2655
+ }
2656
+ //#endregion
2657
+ //#region src/scheduled-tasks/executors/HttpRequestExecutor.d.ts
2658
+ export declare class HttpRequestExecutor implements TaskExecutor {
2659
+ execute(payload: unknown, abortSignal?: AbortSignal): Promise<ExecutorResult>;
2660
+ }
2661
+ //#endregion
2662
+ //#region src/scheduled-tasks/executors/ShellExecutor.d.ts
2663
+ export declare class ShellExecutor implements StreamingTaskExecutor {
2664
+ execute(payload: unknown, abortSignal?: AbortSignal): Promise<ExecutorResult>;
2665
+ executeStreaming(payload: unknown, onOutput: OutputEventCallback, abortSignal?: AbortSignal): StreamingExecutorHandle;
2666
+ }
2667
+ //#endregion
2668
+ //#region src/scheduled-tasks/executors/index.d.ts
2669
+ export declare function getExecutor(taskType: ScheduledTaskType): TaskExecutor;
2670
+ //#endregion
2671
+ //#region src/scheduled-tasks/TaskConfigManager.d.ts
2672
+ export declare function validateTaskPayload(taskType: ScheduledTaskType, payload: TaskPayload): void;
2445
2673
  interface CreateTaskInput {
2446
- name: string;
2447
- description?: string;
2448
- scheduleType: "cron" | "interval";
2449
- schedule: string;
2450
- taskType: ScheduledTaskType;
2451
- payload: TaskPayload;
2452
- workspace: TaskWorkspaceRef;
2453
- enabled?: boolean;
2674
+ name: string;
2675
+ description?: string;
2676
+ scheduleType: "cron" | "interval";
2677
+ schedule: string;
2678
+ taskType: ScheduledTaskType;
2679
+ payload: TaskPayload;
2680
+ workspace: TaskWorkspaceRef;
2681
+ enabled?: boolean;
2454
2682
  }
2455
2683
  interface EditTaskInput {
2456
- name?: string;
2457
- description?: string;
2458
- scheduleType?: "cron" | "interval";
2459
- schedule?: string;
2460
- taskType?: ScheduledTaskType;
2461
- payload?: TaskPayload;
2462
- workspace?: TaskWorkspaceRef;
2463
- enabled?: boolean;
2684
+ name?: string;
2685
+ description?: string;
2686
+ scheduleType?: "cron" | "interval";
2687
+ schedule?: string;
2688
+ taskType?: ScheduledTaskType;
2689
+ payload?: TaskPayload;
2690
+ workspace?: TaskWorkspaceRef;
2691
+ enabled?: boolean;
2464
2692
  }
2465
2693
  interface TaskConfigManagerOptions {
2466
- /**
2467
- * Override the on-disk config path. Defaults to the global
2468
- * `~/.serviceme/scheduled-tasks.json`. Tests use this to point at a tmp
2469
- * directory; production code should leave it unset.
2470
- */
2471
- configPath?: string;
2472
- /**
2473
- * Workspace context used when a legacy v1 config is read. v1 tasks had no
2474
- * per-task workspace, so the manager needs a fallback to attach when
2475
- * auto-migrating. Required only if the underlying file might still be v1.
2476
- */
2477
- workspaceContext?: TaskWorkspaceRef;
2478
- /**
2479
- * Override the path where malformed-config diagnostic entries are appended.
2480
- * Defaults to `~/.serviceme/migration-failures.json`. Tests can point at a
2481
- * tmp file to assert failures were recorded.
2482
- */
2483
- migrationFailuresPath?: string;
2484
- /**
2485
- * Inject a logger for the manager's recovery / migration warnings. Defaults
2486
- * to `console.warn`. Tests pass a `vi.fn`/`mock.fn` to assert the warnings
2487
- * were emitted.
2488
- */
2489
- logger?: (message: string) => void;
2490
- }
2491
- declare class TaskConfigManager {
2492
- private readonly configPath;
2493
- private readonly workspaceContext?;
2494
- private readonly migrationFailuresPath?;
2495
- private readonly logger?;
2496
- constructor(options?: TaskConfigManagerOptions);
2497
- getConfigPath(): string;
2498
- readConfig(): ScheduledTasksConfig;
2499
- private warn;
2500
- private recordMalformedConfigFailure;
2501
- private writeConfig;
2502
- listTasks(): ScheduledTask[];
2503
- getTask(id: string): ScheduledTask | undefined;
2504
- getTaskByName(name: string): ScheduledTask | undefined;
2505
- createTask(input: CreateTaskInput): ScheduledTask;
2506
- editTask(id: string, input: EditTaskInput): ScheduledTask;
2507
- deleteTask(id: string): ScheduledTask;
2508
- toggleTask(id: string, enabled: boolean): ScheduledTask;
2509
- }
2510
-
2694
+ /**
2695
+ * Override the on-disk config path. Defaults to the global
2696
+ * `~/.serviceme/scheduled-tasks.json`. Tests use this to point at a tmp
2697
+ * directory; production code should leave it unset.
2698
+ */
2699
+ configPath?: string;
2700
+ /**
2701
+ * Workspace context used when a legacy v1 config is read. v1 tasks had no
2702
+ * per-task workspace, so the manager needs a fallback to attach when
2703
+ * auto-migrating. Required only if the underlying file might still be v1.
2704
+ */
2705
+ workspaceContext?: TaskWorkspaceRef;
2706
+ /**
2707
+ * Override the path where malformed-config diagnostic entries are appended.
2708
+ * Defaults to `~/.serviceme/migration-failures.json`. Tests can point at a
2709
+ * tmp file to assert failures were recorded.
2710
+ */
2711
+ migrationFailuresPath?: string;
2712
+ /**
2713
+ * Inject a logger for the manager's recovery / migration warnings. Defaults
2714
+ * to `console.warn`. Tests pass a `vi.fn`/`mock.fn` to assert the warnings
2715
+ * were emitted.
2716
+ */
2717
+ logger?: (message: string) => void;
2718
+ }
2719
+ export declare class TaskConfigManager {
2720
+ private readonly configPath;
2721
+ private readonly workspaceContext?;
2722
+ private readonly migrationFailuresPath?;
2723
+ private readonly logger?;
2724
+ constructor(options?: TaskConfigManagerOptions);
2725
+ getConfigPath(): string;
2726
+ readConfig(): ScheduledTasksConfig;
2727
+ private warn;
2728
+ private recordMalformedConfigFailure;
2729
+ private writeConfig;
2730
+ listTasks(): ScheduledTask[];
2731
+ getTask(id: string): ScheduledTask | undefined;
2732
+ getTaskByName(name: string): ScheduledTask | undefined;
2733
+ createTask(input: CreateTaskInput): ScheduledTask;
2734
+ editTask(id: string, input: EditTaskInput): ScheduledTask;
2735
+ deleteTask(id: string): ScheduledTask;
2736
+ toggleTask(id: string, enabled: boolean): ScheduledTask;
2737
+ }
2738
+ //#endregion
2739
+ //#region src/scheduled-tasks/TaskLogManager.d.ts
2511
2740
  interface AppendLogInput {
2512
- taskId: string;
2513
- taskName: string;
2514
- startedAt: string;
2515
- finishedAt: string;
2516
- status: Exclude<TaskExecutionStatus, "running">;
2517
- output?: string;
2518
- error?: string;
2741
+ taskId: string;
2742
+ taskName: string;
2743
+ startedAt: string;
2744
+ finishedAt: string;
2745
+ status: Exclude<TaskExecutionStatus, "running">;
2746
+ output?: string;
2747
+ error?: string;
2519
2748
  }
2520
2749
  interface TaskLogManagerOptions {
2521
- /**
2522
- * Override the on-disk log path. Defaults to the global
2523
- * `~/.serviceme/scheduled-tasks-log.json`. Tests use this to point at a
2524
- * tmp directory; production code should leave it unset.
2525
- */
2526
- logPath?: string;
2527
- }
2528
- declare class TaskLogManager {
2529
- private readonly logPath;
2530
- constructor(options?: TaskLogManagerOptions);
2531
- getLogPath(): string;
2532
- private readLogFile;
2533
- private backupCorruptedFile;
2534
- private writeLogFile;
2535
- appendLog(input: AppendLogInput): TaskExecutionLog;
2536
- getLogs(options?: {
2537
- taskId?: string;
2538
- limit?: number;
2539
- }): {
2540
- logs: TaskExecutionLog[];
2541
- total: number;
2542
- };
2543
- clearLogs(taskId?: string): number;
2544
- }
2545
-
2750
+ /**
2751
+ * Override the on-disk log path. Defaults to the global
2752
+ * `~/.serviceme/scheduled-tasks-log.json`. Tests use this to point at a
2753
+ * tmp directory; production code should leave it unset.
2754
+ */
2755
+ logPath?: string;
2756
+ }
2757
+ export declare class TaskLogManager {
2758
+ private readonly logPath;
2759
+ constructor(options?: TaskLogManagerOptions);
2760
+ getLogPath(): string;
2761
+ private readLogFile;
2762
+ private backupCorruptedFile;
2763
+ private writeLogFile;
2764
+ appendLog(input: AppendLogInput): TaskExecutionLog;
2765
+ getLogs(options?: {
2766
+ taskId?: string;
2767
+ limit?: number;
2768
+ }): {
2769
+ logs: TaskExecutionLog[];
2770
+ total: number;
2771
+ };
2772
+ clearLogs(taskId?: string): number;
2773
+ }
2774
+ //#endregion
2775
+ //#region src/scheduled-tasks/daemon/SchedulerDaemonV2.d.ts
2546
2776
  interface SchedulerDaemonV2Options {
2547
- /**
2548
- * Override the executor factory. Production callers should leave this
2549
- * undefined; tests inject a fake to drive the execution branch without
2550
- * spawning real subprocesses.
2551
- */
2552
- getExecutor?: typeof getExecutor;
2553
- /** Override the config manager. Tests inject a fake pointing at a tmp dir. */
2554
- configManager?: TaskConfigManager;
2555
- /** Override the log manager. */
2556
- logManager?: TaskLogManager;
2557
- /** Override the PID manager. */
2558
- pidManager?: PidManager;
2559
- /** Override the daemon logger (for tests; the default writes to ~/.serviceme/scheduler.log). */
2560
- logger?: DaemonLogger;
2561
- /** Override the startup lock acquisition (tests use this to inject "lock held" / "lock free"). */
2562
- tryAcquireLock?: () => boolean;
2563
- /** Override the startup lock release. */
2564
- releaseLock?: () => void;
2565
- /**
2566
- * Override the PID file existence + process liveness check. Production
2567
- * reads PID file + `process.kill(pid, 0)`; tests inject a stub.
2568
- */
2569
- getRunningPid?: () => number | null;
2570
- }
2571
- declare class SchedulerDaemonV2 {
2572
- private readonly configManager;
2573
- private readonly logManager;
2574
- private readonly pidManager;
2575
- private readonly logger;
2576
- private readonly getExecutor;
2577
- private readonly tryAcquireLock;
2578
- private readonly releaseLock;
2579
- private readonly getRunningPid;
2580
- private tickTimer;
2581
- private running;
2582
- private readonly sigtermHandler;
2583
- private readonly sigintHandler;
2584
- private startTime;
2585
- private lastRun;
2586
- private workspaceLocks;
2587
- constructor(options?: SchedulerDaemonV2Options);
2588
- start(): void;
2589
- stop(): void;
2590
- private tick;
2591
- private disableTaskForMissingWorkspace;
2592
- private shouldRun;
2593
- private executeTask;
2594
- getStatus(): {
2595
- running: boolean;
2596
- pid: number;
2597
- uptimeSeconds: number | null;
2598
- tasksRegistered: number;
2599
- tasksEnabled: number;
2600
- pidFile: string;
2601
- };
2602
- }
2603
-
2777
+ /**
2778
+ * Override the executor factory. Production callers should leave this
2779
+ * undefined; tests inject a fake to drive the execution branch without
2780
+ * spawning real subprocesses.
2781
+ */
2782
+ getExecutor?: typeof getExecutor;
2783
+ /** Override the config manager. Tests inject a fake pointing at a tmp dir. */
2784
+ configManager?: TaskConfigManager;
2785
+ /** Override the log manager. */
2786
+ logManager?: TaskLogManager;
2787
+ /** Override the PID manager. */
2788
+ pidManager?: PidManager;
2789
+ /** Override the daemon logger (for tests; the default writes to ~/.serviceme/scheduler.log). */
2790
+ logger?: DaemonLogger;
2791
+ /** Override the startup lock acquisition (tests use this to inject "lock held" / "lock free"). */
2792
+ tryAcquireLock?: () => boolean;
2793
+ /** Override the startup lock release. */
2794
+ releaseLock?: () => void;
2795
+ /**
2796
+ * Override the PID file existence + process liveness check. Production
2797
+ * reads PID file + `process.kill(pid, 0)`; tests inject a stub.
2798
+ */
2799
+ getRunningPid?: () => number | null;
2800
+ }
2801
+ export declare class SchedulerDaemonV2 {
2802
+ private readonly configManager;
2803
+ private readonly logManager;
2804
+ private readonly pidManager;
2805
+ private readonly logger;
2806
+ private readonly getExecutor;
2807
+ private readonly tryAcquireLock;
2808
+ private readonly releaseLock;
2809
+ private readonly getRunningPid;
2810
+ private tickTimer;
2811
+ private running;
2812
+ private readonly sigtermHandler;
2813
+ private readonly sigintHandler;
2814
+ private startTime;
2815
+ private lastRun;
2816
+ private workspaceLocks;
2817
+ constructor(options?: SchedulerDaemonV2Options);
2818
+ start(): void;
2819
+ stop(): void;
2820
+ private tick;
2821
+ private disableTaskForMissingWorkspace;
2822
+ private shouldRun;
2823
+ private executeTask;
2824
+ getStatus(): {
2825
+ running: boolean;
2826
+ pid: number;
2827
+ uptimeSeconds: number | null;
2828
+ tasksRegistered: number;
2829
+ tasksEnabled: number;
2830
+ pidFile: string;
2831
+ };
2832
+ }
2833
+ //#endregion
2834
+ //#region src/scheduled-tasks/migration/MigrateToGlobal.d.ts
2604
2835
  interface MigrateToGlobalOptions {
2605
- /**
2606
- * Workspace paths to scan for legacy v1 files. May include the current
2607
- * workspace + any persisted in `~/.serviceme/known-workspaces.json`.
2608
- */
2609
- workspacePaths: string[];
2610
- /**
2611
- * Workspace context to apply to each scanned file. The scanner calls the
2612
- * probe for each candidate path to populate path/name/git metadata.
2613
- * Tests can inject a stub that returns synthetic data.
2614
- */
2615
- probe?: (workspacePath: string) => Promise<TaskWorkspaceRef> | TaskWorkspaceRef;
2616
- /**
2617
- * Override the global config path. Tests use this; production should
2618
- * leave it unset to get the standard ~/.serviceme/scheduled-tasks.json.
2619
- */
2620
- globalConfigPath?: string;
2621
- /**
2622
- * Override the migration-failures path. Same convention.
2623
- */
2624
- migrationFailuresPath?: string;
2836
+ /**
2837
+ * Workspace paths to scan for legacy v1 files. May include the current
2838
+ * workspace + any persisted in `~/.serviceme/known-workspaces.json`.
2839
+ */
2840
+ workspacePaths: string[];
2841
+ /**
2842
+ * Workspace context to apply to each scanned file. The scanner calls the
2843
+ * probe for each candidate path to populate path/name/git metadata.
2844
+ * Tests can inject a stub that returns synthetic data.
2845
+ */
2846
+ probe?: (workspacePath: string) => Promise<TaskWorkspaceRef> | TaskWorkspaceRef;
2847
+ /**
2848
+ * Override the global config path. Tests use this; production should
2849
+ * leave it unset to get the standard ~/.serviceme/scheduled-tasks.json.
2850
+ */
2851
+ globalConfigPath?: string;
2852
+ /**
2853
+ * Override the migration-failures path. Same convention.
2854
+ */
2855
+ migrationFailuresPath?: string;
2625
2856
  }
2626
2857
  interface MigrationResult {
2627
- /** Number of v1 files successfully migrated into the global config. */
2628
- migrated: number;
2629
- /** Number of v1 files that failed to parse / migrate. */
2630
- failed: number;
2631
- /** Task names that had to be disambiguated because they appeared in multiple workspaces. */
2632
- conflicts: string[];
2633
- /** Soft issues surfaced by migrateV1ToV2 (e.g. unknown taskType). */
2634
- issues: string[];
2858
+ /** Number of v1 files successfully migrated into the global config. */
2859
+ migrated: number;
2860
+ /** Number of v1 files that failed to parse / migrate. */
2861
+ failed: number;
2862
+ /** Task names that had to be disambiguated because they appeared in multiple workspaces. */
2863
+ conflicts: string[];
2864
+ /** Soft issues surfaced by migrateV1ToV2 (e.g. unknown taskType). */
2865
+ issues: string[];
2635
2866
  }
2636
2867
  /**
2637
2868
  * Run the migration. Idempotent: each v1 file is deleted after processing,
2638
2869
  * so re-running this on a partially-migrated state is safe (the
2639
2870
  * already-migrated files no longer exist; only the remainder is processed).
2640
2871
  */
2641
- declare function migrateToGlobal(options: MigrateToGlobalOptions): Promise<MigrationResult>;
2642
-
2872
+ export declare function migrateToGlobal(options: MigrateToGlobalOptions): Promise<MigrationResult>;
2873
+ //#endregion
2874
+ //#region src/scheduled-tasks/TaskExecutionEngine.d.ts
2643
2875
  interface TaskEventListener {
2644
- onStarted(params: TaskStartedEventParams): void;
2645
- onOutput(params: TaskOutputEventParams): void;
2646
- onCompleted(params: TaskCompletedEventParams): void;
2647
- onFailed(params: TaskFailedEventParams): void;
2648
- onCancelled(params: TaskCancelledEventParams): void;
2649
- }
2650
- declare function resolveTaskExecutionPayload(taskType: ScheduledTaskType, payload: TaskPayload, workspacePath: string): TaskPayload;
2651
- declare class TaskExecutionEngine {
2652
- private readonly getExecutor;
2653
- private readonly running;
2654
- private readonly taskExecutions;
2655
- private listener;
2656
- constructor(getExecutor: (taskType: string) => TaskExecutor);
2657
- setListener(listener: TaskEventListener): void;
2658
- execute(snapshot: TaskExecutionSnapshot): Promise<void>;
2659
- cancel(executionId: string): boolean;
2660
- listRunning(): RunningTaskInfo[];
2661
- dispose(): void;
2662
- }
2663
-
2876
+ onStarted(params: TaskStartedEventParams): void;
2877
+ onOutput(params: TaskOutputEventParams): void;
2878
+ onCompleted(params: TaskCompletedEventParams): void;
2879
+ onFailed(params: TaskFailedEventParams): void;
2880
+ onCancelled(params: TaskCancelledEventParams): void;
2881
+ }
2882
+ export declare function resolveTaskExecutionPayload(taskType: ScheduledTaskType, payload: TaskPayload, workspacePath: string): TaskPayload;
2883
+ export declare class TaskExecutionEngine {
2884
+ private readonly getExecutor;
2885
+ private readonly running;
2886
+ private readonly taskExecutions;
2887
+ private listener;
2888
+ constructor(getExecutor: (taskType: string) => TaskExecutor);
2889
+ setListener(listener: TaskEventListener): void;
2890
+ execute(snapshot: TaskExecutionSnapshot): Promise<void>;
2891
+ cancel(executionId: string): boolean;
2892
+ listRunning(): RunningTaskInfo[];
2893
+ dispose(): void;
2894
+ }
2895
+ //#endregion
2896
+ //#region src/scheduled-tasks/workspace-probe/WorkspaceProbe.d.ts
2664
2897
  /** Result of probing a single workspace. */
2665
2898
  interface ProbeResult {
2666
- /** Always populated; empty fields are left undefined. */
2667
- workspace: TaskWorkspaceRef;
2668
- /** null on success; one of the {@link ProbeError} tags on failure. */
2669
- error: ProbeError | null;
2899
+ /** Always populated; empty fields are left undefined. */
2900
+ workspace: TaskWorkspaceRef;
2901
+ /** null on success; one of the {@link ProbeError} tags on failure. */
2902
+ error: ProbeError | null;
2670
2903
  }
2671
2904
  type ProbeError = "path-not-found" | "not-a-git-repo" | "git-timeout" | "git-error";
2672
2905
  interface ProbeOptions {
2673
- /** Timeout for each git invocation in ms. Default: 2000. */
2674
- timeoutMs?: number;
2675
- /** Override the git binary (default: 'git'). Tests inject a stub. */
2676
- gitBinary?: string;
2677
- /**
2678
- * Override the underlying runner. Receives the args + cwd and returns
2679
- * { stdout, stderr, code } on success, or throws on timeout. The default
2680
- * implementation spawns `gitBinary` with the given args.
2681
- */
2682
- runGit?: (args: string[], cwd: string) => Promise<{
2683
- stdout: string;
2684
- stderr: string;
2685
- code: number;
2686
- }>;
2906
+ /** Timeout for each git invocation in ms. Default: 2000. */
2907
+ timeoutMs?: number;
2908
+ /** Override the git binary (default: 'git'). Tests inject a stub. */
2909
+ gitBinary?: string;
2910
+ /**
2911
+ * Override the underlying runner. Receives the args + cwd and returns
2912
+ * { stdout, stderr, code } on success, or throws on timeout. The default
2913
+ * implementation spawns `gitBinary` with the given args.
2914
+ */
2915
+ runGit?: (args: string[], cwd: string) => Promise<{
2916
+ stdout: string;
2917
+ stderr: string;
2918
+ code: number;
2919
+ }>;
2687
2920
  }
2688
2921
  /**
2689
2922
  * Probes a workspace for git metadata. Returns a {@link ProbeResult} with
@@ -2691,117 +2924,121 @@ interface ProbeOptions {
2691
2924
  * descriptor is always populated so callers can still surface a partial
2692
2925
  * record.
2693
2926
  */
2694
- declare class WorkspaceProbe {
2695
- private readonly timeoutMs;
2696
- private readonly gitBinary;
2697
- private readonly runGitFn;
2698
- constructor(options?: ProbeOptions);
2699
- probe(workspacePath: string): Promise<ProbeResult>;
2700
- }
2701
-
2702
- interface SkillDownloadFile {
2703
- path: string;
2704
- content: string;
2705
- executable: boolean;
2706
- }
2707
- interface SkillStoreFileSystem {
2708
- readdir: typeof fs.readdir;
2709
- readFile: typeof fs.readFile;
2710
- writeFile: typeof fs.writeFile;
2711
- mkdir: typeof fs.mkdir;
2712
- chmod: typeof fs.chmod;
2713
- }
2714
- interface SkillStoreOptions {
2715
- workspacePath: string;
2716
- userSkillsRoot: string;
2717
- fileSystem?: SkillStoreFileSystem;
2718
- }
2719
-
2720
- interface SkillCatalog {
2721
- skills: SkillMarketplaceEntry[];
2722
- fetchedAt: string;
2723
- }
2724
- interface SkillCatalogClientOptions {
2725
- fetchImpl?: typeof fetch;
2726
- baseUrl?: string;
2727
- }
2728
- declare class SkillCatalogClient {
2729
- private readonly fetchImpl;
2730
- private readonly baseUrl?;
2731
- constructor(options?: SkillCatalogClientOptions);
2732
- getCatalog(): Promise<SkillCatalog>;
2733
- downloadSkill(remoteId: string): Promise<SkillDownloadFile[]>;
2734
- }
2735
-
2927
+ export declare class WorkspaceProbe {
2928
+ private readonly timeoutMs;
2929
+ private readonly gitBinary;
2930
+ private readonly runGitFn;
2931
+ constructor(options?: ProbeOptions);
2932
+ probe(workspacePath: string): Promise<ProbeResult>;
2933
+ }
2934
+ //#endregion
2935
+ //#region src/skills/types.d.ts
2936
+ export interface SkillDownloadFile {
2937
+ path: string;
2938
+ content: string;
2939
+ executable: boolean;
2940
+ }
2941
+ export interface SkillStoreFileSystem {
2942
+ readdir: typeof fs$1.readdir;
2943
+ readFile: typeof fs$1.readFile;
2944
+ writeFile: typeof fs$1.writeFile;
2945
+ mkdir: typeof fs$1.mkdir;
2946
+ chmod: typeof fs$1.chmod;
2947
+ }
2948
+ export interface SkillStoreOptions {
2949
+ workspacePath: string;
2950
+ userSkillsRoot: string;
2951
+ fileSystem?: SkillStoreFileSystem;
2952
+ }
2953
+ //#endregion
2954
+ //#region src/skills/SkillCatalogClient.d.ts
2955
+ export interface SkillCatalog {
2956
+ skills: SkillMarketplaceEntry[];
2957
+ fetchedAt: string;
2958
+ }
2959
+ export interface SkillCatalogClientOptions {
2960
+ fetchImpl?: typeof fetch;
2961
+ baseUrl?: string;
2962
+ }
2963
+ export declare class SkillCatalogClient {
2964
+ private readonly fetchImpl;
2965
+ private readonly baseUrl?;
2966
+ constructor(options?: SkillCatalogClientOptions);
2967
+ getCatalog(): Promise<SkillCatalog>;
2968
+ downloadSkill(remoteId: string): Promise<SkillDownloadFile[]>;
2969
+ }
2970
+ //#endregion
2971
+ //#region src/skills/SkillReconciler.d.ts
2736
2972
  interface CatalogSkillLike {
2737
- id: string;
2738
- hasScripts?: boolean;
2739
- hasHooks?: boolean;
2973
+ id: string;
2974
+ hasScripts?: boolean;
2975
+ hasHooks?: boolean;
2740
2976
  }
2741
2977
  interface CatalogLike {
2742
- skills: CatalogSkillLike[];
2743
- fetchedAt: string;
2978
+ skills: CatalogSkillLike[];
2979
+ fetchedAt: string;
2744
2980
  }
2745
2981
  interface SkillStoreLike {
2746
- normalizeRemoteSkillId(remoteId: string): string;
2747
- listWorkspaceSkillIds(): Promise<string[]>;
2748
- listUserSkillIds(): Promise<string[]>;
2982
+ normalizeRemoteSkillId(remoteId: string): string;
2983
+ listWorkspaceSkillIds(): Promise<string[]>;
2984
+ listUserSkillIds(): Promise<string[]>;
2749
2985
  }
2750
2986
  interface SkillCatalogClientLike {
2751
- getCatalog(): Promise<CatalogLike>;
2752
- }
2753
- interface SkillReconcilerDependencies {
2754
- skillStore: SkillStoreLike;
2755
- catalogClient: SkillCatalogClientLike;
2756
- }
2757
- interface SkillMutateResult {
2758
- status: "success" | "blocked" | "requires_confirmation";
2759
- changed: boolean;
2760
- message?: string;
2761
- hasScripts?: boolean;
2762
- hasHooks?: boolean;
2763
- }
2764
- declare class SkillReconciler {
2765
- private readonly deps;
2766
- constructor(deps: SkillReconcilerDependencies);
2767
- mutate(request: SkillMutationRequest): Promise<SkillMutateResult>;
2768
- }
2769
-
2770
- declare class SkillStore {
2771
- private readonly workspacePath;
2772
- private readonly userSkillsRoot;
2773
- private readonly fileSystem;
2774
- constructor(options: SkillStoreOptions);
2775
- normalizeRemoteSkillId(remoteId: string): string;
2776
- getWorkspaceSkillPath(skillId: string): string;
2777
- getWorkspaceMarkerPath(): string;
2778
- getUserSkillPath(skillId: string): string;
2779
- listWorkspaceSkillIds(): Promise<string[]>;
2780
- listUserSkillIds(): Promise<string[]>;
2781
- writeManagedUserSkillMarker(skillId: string): Promise<void>;
2782
- isManagedUserSkill(skillId: string): Promise<boolean>;
2783
- /**
2784
- * One-time migration: the user-scope skill marker used to be named
2785
- * `.ms-devtools-skill.json`. If the new `.serviceme-skill.json` doesn't
2786
- * exist yet but the legacy marker does, copy it forward so an existing
2787
- * skill doesn't lose its "managed" status.
2788
- */
2789
- private migrateLegacyUserSkillMarker;
2790
- writeSkillFiles(skillId: string, scope: "workspace" | "user", files: SkillDownloadFile[]): Promise<void>;
2987
+ getCatalog(): Promise<CatalogLike>;
2988
+ }
2989
+ export interface SkillReconcilerDependencies {
2990
+ skillStore: SkillStoreLike;
2991
+ catalogClient: SkillCatalogClientLike;
2992
+ }
2993
+ export interface SkillMutateResult {
2994
+ status: "success" | "blocked" | "requires_confirmation";
2995
+ changed: boolean;
2996
+ message?: string;
2997
+ hasScripts?: boolean;
2998
+ hasHooks?: boolean;
2999
+ }
3000
+ export declare class SkillReconciler {
3001
+ private readonly deps;
3002
+ constructor(deps: SkillReconcilerDependencies);
3003
+ mutate(request: SkillMutationRequest): Promise<SkillMutateResult>;
3004
+ }
3005
+ //#endregion
3006
+ //#region src/skills/SkillStore.d.ts
3007
+ export declare class SkillStore {
3008
+ private readonly workspacePath;
3009
+ private readonly userSkillsRoot;
3010
+ private readonly fileSystem;
3011
+ constructor(options: SkillStoreOptions);
3012
+ normalizeRemoteSkillId(remoteId: string): string;
3013
+ getWorkspaceSkillPath(skillId: string): string;
3014
+ getWorkspaceMarkerPath(): string;
3015
+ getUserSkillPath(skillId: string): string;
3016
+ listWorkspaceSkillIds(): Promise<string[]>;
3017
+ listUserSkillIds(): Promise<string[]>;
3018
+ writeManagedUserSkillMarker(skillId: string): Promise<void>;
3019
+ isManagedUserSkill(skillId: string): Promise<boolean>;
3020
+ /**
3021
+ * One-time migration: the user-scope skill marker used to be named
3022
+ * `.ms-devtools-skill.json`. If the new `.serviceme-skill.json` doesn't
3023
+ * exist yet but the legacy marker does, copy it forward so an existing
3024
+ * skill doesn't lose its "managed" status.
3025
+ */
3026
+ private migrateLegacyUserSkillMarker;
3027
+ writeSkillFiles(skillId: string, scope: "workspace" | "user", files: SkillDownloadFile[]): Promise<void>;
2791
3028
  }
2792
3029
  /** 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[];
3030
+ export interface LegacyUserSkillEntry {
3031
+ /** Legacy skill id (directory name under ~/.agents/skills). */
3032
+ id: string;
3033
+ /** Absolute path of the legacy skill directory. */
3034
+ legacyPath: string;
3035
+ /** Target directory under ~/.copilot/skills the migration would create. */
3036
+ targetPath: string;
3037
+ /** Always `migration_available` until the user runs the migration. */
3038
+ status: "migration_available";
3039
+ }
3040
+ export interface LegacyUserSkillMigrationResult {
3041
+ entries: LegacyUserSkillEntry[];
2805
3042
  }
2806
3043
  /**
2807
3044
  * Detect ~/.agents/skills content that can migrate to ~/.copilot/skills.
@@ -2810,13 +3047,15 @@ interface LegacyUserSkillMigrationResult {
2810
3047
  * invokes the migration, so detection never breaks tools that still
2811
3048
  * read the old layout.
2812
3049
  */
2813
- declare function migrateLegacyUserSkillContent(input: {
2814
- homeDir: string;
2815
- workspaceDir: string;
2816
- fileSystem?: SkillStoreFileSystem;
3050
+ export declare function migrateLegacyUserSkillContent(input: {
3051
+ homeDir: string;
3052
+ workspaceDir: string;
3053
+ fileSystem?: SkillStoreFileSystem;
2817
3054
  }): Promise<LegacyUserSkillMigrationResult>;
2818
-
2819
- declare const unzipFile: (zipPath: string, dest: string) => Promise<void>;
2820
- declare const moveFiles: (sourceDir: string, destDir: string, overwrite?: boolean) => Promise<void>;
2821
-
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 };
3055
+ //#endregion
3056
+ //#region src/utils/fileUtils.d.ts
3057
+ export declare const unzipFile: (zipPath: string, dest: string) => Promise<void>;
3058
+ export declare const moveFiles: (sourceDir: string, destDir: string, overwrite?: boolean) => Promise<void>;
3059
+ //#endregion
3060
+ export { type AccessCheckResult, AccessControl, type AccessControlOptions, type AppendLogInput, type AtomicWriteResult, AuthCore, type AuthCoreOptions, AuthStateManager, type AuthStateManagerOptions, BUILTIN_DEFAULT_TOOLS, type BootstrapPhase5Result, type BuildSignedHeadersParams, type CancellationCheck, type CreateTaskInput, FIXED_ADDED_AT as DEFAULT_REPO_FIXED_ADDED_AT, DEVICE_JSON_SCHEMA_VERSION, DefaultToolImmutableError, type DefaultToolSeed, DeviceAuthHeaders, DeviceCore, type DeviceCoreOptions, type DeviceFlowUiCallback, DeviceReenrollRequiresAuthError, type DeviceRequestSignatureParams, DeviceSecretVersionMismatchError, type DeviceSignedHeaders, type EditTaskInput, type EnrollRequestFn, type EnrollResponse, Enroller, type EnrollerOptions, type ExecutorResult, FsIdentityFileBackend, FsToolboxFileBackend, GIT_PROXY_PATH_SUFFIX, GitClient, GitError, GitHubAuthProvider, type GitHubAuthProviderConfig, type IAuthProvider, type IAuthProviderSession, type IAuthProviderUserInfo, type IdentityFileBackend, IdentityStore, type IdentityStoreHooks, type IdentityStoreOptions, InMemoryKeychainAuthTokenStore, type KeyValueStore, type KeychainAccountKey, type KeychainAuthTokenStore, type KeychainTokenEnvelope, type KeychainTokenMetadata, KeychainUnavailableError, MicrosoftAuthProvider, MicrosoftProviderNotHostedError, type MigrateToGlobalOptions, type MigrationResult, NodeGitSpawner, type OrgMembershipFetcher, type OutputEventCallback, type PersistedDeviceIdentity, type PersistedToolbox, type ProbeError, type ProbeOptions, type ProbeResult, ProviderRegistry, type ResolvedToolbox, type SchedulerDaemonV2Options, ServiceMeLogger, type StreamingExecutorHandle, type StreamingTaskExecutor, StubGitSpawner, SubmitClient, SubmitClientOptions, SubmitError, SubmitOptions, SubmitResult, TOOLBOX_JSON_SCHEMA_VERSION, type TaskEventListener, type TaskExecutor, ToolboxCore, type ToolboxCoreOptions, type ToolboxFileBackend, type ToolboxPatch, ToolboxStore, type ToolboxStoreHooks, type ToolboxStoreOptions, WORKSPACE_TOOLBOX_RELATIVE_PATH, repoSchema as anyRepoConfigSchema, buildGitHubLocalEmail, buildGitProxyBase, buildSignedHeaders, createConsoleLogger, createDeviceRequestSignature, defaultRepoSchema as defaultRepoConfigSchema, deriveInstallationId, fingerprintSource, isGitHubLocalEmail, mergeWithDefaults, noopLogger, randomInstallationId, reindexOrder, resolvePrimaryEmail, sortByRecentFirst, sortByUserOrder, toFileUrl, touchLastUsedAt, userRepoSchema as userRepoConfigSchema };
3061
+ //# sourceMappingURL=index.d.ts.map