@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.
- package/dist/auth-Bzss8zOv.mjs +995 -0
- package/dist/auth-Bzss8zOv.mjs.map +1 -0
- package/dist/auth-DXam3c4S.js +1078 -0
- package/dist/auth-DXam3c4S.js.map +1 -0
- package/dist/auth.d.mts +2 -2
- package/dist/auth.d.ts +2 -2
- package/dist/auth.js +14 -1029
- package/dist/auth.mjs +2 -991
- package/dist/device-CDDcwDY6.mjs +758 -0
- package/dist/device-CDDcwDY6.mjs.map +1 -0
- package/dist/device-DuAYH8bk.js +839 -0
- package/dist/device-DuAYH8bk.js.map +1 -0
- package/dist/device.d.mts +2 -455
- package/dist/device.d.ts +2 -455
- package/dist/device.js +15 -728
- package/dist/device.mjs +2 -679
- package/dist/index-2rX86yMq.d.mts +331 -0
- package/dist/index-BI11AfMH.d.mts +377 -0
- package/dist/index-BI11AfMH.d.ts +377 -0
- package/dist/index-CoA6y0MP.d.mts +498 -0
- package/dist/index-CoA6y0MP.d.ts +498 -0
- package/dist/index-DaW7IYA-.d.mts +185 -0
- package/dist/index-DaW7IYA-.d.ts +185 -0
- package/dist/index-Dp6FwWKh.d.ts +331 -0
- package/dist/index.d.mts +2340 -2101
- package/dist/index.d.ts +2340 -2101
- package/dist/index.js +8117 -10538
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +7895 -10318
- package/dist/index.mjs.map +1 -1
- package/dist/rolldown-runtime-VH7oDXx4.js +28 -0
- package/dist/skill-linker.d.mts +82 -81
- package/dist/skill-linker.d.ts +82 -81
- package/dist/skill-linker.js +359 -402
- package/dist/skill-linker.js.map +1 -1
- package/dist/skill-linker.mjs +345 -357
- package/dist/skill-linker.mjs.map +1 -1
- package/dist/skill-store-Bym2yinU.mjs +388 -0
- package/dist/skill-store-Bym2yinU.mjs.map +1 -0
- package/dist/skill-store-CJdYyyxu.js +408 -0
- package/dist/skill-store-CJdYyyxu.js.map +1 -0
- package/dist/skill-store.d.mts +41 -42
- package/dist/skill-store.d.ts +41 -42
- package/dist/skill-store.js +5 -338
- package/dist/skill-store.mjs +2 -301
- package/dist/submit-Cg7wSa3x.mjs +84 -0
- package/dist/submit-Cg7wSa3x.mjs.map +1 -0
- package/dist/submit-CltE6YOZ.js +98 -0
- package/dist/submit-CltE6YOZ.js.map +1 -0
- package/dist/submit.d.mts +2 -3
- package/dist/submit.d.ts +2 -3
- package/dist/submit.js +4 -166
- package/dist/submit.mjs +2 -130
- package/dist/toolbox-CbfxpNg-.mjs +540 -0
- package/dist/toolbox-CbfxpNg-.mjs.map +1 -0
- package/dist/toolbox-CxnOr-FY.js +614 -0
- package/dist/toolbox-CxnOr-FY.js.map +1 -0
- package/dist/toolbox.d.mts +2 -244
- package/dist/toolbox.d.ts +2 -244
- package/dist/toolbox.js +14 -584
- package/dist/toolbox.mjs +2 -536
- package/dist/{types-B9gk3dXH.d.ts → types-BCV3IedE.d.mts} +25 -23
- package/dist/{types-B9gk3dXH.d.mts → types-BCV3IedE.d.ts} +25 -23
- package/dist/userHome-BquDeFVE.js +526 -0
- package/dist/userHome-BquDeFVE.js.map +1 -0
- package/dist/userHome-CcnAQPG1.mjs +212 -0
- package/dist/userHome-CcnAQPG1.mjs.map +1 -0
- package/package.json +10 -10
- package/dist/auth.js.map +0 -1
- package/dist/auth.mjs.map +0 -1
- package/dist/device.js.map +0 -1
- package/dist/device.mjs.map +0 -1
- package/dist/index-BMk4tqIT.d.mts +0 -328
- package/dist/index-CymN0x9Z.d.ts +0 -328
- package/dist/index-PD135hlB.d.mts +0 -626
- package/dist/index-PD135hlB.d.ts +0 -626
- package/dist/skill-store.js.map +0 -1
- package/dist/skill-store.mjs.map +0 -1
- package/dist/submit.js.map +0 -1
- package/dist/submit.mjs.map +0 -1
- package/dist/toolbox.js.map +0 -1
- package/dist/toolbox.mjs.map +0 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,131 +1,131 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
import * as fs
|
|
10
|
-
|
|
11
|
-
export
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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.mjs";
|
|
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.mjs";
|
|
3
|
+
import { i as SkillKind, r as SkillFile } from "./types-BCV3IedE.mjs";
|
|
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-2rX86yMq.mjs";
|
|
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-.mjs";
|
|
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 { z } from "zod";
|
|
9
|
+
import * as fs from "node:fs";
|
|
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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
normalizeRemoteAgentId(remoteId: string): string;
|
|
61
|
+
listWorkspaceAgentIds(): Promise<string[]>;
|
|
62
|
+
listUserAgentIds(): Promise<string[]>;
|
|
64
63
|
}
|
|
65
64
|
interface AgentCatalogLike {
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
agents: AgentMarketplaceEntry[];
|
|
66
|
+
fetchedAt: string;
|
|
68
67
|
}
|
|
69
68
|
interface AgentCatalogClientLike {
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
interface AgentReconcilerDependencies {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
interface AgentMutateResult {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
declare class AgentReconciler {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
interface LegacyUserContentMigrationResult {
|
|
128
|
-
|
|
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
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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():
|
|
150
|
-
declare function createCopilotAuthRequiredError():
|
|
151
|
-
|
|
152
|
-
|
|
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
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
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
|
-
|
|
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
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
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
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
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
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
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
|
-
|
|
216
|
-
|
|
217
|
-
|
|
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
|
-
|
|
222
|
-
|
|
223
|
-
|
|
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
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
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
|
-
|
|
257
|
-
|
|
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
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
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
|
-
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
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
|
-
|
|
304
|
-
|
|
305
|
-
|
|
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
|
-
|
|
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
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
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
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
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
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
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
|
-
|
|
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
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
}
|
|
382
|
-
interface MaterializeResult {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
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
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
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
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
}
|
|
451
|
-
interface CopilotPluginRegisterInput {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
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
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
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
|
-
|
|
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
|
-
|
|
691
|
+
scope: "workspace" | "user";
|
|
605
692
|
workspaceDir?: string;
|
|
693
|
+
}): Promise<void>;
|
|
694
|
+
private write;
|
|
606
695
|
}
|
|
607
|
-
|
|
608
|
-
|
|
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
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
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
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
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
|
-
|
|
658
|
-
|
|
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
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
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
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
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
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
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
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
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
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
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
|
-
|
|
738
|
-
|
|
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
|
-
|
|
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
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
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
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
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
|
-
|
|
781
|
-
|
|
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
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
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
|
-
|
|
802
|
-
|
|
803
|
-
|
|
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
|
-
|
|
807
|
-
|
|
880
|
+
export interface WorkspaceContentReconcileResult {
|
|
881
|
+
changed: boolean;
|
|
882
|
+
entries: WorkspaceContentEntryResult[];
|
|
808
883
|
}
|
|
809
884
|
interface RepositorySource {
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
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
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
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
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
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
|
-
|
|
863
|
-
|
|
864
|
-
}
|
|
865
|
-
interface CopilotPackageInstallInput {
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
}
|
|
874
|
-
interface CopilotPackageUpdateInput {
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
}
|
|
881
|
-
interface CopilotPackageUninstallInput {
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
}
|
|
886
|
-
interface CopilotPackageMoveInput {
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
}
|
|
892
|
-
interface PackageInstallationServiceDeps {
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
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
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
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
|
-
|
|
956
|
-
|
|
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
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
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
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
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
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
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
|
-
|
|
1104
|
-
|
|
1180
|
+
export interface CopilotSourceCatalogQuery {
|
|
1181
|
+
workspaceDir?: string;
|
|
1182
|
+
scope?: CopilotScope;
|
|
1105
1183
|
}
|
|
1106
|
-
interface CopilotUpdatePreviewInput {
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
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
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
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
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
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
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
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
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
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
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
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
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
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
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
}
|
|
1290
|
-
interface DraftDetail extends DraftSummary {
|
|
1291
|
-
|
|
1292
|
-
}
|
|
1293
|
-
interface SaveDraftOptions {
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
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
|
-
|
|
1511
|
+
export declare class DraftsError extends Error {
|
|
1512
|
+
constructor(message: string);
|
|
1303
1513
|
}
|
|
1304
|
-
declare class DraftNotFoundError extends DraftsError {
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
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
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
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
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1573
|
+
stdout: string;
|
|
1574
|
+
stderr: string;
|
|
1575
|
+
code: number;
|
|
1365
1576
|
}
|
|
1366
1577
|
declare function runCommand(command: string, options?: RunCommandOptions): Promise<RunCommandResult>;
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
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
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
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
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
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
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
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
|
-
|
|
1657
|
-
declare
|
|
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
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
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
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
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
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
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
|
-
|
|
1773
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
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
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1832
|
-
|
|
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
|
-
|
|
1851
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
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
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
}
|
|
1934
|
-
interface ReposLoaderOptions {
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
}
|
|
1944
|
-
declare class ReposLoader {
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
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
|
-
|
|
2002
|
-
|
|
2221
|
+
export type ReposStoreChange = {
|
|
2222
|
+
kind: "load";
|
|
2223
|
+
config: ReposFile;
|
|
2003
2224
|
} | {
|
|
2004
|
-
|
|
2005
|
-
|
|
2225
|
+
kind: "add";
|
|
2226
|
+
repo: AnyRepoConfig;
|
|
2006
2227
|
} | {
|
|
2007
|
-
|
|
2008
|
-
|
|
2228
|
+
kind: "update";
|
|
2229
|
+
repo: AnyRepoConfig;
|
|
2009
2230
|
} | {
|
|
2010
|
-
|
|
2011
|
-
|
|
2231
|
+
kind: "remove";
|
|
2232
|
+
repoId: string;
|
|
2012
2233
|
} | {
|
|
2013
|
-
|
|
2014
|
-
|
|
2234
|
+
kind: "default-change";
|
|
2235
|
+
defaultRepoId: string;
|
|
2015
2236
|
} | {
|
|
2016
|
-
|
|
2017
|
-
|
|
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
|
-
|
|
2024
|
-
}
|
|
2025
|
-
interface ReposStoreOptions {
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
}
|
|
2063
|
-
declare class ReposStore {
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
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
|
-
|
|
2150
|
-
|
|
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
|
-
|
|
2155
|
-
|
|
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
|
-
|
|
2160
|
-
|
|
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
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
}
|
|
2202
|
-
interface AddUserRepoInput {
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
}
|
|
2214
|
-
interface AddUserRepoResult {
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
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
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
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
|
-
|
|
2231
|
-
}
|
|
2232
|
-
declare class InvalidRepoUrlError extends RepoManagerError {
|
|
2233
|
-
}
|
|
2234
|
-
declare class
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
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
|
-
|
|
2377
|
-
|
|
2595
|
+
export declare function ensureDefaultsInstalled(existing: ReposFile, now?: () => string): {
|
|
2596
|
+
config: ReposFile;
|
|
2597
|
+
installed: string[];
|
|
2378
2598
|
};
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
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
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
}
|
|
2399
|
-
declare class PidManager {
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
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
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2634
|
+
status: TaskExecutionStatus;
|
|
2635
|
+
output?: string;
|
|
2636
|
+
error?: string;
|
|
2414
2637
|
}
|
|
2415
2638
|
interface TaskExecutor {
|
|
2416
|
-
|
|
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
|
-
|
|
2421
|
-
|
|
2643
|
+
result: Promise<ExecutorResult>;
|
|
2644
|
+
cancel: () => void;
|
|
2422
2645
|
}
|
|
2423
2646
|
interface StreamingTaskExecutor extends TaskExecutor {
|
|
2424
|
-
|
|
2425
|
-
}
|
|
2426
|
-
declare function isStreamingTaskExecutor(executor: TaskExecutor): executor is StreamingTaskExecutor;
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
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
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
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
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
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
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
}
|
|
2491
|
-
declare class TaskConfigManager {
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
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
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
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
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
}
|
|
2528
|
-
declare class TaskLogManager {
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
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
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
}
|
|
2571
|
-
declare class SchedulerDaemonV2 {
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
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
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
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
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
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
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
}
|
|
2650
|
-
declare function resolveTaskExecutionPayload(taskType: ScheduledTaskType, payload: TaskPayload, workspacePath: string): TaskPayload;
|
|
2651
|
-
declare class TaskExecutionEngine {
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
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
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
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
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
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
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
}
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
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
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2973
|
+
id: string;
|
|
2974
|
+
hasScripts?: boolean;
|
|
2975
|
+
hasHooks?: boolean;
|
|
2740
2976
|
}
|
|
2741
2977
|
interface CatalogLike {
|
|
2742
|
-
|
|
2743
|
-
|
|
2978
|
+
skills: CatalogSkillLike[];
|
|
2979
|
+
fetchedAt: string;
|
|
2744
2980
|
}
|
|
2745
2981
|
interface SkillStoreLike {
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2982
|
+
normalizeRemoteSkillId(remoteId: string): string;
|
|
2983
|
+
listWorkspaceSkillIds(): Promise<string[]>;
|
|
2984
|
+
listUserSkillIds(): Promise<string[]>;
|
|
2749
2985
|
}
|
|
2750
2986
|
interface SkillCatalogClientLike {
|
|
2751
|
-
|
|
2752
|
-
}
|
|
2753
|
-
interface SkillReconcilerDependencies {
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
}
|
|
2757
|
-
interface SkillMutateResult {
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
}
|
|
2764
|
-
declare class SkillReconciler {
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
}
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
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
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
}
|
|
2803
|
-
interface LegacyUserSkillMigrationResult {
|
|
2804
|
-
|
|
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
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
3050
|
+
export declare function migrateLegacyUserSkillContent(input: {
|
|
3051
|
+
homeDir: string;
|
|
3052
|
+
workspaceDir: string;
|
|
3053
|
+
fileSystem?: SkillStoreFileSystem;
|
|
2817
3054
|
}): Promise<LegacyUserSkillMigrationResult>;
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
declare const
|
|
2821
|
-
|
|
2822
|
-
|
|
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.mts.map
|