@triedotdev/mcp 1.0.168 → 1.0.170
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 +54 -500
- package/dist/chunk-2YXOBNKW.js +619 -0
- package/dist/chunk-2YXOBNKW.js.map +1 -0
- package/dist/chunk-QR64Y5TI.js +363 -0
- package/dist/chunk-QR64Y5TI.js.map +1 -0
- package/dist/cli/main.d.ts +0 -15
- package/dist/cli/main.js +356 -3100
- package/dist/cli/main.js.map +1 -1
- package/dist/index.js +2 -36
- package/dist/index.js.map +1 -1
- package/dist/server/mcp-server.js +2 -36
- package/package.json +8 -31
- package/dist/autonomy-config-FSERX3O3.js +0 -30
- package/dist/autonomy-config-FSERX3O3.js.map +0 -1
- package/dist/chat-store-JNGNTDSN.js +0 -15
- package/dist/chat-store-JNGNTDSN.js.map +0 -1
- package/dist/chunk-2HF65EHQ.js +0 -311
- package/dist/chunk-2HF65EHQ.js.map +0 -1
- package/dist/chunk-43X6JBEM.js +0 -36
- package/dist/chunk-43X6JBEM.js.map +0 -1
- package/dist/chunk-4MXH2ZPT.js +0 -1827
- package/dist/chunk-4MXH2ZPT.js.map +0 -1
- package/dist/chunk-575YT2SD.js +0 -737
- package/dist/chunk-575YT2SD.js.map +0 -1
- package/dist/chunk-5BRRRTN6.js +0 -354
- package/dist/chunk-5BRRRTN6.js.map +0 -1
- package/dist/chunk-6NLHFIYA.js +0 -344
- package/dist/chunk-6NLHFIYA.js.map +0 -1
- package/dist/chunk-7WITSO22.js +0 -824
- package/dist/chunk-7WITSO22.js.map +0 -1
- package/dist/chunk-DGUM43GV.js +0 -11
- package/dist/chunk-DGUM43GV.js.map +0 -1
- package/dist/chunk-EFWVF6TI.js +0 -267
- package/dist/chunk-EFWVF6TI.js.map +0 -1
- package/dist/chunk-F6WFNUAY.js +0 -216
- package/dist/chunk-F6WFNUAY.js.map +0 -1
- package/dist/chunk-FQ45QP5A.js +0 -361
- package/dist/chunk-FQ45QP5A.js.map +0 -1
- package/dist/chunk-G2TGF6TR.js +0 -573
- package/dist/chunk-G2TGF6TR.js.map +0 -1
- package/dist/chunk-GTKYBOXL.js +0 -700
- package/dist/chunk-GTKYBOXL.js.map +0 -1
- package/dist/chunk-HVCDY3AK.js +0 -850
- package/dist/chunk-HVCDY3AK.js.map +0 -1
- package/dist/chunk-JVMBCWKS.js +0 -348
- package/dist/chunk-JVMBCWKS.js.map +0 -1
- package/dist/chunk-KDHN2ZQE.js +0 -313
- package/dist/chunk-KDHN2ZQE.js.map +0 -1
- package/dist/chunk-LQIMKE3P.js +0 -12524
- package/dist/chunk-LQIMKE3P.js.map +0 -1
- package/dist/chunk-ME2OERF5.js +0 -345
- package/dist/chunk-ME2OERF5.js.map +0 -1
- package/dist/chunk-MRHKX5M5.js +0 -662
- package/dist/chunk-MRHKX5M5.js.map +0 -1
- package/dist/chunk-OBQ74FOU.js +0 -27
- package/dist/chunk-OBQ74FOU.js.map +0 -1
- package/dist/chunk-OMR4YCBS.js +0 -987
- package/dist/chunk-OMR4YCBS.js.map +0 -1
- package/dist/chunk-Q5EKA5YA.js +0 -254
- package/dist/chunk-Q5EKA5YA.js.map +0 -1
- package/dist/chunk-Q63FFI6D.js +0 -132
- package/dist/chunk-Q63FFI6D.js.map +0 -1
- package/dist/chunk-SY6KQG44.js +0 -983
- package/dist/chunk-SY6KQG44.js.map +0 -1
- package/dist/chunk-T63OHG4Q.js +0 -440
- package/dist/chunk-T63OHG4Q.js.map +0 -1
- package/dist/chunk-TN5WEKWI.js +0 -173
- package/dist/chunk-TN5WEKWI.js.map +0 -1
- package/dist/chunk-VUL52BQL.js +0 -402
- package/dist/chunk-VUL52BQL.js.map +0 -1
- package/dist/chunk-VVITXIHN.js +0 -189
- package/dist/chunk-VVITXIHN.js.map +0 -1
- package/dist/chunk-WCN7S3EI.js +0 -14
- package/dist/chunk-WCN7S3EI.js.map +0 -1
- package/dist/chunk-XE6KQRKZ.js +0 -816
- package/dist/chunk-XE6KQRKZ.js.map +0 -1
- package/dist/chunk-XPZZFPBZ.js +0 -491
- package/dist/chunk-XPZZFPBZ.js.map +0 -1
- package/dist/chunk-XTFWT2XM.js +0 -727
- package/dist/chunk-XTFWT2XM.js.map +0 -1
- package/dist/chunk-YDHUCDHM.js +0 -4011
- package/dist/chunk-YDHUCDHM.js.map +0 -1
- package/dist/chunk-YZ6Y2H3P.js +0 -1289
- package/dist/chunk-YZ6Y2H3P.js.map +0 -1
- package/dist/chunk-ZJF5FTBX.js +0 -1396
- package/dist/chunk-ZJF5FTBX.js.map +0 -1
- package/dist/chunk-ZV2K6M7T.js +0 -74
- package/dist/chunk-ZV2K6M7T.js.map +0 -1
- package/dist/cli/create-agent.d.ts +0 -1
- package/dist/cli/create-agent.js +0 -1050
- package/dist/cli/create-agent.js.map +0 -1
- package/dist/cli/yolo-daemon.d.ts +0 -1
- package/dist/cli/yolo-daemon.js +0 -423
- package/dist/cli/yolo-daemon.js.map +0 -1
- package/dist/client-NJPZE5JT.js +0 -28
- package/dist/client-NJPZE5JT.js.map +0 -1
- package/dist/codebase-index-VAPF32XX.js +0 -12
- package/dist/codebase-index-VAPF32XX.js.map +0 -1
- package/dist/fast-analyzer-XXYMOXRK.js +0 -216
- package/dist/fast-analyzer-XXYMOXRK.js.map +0 -1
- package/dist/git-EO5SRFMN.js +0 -28
- package/dist/git-EO5SRFMN.js.map +0 -1
- package/dist/github-ingester-ZOKK6GRS.js +0 -11
- package/dist/github-ingester-ZOKK6GRS.js.map +0 -1
- package/dist/goal-manager-YOB7VWK7.js +0 -25
- package/dist/goal-manager-YOB7VWK7.js.map +0 -1
- package/dist/goal-validator-ULKIBDPX.js +0 -24
- package/dist/goal-validator-ULKIBDPX.js.map +0 -1
- package/dist/graph-B3NA4S7I.js +0 -10
- package/dist/graph-B3NA4S7I.js.map +0 -1
- package/dist/hypothesis-7BFFT5JY.js +0 -23
- package/dist/hypothesis-7BFFT5JY.js.map +0 -1
- package/dist/incident-index-EFNUSGWL.js +0 -11
- package/dist/incident-index-EFNUSGWL.js.map +0 -1
- package/dist/insight-store-EC4PLSAW.js +0 -22
- package/dist/insight-store-EC4PLSAW.js.map +0 -1
- package/dist/issue-store-ZIRP23EP.js +0 -36
- package/dist/issue-store-ZIRP23EP.js.map +0 -1
- package/dist/ledger-TWZTGDFA.js +0 -58
- package/dist/ledger-TWZTGDFA.js.map +0 -1
- package/dist/linear-ingester-XXPAZZRW.js +0 -11
- package/dist/linear-ingester-XXPAZZRW.js.map +0 -1
- package/dist/output-manager-RVJ37XKA.js +0 -13
- package/dist/output-manager-RVJ37XKA.js.map +0 -1
- package/dist/parse-goal-violation-SACGFG3C.js +0 -8
- package/dist/parse-goal-violation-SACGFG3C.js.map +0 -1
- package/dist/pattern-discovery-F7LU5K6E.js +0 -8
- package/dist/pattern-discovery-F7LU5K6E.js.map +0 -1
- package/dist/progress-SRQ2V3BP.js +0 -18
- package/dist/progress-SRQ2V3BP.js.map +0 -1
- package/dist/project-state-AHPA77SM.js +0 -28
- package/dist/project-state-AHPA77SM.js.map +0 -1
- package/dist/sync-M2FSWPBC.js +0 -12
- package/dist/sync-M2FSWPBC.js.map +0 -1
- package/dist/terminal-spawn-5YXDMUCF.js +0 -157
- package/dist/terminal-spawn-5YXDMUCF.js.map +0 -1
- package/dist/tiered-storage-Z3YCR465.js +0 -12
- package/dist/tiered-storage-Z3YCR465.js.map +0 -1
- package/dist/trie-agent-3YDPEGHJ.js +0 -28
- package/dist/trie-agent-3YDPEGHJ.js.map +0 -1
- package/dist/ui/chat.html +0 -1014
- package/dist/ui/goals.html +0 -967
- package/dist/ui/hypotheses.html +0 -1011
- package/dist/ui/ledger.html +0 -954
- package/dist/ui/nudges.html +0 -995
- package/dist/vibe-code-signatures-F6URTBW3.js +0 -16
- package/dist/vibe-code-signatures-F6URTBW3.js.map +0 -1
- package/dist/vulnerability-signatures-T7SKHORW.js +0 -18
- package/dist/vulnerability-signatures-T7SKHORW.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,42 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
startServer
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-HVCDY3AK.js";
|
|
7
|
-
import "./chunk-Q63FFI6D.js";
|
|
8
|
-
import "./chunk-LQIMKE3P.js";
|
|
9
|
-
import "./chunk-Q5EKA5YA.js";
|
|
10
|
-
import "./chunk-JVMBCWKS.js";
|
|
11
|
-
import "./chunk-4MXH2ZPT.js";
|
|
12
|
-
import "./chunk-XTFWT2XM.js";
|
|
13
|
-
import "./chunk-WCN7S3EI.js";
|
|
14
|
-
import "./chunk-G2TGF6TR.js";
|
|
15
|
-
import "./chunk-MRHKX5M5.js";
|
|
16
|
-
import "./chunk-T63OHG4Q.js";
|
|
17
|
-
import "./chunk-YZ6Y2H3P.js";
|
|
18
|
-
import "./chunk-5BRRRTN6.js";
|
|
19
|
-
import "./chunk-OBQ74FOU.js";
|
|
20
|
-
import "./chunk-XPZZFPBZ.js";
|
|
21
|
-
import "./chunk-TN5WEKWI.js";
|
|
22
|
-
import "./chunk-ZV2K6M7T.js";
|
|
23
|
-
import "./chunk-7WITSO22.js";
|
|
24
|
-
import "./chunk-SY6KQG44.js";
|
|
25
|
-
import "./chunk-OMR4YCBS.js";
|
|
26
|
-
import "./chunk-VUL52BQL.js";
|
|
27
|
-
import "./chunk-6NLHFIYA.js";
|
|
28
|
-
import "./chunk-575YT2SD.js";
|
|
29
|
-
import "./chunk-FQ45QP5A.js";
|
|
30
|
-
import "./chunk-XE6KQRKZ.js";
|
|
31
|
-
import "./chunk-ZJF5FTBX.js";
|
|
32
|
-
import "./chunk-GTKYBOXL.js";
|
|
33
|
-
import "./chunk-EFWVF6TI.js";
|
|
34
|
-
import "./chunk-43X6JBEM.js";
|
|
35
|
-
import "./chunk-ME2OERF5.js";
|
|
36
|
-
import "./chunk-VVITXIHN.js";
|
|
37
|
-
import "./chunk-KDHN2ZQE.js";
|
|
38
|
-
import "./chunk-2HF65EHQ.js";
|
|
39
|
-
import "./chunk-DGUM43GV.js";
|
|
4
|
+
} from "./chunk-2YXOBNKW.js";
|
|
5
|
+
import "./chunk-QR64Y5TI.js";
|
|
40
6
|
|
|
41
7
|
// src/index.ts
|
|
42
8
|
startServer().catch((error) => {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { startServer } from './server/mcp-server.js';\n\n// Start the MCP server\nstartServer().catch((error) => {\n console.error('Fatal error:', error);\n process.exit(1);\n});"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { startServer } from './server/mcp-server.js';\n\n// Start the MCP server\nstartServer().catch((error) => {\n console.error('Fatal error:', error);\n process.exit(1);\n});"],"mappings":";;;;;;;AAKA,YAAY,EAAE,MAAM,CAAC,UAAU;AAC7B,UAAQ,MAAM,gBAAgB,KAAK;AACnC,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":[]}
|
|
@@ -1,42 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MCPServer,
|
|
3
3
|
startServer
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
6
|
-
import "../chunk-HVCDY3AK.js";
|
|
7
|
-
import "../chunk-Q63FFI6D.js";
|
|
8
|
-
import "../chunk-LQIMKE3P.js";
|
|
9
|
-
import "../chunk-Q5EKA5YA.js";
|
|
10
|
-
import "../chunk-JVMBCWKS.js";
|
|
11
|
-
import "../chunk-4MXH2ZPT.js";
|
|
12
|
-
import "../chunk-XTFWT2XM.js";
|
|
13
|
-
import "../chunk-WCN7S3EI.js";
|
|
14
|
-
import "../chunk-G2TGF6TR.js";
|
|
15
|
-
import "../chunk-MRHKX5M5.js";
|
|
16
|
-
import "../chunk-T63OHG4Q.js";
|
|
17
|
-
import "../chunk-YZ6Y2H3P.js";
|
|
18
|
-
import "../chunk-5BRRRTN6.js";
|
|
19
|
-
import "../chunk-OBQ74FOU.js";
|
|
20
|
-
import "../chunk-XPZZFPBZ.js";
|
|
21
|
-
import "../chunk-TN5WEKWI.js";
|
|
22
|
-
import "../chunk-ZV2K6M7T.js";
|
|
23
|
-
import "../chunk-7WITSO22.js";
|
|
24
|
-
import "../chunk-SY6KQG44.js";
|
|
25
|
-
import "../chunk-OMR4YCBS.js";
|
|
26
|
-
import "../chunk-VUL52BQL.js";
|
|
27
|
-
import "../chunk-6NLHFIYA.js";
|
|
28
|
-
import "../chunk-575YT2SD.js";
|
|
29
|
-
import "../chunk-FQ45QP5A.js";
|
|
30
|
-
import "../chunk-XE6KQRKZ.js";
|
|
31
|
-
import "../chunk-ZJF5FTBX.js";
|
|
32
|
-
import "../chunk-GTKYBOXL.js";
|
|
33
|
-
import "../chunk-EFWVF6TI.js";
|
|
34
|
-
import "../chunk-43X6JBEM.js";
|
|
35
|
-
import "../chunk-ME2OERF5.js";
|
|
36
|
-
import "../chunk-VVITXIHN.js";
|
|
37
|
-
import "../chunk-KDHN2ZQE.js";
|
|
38
|
-
import "../chunk-2HF65EHQ.js";
|
|
39
|
-
import "../chunk-DGUM43GV.js";
|
|
4
|
+
} from "../chunk-2YXOBNKW.js";
|
|
5
|
+
import "../chunk-QR64Y5TI.js";
|
|
40
6
|
export {
|
|
41
7
|
MCPServer,
|
|
42
8
|
startServer
|
package/package.json
CHANGED
|
@@ -1,25 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@triedotdev/mcp",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.0.170",
|
|
4
|
+
"description": "Trie cloud context bridge for Cursor and Claude Code.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
8
8
|
"trie": "dist/cli/main.js",
|
|
9
9
|
"mcp": "dist/index.js",
|
|
10
10
|
"trie-agent": "dist/cli/main.js",
|
|
11
|
-
"trie-mcp": "dist/index.js"
|
|
12
|
-
"trie-watch": "dist/cli/yolo-daemon.js",
|
|
13
|
-
"trie-create": "dist/cli/create-agent.js"
|
|
11
|
+
"trie-mcp": "dist/index.js"
|
|
14
12
|
},
|
|
15
13
|
"scripts": {
|
|
16
|
-
"build": "tsup
|
|
14
|
+
"build": "tsup",
|
|
17
15
|
"build:server": "tsup",
|
|
18
|
-
"build:ui": "tsx src/ui/build.ts",
|
|
19
16
|
"dev": "tsx src/index.ts",
|
|
20
17
|
"test": "vitest",
|
|
21
|
-
"test:mcp-apps": "tsx scripts/test-mcp-apps-integration.js",
|
|
22
|
-
"preview:ui": "node scripts/preview-ui-apps.js",
|
|
23
18
|
"lint": "eslint src/**/*.ts",
|
|
24
19
|
"typecheck": "tsc --noEmit",
|
|
25
20
|
"prepublishOnly": "npm run build"
|
|
@@ -51,36 +46,18 @@
|
|
|
51
46
|
"url": "https://buy.stripe.com/5kQbJ12isaFyfVk0Tu00005"
|
|
52
47
|
},
|
|
53
48
|
"dependencies": {
|
|
54
|
-
"@
|
|
55
|
-
"@babel/generator": "^7.23.0",
|
|
56
|
-
"@babel/parser": "^7.23.0",
|
|
57
|
-
"@babel/traverse": "^7.23.0",
|
|
58
|
-
"@babel/types": "^7.23.0",
|
|
59
|
-
"@modelcontextprotocol/ext-apps": "^1.0.1",
|
|
60
|
-
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
61
|
-
"@noble/ed25519": "^3.0.0",
|
|
62
|
-
"@triedotdev/mcp": "^1.0.166",
|
|
63
|
-
"@vercel/blob": "^2.0.0",
|
|
64
|
-
"better-sqlite3": "^12.6.2",
|
|
65
|
-
"commander": "^11.1.0",
|
|
66
|
-
"glob": "^10.3.0",
|
|
67
|
-
"ink": "^5.2.1",
|
|
68
|
-
"picocolors": "^1.0.0",
|
|
69
|
-
"playwright": "^1.57.0",
|
|
70
|
-
"react": "^18.3.1",
|
|
49
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
71
50
|
"typescript": "^5.3.0",
|
|
72
51
|
"zod": "^3.22.0"
|
|
73
52
|
},
|
|
53
|
+
"optionalDependencies": {
|
|
54
|
+
"keytar": "^7.9.0"
|
|
55
|
+
},
|
|
74
56
|
"devDependencies": {
|
|
75
|
-
"@types/babel__generator": "^7.6.8",
|
|
76
|
-
"@types/babel__traverse": "^7.20.6",
|
|
77
|
-
"@types/better-sqlite3": "^7.6.13",
|
|
78
57
|
"@types/node": "^20.10.0",
|
|
79
|
-
"@types/react": "^18.3.28",
|
|
80
58
|
"@typescript-eslint/eslint-plugin": "^6.13.0",
|
|
81
59
|
"@typescript-eslint/parser": "^6.13.0",
|
|
82
60
|
"eslint": "^8.55.0",
|
|
83
|
-
"ink-testing-library": "^4.0.0",
|
|
84
61
|
"tsup": "^8.0.0",
|
|
85
62
|
"tsx": "^4.6.0",
|
|
86
63
|
"vitest": "^1.0.0"
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
clearConfigCache,
|
|
3
|
-
createIssueHash,
|
|
4
|
-
getAutonomyConfig,
|
|
5
|
-
getEscalationLevel,
|
|
6
|
-
groupFixesByFile,
|
|
7
|
-
loadAutonomyConfig,
|
|
8
|
-
recordBypass,
|
|
9
|
-
saveAutonomyConfig,
|
|
10
|
-
shouldAutoFix,
|
|
11
|
-
shouldBlockPush,
|
|
12
|
-
trackIssueOccurrence
|
|
13
|
-
} from "./chunk-ME2OERF5.js";
|
|
14
|
-
import "./chunk-VVITXIHN.js";
|
|
15
|
-
import "./chunk-KDHN2ZQE.js";
|
|
16
|
-
import "./chunk-DGUM43GV.js";
|
|
17
|
-
export {
|
|
18
|
-
clearConfigCache,
|
|
19
|
-
createIssueHash,
|
|
20
|
-
getAutonomyConfig,
|
|
21
|
-
getEscalationLevel,
|
|
22
|
-
groupFixesByFile,
|
|
23
|
-
loadAutonomyConfig,
|
|
24
|
-
recordBypass,
|
|
25
|
-
saveAutonomyConfig,
|
|
26
|
-
shouldAutoFix,
|
|
27
|
-
shouldBlockPush,
|
|
28
|
-
trackIssueOccurrence
|
|
29
|
-
};
|
|
30
|
-
//# sourceMappingURL=autonomy-config-FSERX3O3.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ChatStore,
|
|
3
|
-
clearChatStores,
|
|
4
|
-
getChatStore
|
|
5
|
-
} from "./chunk-JVMBCWKS.js";
|
|
6
|
-
import "./chunk-43X6JBEM.js";
|
|
7
|
-
import "./chunk-VVITXIHN.js";
|
|
8
|
-
import "./chunk-KDHN2ZQE.js";
|
|
9
|
-
import "./chunk-DGUM43GV.js";
|
|
10
|
-
export {
|
|
11
|
-
ChatStore,
|
|
12
|
-
clearChatStores,
|
|
13
|
-
getChatStore
|
|
14
|
-
};
|
|
15
|
-
//# sourceMappingURL=chat-store-JNGNTDSN.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/chunk-2HF65EHQ.js
DELETED
|
@@ -1,311 +0,0 @@
|
|
|
1
|
-
// src/agent/git.ts
|
|
2
|
-
import { existsSync } from "fs";
|
|
3
|
-
import path from "path";
|
|
4
|
-
|
|
5
|
-
// src/utils/command-runner.ts
|
|
6
|
-
import { exec, execFile, execSync } from "child_process";
|
|
7
|
-
import { promisify } from "util";
|
|
8
|
-
|
|
9
|
-
// src/utils/audit-logger.ts
|
|
10
|
-
function createAuditEntry(skillName, skillSource, triggeredBy, targetPath) {
|
|
11
|
-
return {
|
|
12
|
-
skillName,
|
|
13
|
-
skillSource,
|
|
14
|
-
triggeredBy,
|
|
15
|
-
targetPath,
|
|
16
|
-
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
17
|
-
commands: []
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
function completeAuditEntry(entry, success, error) {
|
|
21
|
-
const result = {
|
|
22
|
-
...entry,
|
|
23
|
-
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24
|
-
success
|
|
25
|
-
};
|
|
26
|
-
if (error !== void 0) {
|
|
27
|
-
result.error = error;
|
|
28
|
-
}
|
|
29
|
-
return result;
|
|
30
|
-
}
|
|
31
|
-
async function logSkillExecution(_execution) {
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// src/utils/command-runner.ts
|
|
35
|
-
var execAsync = promisify(exec);
|
|
36
|
-
var execFileAsync = promisify(execFile);
|
|
37
|
-
function redact(text) {
|
|
38
|
-
return text.replace(/\b(AWS|ANTHROPIC|OPENAI|GITHUB)_[A-Z0-9_]*\s*=\s*([^\s"'`]+)/gi, "$1_<REDACTED>=<REDACTED>").replace(/\bBearer\s+[A-Za-z0-9\-._~+/]+=*\b/g, "Bearer <REDACTED>").replace(/\bghp_[A-Za-z0-9]{20,}\b/g, "ghp_<REDACTED>").replace(/\b(?:xox[baprs]-)[A-Za-z0-9-]{10,}\b/g, "<REDACTED_SLACK_TOKEN>").replace(/\bAKIA[0-9A-Z]{16}\b/g, "AKIA<REDACTED>");
|
|
39
|
-
}
|
|
40
|
-
function clampOutput(text, maxChars) {
|
|
41
|
-
if (text.length <= maxChars) return text;
|
|
42
|
-
return text.slice(0, maxChars) + `
|
|
43
|
-
\u2026(truncated ${text.length - maxChars} chars)`;
|
|
44
|
-
}
|
|
45
|
-
function buildCommandRecord(command) {
|
|
46
|
-
return {
|
|
47
|
-
command,
|
|
48
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
async function finalizeAndWrite(entry, cmd, outcome, options) {
|
|
52
|
-
const duration = Date.now() - outcome.startedAt;
|
|
53
|
-
cmd.duration = duration;
|
|
54
|
-
if (outcome.exitCode !== void 0) {
|
|
55
|
-
cmd.exitCode = outcome.exitCode;
|
|
56
|
-
}
|
|
57
|
-
const captureOutput = options?.captureOutput ?? false;
|
|
58
|
-
const redactOutput = options?.redactOutput ?? true;
|
|
59
|
-
const maxOutputChars = options?.maxOutputChars ?? 2e3;
|
|
60
|
-
if (captureOutput) {
|
|
61
|
-
const out = outcome.stdout ?? "";
|
|
62
|
-
const err = outcome.stderr ?? "";
|
|
63
|
-
cmd.stdout = redactOutput ? redact(clampOutput(out, maxOutputChars)) : clampOutput(out, maxOutputChars);
|
|
64
|
-
cmd.stderr = redactOutput ? redact(clampOutput(err, maxOutputChars)) : clampOutput(err, maxOutputChars);
|
|
65
|
-
}
|
|
66
|
-
const completed = completeAuditEntry(entry, outcome.success, outcome.error);
|
|
67
|
-
await logSkillExecution(completed);
|
|
68
|
-
}
|
|
69
|
-
function runShellCommandSync(command, audit, options) {
|
|
70
|
-
const startedAt = Date.now();
|
|
71
|
-
const entry = createAuditEntry(audit.actor, audit.source ?? "trie", audit.triggeredBy, audit.targetPath);
|
|
72
|
-
const cmd = buildCommandRecord(command);
|
|
73
|
-
entry.commands?.push(cmd);
|
|
74
|
-
try {
|
|
75
|
-
const stdout = execSync(command, {
|
|
76
|
-
cwd: options?.cwd,
|
|
77
|
-
timeout: options?.timeoutMs,
|
|
78
|
-
maxBuffer: options?.maxBuffer,
|
|
79
|
-
encoding: "utf-8",
|
|
80
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
81
|
-
});
|
|
82
|
-
void finalizeAndWrite(entry, cmd, { success: true, exitCode: 0, stdout, stderr: "", startedAt }, options);
|
|
83
|
-
return { stdout: stdout ?? "", exitCode: 0 };
|
|
84
|
-
} catch (e) {
|
|
85
|
-
const err = e;
|
|
86
|
-
const stdout = typeof err.stdout === "string" ? err.stdout : "";
|
|
87
|
-
const stderr = typeof err.stderr === "string" ? err.stderr : "";
|
|
88
|
-
const exitCode = typeof err.status === "number" ? err.status : 1;
|
|
89
|
-
void finalizeAndWrite(
|
|
90
|
-
entry,
|
|
91
|
-
cmd,
|
|
92
|
-
{ success: false, exitCode, stdout, stderr, error: err.message, startedAt },
|
|
93
|
-
{ ...options, captureOutput: options?.captureOutput ?? true }
|
|
94
|
-
);
|
|
95
|
-
return { stdout, exitCode };
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
async function runExecFile(file, args, audit, options) {
|
|
99
|
-
const startedAt = Date.now();
|
|
100
|
-
const command = [file, ...args].join(" ");
|
|
101
|
-
const entry = createAuditEntry(audit.actor, audit.source ?? "trie", audit.triggeredBy, audit.targetPath);
|
|
102
|
-
const cmd = buildCommandRecord(command);
|
|
103
|
-
entry.commands?.push(cmd);
|
|
104
|
-
try {
|
|
105
|
-
const { stdout, stderr } = await execFileAsync(file, args, {
|
|
106
|
-
cwd: options?.cwd,
|
|
107
|
-
timeout: options?.timeoutMs,
|
|
108
|
-
maxBuffer: options?.maxBuffer
|
|
109
|
-
});
|
|
110
|
-
await finalizeAndWrite(entry, cmd, { success: true, exitCode: 0, stdout: String(stdout ?? ""), stderr: String(stderr ?? ""), startedAt }, options);
|
|
111
|
-
return { stdout: String(stdout ?? ""), stderr: String(stderr ?? ""), exitCode: 0 };
|
|
112
|
-
} catch (e) {
|
|
113
|
-
const err = e;
|
|
114
|
-
const stdout = typeof err.stdout === "string" ? err.stdout : "";
|
|
115
|
-
const stderr = typeof err.stderr === "string" ? err.stderr : "";
|
|
116
|
-
const exitCode = typeof err.code === "number" ? err.code : 1;
|
|
117
|
-
await finalizeAndWrite(
|
|
118
|
-
entry,
|
|
119
|
-
cmd,
|
|
120
|
-
{ success: false, exitCode, stdout, stderr, error: err.message, startedAt },
|
|
121
|
-
{ ...options, captureOutput: options?.captureOutput ?? true }
|
|
122
|
-
);
|
|
123
|
-
return { stdout, stderr, exitCode };
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// src/agent/git.ts
|
|
128
|
-
async function execGit(args, cwd) {
|
|
129
|
-
try {
|
|
130
|
-
const { stdout } = await runExecFile(
|
|
131
|
-
"git",
|
|
132
|
-
["-C", cwd, ...args],
|
|
133
|
-
{ actor: "internal:git", triggeredBy: "manual", targetPath: cwd },
|
|
134
|
-
{ maxBuffer: 10 * 1024 * 1024, captureOutput: false }
|
|
135
|
-
);
|
|
136
|
-
return stdout.trim();
|
|
137
|
-
} catch (error) {
|
|
138
|
-
const stderr = error?.stderr?.toString();
|
|
139
|
-
if (stderr?.includes("not a git repository") || stderr?.includes("does not have any commits")) {
|
|
140
|
-
return null;
|
|
141
|
-
}
|
|
142
|
-
throw error;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
async function ensureRepo(projectPath) {
|
|
146
|
-
const result = await execGit(["rev-parse", "--is-inside-work-tree"], projectPath);
|
|
147
|
-
return result === "true";
|
|
148
|
-
}
|
|
149
|
-
function parseNameStatus(output) {
|
|
150
|
-
return output.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => {
|
|
151
|
-
const parts = line.split(" ");
|
|
152
|
-
const status = parts[0] ?? "";
|
|
153
|
-
const filePath = parts[1] ?? "";
|
|
154
|
-
const oldPath = parts[2];
|
|
155
|
-
const change = { status, path: filePath };
|
|
156
|
-
if (oldPath) change.oldPath = oldPath;
|
|
157
|
-
return change;
|
|
158
|
-
}).filter((entry) => entry.path.length > 0);
|
|
159
|
-
}
|
|
160
|
-
async function getRecentCommits(projectPath, limit) {
|
|
161
|
-
const isRepo = await ensureRepo(projectPath);
|
|
162
|
-
if (!isRepo) return [];
|
|
163
|
-
const output = await execGit(
|
|
164
|
-
["log", `-n`, String(limit), "--pretty=format:%H%x09%an%x09%ad%x09%s", "--date=iso"],
|
|
165
|
-
projectPath
|
|
166
|
-
);
|
|
167
|
-
if (!output) return [];
|
|
168
|
-
return output.split("\n").map((line) => {
|
|
169
|
-
const [hash, author, date, message] = line.split(" ");
|
|
170
|
-
return { hash, author, date, message };
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
async function getLastCommit(projectPath) {
|
|
174
|
-
const commits = await getRecentCommits(projectPath, 1);
|
|
175
|
-
return commits[0] ?? null;
|
|
176
|
-
}
|
|
177
|
-
async function getStagedChanges(projectPath) {
|
|
178
|
-
const isRepo = await ensureRepo(projectPath);
|
|
179
|
-
if (!isRepo) return [];
|
|
180
|
-
const output = await execGit(["diff", "--cached", "--name-status"], projectPath);
|
|
181
|
-
if (!output) return [];
|
|
182
|
-
return parseNameStatus(output);
|
|
183
|
-
}
|
|
184
|
-
async function getUncommittedChanges(projectPath) {
|
|
185
|
-
const isRepo = await ensureRepo(projectPath);
|
|
186
|
-
if (!isRepo) return [];
|
|
187
|
-
const changes = [];
|
|
188
|
-
const unstaged = await execGit(["diff", "--name-status"], projectPath);
|
|
189
|
-
if (unstaged) {
|
|
190
|
-
changes.push(...parseNameStatus(unstaged));
|
|
191
|
-
}
|
|
192
|
-
const untracked = await execGit(["ls-files", "--others", "--exclude-standard"], projectPath);
|
|
193
|
-
if (untracked) {
|
|
194
|
-
changes.push(
|
|
195
|
-
...untracked.split("\n").map((p) => p.trim()).filter(Boolean).map((p) => ({ status: "??", path: p }))
|
|
196
|
-
);
|
|
197
|
-
}
|
|
198
|
-
return changes;
|
|
199
|
-
}
|
|
200
|
-
async function getGitChangedFiles(projectPath) {
|
|
201
|
-
const isRepo = await ensureRepo(projectPath);
|
|
202
|
-
if (!isRepo) return null;
|
|
203
|
-
const [staged, uncommitted] = await Promise.all([
|
|
204
|
-
getStagedChanges(projectPath).catch(() => []),
|
|
205
|
-
getUncommittedChanges(projectPath).catch(() => [])
|
|
206
|
-
]);
|
|
207
|
-
const paths = /* @__PURE__ */ new Set();
|
|
208
|
-
for (const change of [...staged, ...uncommitted]) {
|
|
209
|
-
if (change.path) paths.add(change.path);
|
|
210
|
-
if (change.oldPath) paths.add(change.oldPath);
|
|
211
|
-
}
|
|
212
|
-
return [...paths];
|
|
213
|
-
}
|
|
214
|
-
async function getDiff(projectPath, commitHash) {
|
|
215
|
-
const isRepo = await ensureRepo(projectPath);
|
|
216
|
-
if (!isRepo) return "";
|
|
217
|
-
const diff = await execGit(["show", commitHash, "--unified=3", "--no-color"], projectPath);
|
|
218
|
-
return diff ?? "";
|
|
219
|
-
}
|
|
220
|
-
async function getWorkingTreeDiff(projectPath, stagedOnly = false) {
|
|
221
|
-
const isRepo = await ensureRepo(projectPath);
|
|
222
|
-
if (!isRepo) return "";
|
|
223
|
-
const args = stagedOnly ? ["diff", "--cached", "--unified=3", "--no-color"] : ["diff", "--unified=3", "--no-color"];
|
|
224
|
-
const diff = await execGit(args, projectPath);
|
|
225
|
-
return diff ?? "";
|
|
226
|
-
}
|
|
227
|
-
async function getUnpushedCommits(projectPath) {
|
|
228
|
-
const isRepo = await ensureRepo(projectPath);
|
|
229
|
-
if (!isRepo) return [];
|
|
230
|
-
const upstream = await execGit(["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"], projectPath);
|
|
231
|
-
if (!upstream) {
|
|
232
|
-
return getRecentCommits(projectPath, 10);
|
|
233
|
-
}
|
|
234
|
-
const output = await execGit(["log", `${upstream}..HEAD`, "--pretty=format:%H%x09%an%x09%ad%x09%s", "--date=iso"], projectPath);
|
|
235
|
-
if (!output) return [];
|
|
236
|
-
return output.split("\n").filter(Boolean).map((line) => {
|
|
237
|
-
const [hash, author, date, message] = line.split(" ");
|
|
238
|
-
return { hash, author, date, message };
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
function resolveRepoPath(projectPath) {
|
|
242
|
-
const gitDir = path.join(projectPath, ".git");
|
|
243
|
-
if (existsSync(gitDir)) return projectPath;
|
|
244
|
-
return projectPath;
|
|
245
|
-
}
|
|
246
|
-
async function isGitRepo(projectPath) {
|
|
247
|
-
const result = await execGit(["rev-parse", "--is-inside-work-tree"], projectPath);
|
|
248
|
-
return result === "true";
|
|
249
|
-
}
|
|
250
|
-
async function getChangedFilesSinceTimestamp(projectPath, timestamp) {
|
|
251
|
-
const isRepo = await isGitRepo(projectPath);
|
|
252
|
-
if (!isRepo) return null;
|
|
253
|
-
try {
|
|
254
|
-
const sinceDate = new Date(timestamp).toISOString();
|
|
255
|
-
const GIT_TIMEOUT_MS = 5e3;
|
|
256
|
-
const startTime = Date.now();
|
|
257
|
-
const committedChangesPromise = execGit(
|
|
258
|
-
["log", `--since=${sinceDate}`, "--name-only", "--pretty=format:"],
|
|
259
|
-
projectPath
|
|
260
|
-
);
|
|
261
|
-
const committedChangesTimeout = new Promise((resolve) => {
|
|
262
|
-
setTimeout(() => resolve(null), GIT_TIMEOUT_MS);
|
|
263
|
-
});
|
|
264
|
-
const committedChanges = await Promise.race([committedChangesPromise, committedChangesTimeout]);
|
|
265
|
-
if (Date.now() - startTime > GIT_TIMEOUT_MS) {
|
|
266
|
-
return null;
|
|
267
|
-
}
|
|
268
|
-
const stagedPromise = execGit(["diff", "--cached", "--name-only"], projectPath);
|
|
269
|
-
const unstagedPromise = execGit(["diff", "--name-only"], projectPath);
|
|
270
|
-
const untrackedPromise = execGit(
|
|
271
|
-
["ls-files", "--others", "--exclude-standard"],
|
|
272
|
-
projectPath
|
|
273
|
-
);
|
|
274
|
-
const timeoutPromise = new Promise((resolve) => {
|
|
275
|
-
setTimeout(() => resolve(null), Math.max(0, GIT_TIMEOUT_MS - (Date.now() - startTime)));
|
|
276
|
-
});
|
|
277
|
-
const [stagedChanges, unstagedChanges, untrackedFiles] = await Promise.race([
|
|
278
|
-
Promise.all([stagedPromise, unstagedPromise, untrackedPromise]),
|
|
279
|
-
timeoutPromise.then(() => [null, null, null])
|
|
280
|
-
]);
|
|
281
|
-
const changedFiles = /* @__PURE__ */ new Set();
|
|
282
|
-
const addFiles = (output) => {
|
|
283
|
-
if (output) {
|
|
284
|
-
output.split("\n").map((f) => f.trim()).filter(Boolean).forEach((f) => changedFiles.add(path.join(projectPath, f)));
|
|
285
|
-
}
|
|
286
|
-
};
|
|
287
|
-
addFiles(committedChanges);
|
|
288
|
-
addFiles(stagedChanges);
|
|
289
|
-
addFiles(unstagedChanges);
|
|
290
|
-
addFiles(untrackedFiles);
|
|
291
|
-
return Array.from(changedFiles);
|
|
292
|
-
} catch {
|
|
293
|
-
return null;
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
export {
|
|
298
|
-
runShellCommandSync,
|
|
299
|
-
getRecentCommits,
|
|
300
|
-
getLastCommit,
|
|
301
|
-
getStagedChanges,
|
|
302
|
-
getUncommittedChanges,
|
|
303
|
-
getGitChangedFiles,
|
|
304
|
-
getDiff,
|
|
305
|
-
getWorkingTreeDiff,
|
|
306
|
-
getUnpushedCommits,
|
|
307
|
-
resolveRepoPath,
|
|
308
|
-
isGitRepo,
|
|
309
|
-
getChangedFilesSinceTimestamp
|
|
310
|
-
};
|
|
311
|
-
//# sourceMappingURL=chunk-2HF65EHQ.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/agent/git.ts","../src/utils/command-runner.ts","../src/utils/audit-logger.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport path from 'node:path';\nimport { runExecFile } from '../utils/command-runner.js';\n\nexport interface Commit {\n hash: string;\n author: string;\n date: string;\n message: string;\n}\n\nexport interface Change {\n path: string;\n status: string;\n oldPath?: string;\n}\n\nasync function execGit(args: string[], cwd: string): Promise<string | null> {\n try {\n const { stdout } = await runExecFile(\n 'git',\n ['-C', cwd, ...args],\n { actor: 'internal:git', triggeredBy: 'manual', targetPath: cwd },\n { maxBuffer: 10 * 1024 * 1024, captureOutput: false }\n );\n return stdout.trim();\n } catch (error: any) {\n const stderr: string | undefined = error?.stderr?.toString();\n // Gracefully handle non-git directories and repos with no commits\n if (stderr?.includes('not a git repository') || stderr?.includes('does not have any commits')) {\n return null;\n }\n throw error;\n }\n}\n\nasync function ensureRepo(projectPath: string): Promise<boolean> {\n const result = await execGit(['rev-parse', '--is-inside-work-tree'], projectPath);\n return result === 'true';\n}\n\nfunction parseNameStatus(output: string): Change[] {\n return output\n .split('\\n')\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => {\n const parts = line.split('\\t');\n const status = parts[0] ?? '';\n const filePath = parts[1] ?? '';\n const oldPath = parts[2];\n const change: Change = { status, path: filePath };\n if (oldPath) change.oldPath = oldPath;\n return change;\n })\n .filter((entry) => entry.path.length > 0);\n}\n\nexport async function getRecentCommits(projectPath: string, limit: number): Promise<Commit[]> {\n const isRepo = await ensureRepo(projectPath);\n if (!isRepo) return [];\n\n const output = await execGit(\n ['log', `-n`, String(limit), '--pretty=format:%H%x09%an%x09%ad%x09%s', '--date=iso'],\n projectPath\n );\n\n if (!output) return [];\n\n return output.split('\\n').map((line) => {\n const [hash, author, date, message] = line.split('\\t');\n return { hash, author, date, message } as Commit;\n });\n}\n\nexport async function getLastCommit(projectPath: string): Promise<Commit | null> {\n const commits = await getRecentCommits(projectPath, 1);\n return commits[0] ?? null;\n}\n\nexport async function getStagedChanges(projectPath: string): Promise<Change[]> {\n const isRepo = await ensureRepo(projectPath);\n if (!isRepo) return [];\n\n const output = await execGit(['diff', '--cached', '--name-status'], projectPath);\n if (!output) return [];\n return parseNameStatus(output);\n}\n\nexport async function getUncommittedChanges(projectPath: string): Promise<Change[]> {\n const isRepo = await ensureRepo(projectPath);\n if (!isRepo) return [];\n\n const changes: Change[] = [];\n\n const unstaged = await execGit(['diff', '--name-status'], projectPath);\n if (unstaged) {\n changes.push(...parseNameStatus(unstaged));\n }\n\n const untracked = await execGit(['ls-files', '--others', '--exclude-standard'], projectPath);\n if (untracked) {\n changes.push(\n ...untracked\n .split('\\n')\n .map((p) => p.trim())\n .filter(Boolean)\n .map((p) => ({ status: '??', path: p }))\n );\n }\n\n return changes;\n}\n\n/**\n * Get a flat list of changed file paths in the working tree.\n * Convenience helper used by tooling (e.g. cache invalidation).\n *\n * Returns null if not a git repository.\n */\nexport async function getGitChangedFiles(projectPath: string): Promise<string[] | null> {\n const isRepo = await ensureRepo(projectPath);\n if (!isRepo) return null;\n\n const [staged, uncommitted] = await Promise.all([\n getStagedChanges(projectPath).catch(() => []),\n getUncommittedChanges(projectPath).catch(() => []),\n ]);\n\n const paths = new Set<string>();\n for (const change of [...staged, ...uncommitted]) {\n if (change.path) paths.add(change.path);\n if (change.oldPath) paths.add(change.oldPath);\n }\n\n return [...paths];\n}\n\nexport async function getDiff(projectPath: string, commitHash: string): Promise<string> {\n const isRepo = await ensureRepo(projectPath);\n if (!isRepo) return '';\n\n const diff = await execGit(['show', commitHash, '--unified=3', '--no-color'], projectPath);\n return diff ?? '';\n}\n\nexport async function getWorkingTreeDiff(projectPath: string, stagedOnly = false): Promise<string> {\n const isRepo = await ensureRepo(projectPath);\n if (!isRepo) return '';\n\n const args = stagedOnly ? ['diff', '--cached', '--unified=3', '--no-color'] : ['diff', '--unified=3', '--no-color'];\n const diff = await execGit(args, projectPath);\n return diff ?? '';\n}\n\nexport async function getUnpushedCommits(projectPath: string): Promise<Commit[]> {\n const isRepo = await ensureRepo(projectPath);\n if (!isRepo) return [];\n\n // Handles detached HEAD by falling back to HEAD if upstream missing\n const upstream = await execGit(['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}'], projectPath);\n if (!upstream) {\n return getRecentCommits(projectPath, 10);\n }\n\n const output = await execGit(['log', `${upstream}..HEAD`, '--pretty=format:%H%x09%an%x09%ad%x09%s', '--date=iso'], projectPath);\n if (!output) return [];\n\n return output.split('\\n').filter(Boolean).map((line) => {\n const [hash, author, date, message] = line.split('\\t');\n return { hash, author, date, message } as Commit;\n });\n}\n\nexport function resolveRepoPath(projectPath: string): string {\n const gitDir = path.join(projectPath, '.git');\n if (existsSync(gitDir)) return projectPath;\n return projectPath;\n}\n\n/**\n * Check if the given path is inside a git repository\n */\nexport async function isGitRepo(projectPath: string): Promise<boolean> {\n const result = await execGit(['rev-parse', '--is-inside-work-tree'], projectPath);\n return result === 'true';\n}\n\n/**\n * Get files changed since a given timestamp\n * Uses git log to find commits after timestamp, then gets affected files\n * Returns null if not a git repo or on error\n */\nexport async function getChangedFilesSinceTimestamp(\n projectPath: string,\n timestamp: number\n): Promise<string[] | null> {\n const isRepo = await isGitRepo(projectPath);\n if (!isRepo) return null;\n\n try {\n // Convert timestamp to ISO date for git\n const sinceDate = new Date(timestamp).toISOString();\n \n // Set timeout for git operations (5 seconds total)\n const GIT_TIMEOUT_MS = 5000;\n const startTime = Date.now();\n \n // Get all files that changed in commits since the timestamp\n // Use Promise.race to timeout if git operations take too long\n const committedChangesPromise = execGit(\n ['log', `--since=${sinceDate}`, '--name-only', '--pretty=format:'],\n projectPath\n );\n const committedChangesTimeout = new Promise<string | null>((resolve) => {\n setTimeout(() => resolve(null), GIT_TIMEOUT_MS);\n });\n const committedChanges = await Promise.race([committedChangesPromise, committedChangesTimeout]);\n\n // Check if we've exceeded timeout\n if (Date.now() - startTime > GIT_TIMEOUT_MS) {\n return null;\n }\n\n // Get currently modified files (staged + unstaged) - run in parallel with timeout\n const stagedPromise = execGit(['diff', '--cached', '--name-only'], projectPath);\n const unstagedPromise = execGit(['diff', '--name-only'], projectPath);\n const untrackedPromise = execGit(\n ['ls-files', '--others', '--exclude-standard'],\n projectPath\n );\n \n const timeoutPromise = new Promise<null>((resolve) => {\n setTimeout(() => resolve(null), Math.max(0, GIT_TIMEOUT_MS - (Date.now() - startTime)));\n });\n \n const [stagedChanges, unstagedChanges, untrackedFiles] = await Promise.race([\n Promise.all([stagedPromise, unstagedPromise, untrackedPromise]),\n timeoutPromise.then(() => [null, null, null] as const)\n ]);\n\n // Combine all changed files\n const changedFiles = new Set<string>();\n \n const addFiles = (output: string | null) => {\n if (output) {\n output.split('\\n')\n .map(f => f.trim())\n .filter(Boolean)\n .forEach(f => changedFiles.add(path.join(projectPath, f)));\n }\n };\n\n addFiles(committedChanges);\n addFiles(stagedChanges);\n addFiles(unstagedChanges);\n addFiles(untrackedFiles);\n\n return Array.from(changedFiles);\n } catch {\n return null;\n }\n}\n","/**\n * Command Runner (with audit logging)\n *\n * Goal: Whenever Trie runs a shell command, record:\n * - command string\n * - exit code\n * - duration\n * - optional (redacted) stdout/stderr\n */\nimport { exec, execFile, execSync, type ExecException } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nimport {\n createAuditEntry,\n completeAuditEntry,\n logSkillExecution,\n type ExecutedCommand,\n type SkillExecution,\n} from './audit-logger.js';\n\nconst execAsync = promisify(exec);\nconst execFileAsync = promisify(execFile);\n\nexport type { ExecutedCommand, SkillExecution };\nexport type AuditTriggeredBy = SkillExecution['triggeredBy'];\n\nexport interface CommandAuditContext {\n /** Shown as `skillName` in audit logs; use something like `tool:pr-review` */\n actor: string;\n /** Where this came from in the product flow */\n triggeredBy: AuditTriggeredBy;\n /** Usually the working directory / repo path */\n targetPath: string;\n /** Optional string for `skillSource` */\n source?: string;\n}\n\nexport interface RunCommandOptions {\n cwd?: string;\n timeoutMs?: number;\n maxBuffer?: number;\n\n /** Capture stdout/stderr in the audit log */\n captureOutput?: boolean;\n /** Redact obvious secrets from captured output */\n redactOutput?: boolean;\n /** Max chars to keep per output stream */\n maxOutputChars?: number;\n}\n\nfunction redact(text: string): string {\n // Keep this conservative to avoid false redaction and avoid expensive processing.\n return text\n // Common key=value secrets\n .replace(/\\b(AWS|ANTHROPIC|OPENAI|GITHUB)_[A-Z0-9_]*\\s*=\\s*([^\\s\"'`]+)/gi, '$1_<REDACTED>=<REDACTED>')\n // Bearer tokens\n .replace(/\\bBearer\\s+[A-Za-z0-9\\-._~+/]+=*\\b/g, 'Bearer <REDACTED>')\n // GitHub tokens / generic tokens\n .replace(/\\bghp_[A-Za-z0-9]{20,}\\b/g, 'ghp_<REDACTED>')\n .replace(/\\b(?:xox[baprs]-)[A-Za-z0-9-]{10,}\\b/g, '<REDACTED_SLACK_TOKEN>')\n // AWS access key id (best-effort)\n .replace(/\\bAKIA[0-9A-Z]{16}\\b/g, 'AKIA<REDACTED>');\n}\n\nfunction clampOutput(text: string, maxChars: number): string {\n if (text.length <= maxChars) return text;\n return text.slice(0, maxChars) + `\\n…(truncated ${text.length - maxChars} chars)`;\n}\n\nfunction buildCommandRecord(command: string): ExecutedCommand {\n return {\n command,\n timestamp: new Date().toISOString(),\n };\n}\n\nasync function finalizeAndWrite(\n entry: SkillExecution,\n cmd: ExecutedCommand,\n outcome: { success: boolean; exitCode?: number; stdout?: string; stderr?: string; error?: string; startedAt: number },\n options?: Pick<RunCommandOptions, 'captureOutput' | 'redactOutput' | 'maxOutputChars'>\n): Promise<void> {\n const duration = Date.now() - outcome.startedAt;\n cmd.duration = duration;\n if (outcome.exitCode !== undefined) {\n cmd.exitCode = outcome.exitCode;\n }\n\n const captureOutput = options?.captureOutput ?? false;\n const redactOutput = options?.redactOutput ?? true;\n const maxOutputChars = options?.maxOutputChars ?? 2000;\n\n if (captureOutput) {\n const out = outcome.stdout ?? '';\n const err = outcome.stderr ?? '';\n cmd.stdout = redactOutput ? redact(clampOutput(out, maxOutputChars)) : clampOutput(out, maxOutputChars);\n cmd.stderr = redactOutput ? redact(clampOutput(err, maxOutputChars)) : clampOutput(err, maxOutputChars);\n }\n\n const completed = completeAuditEntry(entry, outcome.success, outcome.error);\n await logSkillExecution(completed);\n}\n\nexport async function runShellCommand(\n command: string,\n audit: CommandAuditContext,\n options?: RunCommandOptions\n): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n const startedAt = Date.now();\n const entry = createAuditEntry(audit.actor, audit.source ?? 'trie', audit.triggeredBy, audit.targetPath);\n const cmd = buildCommandRecord(command);\n entry.commands?.push(cmd);\n\n try {\n const { stdout, stderr } = await execAsync(command, {\n cwd: options?.cwd,\n timeout: options?.timeoutMs,\n maxBuffer: options?.maxBuffer,\n });\n\n await finalizeAndWrite(entry, cmd, { success: true, exitCode: 0, stdout, stderr, startedAt }, options);\n return { stdout: stdout ?? '', stderr: stderr ?? '', exitCode: 0 };\n } catch (e) {\n const err = e as ExecException & { stdout?: unknown; stderr?: unknown; code?: unknown };\n const stdout = typeof err.stdout === 'string' ? err.stdout : '';\n const stderr = typeof err.stderr === 'string' ? err.stderr : '';\n const exitCode = typeof err.code === 'number' ? err.code : 1;\n\n await finalizeAndWrite(\n entry,\n cmd,\n { success: false, exitCode, stdout, stderr, error: err.message, startedAt },\n // Capture output for failures by default (so audits are useful)\n { ...options, captureOutput: options?.captureOutput ?? true }\n );\n\n return { stdout, stderr, exitCode };\n }\n}\n\nexport function runShellCommandSync(\n command: string,\n audit: CommandAuditContext,\n options?: Omit<RunCommandOptions, 'timeoutMs'> & { timeoutMs?: number }\n): { stdout: string; exitCode: number } {\n const startedAt = Date.now();\n const entry = createAuditEntry(audit.actor, audit.source ?? 'trie', audit.triggeredBy, audit.targetPath);\n const cmd = buildCommandRecord(command);\n entry.commands?.push(cmd);\n\n try {\n const stdout = execSync(command, {\n cwd: options?.cwd,\n timeout: options?.timeoutMs,\n maxBuffer: options?.maxBuffer,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n // Fire-and-forget write; sync APIs can’t await.\n void finalizeAndWrite(entry, cmd, { success: true, exitCode: 0, stdout, stderr: '', startedAt }, options);\n return { stdout: stdout ?? '', exitCode: 0 };\n } catch (e) {\n const err = e as ExecException & { stdout?: unknown; stderr?: unknown; status?: unknown };\n const stdout = typeof err.stdout === 'string' ? err.stdout : '';\n const stderr = typeof err.stderr === 'string' ? err.stderr : '';\n const exitCode = typeof err.status === 'number' ? err.status : 1;\n\n void finalizeAndWrite(\n entry,\n cmd,\n { success: false, exitCode, stdout, stderr, error: err.message, startedAt },\n { ...options, captureOutput: options?.captureOutput ?? true }\n );\n\n return { stdout, exitCode };\n }\n}\n\nexport async function runExecFile(\n file: string,\n args: string[],\n audit: CommandAuditContext,\n options?: Omit<RunCommandOptions, 'timeoutMs'> & { timeoutMs?: number }\n): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n const startedAt = Date.now();\n const command = [file, ...args].join(' ');\n const entry = createAuditEntry(audit.actor, audit.source ?? 'trie', audit.triggeredBy, audit.targetPath);\n const cmd = buildCommandRecord(command);\n entry.commands?.push(cmd);\n\n try {\n const { stdout, stderr } = await execFileAsync(file, args, {\n cwd: options?.cwd,\n timeout: options?.timeoutMs,\n maxBuffer: options?.maxBuffer,\n });\n\n await finalizeAndWrite(entry, cmd, { success: true, exitCode: 0, stdout: String(stdout ?? ''), stderr: String(stderr ?? ''), startedAt }, options);\n return { stdout: String(stdout ?? ''), stderr: String(stderr ?? ''), exitCode: 0 };\n } catch (e) {\n const err = e as ExecException & { stdout?: unknown; stderr?: unknown; code?: unknown };\n const stdout = typeof err.stdout === 'string' ? err.stdout : '';\n const stderr = typeof err.stderr === 'string' ? err.stderr : '';\n const exitCode = typeof err.code === 'number' ? err.code : 1;\n\n await finalizeAndWrite(\n entry,\n cmd,\n { success: false, exitCode, stdout, stderr, error: err.message, startedAt },\n { ...options, captureOutput: options?.captureOutput ?? true }\n );\n return { stdout, stderr, exitCode };\n }\n}\n\n","/**\n * Audit logger stub\n *\n * Audit functionality has been integrated into the decision ledger.\n * This module exists to keep legacy CLI/tooling paths working without the old skills system.\n */\n\nexport interface AuditStatistics {\n totalScans: number;\n totalIssues: number;\n criticalCount: number;\n seriousCount: number;\n moderateCount: number;\n lowCount: number;\n totalExecutions: number;\n successfulExecutions: number;\n failedExecutions: number;\n uniqueSkills: number;\n totalCommands: number;\n blockedCommands: number;\n totalNetworkCalls: number;\n blockedNetworkCalls: number;\n}\n\nexport interface AuditEntry {\n id: string;\n timestamp: string;\n command: string;\n status: string;\n commands?: ExecutedCommand[];\n}\n\nexport interface ExecutedCommand {\n command: string;\n timestamp: string;\n exitCode?: number;\n duration?: number;\n stdout?: string;\n stderr?: string;\n}\n\nexport interface SkillExecution {\n skillName: string;\n skillSource: string;\n triggeredBy: 'scan' | 'mcp' | 'cli' | 'watch' | 'manual';\n targetPath: string;\n startedAt: string;\n completedAt?: string;\n success?: boolean;\n error?: string;\n commands?: ExecutedCommand[];\n}\n\nexport function formatAuditLog(_entry: AuditEntry): string {\n return 'Audit logging has been integrated into the decision ledger';\n}\n\nexport function getAuditStatistics(): AuditStatistics {\n return {\n totalScans: 0,\n totalIssues: 0,\n criticalCount: 0,\n seriousCount: 0,\n moderateCount: 0,\n lowCount: 0,\n totalExecutions: 0,\n successfulExecutions: 0,\n failedExecutions: 0,\n uniqueSkills: 0,\n totalCommands: 0,\n blockedCommands: 0,\n totalNetworkCalls: 0,\n blockedNetworkCalls: 0,\n };\n}\n\nexport function createAuditEntry(\n skillName: string,\n skillSource: string,\n triggeredBy: SkillExecution['triggeredBy'],\n targetPath: string\n): SkillExecution {\n return {\n skillName,\n skillSource,\n triggeredBy,\n targetPath,\n startedAt: new Date().toISOString(),\n commands: [],\n };\n}\n\nexport function completeAuditEntry(\n entry: SkillExecution,\n success: boolean,\n error?: string\n): SkillExecution {\n const result: SkillExecution = {\n ...entry,\n completedAt: new Date().toISOString(),\n success,\n };\n if (error !== undefined) {\n result.error = error;\n }\n return result;\n}\n\nexport async function logSkillExecution(_execution: SkillExecution): Promise<void> {\n // Stub - no-op\n}\n\nexport async function getRecentAuditLogs(_limit: number = 10): Promise<AuditEntry[]> {\n return [];\n}\n\nexport async function getSkillAuditLogs(_skillName: string): Promise<AuditEntry[]> {\n return [];\n}\n\n"],"mappings":"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","names":[]}
|
package/dist/chunk-43X6JBEM.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
// src/utils/atomic-write.ts
|
|
2
|
-
import { writeFile, rename, unlink, mkdir } from "fs/promises";
|
|
3
|
-
import { randomBytes } from "crypto";
|
|
4
|
-
import { dirname } from "path";
|
|
5
|
-
async function atomicWriteFile(filePath, data, options = {}) {
|
|
6
|
-
const { createDir = true, encoding = "utf-8" } = options;
|
|
7
|
-
const tempSuffix = randomBytes(6).toString("hex");
|
|
8
|
-
const tempPath = `${filePath}.${tempSuffix}.tmp`;
|
|
9
|
-
try {
|
|
10
|
-
if (createDir) {
|
|
11
|
-
await mkdir(dirname(filePath), { recursive: true });
|
|
12
|
-
}
|
|
13
|
-
if (typeof data === "string") {
|
|
14
|
-
await writeFile(tempPath, data, { encoding });
|
|
15
|
-
} else {
|
|
16
|
-
await writeFile(tempPath, data);
|
|
17
|
-
}
|
|
18
|
-
await rename(tempPath, filePath);
|
|
19
|
-
} catch (error) {
|
|
20
|
-
try {
|
|
21
|
-
await unlink(tempPath);
|
|
22
|
-
} catch {
|
|
23
|
-
}
|
|
24
|
-
throw error;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
async function atomicWriteJSON(filePath, data, options = {}) {
|
|
28
|
-
const { spaces = 2, ...writeOptions } = options;
|
|
29
|
-
const json = JSON.stringify(data, null, spaces);
|
|
30
|
-
await atomicWriteFile(filePath, json, writeOptions);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export {
|
|
34
|
-
atomicWriteJSON
|
|
35
|
-
};
|
|
36
|
-
//# sourceMappingURL=chunk-43X6JBEM.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/atomic-write.ts"],"sourcesContent":["/**\n * Atomic File Write Utility\n * \n * Provides safe file writes using the temp file + rename pattern.\n * Prevents data corruption from interrupted writes or crashes.\n * \n * Pattern:\n * 1. Write to a temporary file with random suffix\n * 2. Rename temp file to target path (atomic on POSIX systems)\n * 3. Clean up temp file on failure\n */\n\nimport { writeFile, rename, unlink, mkdir } from 'fs/promises';\nimport { randomBytes } from 'crypto';\nimport { dirname } from 'path';\n\nexport interface AtomicWriteOptions {\n /**\n * Create parent directories if they don't exist\n * @default true\n */\n createDir?: boolean;\n \n /**\n * File encoding for string data\n * @default 'utf-8'\n */\n encoding?: BufferEncoding;\n}\n\n/**\n * Write data to a file atomically\n * \n * Uses a temp file + rename pattern to ensure the target file\n * is never in a partially written state. On POSIX systems,\n * rename() is atomic, so readers will always see either the\n * old complete file or the new complete file.\n * \n * @param filePath - Target file path\n * @param data - Data to write (string or Buffer)\n * @param options - Write options\n * @throws Error if write or rename fails\n * \n * @example\n * ```typescript\n * await atomicWriteFile('/path/to/data.json', JSON.stringify(data, null, 2));\n * ```\n */\nexport async function atomicWriteFile(\n filePath: string,\n data: string | Buffer,\n options: AtomicWriteOptions = {}\n): Promise<void> {\n const { createDir = true, encoding = 'utf-8' } = options;\n \n // Generate a unique temp file path\n const tempSuffix = randomBytes(6).toString('hex');\n const tempPath = `${filePath}.${tempSuffix}.tmp`;\n \n try {\n // Ensure parent directory exists\n if (createDir) {\n await mkdir(dirname(filePath), { recursive: true });\n }\n \n // Write to temp file\n if (typeof data === 'string') {\n await writeFile(tempPath, data, { encoding });\n } else {\n await writeFile(tempPath, data);\n }\n \n // Atomic rename to target path\n await rename(tempPath, filePath);\n } catch (error) {\n // Clean up temp file on failure\n try {\n await unlink(tempPath);\n } catch {\n // Ignore cleanup errors - temp file might not exist\n }\n throw error;\n }\n}\n\n/**\n * Write JSON data to a file atomically\n * \n * Convenience wrapper that handles JSON serialization\n * with optional pretty printing.\n * \n * @param filePath - Target file path\n * @param data - Data to serialize as JSON\n * @param options - Write options and JSON formatting\n * @throws Error if serialization, write, or rename fails\n * \n * @example\n * ```typescript\n * await atomicWriteJSON('/path/to/config.json', { key: 'value' });\n * ```\n */\nexport async function atomicWriteJSON(\n filePath: string,\n data: unknown,\n options: AtomicWriteOptions & {\n /**\n * Spaces for JSON pretty printing\n * @default 2\n */\n spaces?: number;\n } = {}\n): Promise<void> {\n const { spaces = 2, ...writeOptions } = options;\n const json = JSON.stringify(data, null, spaces);\n await atomicWriteFile(filePath, json, writeOptions);\n}\n"],"mappings":";AAYA,SAAS,WAAW,QAAQ,QAAQ,aAAa;AACjD,SAAS,mBAAmB;AAC5B,SAAS,eAAe;AAkCxB,eAAsB,gBACpB,UACA,MACA,UAA8B,CAAC,GAChB;AACf,QAAM,EAAE,YAAY,MAAM,WAAW,QAAQ,IAAI;AAGjD,QAAM,aAAa,YAAY,CAAC,EAAE,SAAS,KAAK;AAChD,QAAM,WAAW,GAAG,QAAQ,IAAI,UAAU;AAE1C,MAAI;AAEF,QAAI,WAAW;AACb,YAAM,MAAM,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAAA,IACpD;AAGA,QAAI,OAAO,SAAS,UAAU;AAC5B,YAAM,UAAU,UAAU,MAAM,EAAE,SAAS,CAAC;AAAA,IAC9C,OAAO;AACL,YAAM,UAAU,UAAU,IAAI;AAAA,IAChC;AAGA,UAAM,OAAO,UAAU,QAAQ;AAAA,EACjC,SAAS,OAAO;AAEd,QAAI;AACF,YAAM,OAAO,QAAQ;AAAA,IACvB,QAAQ;AAAA,IAER;AACA,UAAM;AAAA,EACR;AACF;AAkBA,eAAsB,gBACpB,UACA,MACA,UAMI,CAAC,GACU;AACf,QAAM,EAAE,SAAS,GAAG,GAAG,aAAa,IAAI;AACxC,QAAM,OAAO,KAAK,UAAU,MAAM,MAAM,MAAM;AAC9C,QAAM,gBAAgB,UAAU,MAAM,YAAY;AACpD;","names":[]}
|