@dadado/agent-kit-cli 5.0.0 → 5.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.
- package/README.md +2 -0
- package/dashboard/dashboard.html +58 -12
- package/dashboard/lib/guards.d.mts +103 -0
- package/dashboard/lib/guards.mjs +56 -2
- package/dashboard/lib/open-browser.mjs +0 -5
- package/dashboard/lib/semantic-model.mjs +7 -1
- package/dashboard/start-broadcast.mjs +4 -3
- package/dashboard/start.mjs +4 -3
- package/dist/index.js +621 -150
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -72,8 +72,11 @@ var KNOWN_SHIPPED_OVERLAY_HASHES = /* @__PURE__ */ new Set([
|
|
|
72
72
|
"004d98f557942677264d053dcd8335f2bbcf19c5591123ec16a7a2697cb88932",
|
|
73
73
|
"05ee6ecde4215e33ace0ee152ffbf2cd885d2bd4b032900f0f0bb001d350ef0f",
|
|
74
74
|
"082bdbc584be3f3d8aa6e9d7b9f4e076450f3ff48f9147a1deb557e31475036b",
|
|
75
|
+
"09850afc201eccb3e700cb934400d49c9cbe7510d4a546ee84ee519771a8200e",
|
|
75
76
|
"0b5fe4729c3c68654434837630d775b847c082418f25b0b2c581700fe84b797a",
|
|
76
77
|
"1106b279558b6a20f87951102f172a680976f3e6530855d5dad083e1f89b9ba3",
|
|
78
|
+
"12bed56b332406477cf546d9e8360d3cab129bd82a638bea356726d00a6847a3",
|
|
79
|
+
"13f6a0711a2fcadcc7f1b751772448517ce4871cdef6a0269fc26dad51ebe26d",
|
|
77
80
|
"15566765ec95dad3bc3160f20ac910e01a13471df536e6d990f4b263700784a9",
|
|
78
81
|
"1681e6cf7b80a67cd999b94b8b6e16eb8caed0e11b32905848ba733da956e902",
|
|
79
82
|
"17818e47e06349ee35c1d8e1cc16e8bcbbbcc89c664014e9096e1f08c8567807",
|
|
@@ -83,6 +86,7 @@ var KNOWN_SHIPPED_OVERLAY_HASHES = /* @__PURE__ */ new Set([
|
|
|
83
86
|
"1c5c1af87951367ad04bb6fa5b1d6ebaaefbc0ee95989b624cabf406a1869907",
|
|
84
87
|
"1ded5c7b7eefc355fc1d17feb65ec472e35ed96076e47ce95f7bff5c1b84746c",
|
|
85
88
|
"1e58e0d4f2e8459b95a40d1b1e72c5c85a87230cbde945840a84073fe3a20422",
|
|
89
|
+
"2280e3ca96129ab2de8a85a301df7c2b15ffaa6204b734ed3b1f303e0055c41d",
|
|
86
90
|
"285668d08f1b15d96286d27e29cc4a67e126e097fb8a940bdde33ccf25bd2bcd",
|
|
87
91
|
"2acdb148b07f3a4872b896da419af796fd3fefaace7ac79cdee0aab447004a83",
|
|
88
92
|
"2cd7fc018a384b0188737259ecf593ce25b4b75cc38b3e410063ac91745894b9",
|
|
@@ -95,6 +99,7 @@ var KNOWN_SHIPPED_OVERLAY_HASHES = /* @__PURE__ */ new Set([
|
|
|
95
99
|
"46a1dd4a07a2190ab9fb09abc05a3962277209f8e0c28033bb41450301474c86",
|
|
96
100
|
"48a0d55e21132a305946b195db7f6b75da78d44a1d32166fb0c69bef4a5ffbe2",
|
|
97
101
|
"4b62a46c74e5fa6a80283f21e8e6711958fbcd577051dc73ff4050643a031475",
|
|
102
|
+
"4ba6e319ac79455a7d2713674f64fabbc9cd401b5d26b1c0edbd19c27a52297e",
|
|
98
103
|
"4bf23acbc9bd4e0f8468e61f4970e182600b72d9025d29e81ddbd83cb7b1710a",
|
|
99
104
|
"4c5167d0ebde685f266dce32c516a7c43876e0520647b93f07f2e2147e6a7b2f",
|
|
100
105
|
"4dc4efcd1b43c643d3889fb349df8d4964d0867c3a67eb67e2ec168fbb70fc75",
|
|
@@ -113,11 +118,16 @@ var KNOWN_SHIPPED_OVERLAY_HASHES = /* @__PURE__ */ new Set([
|
|
|
113
118
|
"6994595e3a62edb6c518006a6bece6848c7077977c041439cf7c822b89304a14",
|
|
114
119
|
"6a42e76fc038ca69ddad18541b8df161770c58980fefaf9e5e80d87407074bec",
|
|
115
120
|
"6a9af9e8a95dbb279347166c43dcee245ca673f9687841086b49911c54944c26",
|
|
121
|
+
"99fdd85310e658a1c1b0e8f92257493409c28c3d693f24deeaa665861788e1e4",
|
|
122
|
+
// public registry SoT n8n-workflows/SKILL.md (em dash description)
|
|
116
123
|
"6b66ed7747ea2d19cb457f5af656e3c07f9f563f7f32b3951fa4ae5f27f0ac46",
|
|
117
124
|
"6dede0588274f5b44d833bcc696ec4776eb978ed24a20efdcc9c38caf3df1576",
|
|
118
125
|
"71991a10972b8b956cae93c88517e31741c95e351814082df65e44f813590210",
|
|
126
|
+
"75ae3018a70ed838428c0e63e8b6901ac05bf1f1cf1845faa6f73c3940d22e4a",
|
|
119
127
|
"75e591bfde61ca1ca3ca1303cc9bc487197af2f713c68f346a46e94ca9432fd5",
|
|
120
128
|
"76ae85bbc336c6f435d9653e8f254ae49774b4ebaecf7335697115933eb8797c",
|
|
129
|
+
"76c4361e70a73276771e841e2c939253b4124d690a0fd25aff2a3ac636d8f4b0",
|
|
130
|
+
// mission-kit-comms/SKILL.md
|
|
121
131
|
"79878f0f6f59d1a0b65d94011c0cafe7b6f8e03e89f568aa638b8ba7a2c34076",
|
|
122
132
|
"8108b202c829627c3c2df33575016ebe942df42acf4f1cc393900be3b82b402c",
|
|
123
133
|
"819b7bd3ba9e8bf12dcd4f81a76c98e48261b34c397f339b36d36eb364d9c3f4",
|
|
@@ -126,6 +136,7 @@ var KNOWN_SHIPPED_OVERLAY_HASHES = /* @__PURE__ */ new Set([
|
|
|
126
136
|
"8a11c80b0fbf6c4aabf60eec05b8cca7dccf5bca472787a8afa3028fd8fbedfa",
|
|
127
137
|
"8b25659727063013e8bf6d7925f815b2630c2919b21e6fdac354362bf122bfab",
|
|
128
138
|
"8c7edbacc74b1431fbecb04c9857c0e7a9cb1578fc6ca6367be888dbcec3c98f",
|
|
139
|
+
"8d8d60e929ebf717eed3c1a29ee0de7c71ae917d125eb1b220a77220597281ed",
|
|
129
140
|
"8ffc181bb152c68a3353309bfdc87c42bdb925b98675cdba959c0cdb90b2adea",
|
|
130
141
|
"91ce0c933e3c8ee81927b8224f944ec5ce5445098a2ad154773092e3541dbf69",
|
|
131
142
|
"9309af07a0a99a56143386b3ddd2a35fae29378fba3f6b4c9297a5d1c02a9724",
|
|
@@ -137,6 +148,7 @@ var KNOWN_SHIPPED_OVERLAY_HASHES = /* @__PURE__ */ new Set([
|
|
|
137
148
|
"9ccf52fe53c6fa4d731650ab4928ce50e201fa34f3e174fee70e3d29867fef2a",
|
|
138
149
|
"9d905aca0123f3018c81c579217104f1749d8da802f3837b2407fbad8f2d803f",
|
|
139
150
|
"9e324c52c1a9d1ceee738bccf47da92910aca9f7a5a21cc41738d9573c414830",
|
|
151
|
+
"9eb457654167df562481637b25ecd91f0ff3c9282ba79409089d644d3b09b926",
|
|
140
152
|
"a013a6a476160183d6457ff6c1c51ec228bdca359b11eb15cd9b7fc177a705db",
|
|
141
153
|
"a08d04f8efa121ad498f96873778c22630c9172c07c216839e348cd0bb7c2292",
|
|
142
154
|
"a7cd7058bcb6fbd962c37317fa16893bc86a270d0164af5a0e6f3f026aa408ad",
|
|
@@ -145,6 +157,8 @@ var KNOWN_SHIPPED_OVERLAY_HASHES = /* @__PURE__ */ new Set([
|
|
|
145
157
|
"b5c7a10df90d209be07159b7ff9bfa24e869538a0b6026bb5ce79e1cdd5b2528",
|
|
146
158
|
"bd9fd1efacbd132c5dafc12cd0cf2b651a2b1fab7b2d7a9ba4a3e44128097f48",
|
|
147
159
|
"be964ff33a40280e13ce6071fb3e30ce87c374527efbb74c25c9d4534084a634",
|
|
160
|
+
"c245035b539e41e822fab8c74fcde3b18c45f4b9f26f1c8583fc9e7254249698",
|
|
161
|
+
"c794accc6668d74a739c982c1b63985a8be4be08afe3766214ab1e08d25ea95c",
|
|
148
162
|
"c96d522be440fbb638dbe953cebf1bb31185c431ac2e14446369cfb7d155a951",
|
|
149
163
|
"cf2bd11891b934484171fa705f470de284e3874402e1e487750735dbc7692857",
|
|
150
164
|
"d0e3bf82efbe32c09761689802ffea7838046dbdd4803b88ead5ec3dfc7efb7e",
|
|
@@ -174,11 +188,15 @@ var KNOWN_SHIPPED_OVERLAY_HASHES = /* @__PURE__ */ new Set([
|
|
|
174
188
|
"f061432a2606049717c0cbf098ef07b1da4df2b136c4cb9cdaa7ea44c876bcd6",
|
|
175
189
|
"f061d36a1180293519fbb560bbf659c621bd90885e995fca6eaf2eda9e418a50",
|
|
176
190
|
"f28731a82f4b394a5765fdefe2d1b667810831f6dcea400ca62bc66e1d65371c",
|
|
191
|
+
"f43a5484e39aca4e6af86e7f8d2941773cdc1c960838ad88ae3540c49a1097df",
|
|
177
192
|
"f46c108457e4fe12953dca75b409e06fca9cb264baffabe0c0d04c89af471e56",
|
|
178
193
|
"f6bc17efa746680a44bbc49be67ac3f924d9c306c6d937f9959c57a1d3c5b9af",
|
|
179
194
|
"f981764422d468567b5aff31148dc659aeee22cb13dc0ecd873d737deaf07372",
|
|
180
195
|
"fa306a0cdb0f40c817e32164cd03b946564a02b4b7f7c3f4f0b9513096584d28",
|
|
181
|
-
"fa5cf460eb314437081f7cea30dc8041c0bd6fc3f560a74bc2d7be1bf07384b0"
|
|
196
|
+
"fa5cf460eb314437081f7cea30dc8041c0bd6fc3f560a74bc2d7be1bf07384b0",
|
|
197
|
+
"fc39ec6d8a22498697f968ffc0fe5f717bed97afd68f922c76a80ed1f10d6579",
|
|
198
|
+
"a8756742197c3a2e1a6d64f4bde2a88db48abb66a0f449d625cd2e1c7b8d0cb4",
|
|
199
|
+
"6a5f8795a4a26b419f167e249576b798781c95308dc1ea50958351de713231d4"
|
|
182
200
|
]);
|
|
183
201
|
|
|
184
202
|
// src/lifecycle/paths.ts
|
|
@@ -572,18 +590,36 @@ async function readLockOwner(lockDir) {
|
|
|
572
590
|
}
|
|
573
591
|
async function writeLockOwner(lockDir, owner) {
|
|
574
592
|
const finalPath = lockOwnerPath(lockDir);
|
|
575
|
-
const tmpPath = path5.join(lockDir, `owner.${owner.uuid}.tmp`);
|
|
593
|
+
const tmpPath = path5.join(lockDir, `owner.${owner.uuid}.${randomUUID()}.tmp`);
|
|
576
594
|
await writeFile3(tmpPath, JSON.stringify(owner), "utf8");
|
|
577
595
|
await rename(tmpPath, finalPath);
|
|
578
596
|
}
|
|
579
597
|
async function refreshLockOwner(lockDir, uuid) {
|
|
580
598
|
const owner = await readLockOwner(lockDir);
|
|
581
|
-
if (
|
|
582
|
-
await writeLockOwner(lockDir, {
|
|
599
|
+
if (owner && owner.uuid !== uuid) return;
|
|
600
|
+
await writeLockOwner(lockDir, { pid: process.pid, uuid, updatedAt: Date.now() });
|
|
583
601
|
}
|
|
584
602
|
async function releaseCacheLock(lockDir, uuid) {
|
|
585
|
-
const
|
|
586
|
-
|
|
603
|
+
const claimPath = path5.join(lockDir, `releasing.${uuid}`);
|
|
604
|
+
try {
|
|
605
|
+
await rename(lockOwnerPath(lockDir), claimPath);
|
|
606
|
+
} catch {
|
|
607
|
+
return;
|
|
608
|
+
}
|
|
609
|
+
let claimed = null;
|
|
610
|
+
try {
|
|
611
|
+
const raw = await readFile4(claimPath, "utf8");
|
|
612
|
+
const parsed = JSON.parse(raw);
|
|
613
|
+
if (typeof parsed.pid === "number" && typeof parsed.uuid === "string") {
|
|
614
|
+
claimed = parsed;
|
|
615
|
+
}
|
|
616
|
+
} catch {
|
|
617
|
+
}
|
|
618
|
+
if (!claimed || claimed.uuid !== uuid) {
|
|
619
|
+
try {
|
|
620
|
+
await rename(claimPath, lockOwnerPath(lockDir));
|
|
621
|
+
} catch {
|
|
622
|
+
}
|
|
587
623
|
return;
|
|
588
624
|
}
|
|
589
625
|
try {
|
|
@@ -622,12 +658,18 @@ async function acquireCacheLock(cacheDir) {
|
|
|
622
658
|
const uuid = randomUUID();
|
|
623
659
|
const owner = { pid: process.pid, uuid, updatedAt: Date.now() };
|
|
624
660
|
await mkdir4(path5.dirname(lockDir), { recursive: true });
|
|
661
|
+
let lastErrorCode;
|
|
625
662
|
while (Date.now() < deadline) {
|
|
626
663
|
try {
|
|
627
664
|
await mkdir4(lockDir, { recursive: false });
|
|
628
665
|
await writeLockOwner(lockDir, owner);
|
|
666
|
+
let refreshing = false;
|
|
629
667
|
const refreshInterval = setInterval(() => {
|
|
668
|
+
if (refreshing) return;
|
|
669
|
+
refreshing = true;
|
|
630
670
|
refreshLockOwner(lockDir, uuid).catch(() => {
|
|
671
|
+
}).finally(() => {
|
|
672
|
+
refreshing = false;
|
|
631
673
|
});
|
|
632
674
|
}, LOCK_REFRESH_MS);
|
|
633
675
|
return async () => {
|
|
@@ -636,6 +678,7 @@ async function acquireCacheLock(cacheDir) {
|
|
|
636
678
|
};
|
|
637
679
|
} catch (err) {
|
|
638
680
|
const code = err.code;
|
|
681
|
+
lastErrorCode = code;
|
|
639
682
|
if (code === "EEXIST") {
|
|
640
683
|
if (await tryReclaimStaleLock(lockDir)) {
|
|
641
684
|
continue;
|
|
@@ -644,12 +687,16 @@ async function acquireCacheLock(cacheDir) {
|
|
|
644
687
|
continue;
|
|
645
688
|
}
|
|
646
689
|
if (code === "ENOENT") {
|
|
690
|
+
await mkdir4(path5.dirname(lockDir), { recursive: true });
|
|
691
|
+
await new Promise((r) => setTimeout(r, LOCK_RETRY_MS + Math.random() * 100));
|
|
647
692
|
continue;
|
|
648
693
|
}
|
|
649
694
|
throw err;
|
|
650
695
|
}
|
|
651
696
|
}
|
|
652
|
-
throw new Error(
|
|
697
|
+
throw new Error(
|
|
698
|
+
lastErrorCode === "ENOENT" ? `Timed out acquiring cache lock on ${cacheDir}: the lock parent directory kept vanishing (concurrent cache clear?).` : `Timed out waiting for cache lock on ${cacheDir}. Another install may be stuck.`
|
|
699
|
+
);
|
|
653
700
|
}
|
|
654
701
|
var DEFAULT_REGISTRY_URL = "https://github.com/agent-kit-startup/agent-kit";
|
|
655
702
|
var DEFAULT_REGISTRY_REF = "main";
|
|
@@ -1835,6 +1882,7 @@ async function resolveInventoryRoot(cwd) {
|
|
|
1835
1882
|
return dir;
|
|
1836
1883
|
} catch {
|
|
1837
1884
|
}
|
|
1885
|
+
if (await fileExists(path10.join(dir, ".git"))) break;
|
|
1838
1886
|
const parent = path10.dirname(dir);
|
|
1839
1887
|
if (parent === dir) break;
|
|
1840
1888
|
dir = parent;
|
|
@@ -2011,12 +2059,16 @@ function baseResult(partial) {
|
|
|
2011
2059
|
};
|
|
2012
2060
|
}
|
|
2013
2061
|
async function checkCursorUpdateAwareness(cwd, options = {}) {
|
|
2014
|
-
const
|
|
2062
|
+
const inventoryRoot = await resolveInventoryRoot(cwd);
|
|
2063
|
+
const prefs = readCursorUpdateCheckPrefs(
|
|
2064
|
+
inventoryRoot ? await loadContextConfig(inventoryRoot) : null
|
|
2065
|
+
);
|
|
2015
2066
|
const changelogUrl = options.changelogUrl ?? prefs.changelogUrl;
|
|
2016
2067
|
if (options.respectPrefs) {
|
|
2017
2068
|
if (!prefs.enabled) {
|
|
2018
2069
|
return baseResult({
|
|
2019
2070
|
status: "skipped-disabled",
|
|
2071
|
+
inventoryRoot,
|
|
2020
2072
|
inventoryPath: INVENTORY_REL,
|
|
2021
2073
|
featuresPath: FEATURES_REL,
|
|
2022
2074
|
changelogUrl,
|
|
@@ -2031,6 +2083,7 @@ async function checkCursorUpdateAwareness(cwd, options = {}) {
|
|
|
2031
2083
|
if (!intervalElapsed(prefs.lastCheckedAt, prefs.intervalDays)) {
|
|
2032
2084
|
return baseResult({
|
|
2033
2085
|
status: "skipped-interval",
|
|
2086
|
+
inventoryRoot,
|
|
2034
2087
|
inventoryPath: INVENTORY_REL,
|
|
2035
2088
|
featuresPath: FEATURES_REL,
|
|
2036
2089
|
changelogUrl,
|
|
@@ -2043,10 +2096,10 @@ async function checkCursorUpdateAwareness(cwd, options = {}) {
|
|
|
2043
2096
|
});
|
|
2044
2097
|
}
|
|
2045
2098
|
}
|
|
2046
|
-
const inventoryRoot = await resolveInventoryRoot(cwd);
|
|
2047
2099
|
if (!inventoryRoot) {
|
|
2048
2100
|
return baseResult({
|
|
2049
2101
|
status: "error",
|
|
2102
|
+
inventoryRoot: null,
|
|
2050
2103
|
inventoryPath: INVENTORY_REL,
|
|
2051
2104
|
featuresPath: FEATURES_REL,
|
|
2052
2105
|
changelogUrl,
|
|
@@ -2066,6 +2119,7 @@ async function checkCursorUpdateAwareness(cwd, options = {}) {
|
|
|
2066
2119
|
} catch {
|
|
2067
2120
|
return baseResult({
|
|
2068
2121
|
status: "error",
|
|
2122
|
+
inventoryRoot,
|
|
2069
2123
|
inventoryPath: INVENTORY_REL,
|
|
2070
2124
|
featuresPath: FEATURES_REL,
|
|
2071
2125
|
changelogUrl,
|
|
@@ -2150,6 +2204,7 @@ async function checkCursorUpdateAwareness(cwd, options = {}) {
|
|
|
2150
2204
|
const msg = err instanceof Error ? err.message : String(err);
|
|
2151
2205
|
return baseResult({
|
|
2152
2206
|
status: "error",
|
|
2207
|
+
inventoryRoot,
|
|
2153
2208
|
inventoryPath: INVENTORY_REL,
|
|
2154
2209
|
featuresPath: FEATURES_REL,
|
|
2155
2210
|
changelogUrl,
|
|
@@ -2162,8 +2217,8 @@ async function checkCursorUpdateAwareness(cwd, options = {}) {
|
|
|
2162
2217
|
});
|
|
2163
2218
|
}
|
|
2164
2219
|
}
|
|
2165
|
-
if (options.stamp) {
|
|
2166
|
-
await stampCursorUpdateCheck(
|
|
2220
|
+
if (options.stamp && inventoryRoot) {
|
|
2221
|
+
await stampCursorUpdateCheck(inventoryRoot, {
|
|
2167
2222
|
lastSeenCursorVersion: latestCursorVersion ?? prefs.lastSeenCursorVersion
|
|
2168
2223
|
});
|
|
2169
2224
|
}
|
|
@@ -2171,6 +2226,7 @@ async function checkCursorUpdateAwareness(cwd, options = {}) {
|
|
|
2171
2226
|
const message = status === "current" ? "No advisory Cursor-update gaps vs inventory (check-only)." : `Found ${gaps.length} advisory gap(s). ${CONVEYOR_HINT}`;
|
|
2172
2227
|
return baseResult({
|
|
2173
2228
|
status,
|
|
2229
|
+
inventoryRoot,
|
|
2174
2230
|
inventoryPath: INVENTORY_REL,
|
|
2175
2231
|
featuresPath: FEATURES_REL,
|
|
2176
2232
|
changelogUrl: options.offline ? null : changelogUrl,
|
|
@@ -2270,7 +2326,7 @@ var KIT_ROOT_ENV_KEYS = Object.freeze(["MISSION_CONTROL_KIT_ROOT", "AGENT_KIT_HO
|
|
|
2270
2326
|
var CONTEXT_CONFIG_REL = ".cursor/context/config.json";
|
|
2271
2327
|
var CONFIG_PERSONA_IDS = Object.freeze(["autopilot", "night-shift", "ghost-runner"]);
|
|
2272
2328
|
var CONFIG_PERSONA_MODES = Object.freeze(["continue-plan", "run-plan", "cli-run-plan"]);
|
|
2273
|
-
var CONFIG_REVIEW_BACKENDS = Object.freeze(["claude"]);
|
|
2329
|
+
var CONFIG_REVIEW_BACKENDS = Object.freeze(["auto", "claude", "cursor"]);
|
|
2274
2330
|
var CONFIG_REVIEW_MODES = Object.freeze(["paste", "autonomous"]);
|
|
2275
2331
|
var CONFIG_REVIEW_PREFLIGHT = Object.freeze(["off", "warn", "block"]);
|
|
2276
2332
|
function resolveContextConfigPath(repoRoot, fsHooks = {}) {
|
|
@@ -2367,6 +2423,14 @@ function applyDashboardOpenEnv(env, opts) {
|
|
|
2367
2423
|
}
|
|
2368
2424
|
return next;
|
|
2369
2425
|
}
|
|
2426
|
+
function dashboardSpawnEnv(env, snapshotRoot, opts) {
|
|
2427
|
+
const root = path11.resolve(snapshotRoot);
|
|
2428
|
+
return applyDashboardOpenEnv({ ...env, MISSION_CONTROL_REPO_ROOT: root }, { ...opts, cwd: root });
|
|
2429
|
+
}
|
|
2430
|
+
function dashboardProcessTitle(snapshotRoot) {
|
|
2431
|
+
const base = path11.basename(path11.resolve(snapshotRoot)) || "workspace";
|
|
2432
|
+
return `Mission Control \xB7 ${base}`;
|
|
2433
|
+
}
|
|
2370
2434
|
function bundledDashboardCandidates(filename, moduleUrl = import.meta.url) {
|
|
2371
2435
|
const here = path11.dirname(fileURLToPath(moduleUrl));
|
|
2372
2436
|
return [
|
|
@@ -2501,10 +2565,11 @@ var dashboardCommand = defineCommand4({
|
|
|
2501
2565
|
process.exitCode = 1;
|
|
2502
2566
|
return;
|
|
2503
2567
|
}
|
|
2504
|
-
const env =
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
);
|
|
2568
|
+
const env = dashboardSpawnEnv({ ...process.env }, snapshotRoot, {
|
|
2569
|
+
noOpen: Boolean(args["no-open"]),
|
|
2570
|
+
browser: args.browser
|
|
2571
|
+
});
|
|
2572
|
+
process.title = dashboardProcessTitle(snapshotRoot);
|
|
2508
2573
|
const code = await runStartScript(startPath, env);
|
|
2509
2574
|
if (code !== 0) process.exitCode = code;
|
|
2510
2575
|
}
|
|
@@ -2601,10 +2666,11 @@ var dashboardBroadcastCommand = defineCommand5({
|
|
|
2601
2666
|
return;
|
|
2602
2667
|
}
|
|
2603
2668
|
const snapshotRoot = resolveDashboardSnapshotRoot(args.cwd);
|
|
2604
|
-
const env =
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
);
|
|
2669
|
+
const env = dashboardSpawnEnv({ ...process.env }, snapshotRoot, {
|
|
2670
|
+
noOpen: Boolean(args["no-open"]),
|
|
2671
|
+
browser: args.browser
|
|
2672
|
+
});
|
|
2673
|
+
process.title = dashboardProcessTitle(snapshotRoot);
|
|
2608
2674
|
const code = await runStartScript2(startPath, env);
|
|
2609
2675
|
if (code !== 0) process.exitCode = code;
|
|
2610
2676
|
}
|
|
@@ -4115,6 +4181,169 @@ async function writeReadinessSnapshot(rootDir, report) {
|
|
|
4115
4181
|
return snapshotPath;
|
|
4116
4182
|
}
|
|
4117
4183
|
|
|
4184
|
+
// src/welcome/visual-kit.ts
|
|
4185
|
+
import { cyan as cyan2, gray, options as koloristOptions } from "kolorist";
|
|
4186
|
+
var HELMET_OUTLINE = "#e2e8f0";
|
|
4187
|
+
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
4188
|
+
var SPACE_MARKS = {
|
|
4189
|
+
star: "\u2726",
|
|
4190
|
+
tick: "\xB7",
|
|
4191
|
+
diamond: "\u2727",
|
|
4192
|
+
visor: "( )"
|
|
4193
|
+
};
|
|
4194
|
+
var KIT_TIPS = [
|
|
4195
|
+
"Try agent-kit doctor for repository readiness.",
|
|
4196
|
+
"HITL gates stay in Cursor slash commands.",
|
|
4197
|
+
"/run-plan never promotes to production.",
|
|
4198
|
+
"Mission Control is the dashboard, not the CLI name.",
|
|
4199
|
+
"NO_COLOR and CI keep this output static.",
|
|
4200
|
+
"agent-kit --help groups SETUP, MISSION, DASHBOARD, INTEGRITY."
|
|
4201
|
+
];
|
|
4202
|
+
function shouldUseWelcomeColor(opts = {}) {
|
|
4203
|
+
if (opts.color === false) return false;
|
|
4204
|
+
if (process.env.NO_COLOR) return false;
|
|
4205
|
+
if (process.env.NODE_DISABLE_COLORS) return false;
|
|
4206
|
+
if (process.env.FORCE_COLOR === "0") return false;
|
|
4207
|
+
if (process.env.CI != null && process.env.CI !== "") return false;
|
|
4208
|
+
if (opts.color === true) return true;
|
|
4209
|
+
const tty = opts.stdoutIsTTY ?? Boolean(process.stdout.isTTY);
|
|
4210
|
+
return tty;
|
|
4211
|
+
}
|
|
4212
|
+
function shouldUseVisualMotion(opts = {}) {
|
|
4213
|
+
if (process.env.AGENT_KIT_REDUCED_MOTION === "1") return false;
|
|
4214
|
+
return shouldUseWelcomeColor(opts);
|
|
4215
|
+
}
|
|
4216
|
+
function spinnerFrame(index) {
|
|
4217
|
+
const n = SPINNER_FRAMES.length;
|
|
4218
|
+
return SPINNER_FRAMES[(index % n + n) % n] ?? SPINNER_FRAMES[0];
|
|
4219
|
+
}
|
|
4220
|
+
function tipAt(index) {
|
|
4221
|
+
const n = KIT_TIPS.length;
|
|
4222
|
+
return KIT_TIPS[(index % n + n) % n] ?? KIT_TIPS[0];
|
|
4223
|
+
}
|
|
4224
|
+
function wrapNarrow(text, columns) {
|
|
4225
|
+
const width = Math.max(8, Number.isFinite(columns) ? Math.floor(columns) : 80);
|
|
4226
|
+
const words = text.trim().split(/\s+/).filter(Boolean);
|
|
4227
|
+
if (words.length === 0) return "";
|
|
4228
|
+
const lines = [];
|
|
4229
|
+
let current = "";
|
|
4230
|
+
for (const word of words) {
|
|
4231
|
+
if (word.length > width) {
|
|
4232
|
+
if (current) {
|
|
4233
|
+
lines.push(current);
|
|
4234
|
+
current = "";
|
|
4235
|
+
}
|
|
4236
|
+
for (let i = 0; i < word.length; i += width) {
|
|
4237
|
+
const chunk = word.slice(i, i + width);
|
|
4238
|
+
if (i + width >= word.length) current = chunk;
|
|
4239
|
+
else lines.push(chunk);
|
|
4240
|
+
}
|
|
4241
|
+
continue;
|
|
4242
|
+
}
|
|
4243
|
+
const next = current ? `${current} ${word}` : word;
|
|
4244
|
+
if (next.length > width) {
|
|
4245
|
+
lines.push(current);
|
|
4246
|
+
current = word;
|
|
4247
|
+
} else {
|
|
4248
|
+
current = next;
|
|
4249
|
+
}
|
|
4250
|
+
}
|
|
4251
|
+
if (current) lines.push(current);
|
|
4252
|
+
return lines.join("\n");
|
|
4253
|
+
}
|
|
4254
|
+
function renderProgressLine(opts) {
|
|
4255
|
+
const motion = opts.motion ?? shouldUseVisualMotion();
|
|
4256
|
+
const color = opts.color ?? shouldUseWelcomeColor();
|
|
4257
|
+
const mark = motion ? spinnerFrame(opts.frameIndex) : SPACE_MARKS.tick;
|
|
4258
|
+
const tip = tipAt(opts.tipIndex);
|
|
4259
|
+
const label = opts.label?.trim() ?? "";
|
|
4260
|
+
const raw = label ? `${mark} ${label} ${SPACE_MARKS.star} ${tip}` : `${mark} ${tip}`;
|
|
4261
|
+
const cols = opts.columns ?? process.stdout.columns ?? 80;
|
|
4262
|
+
const wrapped = wrapNarrow(raw, cols);
|
|
4263
|
+
if (!color) return wrapped;
|
|
4264
|
+
const prevEnabled = koloristOptions.enabled;
|
|
4265
|
+
koloristOptions.enabled = true;
|
|
4266
|
+
try {
|
|
4267
|
+
return wrapped.split("\n").map((line, i) => i === 0 ? cyan2(line) : gray(line)).join("\n");
|
|
4268
|
+
} finally {
|
|
4269
|
+
koloristOptions.enabled = prevEnabled;
|
|
4270
|
+
}
|
|
4271
|
+
}
|
|
4272
|
+
var TtySpinner = class {
|
|
4273
|
+
timer = null;
|
|
4274
|
+
frame = 0;
|
|
4275
|
+
startedAt = 0;
|
|
4276
|
+
label = "";
|
|
4277
|
+
write;
|
|
4278
|
+
columns;
|
|
4279
|
+
motion;
|
|
4280
|
+
color;
|
|
4281
|
+
intervalMs;
|
|
4282
|
+
now;
|
|
4283
|
+
constructor(opts = {}) {
|
|
4284
|
+
this.write = opts.write ?? ((chunk) => process.stdout.write(chunk));
|
|
4285
|
+
this.columns = opts.columns ?? (() => process.stdout.columns ?? 80);
|
|
4286
|
+
this.motion = opts.motion ?? shouldUseVisualMotion();
|
|
4287
|
+
this.color = opts.color ?? shouldUseWelcomeColor();
|
|
4288
|
+
this.intervalMs = opts.intervalMs ?? 80;
|
|
4289
|
+
this.now = opts.now ?? (() => Date.now());
|
|
4290
|
+
}
|
|
4291
|
+
start(label = "") {
|
|
4292
|
+
this.stop();
|
|
4293
|
+
this.label = label;
|
|
4294
|
+
this.frame = 0;
|
|
4295
|
+
this.startedAt = this.now();
|
|
4296
|
+
this.paint(false);
|
|
4297
|
+
if (!this.motion) return;
|
|
4298
|
+
this.timer = setInterval(() => {
|
|
4299
|
+
this.frame += 1;
|
|
4300
|
+
this.paint(true);
|
|
4301
|
+
}, this.intervalMs);
|
|
4302
|
+
this.timer.unref?.();
|
|
4303
|
+
}
|
|
4304
|
+
stop(finalLine) {
|
|
4305
|
+
if (this.timer) {
|
|
4306
|
+
clearInterval(this.timer);
|
|
4307
|
+
this.timer = null;
|
|
4308
|
+
}
|
|
4309
|
+
if (this.motion) this.write("\r\x1B[K");
|
|
4310
|
+
if (finalLine) this.write(`${finalLine}
|
|
4311
|
+
`);
|
|
4312
|
+
}
|
|
4313
|
+
paint(overwrite) {
|
|
4314
|
+
const elapsed = this.now() - this.startedAt;
|
|
4315
|
+
const tipIndex = Math.floor(elapsed / 4e3);
|
|
4316
|
+
const line = renderProgressLine({
|
|
4317
|
+
frameIndex: this.frame,
|
|
4318
|
+
tipIndex,
|
|
4319
|
+
columns: this.columns(),
|
|
4320
|
+
label: this.label,
|
|
4321
|
+
motion: this.motion,
|
|
4322
|
+
color: this.color
|
|
4323
|
+
}).split("\n")[0] ?? "";
|
|
4324
|
+
if (overwrite && this.motion) this.write(`\r\x1B[K${line}`);
|
|
4325
|
+
else if (this.motion) this.write(line);
|
|
4326
|
+
else this.write(`${line}
|
|
4327
|
+
`);
|
|
4328
|
+
}
|
|
4329
|
+
};
|
|
4330
|
+
async function withCliProgress(label, fn, opts) {
|
|
4331
|
+
const motion = opts?.motion ?? shouldUseVisualMotion();
|
|
4332
|
+
if (!motion) {
|
|
4333
|
+
return fn();
|
|
4334
|
+
}
|
|
4335
|
+
const spinner = new TtySpinner({ ...opts, motion: true });
|
|
4336
|
+
spinner.start(label);
|
|
4337
|
+
try {
|
|
4338
|
+
const result = await fn();
|
|
4339
|
+
spinner.stop();
|
|
4340
|
+
return result;
|
|
4341
|
+
} catch (err) {
|
|
4342
|
+
spinner.stop();
|
|
4343
|
+
throw err;
|
|
4344
|
+
}
|
|
4345
|
+
}
|
|
4346
|
+
|
|
4118
4347
|
// src/commands/doctor.ts
|
|
4119
4348
|
async function runDoctor(cwd, options = {}) {
|
|
4120
4349
|
const rootDir = path24.resolve(cwd);
|
|
@@ -4188,7 +4417,8 @@ var doctorCommand = defineCommand7({
|
|
|
4188
4417
|
}
|
|
4189
4418
|
},
|
|
4190
4419
|
async run({ args }) {
|
|
4191
|
-
const
|
|
4420
|
+
const run = () => runDoctor(args.cwd, { fixSafe: args["fix-safe"] });
|
|
4421
|
+
const result = args.json ? await run() : await withCliProgress("doctor", run);
|
|
4192
4422
|
if (args.json) {
|
|
4193
4423
|
console.log(JSON.stringify(result, null, 2));
|
|
4194
4424
|
return;
|
|
@@ -4818,11 +5048,19 @@ async function fileExists2(p) {
|
|
|
4818
5048
|
return false;
|
|
4819
5049
|
}
|
|
4820
5050
|
}
|
|
5051
|
+
function isMarkdownTableSeparator(line) {
|
|
5052
|
+
const stripped = line.trim();
|
|
5053
|
+
if (!stripped.startsWith("|")) return false;
|
|
5054
|
+
const parts = stripped.replace(/^\|/, "").replace(/\|$/, "").split("|").map((cell) => cell.trim());
|
|
5055
|
+
return parts.length > 0 && parts.every((cell) => /^:?-+:?$/.test(cell));
|
|
5056
|
+
}
|
|
4821
5057
|
function parseUnprocessedDogfoodItems(readmeText) {
|
|
4822
5058
|
const items = [];
|
|
4823
5059
|
let inSection = false;
|
|
4824
5060
|
let sectionLevel = 0;
|
|
4825
|
-
|
|
5061
|
+
const lines = readmeText.split(/\r?\n/);
|
|
5062
|
+
for (let i = 0; i < lines.length; i++) {
|
|
5063
|
+
const line = lines[i] ?? "";
|
|
4826
5064
|
const unprocessedMatch = /^(#{2,3})\s+Unprocessed Files\b/.exec(line);
|
|
4827
5065
|
if (unprocessedMatch) {
|
|
4828
5066
|
const hashes = unprocessedMatch[1];
|
|
@@ -4834,11 +5072,14 @@ function parseUnprocessedDogfoodItems(readmeText) {
|
|
|
4834
5072
|
if (!inSection) continue;
|
|
4835
5073
|
const headingMatch = /^(#{1,6})\s+/.exec(line);
|
|
4836
5074
|
if (headingMatch) {
|
|
4837
|
-
if (
|
|
5075
|
+
if (/^#{1,6}\s+Processed(?:\s+Files)?\b/.test(line)) break;
|
|
4838
5076
|
const hashes = headingMatch[1];
|
|
4839
5077
|
if (hashes && hashes.length <= sectionLevel) break;
|
|
4840
5078
|
continue;
|
|
4841
5079
|
}
|
|
5080
|
+
if (line.trim().startsWith("|") && isMarkdownTableSeparator(lines[i + 1] ?? "")) {
|
|
5081
|
+
continue;
|
|
5082
|
+
}
|
|
4842
5083
|
const body = extractUnprocessedDogfoodLine(line);
|
|
4843
5084
|
if (!body) continue;
|
|
4844
5085
|
items.push(body);
|
|
@@ -4856,13 +5097,10 @@ function extractUnprocessedDogfoodLine(line) {
|
|
|
4856
5097
|
if (numbered?.[2]) {
|
|
4857
5098
|
raw = numbered[2].trim();
|
|
4858
5099
|
} else if (stripped.startsWith("|")) {
|
|
5100
|
+
if (isMarkdownTableSeparator(stripped)) return null;
|
|
4859
5101
|
const parts = stripped.replace(/^\|/, "").replace(/\|$/, "").split("|").map((cell) => cell.trim());
|
|
4860
5102
|
if (parts.length === 0) return null;
|
|
4861
|
-
|
|
4862
|
-
const first = parts[0] ?? "";
|
|
4863
|
-
const headerish = first.toLowerCase().replace(/[*_`]/g, "").trim();
|
|
4864
|
-
if (/^(note|file|entrada|title|name|item|path)$/.test(headerish)) return null;
|
|
4865
|
-
raw = first.trim();
|
|
5103
|
+
raw = (parts[0] ?? "").trim();
|
|
4866
5104
|
}
|
|
4867
5105
|
}
|
|
4868
5106
|
if (!raw) return null;
|
|
@@ -5340,16 +5578,83 @@ function classifyInstallError(err) {
|
|
|
5340
5578
|
}
|
|
5341
5579
|
|
|
5342
5580
|
// src/commands/install.ts
|
|
5343
|
-
import
|
|
5581
|
+
import path33 from "path";
|
|
5344
5582
|
import { defineCommand as defineCommand11 } from "citty";
|
|
5345
5583
|
|
|
5346
5584
|
// src/generator/personalization.ts
|
|
5347
|
-
import { readFile as readFile15, writeFile as
|
|
5348
|
-
import
|
|
5585
|
+
import { readFile as readFile15, writeFile as writeFile9 } from "fs/promises";
|
|
5586
|
+
import path31 from "path";
|
|
5349
5587
|
|
|
5350
|
-
// src/generator/
|
|
5588
|
+
// src/generator/claude-kit-load.ts
|
|
5351
5589
|
import { writeFile as writeFile7 } from "fs/promises";
|
|
5352
5590
|
import path29 from "path";
|
|
5591
|
+
var CLAUDE_MD_REL = "CLAUDE.md";
|
|
5592
|
+
var AGENT_KIT_COMMAND_REL = ".claude/commands/agent-kit.md";
|
|
5593
|
+
function renderClaudeMd() {
|
|
5594
|
+
return `# Agent Kit (Claude Code)
|
|
5595
|
+
|
|
5596
|
+
This repository uses Agent Kit / Mission Control. Before rediscovering the tree, read the shared sources of truth (paths below are pointers; do not treat this file as a second rulebook).
|
|
5597
|
+
|
|
5598
|
+
## Read first
|
|
5599
|
+
|
|
5600
|
+
1. \`AGENTS.md\` - cross-IDE contract
|
|
5601
|
+
2. \`.cursor/project-context.md\` - verified repository facts (derived; prefer code, tests, SHAs when docs conflict)
|
|
5602
|
+
3. \`.cursor/HANDOFF.md\` - if present: active plan, next to-do, queue fields
|
|
5603
|
+
4. \`.cursor/commands/\` - slash catalog (Cursor). Follow the same HITL contracts here.
|
|
5604
|
+
|
|
5605
|
+
Mid-session refresh: \`/agent-kit\`.
|
|
5606
|
+
|
|
5607
|
+
## HITL
|
|
5608
|
+
|
|
5609
|
+
Cursor Ask questions is not available in this CLI. When a command requires a choice, list the same labels as a numbered list and wait. Skip or cancel means stop. Never \`/git-prod\` without an explicit operator yes.
|
|
5610
|
+
|
|
5611
|
+
## Non-goals
|
|
5612
|
+
|
|
5613
|
+
- Not Action A7 (Windsurf / VS Code generator parity)
|
|
5614
|
+
- Not Claude external plan-review audits (\`/plan-external-review\`)
|
|
5615
|
+
- Not \`--backend claude\` plan-loop ticks
|
|
5616
|
+
- Not a copy of Cursor \`sessionStart\` / other IDE hooks
|
|
5617
|
+
`;
|
|
5618
|
+
}
|
|
5619
|
+
function renderAgentKitCommand() {
|
|
5620
|
+
return `---
|
|
5621
|
+
description: Load Agent Kit session context (HANDOFF, project-context, commands). Manual refresh only.
|
|
5622
|
+
disable-model-invocation: true
|
|
5623
|
+
---
|
|
5624
|
+
|
|
5625
|
+
Read these files if they exist, then summarize the active plan, next to-do, and any Gaps. Do not scan the whole repository first.
|
|
5626
|
+
|
|
5627
|
+
1. \`AGENTS.md\`
|
|
5628
|
+
2. \`.cursor/project-context.md\`
|
|
5629
|
+
3. \`.cursor/HANDOFF.md\`
|
|
5630
|
+
4. The plan file named in HANDOFF \`- **Plan:**\` under \`.cursor/plans/\`
|
|
5631
|
+
|
|
5632
|
+
If HANDOFF is missing, say so and point at \`/agent-kit-onboard\` or \`/start-project\` rather than inventing a plan.
|
|
5633
|
+
|
|
5634
|
+
HITL: numbered-list fallback for Ask questions labels. Never \`/git-prod\` from this skill.
|
|
5635
|
+
|
|
5636
|
+
Non-goals: not audits / \`/plan-external-review\`, not \`--backend claude\` ticks, not A7, not Cursor hook clones.
|
|
5637
|
+
`;
|
|
5638
|
+
}
|
|
5639
|
+
async function writeUnlessExists(rootDir, relativePath, content) {
|
|
5640
|
+
const target = path29.join(rootDir, relativePath);
|
|
5641
|
+
if (await fileExists(target)) {
|
|
5642
|
+
return { relativePath, status: "skipped-customized" };
|
|
5643
|
+
}
|
|
5644
|
+
await ensureDir(path29.dirname(target));
|
|
5645
|
+
await writeFile7(target, content, "utf8");
|
|
5646
|
+
return { relativePath, status: "applied" };
|
|
5647
|
+
}
|
|
5648
|
+
async function generateClaudeKitLoadArtifacts(rootDir) {
|
|
5649
|
+
return Promise.all([
|
|
5650
|
+
writeUnlessExists(rootDir, CLAUDE_MD_REL, renderClaudeMd()),
|
|
5651
|
+
writeUnlessExists(rootDir, AGENT_KIT_COMMAND_REL, renderAgentKitCommand())
|
|
5652
|
+
]);
|
|
5653
|
+
}
|
|
5654
|
+
|
|
5655
|
+
// src/generator/vscode.ts
|
|
5656
|
+
import { writeFile as writeFile8 } from "fs/promises";
|
|
5657
|
+
import path30 from "path";
|
|
5353
5658
|
|
|
5354
5659
|
// src/generator/platform.ts
|
|
5355
5660
|
function gitProviderLabel(profile) {
|
|
@@ -5373,14 +5678,14 @@ function prTerminology(profile) {
|
|
|
5373
5678
|
// src/generator/vscode.ts
|
|
5374
5679
|
async function generateVSCodeArtifacts(profile) {
|
|
5375
5680
|
const results = [];
|
|
5376
|
-
const vscodeDir =
|
|
5377
|
-
const githubDir =
|
|
5681
|
+
const vscodeDir = path30.join(profile.rootDir, ".vscode");
|
|
5682
|
+
const githubDir = path30.join(profile.rootDir, ".github");
|
|
5378
5683
|
await Promise.all([ensureDir(vscodeDir), ensureDir(githubDir)]);
|
|
5379
|
-
const settingsPath =
|
|
5684
|
+
const settingsPath = path30.join(vscodeDir, "settings.json");
|
|
5380
5685
|
if (await fileExists(settingsPath)) {
|
|
5381
5686
|
results.push({ relativePath: ".vscode/settings.json", status: "skipped-customized" });
|
|
5382
5687
|
} else {
|
|
5383
|
-
await
|
|
5688
|
+
await writeFile8(
|
|
5384
5689
|
settingsPath,
|
|
5385
5690
|
`${JSON.stringify(
|
|
5386
5691
|
{
|
|
@@ -5400,11 +5705,11 @@ async function generateVSCodeArtifacts(profile) {
|
|
|
5400
5705
|
}
|
|
5401
5706
|
const provider = gitProviderLabel(profile);
|
|
5402
5707
|
const prTerm = prTerminology(profile);
|
|
5403
|
-
const copilotPath =
|
|
5708
|
+
const copilotPath = path30.join(githubDir, "copilot-instructions.md");
|
|
5404
5709
|
if (await fileExists(copilotPath)) {
|
|
5405
5710
|
results.push({ relativePath: ".github/copilot-instructions.md", status: "skipped-customized" });
|
|
5406
5711
|
} else {
|
|
5407
|
-
await
|
|
5712
|
+
await writeFile8(
|
|
5408
5713
|
copilotPath,
|
|
5409
5714
|
`# Copilot Instructions
|
|
5410
5715
|
|
|
@@ -5418,14 +5723,14 @@ async function generateVSCodeArtifacts(profile) {
|
|
|
5418
5723
|
results.push({ relativePath: ".github/copilot-instructions.md", status: "applied" });
|
|
5419
5724
|
}
|
|
5420
5725
|
if (profile.ide.plan === "vscode-pro") {
|
|
5421
|
-
const securityPath =
|
|
5726
|
+
const securityPath = path30.join(vscodeDir, "security-review.agent.md");
|
|
5422
5727
|
if (await fileExists(securityPath)) {
|
|
5423
5728
|
results.push({
|
|
5424
5729
|
relativePath: ".vscode/security-review.agent.md",
|
|
5425
5730
|
status: "skipped-customized"
|
|
5426
5731
|
});
|
|
5427
5732
|
} else {
|
|
5428
|
-
await
|
|
5733
|
+
await writeFile8(
|
|
5429
5734
|
securityPath,
|
|
5430
5735
|
"# Security Review Agent\n\nSpecialized mode for security review.\n",
|
|
5431
5736
|
"utf8"
|
|
@@ -5561,7 +5866,40 @@ function buildPersonalizationPlan(profile, report, registry) {
|
|
|
5561
5866
|
(item) => componentAvailable(registry, item) ? item : { ...item, status: "unavailable" }
|
|
5562
5867
|
).sort((left, right) => `${left.kind}:${left.id}`.localeCompare(`${right.kind}:${right.id}`));
|
|
5563
5868
|
}
|
|
5564
|
-
|
|
5869
|
+
var INSTALLED_SKILL_STATUSES = /* @__PURE__ */ new Set(["applied", "skipped-customized"]);
|
|
5870
|
+
function installedSkillItems(items, installedIds = []) {
|
|
5871
|
+
const rows = [];
|
|
5872
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5873
|
+
for (const item of items) {
|
|
5874
|
+
if (item.kind !== "skill" || !INSTALLED_SKILL_STATUSES.has(item.status)) continue;
|
|
5875
|
+
if (seen.has(item.id)) continue;
|
|
5876
|
+
seen.add(item.id);
|
|
5877
|
+
rows.push(item);
|
|
5878
|
+
}
|
|
5879
|
+
for (const id of installedIds) {
|
|
5880
|
+
if (seen.has(id)) continue;
|
|
5881
|
+
seen.add(id);
|
|
5882
|
+
rows.push({
|
|
5883
|
+
kind: "skill",
|
|
5884
|
+
id,
|
|
5885
|
+
status: "applied",
|
|
5886
|
+
evidence: [{ source: "configuration", value: `.cursor/agent-kit.json skills[]:${id}` }]
|
|
5887
|
+
});
|
|
5888
|
+
}
|
|
5889
|
+
return rows.sort((left, right) => left.id.localeCompare(right.id));
|
|
5890
|
+
}
|
|
5891
|
+
function relevantSkillTableRows(skills) {
|
|
5892
|
+
if (skills.length === 0) {
|
|
5893
|
+
return ["| (none yet) | No installed or project-owned skills detected | \u2014 |"];
|
|
5894
|
+
}
|
|
5895
|
+
return skills.map((skill) => {
|
|
5896
|
+
const label = skill.path ?? skill.id;
|
|
5897
|
+
const role = skill.status === "skipped-customized" ? "Already present (customized)" : "Installed by personalization";
|
|
5898
|
+
const evidence = skill.path ?? skill.evidence[0]?.value ?? "personalization";
|
|
5899
|
+
return `| ${label} | ${role} | ${evidence} |`;
|
|
5900
|
+
});
|
|
5901
|
+
}
|
|
5902
|
+
function renderProjectContext(profile, skillItems = []) {
|
|
5565
5903
|
const sections = ["# Project Context", "", "Verified repository facts:"];
|
|
5566
5904
|
const purpose = purposeEvidence(profile);
|
|
5567
5905
|
if (purpose.length > 0 && profile.purpose.value !== "unknown") {
|
|
@@ -5588,7 +5926,7 @@ function renderProjectContext(profile) {
|
|
|
5588
5926
|
"",
|
|
5589
5927
|
"| Skill / path | Role | Evidence |",
|
|
5590
5928
|
"|--------------|------|----------|",
|
|
5591
|
-
|
|
5929
|
+
...relevantSkillTableRows(installedSkillItems(skillItems))
|
|
5592
5930
|
);
|
|
5593
5931
|
if (profile.context.sources.length > 0) {
|
|
5594
5932
|
sections.push("", "## Sources", ...profile.context.sources.map((item) => `- ${item.value}`));
|
|
@@ -5597,7 +5935,7 @@ function renderProjectContext(profile) {
|
|
|
5597
5935
|
`;
|
|
5598
5936
|
}
|
|
5599
5937
|
async function createOwnedFile(rootDir, relativePath, content, evidence) {
|
|
5600
|
-
const target =
|
|
5938
|
+
const target = path31.join(rootDir, relativePath);
|
|
5601
5939
|
if (await fileExists(target)) {
|
|
5602
5940
|
return {
|
|
5603
5941
|
kind: "file",
|
|
@@ -5607,8 +5945,8 @@ async function createOwnedFile(rootDir, relativePath, content, evidence) {
|
|
|
5607
5945
|
evidence
|
|
5608
5946
|
};
|
|
5609
5947
|
}
|
|
5610
|
-
await ensureDir(
|
|
5611
|
-
await
|
|
5948
|
+
await ensureDir(path31.dirname(target));
|
|
5949
|
+
await writeFile9(target, content, "utf8");
|
|
5612
5950
|
return {
|
|
5613
5951
|
kind: "file",
|
|
5614
5952
|
id: relativePath,
|
|
@@ -5624,7 +5962,7 @@ async function packTargets(registryRoot, packId) {
|
|
|
5624
5962
|
async function existingTargets(projectRoot, targets) {
|
|
5625
5963
|
const checks = await Promise.all(
|
|
5626
5964
|
targets.map(
|
|
5627
|
-
async (target) => await fileExists(
|
|
5965
|
+
async (target) => await fileExists(path31.join(projectRoot, target)) ? target : null
|
|
5628
5966
|
)
|
|
5629
5967
|
);
|
|
5630
5968
|
return checks.filter((target) => target !== null);
|
|
@@ -5646,14 +5984,14 @@ async function applyPersonalization(input) {
|
|
|
5646
5984
|
componentResults.push({ ...item, status: "unavailable" });
|
|
5647
5985
|
continue;
|
|
5648
5986
|
}
|
|
5649
|
-
const target =
|
|
5987
|
+
const target = path31.posix.join(
|
|
5650
5988
|
".cursor",
|
|
5651
5989
|
"skills",
|
|
5652
5990
|
skill.path.includes("/core/") ? "core" : "community",
|
|
5653
5991
|
skill.id,
|
|
5654
5992
|
"SKILL.md"
|
|
5655
5993
|
);
|
|
5656
|
-
if (await fileExists(
|
|
5994
|
+
if (await fileExists(path31.join(input.rootDir, target))) {
|
|
5657
5995
|
componentResults.push({ ...item, status: "skipped-customized", path: target });
|
|
5658
5996
|
protectedPaths.add(target);
|
|
5659
5997
|
continue;
|
|
@@ -5689,7 +6027,7 @@ async function applyPersonalization(input) {
|
|
|
5689
6027
|
createOwnedFile(
|
|
5690
6028
|
input.rootDir,
|
|
5691
6029
|
CONTEXT_PATH,
|
|
5692
|
-
renderProjectContext(input.profile),
|
|
6030
|
+
renderProjectContext(input.profile, installedSkillItems(componentResults, skills)),
|
|
5693
6031
|
profileEvidence
|
|
5694
6032
|
),
|
|
5695
6033
|
createOwnedFile(
|
|
@@ -5701,6 +6039,17 @@ async function applyPersonalization(input) {
|
|
|
5701
6039
|
]);
|
|
5702
6040
|
protectedPaths.add(CONTEXT_PATH);
|
|
5703
6041
|
protectedPaths.add(AGENTS_PATH);
|
|
6042
|
+
const claudeResults = await generateClaudeKitLoadArtifacts(input.rootDir);
|
|
6043
|
+
const claudeItems = claudeResults.map((artifact) => {
|
|
6044
|
+
protectedPaths.add(artifact.relativePath);
|
|
6045
|
+
return {
|
|
6046
|
+
kind: "file",
|
|
6047
|
+
id: artifact.relativePath,
|
|
6048
|
+
path: artifact.relativePath,
|
|
6049
|
+
status: artifact.status,
|
|
6050
|
+
evidence: profileEvidence
|
|
6051
|
+
};
|
|
6052
|
+
});
|
|
5704
6053
|
const ideDetection = await detectIde(input.rootDir);
|
|
5705
6054
|
if (ideDetection.ide === "vscode" || ideDetection.ide === "other") {
|
|
5706
6055
|
const git = {
|
|
@@ -5748,10 +6097,10 @@ async function applyPersonalization(input) {
|
|
|
5748
6097
|
contractVersion: PERSONALIZATION_CONTRACT_VERSION,
|
|
5749
6098
|
generatorVersion: input.generatorVersion,
|
|
5750
6099
|
repositoryFingerprint: input.report.repositoryFingerprint,
|
|
5751
|
-
items: [...fileResults, ...componentResults],
|
|
6100
|
+
items: [...fileResults, ...claudeItems, ...componentResults],
|
|
5752
6101
|
protectedPaths: [...protectedPaths].sort()
|
|
5753
6102
|
};
|
|
5754
|
-
await writeJson(
|
|
6103
|
+
await writeJson(path31.join(input.rootDir, RESULT_PATH), result);
|
|
5755
6104
|
return {
|
|
5756
6105
|
result,
|
|
5757
6106
|
manifest: {
|
|
@@ -5769,7 +6118,7 @@ async function applyPersonalization(input) {
|
|
|
5769
6118
|
};
|
|
5770
6119
|
}
|
|
5771
6120
|
async function readRepositoryProfile(rootDir) {
|
|
5772
|
-
const target =
|
|
6121
|
+
const target = path31.join(rootDir, ".cursor/agent-kit.config.json");
|
|
5773
6122
|
if (!await fileExists(target)) return null;
|
|
5774
6123
|
return JSON.parse(await readFile15(target, "utf8"));
|
|
5775
6124
|
}
|
|
@@ -5777,16 +6126,16 @@ async function readRepositoryProfile(rootDir) {
|
|
|
5777
6126
|
// src/lifecycle/onboard-migration.ts
|
|
5778
6127
|
import { createHash as createHash4 } from "crypto";
|
|
5779
6128
|
import { readFile as readFile16, unlink } from "fs/promises";
|
|
5780
|
-
import
|
|
6129
|
+
import path32 from "path";
|
|
5781
6130
|
var LEGACY_ONBOARD_PATH = ".cursor/commands/onboard.md";
|
|
5782
6131
|
var NAMESPACED_ONBOARD_PATH = ".cursor/commands/agent-kit-onboard.md";
|
|
5783
6132
|
var MANAGED_LEGACY_HASHES = /* @__PURE__ */ new Set([
|
|
5784
6133
|
"b274a68941813f19b185893cb7c5561dff027f53270890029992f208e24992fe"
|
|
5785
6134
|
]);
|
|
5786
6135
|
async function migrateLegacyOnboardCommand(projectRoot, managedHashes = MANAGED_LEGACY_HASHES) {
|
|
5787
|
-
const legacyPath =
|
|
6136
|
+
const legacyPath = path32.join(projectRoot, LEGACY_ONBOARD_PATH);
|
|
5788
6137
|
if (!await fileExists(legacyPath)) return "absent";
|
|
5789
|
-
const namespacedPath =
|
|
6138
|
+
const namespacedPath = path32.join(projectRoot, NAMESPACED_ONBOARD_PATH);
|
|
5790
6139
|
if (!await fileExists(namespacedPath)) return "preserved-customized";
|
|
5791
6140
|
const content = await readFile16(legacyPath);
|
|
5792
6141
|
const hash = createHash4("sha256").update(content).digest("hex");
|
|
@@ -5861,7 +6210,7 @@ function printReadinessNarrative(result) {
|
|
|
5861
6210
|
);
|
|
5862
6211
|
}
|
|
5863
6212
|
async function performInstall(options) {
|
|
5864
|
-
const projectRoot =
|
|
6213
|
+
const projectRoot = path33.resolve(options.cwd);
|
|
5865
6214
|
const packs = parsePackList(options.pack);
|
|
5866
6215
|
const existing = await loadAgentKitManifest(projectRoot);
|
|
5867
6216
|
const registry = await resolveRegistryFromCli({
|
|
@@ -5979,15 +6328,18 @@ var installCommand = defineCommand11({
|
|
|
5979
6328
|
}
|
|
5980
6329
|
}
|
|
5981
6330
|
try {
|
|
5982
|
-
const result = await
|
|
5983
|
-
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
|
|
6331
|
+
const result = await withCliProgress(
|
|
6332
|
+
"install",
|
|
6333
|
+
() => performInstall({
|
|
6334
|
+
cwd: projectRoot,
|
|
6335
|
+
profile: args.profile,
|
|
6336
|
+
pack: args.pack,
|
|
6337
|
+
registry: args.registry,
|
|
6338
|
+
url: args.url,
|
|
6339
|
+
ref: args.ref,
|
|
6340
|
+
refresh: args.refresh
|
|
6341
|
+
})
|
|
6342
|
+
);
|
|
5991
6343
|
logApplyStats(result.stats);
|
|
5992
6344
|
logger.success(`Manifest written: ${result.manifestPath}`);
|
|
5993
6345
|
logger.success("Readiness snapshot written: .cursor/context/readiness.json");
|
|
@@ -5998,7 +6350,8 @@ var installCommand = defineCommand11({
|
|
|
5998
6350
|
console.error(`
|
|
5999
6351
|
${hint.recovery}
|
|
6000
6352
|
`);
|
|
6001
|
-
process.
|
|
6353
|
+
process.exitCode = 1;
|
|
6354
|
+
return;
|
|
6002
6355
|
}
|
|
6003
6356
|
}
|
|
6004
6357
|
});
|
|
@@ -6028,7 +6381,7 @@ var initCommand = defineCommand12({
|
|
|
6028
6381
|
}
|
|
6029
6382
|
logger.info("init now uses the canonical install and readiness workflow.");
|
|
6030
6383
|
try {
|
|
6031
|
-
const result = await runInitCompatibility(args.cwd);
|
|
6384
|
+
const result = await withCliProgress("init", () => runInitCompatibility(args.cwd));
|
|
6032
6385
|
const pending = result.readiness.pendingActions.length;
|
|
6033
6386
|
logger.success(`L0 and readiness prepared in ${result.projectRoot}`);
|
|
6034
6387
|
const nextStep = pending > 0 ? "Next: run /agent-kit-onboard in Cursor to resolve the first pending action." : "Next: run /start-project in Cursor when you have a deliverable.";
|
|
@@ -6049,13 +6402,13 @@ ${hint.recovery}
|
|
|
6049
6402
|
});
|
|
6050
6403
|
|
|
6051
6404
|
// src/commands/monitors.ts
|
|
6052
|
-
import
|
|
6405
|
+
import path35 from "path";
|
|
6053
6406
|
import { defineCommand as defineCommand13 } from "citty";
|
|
6054
6407
|
|
|
6055
6408
|
// src/invariants/monitors-untriaged.ts
|
|
6056
6409
|
import { execFile as execFile5 } from "child_process";
|
|
6057
6410
|
import { readFile as readFile17, readdir as readdir5, stat as stat3 } from "fs/promises";
|
|
6058
|
-
import
|
|
6411
|
+
import path34 from "path";
|
|
6059
6412
|
import { promisify as promisify5 } from "util";
|
|
6060
6413
|
|
|
6061
6414
|
// src/invariants/triage-heading.ts
|
|
@@ -6096,7 +6449,7 @@ async function gitFreshMonitorNames(rootDir) {
|
|
|
6096
6449
|
for (const line of stdout.split("\n")) {
|
|
6097
6450
|
if (!line.trim()) continue;
|
|
6098
6451
|
const file = line.slice(3).trim().replace(/^.* -> /, "");
|
|
6099
|
-
const base =
|
|
6452
|
+
const base = path34.basename(file);
|
|
6100
6453
|
if (base.startsWith("plan-monitor-") && base.endsWith(".md")) {
|
|
6101
6454
|
names.add(base);
|
|
6102
6455
|
}
|
|
@@ -6119,13 +6472,13 @@ function monitorSlugFromName(fileName) {
|
|
|
6119
6472
|
return fileName.replace(/^plan-monitor-/, "").replace(/\.md$/, "").toLowerCase();
|
|
6120
6473
|
}
|
|
6121
6474
|
async function selectUntriagedMonitors(rootDir) {
|
|
6122
|
-
const root =
|
|
6123
|
-
const memoryDir =
|
|
6475
|
+
const root = path34.resolve(rootDir);
|
|
6476
|
+
const memoryDir = path34.join(root, ".cursor", "memory");
|
|
6124
6477
|
const allNames = await listMonitorFiles(memoryDir);
|
|
6125
6478
|
const selectionOrder = ["git-fresh", "handoff-aligned", "untriaged-scan"];
|
|
6126
6479
|
const byName = /* @__PURE__ */ new Map();
|
|
6127
6480
|
for (const name of allNames) {
|
|
6128
|
-
const abs =
|
|
6481
|
+
const abs = path34.join(memoryDir, name);
|
|
6129
6482
|
try {
|
|
6130
6483
|
const [content, st] = await Promise.all([readFile17(abs, "utf8"), stat3(abs)]);
|
|
6131
6484
|
byName.set(name, { content, mtimeMs: st.mtimeMs });
|
|
@@ -6140,7 +6493,7 @@ async function selectUntriagedMonitors(rootDir) {
|
|
|
6140
6493
|
const gitFreshSet = [...gitFresh].filter(untriaged).sort();
|
|
6141
6494
|
let handoff = "";
|
|
6142
6495
|
try {
|
|
6143
|
-
handoff = await readFile17(
|
|
6496
|
+
handoff = await readFile17(path34.join(root, ".cursor", "HANDOFF.md"), "utf8");
|
|
6144
6497
|
} catch {
|
|
6145
6498
|
handoff = "";
|
|
6146
6499
|
}
|
|
@@ -6160,8 +6513,8 @@ async function selectUntriagedMonitors(rootDir) {
|
|
|
6160
6513
|
const row = byName.get(name);
|
|
6161
6514
|
if (!row) continue;
|
|
6162
6515
|
entries.push({
|
|
6163
|
-
path:
|
|
6164
|
-
relativePath:
|
|
6516
|
+
path: path34.join(memoryDir, name),
|
|
6517
|
+
relativePath: path34.relative(root, path34.join(memoryDir, name)).split(path34.sep).join("/"),
|
|
6165
6518
|
mtimeMs: row.mtimeMs,
|
|
6166
6519
|
hasTriageHeading: false,
|
|
6167
6520
|
hasOpenGaps: hasOpenGaps(row.content),
|
|
@@ -6207,7 +6560,7 @@ var monitorsCommand = defineCommand13({
|
|
|
6207
6560
|
process.exitCode = 2;
|
|
6208
6561
|
return;
|
|
6209
6562
|
}
|
|
6210
|
-
const result = await selectUntriagedMonitors(
|
|
6563
|
+
const result = await selectUntriagedMonitors(path35.resolve(args.cwd));
|
|
6211
6564
|
if (args.json) {
|
|
6212
6565
|
console.log(JSON.stringify(result, null, 2));
|
|
6213
6566
|
return;
|
|
@@ -6223,7 +6576,7 @@ var monitorsCommand = defineCommand13({
|
|
|
6223
6576
|
});
|
|
6224
6577
|
|
|
6225
6578
|
// src/commands/run-plan.ts
|
|
6226
|
-
import
|
|
6579
|
+
import path40 from "path";
|
|
6227
6580
|
import { defineCommand as defineCommand14 } from "citty";
|
|
6228
6581
|
|
|
6229
6582
|
// src/plan-loop/backends.ts
|
|
@@ -6309,13 +6662,13 @@ function listBackendIds() {
|
|
|
6309
6662
|
|
|
6310
6663
|
// src/plan-loop/run-loop.ts
|
|
6311
6664
|
import { mkdir as mkdir6, readFile as readFile20, rm as rm2, unlink as unlink2 } from "fs/promises";
|
|
6312
|
-
import
|
|
6665
|
+
import path39 from "path";
|
|
6313
6666
|
|
|
6314
6667
|
// src/plan-loop/external-review.ts
|
|
6315
6668
|
import { spawn as spawn7 } from "child_process";
|
|
6316
|
-
import
|
|
6317
|
-
var CANONICAL_REL =
|
|
6318
|
-
var FALLBACK_REL =
|
|
6669
|
+
import path36 from "path";
|
|
6670
|
+
var CANONICAL_REL = path36.join(".cursor", "scripts", "plan-external-review.sh");
|
|
6671
|
+
var FALLBACK_REL = path36.join("scripts", "plan-external-review.sh");
|
|
6319
6672
|
function isPlanExhaustedReason(reason) {
|
|
6320
6673
|
const r = reason.trim().toLowerCase();
|
|
6321
6674
|
if (!r) return false;
|
|
@@ -6337,8 +6690,8 @@ async function armExternalPlanReview(root, options = {}) {
|
|
|
6337
6690
|
const existsFn = options.existsFn ?? fileExists;
|
|
6338
6691
|
const log = options.log ?? ((line) => console.log(line));
|
|
6339
6692
|
const force = options.force === true;
|
|
6340
|
-
const canonicalPath =
|
|
6341
|
-
const fallbackPath =
|
|
6693
|
+
const canonicalPath = path36.join(root, CANONICAL_REL);
|
|
6694
|
+
const fallbackPath = path36.join(root, FALLBACK_REL);
|
|
6342
6695
|
let scriptPath = null;
|
|
6343
6696
|
let scriptRel = CANONICAL_REL;
|
|
6344
6697
|
if (await existsFn(canonicalPath)) {
|
|
@@ -6391,11 +6744,11 @@ async function armExternalPlanReview(root, options = {}) {
|
|
|
6391
6744
|
}
|
|
6392
6745
|
|
|
6393
6746
|
// src/plan-loop/persona-banners.ts
|
|
6394
|
-
import
|
|
6747
|
+
import path37 from "path";
|
|
6395
6748
|
import {
|
|
6396
6749
|
blue,
|
|
6397
|
-
cyan as
|
|
6398
|
-
gray,
|
|
6750
|
+
cyan as cyan3,
|
|
6751
|
+
gray as gray2,
|
|
6399
6752
|
green as green2,
|
|
6400
6753
|
lightGray,
|
|
6401
6754
|
lightGreen,
|
|
@@ -6408,9 +6761,9 @@ var CLI_RUN_PLAN_MODE = "cli-run-plan";
|
|
|
6408
6761
|
var DEFAULT_CLI_PERSONA_ID = "ghost-runner";
|
|
6409
6762
|
var COLORS = {
|
|
6410
6763
|
white,
|
|
6411
|
-
gray,
|
|
6764
|
+
gray: gray2,
|
|
6412
6765
|
green: green2,
|
|
6413
|
-
cyan:
|
|
6766
|
+
cyan: cyan3,
|
|
6414
6767
|
magenta,
|
|
6415
6768
|
yellow: yellow2,
|
|
6416
6769
|
red: red2,
|
|
@@ -6427,7 +6780,7 @@ function resolveColor(name, fallback) {
|
|
|
6427
6780
|
async function resolveCliPersonaId(root) {
|
|
6428
6781
|
try {
|
|
6429
6782
|
const cfg = await readJson(
|
|
6430
|
-
|
|
6783
|
+
path37.join(root, ".cursor", "context", "config.json")
|
|
6431
6784
|
);
|
|
6432
6785
|
const modes = cfg?.agentPersona?.modes ?? cfg?.workspaceSkin?.modes;
|
|
6433
6786
|
const id = modes?.[CLI_RUN_PLAN_MODE];
|
|
@@ -6438,7 +6791,7 @@ async function resolveCliPersonaId(root) {
|
|
|
6438
6791
|
}
|
|
6439
6792
|
async function loadPersonaPack(root, personaId) {
|
|
6440
6793
|
try {
|
|
6441
|
-
const personaPath =
|
|
6794
|
+
const personaPath = path37.join(root, "registry", "personas", "core", personaId, "persona.json");
|
|
6442
6795
|
const pack = await readJson(personaPath);
|
|
6443
6796
|
if (!pack || typeof pack.id !== "string") return null;
|
|
6444
6797
|
return pack;
|
|
@@ -6455,7 +6808,7 @@ function createPersonaBannerPrinter(persona) {
|
|
|
6455
6808
|
const banners = persona.cliBanners;
|
|
6456
6809
|
if (!banners.tickStart && !banners.tickEnd && !banners.phaseComplete) return null;
|
|
6457
6810
|
const primary = resolveColor(persona.ansiPalette?.primary, white);
|
|
6458
|
-
const secondary = resolveColor(persona.ansiPalette?.secondary,
|
|
6811
|
+
const secondary = resolveColor(persona.ansiPalette?.secondary, gray2);
|
|
6459
6812
|
const accent = resolveColor(persona.ansiPalette?.accent, green2);
|
|
6460
6813
|
return {
|
|
6461
6814
|
tickStart(detail) {
|
|
@@ -6488,7 +6841,7 @@ function createPersonaBannerPrinter(persona) {
|
|
|
6488
6841
|
|
|
6489
6842
|
// src/plan-loop/plan-state.ts
|
|
6490
6843
|
import { readFile as readFile18, readdir as readdir6 } from "fs/promises";
|
|
6491
|
-
import
|
|
6844
|
+
import path38 from "path";
|
|
6492
6845
|
function countPendingTodos(raw) {
|
|
6493
6846
|
const lines = raw.split(/\r?\n/);
|
|
6494
6847
|
let inFront = 0;
|
|
@@ -6516,7 +6869,7 @@ function countPendingTodos(raw) {
|
|
|
6516
6869
|
async function findActivePlanFile(plansDir) {
|
|
6517
6870
|
if (!await fileExists(plansDir)) return null;
|
|
6518
6871
|
const files = (await readdir6(plansDir)).filter((f) => f.endsWith(".plan.md")).sort();
|
|
6519
|
-
return files[0] ?
|
|
6872
|
+
return files[0] ? path38.join(plansDir, files[0]) : null;
|
|
6520
6873
|
}
|
|
6521
6874
|
async function readPlan(planPath) {
|
|
6522
6875
|
return readFile18(planPath, "utf8");
|
|
@@ -6593,9 +6946,9 @@ function sleep(ms) {
|
|
|
6593
6946
|
return new Promise((r) => setTimeout(r, ms));
|
|
6594
6947
|
}
|
|
6595
6948
|
async function runPlanLoop(opts) {
|
|
6596
|
-
const plansDir =
|
|
6597
|
-
const stopFile =
|
|
6598
|
-
const logDir =
|
|
6949
|
+
const plansDir = path39.join(opts.root, ".cursor", "plans");
|
|
6950
|
+
const stopFile = path39.join(opts.root, ".cursor", "loop.stop");
|
|
6951
|
+
const logDir = path39.join(opts.root, ".cursor", "loop-logs");
|
|
6599
6952
|
const planPath = await findActivePlanFile(plansDir);
|
|
6600
6953
|
if (!planPath) {
|
|
6601
6954
|
logger.error("No active plan in .cursor/plans/");
|
|
@@ -6616,7 +6969,7 @@ async function runPlanLoop(opts) {
|
|
|
6616
6969
|
try {
|
|
6617
6970
|
const persona = await loadCliRunPlanPersona(opts.root);
|
|
6618
6971
|
const banners = createPersonaBannerPrinter(persona);
|
|
6619
|
-
console.log(`Active plan: ${
|
|
6972
|
+
console.log(`Active plan: ${path39.basename(planPath)}`);
|
|
6620
6973
|
console.log(`Pending to-dos: ${await pending()} | max ticks: ${opts.maxTicks}`);
|
|
6621
6974
|
console.log(`Backend: ${opts.backend.id}`);
|
|
6622
6975
|
if (persona) {
|
|
@@ -6659,20 +7012,23 @@ async function runPlanLoop(opts) {
|
|
|
6659
7012
|
planExhausted = true;
|
|
6660
7013
|
break;
|
|
6661
7014
|
}
|
|
6662
|
-
const logPath =
|
|
6663
|
-
const relLog =
|
|
7015
|
+
const logPath = path39.join(logDir, `tick-${stamp()}.log`);
|
|
7016
|
+
const relLog = path39.relative(opts.root, logPath);
|
|
6664
7017
|
console.log("");
|
|
6665
7018
|
const tickLine = `=== tick ${tick}/${opts.maxTicks} - pending: ${before} - log: ${relLog} ===`;
|
|
6666
7019
|
if (banners) banners.tickStart(tickLine);
|
|
6667
7020
|
else console.log(tickLine);
|
|
6668
7021
|
let agentExit = 0;
|
|
6669
7022
|
try {
|
|
6670
|
-
const result = await
|
|
6671
|
-
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
|
|
7023
|
+
const result = await withCliProgress(
|
|
7024
|
+
`tick ${tick}`,
|
|
7025
|
+
() => opts.backend.run({
|
|
7026
|
+
workspace: opts.root,
|
|
7027
|
+
prompt: TICK_PROMPT,
|
|
7028
|
+
model: opts.model,
|
|
7029
|
+
logPath
|
|
7030
|
+
})
|
|
7031
|
+
);
|
|
6676
7032
|
agentExit = result.exitCode;
|
|
6677
7033
|
} catch (err) {
|
|
6678
7034
|
logger.error(String(err));
|
|
@@ -6728,7 +7084,7 @@ async function runPlanLoop(opts) {
|
|
|
6728
7084
|
}
|
|
6729
7085
|
if (opts.sleepSeconds > 0) {
|
|
6730
7086
|
if (banners) banners.sleep(opts.sleepSeconds);
|
|
6731
|
-
await sleep(opts.sleepSeconds * 1e3);
|
|
7087
|
+
await withCliProgress(`sleep ${opts.sleepSeconds}s`, () => sleep(opts.sleepSeconds * 1e3));
|
|
6732
7088
|
}
|
|
6733
7089
|
}
|
|
6734
7090
|
const pendingNow = await pending();
|
|
@@ -6736,7 +7092,7 @@ async function runPlanLoop(opts) {
|
|
|
6736
7092
|
const finishDetail = `after ${tick} tick(s); pending: ${pendingNow}`;
|
|
6737
7093
|
if (banners) banners.phaseComplete(finishDetail);
|
|
6738
7094
|
console.log(
|
|
6739
|
-
`Loop finished after ${tick} tick(s). Pending now: ${pendingNow}. Logs in ${
|
|
7095
|
+
`Loop finished after ${tick} tick(s). Pending now: ${pendingNow}. Logs in ${path39.relative(opts.root, logDir)}/`
|
|
6740
7096
|
);
|
|
6741
7097
|
if (planExhausted || shouldArmExternalPlanReview({ pending: pendingNow, stopReason })) {
|
|
6742
7098
|
await armExternalPlanReview(opts.root);
|
|
@@ -6807,7 +7163,7 @@ var runPlanCommand = defineCommand14({
|
|
|
6807
7163
|
return;
|
|
6808
7164
|
}
|
|
6809
7165
|
const code = await runPlanLoop({
|
|
6810
|
-
root:
|
|
7166
|
+
root: path40.resolve(args.cwd),
|
|
6811
7167
|
maxTicks,
|
|
6812
7168
|
sleepSeconds,
|
|
6813
7169
|
model: args.model ? String(args.model) : void 0,
|
|
@@ -6841,7 +7197,7 @@ var scanCommand = defineCommand15({
|
|
|
6841
7197
|
});
|
|
6842
7198
|
|
|
6843
7199
|
// src/commands/status.ts
|
|
6844
|
-
import
|
|
7200
|
+
import path41 from "path";
|
|
6845
7201
|
import { defineCommand as defineCommand16 } from "citty";
|
|
6846
7202
|
function profileStatus(profile) {
|
|
6847
7203
|
if (!profile) return { origin: "none", evidence: [], profile: null };
|
|
@@ -6872,11 +7228,11 @@ var statusCommand = defineCommand16({
|
|
|
6872
7228
|
}
|
|
6873
7229
|
},
|
|
6874
7230
|
async run({ args }) {
|
|
6875
|
-
const rootDir =
|
|
7231
|
+
const rootDir = path41.resolve(args.cwd);
|
|
6876
7232
|
const [manifest, rawProfile, scan] = await Promise.all([
|
|
6877
7233
|
loadAgentKitManifest(rootDir),
|
|
6878
7234
|
readJson(
|
|
6879
|
-
|
|
7235
|
+
path41.join(rootDir, ".cursor", "agent-kit.config.json")
|
|
6880
7236
|
),
|
|
6881
7237
|
runScanner(rootDir)
|
|
6882
7238
|
]);
|
|
@@ -6935,7 +7291,7 @@ import { defineCommand as defineCommand17 } from "citty";
|
|
|
6935
7291
|
|
|
6936
7292
|
// src/lifecycle/check-updates.ts
|
|
6937
7293
|
import { execFile as execFile6 } from "child_process";
|
|
6938
|
-
import
|
|
7294
|
+
import path42 from "path";
|
|
6939
7295
|
import { promisify as promisify6 } from "util";
|
|
6940
7296
|
var execFileAsync5 = promisify6(execFile6);
|
|
6941
7297
|
var SEMVER_CORE = /^v?(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/i;
|
|
@@ -7026,11 +7382,11 @@ function intervalElapsed2(lastCheckedAt, intervalDays) {
|
|
|
7026
7382
|
return Date.now() - last >= ms;
|
|
7027
7383
|
}
|
|
7028
7384
|
async function loadContextConfig2(cwd) {
|
|
7029
|
-
const configPath =
|
|
7385
|
+
const configPath = path42.join(cwd, ".cursor", "context", "config.json");
|
|
7030
7386
|
return readJson(configPath);
|
|
7031
7387
|
}
|
|
7032
7388
|
async function stampLastCheckedAt(cwd) {
|
|
7033
|
-
const configPath =
|
|
7389
|
+
const configPath = path42.join(cwd, ".cursor", "context", "config.json");
|
|
7034
7390
|
const existing = await loadContextConfig2(cwd) ?? {};
|
|
7035
7391
|
const prev = existing.updateCheck && typeof existing.updateCheck === "object" ? { ...existing.updateCheck } : {};
|
|
7036
7392
|
existing.updateCheck = {
|
|
@@ -7040,6 +7396,117 @@ async function stampLastCheckedAt(cwd) {
|
|
|
7040
7396
|
};
|
|
7041
7397
|
await writeJson(configPath, existing);
|
|
7042
7398
|
}
|
|
7399
|
+
async function readLocalKitVersion(registryRoot) {
|
|
7400
|
+
for (const rel of ["packages/cli/package.json", "package.json"]) {
|
|
7401
|
+
const data = await readJson(path42.join(registryRoot, rel));
|
|
7402
|
+
if (data && typeof data.version === "string" && data.version.length > 0) {
|
|
7403
|
+
return data.version;
|
|
7404
|
+
}
|
|
7405
|
+
}
|
|
7406
|
+
return null;
|
|
7407
|
+
}
|
|
7408
|
+
async function checkAgainstLocalRegistry(cwd, manifest, options) {
|
|
7409
|
+
const registryPath = options.registryPath;
|
|
7410
|
+
if (!registryPath) {
|
|
7411
|
+
throw new Error("checkAgainstLocalRegistry requires registryPath");
|
|
7412
|
+
}
|
|
7413
|
+
let resolved;
|
|
7414
|
+
try {
|
|
7415
|
+
resolved = await resolveRegistryRoot({ cwd, registryPath });
|
|
7416
|
+
} catch (err) {
|
|
7417
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
7418
|
+
return {
|
|
7419
|
+
status: "error",
|
|
7420
|
+
installedVersion: manifest.version,
|
|
7421
|
+
latestVersion: null,
|
|
7422
|
+
registryUrl: path42.resolve(registryPath),
|
|
7423
|
+
registryRef: "local",
|
|
7424
|
+
applyRecommended: false,
|
|
7425
|
+
message: `Failed to resolve --registry: ${msg}`
|
|
7426
|
+
};
|
|
7427
|
+
}
|
|
7428
|
+
const registryUrl = resolved.root;
|
|
7429
|
+
const registryRef = "local";
|
|
7430
|
+
try {
|
|
7431
|
+
let latest;
|
|
7432
|
+
if (options.latestVersion !== void 0) {
|
|
7433
|
+
latest = options.latestVersion;
|
|
7434
|
+
} else {
|
|
7435
|
+
const raw = await readLocalKitVersion(resolved.root);
|
|
7436
|
+
latest = raw ? normalizeSemver(raw) : null;
|
|
7437
|
+
}
|
|
7438
|
+
const summary = summarizeDiff(await diffAgainstRegistry(resolved.root, cwd, manifest));
|
|
7439
|
+
const hasFileDrift = summary.drift > 0 || summary["missing-local"] > 0;
|
|
7440
|
+
const installed = normalizeSemver(manifest.version);
|
|
7441
|
+
if (!installed) {
|
|
7442
|
+
return {
|
|
7443
|
+
status: "error",
|
|
7444
|
+
installedVersion: manifest.version,
|
|
7445
|
+
latestVersion: latest,
|
|
7446
|
+
registryUrl,
|
|
7447
|
+
registryRef,
|
|
7448
|
+
applyRecommended: false,
|
|
7449
|
+
message: `Installed version "${manifest.version}" is not valid semver.`
|
|
7450
|
+
};
|
|
7451
|
+
}
|
|
7452
|
+
if (!latest) {
|
|
7453
|
+
return {
|
|
7454
|
+
status: "error",
|
|
7455
|
+
installedVersion: installed,
|
|
7456
|
+
latestVersion: null,
|
|
7457
|
+
registryUrl,
|
|
7458
|
+
registryRef,
|
|
7459
|
+
applyRecommended: false,
|
|
7460
|
+
message: "No semver found in the local --registry checkout (packages/cli/package.json or package.json)."
|
|
7461
|
+
};
|
|
7462
|
+
}
|
|
7463
|
+
const cmp = compareSemver(installed, latest);
|
|
7464
|
+
if (hasFileDrift) {
|
|
7465
|
+
return {
|
|
7466
|
+
status: "update-available",
|
|
7467
|
+
installedVersion: installed,
|
|
7468
|
+
latestVersion: latest,
|
|
7469
|
+
registryUrl,
|
|
7470
|
+
registryRef,
|
|
7471
|
+
applyRecommended: false,
|
|
7472
|
+
message: `Local registry has drift vs this install (drift=${summary.drift}, missing-local=${summary["missing-local"]}; source v${latest}). Run /update --registry <path> (Ask confirm) to apply; never silent.`
|
|
7473
|
+
};
|
|
7474
|
+
}
|
|
7475
|
+
if (cmp === 0) {
|
|
7476
|
+
return {
|
|
7477
|
+
status: "up-to-date",
|
|
7478
|
+
installedVersion: installed,
|
|
7479
|
+
latestVersion: latest,
|
|
7480
|
+
registryUrl,
|
|
7481
|
+
registryRef,
|
|
7482
|
+
applyRecommended: false,
|
|
7483
|
+
message: `Installed v${installed} matches local registry v${latest}.`
|
|
7484
|
+
};
|
|
7485
|
+
}
|
|
7486
|
+
if (cmp < 0) {
|
|
7487
|
+
return {
|
|
7488
|
+
status: "update-available",
|
|
7489
|
+
installedVersion: installed,
|
|
7490
|
+
latestVersion: latest,
|
|
7491
|
+
registryUrl,
|
|
7492
|
+
registryRef,
|
|
7493
|
+
applyRecommended: false,
|
|
7494
|
+
message: `Update available from local registry: v${installed} \u2192 v${latest}. Run /update --registry <path> (Ask confirm) to apply; never silent.`
|
|
7495
|
+
};
|
|
7496
|
+
}
|
|
7497
|
+
return {
|
|
7498
|
+
status: "ahead-of-public",
|
|
7499
|
+
installedVersion: installed,
|
|
7500
|
+
latestVersion: latest,
|
|
7501
|
+
registryUrl,
|
|
7502
|
+
registryRef,
|
|
7503
|
+
applyRecommended: false,
|
|
7504
|
+
message: `Installed v${installed} is ahead of local registry v${latest}.`
|
|
7505
|
+
};
|
|
7506
|
+
} finally {
|
|
7507
|
+
await resolved.unlock?.();
|
|
7508
|
+
}
|
|
7509
|
+
}
|
|
7043
7510
|
async function checkForUpdates(cwd, options = {}) {
|
|
7044
7511
|
const manifest = await loadAgentKitManifest(cwd);
|
|
7045
7512
|
if (!manifest) {
|
|
@@ -7053,7 +7520,10 @@ async function checkForUpdates(cwd, options = {}) {
|
|
|
7053
7520
|
message: "No .cursor/agent-kit.json \u2014 run agent-kit install first."
|
|
7054
7521
|
};
|
|
7055
7522
|
}
|
|
7056
|
-
|
|
7523
|
+
if (options.registryPath) {
|
|
7524
|
+
return checkAgainstLocalRegistry(cwd, manifest, options);
|
|
7525
|
+
}
|
|
7526
|
+
const registryUrl = options.publicRegistryUrl ?? manifest.registry?.url ?? null;
|
|
7057
7527
|
const registryRef = manifest.registry?.ref ?? null;
|
|
7058
7528
|
if (isFactoryOrDevRegistry(registryUrl, registryRef)) {
|
|
7059
7529
|
return {
|
|
@@ -7183,7 +7653,7 @@ var updateCommand = defineCommand17({
|
|
|
7183
7653
|
},
|
|
7184
7654
|
check: {
|
|
7185
7655
|
type: "boolean",
|
|
7186
|
-
description: "Check-only: compare installed version to
|
|
7656
|
+
description: "Check-only: compare installed version to the resolved registry (public tags, or --registry local checkout); never apply L0 writes",
|
|
7187
7657
|
default: false
|
|
7188
7658
|
},
|
|
7189
7659
|
json: {
|
|
@@ -7224,7 +7694,8 @@ var updateCommand = defineCommand17({
|
|
|
7224
7694
|
const result = await checkForUpdates(args.cwd, {
|
|
7225
7695
|
respectPrefs: Boolean(args["respect-prefs"]),
|
|
7226
7696
|
stamp: Boolean(args.stamp),
|
|
7227
|
-
publicRegistryUrl: typeof args.url === "string" && args.url ? args.url : void 0
|
|
7697
|
+
publicRegistryUrl: typeof args.url === "string" && args.url ? args.url : void 0,
|
|
7698
|
+
registryPath: typeof args.registry === "string" && args.registry ? args.registry : void 0
|
|
7228
7699
|
});
|
|
7229
7700
|
if (args.json) {
|
|
7230
7701
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -7287,7 +7758,10 @@ var updateCommand = defineCommand17({
|
|
|
7287
7758
|
await seedManagedHashLedger(projectRoot);
|
|
7288
7759
|
logger.info("Seeded managed-hash ledger from current local overlay files.");
|
|
7289
7760
|
}
|
|
7290
|
-
const stats = await
|
|
7761
|
+
const stats = await withCliProgress(
|
|
7762
|
+
"update",
|
|
7763
|
+
() => syncFromManifest(registry.root, projectRoot, next)
|
|
7764
|
+
);
|
|
7291
7765
|
await saveManifest(projectRoot, next);
|
|
7292
7766
|
logApplyStats(stats);
|
|
7293
7767
|
logger.success("Update complete (L3 protected paths left untouched).");
|
|
@@ -7299,7 +7773,7 @@ var updateCommand = defineCommand17({
|
|
|
7299
7773
|
|
|
7300
7774
|
// src/commands/validate.ts
|
|
7301
7775
|
import { readFile as readFile21 } from "fs/promises";
|
|
7302
|
-
import
|
|
7776
|
+
import path43 from "path";
|
|
7303
7777
|
import { defineCommand as defineCommand18 } from "citty";
|
|
7304
7778
|
|
|
7305
7779
|
// src/invariants/plan-schema.ts
|
|
@@ -7346,7 +7820,7 @@ function validatePlanFrontmatterText(text) {
|
|
|
7346
7820
|
// src/commands/validate.ts
|
|
7347
7821
|
async function resolveEditedPath(cwd, explicit) {
|
|
7348
7822
|
if (explicit) {
|
|
7349
|
-
const filePath2 =
|
|
7823
|
+
const filePath2 = path43.resolve(cwd, explicit);
|
|
7350
7824
|
try {
|
|
7351
7825
|
return { filePath: filePath2, content: await readFile21(filePath2, "utf8") };
|
|
7352
7826
|
} catch {
|
|
@@ -7356,7 +7830,7 @@ async function resolveEditedPath(cwd, explicit) {
|
|
|
7356
7830
|
const payload = await readStdinJson();
|
|
7357
7831
|
const rel = typeof payload.file_path === "string" && payload.file_path || typeof payload.path === "string" && payload.path || typeof payload.file === "string" && payload.file || "";
|
|
7358
7832
|
if (!rel) return null;
|
|
7359
|
-
const filePath =
|
|
7833
|
+
const filePath = path43.isAbsolute(rel) ? rel : path43.resolve(cwd, rel);
|
|
7360
7834
|
try {
|
|
7361
7835
|
return { filePath, content: await readFile21(filePath, "utf8") };
|
|
7362
7836
|
} catch {
|
|
@@ -7386,7 +7860,7 @@ var validateCommand = defineCommand18({
|
|
|
7386
7860
|
async run({ args }) {
|
|
7387
7861
|
const cwd = typeof args.cwd === "string" ? args.cwd : process.cwd();
|
|
7388
7862
|
const fileArg = typeof args.file === "string" ? args.file : void 0;
|
|
7389
|
-
const filePath = fileArg ?
|
|
7863
|
+
const filePath = fileArg ? path43.resolve(cwd, fileArg) : path43.join(path43.resolve(cwd), ".cursor", "HANDOFF.md");
|
|
7390
7864
|
let content = "";
|
|
7391
7865
|
try {
|
|
7392
7866
|
content = await readFile21(filePath, "utf8");
|
|
@@ -7413,7 +7887,7 @@ var validateCommand = defineCommand18({
|
|
|
7413
7887
|
process.exitCode = 2;
|
|
7414
7888
|
return;
|
|
7415
7889
|
}
|
|
7416
|
-
const filePath =
|
|
7890
|
+
const filePath = path43.resolve(cwd, fileArg);
|
|
7417
7891
|
let content = "";
|
|
7418
7892
|
try {
|
|
7419
7893
|
content = await readFile21(filePath, "utf8");
|
|
@@ -7435,7 +7909,7 @@ var validateCommand = defineCommand18({
|
|
|
7435
7909
|
},
|
|
7436
7910
|
async run({ args }) {
|
|
7437
7911
|
const cwd = typeof args.cwd === "string" ? args.cwd : process.cwd();
|
|
7438
|
-
const resolved = await resolveEditedPath(
|
|
7912
|
+
const resolved = await resolveEditedPath(path43.resolve(cwd));
|
|
7439
7913
|
if (!resolved) {
|
|
7440
7914
|
console.log(JSON.stringify({}));
|
|
7441
7915
|
return;
|
|
@@ -7478,19 +7952,18 @@ var validateCommand = defineCommand18({
|
|
|
7478
7952
|
});
|
|
7479
7953
|
|
|
7480
7954
|
// src/welcome/help-groups.ts
|
|
7481
|
-
import { bold, gray as
|
|
7955
|
+
import { bold, gray as gray4, underline } from "kolorist";
|
|
7482
7956
|
|
|
7483
7957
|
// src/welcome/screen.ts
|
|
7484
7958
|
import {
|
|
7485
7959
|
blue as blue2,
|
|
7486
|
-
cyan as
|
|
7487
|
-
gray as
|
|
7488
|
-
options as
|
|
7960
|
+
cyan as cyan4,
|
|
7961
|
+
gray as gray3,
|
|
7962
|
+
options as koloristOptions2,
|
|
7489
7963
|
lightCyan,
|
|
7490
7964
|
trueColor,
|
|
7491
7965
|
white as white2
|
|
7492
7966
|
} from "kolorist";
|
|
7493
|
-
var HELMET_OUTLINE = "#e2e8f0";
|
|
7494
7967
|
var KOLORIST_TRUECOLOR = 3;
|
|
7495
7968
|
var HELMET_ASCII = [
|
|
7496
7969
|
" ____",
|
|
@@ -7515,30 +7988,20 @@ function outlineAnsi(line) {
|
|
|
7515
7988
|
return trueColor(r, g, b)(line);
|
|
7516
7989
|
}
|
|
7517
7990
|
function withKoloristColor(fn) {
|
|
7518
|
-
const prevEnabled =
|
|
7519
|
-
const prevLevel =
|
|
7520
|
-
|
|
7521
|
-
|
|
7991
|
+
const prevEnabled = koloristOptions2.enabled;
|
|
7992
|
+
const prevLevel = koloristOptions2.supportLevel;
|
|
7993
|
+
koloristOptions2.enabled = true;
|
|
7994
|
+
koloristOptions2.supportLevel = KOLORIST_TRUECOLOR;
|
|
7522
7995
|
try {
|
|
7523
7996
|
return fn();
|
|
7524
7997
|
} finally {
|
|
7525
|
-
|
|
7526
|
-
|
|
7998
|
+
koloristOptions2.enabled = prevEnabled;
|
|
7999
|
+
koloristOptions2.supportLevel = prevLevel;
|
|
7527
8000
|
}
|
|
7528
8001
|
}
|
|
7529
8002
|
function hasCliSubcommand(rawArgs) {
|
|
7530
8003
|
return Boolean(rawArgs?.some((arg) => !arg.startsWith("-")));
|
|
7531
8004
|
}
|
|
7532
|
-
function shouldUseWelcomeColor(opts = {}) {
|
|
7533
|
-
if (opts.color === false) return false;
|
|
7534
|
-
if (process.env.NO_COLOR) return false;
|
|
7535
|
-
if (process.env.NODE_DISABLE_COLORS) return false;
|
|
7536
|
-
if (process.env.FORCE_COLOR === "0") return false;
|
|
7537
|
-
if (process.env.CI != null && process.env.CI !== "") return false;
|
|
7538
|
-
if (opts.color === true) return true;
|
|
7539
|
-
const tty = opts.stdoutIsTTY ?? Boolean(process.stdout.isTTY);
|
|
7540
|
-
return tty;
|
|
7541
|
-
}
|
|
7542
8005
|
function renderHelmetAscii(color) {
|
|
7543
8006
|
if (!color) return HELMET_ASCII.join("\n");
|
|
7544
8007
|
return withKoloristColor(
|
|
@@ -7560,8 +8023,8 @@ function renderWelcomeScreen(opts = {}) {
|
|
|
7560
8023
|
const version = opts.version ?? KIT_VERSION;
|
|
7561
8024
|
const color = shouldUseWelcomeColor(opts);
|
|
7562
8025
|
const title = color ? white2("Mission Kit") : "Mission Kit";
|
|
7563
|
-
const product = color ?
|
|
7564
|
-
const muted = (s) => color ?
|
|
8026
|
+
const product = color ? cyan4("agent-kit") : "agent-kit";
|
|
8027
|
+
const muted = (s) => color ? gray3(s) : s;
|
|
7565
8028
|
const lines = [
|
|
7566
8029
|
renderHelmetAscii(color),
|
|
7567
8030
|
"",
|
|
@@ -7573,13 +8036,18 @@ function renderWelcomeScreen(opts = {}) {
|
|
|
7573
8036
|
const width = Math.max(...WELCOME_UTILITY_HINTS.map(({ cmd }) => cmd.length));
|
|
7574
8037
|
return WELCOME_UTILITY_HINTS.map(({ cmd, hint }) => {
|
|
7575
8038
|
const pad = " ".repeat(width - cmd.length + 2);
|
|
7576
|
-
const left = color ?
|
|
8039
|
+
const left = color ? cyan4(` ${cmd}`) : ` ${cmd}`;
|
|
7577
8040
|
return `${left}${pad}${muted(hint)}`;
|
|
7578
8041
|
});
|
|
7579
8042
|
})(),
|
|
7580
8043
|
"",
|
|
7581
8044
|
muted(
|
|
7582
8045
|
"Chat HITL (start-project, git-staging/prod, run-plan-all) stays in Cursor slash commands."
|
|
8046
|
+
),
|
|
8047
|
+
muted(
|
|
8048
|
+
`${shouldUseVisualMotion(opts) ? SPACE_MARKS.star : SPACE_MARKS.tick} ${tipAt(
|
|
8049
|
+
[...version].reduce((n, c) => n + c.charCodeAt(0), 0)
|
|
8050
|
+
)}`
|
|
7583
8051
|
)
|
|
7584
8052
|
];
|
|
7585
8053
|
return `${lines.join("\n")}
|
|
@@ -7630,7 +8098,7 @@ async function resolveSubMeta(subCommands) {
|
|
|
7630
8098
|
async function renderGroupedRootHelp(cmd) {
|
|
7631
8099
|
const color = shouldUseWelcomeColor();
|
|
7632
8100
|
const u = (s) => color ? underline(bold(s)) : s;
|
|
7633
|
-
const g = (s) => color ?
|
|
8101
|
+
const g = (s) => color ? gray4(s) : s;
|
|
7634
8102
|
const meta = await resolveCommandMeta(cmd.meta);
|
|
7635
8103
|
const name = meta?.name ?? "agent-kit";
|
|
7636
8104
|
const version = meta?.version ?? KIT_VERSION;
|
|
@@ -7660,11 +8128,14 @@ async function renderGroupedRootHelp(cmd) {
|
|
|
7660
8128
|
}
|
|
7661
8129
|
lines.push("");
|
|
7662
8130
|
}
|
|
8131
|
+
const tipMark = shouldUseVisualMotion() ? SPACE_MARKS.star : SPACE_MARKS.tick;
|
|
8132
|
+
const tip = tipAt([...version].reduce((n, c) => n + c.charCodeAt(0), 0));
|
|
7663
8133
|
lines.push(
|
|
7664
8134
|
g(`Use \`${name} <command> --help\` for more information about a command.`),
|
|
7665
8135
|
g(
|
|
7666
8136
|
"Chat-only HITL (start-project, backlog, git-staging/prod, run-plan-all) is not a CLI surface."
|
|
7667
8137
|
),
|
|
8138
|
+
g(`${tipMark} ${tip}`),
|
|
7668
8139
|
""
|
|
7669
8140
|
);
|
|
7670
8141
|
return lines.join("\n");
|