@flydocs/cli 0.6.0-alpha.33 → 0.6.0-alpha.35
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/cli.js +124 -75
- package/package.json +1 -1
- package/template/.flydocs/config.json +1 -1
- package/template/.flydocs/version +1 -1
- package/template/manifest.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -15,7 +15,7 @@ var CLI_VERSION, CLI_NAME, PACKAGE_NAME, POSTHOG_API_KEY;
|
|
|
15
15
|
var init_constants = __esm({
|
|
16
16
|
"src/lib/constants.ts"() {
|
|
17
17
|
"use strict";
|
|
18
|
-
CLI_VERSION = "0.6.0-alpha.
|
|
18
|
+
CLI_VERSION = "0.6.0-alpha.35";
|
|
19
19
|
CLI_NAME = "flydocs";
|
|
20
20
|
PACKAGE_NAME = "@flydocs/cli";
|
|
21
21
|
POSTHOG_API_KEY = "phc_v1MSJTQDFkMS90CBh3mxIz3v8bYCCnKU6v1ir6bz0Xn";
|
|
@@ -1328,6 +1328,11 @@ async function scanDeprecated(targetDir) {
|
|
|
1328
1328
|
found.push(item);
|
|
1329
1329
|
}
|
|
1330
1330
|
}
|
|
1331
|
+
for (const file of DEPRECATED_CONTEXT_FILES) {
|
|
1332
|
+
if (await pathExists(join10(targetDir, file))) {
|
|
1333
|
+
found.push(file);
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1331
1336
|
for (const skill of DEPRECATED_SKILLS) {
|
|
1332
1337
|
const p = join10(targetDir, ".claude", "skills", skill);
|
|
1333
1338
|
if (await pathExists(p)) {
|
|
@@ -1413,6 +1418,17 @@ async function checkLegacyFolder(targetDir) {
|
|
|
1413
1418
|
}
|
|
1414
1419
|
return null;
|
|
1415
1420
|
}
|
|
1421
|
+
async function autoCleanup(targetDir, paths) {
|
|
1422
|
+
let cleaned = 0;
|
|
1423
|
+
for (const p of paths) {
|
|
1424
|
+
await rm3(join10(targetDir, p), { recursive: true, force: true });
|
|
1425
|
+
cleaned++;
|
|
1426
|
+
}
|
|
1427
|
+
if (cleaned > 0) {
|
|
1428
|
+
printStatus(`Cleaned ${cleaned} deprecated file(s)`);
|
|
1429
|
+
}
|
|
1430
|
+
return cleaned;
|
|
1431
|
+
}
|
|
1416
1432
|
async function promptCleanup(targetDir, paths) {
|
|
1417
1433
|
if (paths.length === 0) {
|
|
1418
1434
|
printStatus("No deprecated files found");
|
|
@@ -1436,7 +1452,7 @@ async function promptCleanup(targetDir, paths) {
|
|
|
1436
1452
|
printStatus(`Deleted: ${p}`);
|
|
1437
1453
|
}
|
|
1438
1454
|
}
|
|
1439
|
-
var DEPRECATED_DIRS, DEPRECATED_FILES, DEPRECATED_SKILLS, DEPRECATED_RULES_DIR, DEPRECATED_FLYDOCS_DIRS, DEPRECATED_HOOKS, DEPRECATED_CURSOR_RULES, DEPRECATED_CURSOR_RULE_DIRS, DEPRECATED_COMMANDS;
|
|
1455
|
+
var DEPRECATED_DIRS, DEPRECATED_FILES, DEPRECATED_CONTEXT_FILES, DEPRECATED_SKILLS, DEPRECATED_RULES_DIR, DEPRECATED_FLYDOCS_DIRS, DEPRECATED_HOOKS, DEPRECATED_CURSOR_RULES, DEPRECATED_CURSOR_RULE_DIRS, DEPRECATED_COMMANDS;
|
|
1440
1456
|
var init_deprecated = __esm({
|
|
1441
1457
|
"src/lib/deprecated.ts"() {
|
|
1442
1458
|
"use strict";
|
|
@@ -1444,6 +1460,11 @@ var init_deprecated = __esm({
|
|
|
1444
1460
|
init_ui();
|
|
1445
1461
|
DEPRECATED_DIRS = [".docflow", "docflow"];
|
|
1446
1462
|
DEPRECATED_FILES = ["AGENTS.md.bak", ".cursor/mcp.json"];
|
|
1463
|
+
DEPRECATED_CONTEXT_FILES = [
|
|
1464
|
+
"flydocs/context/overview.md",
|
|
1465
|
+
"flydocs/context/stack.md",
|
|
1466
|
+
"flydocs/context/standards.md"
|
|
1467
|
+
];
|
|
1447
1468
|
DEPRECATED_SKILLS = [
|
|
1448
1469
|
"linear-workflow",
|
|
1449
1470
|
"session-workflow",
|
|
@@ -3027,11 +3048,11 @@ async function fetchTemplates(apiKey, sinceVersion, workspaceId) {
|
|
|
3027
3048
|
}
|
|
3028
3049
|
return await response.json();
|
|
3029
3050
|
}
|
|
3030
|
-
async function fetchArtifacts(apiKey, sinceVersion) {
|
|
3051
|
+
async function fetchArtifacts(apiKey, sinceVersion, workspaceId) {
|
|
3031
3052
|
const baseUrl = resolveRelayUrl();
|
|
3032
3053
|
const response = await fetch(`${baseUrl}/artifacts?since=${sinceVersion}`, {
|
|
3033
3054
|
method: "GET",
|
|
3034
|
-
headers: headers(apiKey),
|
|
3055
|
+
headers: headers(apiKey, workspaceId),
|
|
3035
3056
|
signal: AbortSignal.timeout(3e4)
|
|
3036
3057
|
});
|
|
3037
3058
|
if (!response.ok) {
|
|
@@ -3044,23 +3065,6 @@ async function fetchArtifacts(apiKey, sinceVersion) {
|
|
|
3044
3065
|
}
|
|
3045
3066
|
return await response.json();
|
|
3046
3067
|
}
|
|
3047
|
-
async function fetchAgentConfigs(apiKey, workspaceId) {
|
|
3048
|
-
const baseUrl = resolveRelayUrl();
|
|
3049
|
-
const response = await fetch(`${baseUrl}/artifacts/agent-configs`, {
|
|
3050
|
-
method: "GET",
|
|
3051
|
-
headers: headers(apiKey, workspaceId),
|
|
3052
|
-
signal: AbortSignal.timeout(15e3)
|
|
3053
|
-
});
|
|
3054
|
-
if (!response.ok) {
|
|
3055
|
-
const body = await response.text().catch(() => "");
|
|
3056
|
-
throw new RelayError(
|
|
3057
|
-
`agent-configs fetch failed (${response.status})`,
|
|
3058
|
-
response.status,
|
|
3059
|
-
body
|
|
3060
|
-
);
|
|
3061
|
-
}
|
|
3062
|
-
return await response.json();
|
|
3063
|
-
}
|
|
3064
3068
|
async function triggerScan(apiKey, repoName, options) {
|
|
3065
3069
|
const baseUrl = resolveRelayUrl();
|
|
3066
3070
|
const body = {
|
|
@@ -3191,7 +3195,7 @@ function isPathSkipped(artifactPath, skipPaths) {
|
|
|
3191
3195
|
);
|
|
3192
3196
|
}
|
|
3193
3197
|
async function syncArtifacts(targetDir, apiKey, workspaceId, currentVersion, skipPaths = []) {
|
|
3194
|
-
const response = await fetchArtifacts(apiKey, currentVersion);
|
|
3198
|
+
const response = await fetchArtifacts(apiKey, currentVersion, workspaceId);
|
|
3195
3199
|
if (response.artifacts.length === 0) {
|
|
3196
3200
|
return { written: 0, skipped: 0, version: currentVersion };
|
|
3197
3201
|
}
|
|
@@ -3213,23 +3217,6 @@ async function syncArtifacts(targetDir, apiKey, workspaceId, currentVersion, ski
|
|
|
3213
3217
|
}
|
|
3214
3218
|
return { written, skipped, version: response.version };
|
|
3215
3219
|
}
|
|
3216
|
-
async function syncAgentConfigs(targetDir, apiKey, workspaceId, skipPaths = []) {
|
|
3217
|
-
const response = await fetchAgentConfigs(apiKey, workspaceId);
|
|
3218
|
-
let written = 0;
|
|
3219
|
-
for (const file of response.files) {
|
|
3220
|
-
if (skipPaths.length > 0 && isPathSkipped(file.path, skipPaths)) {
|
|
3221
|
-
continue;
|
|
3222
|
-
}
|
|
3223
|
-
const filePath = join19(targetDir, file.path);
|
|
3224
|
-
await mkdir9(dirname3(filePath), { recursive: true });
|
|
3225
|
-
await writeFile11(filePath, file.content, "utf-8");
|
|
3226
|
-
written++;
|
|
3227
|
-
}
|
|
3228
|
-
if (written > 0) {
|
|
3229
|
-
printStatus(`Wrote ${written} agent config(s) (CLAUDE.md, AGENTS.md)`);
|
|
3230
|
-
}
|
|
3231
|
-
return written;
|
|
3232
|
-
}
|
|
3233
3220
|
async function writeArtifact(targetDir, artifact) {
|
|
3234
3221
|
const filePath = join19(targetDir, artifact.path);
|
|
3235
3222
|
await mkdir9(dirname3(filePath), { recursive: true });
|
|
@@ -3271,25 +3258,6 @@ async function syncAllArtifacts(targetDir, apiKey, workspaceId, currentArtifactV
|
|
|
3271
3258
|
printWarning("Artifact sync failed. Will retry on next sync.");
|
|
3272
3259
|
}
|
|
3273
3260
|
}
|
|
3274
|
-
try {
|
|
3275
|
-
const configCount = await syncAgentConfigs(
|
|
3276
|
-
targetDir,
|
|
3277
|
-
apiKey,
|
|
3278
|
-
workspaceId,
|
|
3279
|
-
skipPaths
|
|
3280
|
-
);
|
|
3281
|
-
if (configCount > 0) {
|
|
3282
|
-
changes.push(`Wrote ${configCount} agent config(s)`);
|
|
3283
|
-
}
|
|
3284
|
-
} catch (err) {
|
|
3285
|
-
if (err instanceof RelayError) {
|
|
3286
|
-
printWarning(
|
|
3287
|
-
`Could not fetch agent configs (${err.status}). Will retry on next sync.`
|
|
3288
|
-
);
|
|
3289
|
-
} else {
|
|
3290
|
-
printWarning("Agent config sync failed. Will retry on next sync.");
|
|
3291
|
-
}
|
|
3292
|
-
}
|
|
3293
3261
|
return { artifactVersion, changes };
|
|
3294
3262
|
}
|
|
3295
3263
|
var init_artifacts = __esm({
|
|
@@ -3938,7 +3906,14 @@ __export(init_exports, {
|
|
|
3938
3906
|
default: () => init_default
|
|
3939
3907
|
});
|
|
3940
3908
|
import { defineCommand as defineCommand4 } from "citty";
|
|
3941
|
-
import {
|
|
3909
|
+
import {
|
|
3910
|
+
text as text2,
|
|
3911
|
+
confirm as confirm3,
|
|
3912
|
+
select as select2,
|
|
3913
|
+
multiselect as multiselect2,
|
|
3914
|
+
isCancel as isCancel4,
|
|
3915
|
+
cancel as cancel3
|
|
3916
|
+
} from "@clack/prompts";
|
|
3942
3917
|
import pc9 from "picocolors";
|
|
3943
3918
|
import { join as join24 } from "path";
|
|
3944
3919
|
import { mkdir as mkdir12, writeFile as writeFile16 } from "fs/promises";
|
|
@@ -4309,19 +4284,61 @@ async function isParentDirectory(dir) {
|
|
|
4309
4284
|
}
|
|
4310
4285
|
async function runMultiRepoInit(parentDir, keyArg) {
|
|
4311
4286
|
const repos = await detectSiblingRepos(parentDir);
|
|
4312
|
-
const
|
|
4313
|
-
printInfo(`Detected ${
|
|
4314
|
-
for (const name of repoNames) {
|
|
4315
|
-
console.log(` ${pc9.cyan(name)}`);
|
|
4316
|
-
}
|
|
4287
|
+
const allRepoNames = Object.keys(repos).sort();
|
|
4288
|
+
printInfo(`Detected ${allRepoNames.length} repos:`);
|
|
4317
4289
|
console.log();
|
|
4318
|
-
const
|
|
4319
|
-
|
|
4290
|
+
const existingInstalls = [];
|
|
4291
|
+
for (const name of allRepoNames) {
|
|
4292
|
+
const repoDir = join24(parentDir, name);
|
|
4293
|
+
const hasSkills = await pathExists(join24(repoDir, ".claude", "skills"));
|
|
4294
|
+
const hasConfig = await pathExists(
|
|
4295
|
+
join24(repoDir, ".flydocs", "config.json")
|
|
4296
|
+
);
|
|
4297
|
+
if (hasSkills && hasConfig) {
|
|
4298
|
+
existingInstalls.push(name);
|
|
4299
|
+
}
|
|
4300
|
+
}
|
|
4301
|
+
if (existingInstalls.length > 0) {
|
|
4302
|
+
printWarning(
|
|
4303
|
+
`${existingInstalls.length} repo(s) have existing single-repo FlyDocs installs:`
|
|
4304
|
+
);
|
|
4305
|
+
for (const name of existingInstalls) {
|
|
4306
|
+
console.log(` ${pc9.yellow(name)}`);
|
|
4307
|
+
}
|
|
4308
|
+
console.log();
|
|
4309
|
+
console.log(` Multi-repo init will migrate these to workspace mode:`);
|
|
4310
|
+
console.log(
|
|
4311
|
+
` ${pc9.dim("- IDE configs (skills, hooks, commands) move to workspace root")}`
|
|
4312
|
+
);
|
|
4313
|
+
console.log(
|
|
4314
|
+
` ${pc9.dim("- Per-repo context (project.md, service.json) preserved")}`
|
|
4315
|
+
);
|
|
4316
|
+
console.log(
|
|
4317
|
+
` ${pc9.dim("- Existing IDE configs archived to flydocs/knowledge/archived/")}`
|
|
4318
|
+
);
|
|
4319
|
+
console.log();
|
|
4320
|
+
}
|
|
4321
|
+
const selectedRepos = await multiselect2({
|
|
4322
|
+
message: "Which repos would you like to initialize?",
|
|
4323
|
+
options: allRepoNames.map((name) => ({
|
|
4324
|
+
value: name,
|
|
4325
|
+
label: name,
|
|
4326
|
+
hint: existingInstalls.includes(name) ? "has existing install" : void 0
|
|
4327
|
+
})),
|
|
4328
|
+
initialValues: allRepoNames,
|
|
4329
|
+
required: true
|
|
4320
4330
|
});
|
|
4321
|
-
if (isCancel4(
|
|
4331
|
+
if (isCancel4(selectedRepos)) {
|
|
4322
4332
|
cancel3("Init cancelled.");
|
|
4323
4333
|
process.exit(0);
|
|
4324
4334
|
}
|
|
4335
|
+
const repoNames = selectedRepos;
|
|
4336
|
+
if (repoNames.length === 0) {
|
|
4337
|
+
cancel3("No repos selected.");
|
|
4338
|
+
process.exit(0);
|
|
4339
|
+
}
|
|
4340
|
+
printInfo(`Initializing ${repoNames.length} of ${allRepoNames.length} repos`);
|
|
4341
|
+
console.log();
|
|
4325
4342
|
const firstRepoDir = join24(parentDir, repoNames[0]);
|
|
4326
4343
|
const { apiKey, workspaceId } = await resolveAndValidateKey(
|
|
4327
4344
|
keyArg,
|
|
@@ -4380,9 +4397,13 @@ async function runMultiRepoInit(parentDir, keyArg) {
|
|
|
4380
4397
|
if (existing) {
|
|
4381
4398
|
allSkipped.push(".flydocs-workspace.json (already exists)");
|
|
4382
4399
|
} else {
|
|
4400
|
+
const selectedRepoEntries = {};
|
|
4401
|
+
for (const name of repoNames) {
|
|
4402
|
+
if (repos[name]) selectedRepoEntries[name] = repos[name];
|
|
4403
|
+
}
|
|
4383
4404
|
const workspaceFile = buildWorkspaceFile(
|
|
4384
4405
|
firstResponse.workspaceId,
|
|
4385
|
-
|
|
4406
|
+
selectedRepoEntries
|
|
4386
4407
|
);
|
|
4387
4408
|
await writeWorkspaceFile(parentDir, workspaceFile);
|
|
4388
4409
|
allActions.push(`.flydocs-workspace.json (${repoNames.length} repos)`);
|
|
@@ -4799,7 +4820,10 @@ async function runSync(targetDir) {
|
|
|
4799
4820
|
}
|
|
4800
4821
|
let serverResponse;
|
|
4801
4822
|
try {
|
|
4802
|
-
serverResponse = await fetchConfigV2(apiKey, {
|
|
4823
|
+
serverResponse = await fetchConfigV2(apiKey, {
|
|
4824
|
+
workspaceId,
|
|
4825
|
+
includeContext: true
|
|
4826
|
+
});
|
|
4803
4827
|
} catch (err) {
|
|
4804
4828
|
if (err instanceof RelayError) {
|
|
4805
4829
|
printWarning(`Server unavailable (${err.status}), using cached config.`);
|
|
@@ -4910,6 +4934,33 @@ async function runSync(targetDir) {
|
|
|
4910
4934
|
changes.push(`Deleted ${conflicts.deleted} non-core skill(s)`);
|
|
4911
4935
|
}
|
|
4912
4936
|
}
|
|
4937
|
+
const deprecated = await scanDeprecated(targetDir);
|
|
4938
|
+
if (deprecated.length > 0) {
|
|
4939
|
+
const cleaned = await autoCleanup(targetDir, deprecated);
|
|
4940
|
+
changes.push(`Removed ${cleaned} deprecated file(s)`);
|
|
4941
|
+
}
|
|
4942
|
+
if (serverResponse.context?.projectMd) {
|
|
4943
|
+
const { writeFile: fsWriteFile } = await import("fs/promises");
|
|
4944
|
+
const contextDir = join26(targetDir, "flydocs", "context");
|
|
4945
|
+
await mkdir14(contextDir, { recursive: true });
|
|
4946
|
+
await fsWriteFile(
|
|
4947
|
+
join26(contextDir, "project.md"),
|
|
4948
|
+
serverResponse.context.projectMd,
|
|
4949
|
+
"utf-8"
|
|
4950
|
+
);
|
|
4951
|
+
changes.push("Updated flydocs/context/project.md from server");
|
|
4952
|
+
}
|
|
4953
|
+
if (serverResponse.context?.serviceJson) {
|
|
4954
|
+
const { writeFile: fsWriteFile } = await import("fs/promises");
|
|
4955
|
+
const contextDir = join26(targetDir, "flydocs", "context");
|
|
4956
|
+
await mkdir14(contextDir, { recursive: true });
|
|
4957
|
+
await fsWriteFile(
|
|
4958
|
+
join26(contextDir, "service.json"),
|
|
4959
|
+
JSON.stringify(serverResponse.context.serviceJson, null, 2) + "\n",
|
|
4960
|
+
"utf-8"
|
|
4961
|
+
);
|
|
4962
|
+
changes.push("Updated flydocs/context/service.json from server");
|
|
4963
|
+
}
|
|
4913
4964
|
await migrateGitignore(targetDir);
|
|
4914
4965
|
return changes;
|
|
4915
4966
|
}
|
|
@@ -4938,10 +4989,11 @@ var init_sync = __esm({
|
|
|
4938
4989
|
init_workspace();
|
|
4939
4990
|
init_relay_client();
|
|
4940
4991
|
init_skill_conflicts();
|
|
4992
|
+
init_deprecated();
|
|
4941
4993
|
sync_default = defineCommand5({
|
|
4942
4994
|
meta: {
|
|
4943
4995
|
name: "sync",
|
|
4944
|
-
description: "
|
|
4996
|
+
description: "Sync files from server (alias for update)"
|
|
4945
4997
|
},
|
|
4946
4998
|
args: {
|
|
4947
4999
|
path: {
|
|
@@ -4952,6 +5004,7 @@ var init_sync = __esm({
|
|
|
4952
5004
|
async run({ args }) {
|
|
4953
5005
|
const targetDir = args.path ?? process.cwd();
|
|
4954
5006
|
console.log();
|
|
5007
|
+
printInfo("Note: flydocs sync is now an alias for flydocs update");
|
|
4955
5008
|
const changes = await runSync(targetDir);
|
|
4956
5009
|
if (changes.length === 0) {
|
|
4957
5010
|
printStatus("Already up to date.");
|
|
@@ -5001,7 +5054,7 @@ var init_update = __esm({
|
|
|
5001
5054
|
update_default = defineCommand6({
|
|
5002
5055
|
meta: {
|
|
5003
5056
|
name: "update",
|
|
5004
|
-
description: "Update
|
|
5057
|
+
description: "Update CLI and sync all managed files from server"
|
|
5005
5058
|
},
|
|
5006
5059
|
args: {
|
|
5007
5060
|
path: {
|
|
@@ -5157,10 +5210,6 @@ var init_update = __esm({
|
|
|
5157
5210
|
printStatus(change);
|
|
5158
5211
|
}
|
|
5159
5212
|
}
|
|
5160
|
-
console.log();
|
|
5161
|
-
console.log(
|
|
5162
|
-
` ${pc11.dim("Tip: use")} ${pc11.cyan("flydocs sync")} ${pc11.dim("for file-only refresh (no CLI update).")}`
|
|
5163
|
-
);
|
|
5164
5213
|
await capture("update_completed", {
|
|
5165
5214
|
current_version: currentVersion,
|
|
5166
5215
|
version,
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.6.0-alpha.
|
|
1
|
+
0.6.0-alpha.35
|
package/template/manifest.json
CHANGED