skill-flow 1.0.3 → 1.0.4

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/README.md CHANGED
@@ -27,6 +27,9 @@ Set it up once, deploy to multiple agents (Claude Code, Cursor, Windsurf, and 13
27
27
  **Interactive Terminal UI**
28
28
  Intuitive TUI: view groups → select skills → choose targets → save configuration.
29
29
 
30
+ **Bootstrap On Config Open**
31
+ `config` renders immediately, shows boot progress, adopts unmanaged skills already found in agent roots, then audits current projections before entering the main UI.
32
+
30
33
  **Explicit State Tracking**
31
34
  `manifest.json` = what you want, `lock.json` = what's actually installed. Both are readable and queryable.
32
35
 
@@ -86,11 +89,35 @@ skill-flow uninstall my-source-id
86
89
 
87
90
  By default, `add` preselects all discovered skills and all detected agent targets. When `--path <repoSubpath>` is provided, the full repo is still imported, but only skills under that path are preselected.
88
91
 
92
+ Examples:
93
+
94
+ ```bash
95
+ # Local repo
96
+ skill-flow add ~/code/my-skills
97
+
98
+ # GitHub shorthand
99
+ skill-flow add garrytan/gstack
100
+
101
+ # Full Git URL
102
+ skill-flow add https://github.com/garrytan/gstack.git
103
+ skill-flow add git@github.com:garrytan/gstack.git
104
+
105
+ # GitHub tree URL
106
+ skill-flow add https://github.com/garrytan/gstack/tree/main/skills
107
+
108
+ # Import the repo, but only preselect skills under a subpath
109
+ skill-flow add garrytan/gstack --path skills
110
+
111
+ # ClawHub package
112
+ skill-flow add clawhub:example/skill-pack
113
+ skill-flow add clawhub:example/skill-pack@1.2.3
114
+ ```
115
+
89
116
  ## Command Reference
90
117
 
91
118
  | Command | Description |
92
119
  |---|---|
93
- | `add <source>` | Add a skill source (Git repo or ClawHub) |
120
+ | `add <source>` | Add a skill source (local path, Git repo, or ClawHub) |
94
121
  | `find <query>` | Search installed skills, built-in Git catalogs, and ClawHub |
95
122
  | `search <query>` | Alias of `find` |
96
123
  | `list` | Show skills groups |
@@ -106,6 +133,7 @@ When selected skills collide by name, `skill-flow` keeps identical duplicates as
106
133
  **State Management**
107
134
  - `~/.skillflow/manifest.json` - Your configuration (what you want)
108
135
  - `~/.skillflow/lock.json` - Actual state (what's installed)
136
+ - `~/.skillflow/source/local/<source-id>/` - Imported local sources and adopted unmanaged external skills
109
137
  - `~/.skillflow/source/git/<source-id>/` - Git repo cache
110
138
  - `~/.skillflow/source/clawhub/<source-id>/` - ClawHub cache
111
139
  - `~/.skillflow/catalog/git/<source-id>/` - Built-in Git catalog cache
@@ -113,13 +141,22 @@ When selected skills collide by name, `skill-flow` keeps identical duplicates as
113
141
  **Deployment Strategy**
114
142
  Uses symlinks when possible, file copies when needed. Target directories are just deploy points — real state lives in lock.json.
115
143
 
144
+ **Config Bootstrap**
145
+ - detect available agent targets
146
+ - scan known agent `skills/` roots for unmanaged skills
147
+ - import unmanaged external skills into `~/.skillflow/source/local/`
148
+ - refresh inventory, normalize bindings, and audit projections
149
+ - enter the interactive config UI
150
+
151
+ Already-managed projections are not imported again. For example, if an agent root contains symlinks that already point into `~/.skillflow/source/*`, bootstrap treats them as managed state and skips them.
152
+
116
153
  ## Supported Agents
117
154
 
118
155
  Claude Code · Codex · Cursor · GitHub Copilot · Gemini CLI · OpenCode · OpenClaw · Pi · Windsurf · Roo Code · Cline · Amp · Kiro
119
156
 
120
157
  Customize target paths via environment variables (e.g., `SKILL_FLOW_TARGET_CLAUDE_CODE`).
121
158
 
122
- Broader ecosystem path references, including project-level rules and instructions paths, are tracked in [docs/refrences/agent-skill-paths.md](./docs/refrences/agent-skill-paths.md).
159
+ Broader ecosystem path references, including project-level rules and instructions paths (docs TBD).
123
160
 
124
161
  ## Built-in Discovery Catalogs
125
162
 
package/README.zh.md CHANGED
@@ -26,6 +26,9 @@
26
26
  **交互式终端 UI**
27
27
  直观的 TUI 界面:查看分组 → 选择技能 → 选择目标 → 保存配置。
28
28
 
29
+ **进入 Config 自动自举**
30
+ `config` 会先立即渲染,再显示启动进度;启动阶段会识别 agent 根目录里尚未纳入管理的 skill,回填到 `skill-flow`,并在进入主界面前完成状态审计。
31
+
29
32
  **显式状态追踪**
30
33
  `manifest.json` 记录你的意图,`lock.json` 记录实际安装状态。状态清晰可查。
31
34
 
@@ -85,11 +88,35 @@ skill-flow uninstall my-source-id
85
88
 
86
89
  `add` 默认会预选该源的全部 skill,以及当前检测到的全部 agent 目标。传入 `--path <repoSubpath>` 时,仍然会导入整个仓库,但只会预选该路径下的 skill。
87
90
 
91
+ 示例:
92
+
93
+ ```bash
94
+ # 本地仓库
95
+ skill-flow add ~/code/my-skills
96
+
97
+ # GitHub 简写
98
+ skill-flow add garrytan/gstack
99
+
100
+ # 完整 Git URL
101
+ skill-flow add https://github.com/garrytan/gstack.git
102
+ skill-flow add git@github.com:garrytan/gstack.git
103
+
104
+ # GitHub tree URL
105
+ skill-flow add https://github.com/garrytan/gstack/tree/main/skills
106
+
107
+ # 导入整个仓库,但只预选某个子路径下的 skill
108
+ skill-flow add garrytan/gstack --path skills
109
+
110
+ # ClawHub 包
111
+ skill-flow add clawhub:example/skill-pack
112
+ skill-flow add clawhub:example/skill-pack@1.2.3
113
+ ```
114
+
88
115
  ## 命令参考
89
116
 
90
117
  | 命令 | 说明 |
91
118
  |---|---|
92
- | `add <source>` | 添加技能源(Git 仓库或 ClawHub) |
119
+ | `add <source>` | 添加技能源(本地路径、Git 仓库或 ClawHub) |
93
120
  | `find <query>` | 搜索本地已安装技能、内置 Git 仓库和 ClawHub |
94
121
  | `search <query>` | `find` 的别名 |
95
122
  | `list` | 显示 Skill 分组 |
@@ -105,6 +132,7 @@ skill-flow uninstall my-source-id
105
132
  **状态管理**
106
133
  - `~/.skillflow/manifest.json` - 你的配置(你想要什么)
107
134
  - `~/.skillflow/lock.json` - 实际状态(实际装了什么)
135
+ - `~/.skillflow/source/local/<source-id>/` - 本地导入源,以及启动时接管的外部 skill
108
136
  - `~/.skillflow/source/git/<source-id>/` - Git 仓库缓存
109
137
  - `~/.skillflow/source/clawhub/<source-id>/` - ClawHub 缓存
110
138
  - `~/.skillflow/catalog/git/<source-id>/` - 内置 Git 仓库缓存
@@ -112,13 +140,22 @@ skill-flow uninstall my-source-id
112
140
  **部署策略**
113
141
  优先使用符号链接,必要时使用文件复制。目标目录只是部署点,真正的状态在 lock.json 里。
114
142
 
143
+ **Config 启动时会做什么**
144
+ - 检测当前可用 agent 目标
145
+ - 扫描已知 agent `skills/` 根目录中的未受管 skill
146
+ - 将这些外部 skill 导入到 `~/.skillflow/source/local/`
147
+ - 刷新 inventory、归一化 bindings、审计当前投影状态
148
+ - 然后进入交互式 config 界面
149
+
150
+ 如果某个 agent 根目录里的 symlink 本来就已经指向 `~/.skillflow/source/*` 下的受管内容,bootstrap 会把它视为已管理状态,不会重复回填。
151
+
115
152
  ## 支持的 Agent
116
153
 
117
154
  Claude Code · Codex · Cursor · GitHub Copilot · Gemini CLI · OpenCode · OpenClaw · Pi · Windsurf · Roo Code · Cline · Amp · Kiro
118
155
 
119
156
  可通过环境变量自定义目标路径(如 `SKILL_FLOW_TARGET_CLAUDE_CODE`)。
120
157
 
121
- 更广义的生态路径参考,包括 project 级 rules / instructions 路径,见 [docs/refrences/agent-skill-paths.md](./docs/refrences/agent-skill-paths.md)。
158
+ 更广义的生态路径参考,包括 project 级 rules / instructions 路径(文档整理中)。
122
159
 
123
160
  ## 默认内置发现仓库
124
161
 
package/dist/cli.js CHANGED
@@ -3,7 +3,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { Command } from "commander";
4
4
  import { render } from "ink";
5
5
  import { SkillFlowApp } from "./services/skill-flow.js";
6
- import { ConfigApp } from "./tui/config-app.js";
6
+ import { ConfigBootstrapApp } from "./tui/config-app.js";
7
7
  import { FindApp } from "./tui/find-app.js";
8
8
  import { formatGroupRef } from "./utils/naming.js";
9
9
  import { formatDoctorIssue, formatWorkflowList, } from "./utils/format.js";
@@ -48,13 +48,13 @@ program
48
48
  .argument("<query>", "Search query")
49
49
  .option("--json", "Print JSON output")
50
50
  .action(async (query, options) => {
51
- const result = await app.findSkills(query);
52
- if (!result.ok) {
53
- printErrors(result.errors);
54
- process.exitCode = 1;
55
- return;
56
- }
57
51
  if (options.json) {
52
+ const result = await app.findSkills(query);
53
+ if (!result.ok) {
54
+ printErrors(result.errors);
55
+ process.exitCode = 1;
56
+ return;
57
+ }
58
58
  console.log(JSON.stringify(result.data.candidates.map((candidate) => ({
59
59
  ...candidate,
60
60
  nextCommand: buildFindCommand(candidate),
@@ -62,37 +62,11 @@ program
62
62
  printWarnings(result.warnings.map((warning) => warning.message));
63
63
  return;
64
64
  }
65
- const instance = render(_jsx(FindApp, { app: app, query: query, candidates: result.data.candidates }));
66
- if (result.warnings.length > 0) {
67
- for (const warning of result.warnings) {
68
- console.warn(`warning: ${warning.message}`);
69
- }
70
- }
65
+ const instance = render(_jsx(FindApp, { app: app, query: query }));
71
66
  await instance.waitUntilExit();
72
67
  });
73
68
  program.command("config").action(async () => {
74
- const result = await app.getConfigData();
75
- if (!result.ok) {
76
- printErrors(result.errors);
77
- process.exitCode = 1;
78
- return;
79
- }
80
- const initialDrafts = Object.fromEntries(result.data.summaries.map((summary) => {
81
- const targets = summary.bindings.targets;
82
- const enabledTargets = Object.entries(targets)
83
- .filter(([, value]) => value?.enabled)
84
- .map(([target]) => target);
85
- const selectedLeafIds = [...new Set(enabledTargets.flatMap((target) => targets[target]?.leafIds ?? []))];
86
- return [
87
- summary.source.id,
88
- {
89
- enabledTargets,
90
- selectedLeafIds,
91
- },
92
- ];
93
- }));
94
- const availableTargets = await app.getAvailableTargets();
95
- const instance = render(_jsx(ConfigApp, { app: app, availableTargets: availableTargets, summaries: result.data.summaries, initialDrafts: initialDrafts }));
69
+ const instance = render(_jsx(ConfigBootstrapApp, { app: app }));
96
70
  await instance.waitUntilExit();
97
71
  });
98
72
  program
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.tsx"],"names":[],"mappings":"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"}
@@ -17,7 +17,7 @@ export type Result<T> = {
17
17
  warnings: Warning[];
18
18
  errors: Failure[];
19
19
  };
20
- export type SourceKind = "git" | "clawhub";
20
+ export type SourceKind = "local" | "git" | "clawhub";
21
21
  export type DeploymentTargetName = "claude-code" | "codex" | "cursor" | "github-copilot" | "gemini-cli" | "opencode" | "openclaw" | "pi" | "windsurf" | "roo-code" | "cline" | "amp" | "kiro";
22
22
  export type DeploymentStrategy = "symlink" | "copy";
23
23
  export type HealthStatus = "HEALTHY" | "ACTIVE" | "INACTIVE" | "PARTIAL" | "BLOCKED" | "INVALID" | "UPDATE AVAILABLE" | "UP TO DATE" | "DRIFT DETECTED";
@@ -28,6 +28,9 @@ export type SourceManifestRecord = {
28
28
  displayName: string;
29
29
  addedAt: string;
30
30
  requestedPath?: string;
31
+ selectionMode?: "all" | "partial";
32
+ originLocator?: string;
33
+ originRequestedPath?: string;
31
34
  };
32
35
  export type TargetBinding = {
33
36
  enabled: boolean;
@@ -59,6 +62,9 @@ export type SourceLockRecord = {
59
62
  resolvedVersion?: string;
60
63
  contentHash?: string;
61
64
  versionMode?: "pinned" | "floating";
65
+ originBranch?: string;
66
+ importedFromTargets?: DeploymentTargetName[];
67
+ importMode?: "explicit-add" | "bootstrap-detected";
62
68
  };
63
69
  export type LeafRecord = {
64
70
  id: string;
@@ -138,6 +144,11 @@ export type WorkflowSummary = {
138
144
  bindings: SourceBinding;
139
145
  activeTargetCount: number;
140
146
  health: HealthStatus;
147
+ issueCounts?: {
148
+ warning: number;
149
+ error: number;
150
+ };
151
+ healthReason?: string;
141
152
  };
142
153
  export type SkillCandidateAction = {
143
154
  type: "none";
@@ -1,4 +1,4 @@
1
- import type { DeploymentAction, DeploymentPlan, DeploymentTargetName, DoctorReport, LockFile, Manifest, Result, SkillCandidate, SourceBinding, Warning, WorkflowSummary } from "../domain/types.js";
1
+ import type { DeploymentAction, DeploymentPlan, DeploymentTargetName, DoctorReport, LockFile, Manifest, Result, SkillCandidate, SourceBinding, WorkflowSummary } from "../domain/types.js";
2
2
  import { StateStore } from "../state/store.js";
3
3
  import { DeploymentApplier } from "./deployment-applier.js";
4
4
  import { DeploymentPlanner } from "./deployment-planner.js";
@@ -6,7 +6,8 @@ import { DoctorService } from "./doctor-service.js";
6
6
  import { InventoryService } from "./inventory-service.js";
7
7
  import { SourceService } from "./source-service.js";
8
8
  import { WorkflowService } from "./workflow-service.js";
9
- import type { AddSourceOptions } from "./source-service.js";
9
+ import type { AddSourceOptions, SourceSnapshot } from "./source-service.js";
10
+ import { WorkspaceBootstrapService, type BootstrapEvent } from "./workspace-bootstrap-service.js";
10
11
  export type DraftBinding = {
11
12
  enabledTargets: DeploymentTargetName[];
12
13
  selectedLeafIds: string[];
@@ -19,17 +20,8 @@ export declare class SkillFlowApp {
19
20
  readonly applier: DeploymentApplier;
20
21
  readonly doctorService: DoctorService;
21
22
  readonly workflowService: WorkflowService;
22
- addSource(locator: string, options?: AddSourceOptions): Promise<{
23
- ok: true;
24
- data: import("./source-service.js").SourceSnapshot;
25
- warnings: Warning[];
26
- errors: [];
27
- } | {
28
- ok: false;
29
- data?: import("./source-service.js").SourceSnapshot;
30
- warnings: Warning[];
31
- errors: import("../domain/types.js").Failure[];
32
- }>;
23
+ readonly workspaceBootstrapService: WorkspaceBootstrapService;
24
+ addSource(locator: string, options?: AddSourceOptions): Promise<Result<SourceSnapshot>>;
33
25
  findSkills(query: string): Promise<Result<{
34
26
  candidates: SkillCandidate[];
35
27
  }>>;
@@ -41,6 +33,15 @@ export declare class SkillFlowApp {
41
33
  lockFile: LockFile;
42
34
  summaries: WorkflowSummary[];
43
35
  }>>;
36
+ bootstrapWorkspaceState(onEvent?: (event: BootstrapEvent) => void): Promise<Result<{
37
+ availableTargets: DeploymentTargetName[];
38
+ manifest: Manifest;
39
+ lockFile: LockFile;
40
+ summaries: WorkflowSummary[];
41
+ initialDrafts: Record<string, DraftBinding>;
42
+ audit: DoctorReport;
43
+ importedSourceIds: string[];
44
+ }>>;
44
45
  getAvailableTargets(): Promise<DeploymentTargetName[]>;
45
46
  previewDraft(sourceId: string, draft: DraftBinding): Promise<Result<{
46
47
  plan: DeploymentPlan;
@@ -89,4 +90,6 @@ export declare class SkillFlowApp {
89
90
  private getQueryScore;
90
91
  private getCandidateKey;
91
92
  private formatSourceLabel;
93
+ private buildInitialDrafts;
94
+ private applySelectionModeForUpdatedSources;
92
95
  }
@@ -1,4 +1,5 @@
1
1
  import fs from "node:fs/promises";
2
+ import path from "node:path";
2
3
  import { createChannelAdapters } from "../adapters/channel-adapters.js";
3
4
  import { StateStore } from "../state/store.js";
4
5
  import { ensureDir, hashDirectory, pathExists, readJsonFile, removePath, writeJsonFile } from "../utils/fs.js";
@@ -14,6 +15,7 @@ import { DoctorService } from "./doctor-service.js";
14
15
  import { InventoryService } from "./inventory-service.js";
15
16
  import { SourceService } from "./source-service.js";
16
17
  import { WorkflowService } from "./workflow-service.js";
18
+ import { WorkspaceBootstrapService, } from "./workspace-bootstrap-service.js";
17
19
  export class SkillFlowApp {
18
20
  store = new StateStore();
19
21
  inventoryService = new InventoryService();
@@ -22,8 +24,10 @@ export class SkillFlowApp {
22
24
  applier = new DeploymentApplier();
23
25
  doctorService = new DoctorService();
24
26
  workflowService = new WorkflowService();
27
+ workspaceBootstrapService = new WorkspaceBootstrapService(this.store);
25
28
  async addSource(locator, options) {
26
- const result = await this.sourceService.addSource(locator, options);
29
+ const addOptions = options ?? {};
30
+ const result = await this.sourceService.addSource(locator, addOptions);
27
31
  if (!result.ok) {
28
32
  return result;
29
33
  }
@@ -34,12 +38,29 @@ export class SkillFlowApp {
34
38
  if (!source) {
35
39
  return result;
36
40
  }
41
+ source.selectionMode =
42
+ addOptions.selectionMode ??
43
+ (source.requestedPath ? "partial" : "all");
44
+ const enabledTargets = addOptions.enabledTargets ??
45
+ await this.getAvailableTargets();
37
46
  manifest.bindings[source.id] = this.bindingFromDraft({
38
- enabledTargets: await this.getAvailableTargets(),
47
+ enabledTargets,
39
48
  selectedLeafIds: this.selectLeafIdsForRequestedPath(lockFile.leafInventory.filter((leaf) => leaf.sourceId === source.id), source.requestedPath),
40
49
  });
41
50
  await this.store.writeManifest(manifest);
42
- return result;
51
+ if (addOptions.project === false) {
52
+ return result;
53
+ }
54
+ const plan = await this.planForAffectedSources(manifest, lockFile, source.id);
55
+ if (!plan.ok) {
56
+ return fail(plan.errors, [...result.warnings, ...plan.warnings]);
57
+ }
58
+ const applied = await this.applier.applyPlan(lockFile, plan.data.actions);
59
+ await this.store.writeLock(lockFile);
60
+ if (!applied.ok) {
61
+ return fail(applied.errors, [...result.warnings, ...plan.warnings, ...applied.warnings]);
62
+ }
63
+ return ok(result.data, [...result.warnings, ...plan.warnings, ...applied.warnings]);
43
64
  }
44
65
  async findSkills(query) {
45
66
  await this.store.init();
@@ -157,6 +178,95 @@ export class SkillFlowApp {
157
178
  summaries: this.workflowService.getSummaries(manifest, lockFile),
158
179
  });
159
180
  }
181
+ async bootstrapWorkspaceState(onEvent) {
182
+ onEvent?.({
183
+ phase: "detect-targets",
184
+ level: "info",
185
+ message: "Detecting available agent targets...",
186
+ });
187
+ const availableTargets = await this.getAvailableTargets();
188
+ await this.store.init();
189
+ let manifest = await this.store.readManifest();
190
+ let lockFile = await this.store.readLock();
191
+ const detected = await this.workspaceBootstrapService.detectUnmanagedExternalSkills(manifest, lockFile, onEvent);
192
+ const importedSourceIds = [];
193
+ if (detected.length > 0) {
194
+ onEvent?.({
195
+ phase: "import-unmanaged-skills",
196
+ level: "info",
197
+ message: `Importing ${detected.length} unmanaged skill${detected.length === 1 ? "" : "s"} into skill-flow...`,
198
+ });
199
+ }
200
+ for (const item of detected) {
201
+ const imported = await this.addSource(item.path, {
202
+ enabledTargets: item.importedFromTargets,
203
+ selectionMode: "all",
204
+ project: false,
205
+ sourceIdOverride: item.sourceId,
206
+ displayNameOverride: item.displayName,
207
+ importedFromTargets: item.importedFromTargets,
208
+ importMode: "bootstrap-detected",
209
+ ...(item.originLocator ? { originLocator: item.originLocator } : {}),
210
+ ...(item.originRequestedPath ? { originRequestedPath: item.originRequestedPath } : {}),
211
+ ...(item.originBranch ? { originBranch: item.originBranch } : {}),
212
+ });
213
+ if (!imported.ok) {
214
+ return fail(imported.errors, imported.warnings);
215
+ }
216
+ importedSourceIds.push(imported.data.manifest.id);
217
+ onEvent?.({
218
+ phase: "import-unmanaged-skills",
219
+ level: "success",
220
+ message: `Imported ${imported.data.manifest.displayName}.`,
221
+ });
222
+ }
223
+ onEvent?.({
224
+ phase: "refresh-sources",
225
+ level: "info",
226
+ message: "Refreshing managed inventory...",
227
+ });
228
+ const reconciled = await this.sourceService.reconcileInventory(undefined, { force: true });
229
+ if (!reconciled.ok) {
230
+ return fail(reconciled.errors, reconciled.warnings);
231
+ }
232
+ manifest = await this.store.readManifest();
233
+ lockFile = await this.store.readLock();
234
+ onEvent?.({
235
+ phase: "normalize-bindings",
236
+ level: "info",
237
+ message: "Normalizing config state...",
238
+ });
239
+ await this.persistNormalizedBindings(manifest, lockFile);
240
+ onEvent?.({
241
+ phase: "audit-projections",
242
+ level: "info",
243
+ message: "Auditing current projections...",
244
+ });
245
+ const audit = await this.doctorService.run(manifest, lockFile);
246
+ if (!audit.ok) {
247
+ return fail(audit.errors, audit.warnings);
248
+ }
249
+ onEvent?.({
250
+ phase: "build-summaries",
251
+ level: "info",
252
+ message: "Building config summaries...",
253
+ });
254
+ const summaries = this.workflowService.getSummaries(manifest, lockFile, audit.data);
255
+ onEvent?.({
256
+ phase: "done",
257
+ level: "success",
258
+ message: "Config bootstrap complete.",
259
+ });
260
+ return ok({
261
+ availableTargets,
262
+ manifest,
263
+ lockFile,
264
+ summaries,
265
+ initialDrafts: this.buildInitialDrafts(summaries),
266
+ audit: audit.data,
267
+ importedSourceIds,
268
+ });
269
+ }
160
270
  async getAvailableTargets() {
161
271
  const adapters = createChannelAdapters();
162
272
  const availableTargets = [];
@@ -220,6 +330,7 @@ export class SkillFlowApp {
220
330
  }
221
331
  const manifest = await this.store.readManifest();
222
332
  const lockFile = await this.store.readLock();
333
+ this.applySelectionModeForUpdatedSources(manifest, lockFile, updated.data.updated);
223
334
  await this.persistNormalizedBindings(manifest, lockFile);
224
335
  const activeSourceIds = manifest.sources
225
336
  .map((source) => source.id)
@@ -339,6 +450,14 @@ export class SkillFlowApp {
339
450
  }
340
451
  prepareManifestForDraft(manifest, lockFile, sourceId, draft) {
341
452
  manifest.bindings[sourceId] = this.bindingFromDraft(draft);
453
+ const source = manifest.sources.find((item) => item.id === sourceId);
454
+ if (source) {
455
+ const sourceLeafCount = lockFile.leafInventory.filter((leaf) => leaf.sourceId === sourceId).length;
456
+ source.selectionMode =
457
+ draft.selectedLeafIds.length >= sourceLeafCount && sourceLeafCount > 0
458
+ ? "all"
459
+ : "partial";
460
+ }
342
461
  const conflictingLeafIds = this.findExactDuplicateLeafSelections(manifest, lockFile, sourceId, draft.enabledTargets);
343
462
  const normalizedDraft = {
344
463
  enabledTargets: [...draft.enabledTargets],
@@ -605,11 +724,45 @@ export class SkillFlowApp {
605
724
  return candidate.locator;
606
725
  }
607
726
  formatSourceLabel(locator, displayName) {
727
+ if (locator.startsWith("clawhub:")) {
728
+ return `${displayName}@clawhub`;
729
+ }
730
+ if (path.isAbsolute(locator)) {
731
+ return `${displayName}@local`;
732
+ }
608
733
  const repo = parseGitHubRepo(locator);
609
734
  if (!repo) {
610
735
  return displayName;
611
736
  }
612
- return `${displayName}(@${repo.owner})`;
737
+ return `${displayName}@${repo.owner}`;
738
+ }
739
+ buildInitialDrafts(summaries) {
740
+ return Object.fromEntries(summaries.map((summary) => {
741
+ const enabledTargets = Object.entries(summary.bindings.targets)
742
+ .filter(([, value]) => value?.enabled)
743
+ .map(([target]) => target);
744
+ const selectedLeafIds = [...new Set(enabledTargets.flatMap((target) => summary.bindings.targets[target]?.leafIds ?? []))];
745
+ return [summary.source.id, { enabledTargets, selectedLeafIds }];
746
+ }));
747
+ }
748
+ applySelectionModeForUpdatedSources(manifest, lockFile, updates) {
749
+ for (const update of updates) {
750
+ if (!update.changed || update.addedLeafIds.length === 0) {
751
+ continue;
752
+ }
753
+ const source = manifest.sources.find((item) => item.id === update.sourceId);
754
+ const binding = manifest.bindings[update.sourceId];
755
+ if (!source || !binding || source.selectionMode !== "all") {
756
+ continue;
757
+ }
758
+ for (const targetBinding of Object.values(binding.targets)) {
759
+ if (!targetBinding?.enabled) {
760
+ continue;
761
+ }
762
+ const merged = new Set([...targetBinding.leafIds, ...update.addedLeafIds]);
763
+ targetBinding.leafIds = [...merged].filter((leafId) => lockFile.leafInventory.some((leaf) => leaf.id === leafId && leaf.sourceId === update.sourceId));
764
+ }
765
+ }
613
766
  }
614
767
  }
615
768
  //# sourceMappingURL=skill-flow.js.map