@praneeth_54/agentdoctor 2.1.0 → 3.0.1
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/CHANGELOG.md +86 -3
- package/README.md +490 -290
- package/dist/agent/chat/deterministic.d.ts +6 -0
- package/dist/agent/chat/deterministic.js +180 -0
- package/dist/agent/chat/service.js +8 -14
- package/dist/agent/context/retrieve.d.ts +2 -1
- package/dist/agent/context/retrieve.js +14 -1
- package/dist/agent/index.d.ts +2 -0
- package/dist/agent/index.js +1 -0
- package/dist/agent/loop.d.ts +2 -0
- package/dist/agent/loop.js +31 -0
- package/dist/agent/roles.d.ts +12 -0
- package/dist/agent/roles.js +138 -0
- package/dist/agent/runtime.d.ts +21 -5
- package/dist/agent/runtime.js +141 -28
- package/dist/agent/tools/execute.d.ts +2 -0
- package/dist/agent/tools/execute.js +49 -43
- package/dist/agent/tools/write.d.ts +1 -1
- package/dist/agent/tools/write.js +18 -4
- package/dist/ai/config.js +1 -0
- package/dist/ai/providers/adversarial-local.d.ts +7 -0
- package/dist/ai/providers/adversarial-local.js +146 -0
- package/dist/ai/redact.d.ts +1 -0
- package/dist/ai/redact.js +47 -7
- package/dist/ai/types.d.ts +1 -1
- package/dist/cli/commands/agent.d.ts +2 -0
- package/dist/cli/commands/agent.js +32 -11
- package/dist/cli/commands/architecture.js +7 -2
- package/dist/cli/commands/brain.js +7 -2
- package/dist/cli/commands/chat.js +15 -7
- package/dist/cli/commands/complete.js +13 -3
- package/dist/cli/commands/fix.js +6 -0
- package/dist/cli/commands/learn.js +7 -2
- package/dist/cli/commands/mcp.js +7 -3
- package/dist/cli/commands/platform.js +7 -2
- package/dist/cli/commands/policy-graph-run.js +7 -0
- package/dist/cli/commands/product.d.ts +19 -0
- package/dist/cli/commands/product.js +157 -0
- package/dist/cli/commands/scan.js +6 -0
- package/dist/cli/commands/start.d.ts +15 -0
- package/dist/cli/commands/start.js +86 -0
- package/dist/cli/commands/v2.js +61 -11
- package/dist/cli/commands/verify.js +6 -0
- package/dist/cli/program.js +141 -0
- package/dist/cli/safe-root.d.ts +17 -0
- package/dist/cli/safe-root.js +32 -0
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/core/brain-cli/service.js +5 -2
- package/dist/core/monorepo/detect.js +10 -0
- package/dist/core/secrets/scan.js +9 -0
- package/dist/core/understanding/brain/storage/store.d.ts +4 -0
- package/dist/core/understanding/brain/storage/store.js +22 -2
- package/dist/dashboard/page.d.ts +2 -0
- package/dist/dashboard/page.js +53 -0
- package/dist/dashboard/server.js +117 -140
- package/dist/dashboard/ui/client.d.ts +2 -0
- package/dist/dashboard/ui/client.js +2 -0
- package/dist/dashboard/ui/styles.d.ts +2 -0
- package/dist/dashboard/ui/styles.js +138 -0
- package/dist/discovery/files.js +13 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +2 -0
- package/dist/intelligence/graph/build.js +46 -38
- package/dist/intelligence/graph/incremental.d.ts +2 -0
- package/dist/intelligence/graph/incremental.js +9 -0
- package/dist/intelligence/resolve/imports.js +1 -1
- package/dist/languages/dart.d.ts +10 -0
- package/dist/languages/dart.js +99 -0
- package/dist/languages/go.d.ts +13 -7
- package/dist/languages/go.js +84 -24
- package/dist/languages/index.d.ts +5 -1
- package/dist/languages/index.js +13 -36
- package/dist/languages/java.d.ts +10 -0
- package/dist/languages/java.js +80 -0
- package/dist/languages/kotlin.d.ts +10 -0
- package/dist/languages/kotlin.js +85 -0
- package/dist/languages/rust.d.ts +10 -0
- package/dist/languages/rust.js +93 -0
- package/dist/languages/types.d.ts +4 -3
- package/dist/mcp/agent/registry.d.ts +1 -1
- package/dist/mcp/agent/registry.js +109 -23
- package/dist/mcp/intelligence/handlers.d.ts +3 -0
- package/dist/mcp/intelligence/handlers.js +28 -0
- package/dist/mcp/intelligence/path-safety.d.ts +6 -1
- package/dist/mcp/intelligence/path-safety.js +55 -2
- package/dist/mcp/intelligence/registry.d.ts +1 -1
- package/dist/mcp/intelligence/registry.js +30 -1
- package/dist/platform/graph/build.js +9 -0
- package/dist/product/api/doctor.d.ts +14 -0
- package/dist/product/api/doctor.js +185 -0
- package/dist/product/api/openapi.d.ts +7 -0
- package/dist/product/api/openapi.js +122 -0
- package/dist/product/approval/model.d.ts +30 -0
- package/dist/product/approval/model.js +64 -0
- package/dist/product/approval/session.d.ts +49 -0
- package/dist/product/approval/session.js +134 -0
- package/dist/product/database/doctor.d.ts +30 -0
- package/dist/product/database/doctor.js +184 -0
- package/dist/product/decisions/ledger.d.ts +36 -0
- package/dist/product/decisions/ledger.js +141 -0
- package/dist/product/deps/analyze.d.ts +46 -0
- package/dist/product/deps/analyze.js +137 -0
- package/dist/product/deps/lockfiles.d.ts +25 -0
- package/dist/product/deps/lockfiles.js +200 -0
- package/dist/product/discovery/roots.d.ts +52 -0
- package/dist/product/discovery/roots.js +231 -0
- package/dist/product/dna/build.d.ts +50 -0
- package/dist/product/dna/build.js +255 -0
- package/dist/product/eval/lab.d.ts +17 -0
- package/dist/product/eval/lab.js +218 -0
- package/dist/product/events/doctor.d.ts +21 -0
- package/dist/product/events/doctor.js +147 -0
- package/dist/product/evidence-scan.d.ts +12 -0
- package/dist/product/evidence-scan.js +46 -0
- package/dist/product/evolution/timeline.d.ts +29 -0
- package/dist/product/evolution/timeline.js +123 -0
- package/dist/product/features/intelligence.d.ts +23 -0
- package/dist/product/features/intelligence.js +158 -0
- package/dist/product/forensic/mode.d.ts +25 -0
- package/dist/product/forensic/mode.js +70 -0
- package/dist/product/graph/enrich-languages.d.ts +20 -0
- package/dist/product/graph/enrich-languages.js +168 -0
- package/dist/product/health/code-health.d.ts +20 -0
- package/dist/product/health/code-health.js +149 -0
- package/dist/product/index.d.ts +72 -0
- package/dist/product/index.js +36 -0
- package/dist/product/ledger/change-ledger.d.ts +23 -0
- package/dist/product/ledger/change-ledger.js +64 -0
- package/dist/product/map/software-map.d.ts +17 -0
- package/dist/product/map/software-map.js +96 -0
- package/dist/product/memory/institutional.d.ts +16 -0
- package/dist/product/memory/institutional.js +92 -0
- package/dist/product/ops/incident.d.ts +20 -0
- package/dist/product/ops/incident.js +61 -0
- package/dist/product/ops/infra.d.ts +15 -0
- package/dist/product/ops/infra.js +112 -0
- package/dist/product/org/model.d.ts +34 -0
- package/dist/product/org/model.js +195 -0
- package/dist/product/privacy/doctor.d.ts +13 -0
- package/dist/product/privacy/doctor.js +90 -0
- package/dist/product/requirements/trace.d.ts +21 -0
- package/dist/product/requirements/trace.js +166 -0
- package/dist/product/search/index.d.ts +29 -0
- package/dist/product/search/index.js +116 -0
- package/dist/product/search/software-search.d.ts +19 -0
- package/dist/product/search/software-search.js +105 -0
- package/dist/product/security/doctor.d.ts +23 -0
- package/dist/product/security/doctor.js +124 -0
- package/dist/product/self/diagnose.d.ts +15 -0
- package/dist/product/self/diagnose.js +82 -0
- package/dist/product/techdebt/roadmap.d.ts +20 -0
- package/dist/product/techdebt/roadmap.js +118 -0
- package/dist/product/testbrain/analyze.d.ts +29 -0
- package/dist/product/testbrain/analyze.js +129 -0
- package/dist/product/truth.d.ts +12 -0
- package/dist/product/truth.js +30 -0
- package/dist/product/twin/digital-twin.d.ts +23 -0
- package/dist/product/twin/digital-twin.js +52 -0
- package/dist/product/twin/store.d.ts +21 -0
- package/dist/product/twin/store.js +78 -0
- package/dist/product/whatif/engine.d.ts +28 -0
- package/dist/product/whatif/engine.js +91 -0
- package/dist/project/ownership.d.ts +65 -0
- package/dist/project/ownership.js +169 -0
- package/dist/utils/fs.js +10 -2
- package/package.json +1 -1
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/** AgentDoctor dashboard design system CSS. */
|
|
2
|
+
export const DASHBOARD_CSS = `
|
|
3
|
+
:root{
|
|
4
|
+
--bg:#0b0f14;--bg-elev:#111820;--bg-soft:#151d27;--panel:#161e28;--border:#243040;
|
|
5
|
+
--fg:#e8eef5;--muted:#93a0b0;--faint:#6b7888;--accent:#4aa3ff;--accent-2:#2d7fd6;
|
|
6
|
+
--ok:#3ecf8e;--warn:#e6b84d;--crit:#e26060;--unk:#8b9aab;--focus:#7cc4ff;
|
|
7
|
+
--sidebar-w:248px;--sidebar-collapsed:64px;--topbar-h:52px;
|
|
8
|
+
--radius:10px;--font:ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
|
|
9
|
+
--mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
|
|
10
|
+
}
|
|
11
|
+
*{box-sizing:border-box}
|
|
12
|
+
html,body{height:100%;margin:0}
|
|
13
|
+
body{font-family:var(--font);background:var(--bg);color:var(--fg);line-height:1.45;overflow-x:hidden}
|
|
14
|
+
a{color:var(--accent);text-decoration:none}a:hover{text-decoration:underline}
|
|
15
|
+
button,input,textarea,select{font:inherit}
|
|
16
|
+
button:focus-visible,a:focus-visible,input:focus-visible,textarea:focus-visible,[tabindex]:focus-visible{
|
|
17
|
+
outline:2px solid var(--focus);outline-offset:2px}
|
|
18
|
+
.app{display:grid;grid-template-columns:var(--sidebar-w) 1fr;grid-template-rows:var(--topbar-h) 1fr;height:100vh;min-height:100vh}
|
|
19
|
+
.app.collapsed{grid-template-columns:var(--sidebar-collapsed) 1fr}
|
|
20
|
+
.topbar{grid-column:1/-1;display:flex;align-items:center;gap:.75rem;padding:0 .9rem;border-bottom:1px solid var(--border);background:var(--bg-elev);min-width:0}
|
|
21
|
+
.brand{display:flex;align-items:baseline;gap:.45rem;flex:0 0 auto}
|
|
22
|
+
.brand-name{font-weight:700;letter-spacing:.02em;font-size:.98rem}
|
|
23
|
+
.brand-ver{color:var(--muted);font-size:.78rem}
|
|
24
|
+
.project-chip{display:flex;flex-direction:column;min-width:0;max-width:280px;padding:.25rem .55rem;border:1px solid var(--border);border-radius:8px;background:var(--bg-soft)}
|
|
25
|
+
.project-chip strong{font-size:.82rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
26
|
+
.project-chip span{font-size:.7rem;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
27
|
+
.topbar-spacer{flex:1}
|
|
28
|
+
.topbar-actions{display:flex;align-items:center;gap:.4rem;flex:0 0 auto}
|
|
29
|
+
.btn{appearance:none;border:1px solid var(--border);background:var(--bg-soft);color:var(--fg);border-radius:8px;padding:.35rem .65rem;font-size:.8rem;cursor:pointer}
|
|
30
|
+
.btn:hover{border-color:#35506a}
|
|
31
|
+
.btn-accent{background:var(--accent);border-color:var(--accent-2);color:#041018;font-weight:650}
|
|
32
|
+
.btn-ghost{background:transparent}
|
|
33
|
+
.kbd{font-family:var(--mono);font-size:.7rem;color:var(--muted);border:1px solid var(--border);border-radius:5px;padding:.05rem .3rem}
|
|
34
|
+
.sidebar{border-right:1px solid var(--border);background:var(--bg-elev);overflow:auto;padding:.6rem .45rem .9rem;display:flex;flex-direction:column;gap:.35rem}
|
|
35
|
+
.side-toggle{align-self:flex-end;margin:.15rem .2rem .4rem}
|
|
36
|
+
.nav-group{margin:.35rem 0 .15rem}
|
|
37
|
+
.nav-group-label{font-size:.65rem;letter-spacing:.08em;text-transform:uppercase;color:var(--faint);padding:.2rem .55rem;font-weight:650}
|
|
38
|
+
.nav-link{display:flex;align-items:center;gap:.55rem;padding:.42rem .55rem;border-radius:8px;color:var(--muted);font-size:.84rem;text-decoration:none;border:1px solid transparent}
|
|
39
|
+
.nav-link:hover{background:var(--bg-soft);color:var(--fg);text-decoration:none}
|
|
40
|
+
.nav-link.active{background:#1a2838;color:var(--fg);border-color:#2b425a}
|
|
41
|
+
.nav-ico{width:1.1rem;text-align:center;opacity:.85;flex:0 0 auto}
|
|
42
|
+
.app.collapsed .nav-group-label,.app.collapsed .nav-text,.app.collapsed .project-chip span,.app.collapsed .brand-ver{display:none}
|
|
43
|
+
.app.collapsed .nav-link{justify-content:center;padding:.5rem}
|
|
44
|
+
.app.collapsed .project-chip{max-width:100%;padding:.35rem}
|
|
45
|
+
.main{overflow:auto;min-width:0;background:var(--bg)}
|
|
46
|
+
.content{padding:1rem 1.15rem 2rem;max-width:1180px;margin:0 auto}
|
|
47
|
+
.page-header{margin:0 0 1rem}
|
|
48
|
+
.page-header h1{margin:0;font-size:1.35rem;font-weight:700}
|
|
49
|
+
.page-desc{margin:.35rem 0 0;color:var(--muted);font-size:.9rem;max-width:70ch}
|
|
50
|
+
.meta-row{display:flex;flex-wrap:wrap;gap:.35rem;margin-top:.55rem}
|
|
51
|
+
.badge{display:inline-flex;align-items:center;gap:.25rem;padding:.14rem .48rem;border-radius:999px;border:1px solid var(--border);font-size:.72rem;color:var(--muted);background:var(--bg-soft)}
|
|
52
|
+
.badge.ok{color:var(--ok);border-color:#2a5a44}.badge.attention{color:var(--warn);border-color:#5a4a22}
|
|
53
|
+
.badge.warning,.badge.critical{color:var(--crit);border-color:#6a3030}.badge.unknown{color:var(--unk)}
|
|
54
|
+
.badge.truth{text-transform:uppercase;letter-spacing:.04em;font-size:.68rem}
|
|
55
|
+
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:.7rem}
|
|
56
|
+
.card{background:var(--panel);border:1px solid var(--border);border-radius:var(--radius);padding:.85rem .9rem;min-width:0;display:flex;flex-direction:column;gap:.35rem}
|
|
57
|
+
.card h3{margin:0;font-size:.88rem}.card p{margin:0;font-size:.8rem;color:var(--muted)}
|
|
58
|
+
.card .actions{margin-top:auto;padding-top:.35rem}
|
|
59
|
+
.section{margin:1rem 0;background:var(--panel);border:1px solid var(--border);border-radius:var(--radius);padding:1rem}
|
|
60
|
+
.section h2{margin:0 0 .65rem;font-size:1rem}
|
|
61
|
+
.section h3{margin:.8rem 0 .4rem;font-size:.9rem}
|
|
62
|
+
.empty,.error,.loading{padding:1.05rem 1.1rem;border:1px dashed var(--border);border-radius:var(--radius);color:var(--muted);background:var(--bg-soft)}
|
|
63
|
+
.empty strong,.error strong,.loading strong{display:block;color:var(--fg);font-size:.92rem;margin-bottom:.35rem}
|
|
64
|
+
.empty p,.error p,.loading p{margin:.3rem 0 0;font-size:.84rem}
|
|
65
|
+
.error{border-style:solid;border-color:#6a3030;color:#f0b4b4;background:#1a1214}
|
|
66
|
+
.ask-banner{margin:0 0 .85rem;padding:.65rem .8rem;border:1px solid #2b425a;border-radius:var(--radius);background:#121a24;color:var(--muted);font-size:.82rem}
|
|
67
|
+
.ask-banner strong{color:var(--fg)}
|
|
68
|
+
.scope-note{margin:.5rem 0 0;font-size:.8rem;color:var(--faint)}
|
|
69
|
+
.filter-input{width:100%;text-align:left;margin-bottom:.5rem}
|
|
70
|
+
.section-plain{margin:1rem 0}
|
|
71
|
+
.section-plain h2{margin:0 0 .65rem;font-size:1rem}
|
|
72
|
+
.status-dot{width:.55rem;height:.55rem;border-radius:50%;background:var(--ok);display:inline-block;margin-right:.35rem;vertical-align:middle}
|
|
73
|
+
.status-dot.warn{background:var(--warn)}.status-dot.off{background:var(--unk)}
|
|
74
|
+
.topbar-status{font-size:.72rem;color:var(--muted);white-space:nowrap}
|
|
75
|
+
.uncertainty{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:.55rem;margin:.65rem 0}
|
|
76
|
+
.uncertainty .card h3{font-size:.78rem;text-transform:uppercase;letter-spacing:.04em;color:var(--faint)}
|
|
77
|
+
@media (max-width:1280px){
|
|
78
|
+
.content{max-width:100%}
|
|
79
|
+
}
|
|
80
|
+
@media (max-width:1024px){
|
|
81
|
+
.project-chip{max-width:200px}
|
|
82
|
+
}
|
|
83
|
+
@media (max-width:768px){
|
|
84
|
+
.topbar{gap:.45rem;padding:0 .55rem}
|
|
85
|
+
.topbar-status,.brand-ver{display:none}
|
|
86
|
+
.btn .kbd{display:none}
|
|
87
|
+
.content{padding:.75rem .7rem 1.5rem}
|
|
88
|
+
}
|
|
89
|
+
@media (max-width:390px){
|
|
90
|
+
.project-chip{max-width:36vw}
|
|
91
|
+
.brand-name{font-size:.9rem}
|
|
92
|
+
}
|
|
93
|
+
.skeleton{height:.85rem;border-radius:6px;background:linear-gradient(90deg,#15202b,#1c2835,#15202b);background-size:200% 100%;animation:sk 1.2s infinite}
|
|
94
|
+
@keyframes sk{0%{background-position:200% 0}100%{background-position:-200% 0}}
|
|
95
|
+
.table-wrap{overflow:auto;border:1px solid var(--border);border-radius:8px}
|
|
96
|
+
table,.table-wrap table{width:100%;border-collapse:collapse;font-size:.8rem}
|
|
97
|
+
table.data{width:100%;border-collapse:collapse;font-size:.8rem}
|
|
98
|
+
table th,table td,table.data th,table.data td{padding:.45rem .55rem;border-bottom:1px solid var(--border);text-align:left;vertical-align:top}
|
|
99
|
+
table.data th{color:var(--muted);font-weight:600;background:var(--bg-soft);position:sticky;top:0}
|
|
100
|
+
table.data tr:hover td{background:#182230}
|
|
101
|
+
.mono,.code{font-family:var(--mono);font-size:.78rem}
|
|
102
|
+
.tech details{margin-top:.75rem}
|
|
103
|
+
.tech summary{cursor:pointer;color:var(--accent);font-size:.85rem}
|
|
104
|
+
.pre{white-space:pre-wrap;word-break:break-word;font-family:var(--mono);font-size:.75rem;color:#d5dde6;margin:0;max-height:420px;overflow:auto;background:var(--bg-soft);border:1px solid var(--border);border-radius:8px;padding:.65rem}
|
|
105
|
+
.chips{display:flex;flex-wrap:wrap;gap:.3rem}
|
|
106
|
+
.path-sec{font-size:.75rem;color:var(--faint);word-break:break-all;margin:.25rem 0 0}
|
|
107
|
+
.chat-layout{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(240px,1fr);gap:.85rem}
|
|
108
|
+
.chat-log{min-height:280px;max-height:52vh;overflow:auto;border:1px solid var(--border);border-radius:8px;padding:.75rem;background:var(--bg-soft)}
|
|
109
|
+
.chat-msg{margin:0 0 .75rem;padding:.55rem .65rem;border-radius:8px;border:1px solid var(--border);background:var(--panel)}
|
|
110
|
+
.chat-msg.user{border-color:#2b425a}
|
|
111
|
+
.composer{display:flex;flex-direction:column;gap:.45rem;margin-top:.55rem}
|
|
112
|
+
.composer textarea{width:100%;min-height:72px;resize:vertical;background:#0d1520;color:var(--fg);border:1px solid var(--border);border-radius:8px;padding:.55rem}
|
|
113
|
+
.graph-legend{display:flex;flex-wrap:wrap;gap:.4rem;margin:.5rem 0}
|
|
114
|
+
.graph-canvas{width:100%;height:320px;border:1px solid var(--border);border-radius:8px;background:#0d1520;overflow:hidden}
|
|
115
|
+
.palette{position:fixed;inset:0;background:rgba(0,0,0,.55);display:none;align-items:flex-start;justify-content:center;padding:12vh 1rem;z-index:50}
|
|
116
|
+
.palette.open{display:flex}
|
|
117
|
+
.palette-box{width:min(640px,100%);background:var(--bg-elev);border:1px solid var(--border);border-radius:12px;overflow:hidden;box-shadow:0 20px 60px rgba(0,0,0,.45)}
|
|
118
|
+
.palette-box input{width:100%;border:0;border-bottom:1px solid var(--border);background:transparent;color:var(--fg);padding:.85rem 1rem;font-size:1rem}
|
|
119
|
+
.palette-list{max-height:50vh;overflow:auto}
|
|
120
|
+
.palette-item{display:flex;justify-content:space-between;gap:1rem;padding:.65rem 1rem;cursor:pointer;border:0;background:transparent;color:var(--fg);width:100%;text-align:left}
|
|
121
|
+
.palette-item:hover,.palette-item.active{background:var(--bg-soft)}
|
|
122
|
+
.palette-item small{color:var(--muted)}
|
|
123
|
+
.drawer-backdrop{position:fixed;inset:0;background:rgba(0,0,0,.45);display:none;z-index:40}
|
|
124
|
+
.drawer-backdrop.open{display:block}
|
|
125
|
+
.mobile-nav{display:none}
|
|
126
|
+
.safety-row{display:flex;flex-wrap:wrap;gap:.3rem;align-items:center}
|
|
127
|
+
@media (max-width:980px){
|
|
128
|
+
.app,.app.collapsed{grid-template-columns:1fr}
|
|
129
|
+
.sidebar{position:fixed;inset:var(--topbar-h) auto 0 0;width:min(280px,86vw);z-index:45;transform:translateX(-105%);transition:transform .18s ease;box-shadow:8px 0 30px rgba(0,0,0,.35)}
|
|
130
|
+
.sidebar.open{transform:translateX(0)}
|
|
131
|
+
.mobile-nav{display:inline-flex}
|
|
132
|
+
.chat-layout{grid-template-columns:1fr}
|
|
133
|
+
}
|
|
134
|
+
@media (max-width:640px){
|
|
135
|
+
.content{padding:.85rem}.page-header h1{font-size:1.15rem}.grid{grid-template-columns:1fr}
|
|
136
|
+
.project-chip{max-width:42vw}
|
|
137
|
+
}
|
|
138
|
+
`.trim();
|
package/dist/discovery/files.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { DEFAULT_IGNORE_DIRECTORIES, DEFAULT_MAX_FILE_SIZE_BYTES } from "../constants.js";
|
|
4
|
+
import { classifyRelativePathOwnership, decideDirectoryTraversal } from "../project/ownership.js";
|
|
4
5
|
import { isPathInsideRoot, toPosixRelative } from "../utils/path.js";
|
|
5
6
|
import { isLogLikePath } from "./log-like.js";
|
|
6
7
|
/**
|
|
@@ -63,6 +64,15 @@ export async function discoverFiles(options) {
|
|
|
63
64
|
directoriesSkipped.push(relativePath);
|
|
64
65
|
continue;
|
|
65
66
|
}
|
|
67
|
+
const traversal = await decideDirectoryTraversal({
|
|
68
|
+
projectRoot: root,
|
|
69
|
+
absoluteDir: absolutePath,
|
|
70
|
+
relativeDir: relativePath,
|
|
71
|
+
});
|
|
72
|
+
if (!traversal.traverse) {
|
|
73
|
+
directoriesSkipped.push(`${relativePath} (${traversal.ownership})`);
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
66
76
|
queue.push(absolutePath);
|
|
67
77
|
continue;
|
|
68
78
|
}
|
|
@@ -79,6 +89,9 @@ export async function discoverFiles(options) {
|
|
|
79
89
|
filesSkippedOversized += 1;
|
|
80
90
|
continue;
|
|
81
91
|
}
|
|
92
|
+
if (classifyRelativePathOwnership(relativePath) !== "project_owned") {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
82
95
|
files.push({
|
|
83
96
|
absolutePath,
|
|
84
97
|
relativePath,
|
package/dist/index.d.ts
CHANGED
|
@@ -62,4 +62,8 @@ export type { ChatTurnResponse, ChatServiceOptions, TruthClaim, ProjectChatSumma
|
|
|
62
62
|
export { listAgentToolSpecs, getToolSpec, riskForTool, executeAgentTool, isReadTool, newToolCall, evaluateApproval, formatApprovalPrompt, buildAgentPlan, formatAgentPlan, approvePlan, runCodingLoop, verifyAgentWork, formatVerificationReport, } from "./agent/index.js";
|
|
63
63
|
export type { AgentToolName, AgentToolSpec, AgentToolCall, AgentToolResult, AgentRiskLevel, ApprovalRequest, ApprovalResult, ApprovalDecision, AgentPlan, AgentPlanStep, CodingLoopOptions, CodingLoopResult, AgentVerificationReport, VerificationCheck, } from "./agent/index.js";
|
|
64
64
|
export { getModeProfile, defaultStudentMode, parseAgentMode, modeAllowsMutation, modeBlocksToolCategory, StudentService, } from "./agent/index.js";
|
|
65
|
+
export { traceRequirements, analyzeApiSurface, analyzeDatabaseSchema, analyzeEvents, analyzeDependencies, analyzeCodeHealth, buildSoftwareMap, appendChangeLedgerEntry, readChangeLedger, analyzeWhatIf, loadDecisionLedger, runForensicAnalysis, assertForensicReadOnly, buildSoftwareDigitalTwin, runEvalLab, diagnoseAgentDoctorSelf, analyzeInfra, buildIncidentHypotheses, enrichGraphWithLanguageAdapters, analyzeSecuritySurface, analyzePrivacySurface, searchSymbolsAndConcepts, buildTechnicalDebtRoadmap, loadOrganizationModel, saveOrganizationModel, linkProjectToOrgModel, analyzeFeatureIntelligence, buildSoftwareEvolutionTimeline, queryMemory, evaluateApprovalRecord, formatApprovalRecordSummary, issueApprovalGrant, consumeApprovalGrant, hashPlanPayload, hashFileWritePlan, minProductTruth, truthLabelDescription, } from "./product/index.js";
|
|
66
|
+
export type { TruthLabel as ProductTruthLabel, ProductEvidence, RequirementsTraceReport, ApiDoctorReport, DatabaseDoctorReport, EventsDoctorReport, DependencyAnalysisReport, CodeHealthReport, SoftwareMap, ChangeLedgerEntry, WhatIfReport, DecisionRecord, ForensicAnalysisReport, SoftwareDigitalTwin, EvalLabReport, SelfDiagnoseReport, InfraReport, IncidentReport, LanguageGraphEnrichmentStats, SecurityDoctorReport, PrivacyDoctorReport, SoftwareSearchReport, TechnicalDebtRoadmap, OrganizationModel, FeatureIntelligenceReport, SoftwareEvolutionReport, InstitutionalMemoryQueryResult, ApprovalRecord, } from "./product/index.js";
|
|
67
|
+
export { rolePrompt, roleAllowedTools, runRoleAgent } from "./agent/roles.js";
|
|
68
|
+
export type { AgentRole, RoleAgentOptions } from "./agent/roles.js";
|
|
65
69
|
export type { AgentMode, ModeProfile, StudentDocSection, BuildWithMeResult, } from "./agent/index.js";
|
package/dist/index.js
CHANGED
|
@@ -44,3 +44,5 @@ export { ChatService, createChatService, ChatMemory, CHAT_PROVIDER_NONE_MESSAGE,
|
|
|
44
44
|
/** AgentDoctor 2.1 agent tools + plan (M3). */
|
|
45
45
|
export { listAgentToolSpecs, getToolSpec, riskForTool, executeAgentTool, isReadTool, newToolCall, evaluateApproval, formatApprovalPrompt, buildAgentPlan, formatAgentPlan, approvePlan, runCodingLoop, verifyAgentWork, formatVerificationReport, } from "./agent/index.js";
|
|
46
46
|
export { getModeProfile, defaultStudentMode, parseAgentMode, modeAllowsMutation, modeBlocksToolCategory, StudentService, } from "./agent/index.js";
|
|
47
|
+
export { traceRequirements, analyzeApiSurface, analyzeDatabaseSchema, analyzeEvents, analyzeDependencies, analyzeCodeHealth, buildSoftwareMap, appendChangeLedgerEntry, readChangeLedger, analyzeWhatIf, loadDecisionLedger, runForensicAnalysis, assertForensicReadOnly, buildSoftwareDigitalTwin, runEvalLab, diagnoseAgentDoctorSelf, analyzeInfra, buildIncidentHypotheses, enrichGraphWithLanguageAdapters, analyzeSecuritySurface, analyzePrivacySurface, searchSymbolsAndConcepts, buildTechnicalDebtRoadmap, loadOrganizationModel, saveOrganizationModel, linkProjectToOrgModel, analyzeFeatureIntelligence, buildSoftwareEvolutionTimeline, queryMemory, evaluateApprovalRecord, formatApprovalRecordSummary, issueApprovalGrant, consumeApprovalGrant, hashPlanPayload, hashFileWritePlan, minProductTruth, truthLabelDescription, } from "./product/index.js";
|
|
48
|
+
export { rolePrompt, roleAllowedTools, runRoleAgent } from "./agent/roles.js";
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import fs from "node:fs/promises";
|
|
2
1
|
import path from "node:path";
|
|
3
2
|
import { createHash } from "node:crypto";
|
|
4
3
|
import ts from "typescript";
|
|
4
|
+
import { discoverFiles } from "../../discovery/files.js";
|
|
5
5
|
import { resolveRepoRoot, toPosixRelative } from "../../utils/path.js";
|
|
6
6
|
import { buildRepositoryGraph } from "../../platform/graph/build.js";
|
|
7
7
|
import { CONTRACTS_VERSION } from "../../contracts/index.js";
|
|
8
8
|
import { loadTsconfigPaths, resolveImportSpecifier, } from "../resolve/imports.js";
|
|
9
|
+
import { enrichGraphWithLanguageAdapters } from "../../product/graph/enrich-languages.js";
|
|
9
10
|
function evidenceForConfidence(confidence) {
|
|
10
11
|
if (confidence === "EXACT")
|
|
11
12
|
return "verified";
|
|
@@ -16,36 +17,43 @@ function evidenceForConfidence(confidence) {
|
|
|
16
17
|
export function nodeId(kind, key) {
|
|
17
18
|
return `${kind}:${createHash("sha1").update(key).digest("hex").slice(0, 12)}`;
|
|
18
19
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const abs = path.join(dir, e.name);
|
|
36
|
-
if (e.isSymbolicLink())
|
|
37
|
-
continue;
|
|
38
|
-
if (e.isDirectory()) {
|
|
39
|
-
await walk(abs);
|
|
40
|
-
continue;
|
|
41
|
-
}
|
|
42
|
-
if (/\.(ts|tsx|mts|cts)$/i.test(e.name) && !e.name.endsWith(".d.ts")) {
|
|
43
|
-
out.push(abs);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
20
|
+
async function applyLanguageEnrichment(graph, root) {
|
|
21
|
+
try {
|
|
22
|
+
const { graph: enriched, stats } = await enrichGraphWithLanguageAdapters(graph, root);
|
|
23
|
+
const extra = stats.filesParsed > 0
|
|
24
|
+
? [
|
|
25
|
+
`Language adapters enriched graph (+${stats.nodesAdded} nodes, +${stats.edgesAdded} edges, ${stats.filesParsed} files parsed)`,
|
|
26
|
+
]
|
|
27
|
+
: stats.filesAttempted > 0
|
|
28
|
+
? ["Language adapter enrichment: no supported parses in sampled .py/.php/.go files"]
|
|
29
|
+
: [];
|
|
30
|
+
return {
|
|
31
|
+
...enriched,
|
|
32
|
+
builder: graph.builder,
|
|
33
|
+
astFilesParsed: graph.astFilesParsed,
|
|
34
|
+
limitations: [...enriched.limitations, ...extra],
|
|
35
|
+
};
|
|
46
36
|
}
|
|
47
|
-
|
|
48
|
-
|
|
37
|
+
catch (error) {
|
|
38
|
+
return {
|
|
39
|
+
...graph,
|
|
40
|
+
limitations: [
|
|
41
|
+
...graph.limitations,
|
|
42
|
+
`Language adapter enrichment failed (${error instanceof Error ? error.message : String(error)})`,
|
|
43
|
+
],
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export async function listTsFiles(root, limit = 400) {
|
|
48
|
+
const discovered = await discoverFiles({ root });
|
|
49
|
+
return discovered.files
|
|
50
|
+
.filter((f) => {
|
|
51
|
+
const name = path.basename(f.relativePath);
|
|
52
|
+
return /\.(ts|tsx|mts|cts)$/i.test(name) && !name.endsWith(".d.ts");
|
|
53
|
+
})
|
|
54
|
+
.map((f) => f.absolutePath)
|
|
55
|
+
.sort()
|
|
56
|
+
.slice(0, limit);
|
|
49
57
|
}
|
|
50
58
|
/**
|
|
51
59
|
* TypeScript compiler API based graph enrichment.
|
|
@@ -56,13 +64,13 @@ export async function buildIntelligenceGraph(options) {
|
|
|
56
64
|
const mode = options.mode ?? "auto";
|
|
57
65
|
if (mode === "regex") {
|
|
58
66
|
const g = await buildRepositoryGraph(root);
|
|
59
|
-
return { ...g, builder: "regex", astFilesParsed: 0 };
|
|
67
|
+
return applyLanguageEnrichment({ ...g, builder: "regex", astFilesParsed: 0 }, root);
|
|
60
68
|
}
|
|
61
69
|
try {
|
|
62
70
|
const files = await listTsFiles(root);
|
|
63
71
|
if (files.length === 0) {
|
|
64
72
|
const g = await buildRepositoryGraph(root);
|
|
65
|
-
return {
|
|
73
|
+
return applyLanguageEnrichment({
|
|
66
74
|
...g,
|
|
67
75
|
builder: "regex",
|
|
68
76
|
astFilesParsed: 0,
|
|
@@ -70,7 +78,7 @@ export async function buildIntelligenceGraph(options) {
|
|
|
70
78
|
...g.limitations,
|
|
71
79
|
"No TypeScript sources found for AST builder; used regex fallback",
|
|
72
80
|
],
|
|
73
|
-
};
|
|
81
|
+
}, root);
|
|
74
82
|
}
|
|
75
83
|
const program = ts.createProgram({
|
|
76
84
|
rootNames: files,
|
|
@@ -228,7 +236,7 @@ export async function buildIntelligenceGraph(options) {
|
|
|
228
236
|
}
|
|
229
237
|
nodes.sort((a, b) => a.id.localeCompare(b.id));
|
|
230
238
|
edges.sort((a, b) => a.id.localeCompare(b.id));
|
|
231
|
-
return {
|
|
239
|
+
return applyLanguageEnrichment({
|
|
232
240
|
root,
|
|
233
241
|
generatedAt: new Date().toISOString(),
|
|
234
242
|
nodes,
|
|
@@ -239,14 +247,14 @@ export async function buildIntelligenceGraph(options) {
|
|
|
239
247
|
"TypeScript AST builder uses the TypeScript compiler API for .ts/.tsx only",
|
|
240
248
|
"Cross-file call resolution is identifier-based (not full type-checker binding)",
|
|
241
249
|
"Import edges use EXACT|RESOLVED|INFERRED confidence; UNRESOLVED never invents file targets",
|
|
242
|
-
"
|
|
250
|
+
"Additional .py/.php/.go nodes may be merged via language adapters when supported",
|
|
243
251
|
`analysisVersion=${CONTRACTS_VERSION}`,
|
|
244
252
|
],
|
|
245
|
-
};
|
|
253
|
+
}, root);
|
|
246
254
|
}
|
|
247
255
|
catch (error) {
|
|
248
256
|
const g = await buildRepositoryGraph(root);
|
|
249
|
-
return {
|
|
257
|
+
return applyLanguageEnrichment({
|
|
250
258
|
...g,
|
|
251
259
|
builder: "regex",
|
|
252
260
|
astFilesParsed: 0,
|
|
@@ -254,6 +262,6 @@ export async function buildIntelligenceGraph(options) {
|
|
|
254
262
|
...g.limitations,
|
|
255
263
|
`TypeScript AST builder failed; regex fallback used (${error instanceof Error ? error.message : String(error)})`,
|
|
256
264
|
],
|
|
257
|
-
};
|
|
265
|
+
}, root);
|
|
258
266
|
}
|
|
259
267
|
}
|
|
@@ -12,6 +12,8 @@ export interface GraphSnapshot {
|
|
|
12
12
|
nodes: GraphNode[];
|
|
13
13
|
edges: GraphEdge[];
|
|
14
14
|
limitations: string[];
|
|
15
|
+
/** Reject cached graphs built under a prior ownership boundary. */
|
|
16
|
+
ownershipBoundaryVersion?: number;
|
|
15
17
|
}
|
|
16
18
|
export interface GraphStatus {
|
|
17
19
|
present: boolean;
|
|
@@ -3,6 +3,7 @@ import { spawnSync } from "node:child_process";
|
|
|
3
3
|
import fs from "node:fs/promises";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { PACKAGE_VERSION } from "../../constants.js";
|
|
6
|
+
import { OWNERSHIP_BOUNDARY_VERSION } from "../../project/ownership.js";
|
|
6
7
|
import { resolveRepoRoot, toPosixRelative } from "../../utils/path.js";
|
|
7
8
|
import { atomicWriteTextFile } from "../../utils/fs.js";
|
|
8
9
|
import { buildIntelligenceGraph, listTsFiles } from "./build.js";
|
|
@@ -75,6 +76,13 @@ async function loadSnapshot(root) {
|
|
|
75
76
|
if (!isValidSnapshot(parsed)) {
|
|
76
77
|
return { ok: false, corrupt: true, error: "index.json failed schema checks" };
|
|
77
78
|
}
|
|
79
|
+
if (parsed.ownershipBoundaryVersion !== OWNERSHIP_BOUNDARY_VERSION) {
|
|
80
|
+
return {
|
|
81
|
+
ok: false,
|
|
82
|
+
corrupt: false,
|
|
83
|
+
error: `graph index ownership boundary is stale (have ${String(parsed.ownershipBoundaryVersion ?? "missing")}, need ${OWNERSHIP_BOUNDARY_VERSION})`,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
78
86
|
return { ok: true, snapshot: parsed };
|
|
79
87
|
}
|
|
80
88
|
catch (error) {
|
|
@@ -109,6 +117,7 @@ async function buildAndPersist(root, mode = "auto") {
|
|
|
109
117
|
...graph.limitations,
|
|
110
118
|
"Incremental index persists file hashes for change detection",
|
|
111
119
|
],
|
|
120
|
+
ownershipBoundaryVersion: OWNERSHIP_BOUNDARY_VERSION,
|
|
112
121
|
};
|
|
113
122
|
const saved = await persistSnapshot(root, snapshot);
|
|
114
123
|
return { snapshot, path: saved };
|
|
@@ -143,7 +143,7 @@ function matchTsconfigPath(specifier, config) {
|
|
|
143
143
|
specifier.endsWith(suffix)) {
|
|
144
144
|
const star = specifier.slice(prefix.length, specifier.length - suffix.length);
|
|
145
145
|
const target = targets[0];
|
|
146
|
-
const mapped = target.includes("*") ? target.
|
|
146
|
+
const mapped = target.includes("*") ? target.split("*").join(star) : target;
|
|
147
147
|
return { mapped, pattern };
|
|
148
148
|
}
|
|
149
149
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { LanguageAdapter, LanguageImport, LanguageSymbol } from "./types.js";
|
|
2
|
+
export interface DartParseSummary {
|
|
3
|
+
libraryName: string;
|
|
4
|
+
imports: LanguageImport[];
|
|
5
|
+
symbols: LanguageSymbol[];
|
|
6
|
+
limitations: string[];
|
|
7
|
+
}
|
|
8
|
+
/** Lightweight line-oriented Dart scan — not Dart analyzer APIs. */
|
|
9
|
+
export declare function parseDartSource(filePath: string, source: string): DartParseSummary;
|
|
10
|
+
export declare const dartAdapter: LanguageAdapter;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/** Lightweight line-oriented Dart scan — not Dart analyzer APIs. */
|
|
2
|
+
export function parseDartSource(filePath, source) {
|
|
3
|
+
const lines = source.split(/\r?\n/);
|
|
4
|
+
const limitations = [
|
|
5
|
+
"Dart parsing uses a lightweight line scanner — not the Dart analyzer; calls/types are partial.",
|
|
6
|
+
"Full Dart analyzer or tree-sitter-dart integration remains an EXTERNAL enhancement path (not bundled).",
|
|
7
|
+
];
|
|
8
|
+
let libraryName = "";
|
|
9
|
+
const imports = [];
|
|
10
|
+
const symbols = [];
|
|
11
|
+
for (let i = 0; i < lines.length; i++) {
|
|
12
|
+
const trimmed = lines[i].trim();
|
|
13
|
+
if (!libraryName && trimmed.startsWith("library ")) {
|
|
14
|
+
libraryName = trimmed.slice("library ".length).replace(/;$/, "").trim();
|
|
15
|
+
}
|
|
16
|
+
if (trimmed.startsWith("import ") && trimmed.endsWith(";")) {
|
|
17
|
+
const spec = trimmed
|
|
18
|
+
.slice("import ".length, -1)
|
|
19
|
+
.replace(/^['"]|['"]$/g, "")
|
|
20
|
+
.trim();
|
|
21
|
+
if (spec)
|
|
22
|
+
imports.push({ fromFile: filePath, specifier: spec, evidence: "ast" });
|
|
23
|
+
}
|
|
24
|
+
if (trimmed.startsWith("export ") && trimmed.endsWith(";")) {
|
|
25
|
+
const spec = trimmed
|
|
26
|
+
.slice("export ".length, -1)
|
|
27
|
+
.replace(/^['"]|['"]$/g, "")
|
|
28
|
+
.trim();
|
|
29
|
+
if (spec)
|
|
30
|
+
imports.push({ fromFile: filePath, specifier: spec, evidence: "ast" });
|
|
31
|
+
}
|
|
32
|
+
const typeMatch = /^(?:abstract\s+)?(?:class|mixin|extension)\s+(\w+)/.exec(trimmed);
|
|
33
|
+
if (typeMatch) {
|
|
34
|
+
let kind = "class";
|
|
35
|
+
if (trimmed.includes("mixin"))
|
|
36
|
+
kind = "mixin";
|
|
37
|
+
else if (trimmed.includes("extension"))
|
|
38
|
+
kind = "extension";
|
|
39
|
+
symbols.push({
|
|
40
|
+
id: `dart:${kind}:${filePath}:${typeMatch[1]}`,
|
|
41
|
+
name: typeMatch[1],
|
|
42
|
+
kind,
|
|
43
|
+
file: filePath,
|
|
44
|
+
line: i + 1,
|
|
45
|
+
evidence: "ast",
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
const fnMatch = /^(?:\w+\s+)?(\w+)\s*\([^)]*\)\s*(?:async\s*)?\{?\s*$/.exec(trimmed);
|
|
49
|
+
if (fnMatch &&
|
|
50
|
+
!trimmed.startsWith("if ") &&
|
|
51
|
+
!trimmed.startsWith("for ") &&
|
|
52
|
+
!trimmed.startsWith("while ") &&
|
|
53
|
+
!trimmed.startsWith("class ") &&
|
|
54
|
+
!trimmed.startsWith("return ")) {
|
|
55
|
+
const name = fnMatch[1];
|
|
56
|
+
if (!["void", "final", "const", "var", "late"].includes(name)) {
|
|
57
|
+
symbols.push({
|
|
58
|
+
id: `dart:function:${filePath}:${name}`,
|
|
59
|
+
name,
|
|
60
|
+
kind: "function",
|
|
61
|
+
file: filePath,
|
|
62
|
+
line: i + 1,
|
|
63
|
+
evidence: "ast",
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return { libraryName, imports, symbols, limitations };
|
|
69
|
+
}
|
|
70
|
+
const DART_CAPABILITIES = () => ({
|
|
71
|
+
parse: "supported",
|
|
72
|
+
symbols: "supported",
|
|
73
|
+
definitions: "unsupported",
|
|
74
|
+
references: "unsupported",
|
|
75
|
+
imports: "supported",
|
|
76
|
+
calls: "partial",
|
|
77
|
+
diagnostics: "unsupported",
|
|
78
|
+
types: "partial",
|
|
79
|
+
});
|
|
80
|
+
export const dartAdapter = {
|
|
81
|
+
id: "dart",
|
|
82
|
+
extensions: [".dart"],
|
|
83
|
+
capabilities: DART_CAPABILITIES,
|
|
84
|
+
async parse(filePath, source) {
|
|
85
|
+
const summary = parseDartSource(filePath, source);
|
|
86
|
+
const ok = Boolean(summary.libraryName || summary.symbols.length > 0 || summary.imports.length > 0);
|
|
87
|
+
return {
|
|
88
|
+
language: "dart",
|
|
89
|
+
file: filePath,
|
|
90
|
+
ok,
|
|
91
|
+
capabilities: dartAdapter.capabilities(),
|
|
92
|
+
symbols: summary.symbols,
|
|
93
|
+
imports: summary.imports,
|
|
94
|
+
calls: [],
|
|
95
|
+
diagnostics: ok ? [] : ["no library, import, or declarations detected"],
|
|
96
|
+
limitations: summary.limitations,
|
|
97
|
+
};
|
|
98
|
+
},
|
|
99
|
+
};
|
package/dist/languages/go.d.ts
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import type { LanguageAdapter } from "./types.js";
|
|
2
|
-
/**
|
|
3
|
-
* Go toolchain bridge placeholder.
|
|
4
|
-
* Prefer real `go/ast` via `go run` when the Go toolchain is present; until an
|
|
5
|
-
* extractor is bundled, capability remains unsupported even if `go` exists.
|
|
6
|
-
* Today: always unsupported (no bundled extractor; avoids fake AST claims).
|
|
7
|
-
*/
|
|
1
|
+
import type { LanguageAdapter, LanguageSymbol, LanguageImport } from "./types.js";
|
|
8
2
|
export declare function goAvailable(): boolean;
|
|
3
|
+
export interface GoSourceRange {
|
|
4
|
+
startLine: number;
|
|
5
|
+
endLine: number;
|
|
6
|
+
}
|
|
7
|
+
export interface GoParseSummary {
|
|
8
|
+
packageName: string;
|
|
9
|
+
imports: LanguageImport[];
|
|
10
|
+
symbols: LanguageSymbol[];
|
|
11
|
+
limitations: string[];
|
|
12
|
+
}
|
|
13
|
+
/** Lightweight line-oriented Go scan (not go/ast). Honest partial call resolution. */
|
|
14
|
+
export declare function parseGoSource(filePath: string, source: string): GoParseSummary;
|
|
9
15
|
export declare const goAdapter: LanguageAdapter;
|
package/dist/languages/go.js
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
2
|
const GO_PROBE_TIMEOUT_MS = 5_000;
|
|
3
|
-
/**
|
|
4
|
-
* Go toolchain bridge placeholder.
|
|
5
|
-
* Prefer real `go/ast` via `go run` when the Go toolchain is present; until an
|
|
6
|
-
* extractor is bundled, capability remains unsupported even if `go` exists.
|
|
7
|
-
* Today: always unsupported (no bundled extractor; avoids fake AST claims).
|
|
8
|
-
*/
|
|
9
3
|
export function goAvailable() {
|
|
10
4
|
const r = spawnSync("go", ["version"], {
|
|
11
5
|
encoding: "utf8",
|
|
@@ -14,37 +8,103 @@ export function goAvailable() {
|
|
|
14
8
|
});
|
|
15
9
|
return r.status === 0 && !r.error;
|
|
16
10
|
}
|
|
11
|
+
function lineTrimmed(source, lineIndex) {
|
|
12
|
+
const lines = source.split(/\r?\n/);
|
|
13
|
+
return lines[lineIndex]?.trim() ?? "";
|
|
14
|
+
}
|
|
15
|
+
/** Lightweight line-oriented Go scan (not go/ast). Honest partial call resolution. */
|
|
16
|
+
export function parseGoSource(filePath, source) {
|
|
17
|
+
const lines = source.split(/\r?\n/);
|
|
18
|
+
const limitations = [
|
|
19
|
+
"Go parsing uses a lightweight line scanner — not go/ast; calls are not resolved.",
|
|
20
|
+
goAvailable()
|
|
21
|
+
? "Go toolchain is present; full go/ast bridge remains EXTERNAL (not bundled)."
|
|
22
|
+
: "Go toolchain not on PATH; same lightweight scanner used.",
|
|
23
|
+
];
|
|
24
|
+
let packageName = "";
|
|
25
|
+
const imports = [];
|
|
26
|
+
const symbols = [];
|
|
27
|
+
for (let i = 0; i < lines.length; i++) {
|
|
28
|
+
const raw = lines[i];
|
|
29
|
+
const trimmed = raw.trim();
|
|
30
|
+
if (!packageName && trimmed.startsWith("package ") && !trimmed.startsWith("package (")) {
|
|
31
|
+
packageName = trimmed.slice("package ".length).split(/\s+/)[0] ?? "";
|
|
32
|
+
}
|
|
33
|
+
if (trimmed.startsWith("import ") || trimmed === "import (") {
|
|
34
|
+
if (trimmed === "import (") {
|
|
35
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
36
|
+
const inner = lines[j].trim();
|
|
37
|
+
if (inner === ")") {
|
|
38
|
+
i = j;
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
const spec = inner.replace(/^"|"$/g, "").replace(/^'|'$/g, "");
|
|
42
|
+
if (spec && spec !== "") {
|
|
43
|
+
imports.push({ fromFile: filePath, specifier: spec, evidence: "ast" });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
const spec = trimmed.slice("import ".length).replace(/^"|"$/g, "").trim();
|
|
49
|
+
if (spec)
|
|
50
|
+
imports.push({ fromFile: filePath, specifier: spec, evidence: "ast" });
|
|
51
|
+
}
|
|
52
|
+
if (trimmed.startsWith("func ")) {
|
|
53
|
+
const nameMatch = /^func\s+(?:\([^)]*\)\s+)?(\w+)/.exec(trimmed);
|
|
54
|
+
if (nameMatch) {
|
|
55
|
+
symbols.push({
|
|
56
|
+
id: `go:func:${filePath}:${nameMatch[1]}`,
|
|
57
|
+
name: nameMatch[1],
|
|
58
|
+
kind: "function",
|
|
59
|
+
file: filePath,
|
|
60
|
+
line: i + 1,
|
|
61
|
+
evidence: "ast",
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (trimmed.startsWith("type ")) {
|
|
66
|
+
const typeMatch = /^type\s+(\w+)/.exec(trimmed);
|
|
67
|
+
if (typeMatch) {
|
|
68
|
+
symbols.push({
|
|
69
|
+
id: `go:type:${filePath}:${typeMatch[1]}`,
|
|
70
|
+
name: typeMatch[1],
|
|
71
|
+
kind: "type",
|
|
72
|
+
file: filePath,
|
|
73
|
+
line: i + 1,
|
|
74
|
+
evidence: "ast",
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (!packageName) {
|
|
80
|
+
limitations.push(`No package clause detected in ${lineTrimmed(source, 0) || "(file)"}`);
|
|
81
|
+
}
|
|
82
|
+
return { packageName, imports, symbols, limitations };
|
|
83
|
+
}
|
|
17
84
|
export const goAdapter = {
|
|
18
85
|
id: "go",
|
|
19
86
|
extensions: [".go"],
|
|
20
87
|
capabilities: () => ({
|
|
21
|
-
parse: "
|
|
22
|
-
symbols: "
|
|
88
|
+
parse: "supported",
|
|
89
|
+
symbols: "supported",
|
|
23
90
|
definitions: "unsupported",
|
|
24
91
|
references: "unsupported",
|
|
25
|
-
imports: "
|
|
26
|
-
calls: "
|
|
92
|
+
imports: "supported",
|
|
93
|
+
calls: "partial",
|
|
27
94
|
diagnostics: "unsupported",
|
|
28
95
|
}),
|
|
29
|
-
async parse(filePath,
|
|
30
|
-
const
|
|
96
|
+
async parse(filePath, source) {
|
|
97
|
+
const summary = parseGoSource(filePath, source);
|
|
31
98
|
return {
|
|
32
99
|
language: "go",
|
|
33
100
|
file: filePath,
|
|
34
|
-
ok:
|
|
101
|
+
ok: Boolean(summary.packageName),
|
|
35
102
|
capabilities: goAdapter.capabilities(),
|
|
36
|
-
symbols:
|
|
37
|
-
imports:
|
|
103
|
+
symbols: summary.symbols,
|
|
104
|
+
imports: summary.imports,
|
|
38
105
|
calls: [],
|
|
39
|
-
diagnostics: [
|
|
40
|
-
|
|
41
|
-
? "Go toolchain present but AgentDoctor go/ast extractor is not bundled yet"
|
|
42
|
-
: "go not available on PATH",
|
|
43
|
-
],
|
|
44
|
-
limitations: [
|
|
45
|
-
"Go AST requires a go/ast bridge or tree-sitter-go; not shipped in this package",
|
|
46
|
-
"Capability remains unsupported — no regex fallback under an AST claim",
|
|
47
|
-
],
|
|
106
|
+
diagnostics: summary.packageName ? [] : ["missing package clause"],
|
|
107
|
+
limitations: summary.limitations,
|
|
48
108
|
};
|
|
49
109
|
},
|
|
50
110
|
};
|