@slats/claude-assets-sync 0.1.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (228) hide show
  1. package/README.md +111 -587
  2. package/bin/claude-sync.mjs +24 -0
  3. package/dist/@aileron/declare/index.d.ts +4 -4
  4. package/dist/claude-hashes.json +20 -0
  5. package/dist/commands/index.d.ts +1 -112
  6. package/dist/commands/runCli/index.d.ts +2 -0
  7. package/dist/commands/runCli/runCli.cjs +31 -0
  8. package/dist/commands/runCli/runCli.d.ts +10 -0
  9. package/dist/commands/runCli/runCli.mjs +29 -0
  10. package/dist/commands/runCli/type.d.ts +28 -0
  11. package/dist/commands/runCli/utils/injectOne.cjs +48 -0
  12. package/dist/commands/runCli/utils/injectOne.d.ts +3 -0
  13. package/dist/commands/runCli/utils/injectOne.mjs +46 -0
  14. package/dist/commands/runCli/utils/resolveScopeFlag.cjs +28 -0
  15. package/dist/commands/runCli/utils/resolveScopeFlag.d.ts +2 -0
  16. package/dist/commands/runCli/utils/resolveScopeFlag.mjs +26 -0
  17. package/dist/commands/runCli/utils/runInject.cjs +36 -0
  18. package/dist/commands/runCli/utils/runInject.d.ts +2 -0
  19. package/dist/commands/runCli/utils/runInject.mjs +34 -0
  20. package/dist/core/buildPlan/buildPlan.cjs +42 -0
  21. package/dist/core/buildPlan/buildPlan.d.ts +2 -0
  22. package/dist/core/buildPlan/buildPlan.mjs +40 -0
  23. package/dist/core/buildPlan/index.d.ts +2 -0
  24. package/dist/core/buildPlan/type.d.ts +32 -0
  25. package/dist/core/buildPlan/utils/toPosix.cjs +9 -0
  26. package/dist/core/buildPlan/utils/toPosix.d.ts +1 -0
  27. package/dist/core/buildPlan/utils/toPosix.mjs +7 -0
  28. package/dist/core/buildPlan/utils/walkFiles.cjs +25 -0
  29. package/dist/core/buildPlan/utils/walkFiles.d.ts +1 -0
  30. package/dist/core/buildPlan/utils/walkFiles.mjs +23 -0
  31. package/dist/core/hash/hash.cjs +30 -0
  32. package/dist/core/hash/hash.d.ts +4 -0
  33. package/dist/core/hash/hash.mjs +26 -0
  34. package/dist/core/hash/index.d.ts +1 -0
  35. package/dist/core/hashManifest/hashManifest.cjs +27 -0
  36. package/dist/core/hashManifest/hashManifest.d.ts +17 -0
  37. package/dist/core/hashManifest/hashManifest.mjs +23 -0
  38. package/dist/core/hashManifest/index.d.ts +1 -0
  39. package/dist/core/index.d.ts +5 -0
  40. package/dist/core/injectDocs/index.d.ts +2 -0
  41. package/dist/core/injectDocs/injectDocs.cjs +43 -0
  42. package/dist/core/injectDocs/injectDocs.d.ts +2 -0
  43. package/dist/core/injectDocs/injectDocs.mjs +41 -0
  44. package/dist/core/injectDocs/type.d.ts +30 -0
  45. package/dist/core/injectDocs/utils/applyAction.cjs +21 -0
  46. package/dist/core/injectDocs/utils/applyAction.d.ts +2 -0
  47. package/dist/core/injectDocs/utils/applyAction.mjs +19 -0
  48. package/dist/core/injectDocs/utils/emitCiForceList.cjs +10 -0
  49. package/dist/core/injectDocs/utils/emitCiForceList.d.ts +2 -0
  50. package/dist/core/injectDocs/utils/emitCiForceList.mjs +8 -0
  51. package/dist/core/injectDocs/utils/printPlan.cjs +20 -0
  52. package/dist/core/injectDocs/utils/printPlan.d.ts +2 -0
  53. package/dist/core/injectDocs/utils/printPlan.mjs +18 -0
  54. package/dist/core/injectDocs/utils/summarize.cjs +27 -0
  55. package/dist/core/injectDocs/utils/summarize.d.ts +3 -0
  56. package/dist/core/injectDocs/utils/summarize.mjs +25 -0
  57. package/dist/core/scope/index.d.ts +1 -0
  58. package/dist/core/scope/scope.cjs +46 -0
  59. package/dist/core/scope/scope.d.ts +16 -0
  60. package/dist/core/scope/scope.mjs +41 -0
  61. package/dist/core/scope/utils/isDirectory.cjs +14 -0
  62. package/dist/core/scope/utils/isDirectory.d.ts +1 -0
  63. package/dist/core/scope/utils/isDirectory.mjs +12 -0
  64. package/dist/index.cjs +15 -9
  65. package/dist/index.d.ts +3 -5
  66. package/dist/index.mjs +7 -3
  67. package/dist/prompts/confirmForce.cjs +27 -0
  68. package/dist/prompts/confirmForce.d.ts +1 -0
  69. package/dist/prompts/confirmForce.mjs +25 -0
  70. package/dist/prompts/index.d.ts +2 -0
  71. package/dist/prompts/selectScope.cjs +30 -0
  72. package/dist/prompts/selectScope.d.ts +2 -0
  73. package/dist/prompts/selectScope.mjs +28 -0
  74. package/dist/utils/heartbeat.cjs +25 -0
  75. package/dist/utils/heartbeat.d.ts +16 -0
  76. package/dist/utils/heartbeat.mjs +23 -0
  77. package/dist/utils/logger.cjs +7 -0
  78. package/dist/utils/logger.d.ts +8 -0
  79. package/dist/utils/logger.mjs +7 -0
  80. package/dist/utils/types.d.ts +1 -252
  81. package/dist/utils/version.cjs +2 -14
  82. package/dist/utils/version.d.ts +3 -53
  83. package/dist/utils/version.mjs +2 -13
  84. package/docs/bundle-size-decision.md +36 -0
  85. package/docs/claude/skills/claude-sync-applier/SKILL.md +195 -0
  86. package/docs/claude/skills/claude-sync-applier/knowledge/claude-md-template.md +77 -0
  87. package/docs/claude/skills/claude-sync-applier/knowledge/dependency-cruiser.md +126 -0
  88. package/docs/claude/skills/claude-sync-applier/knowledge/gotchas.md +139 -0
  89. package/docs/claude/skills/claude-sync-applier/knowledge/package-json-patches.md +130 -0
  90. package/docs/claude/skills/claude-sync-applier/knowledge/reference-files.md +120 -0
  91. package/docs/claude/skills/claude-sync-applier/knowledge/smoke-tests.md +102 -0
  92. package/docs/consumer-integration.md +153 -0
  93. package/package.json +25 -17
  94. package/scripts/build-hashes.mjs +30 -0
  95. package/scripts/buildHashes.d.mts +15 -0
  96. package/scripts/buildHashes.mjs +82 -0
  97. package/scripts/claude-build-hashes.mjs +42 -0
  98. package/scripts/inject-version.js +112 -0
  99. package/dist/cli.cjs +0 -8
  100. package/dist/cli.d.ts +0 -1
  101. package/dist/cli.mjs +0 -7
  102. package/dist/commands/add.cjs +0 -80
  103. package/dist/commands/add.d.ts +0 -8
  104. package/dist/commands/add.mjs +0 -78
  105. package/dist/commands/list.cjs +0 -94
  106. package/dist/commands/list.d.ts +0 -15
  107. package/dist/commands/list.mjs +0 -91
  108. package/dist/commands/migrate.cjs +0 -9
  109. package/dist/commands/migrate.d.ts +0 -6
  110. package/dist/commands/migrate.mjs +0 -7
  111. package/dist/commands/remove.cjs +0 -127
  112. package/dist/commands/remove.d.ts +0 -6
  113. package/dist/commands/remove.mjs +0 -105
  114. package/dist/commands/status.cjs +0 -193
  115. package/dist/commands/status.d.ts +0 -6
  116. package/dist/commands/status.mjs +0 -171
  117. package/dist/commands/sync.cjs +0 -28
  118. package/dist/commands/sync.d.ts +0 -6
  119. package/dist/commands/sync.mjs +0 -26
  120. package/dist/commands/types.d.ts +0 -89
  121. package/dist/commands/update.cjs +0 -209
  122. package/dist/commands/update.d.ts +0 -29
  123. package/dist/commands/update.mjs +0 -206
  124. package/dist/components/add/AddCommand.cjs +0 -103
  125. package/dist/components/add/AddCommand.d.ts +0 -14
  126. package/dist/components/add/AddCommand.mjs +0 -101
  127. package/dist/components/add/BulkAddView.cjs +0 -165
  128. package/dist/components/add/BulkAddView.d.ts +0 -11
  129. package/dist/components/add/BulkAddView.mjs +0 -163
  130. package/dist/components/add/index.d.ts +0 -2
  131. package/dist/components/index.d.ts +0 -2
  132. package/dist/components/list/EditableTreeItem.d.ts +0 -13
  133. package/dist/components/list/ListCommand.cjs +0 -651
  134. package/dist/components/list/ListCommand.d.ts +0 -5
  135. package/dist/components/list/ListCommand.mjs +0 -649
  136. package/dist/components/list/SyncedPackageTree.d.ts +0 -14
  137. package/dist/components/list/index.d.ts +0 -10
  138. package/dist/components/list/types.d.ts +0 -14
  139. package/dist/components/primitives/Box.d.ts +0 -4
  140. package/dist/components/primitives/Spinner.d.ts +0 -6
  141. package/dist/components/primitives/Text.d.ts +0 -4
  142. package/dist/components/primitives/index.d.ts +0 -3
  143. package/dist/components/remove/RemoveConfirm.cjs +0 -18
  144. package/dist/components/remove/RemoveConfirm.d.ts +0 -11
  145. package/dist/components/remove/RemoveConfirm.mjs +0 -16
  146. package/dist/components/shared/Confirm.cjs +0 -30
  147. package/dist/components/shared/Confirm.d.ts +0 -8
  148. package/dist/components/shared/Confirm.mjs +0 -28
  149. package/dist/components/shared/MenuItem.cjs +0 -18
  150. package/dist/components/shared/MenuItem.d.ts +0 -7
  151. package/dist/components/shared/MenuItem.mjs +0 -16
  152. package/dist/components/shared/ProgressBar.d.ts +0 -7
  153. package/dist/components/shared/StepRunner.cjs +0 -58
  154. package/dist/components/shared/StepRunner.d.ts +0 -15
  155. package/dist/components/shared/StepRunner.mjs +0 -56
  156. package/dist/components/shared/Table.cjs +0 -19
  157. package/dist/components/shared/Table.d.ts +0 -8
  158. package/dist/components/shared/Table.mjs +0 -17
  159. package/dist/components/shared/index.d.ts +0 -6
  160. package/dist/components/status/PackageStatusCard.d.ts +0 -10
  161. package/dist/components/status/StatusDisplay.cjs +0 -26
  162. package/dist/components/status/StatusDisplay.d.ts +0 -23
  163. package/dist/components/status/StatusDisplay.mjs +0 -24
  164. package/dist/components/status/StatusTreeNode.cjs +0 -40
  165. package/dist/components/status/StatusTreeNode.d.ts +0 -15
  166. package/dist/components/status/StatusTreeNode.mjs +0 -38
  167. package/dist/components/status/index.d.ts +0 -6
  168. package/dist/components/tree/AssetTreeNode.cjs +0 -54
  169. package/dist/components/tree/AssetTreeNode.d.ts +0 -12
  170. package/dist/components/tree/AssetTreeNode.mjs +0 -52
  171. package/dist/components/tree/TreeSelect.cjs +0 -129
  172. package/dist/components/tree/TreeSelect.d.ts +0 -12
  173. package/dist/components/tree/TreeSelect.mjs +0 -127
  174. package/dist/components/tree/index.d.ts +0 -4
  175. package/dist/core/assetStructure.cjs +0 -30
  176. package/dist/core/assetStructure.d.ts +0 -36
  177. package/dist/core/assetStructure.mjs +0 -27
  178. package/dist/core/cli.cjs +0 -106
  179. package/dist/core/cli.d.ts +0 -9
  180. package/dist/core/cli.mjs +0 -103
  181. package/dist/core/constants.cjs +0 -28
  182. package/dist/core/constants.d.ts +0 -94
  183. package/dist/core/constants.mjs +0 -21
  184. package/dist/core/filesystem.cjs +0 -98
  185. package/dist/core/filesystem.d.ts +0 -94
  186. package/dist/core/filesystem.mjs +0 -88
  187. package/dist/core/github.cjs +0 -115
  188. package/dist/core/github.d.ts +0 -61
  189. package/dist/core/github.mjs +0 -107
  190. package/dist/core/io.cjs +0 -46
  191. package/dist/core/io.d.ts +0 -40
  192. package/dist/core/io.mjs +0 -39
  193. package/dist/core/listOperations.cjs +0 -228
  194. package/dist/core/listOperations.d.ts +0 -43
  195. package/dist/core/listOperations.mjs +0 -205
  196. package/dist/core/localSource.cjs +0 -126
  197. package/dist/core/localSource.d.ts +0 -33
  198. package/dist/core/localSource.mjs +0 -120
  199. package/dist/core/migration.cjs +0 -201
  200. package/dist/core/migration.d.ts +0 -57
  201. package/dist/core/migration.mjs +0 -198
  202. package/dist/core/packageScanner.cjs +0 -360
  203. package/dist/core/packageScanner.d.ts +0 -22
  204. package/dist/core/packageScanner.mjs +0 -356
  205. package/dist/core/sync.cjs +0 -400
  206. package/dist/core/sync.d.ts +0 -21
  207. package/dist/core/sync.mjs +0 -397
  208. package/dist/core/syncMeta.cjs +0 -242
  209. package/dist/core/syncMeta.d.ts +0 -75
  210. package/dist/core/syncMeta.mjs +0 -229
  211. package/dist/utils/dependencies.cjs +0 -57
  212. package/dist/utils/dependencies.d.ts +0 -10
  213. package/dist/utils/dependencies.mjs +0 -34
  214. package/dist/utils/nameTransform.cjs +0 -13
  215. package/dist/utils/nameTransform.d.ts +0 -65
  216. package/dist/utils/nameTransform.mjs +0 -11
  217. package/dist/utils/package.cjs +0 -170
  218. package/dist/utils/package.d.ts +0 -105
  219. package/dist/utils/package.mjs +0 -157
  220. package/dist/utils/packageName.cjs +0 -24
  221. package/dist/utils/packageName.d.ts +0 -32
  222. package/dist/utils/packageName.mjs +0 -21
  223. package/dist/utils/paths.cjs +0 -18
  224. package/dist/utils/paths.d.ts +0 -55
  225. package/dist/utils/paths.mjs +0 -15
  226. package/dist/version.cjs +0 -5
  227. package/dist/version.d.ts +0 -5
  228. package/dist/version.mjs +0 -3
@@ -1,649 +0,0 @@
1
- import { jsx, jsxs } from 'react/jsx-runtime';
2
- import { useApp, useInput, Box, Text } from 'ink';
3
- import SelectInput from 'ink-select-input';
4
- import Spinner from 'ink-spinner';
5
- import { useState, useRef, useEffect, useCallback } from 'react';
6
- import { applyChangesAndSync, computeFileOperations } from '../../core/listOperations.mjs';
7
- import { scanPackageAssets } from '../../core/packageScanner.mjs';
8
- import { syncPackage } from '../../core/sync.mjs';
9
- import { readUnifiedSyncMeta } from '../../core/syncMeta.mjs';
10
- import { updatePackageVersionAndSync } from '../../commands/update.mjs';
11
- import { readLocalPackageJson, readPackageJson } from '../../utils/package.mjs';
12
- import { Confirm } from '../shared/Confirm.mjs';
13
- import { MenuItem } from '../shared/MenuItem.mjs';
14
- import { StepRunner } from '../shared/StepRunner.mjs';
15
- import { Table } from '../shared/Table.mjs';
16
- import { TreeSelect } from '../tree/TreeSelect.mjs';
17
-
18
- function buildPackageDetail(prefix, info, syncedAt) {
19
- let totalAssets = 0;
20
- for (const files of Object.values(info.files)) {
21
- totalAssets += Array.isArray(files) ? files.length : 0;
22
- }
23
- return {
24
- prefix,
25
- originalName: info.originalName,
26
- version: info.version,
27
- local: info.local ?? false,
28
- syncedAt,
29
- files: info.files,
30
- totalAssets,
31
- };
32
- }
33
- function formatSyncDate(dateStr) {
34
- if (!dateStr)
35
- return 'unknown';
36
- try {
37
- return new Date(dateStr).toLocaleString();
38
- }
39
- catch {
40
- return dateStr;
41
- }
42
- }
43
- const ListCommand = ({ cwd }) => {
44
- const { exit } = useApp();
45
- const [phase, setPhase] = useState('loading');
46
- const [meta, setMeta] = useState(null);
47
- const [errorMessage, setErrorMessage] = useState(null);
48
- const [selectedPackage, setSelectedPackage] = useState(null);
49
- const [syncSteps, setSyncSteps] = useState([]);
50
- const [packageFiles, setPackageFiles] = useState({});
51
- const [editTrees, setEditTrees] = useState([]);
52
- const [updateChecking, setUpdateChecking] = useState(false);
53
- const [updateResult, setUpdateResult] = useState(null);
54
- const [updateConfirmPending, setUpdateConfirmPending] = useState(false);
55
- const [updateSyncSteps, setUpdateSyncSteps] = useState([]);
56
- const [updateSyncing, setUpdateSyncing] = useState(false);
57
- const [checkingRemote, setCheckingRemote] = useState(false);
58
- const [remoteVersions, setRemoteVersions] = useState(null);
59
- const hasLoadedRef = useRef(false);
60
- useInput((_input, key) => {
61
- if (!key.escape)
62
- return;
63
- switch (phase) {
64
- case 'main-menu':
65
- exit();
66
- break;
67
- case 'package-list':
68
- setPhase('main-menu');
69
- break;
70
- case 'package-detail':
71
- setSelectedPackage(null);
72
- setPhase('package-list');
73
- break;
74
- case 'edit-assets':
75
- setPhase('package-detail');
76
- break;
77
- case 'status-view':
78
- setRemoteVersions(null);
79
- setCheckingRemote(false);
80
- setPhase('main-menu');
81
- break;
82
- case 'error':
83
- exit();
84
- break;
85
- }
86
- });
87
- useEffect(() => {
88
- if (phase !== 'done')
89
- return;
90
- const timer = setTimeout(() => exit(), 1500);
91
- return () => clearTimeout(timer);
92
- }, [phase, exit]);
93
- const loadMeta = useCallback(() => {
94
- try {
95
- const loaded = readUnifiedSyncMeta(cwd);
96
- setMeta(loaded);
97
- return loaded;
98
- }
99
- catch (err) {
100
- setErrorMessage(err instanceof Error ? err.message : 'Failed to load sync metadata');
101
- setPhase('error');
102
- return null;
103
- }
104
- }, [cwd]);
105
- useEffect(() => {
106
- if (!hasLoadedRef.current) {
107
- hasLoadedRef.current = true;
108
- const loaded = loadMeta();
109
- if (loaded && Object.keys(loaded.packages).length > 0) {
110
- setPhase('main-menu');
111
- }
112
- else if (loaded) {
113
- setPhase('done');
114
- }
115
- }
116
- }, [loadMeta]);
117
- const reloadMeta = useCallback(() => {
118
- const loaded = loadMeta();
119
- if (loaded && selectedPackage) {
120
- const pkgInfo = loaded.packages[selectedPackage.prefix];
121
- if (pkgInfo) {
122
- setSelectedPackage(buildPackageDetail(selectedPackage.prefix, pkgInfo, loaded.syncedAt));
123
- }
124
- else {
125
- setSelectedPackage(null);
126
- }
127
- }
128
- return loaded;
129
- }, [loadMeta, selectedPackage]);
130
- const handleMainMenuSelect = (item) => {
131
- switch (item.value) {
132
- case 'packages':
133
- setPhase('package-list');
134
- break;
135
- case 'status':
136
- setRemoteVersions(null);
137
- setCheckingRemote(false);
138
- setPhase('status-view');
139
- break;
140
- case 'exit':
141
- exit();
142
- break;
143
- }
144
- };
145
- const handlePackageSelect = (item) => {
146
- if (item.value === 'back') {
147
- setPhase('main-menu');
148
- return;
149
- }
150
- if (!meta)
151
- return;
152
- const prefix = item.value;
153
- const pkgInfo = meta.packages[prefix];
154
- if (pkgInfo) {
155
- setSelectedPackage(buildPackageDetail(prefix, pkgInfo, meta.syncedAt));
156
- setPhase('package-detail');
157
- }
158
- };
159
- const handleDetailActionSelect = (item) => {
160
- switch (item.value) {
161
- case 'sync':
162
- setPhase('sync-action');
163
- handleSyncAction();
164
- break;
165
- case 'update':
166
- setUpdateResult(null);
167
- setUpdateConfirmPending(false);
168
- setUpdateSyncing(false);
169
- setUpdateSyncSteps([]);
170
- setPhase('update-action');
171
- handleUpdateActionCheck();
172
- break;
173
- case 'edit-assets':
174
- handleEditAssetsInit();
175
- break;
176
- case 'remove':
177
- setPhase('remove-action');
178
- break;
179
- case 'back':
180
- setSelectedPackage(null);
181
- setPhase('package-list');
182
- break;
183
- }
184
- };
185
- const handleSyncAction = async () => {
186
- if (!selectedPackage || !meta)
187
- return;
188
- const pkgInfo = meta.packages[selectedPackage.prefix];
189
- if (!pkgInfo)
190
- return;
191
- setSyncSteps([
192
- { name: `Syncing ${selectedPackage.originalName}`, status: 'running' },
193
- ]);
194
- try {
195
- await syncPackage(selectedPackage.originalName, {
196
- force: true,
197
- dryRun: false,
198
- local: pkgInfo.local ?? false,
199
- ref: undefined,
200
- flat: undefined,
201
- }, cwd, pkgInfo.exclusions);
202
- setSyncSteps([
203
- { name: `Syncing ${selectedPackage.originalName}`, status: 'success' },
204
- ]);
205
- }
206
- catch (err) {
207
- setSyncSteps([
208
- {
209
- name: `Syncing ${selectedPackage.originalName}`,
210
- status: 'failed',
211
- error: err instanceof Error ? err.message : String(err),
212
- },
213
- ]);
214
- }
215
- setTimeout(() => {
216
- reloadMeta();
217
- setPhase('package-detail');
218
- }, 1000);
219
- };
220
- const handleUpdateActionCheck = async () => {
221
- if (!selectedPackage || !meta)
222
- return;
223
- setUpdateChecking(true);
224
- const pkgInfo = meta.packages[selectedPackage.prefix];
225
- if (!pkgInfo)
226
- return;
227
- const isLocal = pkgInfo.local ?? false;
228
- try {
229
- const currentPkgInfo = isLocal
230
- ? readLocalPackageJson(pkgInfo.originalName, cwd)
231
- : readPackageJson(pkgInfo.originalName, cwd);
232
- if (!currentPkgInfo) {
233
- setUpdateResult({ versionChanged: false, notFound: true });
234
- setUpdateChecking(false);
235
- setTimeout(() => {
236
- reloadMeta();
237
- setPhase('package-detail');
238
- }, 2000);
239
- return;
240
- }
241
- const installedVersion = currentPkgInfo.version;
242
- const syncedVersion = pkgInfo.version;
243
- if (installedVersion === syncedVersion) {
244
- setUpdateResult({
245
- versionChanged: false,
246
- oldVersion: syncedVersion,
247
- newVersion: installedVersion,
248
- });
249
- setUpdateChecking(false);
250
- setTimeout(() => {
251
- reloadMeta();
252
- setPhase('package-detail');
253
- }, 1500);
254
- }
255
- else {
256
- setUpdateResult({
257
- versionChanged: true,
258
- oldVersion: syncedVersion,
259
- newVersion: installedVersion,
260
- });
261
- setUpdateChecking(false);
262
- setUpdateConfirmPending(true);
263
- }
264
- }
265
- catch {
266
- setUpdateResult({ versionChanged: false, notFound: true });
267
- setUpdateChecking(false);
268
- setTimeout(() => {
269
- reloadMeta();
270
- setPhase('package-detail');
271
- }, 2000);
272
- }
273
- };
274
- const handleUpdateConfirm = async (yes) => {
275
- setUpdateConfirmPending(false);
276
- if (!yes) {
277
- reloadMeta();
278
- setPhase('package-detail');
279
- return;
280
- }
281
- if (!selectedPackage || !meta)
282
- return;
283
- setUpdateSyncing(true);
284
- setUpdateSyncSteps([
285
- { name: 'Updating version and syncing files...', status: 'running' },
286
- ]);
287
- try {
288
- await updatePackageVersionAndSync(selectedPackage.prefix, meta, { local: meta.packages[selectedPackage.prefix]?.local, sync: true }, cwd);
289
- setUpdateSyncSteps([
290
- { name: 'Version updated and files synced', status: 'success' },
291
- ]);
292
- }
293
- catch (err) {
294
- setUpdateSyncSteps([
295
- {
296
- name: 'Update version',
297
- status: 'failed',
298
- error: err instanceof Error ? err.message : String(err),
299
- },
300
- ]);
301
- }
302
- setTimeout(() => {
303
- reloadMeta();
304
- setPhase('package-detail');
305
- }, 1000);
306
- };
307
- const handleRemoveConfirm = async (yes) => {
308
- if (!yes) {
309
- setPhase('package-detail');
310
- return;
311
- }
312
- if (!selectedPackage || !meta)
313
- return;
314
- const pkgInfo = meta.packages[selectedPackage.prefix];
315
- if (!pkgInfo)
316
- return;
317
- try {
318
- const filesToDelete = [];
319
- const fileOperations = [];
320
- for (const [assetType, files] of Object.entries(pkgInfo.files)) {
321
- if (!Array.isArray(files))
322
- continue;
323
- const units = files;
324
- for (const unit of units) {
325
- fileOperations.push({
326
- type: 'remove',
327
- prefix: selectedPackage.prefix,
328
- assetType,
329
- skillName: unit.name,
330
- });
331
- }
332
- }
333
- await applyChangesAndSync({ filesToDelete, fileOperations, packagesToSync: [] }, meta, cwd);
334
- const reloaded = reloadMeta();
335
- if (reloaded &&
336
- Object.keys(reloaded.packages).length > 0) {
337
- setSelectedPackage(null);
338
- setPhase('package-list');
339
- }
340
- else {
341
- setPhase('done');
342
- }
343
- }
344
- catch (err) {
345
- setErrorMessage(err instanceof Error ? err.message : 'Failed to remove package');
346
- setPhase('error');
347
- }
348
- };
349
- const handleEditAssetsInit = async () => {
350
- if (!selectedPackage || !meta)
351
- return;
352
- setPhase('edit-assets');
353
- const pkgInfo = meta.packages[selectedPackage.prefix];
354
- if (!pkgInfo)
355
- return;
356
- const prefix = selectedPackage.prefix;
357
- try {
358
- const isLocal = pkgInfo.local ?? true;
359
- let scannedTrees = await scanPackageAssets(pkgInfo.originalName, {
360
- local: isLocal,
361
- ref: undefined,
362
- }).catch(() => null);
363
- if (!scannedTrees && pkgInfo.local === undefined) {
364
- scannedTrees = await scanPackageAssets(pkgInfo.originalName, {
365
- local: !isLocal,
366
- ref: undefined,
367
- }).catch(() => null);
368
- }
369
- let available;
370
- if (scannedTrees) {
371
- available = scannedTrees;
372
- }
373
- else {
374
- available = buildFallbackTrees(prefix, pkgInfo);
375
- }
376
- const excludedFiles = new Set(pkgInfo.exclusions?.files || []);
377
- const metaSelectedFiles = new Set(Object.entries(pkgInfo.files).flatMap(([assetType, files]) => (Array.isArray(files) ? files : [])
378
- .map((unit) => {
379
- const filePath = `${assetType}/${unit.name}`;
380
- if (excludedFiles.has(filePath) ||
381
- excludedFiles.has(unit.name)) {
382
- return null;
383
- }
384
- return filePath;
385
- })
386
- .filter((f) => f !== null)));
387
- const newPackageFiles = {
388
- [prefix]: { available, selected: metaSelectedFiles },
389
- };
390
- setPackageFiles(newPackageFiles);
391
- const trees = buildEditTrees(prefix, pkgInfo, available, metaSelectedFiles);
392
- setEditTrees(trees);
393
- }
394
- catch {
395
- setPhase('package-detail');
396
- }
397
- };
398
- const handleEditAssetsSubmit = async (selectedTrees) => {
399
- if (!meta || !selectedPackage)
400
- return;
401
- const summary = computeFileOperations(meta, packageFiles, selectedTrees, cwd);
402
- if (summary.filesToDelete.length === 0 &&
403
- summary.packagesToSync.length === 0 &&
404
- summary.fileOperations.length === 0) {
405
- setPhase('package-detail');
406
- return;
407
- }
408
- setPhase('sync-action');
409
- setSyncSteps([{ name: 'Applying changes...', status: 'running' }]);
410
- try {
411
- await applyChangesAndSync(summary, meta, cwd, {
412
- onSyncStart: () => {
413
- setSyncSteps([{ name: 'Syncing files...', status: 'running' }]);
414
- },
415
- });
416
- setSyncSteps([{ name: 'Changes applied', status: 'success' }]);
417
- }
418
- catch (err) {
419
- setSyncSteps([
420
- {
421
- name: 'Apply changes',
422
- status: 'failed',
423
- error: err instanceof Error ? err.message : String(err),
424
- },
425
- ]);
426
- }
427
- setTimeout(() => {
428
- reloadMeta();
429
- setPhase('package-detail');
430
- }, 1000);
431
- };
432
- const handleEditAssetsCancel = () => {
433
- setPhase('package-detail');
434
- };
435
- const handleStatusMenuSelect = (item) => {
436
- if (item.value === 'check-remote') {
437
- handleCheckRemoteVersions();
438
- }
439
- else if (item.value === 'back') {
440
- setRemoteVersions(null);
441
- setCheckingRemote(false);
442
- setPhase('main-menu');
443
- }
444
- };
445
- const handleCheckRemoteVersions = async () => {
446
- if (!meta)
447
- return;
448
- setCheckingRemote(true);
449
- try {
450
- const versions = {};
451
- for (const [, pkgInfo] of Object.entries(meta.packages)) {
452
- try {
453
- const res = await fetch(`https://registry.npmjs.org/${pkgInfo.originalName}/latest`);
454
- if (res.ok) {
455
- const data = (await res.json());
456
- versions[pkgInfo.originalName] = data.version;
457
- }
458
- }
459
- catch {
460
- }
461
- }
462
- setRemoteVersions(versions);
463
- }
464
- catch {
465
- }
466
- finally {
467
- setCheckingRemote(false);
468
- }
469
- };
470
- if (phase === 'loading') {
471
- return (jsx(Box, { children: jsxs(Text, { color: "cyan", children: [jsx(Spinner, { type: "dots" }), " Loading synced packages..."] }) }));
472
- }
473
- if (phase === 'error') {
474
- return (jsxs(Box, { flexDirection: "column", children: [jsxs(Text, { color: "red", children: ["Error: ", errorMessage ?? 'Unknown error'] }), jsx(Box, { marginTop: 1, children: jsxs(Text, { dimColor: true, children: ["Press ", jsx(Text, { bold: true, children: "ESC" }), " to exit"] }) })] }));
475
- }
476
- if (phase === 'done') {
477
- if (!meta || Object.keys(meta.packages).length === 0) {
478
- return (jsxs(Box, { flexDirection: "column", children: [jsx(Text, { color: "yellow", children: "No packages synced yet." }), jsx(Text, { dimColor: true, children: "Exiting..." })] }));
479
- }
480
- return null;
481
- }
482
- if (phase === 'main-menu' && meta) {
483
- const packageCount = Object.keys(meta.packages).length;
484
- const menuItems = [
485
- { label: `Packages (${packageCount})`, value: 'packages' },
486
- { label: 'Status', value: 'status' },
487
- { label: 'Exit', value: 'exit' },
488
- ];
489
- return (jsxs(Box, { flexDirection: "column", children: [jsx(SelectInput, { items: menuItems, onSelect: handleMainMenuSelect, itemComponent: MenuItem }), jsx(Box, { marginTop: 1, children: jsxs(Text, { dimColor: true, children: ["Press ", jsx(Text, { bold: true, children: "ESC" }), " to exit"] }) })] }));
490
- }
491
- if (phase === 'package-list' && meta) {
492
- const items = Object.entries(meta.packages).map(([prefix, pkgInfo]) => {
493
- let totalAssets = 0;
494
- for (const files of Object.values(pkgInfo.files)) {
495
- totalAssets += Array.isArray(files) ? files.length : 0;
496
- }
497
- const syncDate = formatSyncDate(meta.syncedAt);
498
- return {
499
- label: `${pkgInfo.originalName}@${pkgInfo.version} \u2022 ${totalAssets} assets \u2022 ${syncDate}`,
500
- value: prefix,
501
- };
502
- });
503
- items.push({ label: '\u2190 Back', value: 'back' });
504
- return (jsxs(Box, { flexDirection: "column", children: [jsx(Box, { marginBottom: 1, children: jsx(Text, { bold: true, children: "Synced Packages" }) }), jsx(SelectInput, { items: items, onSelect: handlePackageSelect, itemComponent: MenuItem }), jsx(Box, { marginTop: 1, children: jsxs(Text, { dimColor: true, children: ["Press ", jsx(Text, { bold: true, children: "ESC" }), " to go back"] }) })] }));
505
- }
506
- if (phase === 'package-detail' && selectedPackage && meta) {
507
- const assetEntries = Object.entries(selectedPackage.files);
508
- const actionItems = [
509
- { label: 'Sync', value: 'sync' },
510
- { label: 'Update Version', value: 'update' },
511
- { label: 'Edit Assets', value: 'edit-assets' },
512
- { label: 'Remove', value: 'remove' },
513
- { label: '\u2190 Back', value: 'back' },
514
- ];
515
- return (jsxs(Box, { flexDirection: "column", children: [jsx(Box, { marginBottom: 1, children: jsxs(Text, { bold: true, children: [selectedPackage.originalName, "@", selectedPackage.version] }) }), jsxs(Box, { flexDirection: "column", marginLeft: 2, marginBottom: 1, children: [jsxs(Text, { children: [jsx(Text, { dimColor: true, children: "Source: " }), jsx(Text, { children: selectedPackage.local ? 'local' : 'remote' })] }), jsxs(Text, { children: [jsx(Text, { dimColor: true, children: "Synced: " }), jsx(Text, { children: formatSyncDate(selectedPackage.syncedAt) })] }), jsxs(Text, { children: [jsx(Text, { dimColor: true, children: "Total: " }), jsxs(Text, { children: [selectedPackage.totalAssets, " assets"] })] }), assetEntries.map(([assetType, files]) => {
516
- const count = Array.isArray(files) ? files.length : 0;
517
- return (jsxs(Text, { children: [jsxs(Text, { dimColor: true, children: [" ", assetType, ": "] }), jsxs(Text, { children: [count, " files"] })] }, assetType));
518
- })] }), jsx(SelectInput, { items: actionItems, onSelect: handleDetailActionSelect, itemComponent: MenuItem }), jsx(Box, { marginTop: 1, children: jsxs(Text, { dimColor: true, children: ["Press ", jsx(Text, { bold: true, children: "ESC" }), " to go back"] }) })] }));
519
- }
520
- if (phase === 'sync-action') {
521
- return (jsxs(Box, { flexDirection: "column", children: [jsx(Box, { marginBottom: 1, children: jsx(Text, { bold: true, children: "Syncing Package" }) }), jsx(StepRunner, { steps: syncSteps, currentStep: 0, total: syncSteps.length })] }));
522
- }
523
- if (phase === 'remove-action' && selectedPackage) {
524
- return (jsx(Box, { flexDirection: "column", children: jsx(Confirm, { message: `Remove ${selectedPackage.originalName}? This will delete all synced files.`, onConfirm: handleRemoveConfirm, defaultYes: false }) }));
525
- }
526
- if (phase === 'update-action') {
527
- if (updateChecking) {
528
- return (jsx(Box, { children: jsxs(Text, { color: "cyan", children: [jsx(Spinner, { type: "dots" }), " Checking installed version..."] }) }));
529
- }
530
- if (updateSyncing) {
531
- return (jsxs(Box, { flexDirection: "column", children: [jsx(Box, { marginBottom: 1, children: jsx(Text, { bold: true, children: "Updating Package" }) }), jsx(StepRunner, { steps: updateSyncSteps, currentStep: 0, total: updateSyncSteps.length })] }));
532
- }
533
- if (updateConfirmPending && updateResult) {
534
- return (jsxs(Box, { flexDirection: "column", children: [jsx(Box, { marginBottom: 1, children: jsxs(Text, { children: [jsx(Text, { dimColor: true, children: "Current sync: " }), jsx(Text, { color: "yellow", children: updateResult.oldVersion }), jsx(Text, { dimColor: true, children: " \u2192 Installed: " }), jsx(Text, { color: "green", children: updateResult.newVersion })] }) }), jsx(Confirm, { message: "Update version and re-sync?", onConfirm: handleUpdateConfirm, defaultYes: true })] }));
535
- }
536
- if (updateResult && !updateResult.versionChanged) {
537
- if (updateResult.notFound) {
538
- return (jsx(Box, { children: jsx(Text, { color: "yellow", children: "Package not found in node_modules or workspace" }) }));
539
- }
540
- return (jsx(Box, { children: jsxs(Text, { color: "green", children: ["Already up to date (version ", updateResult.oldVersion, ")"] }) }));
541
- }
542
- return null;
543
- }
544
- if (phase === 'edit-assets') {
545
- if (editTrees.length === 0) {
546
- return (jsx(Box, { children: jsxs(Text, { color: "cyan", children: [jsx(Spinner, { type: "dots" }), " Loading available assets..."] }) }));
547
- }
548
- return (jsxs(Box, { flexDirection: "column", children: [jsx(Box, { marginBottom: 1, children: jsx(Text, { bold: true, children: "Edit Assets" }) }), jsx(Box, { marginBottom: 1, children: jsx(Text, { dimColor: true, children: "Space: toggle | Enter: save | Esc: cancel" }) }), jsx(TreeSelect, { trees: editTrees, onSubmit: handleEditAssetsSubmit, onCancel: handleEditAssetsCancel })] }));
549
- }
550
- if (phase === 'status-view' && meta) {
551
- const packageEntries = Object.entries(meta.packages);
552
- const statusRows = packageEntries.map(([, pkgInfo]) => {
553
- let totalAssets = 0;
554
- for (const files of Object.values(pkgInfo.files)) {
555
- totalAssets += Array.isArray(files) ? files.length : 0;
556
- }
557
- const remoteVer = remoteVersions?.[pkgInfo.originalName] ?? '-';
558
- return [
559
- pkgInfo.originalName,
560
- pkgInfo.version,
561
- remoteVer,
562
- String(totalAssets),
563
- formatSyncDate(meta.syncedAt),
564
- ];
565
- });
566
- const statusMenuItems = [
567
- { label: 'Check Remote Versions', value: 'check-remote' },
568
- { label: '\u2190 Back', value: 'back' },
569
- ];
570
- return (jsxs(Box, { flexDirection: "column", children: [jsx(Box, { marginBottom: 1, children: jsx(Text, { bold: true, children: "Sync Status" }) }), jsx(Table, { headers: ['Package', 'Local', 'Remote', 'Assets', 'Synced'], rows: statusRows }), checkingRemote && (jsx(Box, { marginTop: 1, children: jsxs(Text, { color: "cyan", children: [jsx(Spinner, { type: "dots" }), " Checking remote versions..."] }) })), jsx(Box, { marginTop: 1, children: jsx(SelectInput, { items: statusMenuItems, onSelect: handleStatusMenuSelect, itemComponent: MenuItem }) }), jsx(Box, { marginTop: 1, children: jsxs(Text, { dimColor: true, children: ["Press ", jsx(Text, { bold: true, children: "ESC" }), " to go back"] }) })] }));
571
- }
572
- return null;
573
- };
574
- function buildFallbackTrees(prefix, packageInfo) {
575
- const assetTypeTrees = [];
576
- for (const [assetType, files] of Object.entries(packageInfo.files)) {
577
- const units = Array.isArray(files) ? files : [];
578
- if (units.length === 0)
579
- continue;
580
- const skillNodes = units.map((unit) => {
581
- const displayName = unit.transformed ?? unit.name;
582
- if (unit.isDirectory) {
583
- return {
584
- id: `${prefix}/${assetType}/${displayName}`,
585
- label: displayName,
586
- path: `${assetType}/${unit.name}`,
587
- type: 'skill-directory',
588
- viewOnly: true,
589
- selected: true,
590
- expanded: false,
591
- children: (unit.internalFiles || []).map((f) => ({
592
- id: `${prefix}/${assetType}/${displayName}/${f}`,
593
- label: f,
594
- path: `${assetType}/${unit.name}/${f}`,
595
- type: 'file',
596
- selected: true,
597
- expanded: false,
598
- disabled: true,
599
- })),
600
- };
601
- }
602
- return {
603
- id: `${prefix}/${assetType}/${displayName}`,
604
- label: displayName,
605
- path: `${assetType}/${unit.name}`,
606
- type: 'file',
607
- selected: true,
608
- expanded: false,
609
- };
610
- });
611
- assetTypeTrees.push({
612
- id: `${prefix}/${assetType}`,
613
- label: assetType,
614
- path: assetType,
615
- type: 'directory',
616
- children: skillNodes,
617
- selected: true,
618
- expanded: true,
619
- });
620
- }
621
- return assetTypeTrees;
622
- }
623
- function buildEditTrees(prefix, packageInfo, available, selectedFiles) {
624
- const assetTypeTrees = available.map((assetTypeTree) => {
625
- const clonedTree = { ...assetTypeTree };
626
- if (clonedTree.children) {
627
- clonedTree.children = clonedTree.children.map((fileNode) => {
628
- const selected = selectedFiles.has(fileNode.path);
629
- return { ...fileNode, selected };
630
- });
631
- const anySelected = clonedTree.children.some((f) => f.selected);
632
- clonedTree.selected = anySelected;
633
- }
634
- return clonedTree;
635
- });
636
- return [
637
- {
638
- id: prefix,
639
- label: `${packageInfo.originalName}@${packageInfo.version}`,
640
- path: packageInfo.originalName,
641
- type: 'directory',
642
- children: assetTypeTrees,
643
- selected: true,
644
- expanded: true,
645
- },
646
- ];
647
- }
648
-
649
- export { ListCommand };
@@ -1,14 +0,0 @@
1
- import React from 'react';
2
- import type { PackageSyncInfo } from '../../utils/types.js';
3
- export interface SyncedPackageTreeProps {
4
- packages: Array<{
5
- prefix: string;
6
- packageInfo: PackageSyncInfo;
7
- }>;
8
- editMode: boolean;
9
- onEdit?: () => void;
10
- }
11
- /**
12
- * Synced package tree component
13
- */
14
- export declare const SyncedPackageTree: React.FC<SyncedPackageTreeProps>;
@@ -1,10 +0,0 @@
1
- /**
2
- * List command components
3
- */
4
- export { EditableTreeItem } from './EditableTreeItem.js';
5
- export { SyncedPackageTree } from './SyncedPackageTree.js';
6
- export { ListCommand } from './ListCommand.js';
7
- export type { EditableTreeItemProps } from './EditableTreeItem.js';
8
- export type { SyncedPackageTreeProps } from './SyncedPackageTree.js';
9
- export type { ListCommandProps } from './ListCommand.js';
10
- export type { ListPhase, SelectItem, PackageDetailInfo } from './types.js';
@@ -1,14 +0,0 @@
1
- export type ListPhase = 'loading' | 'main-menu' | 'package-list' | 'package-detail' | 'sync-action' | 'remove-action' | 'update-action' | 'edit-assets' | 'status-view' | 'confirming' | 'done' | 'error';
2
- export interface SelectItem {
3
- label: string;
4
- value: string;
5
- }
6
- export interface PackageDetailInfo {
7
- prefix: string;
8
- originalName: string;
9
- version: string;
10
- local: boolean;
11
- syncedAt?: string;
12
- files: Record<string, any[]>;
13
- totalAssets: number;
14
- }