@lousy-agents/cli 5.13.0 → 5.13.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api/copilot-with-fastify/.devcontainer/devcontainer.json +1 -1
- package/api/copilot-with-fastify/package-lock.json +13 -13
- package/api/copilot-with-fastify/package.json +4 -4
- package/cli/copilot-with-citty/.devcontainer/devcontainer.json +1 -1
- package/cli/copilot-with-citty/package.json +3 -3
- package/dist/27.js +2 -2
- package/dist/653.js +1 -1
- package/dist/962.js +1 -1
- package/dist/index.js +163 -153
- package/package.json +2 -2
- package/ui/copilot-with-react/.devcontainer/devcontainer.json +1 -1
- package/ui/copilot-with-react/package.json +4 -4
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
"ghcr.io/devcontainers/features/copilot-cli:1.0.0": {},
|
|
12
12
|
"ghcr.io/anthropics/devcontainer-features/claude-code:1": {
|
|
13
|
-
"version": "v2.1.
|
|
13
|
+
"version": "v2.1.131"
|
|
14
14
|
},
|
|
15
15
|
"ghcr.io/rocker-org/devcontainer-features/apt-packages:1.0.2": {
|
|
16
16
|
"packages": "yamllint, shellcheck",
|
|
@@ -14,15 +14,15 @@
|
|
|
14
14
|
"kysely": "0.28.17",
|
|
15
15
|
"pino": "10.3.1",
|
|
16
16
|
"postgres": "3.4.9",
|
|
17
|
-
"zod": "4.4.
|
|
17
|
+
"zod": "4.4.3"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
20
|
"@biomejs/biome": "2.4.14",
|
|
21
|
-
"@lousy-agents/mcp": "5.
|
|
21
|
+
"@lousy-agents/mcp": "5.13.1",
|
|
22
22
|
"@modelcontextprotocol/server-sequential-thinking": "2025.12.18",
|
|
23
23
|
"@testcontainers/postgresql": "11.14.0",
|
|
24
24
|
"@types/node": "24.12.2",
|
|
25
|
-
"@upstash/context7-mcp": "2.2.
|
|
25
|
+
"@upstash/context7-mcp": "2.2.4",
|
|
26
26
|
"chance": "1.1.13",
|
|
27
27
|
"testcontainers": "11.14.0",
|
|
28
28
|
"tsx": "4.21.0",
|
|
@@ -956,15 +956,15 @@
|
|
|
956
956
|
}
|
|
957
957
|
},
|
|
958
958
|
"node_modules/@lousy-agents/mcp": {
|
|
959
|
-
"version": "5.
|
|
960
|
-
"resolved": "https://registry.npmjs.org/@lousy-agents/mcp/-/mcp-5.
|
|
961
|
-
"integrity": "sha512-
|
|
959
|
+
"version": "5.13.1",
|
|
960
|
+
"resolved": "https://registry.npmjs.org/@lousy-agents/mcp/-/mcp-5.13.1.tgz",
|
|
961
|
+
"integrity": "sha512-hzkNWfxl7YwOhjA//v7xJTuEQtWw+jhECGy6n36leuMGlqSgMJnKmQqQe7YvpE1kyQNrXkW1MxvO8xKKjkdEUg==",
|
|
962
962
|
"dev": true,
|
|
963
963
|
"license": "BSD-2-Clause-Patent",
|
|
964
964
|
"dependencies": {
|
|
965
965
|
"@modelcontextprotocol/sdk": "1.29.0",
|
|
966
966
|
"yaml": "2.8.4",
|
|
967
|
-
"zod": "4.4.
|
|
967
|
+
"zod": "4.4.3"
|
|
968
968
|
},
|
|
969
969
|
"bin": {
|
|
970
970
|
"lousy-agents-mcp": "dist/mcp-server.js"
|
|
@@ -1649,9 +1649,9 @@
|
|
|
1649
1649
|
"license": "MIT"
|
|
1650
1650
|
},
|
|
1651
1651
|
"node_modules/@upstash/context7-mcp": {
|
|
1652
|
-
"version": "2.2.
|
|
1653
|
-
"resolved": "https://registry.npmjs.org/@upstash/context7-mcp/-/context7-mcp-2.2.
|
|
1654
|
-
"integrity": "sha512-
|
|
1652
|
+
"version": "2.2.4",
|
|
1653
|
+
"resolved": "https://registry.npmjs.org/@upstash/context7-mcp/-/context7-mcp-2.2.4.tgz",
|
|
1654
|
+
"integrity": "sha512-6kpjAxif2w+HhxSPmyi+SUsVPgFKBi+xtFgKRc9f0fhLpZGTBX1QKWFmleAIZ4T69Ykynzxc4nHGEDrr219noA==",
|
|
1655
1655
|
"dev": true,
|
|
1656
1656
|
"license": "MIT",
|
|
1657
1657
|
"dependencies": {
|
|
@@ -6009,9 +6009,9 @@
|
|
|
6009
6009
|
}
|
|
6010
6010
|
},
|
|
6011
6011
|
"node_modules/zod": {
|
|
6012
|
-
"version": "4.4.
|
|
6013
|
-
"resolved": "https://registry.npmjs.org/zod/-/zod-4.4.
|
|
6014
|
-
"integrity": "sha512-
|
|
6012
|
+
"version": "4.4.3",
|
|
6013
|
+
"resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz",
|
|
6014
|
+
"integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==",
|
|
6015
6015
|
"license": "MIT",
|
|
6016
6016
|
"funding": {
|
|
6017
6017
|
"url": "https://github.com/sponsors/colinhacks"
|
|
@@ -22,18 +22,18 @@
|
|
|
22
22
|
"kysely": "0.28.17",
|
|
23
23
|
"pino": "10.3.1",
|
|
24
24
|
"postgres": "3.4.9",
|
|
25
|
-
"zod": "4.4.
|
|
25
|
+
"zod": "4.4.3"
|
|
26
26
|
},
|
|
27
27
|
"overrides": {
|
|
28
|
-
"zod": "4.4.
|
|
28
|
+
"zod": "4.4.3"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@biomejs/biome": "2.4.14",
|
|
32
|
-
"@lousy-agents/mcp": "5.
|
|
32
|
+
"@lousy-agents/mcp": "5.13.1",
|
|
33
33
|
"@modelcontextprotocol/server-sequential-thinking": "2025.12.18",
|
|
34
34
|
"@testcontainers/postgresql": "11.14.0",
|
|
35
35
|
"@types/node": "24.12.2",
|
|
36
|
-
"@upstash/context7-mcp": "2.2.
|
|
36
|
+
"@upstash/context7-mcp": "2.2.4",
|
|
37
37
|
"chance": "1.1.13",
|
|
38
38
|
"testcontainers": "11.14.0",
|
|
39
39
|
"tsx": "4.21.0",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
"ghcr.io/devcontainers/features/copilot-cli:1.0.0": {},
|
|
12
12
|
"ghcr.io/anthropics/devcontainer-features/claude-code:1": {
|
|
13
|
-
"version": "v2.1.
|
|
13
|
+
"version": "v2.1.131"
|
|
14
14
|
},
|
|
15
15
|
"ghcr.io/rocker-org/devcontainer-features/apt-packages:1.0.2": {
|
|
16
16
|
"packages": "yamllint, shellcheck",
|
|
@@ -16,14 +16,14 @@
|
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"citty": "0.2.2",
|
|
18
18
|
"consola": "3.4.2",
|
|
19
|
-
"zod": "4.4.
|
|
19
|
+
"zod": "4.4.3"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@biomejs/biome": "2.4.14",
|
|
23
|
-
"@lousy-agents/mcp": "5.
|
|
23
|
+
"@lousy-agents/mcp": "5.13.1",
|
|
24
24
|
"@modelcontextprotocol/server-sequential-thinking": "2025.12.18",
|
|
25
25
|
"@types/node": "24.12.2",
|
|
26
|
-
"@upstash/context7-mcp": "2.2.
|
|
26
|
+
"@upstash/context7-mcp": "2.2.4",
|
|
27
27
|
"chance": "1.1.13",
|
|
28
28
|
"tsx": "4.21.0",
|
|
29
29
|
"typescript": "6.0.3",
|
package/dist/27.js
CHANGED
|
@@ -7,10 +7,10 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
7
7
|
|
|
8
8
|
// EXPORTS
|
|
9
9
|
__webpack_require__.d(__webpack_exports__, {
|
|
10
|
+
FSWatcher: () => (/* binding */ FSWatcher),
|
|
10
11
|
WatchHelper: () => (/* binding */ WatchHelper),
|
|
11
12
|
"default": () => (/* binding */ chokidar),
|
|
12
|
-
watch: () => (/* binding */ watch)
|
|
13
|
-
FSWatcher: () => (/* binding */ FSWatcher)
|
|
13
|
+
watch: () => (/* binding */ watch)
|
|
14
14
|
});
|
|
15
15
|
|
|
16
16
|
// EXTERNAL MODULE: external "node:events"
|
package/dist/653.js
CHANGED
|
@@ -720,7 +720,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
720
720
|
downloadTemplate: () => (/* reexport */ downloadTemplate)
|
|
721
721
|
});
|
|
722
722
|
|
|
723
|
-
// UNUSED EXPORTS:
|
|
723
|
+
// UNUSED EXPORTS: registryProvider, startShell
|
|
724
724
|
|
|
725
725
|
// EXTERNAL MODULE: ../../node_modules/giget/dist/_chunks/libs/nypm.mjs
|
|
726
726
|
var nypm = __webpack_require__(292);
|
package/dist/962.js
CHANGED
|
@@ -8,7 +8,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
8
8
|
digest: () => (/* reexport */ node_digest)
|
|
9
9
|
});
|
|
10
10
|
|
|
11
|
-
// UNUSED EXPORTS: isEqual, serialize
|
|
11
|
+
// UNUSED EXPORTS: hash, isEqual, serialize
|
|
12
12
|
|
|
13
13
|
// EXTERNAL MODULE: external "node:crypto"
|
|
14
14
|
var external_node_crypto_ = __webpack_require__(7598);
|
package/dist/index.js
CHANGED
|
@@ -567,7 +567,7 @@ module.exports = webpackEmptyAsyncContext;
|
|
|
567
567
|
|
|
568
568
|
|
|
569
569
|
},
|
|
570
|
-
|
|
570
|
+
2091(__unused_rspack_module, __unused_rspack___webpack_exports__, __webpack_require__) {
|
|
571
571
|
// NAMESPACE OBJECT: ../../node_modules/micromark/lib/constructs.js
|
|
572
572
|
var constructs_namespaceObject = {};
|
|
573
573
|
__webpack_require__.r(constructs_namespaceObject);
|
|
@@ -5685,7 +5685,7 @@ const safeDecodeAsync = /* @__PURE__*/ _safeDecodeAsync($ZodRealError);
|
|
|
5685
5685
|
const versions_version = {
|
|
5686
5686
|
major: 4,
|
|
5687
5687
|
minor: 4,
|
|
5688
|
-
patch:
|
|
5688
|
+
patch: 3,
|
|
5689
5689
|
};
|
|
5690
5690
|
|
|
5691
5691
|
;// CONCATENATED MODULE: ../../node_modules/zod/v4/core/schemas.js
|
|
@@ -7408,6 +7408,7 @@ const $ZodFile = /*@__PURE__*/ (/* unused pure expression or super */ null && (c
|
|
|
7408
7408
|
})));
|
|
7409
7409
|
const $ZodTransform = /*@__PURE__*/ $constructor("$ZodTransform", (inst, def) => {
|
|
7410
7410
|
$ZodType.init(inst, def);
|
|
7411
|
+
inst._zod.optin = "optional";
|
|
7411
7412
|
inst._zod.parse = (payload, ctx) => {
|
|
7412
7413
|
if (ctx.direction === "backward") {
|
|
7413
7414
|
throw new $ZodEncodeError(inst.constructor.name);
|
|
@@ -7417,6 +7418,7 @@ const $ZodTransform = /*@__PURE__*/ $constructor("$ZodTransform", (inst, def) =>
|
|
|
7417
7418
|
const output = _out instanceof Promise ? _out : Promise.resolve(_out);
|
|
7418
7419
|
return output.then((output) => {
|
|
7419
7420
|
payload.value = output;
|
|
7421
|
+
payload.fallback = true;
|
|
7420
7422
|
return payload;
|
|
7421
7423
|
});
|
|
7422
7424
|
}
|
|
@@ -7424,11 +7426,12 @@ const $ZodTransform = /*@__PURE__*/ $constructor("$ZodTransform", (inst, def) =>
|
|
|
7424
7426
|
throw new $ZodAsyncError();
|
|
7425
7427
|
}
|
|
7426
7428
|
payload.value = _out;
|
|
7429
|
+
payload.fallback = true;
|
|
7427
7430
|
return payload;
|
|
7428
7431
|
};
|
|
7429
7432
|
});
|
|
7430
7433
|
function handleOptionalResult(result, input) {
|
|
7431
|
-
if (result.issues.length
|
|
7434
|
+
if (input === undefined && (result.issues.length || result.fallback)) {
|
|
7432
7435
|
return { issues: [], value: undefined };
|
|
7433
7436
|
}
|
|
7434
7437
|
return result;
|
|
@@ -7446,10 +7449,11 @@ const $ZodOptional = /*@__PURE__*/ $constructor("$ZodOptional", (inst, def) => {
|
|
|
7446
7449
|
});
|
|
7447
7450
|
inst._zod.parse = (payload, ctx) => {
|
|
7448
7451
|
if (def.innerType._zod.optin === "optional") {
|
|
7452
|
+
const input = payload.value;
|
|
7449
7453
|
const result = def.innerType._zod.run(payload, ctx);
|
|
7450
7454
|
if (result instanceof Promise)
|
|
7451
|
-
return result.then((r) => handleOptionalResult(r,
|
|
7452
|
-
return handleOptionalResult(result,
|
|
7455
|
+
return result.then((r) => handleOptionalResult(r, input));
|
|
7456
|
+
return handleOptionalResult(result, input);
|
|
7453
7457
|
}
|
|
7454
7458
|
if (payload.value === undefined) {
|
|
7455
7459
|
return payload;
|
|
@@ -7576,7 +7580,7 @@ const $ZodSuccess = /*@__PURE__*/ (/* unused pure expression or super */ null &&
|
|
|
7576
7580
|
})));
|
|
7577
7581
|
const $ZodCatch = /*@__PURE__*/ $constructor("$ZodCatch", (inst, def) => {
|
|
7578
7582
|
$ZodType.init(inst, def);
|
|
7579
|
-
|
|
7583
|
+
inst._zod.optin = "optional";
|
|
7580
7584
|
defineLazy(inst._zod, "optout", () => def.innerType._zod.optout);
|
|
7581
7585
|
defineLazy(inst._zod, "values", () => def.innerType._zod.values);
|
|
7582
7586
|
inst._zod.parse = (payload, ctx) => {
|
|
@@ -7597,6 +7601,7 @@ const $ZodCatch = /*@__PURE__*/ $constructor("$ZodCatch", (inst, def) => {
|
|
|
7597
7601
|
input: payload.value,
|
|
7598
7602
|
});
|
|
7599
7603
|
payload.issues = [];
|
|
7604
|
+
payload.fallback = true;
|
|
7600
7605
|
}
|
|
7601
7606
|
return payload;
|
|
7602
7607
|
});
|
|
@@ -7611,6 +7616,7 @@ const $ZodCatch = /*@__PURE__*/ $constructor("$ZodCatch", (inst, def) => {
|
|
|
7611
7616
|
input: payload.value,
|
|
7612
7617
|
});
|
|
7613
7618
|
payload.issues = [];
|
|
7619
|
+
payload.fallback = true;
|
|
7614
7620
|
}
|
|
7615
7621
|
return payload;
|
|
7616
7622
|
};
|
|
@@ -7657,7 +7663,7 @@ function handlePipeResult(left, next, ctx) {
|
|
|
7657
7663
|
left.aborted = true;
|
|
7658
7664
|
return left;
|
|
7659
7665
|
}
|
|
7660
|
-
return next._zod.run({ value: left.value, issues: left.issues }, ctx);
|
|
7666
|
+
return next._zod.run({ value: left.value, issues: left.issues, fallback: left.fallback }, ctx);
|
|
7661
7667
|
}
|
|
7662
7668
|
const $ZodCodec = /*@__PURE__*/ (/* unused pure expression or super */ null && (core.$constructor("$ZodCodec", (inst, def) => {
|
|
7663
7669
|
$ZodType.init(inst, def);
|
|
@@ -7715,8 +7721,6 @@ function handleCodecTxResult(left, value, nextSchema, ctx) {
|
|
|
7715
7721
|
}
|
|
7716
7722
|
const $ZodPreprocess = /*@__PURE__*/ (/* unused pure expression or super */ null && (core.$constructor("$ZodPreprocess", (inst, def) => {
|
|
7717
7723
|
$ZodPipe.init(inst, def);
|
|
7718
|
-
util.defineLazy(inst._zod, "optin", () => def.out._zod.optin);
|
|
7719
|
-
util.defineLazy(inst._zod, "optout", () => def.out._zod.optout);
|
|
7720
7724
|
})));
|
|
7721
7725
|
const $ZodReadonly = /*@__PURE__*/ $constructor("$ZodReadonly", (inst, def) => {
|
|
7722
7726
|
$ZodType.init(inst, def);
|
|
@@ -8914,7 +8918,7 @@ function _promise(Class, innerType) {
|
|
|
8914
8918
|
}
|
|
8915
8919
|
// @__NO_SIDE_EFFECTS__
|
|
8916
8920
|
function _custom(Class, fn, _params) {
|
|
8917
|
-
const norm =
|
|
8921
|
+
const norm = normalizeParams(_params);
|
|
8918
8922
|
norm.abort ?? (norm.abort = true); // default to abort:false
|
|
8919
8923
|
const schema = new Class({
|
|
8920
8924
|
type: "custom",
|
|
@@ -11303,10 +11307,12 @@ const ZodTransform = /*@__PURE__*/ $constructor("ZodTransform", (inst, def) => {
|
|
|
11303
11307
|
if (output instanceof Promise) {
|
|
11304
11308
|
return output.then((output) => {
|
|
11305
11309
|
payload.value = output;
|
|
11310
|
+
payload.fallback = true;
|
|
11306
11311
|
return payload;
|
|
11307
11312
|
});
|
|
11308
11313
|
}
|
|
11309
11314
|
payload.value = output;
|
|
11315
|
+
payload.fallback = true;
|
|
11310
11316
|
return payload;
|
|
11311
11317
|
};
|
|
11312
11318
|
});
|
|
@@ -11553,7 +11559,7 @@ function schemas_check(fn) {
|
|
|
11553
11559
|
return ch;
|
|
11554
11560
|
}
|
|
11555
11561
|
function custom(fn, _params) {
|
|
11556
|
-
return
|
|
11562
|
+
return _custom(ZodCustom, fn ?? (() => true), _params);
|
|
11557
11563
|
}
|
|
11558
11564
|
function refine(fn, _params = {}) {
|
|
11559
11565
|
return _refine(ZodCustom, fn, _params);
|
|
@@ -11817,6 +11823,26 @@ var compat_ZodFirstPartyTypeKind;
|
|
|
11817
11823
|
setupActionPatterns: DEFAULT_SETUP_ACTION_PATTERNS,
|
|
11818
11824
|
packageManagers: DEFAULT_PACKAGE_MANAGERS
|
|
11819
11825
|
};
|
|
11826
|
+
/**
|
|
11827
|
+
* Gets a version type to action name mapping from config.
|
|
11828
|
+
* Returns a partial record as not all types may be configured.
|
|
11829
|
+
*/ function getVersionTypeToActionMap(config) {
|
|
11830
|
+
const map = {};
|
|
11831
|
+
for (const action of config.setupActions){
|
|
11832
|
+
map[action.type] = action.action;
|
|
11833
|
+
}
|
|
11834
|
+
return map;
|
|
11835
|
+
}
|
|
11836
|
+
/**
|
|
11837
|
+
* Gets a version file type to config key mapping from config.
|
|
11838
|
+
* Returns a partial record as not all types may be configured.
|
|
11839
|
+
*/ function getVersionFileConfigKeyMap(config) {
|
|
11840
|
+
const map = {};
|
|
11841
|
+
for (const action of config.setupActions){
|
|
11842
|
+
map[action.type] = action.versionFileKey;
|
|
11843
|
+
}
|
|
11844
|
+
return map;
|
|
11845
|
+
}
|
|
11820
11846
|
|
|
11821
11847
|
;// CONCATENATED MODULE: ../core/src/lib/copilot-setup-config.ts
|
|
11822
11848
|
/**
|
|
@@ -11944,29 +11970,8 @@ const CopilotSetupConfigSchema = schemas_object({
|
|
|
11944
11970
|
*
|
|
11945
11971
|
* This function is retained for backwards compatibility but is a no-op
|
|
11946
11972
|
* because configuration is no longer cached at module scope.
|
|
11947
|
-
*/ function resetCopilotSetupConfigCache() {
|
|
11948
|
-
|
|
11949
|
-
}
|
|
11950
|
-
/**
|
|
11951
|
-
* Gets a version file type to action mapping from config.
|
|
11952
|
-
* Returns a partial record as not all types may be configured.
|
|
11953
|
-
*/ function getVersionTypeToActionMap(config) {
|
|
11954
|
-
const map = {};
|
|
11955
|
-
for (const action of config.setupActions){
|
|
11956
|
-
map[action.type] = action.action;
|
|
11957
|
-
}
|
|
11958
|
-
return map;
|
|
11959
|
-
}
|
|
11960
|
-
/**
|
|
11961
|
-
* Gets a version file type to config key mapping from config.
|
|
11962
|
-
* Returns a partial record as not all types may be configured.
|
|
11963
|
-
*/ function getVersionFileConfigKeyMap(config) {
|
|
11964
|
-
const map = {};
|
|
11965
|
-
for (const action of config.setupActions){
|
|
11966
|
-
map[action.type] = action.versionFileKey;
|
|
11967
|
-
}
|
|
11968
|
-
return map;
|
|
11969
|
-
}
|
|
11973
|
+
*/ function resetCopilotSetupConfigCache() {}
|
|
11974
|
+
|
|
11970
11975
|
/**
|
|
11971
11976
|
* Gets a filename to version type mapping from config.
|
|
11972
11977
|
*/ function getVersionFilenameToTypeMap(config) {
|
|
@@ -16512,15 +16517,12 @@ function defaultExec(command, args, options) {
|
|
|
16512
16517
|
* File system implementation of instruction analysis gateway
|
|
16513
16518
|
*/ class FileSystemInstructionAnalysisGateway {
|
|
16514
16519
|
async analyzeCoverage(targetDir, scripts, tools) {
|
|
16515
|
-
// Find all instruction files
|
|
16516
16520
|
const instructionFiles = await this.findInstructionFiles(targetDir);
|
|
16517
|
-
// Read and search instruction content
|
|
16518
16521
|
const references = [];
|
|
16519
16522
|
const documentedTargets = new Set();
|
|
16520
16523
|
for (const file of instructionFiles){
|
|
16521
16524
|
const content = await readFile(file, "utf-8");
|
|
16522
16525
|
const lines = content.split("\n");
|
|
16523
|
-
// Check for script references (e.g., "npm test", "npm run build")
|
|
16524
16526
|
for (const script of scripts){
|
|
16525
16527
|
const scriptRefs = this.findReferencesInContent(script.name, content, lines, file, targetDir);
|
|
16526
16528
|
if (scriptRefs.length > 0) {
|
|
@@ -16528,7 +16530,6 @@ function defaultExec(command, args, options) {
|
|
|
16528
16530
|
documentedTargets.add(script.name);
|
|
16529
16531
|
}
|
|
16530
16532
|
}
|
|
16531
|
-
// Check for tool references (e.g., "mise run test", "biome check")
|
|
16532
16533
|
for (const tool of tools){
|
|
16533
16534
|
const toolRefs = this.findReferencesInContent(tool.name, content, lines, file, targetDir);
|
|
16534
16535
|
if (toolRefs.length > 0) {
|
|
@@ -16537,14 +16538,12 @@ function defaultExec(command, args, options) {
|
|
|
16537
16538
|
}
|
|
16538
16539
|
}
|
|
16539
16540
|
}
|
|
16540
|
-
// Filter mandatory scripts/tools
|
|
16541
16541
|
const mandatoryScripts = scripts.filter((s)=>s.isMandatory);
|
|
16542
16542
|
const mandatoryTools = tools.filter((t)=>t.isMandatory);
|
|
16543
16543
|
const allMandatory = [
|
|
16544
16544
|
...mandatoryScripts,
|
|
16545
16545
|
...mandatoryTools
|
|
16546
16546
|
];
|
|
16547
|
-
// Categorize as missing or documented
|
|
16548
16547
|
const missingInInstructions = allMandatory.filter((item)=>!documentedTargets.has(item.name));
|
|
16549
16548
|
const documentedInInstructions = allMandatory.filter((item)=>documentedTargets.has(item.name));
|
|
16550
16549
|
const totalMandatory = allMandatory.length;
|
|
@@ -16563,12 +16562,10 @@ function defaultExec(command, args, options) {
|
|
|
16563
16562
|
}
|
|
16564
16563
|
async findInstructionFiles(targetDir) {
|
|
16565
16564
|
const files = [];
|
|
16566
|
-
// Check for .github/copilot-instructions.md
|
|
16567
16565
|
const copilotInstructions = join(targetDir, ".github", "copilot-instructions.md");
|
|
16568
16566
|
if (await fileExists(copilotInstructions)) {
|
|
16569
16567
|
files.push(copilotInstructions);
|
|
16570
16568
|
}
|
|
16571
|
-
// Check for .github/instructions/*.md
|
|
16572
16569
|
const instructionsDir = join(targetDir, ".github", "instructions");
|
|
16573
16570
|
if (await fileExists(instructionsDir)) {
|
|
16574
16571
|
try {
|
|
@@ -16578,31 +16575,20 @@ function defaultExec(command, args, options) {
|
|
|
16578
16575
|
files.push(join(instructionsDir, file));
|
|
16579
16576
|
}
|
|
16580
16577
|
}
|
|
16581
|
-
} catch {
|
|
16582
|
-
// Skip directory if we can't read it (e.g., permissions issues)
|
|
16583
|
-
// Similar to how workflow parsing errors are handled
|
|
16584
|
-
}
|
|
16578
|
+
} catch {}
|
|
16585
16579
|
}
|
|
16586
16580
|
return files;
|
|
16587
16581
|
}
|
|
16588
16582
|
findReferencesInContent(target, content, lines, file, targetDir) {
|
|
16589
16583
|
const references = [];
|
|
16590
|
-
// Build a case-insensitive, word-boundary-aware pattern for the target.
|
|
16591
|
-
// This reduces false positives from simple substring matches like
|
|
16592
|
-
// "test" in "testing" or "latest", while still matching common
|
|
16593
|
-
// separators such as spaces, punctuation, etc.
|
|
16594
16584
|
const escapedTarget = target.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
16595
16585
|
const targetPattern = new RegExp(`(?:^|[^\\w])(${escapedTarget})(?=$|[^\\w])`, "i");
|
|
16596
|
-
// Fast path: skip line-by-line processing if the target pattern
|
|
16597
|
-
// never appears in the full content.
|
|
16598
16586
|
if (!targetPattern.test(content)) {
|
|
16599
16587
|
return references;
|
|
16600
16588
|
}
|
|
16601
|
-
// Find line numbers where target appears
|
|
16602
16589
|
for(let i = 0; i < lines.length; i++){
|
|
16603
16590
|
const line = lines[i];
|
|
16604
16591
|
if (targetPattern.test(line)) {
|
|
16605
|
-
// Get context (line before and after if available)
|
|
16606
16592
|
const contextLines = [];
|
|
16607
16593
|
if (i > 0) contextLines.push(lines[i - 1]);
|
|
16608
16594
|
contextLines.push(line);
|
|
@@ -18314,47 +18300,78 @@ const MAX_NPMRC_BYTES = 64 * 1024;
|
|
|
18314
18300
|
|
|
18315
18301
|
|
|
18316
18302
|
|
|
18303
|
+
|
|
18304
|
+
// 1 MB — covers even the largest real-world manifests
|
|
18305
|
+
const MAX_PACKAGE_JSON_BYTES = 1024 * 1024;
|
|
18306
|
+
const PackageJsonSchema = schemas_object({
|
|
18307
|
+
scripts: record(schemas_string(), schemas_string()).optional()
|
|
18308
|
+
});
|
|
18317
18309
|
/**
|
|
18318
18310
|
* File system implementation of script discovery gateway
|
|
18319
18311
|
*/ class FileSystemScriptDiscoveryGateway {
|
|
18312
|
+
constructor(logger){
|
|
18313
|
+
this.logger = logger ?? consola;
|
|
18314
|
+
}
|
|
18315
|
+
logger;
|
|
18320
18316
|
async discoverScripts(targetDir) {
|
|
18321
18317
|
const packageJsonPath = (0,external_node_path_.join)(targetDir, "package.json");
|
|
18322
|
-
|
|
18318
|
+
let content;
|
|
18319
|
+
try {
|
|
18320
|
+
content = await readFileNoFollow(packageJsonPath, MAX_PACKAGE_JSON_BYTES);
|
|
18321
|
+
} catch (error) {
|
|
18322
|
+
const code = error instanceof Error && "code" in error ? error.code : undefined;
|
|
18323
|
+
if (code !== "ENOENT") {
|
|
18324
|
+
this.logger.warn(`script-discovery: could not read ${JSON.stringify(packageJsonPath)}: ${JSON.stringify(error instanceof Error ? error.message : String(error))}`);
|
|
18325
|
+
}
|
|
18323
18326
|
return [];
|
|
18324
18327
|
}
|
|
18328
|
+
let parsed;
|
|
18325
18329
|
try {
|
|
18326
|
-
|
|
18327
|
-
|
|
18328
|
-
if (
|
|
18330
|
+
parsed = JSON.parse(content);
|
|
18331
|
+
} catch (e) {
|
|
18332
|
+
if (e instanceof SyntaxError) {
|
|
18333
|
+
this.logger.warn(`script-discovery: ${JSON.stringify(packageJsonPath)} contains invalid JSON — ${JSON.stringify(e.message)}`);
|
|
18329
18334
|
return [];
|
|
18330
18335
|
}
|
|
18331
|
-
|
|
18332
|
-
|
|
18333
|
-
|
|
18334
|
-
|
|
18335
|
-
|
|
18336
|
-
|
|
18337
|
-
|
|
18338
|
-
|
|
18339
|
-
isMandatory
|
|
18340
|
-
});
|
|
18341
|
-
}
|
|
18342
|
-
return scripts;
|
|
18343
|
-
} catch {
|
|
18344
|
-
// If package.json is malformed or cannot be parsed, return empty array
|
|
18336
|
+
throw e;
|
|
18337
|
+
}
|
|
18338
|
+
const parseResult = PackageJsonSchema.safeParse(parsed);
|
|
18339
|
+
if (!parseResult.success) {
|
|
18340
|
+
this.logger.warn(`script-discovery: ${JSON.stringify(packageJsonPath)} has an unexpected structure — scripts field must be a record of strings`);
|
|
18341
|
+
return [];
|
|
18342
|
+
}
|
|
18343
|
+
if (!parseResult.data.scripts) {
|
|
18345
18344
|
return [];
|
|
18346
18345
|
}
|
|
18346
|
+
const scripts = [];
|
|
18347
|
+
for (const [name, command] of Object.entries(parseResult.data.scripts)){
|
|
18348
|
+
const phase = feedback_loop_determineScriptPhase(name, command);
|
|
18349
|
+
const isMandatory = feedback_loop_isScriptMandatory(phase);
|
|
18350
|
+
scripts.push({
|
|
18351
|
+
name,
|
|
18352
|
+
command,
|
|
18353
|
+
phase,
|
|
18354
|
+
isMandatory
|
|
18355
|
+
});
|
|
18356
|
+
}
|
|
18357
|
+
return scripts;
|
|
18347
18358
|
}
|
|
18348
18359
|
}
|
|
18349
18360
|
/**
|
|
18350
18361
|
* Creates and returns the default script discovery gateway
|
|
18351
|
-
*/ function createScriptDiscoveryGateway() {
|
|
18352
|
-
return new FileSystemScriptDiscoveryGateway();
|
|
18362
|
+
*/ function createScriptDiscoveryGateway(logger) {
|
|
18363
|
+
return new FileSystemScriptDiscoveryGateway(logger);
|
|
18353
18364
|
}
|
|
18354
18365
|
/**
|
|
18355
18366
|
* Creates a FeedbackLoopCommandsGateway that discovers mandatory commands from package.json scripts.
|
|
18356
|
-
|
|
18357
|
-
|
|
18367
|
+
*
|
|
18368
|
+
* @param scriptGateway - Optional gateway implementation. If omitted, a default
|
|
18369
|
+
* `FileSystemScriptDiscoveryGateway` is created using `logger`.
|
|
18370
|
+
* @param logger - Optional logger for the default gateway. Only used when
|
|
18371
|
+
* `scriptGateway` is omitted; if a custom `scriptGateway` is supplied, its
|
|
18372
|
+
* own logger configuration applies and this parameter is ignored.
|
|
18373
|
+
*/ function createFeedbackLoopCommandsGateway(scriptGateway, logger) {
|
|
18374
|
+
const gateway = scriptGateway ?? createScriptDiscoveryGateway(logger);
|
|
18358
18375
|
return {
|
|
18359
18376
|
async getMandatoryCommands (targetDir) {
|
|
18360
18377
|
const scripts = await gateway.discoverScripts(targetDir);
|
|
@@ -18573,9 +18590,7 @@ var dist = __webpack_require__(3519);
|
|
|
18573
18590
|
const workflow = parseYaml(content);
|
|
18574
18591
|
const tools = this.extractToolsFromWorkflow(workflow, file);
|
|
18575
18592
|
allTools.push(...tools);
|
|
18576
|
-
} catch {
|
|
18577
|
-
// Skip files that can't be parsed as valid YAML
|
|
18578
|
-
}
|
|
18593
|
+
} catch {}
|
|
18579
18594
|
}
|
|
18580
18595
|
return this.deduplicateTools(allTools);
|
|
18581
18596
|
}
|
|
@@ -18603,7 +18618,6 @@ var dist = __webpack_require__(3519);
|
|
|
18603
18618
|
const stepObj = step;
|
|
18604
18619
|
const run = stepObj.run;
|
|
18605
18620
|
if (typeof run === "string") {
|
|
18606
|
-
// Extract tools from run commands
|
|
18607
18621
|
const extractedTools = this.extractToolsFromRunCommand(run, sourceFile);
|
|
18608
18622
|
tools.push(...extractedTools);
|
|
18609
18623
|
}
|
|
@@ -18613,35 +18627,24 @@ var dist = __webpack_require__(3519);
|
|
|
18613
18627
|
}
|
|
18614
18628
|
extractToolsFromRunCommand(runCommand, sourceFile) {
|
|
18615
18629
|
const tools = [];
|
|
18616
|
-
// Split by newlines and pipe tokens with surrounding whitespace to handle
|
|
18617
|
-
// multi-line and piped commands without breaking on constructs like "cmd || true"
|
|
18618
18630
|
const commands = runCommand.split(/\n|\s\|\s/).map((c)=>c.trim()).filter((c)=>c.length > 0 && !c.startsWith("#"));
|
|
18619
18631
|
for (const command of commands){
|
|
18620
|
-
// Extract the base command (first word)
|
|
18621
18632
|
const parts = command.split(/\s+/);
|
|
18622
18633
|
const baseCommand = parts[0];
|
|
18623
|
-
// Skip shell built-ins and common utilities
|
|
18624
18634
|
if (this.isShellBuiltin(baseCommand)) {
|
|
18625
18635
|
continue;
|
|
18626
18636
|
}
|
|
18627
|
-
// Determine tool name and full command
|
|
18628
18637
|
let toolName;
|
|
18629
18638
|
const fullCommand = command;
|
|
18630
|
-
// Handle special cases like "npm run", "mise run", etc.
|
|
18631
18639
|
if (parts.length >= 2 && (baseCommand === "npm" || baseCommand === "mise") && parts[1] === "run") {
|
|
18632
18640
|
if (parts.length >= 3 && parts[2]) {
|
|
18633
|
-
// "npm run test" -> name: "npm run test"
|
|
18634
18641
|
toolName = parts.slice(0, 3).join(" ");
|
|
18635
18642
|
} else {
|
|
18636
|
-
// Handle commands like "npm run" without a script name
|
|
18637
18643
|
toolName = parts.slice(0, 2).join(" ");
|
|
18638
18644
|
}
|
|
18639
18645
|
} else if (parts.length >= 2) {
|
|
18640
|
-
// For most tools, include the subcommand for better specificity
|
|
18641
|
-
// e.g., "npm test", "npx biome", "pnpm lint"
|
|
18642
18646
|
toolName = parts.slice(0, 2).join(" ");
|
|
18643
18647
|
} else {
|
|
18644
|
-
// Fallback to the base command if no subcommand is present
|
|
18645
18648
|
toolName = baseCommand;
|
|
18646
18649
|
}
|
|
18647
18650
|
const phase = this.determineToolPhase(toolName, fullCommand);
|
|
@@ -18680,13 +18683,11 @@ var dist = __webpack_require__(3519);
|
|
|
18680
18683
|
return builtins.includes(command);
|
|
18681
18684
|
}
|
|
18682
18685
|
determineToolPhase(toolName, fullCommand) {
|
|
18683
|
-
// Use the same logic as script phase determination
|
|
18684
18686
|
return determineScriptPhase(toolName, fullCommand);
|
|
18685
18687
|
}
|
|
18686
18688
|
deduplicateTools(tools) {
|
|
18687
18689
|
const seen = new Map();
|
|
18688
18690
|
for (const tool of tools){
|
|
18689
|
-
// Use full command as key for deduplication
|
|
18690
18691
|
const key = tool.fullCommand;
|
|
18691
18692
|
if (!seen.has(key)) {
|
|
18692
18693
|
seen.set(key, tool);
|
|
@@ -18943,9 +18944,7 @@ class FileSystemWorkflowGateway {
|
|
|
18943
18944
|
const workflow = (0,dist/* .parse */.qg)(content);
|
|
18944
18945
|
const candidates = extractSetupStepsFromWorkflow(workflow, config.setupActionPatterns);
|
|
18945
18946
|
allCandidates.push(...candidates);
|
|
18946
|
-
} catch {
|
|
18947
|
-
// Skip unreadable or malformed YAML workflow files while continuing scan.
|
|
18948
|
-
}
|
|
18947
|
+
} catch {}
|
|
18949
18948
|
}
|
|
18950
18949
|
return deduplicateCandidates(allCandidates);
|
|
18951
18950
|
}
|
|
@@ -18982,8 +18981,7 @@ function createWorkflowGateway(cwd) {
|
|
|
18982
18981
|
;// CONCATENATED MODULE: ../core/src/gateways/workflow-gateway.ts
|
|
18983
18982
|
/**
|
|
18984
18983
|
* Gateway interface for GitHub Actions workflow operations.
|
|
18985
|
-
*/
|
|
18986
|
-
|
|
18984
|
+
*/
|
|
18987
18985
|
|
|
18988
18986
|
;// CONCATENATED MODULE: ../core/src/gateways/index.ts
|
|
18989
18987
|
/**
|
|
@@ -19169,7 +19167,6 @@ function isCopilotCodeScanningRule(rule) {
|
|
|
19169
19167
|
* This module handles the logic of determining which GitHub Actions
|
|
19170
19168
|
* setup steps should be added based on detected version files and package managers.
|
|
19171
19169
|
*/
|
|
19172
|
-
|
|
19173
19170
|
/**
|
|
19174
19171
|
* Creates an ActionVersionPort backed by a static version map.
|
|
19175
19172
|
*/ function createActionVersionPort(versionMap) {
|
|
@@ -42031,16 +42028,14 @@ function hasFrontmatterDelimiters(content) {
|
|
|
42031
42028
|
return false;
|
|
42032
42029
|
}
|
|
42033
42030
|
|
|
42034
|
-
;// CONCATENATED MODULE: ../lint/src/
|
|
42031
|
+
;// CONCATENATED MODULE: ../lint/src/lint-errors.ts
|
|
42035
42032
|
/**
|
|
42036
|
-
*
|
|
42033
|
+
* Public lint API error types.
|
|
42037
42034
|
*
|
|
42038
|
-
*
|
|
42039
|
-
*
|
|
42040
|
-
*
|
|
42041
|
-
*/
|
|
42042
|
-
|
|
42043
|
-
/**
|
|
42035
|
+
* Kept separate from filesystem-backed validation internals so the public
|
|
42036
|
+
* package barrel can export stable error contracts without depending on
|
|
42037
|
+
* implementation modules.
|
|
42038
|
+
*/ /**
|
|
42044
42039
|
* Thrown when user-supplied directory input fails validation.
|
|
42045
42040
|
*
|
|
42046
42041
|
* Consumers can catch this type to distinguish user-input errors
|
|
@@ -42051,6 +42046,17 @@ function hasFrontmatterDelimiters(content) {
|
|
|
42051
42046
|
this.name = "LintValidationError";
|
|
42052
42047
|
}
|
|
42053
42048
|
}
|
|
42049
|
+
|
|
42050
|
+
;// CONCATENATED MODULE: ../lint/src/validate-directory.ts
|
|
42051
|
+
/**
|
|
42052
|
+
* Directory path validation for the public lint API.
|
|
42053
|
+
*
|
|
42054
|
+
* Validates user-supplied directory paths by rejecting unsafe inputs
|
|
42055
|
+
* (control characters, path traversal, null bytes) and canonicalizing
|
|
42056
|
+
* the path via `realpath()` for cross-platform compatibility.
|
|
42057
|
+
*/
|
|
42058
|
+
|
|
42059
|
+
|
|
42054
42060
|
function isControlCharacter(code) {
|
|
42055
42061
|
if (code >= 0x00 && code <= 0x1f) return true;
|
|
42056
42062
|
if (code === 0x7f) return true;
|
|
@@ -42071,8 +42077,17 @@ function containsControlCharacters(value) {
|
|
|
42071
42077
|
function sanitizeForErrorMessage(value) {
|
|
42072
42078
|
return JSON.stringify(value);
|
|
42073
42079
|
}
|
|
42074
|
-
|
|
42075
|
-
|
|
42080
|
+
/**
|
|
42081
|
+
* Detects path traversal segments in a user-supplied directory string.
|
|
42082
|
+
*
|
|
42083
|
+
* On Windows, both '/' and '\' are path separators, so the check splits on
|
|
42084
|
+
* both. On POSIX, '\' is a valid filename character (not a separator), so only
|
|
42085
|
+
* '/' is used as the split boundary to avoid false-rejecting legitimate paths
|
|
42086
|
+
* whose names contain backslashes. Any `platform` value other than `'win32'`
|
|
42087
|
+
* is treated as POSIX.
|
|
42088
|
+
*/ function hasPathTraversalSegment(directory, platform = process.platform) {
|
|
42089
|
+
const separator = platform === "win32" ? /[\\/]/ : "/";
|
|
42090
|
+
return directory.split(separator).includes("..");
|
|
42076
42091
|
}
|
|
42077
42092
|
/**
|
|
42078
42093
|
* Validates a user-supplied directory path for safety and existence.
|
|
@@ -42083,9 +42098,14 @@ function hasPathTraversalSegment(directory) {
|
|
|
42083
42098
|
* the canonicalized absolute path (all symlinks resolved) so downstream
|
|
42084
42099
|
* code always operates on real paths.
|
|
42085
42100
|
*
|
|
42101
|
+
* @param directory - The path to validate.
|
|
42102
|
+
* @param platform - The platform identifier used for path-separator detection.
|
|
42103
|
+
* Defaults to `process.platform`. Only `'win32'` uses `\` as a separator;
|
|
42104
|
+
* all other values are treated as POSIX. Overridable for cross-platform unit
|
|
42105
|
+
* tests so that both branches can be exercised on any host OS.
|
|
42086
42106
|
* @throws {LintValidationError} If the path is empty, contains control
|
|
42087
42107
|
* characters, traversal segments, does not exist, or is not a directory.
|
|
42088
|
-
*/ async function validateDirectory(directory) {
|
|
42108
|
+
*/ async function validateDirectory(directory, platform = process.platform) {
|
|
42089
42109
|
if (directory.length === 0) {
|
|
42090
42110
|
throw new LintValidationError("directory must not be empty");
|
|
42091
42111
|
}
|
|
@@ -42093,7 +42113,7 @@ function hasPathTraversalSegment(directory) {
|
|
|
42093
42113
|
if (containsControlCharacters(directory)) {
|
|
42094
42114
|
throw new LintValidationError(`Invalid directory path (contains control characters): ${safeDir}`);
|
|
42095
42115
|
}
|
|
42096
|
-
if (hasPathTraversalSegment(directory)) {
|
|
42116
|
+
if (hasPathTraversalSegment(directory, platform)) {
|
|
42097
42117
|
throw new LintValidationError(`Invalid directory path (path traversal detected): ${safeDir}`);
|
|
42098
42118
|
}
|
|
42099
42119
|
const resolved = (0,external_node_path_.resolve)(directory);
|
|
@@ -42147,6 +42167,7 @@ function hasPathTraversalSegment(directory) {
|
|
|
42147
42167
|
|
|
42148
42168
|
|
|
42149
42169
|
|
|
42170
|
+
|
|
42150
42171
|
const LintTargetsSchema = schemas_object({
|
|
42151
42172
|
skills: schemas_boolean().optional(),
|
|
42152
42173
|
agents: schemas_boolean().optional(),
|
|
@@ -42155,7 +42176,14 @@ const LintTargetsSchema = schemas_object({
|
|
|
42155
42176
|
}).strict().optional();
|
|
42156
42177
|
const LintOptionsSchema = schemas_object({
|
|
42157
42178
|
directory: schemas_string().min(1, "directory must not be empty"),
|
|
42158
|
-
targets: LintTargetsSchema
|
|
42179
|
+
targets: LintTargetsSchema,
|
|
42180
|
+
// logger is a runtime object — `z.custom` validates its structural contract
|
|
42181
|
+
// at the boundary; TypeScript enforces it further at compile time.
|
|
42182
|
+
// `v === undefined` is NOT needed here: ZodOptional intercepts undefined
|
|
42183
|
+
// before the predicate is invoked, so the guard would be dead code.
|
|
42184
|
+
logger: custom((v)=>v !== null && typeof v === "object" && typeof v.warn === "function", {
|
|
42185
|
+
message: "logger must be an object with a .warn method"
|
|
42186
|
+
}).optional()
|
|
42159
42187
|
}).strict();
|
|
42160
42188
|
/** Converts a use-case lint output to the unified LintOutput shape. */ function toLintOutput(output, target, totalFiles) {
|
|
42161
42189
|
const diagnostics = [];
|
|
@@ -42208,10 +42236,10 @@ async function lintHooks(targetDir) {
|
|
|
42208
42236
|
});
|
|
42209
42237
|
return toLintOutput(output, "hook", output.totalFiles);
|
|
42210
42238
|
}
|
|
42211
|
-
async function lintInstructions(targetDir) {
|
|
42239
|
+
async function lintInstructions(targetDir, logger) {
|
|
42212
42240
|
const discoveryGateway = createInstructionFileDiscoveryGateway();
|
|
42213
42241
|
const astGateway = createMarkdownAstGateway();
|
|
42214
|
-
const commandsGateway = createFeedbackLoopCommandsGateway();
|
|
42242
|
+
const commandsGateway = createFeedbackLoopCommandsGateway(undefined, logger);
|
|
42215
42243
|
const useCase = new AnalyzeInstructionQualityUseCase(discoveryGateway, astGateway, commandsGateway);
|
|
42216
42244
|
const output = await useCase.execute({
|
|
42217
42245
|
targetDir
|
|
@@ -42230,24 +42258,6 @@ async function lintInstructions(targetDir) {
|
|
|
42230
42258
|
}
|
|
42231
42259
|
};
|
|
42232
42260
|
}
|
|
42233
|
-
const LINT_TARGETS = [
|
|
42234
|
-
{
|
|
42235
|
-
key: "skills",
|
|
42236
|
-
execute: lintSkills
|
|
42237
|
-
},
|
|
42238
|
-
{
|
|
42239
|
-
key: "agents",
|
|
42240
|
-
execute: lintAgents
|
|
42241
|
-
},
|
|
42242
|
-
{
|
|
42243
|
-
key: "hooks",
|
|
42244
|
-
execute: lintHooks
|
|
42245
|
-
},
|
|
42246
|
-
{
|
|
42247
|
-
key: "instructions",
|
|
42248
|
-
execute: lintInstructions
|
|
42249
|
-
}
|
|
42250
|
-
];
|
|
42251
42261
|
function isTargetEnabled(key, targets) {
|
|
42252
42262
|
if (!targets) return true;
|
|
42253
42263
|
const hasAnyEnabled = Object.values(targets).some(Boolean);
|
|
@@ -42291,7 +42301,25 @@ function isTargetEnabled(key, targets) {
|
|
|
42291
42301
|
}
|
|
42292
42302
|
throw error;
|
|
42293
42303
|
}
|
|
42294
|
-
const
|
|
42304
|
+
const lintTargets = [
|
|
42305
|
+
{
|
|
42306
|
+
key: "skills",
|
|
42307
|
+
execute: lintSkills
|
|
42308
|
+
},
|
|
42309
|
+
{
|
|
42310
|
+
key: "agents",
|
|
42311
|
+
execute: lintAgents
|
|
42312
|
+
},
|
|
42313
|
+
{
|
|
42314
|
+
key: "hooks",
|
|
42315
|
+
execute: lintHooks
|
|
42316
|
+
},
|
|
42317
|
+
{
|
|
42318
|
+
key: "instructions",
|
|
42319
|
+
execute: (dir)=>lintInstructions(dir, parsed.logger)
|
|
42320
|
+
}
|
|
42321
|
+
];
|
|
42322
|
+
const enabledTargets = lintTargets.filter((t)=>isTargetEnabled(t.key, parsed.targets));
|
|
42295
42323
|
const outputs = [];
|
|
42296
42324
|
for (const target of enabledTargets){
|
|
42297
42325
|
const rawOutput = await target.execute(targetDir);
|
|
@@ -42321,9 +42349,7 @@ function isTargetEnabled(key, targets) {
|
|
|
42321
42349
|
* console.error(formatter.format(result.outputs));
|
|
42322
42350
|
* }
|
|
42323
42351
|
* ```
|
|
42324
|
-
*/
|
|
42325
|
-
|
|
42326
|
-
// ── Output formatters ────────────────────────────────────────────────
|
|
42352
|
+
*/
|
|
42327
42353
|
|
|
42328
42354
|
|
|
42329
42355
|
|
|
@@ -42574,7 +42600,6 @@ You are a ${normalizedName} agent specialized in {domain/responsibility}.
|
|
|
42574
42600
|
* @param agentName The name of the agent to create
|
|
42575
42601
|
* @returns Result of the operation
|
|
42576
42602
|
*/ async execute(targetDir, agentName) {
|
|
42577
|
-
// Validate the agent name using Zod schema
|
|
42578
42603
|
const validationResult = AgentNameSchema.safeParse(agentName);
|
|
42579
42604
|
if (!validationResult.success) {
|
|
42580
42605
|
const errorMessage = validationResult.error.issues[0]?.message ?? "Invalid agent name";
|
|
@@ -42583,18 +42608,14 @@ You are a ${normalizedName} agent specialized in {domain/responsibility}.
|
|
|
42583
42608
|
error: errorMessage
|
|
42584
42609
|
};
|
|
42585
42610
|
}
|
|
42586
|
-
// Normalize the agent name
|
|
42587
42611
|
const normalizedName = normalizeAgentName(validationResult.data);
|
|
42588
|
-
// Validate that the normalized name is not empty (handles whitespace-only input)
|
|
42589
42612
|
if (!normalizedName) {
|
|
42590
42613
|
return {
|
|
42591
42614
|
success: false,
|
|
42592
42615
|
error: "Agent name is required"
|
|
42593
42616
|
};
|
|
42594
42617
|
}
|
|
42595
|
-
// Get the file path
|
|
42596
42618
|
const filePath = this.gateway.getAgentFilePath(targetDir, normalizedName);
|
|
42597
|
-
// Check if the file already exists
|
|
42598
42619
|
if (await this.gateway.agentFileExists(targetDir, normalizedName)) {
|
|
42599
42620
|
return {
|
|
42600
42621
|
success: false,
|
|
@@ -42602,11 +42623,8 @@ You are a ${normalizedName} agent specialized in {domain/responsibility}.
|
|
|
42602
42623
|
filePath
|
|
42603
42624
|
};
|
|
42604
42625
|
}
|
|
42605
|
-
// Ensure the directory exists
|
|
42606
42626
|
await this.gateway.ensureAgentsDirectory(targetDir);
|
|
42607
|
-
// Generate the content
|
|
42608
42627
|
const content = generateAgentContent(normalizedName);
|
|
42609
|
-
// Write the file
|
|
42610
42628
|
await this.gateway.writeAgentFile(targetDir, normalizedName, content);
|
|
42611
42629
|
return {
|
|
42612
42630
|
success: true,
|
|
@@ -42702,7 +42720,6 @@ Copilot should use this skill when:
|
|
|
42702
42720
|
* @param skillName The name of the skill to create
|
|
42703
42721
|
* @returns Result of the operation
|
|
42704
42722
|
*/ async execute(targetDir, skillName) {
|
|
42705
|
-
// Validate the skill name using Zod schema
|
|
42706
42723
|
const validationResult = SkillNameSchema.safeParse(skillName);
|
|
42707
42724
|
if (!validationResult.success) {
|
|
42708
42725
|
const errorMessage = validationResult.error.issues[0]?.message ?? "Invalid skill name";
|
|
@@ -42711,19 +42728,15 @@ Copilot should use this skill when:
|
|
|
42711
42728
|
error: errorMessage
|
|
42712
42729
|
};
|
|
42713
42730
|
}
|
|
42714
|
-
// Normalize the skill name
|
|
42715
42731
|
const normalizedName = normalizeSkillName(validationResult.data);
|
|
42716
|
-
// Validate that the normalized name is not empty (handles whitespace-only input)
|
|
42717
42732
|
if (!normalizedName) {
|
|
42718
42733
|
return {
|
|
42719
42734
|
success: false,
|
|
42720
42735
|
error: "Skill name is required"
|
|
42721
42736
|
};
|
|
42722
42737
|
}
|
|
42723
|
-
// Get the paths
|
|
42724
42738
|
const skillDirectoryPath = this.gateway.getSkillDirectoryPath(targetDir, normalizedName);
|
|
42725
42739
|
const skillFilePath = this.gateway.getSkillFilePath(targetDir, normalizedName);
|
|
42726
|
-
// Check if the skill directory already exists
|
|
42727
42740
|
if (await this.gateway.skillDirectoryExists(targetDir, normalizedName)) {
|
|
42728
42741
|
return {
|
|
42729
42742
|
success: false,
|
|
@@ -42731,11 +42744,8 @@ Copilot should use this skill when:
|
|
|
42731
42744
|
skillDirectoryPath
|
|
42732
42745
|
};
|
|
42733
42746
|
}
|
|
42734
|
-
// Ensure the skill directory exists
|
|
42735
42747
|
await this.gateway.ensureSkillDirectory(targetDir, normalizedName);
|
|
42736
|
-
// Generate the content
|
|
42737
42748
|
const content = generateSkillContent(normalizedName);
|
|
42738
|
-
// Write the SKILL.md file
|
|
42739
42749
|
await this.gateway.writeSkillFile(targetDir, normalizedName, content);
|
|
42740
42750
|
return {
|
|
42741
42751
|
success: true,
|
|
@@ -51678,4 +51688,4 @@ if (installedChunkData !== 0) { // 0 means "already installed".'
|
|
|
51678
51688
|
// module factories are used so entry inlining is disabled
|
|
51679
51689
|
// startup
|
|
51680
51690
|
// Load entry module and return exports
|
|
51681
|
-
var __webpack_exports__ = __webpack_require__(
|
|
51691
|
+
var __webpack_exports__ = __webpack_require__(2091);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lousy-agents/cli",
|
|
3
|
-
"version": "5.13.
|
|
3
|
+
"version": "5.13.2",
|
|
4
4
|
"description": "CLI scaffolding tool that sets up projects with structure, instructions, and feedback loops for AI coding assistants",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"citty": "0.2.2",
|
|
46
46
|
"consola": "3.4.2",
|
|
47
47
|
"eta": "4.6.0",
|
|
48
|
-
"zod": "4.4.
|
|
48
|
+
"zod": "4.4.3"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@lousy-agents/core": "*",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
"ghcr.io/devcontainers/features/copilot-cli:1.0.0": {},
|
|
12
12
|
"ghcr.io/anthropics/devcontainer-features/claude-code:1": {
|
|
13
|
-
"version": "v2.1.
|
|
13
|
+
"version": "v2.1.131"
|
|
14
14
|
},
|
|
15
15
|
"ghcr.io/rocker-org/devcontainer-features/apt-packages:1.0.2": {
|
|
16
16
|
"packages": "libnss3, libnspr4, libatk1.0-0t64, libatk-bridge2.0-0t64, libcups2t64, libdrm2, libdbus-1-3, libatspi2.0-0t64, libxcomposite1, libxdamage1, libxfixes3, libxrandr2, libgbm1, libxkbcommon0, libasound2t64, yamllint, shellcheck",
|
|
@@ -17,20 +17,20 @@
|
|
|
17
17
|
"@mui/material": "9.0.0",
|
|
18
18
|
"@mui/material-nextjs": "9.0.0",
|
|
19
19
|
"next": "16.2.4",
|
|
20
|
-
"react": "19.2.
|
|
21
|
-
"react-dom": "19.2.
|
|
20
|
+
"react": "19.2.6",
|
|
21
|
+
"react-dom": "19.2.6"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@biomejs/biome": "2.4.14",
|
|
25
25
|
"@eslint/eslintrc": "3.3.5",
|
|
26
|
-
"@lousy-agents/mcp": "5.
|
|
26
|
+
"@lousy-agents/mcp": "5.13.1",
|
|
27
27
|
"@modelcontextprotocol/server-sequential-thinking": "2025.12.18",
|
|
28
28
|
"@testing-library/jest-dom": "6.9.1",
|
|
29
29
|
"@testing-library/react": "16.3.2",
|
|
30
30
|
"@types/node": "24.12.2",
|
|
31
31
|
"@types/react": "19.2.14",
|
|
32
32
|
"@types/react-dom": "19.2.3",
|
|
33
|
-
"@upstash/context7-mcp": "2.2.
|
|
33
|
+
"@upstash/context7-mcp": "2.2.4",
|
|
34
34
|
"@vitejs/plugin-react": "6.0.1",
|
|
35
35
|
"@vitest/ui": "4.1.5",
|
|
36
36
|
"eslint": "10.3.0",
|