@serviceme/devtools-core 2.0.0 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/auth-Bzss8zOv.mjs +995 -0
  2. package/dist/auth-Bzss8zOv.mjs.map +1 -0
  3. package/dist/auth-DXam3c4S.js +1078 -0
  4. package/dist/auth-DXam3c4S.js.map +1 -0
  5. package/dist/auth.d.mts +2 -2
  6. package/dist/auth.d.ts +2 -2
  7. package/dist/auth.js +14 -1029
  8. package/dist/auth.mjs +2 -991
  9. package/dist/device-CDDcwDY6.mjs +758 -0
  10. package/dist/device-CDDcwDY6.mjs.map +1 -0
  11. package/dist/device-DuAYH8bk.js +839 -0
  12. package/dist/device-DuAYH8bk.js.map +1 -0
  13. package/dist/device.d.mts +2 -455
  14. package/dist/device.d.ts +2 -455
  15. package/dist/device.js +15 -728
  16. package/dist/device.mjs +2 -679
  17. package/dist/index-2rX86yMq.d.mts +331 -0
  18. package/dist/index-BI11AfMH.d.mts +377 -0
  19. package/dist/index-BI11AfMH.d.ts +377 -0
  20. package/dist/index-CoA6y0MP.d.mts +498 -0
  21. package/dist/index-CoA6y0MP.d.ts +498 -0
  22. package/dist/index-DaW7IYA-.d.mts +185 -0
  23. package/dist/index-DaW7IYA-.d.ts +185 -0
  24. package/dist/index-Dp6FwWKh.d.ts +331 -0
  25. package/dist/index.d.mts +2340 -2101
  26. package/dist/index.d.ts +2340 -2101
  27. package/dist/index.js +8117 -10538
  28. package/dist/index.js.map +1 -1
  29. package/dist/index.mjs +7895 -10318
  30. package/dist/index.mjs.map +1 -1
  31. package/dist/rolldown-runtime-VH7oDXx4.js +28 -0
  32. package/dist/skill-linker.d.mts +82 -81
  33. package/dist/skill-linker.d.ts +82 -81
  34. package/dist/skill-linker.js +359 -402
  35. package/dist/skill-linker.js.map +1 -1
  36. package/dist/skill-linker.mjs +345 -357
  37. package/dist/skill-linker.mjs.map +1 -1
  38. package/dist/skill-store-Bym2yinU.mjs +388 -0
  39. package/dist/skill-store-Bym2yinU.mjs.map +1 -0
  40. package/dist/skill-store-CJdYyyxu.js +408 -0
  41. package/dist/skill-store-CJdYyyxu.js.map +1 -0
  42. package/dist/skill-store.d.mts +41 -42
  43. package/dist/skill-store.d.ts +41 -42
  44. package/dist/skill-store.js +5 -338
  45. package/dist/skill-store.mjs +2 -301
  46. package/dist/submit-Cg7wSa3x.mjs +84 -0
  47. package/dist/submit-Cg7wSa3x.mjs.map +1 -0
  48. package/dist/submit-CltE6YOZ.js +98 -0
  49. package/dist/submit-CltE6YOZ.js.map +1 -0
  50. package/dist/submit.d.mts +2 -3
  51. package/dist/submit.d.ts +2 -3
  52. package/dist/submit.js +4 -166
  53. package/dist/submit.mjs +2 -130
  54. package/dist/toolbox-CbfxpNg-.mjs +540 -0
  55. package/dist/toolbox-CbfxpNg-.mjs.map +1 -0
  56. package/dist/toolbox-CxnOr-FY.js +614 -0
  57. package/dist/toolbox-CxnOr-FY.js.map +1 -0
  58. package/dist/toolbox.d.mts +2 -244
  59. package/dist/toolbox.d.ts +2 -244
  60. package/dist/toolbox.js +14 -584
  61. package/dist/toolbox.mjs +2 -536
  62. package/dist/{types-B9gk3dXH.d.ts → types-BCV3IedE.d.mts} +25 -23
  63. package/dist/{types-B9gk3dXH.d.mts → types-BCV3IedE.d.ts} +25 -23
  64. package/dist/userHome-BquDeFVE.js +526 -0
  65. package/dist/userHome-BquDeFVE.js.map +1 -0
  66. package/dist/userHome-CcnAQPG1.mjs +212 -0
  67. package/dist/userHome-CcnAQPG1.mjs.map +1 -0
  68. package/package.json +10 -10
  69. package/dist/auth.js.map +0 -1
  70. package/dist/auth.mjs.map +0 -1
  71. package/dist/device.js.map +0 -1
  72. package/dist/device.mjs.map +0 -1
  73. package/dist/index-BMk4tqIT.d.mts +0 -328
  74. package/dist/index-CymN0x9Z.d.ts +0 -328
  75. package/dist/index-PD135hlB.d.mts +0 -626
  76. package/dist/index-PD135hlB.d.ts +0 -626
  77. package/dist/skill-store.js.map +0 -1
  78. package/dist/skill-store.mjs.map +0 -1
  79. package/dist/submit.js.map +0 -1
  80. package/dist/submit.mjs.map +0 -1
  81. package/dist/toolbox.js.map +0 -1
  82. package/dist/toolbox.mjs.map +0 -1
@@ -0,0 +1,185 @@
1
+ import { ExternalTool, ToolboxList, ToolboxScope } from "@serviceme/devtools-protocol";
2
+ //#region src/toolbox/sort.d.ts
3
+ /**
4
+ * Sort by "recently used" — entries with newer `lastUsedAt` float to
5
+ * the top, entries with no `lastUsedAt` sort to the bottom (preserving
6
+ * their relative `order` index when both are absent).
7
+ *
8
+ * Ties (same `lastUsedAt` or both missing) are broken by `order`, then
9
+ * by `id` for determinism.
10
+ */
11
+ declare function sortByRecentFirst(tools: readonly ExternalTool[]): ExternalTool[];
12
+ /**
13
+ * Sort by user-defined `order` field. Entries without `order` are
14
+ * appended in their input order (stable sort via `id` tiebreaker).
15
+ */
16
+ declare function sortByUserOrder(tools: readonly ExternalTool[]): ExternalTool[];
17
+ /**
18
+ * Merge built-in defaults with user-stored tools. Defaults keep
19
+ * `isDefault: true` and their `order`; user tools are appended with
20
+ * their stored metadata. Output is sorted by user order.
21
+ */
22
+ declare function mergeWithDefaults(defaults: readonly ExternalTool[], userTools: readonly ExternalTool[]): ExternalTool[];
23
+ /**
24
+ * Re-number `order` for a list of tool ids. Used by
25
+ * `toolbox.update` when the user drags-and-drops entries in the UI.
26
+ */
27
+ declare function reindexOrder(tools: ExternalTool[], newOrderIds: readonly string[]): ExternalTool[];
28
+ /**
29
+ * Stamp `lastUsedAt` on the targeted tool (clones the array). Returns
30
+ * a new array; the input is left untouched.
31
+ */
32
+ declare function touchLastUsedAt(tools: readonly ExternalTool[], id: string, when?: Date): ExternalTool[];
33
+ //#endregion
34
+ //#region src/toolbox/types.d.ts
35
+ /** Schema version of the on-disk toolbox JSON files. Bumped on breaking changes. */
36
+ declare const TOOLBOX_JSON_SCHEMA_VERSION = 1;
37
+ interface PersistedToolbox {
38
+ version: number;
39
+ tools: ExternalTool[];
40
+ }
41
+ /** Patch payload accepted by `ToolboxCore.update` (mirrors `ExternalToolPatch`). */
42
+ type ToolboxPatch = Partial<Omit<ExternalTool, "id" | "isDefault">>;
43
+ /**
44
+ * Built-in (default) tool seeds. Mirrors the Extension's
45
+ * `apps/extension/src/config/external-tools.ts`. The Core stores these
46
+ * verbatim and never mutates them — the Extension's `ToolBoxService`
47
+ * runs the same merge on top of the Core's view.
48
+ */
49
+ interface DefaultToolSeed {
50
+ id: string;
51
+ name: string;
52
+ description: string;
53
+ icon: string;
54
+ url: string;
55
+ }
56
+ /** Built-in tools rendered when the JSON file is missing or empty. */
57
+ declare const BUILTIN_DEFAULT_TOOLS: readonly DefaultToolSeed[];
58
+ /** Resolved toolbox shape returned by `ToolboxStore.read()`. */
59
+ interface ResolvedToolbox {
60
+ scope: ToolboxScope;
61
+ tools: ExternalTool[];
62
+ }
63
+ //#endregion
64
+ //#region src/toolbox/ToolboxStore.d.ts
65
+ declare const WORKSPACE_TOOLBOX_RELATIVE_PATH: string;
66
+ interface ToolboxFileBackend {
67
+ read(filePath: string): Promise<PersistedToolbox | null>;
68
+ write(filePath: string, payload: PersistedToolbox): Promise<void>;
69
+ exists(filePath: string): Promise<boolean>;
70
+ /** Maximum number of `.corrupted.*.bak` snapshots to keep per toolbox file (default: 5). */
71
+ maxBackupCount?: number;
72
+ }
73
+ interface ToolboxStoreOptions {
74
+ /** Override the user-scope file path (default: `getToolboxJsonPath()`). */
75
+ userFilePath?: string;
76
+ /** Override the workspace-scope file path resolver (default: cwd-relative). */
77
+ resolveWorkspacePath?: () => string | null;
78
+ /** Injectable built-in tool seeds (default: `BUILTIN_DEFAULT_TOOLS`). */
79
+ defaultTools?: readonly DefaultToolSeed[];
80
+ hooks?: ToolboxStoreHooks;
81
+ backend?: ToolboxFileBackend;
82
+ lockTimeoutMs?: number;
83
+ lockRetryMs?: number;
84
+ }
85
+ interface ToolboxStoreHooks {
86
+ beforeWrite?: (scope: ToolboxScope, payload: PersistedToolbox) => void | Promise<void>;
87
+ afterWrite?: (scope: ToolboxScope, payload: PersistedToolbox) => void | Promise<void>;
88
+ }
89
+ declare class FsToolboxFileBackend implements ToolboxFileBackend {
90
+ maxBackupCount: number;
91
+ exists(filePath: string): Promise<boolean>;
92
+ read(filePath: string): Promise<PersistedToolbox | null>;
93
+ private backupCorruptedFile;
94
+ private purgeExcessBackups;
95
+ write(filePath: string, payload: PersistedToolbox): Promise<void>;
96
+ }
97
+ declare class ToolboxStore {
98
+ private readonly userFilePath;
99
+ private readonly resolveWorkspacePath;
100
+ private readonly defaults;
101
+ private readonly hooks;
102
+ private readonly backend;
103
+ private readonly lockTimeoutMs;
104
+ private readonly lockRetryMs;
105
+ constructor(opts?: ToolboxStoreOptions);
106
+ /** Read a scope; returns the resolved toolbox (with defaults merged when empty). */
107
+ read(scope: ToolboxScope): Promise<ResolvedToolbox>;
108
+ /**
109
+ * Atomic write under a file lock. Replaces the entire `tools` array
110
+ * with the provided snapshot.
111
+ */
112
+ write(scope: ToolboxScope, tools: readonly ExternalTool[]): Promise<void>;
113
+ /**
114
+ * Read-modify-write under the file lock. The mutator receives the
115
+ * current user-only list (defaults not included) and returns the
116
+ * replacement list. Throwing inside the mutator aborts the write.
117
+ */
118
+ mutate(scope: ToolboxScope, mutator: (current: ExternalTool[]) => Promise<ExternalTool[]>): Promise<ExternalTool[]>;
119
+ /** Wipe a scope entirely (used by `toolbox.remove --all` extensions). */
120
+ clear(scope: ToolboxScope): Promise<void>;
121
+ /** Test seam — resolve the user-scope file path. */
122
+ getUserFilePath(): string;
123
+ /** Test seam — resolve the workspace-scope file path (or null when disabled). */
124
+ getWorkspaceFilePath(): string | null;
125
+ private filePathFor;
126
+ }
127
+ //#endregion
128
+ //#region src/toolbox/ToolboxCore.d.ts
129
+ /** Sentinel — caller tried to remove a built-in (immutable) tool. */
130
+ declare class DefaultToolImmutableError extends Error {
131
+ readonly toolId: string;
132
+ constructor(toolId: string);
133
+ }
134
+ interface ToolboxCoreOptions {
135
+ store?: ToolboxStore;
136
+ defaultTools?: readonly DefaultToolSeed[];
137
+ /** Sort applied to the merged list returned by `list()`. Default: `sortByUserOrder`. */
138
+ listSort?: (tools: readonly ExternalTool[]) => ExternalTool[];
139
+ }
140
+ declare class ToolboxCore {
141
+ private readonly store;
142
+ private readonly defaults;
143
+ private readonly listSort;
144
+ constructor(opts?: ToolboxCoreOptions);
145
+ /** List all tools in a scope. Built-in defaults are merged in. */
146
+ list(scope?: ToolboxScope): Promise<ToolboxList>;
147
+ /**
148
+ * Append a new tool to the requested scope. Default tools are
149
+ * rejected (they are seeds, not user entries).
150
+ */
151
+ add(tool: ExternalTool, scope?: ToolboxScope): Promise<ToolboxList>;
152
+ /**
153
+ * Remove a tool by id. Returns `success: false` when the id is a
154
+ * built-in default (idempotent, never throws on missing entries).
155
+ */
156
+ remove(id: string, scope?: ToolboxScope): Promise<{
157
+ scope: ToolboxScope;
158
+ toolId: string;
159
+ success: boolean;
160
+ }>;
161
+ /**
162
+ * Patch a tool by id. Default tools can only have their `order`
163
+ * updated; other patches are silently ignored for default entries
164
+ * (callers can compare before/after to detect the ignore).
165
+ */
166
+ update(id: string, patch: ToolboxPatch, scope?: ToolboxScope): Promise<ToolboxList>;
167
+ /**
168
+ * Stamp `lastUsedAt` on the targeted tool. This is the "recently
169
+ * used" hook the Extension's webview uses when a user clicks a
170
+ * toolbox entry.
171
+ */
172
+ recordUsage(id: string, scope?: ToolboxScope, when?: Date): Promise<ExternalTool | null>;
173
+ /**
174
+ * Combined view: user + workspace scopes merged, sorted by recent
175
+ * usage. Workspace tools overlay user tools (workspace entries win
176
+ * on `id` collision).
177
+ */
178
+ listMerged(): Promise<ToolboxList>;
179
+ /** Expose the underlying store (CLI / Bridge use it for path-level access). */
180
+ getStore(): ToolboxStore;
181
+ private isDefaultId;
182
+ }
183
+ //#endregion
184
+ export { reindexOrder as _, ToolboxFileBackend as a, touchLastUsedAt as b, ToolboxStoreOptions as c, DefaultToolSeed as d, PersistedToolbox as f, mergeWithDefaults as g, ToolboxPatch as h, FsToolboxFileBackend as i, WORKSPACE_TOOLBOX_RELATIVE_PATH as l, TOOLBOX_JSON_SCHEMA_VERSION as m, ToolboxCore as n, ToolboxStore as o, ResolvedToolbox as p, ToolboxCoreOptions as r, ToolboxStoreHooks as s, DefaultToolImmutableError as t, BUILTIN_DEFAULT_TOOLS as u, sortByRecentFirst as v, sortByUserOrder as y };
185
+ //# sourceMappingURL=index-DaW7IYA-.d.ts.map
@@ -0,0 +1,331 @@
1
+ import { r as SkillFile } from "./types-BCV3IedE.js";
2
+ import { SpawnOptions } from "node:child_process";
3
+ //#region src/git-client/types.d.ts
4
+ /**
5
+ * Skill & Agent v2 — Client GitClient Types (M3)
6
+ *
7
+ * GitClient wraps the local `git` CLI so all commands the SERVICEME
8
+ * pipeline issues (clone, fetch, push, ls-remote) flow through the
9
+ * server's git smart-HTTP proxy instead of talking directly to GitHub.
10
+ *
11
+ * The single trick: `git` only cares about the URL we hand it as a
12
+ * remote. We rewrite `https://github.com/owner/repo.git` to
13
+ * `http://server:port/git-proxy/<id>` and `git` does the rest — the
14
+ * server transparently forwards + injects PATs as needed.
15
+ *
16
+ * @see docs/architecture/skill-agent-v2-repo.md §5.4 GitClient
17
+ */
18
+ /** Result of a `git fetch` (called via the proxy's git-upload-pack). */
19
+ interface PullResult {
20
+ /** Whether new commits were fetched (false = already up-to-date). */
21
+ updated: boolean;
22
+ /** Commit SHA at FETCH_HEAD after the pull. */
23
+ commitSha: string;
24
+ /** Branch name that was pulled (e.g. "v2"). */
25
+ branch: string;
26
+ }
27
+ /** Result of a `git push` (called via the proxy's git-receive-pack). */
28
+ interface PushResult {
29
+ /** Remote ref updated (e.g. "refs/heads/v2"). */
30
+ ref: string;
31
+ /** New commit SHA on the remote. */
32
+ commitSha: string;
33
+ }
34
+ /** A branch as advertised by `git ls-remote`. */
35
+ interface RemoteBranch {
36
+ /** Full ref name, e.g. `refs/heads/main`. */
37
+ ref: string;
38
+ /** Commit SHA the ref points at. */
39
+ sha: string;
40
+ }
41
+ /** Outcome of any spawned `git` process. */
42
+ interface GitSpawnResult {
43
+ stdout: string;
44
+ stderr: string;
45
+ code: number;
46
+ }
47
+ /** Strategy for executing git commands. Tests inject a stub. */
48
+ interface GitSpawner {
49
+ spawn(args: string[], opts: SpawnOptions): Promise<GitSpawnResult>;
50
+ }
51
+ /** Options for instantiating GitClient. */
52
+ interface GitClientOptions {
53
+ /** Base URL of the server git proxy. e.g. `http://localhost:3000/git-proxy`. */
54
+ serverProxyBase: string;
55
+ /** Inject a custom spawner (default: spawn real `git` CLI). */
56
+ spawner?: GitSpawner;
57
+ /** Inject an env override for spawned git (default: process.env minus proxy secrets). */
58
+ env?: NodeJS.ProcessEnv;
59
+ }
60
+ /** Sentinel error when git exits non-zero. */
61
+ declare class GitError extends Error {
62
+ readonly args: string[];
63
+ readonly code: number;
64
+ readonly stderr: string;
65
+ readonly stdout: string;
66
+ constructor(args: string[], result: GitSpawnResult);
67
+ }
68
+ //#endregion
69
+ //#region src/git-client/index.d.ts
70
+ /**
71
+ * Skill & Agent v2 — Client GitClient (M3)
72
+ *
73
+ * Wraps `git` so all upstream traffic flows through the server's git
74
+ * proxy at `serverProxyBase`. See docs/architecture/skill-agent-v2-repo.md
75
+ * §5.4.
76
+ *
77
+ * Why a wrapper instead of using libgit2 directly:
78
+ * 1. `git` is already installed everywhere we run (extension host,
79
+ * CLI). No native deps.
80
+ * 2. Users can debug their skill repos with plain `git` commands when
81
+ * SERVICEME is misbehaving — the wrappers keep a familiar CLI.
82
+ * 3. libgit2's packfile negotiation has subtle correctness gaps that
83
+ * we don't want to debug server-side.
84
+ *
85
+ * URL rewrite:
86
+ * `https://github.com/owner/repo.git` → `<proxyBase>/<id>`
87
+ *
88
+ * When git hits `<proxyBase>/<id>` it discovers the proxy's
89
+ * `/info/refs?service=git-upload-pack` endpoint via the smart-HTTP
90
+ * protocol. From there the server takes over.
91
+ */
92
+ declare class GitClient {
93
+ private readonly serverProxyBase;
94
+ private readonly spawner;
95
+ constructor(opts: GitClientOptions);
96
+ /**
97
+ * Rewrite an upstream URL to its proxy form.
98
+ *
99
+ * Examples:
100
+ * rewriteRemoteUrl("repo-aHR0cHM6Ly9naXRodWIuY29tL21lZGFsc29mdGNoaW5hL21zLXNraWxscy5naXQ",
101
+ * "https://github.com/medalsoftchina/ms-skills.git")
102
+ * → "http://localhost:3000/git-proxy/repo-aHR0cHM6Ly9naXRodWIuY29tL21lZGFsc29mdGNoaW5hL21zLXNraWxscy5naXQ"
103
+ *
104
+ * rewriteRemoteUrl("repo-aHR0cHM6Ly9naXRodWIuY29tL3RlYW0vaW50ZXJuYWwuZ2l0",
105
+ * "git@github.com:medalsoftchina/ms-skills.git")
106
+ * → "http://localhost:3000/git-proxy/repo-aHR0cHM6Ly9naXRodWIuY29tL3RlYW0vaW50ZXJuYWwuZ2l0"
107
+ *
108
+ * The original URL's host/owner is intentionally DROPPED — the proxy
109
+ * knows the upstream from the per-repo config, not from the URL. This
110
+ * means callers can route both default and user repos through the same
111
+ * dynamic proxy-id scheme.
112
+ */
113
+ rewriteRemoteUrl(_repoId: string, originalUrl: string, useProxy?: boolean): string;
114
+ /**
115
+ * `git clone <proxyUrl> <localPath>` — initialize a new local repo
116
+ * from the proxy. Returns when the clone succeeds; throws on failure.
117
+ *
118
+ * When `branch` is provided, the clone is restricted to that branch
119
+ * via `git clone -b <branch> -- <proxyUrl> <localPath>` so the local
120
+ * checkout lands on the configured `repo.branch` instead of the
121
+ * upstream default branch. The parameter is optional and backward
122
+ * compatible — omitting it keeps the original behaviour.
123
+ */
124
+ clone(repoId: string, originalUrl: string, localPath: string, branch?: string, useProxy?: boolean): Promise<void>;
125
+ /**
126
+ * `git fetch <remote> <branch>` + return the resulting commit SHA.
127
+ * Operates on an already-cloned repo at `localPath`.
128
+ *
129
+ * When `branch` is provided, the pull target is forced to that branch:
130
+ * if the local working tree is on a different branch, `git checkout
131
+ * <branch>` is issued first (git auto-tracks `origin/<branch>`), so
132
+ * the sync leaves the repo parked on the configured `repo.branch`.
133
+ * When `branch` is omitted the legacy behaviour is preserved — the
134
+ * current local branch is fast-forwarded. The parameter is optional
135
+ * and backward compatible.
136
+ */
137
+ pull(repoId: string, localPath: string, branch?: string, useProxy?: boolean, originalUrl?: string): Promise<PullResult>;
138
+ /**
139
+ * `git push origin <branch>` via the proxy. Caller is responsible
140
+ * for committing locally first. The server's GitProxy injects the
141
+ * PAT on the way upstream.
142
+ */
143
+ push(repoId: string, localPath: string, branch: string, useProxy?: boolean): Promise<PushResult>;
144
+ /**
145
+ * `git ls-remote <proxyUrl>` — list advertised branches without
146
+ * cloning. Used by addUserRepo to detect the default branch.
147
+ */
148
+ lsRemote(repoId: string, originalUrl: string, useProxy?: boolean): Promise<RemoteBranch[]>;
149
+ /**
150
+ * Fetch an exact commit and detach HEAD at it. Used by workspace
151
+ * content restoration, which must never silently advance to a branch
152
+ * head. Returns the verified commit SHA.
153
+ */
154
+ checkoutCommit(localPath: string, commit: string, repoId: string, useProxy?: boolean, originalUrl?: string): Promise<string>;
155
+ /**
156
+ * Resolve a repo-relative path inside the git directory using
157
+ * `git rev-parse --git-path`, which handles linked worktrees and
158
+ * submodules correctly (their metadata does not live under
159
+ * `<worktree>/.git` as a directory).
160
+ */
161
+ gitPath(localPath: string, pathspec: string): Promise<string>;
162
+ /**
163
+ * Resolve the current HEAD commit of a local clone. Returns an empty
164
+ * string when git cannot resolve it (e.g. an empty repository) so
165
+ * callers can decide how to surface the failure.
166
+ */
167
+ revParseHead(localPath: string): Promise<string>;
168
+ /**
169
+ * `git add <pathspec…>` followed by `git commit -m <message>`. The
170
+ * commit message convention follows the spec: `feat(skills): add
171
+ * <name>` / `feat(agents): add <name>`.
172
+ */
173
+ commit(localPath: string, message: string, addPath?: string): Promise<{
174
+ commitSha: string;
175
+ }>;
176
+ private runOrThrow;
177
+ private getRemoteUrl;
178
+ private safeRevParse;
179
+ private currentBranch;
180
+ }
181
+ declare class NodeGitSpawner implements GitSpawner {
182
+ spawn(args: string[], opts: {
183
+ cwd?: string;
184
+ }): Promise<GitSpawnResult>;
185
+ }
186
+ /** Convenience: a record-based stub spawner for tests. */
187
+ declare class StubGitSpawner implements GitSpawner {
188
+ /** queue of canned responses, consumed FIFO per spawn() call. */
189
+ readonly script: GitSpawnResult[];
190
+ /** All spawn() invocations, in order, for assertions. */
191
+ readonly calls: Array<{
192
+ args: string[];
193
+ cwd: string | undefined;
194
+ }>;
195
+ constructor(script: GitSpawnResult[]);
196
+ spawn(args: string[], opts: {
197
+ cwd?: string;
198
+ }): Promise<GitSpawnResult>;
199
+ }
200
+ /**
201
+ * Helper: encode a bare absolute file URL (`file:///...`) for local
202
+ * git clone tests. Not used by GitClient directly — exposed for
203
+ * RepoManager's `localSeed` use case.
204
+ */
205
+ declare function toFileUrl(absolutePath: string): string;
206
+ /** Path suffix appended to a server base URL to reach its git-proxy route. */
207
+ declare const GIT_PROXY_PATH_SUFFIX = "/git-proxy";
208
+ /**
209
+ * Single source of truth for deriving a {@link GitClientOptions.serverProxyBase}
210
+ * from an already-resolved, non-empty server base URL (e.g. the extension's
211
+ * verified marketplace server). Callers that derive `serverProxyBase` from a
212
+ * known server base URL — extension bootstrap, the sync scheduler, the CLI
213
+ * bridge subprocess env — should go through this helper instead of
214
+ * re-deriving the `/git-proxy` suffix locally, so the route contract only
215
+ * lives in one place. (Standalone CLI defaults such as
216
+ * `http://127.0.0.1:3000/git-proxy`, used when no server base URL is known
217
+ * at all, are a separate concern and don't go through this helper.)
218
+ *
219
+ * Callers MUST guard against an empty/falsy `serverBaseUrl` before calling —
220
+ * this function does not validate its input and will happily return the
221
+ * non-URL `"/git-proxy"` for an empty string.
222
+ */
223
+ declare function buildGitProxyBase(serverBaseUrl: string): string;
224
+ //#endregion
225
+ //#region src/submit/types.d.ts
226
+ /**
227
+ * Skill & Agent v2 — SubmitClient Types (M4)
228
+ *
229
+ * Mirrors the server's POST /api/v1/skills/validate contract (M2
230
+ * SubmitApi). Defined here as a separate types file so the test
231
+ * fixtures + the client can both import without circular deps.
232
+ */
233
+ /** Reasons the server may deny a submission. */
234
+ type DenyReason = "repo_not_writable" | "file_too_large" | "path_traversal" | "invalid_frontmatter" | "name_conflict" |
235
+ /** Local-client-side errors that don't come from the server. */
236
+ "network_error" | "write_error" | "commit_error" | "push_error" | "unknown";
237
+ /** Request payload. Identical to the server's SubmitValidationRequest. */
238
+ interface SubmitValidationRequest {
239
+ repoId: string;
240
+ skillName: string;
241
+ files: Array<{
242
+ path: string;
243
+ content: string;
244
+ }>;
245
+ }
246
+ /** Response payload. Identical to the server's SubmitValidationResponse. */
247
+ interface SubmitValidationResponse {
248
+ allow: boolean;
249
+ reason?: DenyReason;
250
+ detail?: string;
251
+ }
252
+ /** Sentinel error thrown by SubmitClient.submit() / validate(). */
253
+ declare class SubmitError extends Error {
254
+ readonly reason: DenyReason;
255
+ readonly detail: string;
256
+ readonly status?: number;
257
+ constructor(reason: DenyReason, detail: string, options?: {
258
+ status?: number;
259
+ });
260
+ }
261
+ //#endregion
262
+ //#region src/submit/index.d.ts
263
+ /**
264
+ * Skill & Agent v2 — SubmitClient (M4)
265
+ *
266
+ * SubmitClient orchestrates the "validate then push" flow described
267
+ * in docs/architecture/skill-agent-v2-repo.md §5.7:
268
+ *
269
+ * 1. **validate** — POST the candidate files to the server's
270
+ * `/api/v1/skills/validate` endpoint (5 deny reasons: repo_not_
271
+ * writable, file_too_large, path_traversal, invalid_frontmatter,
272
+ * name_conflict).
273
+ * 2. **write** — materialize the files into the local repo clone at
274
+ * `~/.serviceme/repos/<repoId>/skills/<name>/` (or `agents/`).
275
+ * 3. **commit** — `git add . && git commit -m "feat(skills): add <name>"`.
276
+ * 4. **push** — `git push origin <branch>` via the server proxy.
277
+ *
278
+ * The client is intentionally thin: it does NOT do its own validation
279
+ * (the server is the gate), and it does NOT cache anything across
280
+ * calls. The single source of truth for "is this submission allowed?"
281
+ * is the server's validate endpoint.
282
+ *
283
+ * @see docs/architecture/skill-agent-v2-repo.md §5.7 SubmitClient
284
+ */
285
+ interface SubmitOptions {
286
+ /** Override the server's validate URL. Defaults to `http://localhost:3000/api/v1`. */
287
+ serverBaseUrl?: string;
288
+ /** Override the branch to push. Defaults to the repo's `branch` field. */
289
+ branch?: string;
290
+ /** Skip the actual push (for tests + dry-runs). When true, step 4 returns a synthetic PushResult. */
291
+ skipPush?: boolean;
292
+ }
293
+ interface SubmitResult {
294
+ repoId: string;
295
+ skillName: string;
296
+ commitSha: string;
297
+ pushedRef?: string;
298
+ pushedSha?: string;
299
+ }
300
+ interface SubmitClientOptions {
301
+ gitClient: GitClient;
302
+ /** Lookup the default branch for a repo (config-driven). */
303
+ getRepoBranch?: (repoId: string) => string | undefined;
304
+ /** HTTP fetch impl (defaults to the global `fetch`). */
305
+ fetcher?: typeof fetch;
306
+ /** Default server base URL when no override is supplied. */
307
+ defaultServerBaseUrl?: string;
308
+ }
309
+ declare class SubmitClient {
310
+ private readonly git;
311
+ private readonly getRepoBranch;
312
+ private readonly fetcher;
313
+ private readonly defaultServerBaseUrl;
314
+ constructor(opts: SubmitClientOptions);
315
+ /**
316
+ * Validate-only path. Useful for the UI's "Save Draft" flow which
317
+ * wants to surface validation errors without committing or pushing.
318
+ */
319
+ validate(req: SubmitValidationRequest): Promise<SubmitValidationResponse>;
320
+ /**
321
+ * Full submit pipeline. Throws `SubmitError` on:
322
+ * - validate deny (reason echoed)
323
+ * - network failure (network_error)
324
+ * - local write failure
325
+ * - commit/push failure
326
+ */
327
+ submit(repoId: string, skillName: string, files: SkillFile[], opts?: SubmitOptions): Promise<SubmitResult>;
328
+ }
329
+ //#endregion
330
+ export { SubmitError as a, NodeGitSpawner as c, toFileUrl as d, GitError as f, SubmitResult as i, StubGitSpawner as l, SubmitClientOptions as n, GIT_PROXY_PATH_SUFFIX as o, PullResult as p, SubmitOptions as r, GitClient as s, SubmitClient as t, buildGitProxyBase as u };
331
+ //# sourceMappingURL=index-Dp6FwWKh.d.ts.map