@wrongstack/core 0.310.1 → 0.313.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/dist/chronicle/index.js +84 -6391
- package/dist/chronicle/project-server.js +84 -4868
- package/dist/chunk-2BUUIMQB.js +225 -0
- package/dist/chunk-2FK4WTFF.js +207 -0
- package/dist/chunk-2FQL4PDC.js +292 -0
- package/dist/chunk-2KKODIQU.js +2256 -0
- package/dist/chunk-2YU4WVBW.js +134 -0
- package/dist/chunk-3E244UDA.js +356 -0
- package/dist/chunk-3XPVB7BA.js +135 -0
- package/dist/chunk-4LJJYBAU.js +388 -0
- package/dist/chunk-4VWO3ZXL.js +342 -0
- package/dist/chunk-4XV6IR37.js +187 -0
- package/dist/chunk-4ZHTKJHM.js +183 -0
- package/dist/chunk-52RTVH4M.js +361 -0
- package/dist/chunk-57GEWK5X.js +26 -0
- package/dist/chunk-5DSMEVA4.js +931 -0
- package/dist/chunk-5RP3QTRL.js +1223 -0
- package/dist/chunk-5S437PRC.js +50 -0
- package/dist/chunk-5XDUGTKN.js +511 -0
- package/dist/chunk-62V2AFVG.js +422 -0
- package/dist/chunk-65RDIOR2.js +2470 -0
- package/dist/chunk-6AKOTGLM.js +597 -0
- package/dist/chunk-7ZHZE5EO.js +28 -0
- package/dist/chunk-A455ATZB.js +140 -0
- package/dist/chunk-AD7ZFZCS.js +46 -0
- package/dist/chunk-AI4LLQ2U.js +856 -0
- package/dist/chunk-ASX6AW36.js +789 -0
- package/dist/chunk-AT4V4XGI.js +3522 -0
- package/dist/chunk-AWNQ6ED6.js +311 -0
- package/dist/chunk-B4AMLZPB.js +9 -0
- package/dist/chunk-BAKVJLEV.js +417 -0
- package/dist/chunk-BJHVULHO.js +55 -0
- package/dist/chunk-CB2HFKTP.js +9 -0
- package/dist/chunk-CE4ZOCOI.js +1640 -0
- package/dist/chunk-CQQL4ZOQ.js +151 -0
- package/dist/chunk-DEIQMBD2.js +65 -0
- package/dist/chunk-E6I5RXVK.js +58 -0
- package/dist/chunk-EFEHDQGY.js +1589 -0
- package/dist/chunk-EODDVJBM.js +82 -0
- package/dist/chunk-EPC3GZD4.js +308 -0
- package/dist/chunk-FAYRX2AD.js +13 -0
- package/dist/chunk-FFSX2QDQ.js +362 -0
- package/dist/chunk-FHAMQS7Q.js +5856 -0
- package/dist/chunk-FIV4IJL7.js +2263 -0
- package/dist/chunk-FNXVT7HF.js +52 -0
- package/dist/chunk-FSWCWSTS.js +395 -0
- package/dist/chunk-FW5LDDMJ.js +16464 -0
- package/dist/chunk-FXQLIX3K.js +211 -0
- package/dist/chunk-G5AAKEEZ.js +228 -0
- package/dist/chunk-G5S3S5ZN.js +38 -0
- package/dist/chunk-GAZEWQEZ.js +231 -0
- package/dist/chunk-GFJOMSHG.js +125 -0
- package/dist/chunk-GFXZTHNI.js +158 -0
- package/dist/chunk-GM54GJBU.js +960 -0
- package/dist/chunk-GPQ3NJPR.js +900 -0
- package/dist/chunk-GTCU6DZ3.js +1 -0
- package/dist/chunk-H5E77KUJ.js +15 -0
- package/dist/chunk-H72H4XDU.js +1023 -0
- package/dist/chunk-HA4ZYA6T.js +178 -0
- package/dist/chunk-I45KAW2N.js +5020 -0
- package/dist/chunk-IQ35HMQL.js +1396 -0
- package/dist/chunk-IYFBFX34.js +86 -0
- package/dist/chunk-JJPMWPB6.js +109 -0
- package/dist/chunk-JTHKOYWU.js +663 -0
- package/dist/chunk-JVGPR3TS.js +365 -0
- package/dist/chunk-JVKB2TBL.js +48 -0
- package/dist/chunk-JX7VBZDK.js +31 -0
- package/dist/chunk-K3G6JBUC.js +5232 -0
- package/dist/chunk-K4YUNKU7.js +589 -0
- package/dist/chunk-KBZGE6LN.js +710 -0
- package/dist/chunk-KDQJCT2J.js +45 -0
- package/dist/chunk-KI4L2DUL.js +560 -0
- package/dist/chunk-KJ2ZTQSL.js +47 -0
- package/dist/chunk-KSJ5UTP7.js +154 -0
- package/dist/chunk-LHOA5DWA.js +28 -0
- package/dist/chunk-LX5QWLBL.js +27 -0
- package/dist/chunk-LZDDLNCZ.js +279 -0
- package/dist/chunk-M2WF6AXG.js +115 -0
- package/dist/chunk-M7BS2K6U.js +1 -0
- package/dist/chunk-NDBIPFNY.js +102 -0
- package/dist/chunk-NEMIWEXC.js +1199 -0
- package/dist/chunk-NFAYHPRH.js +323 -0
- package/dist/chunk-O37BQ65S.js +21 -0
- package/dist/chunk-O74MJHXU.js +187 -0
- package/dist/chunk-OJZEX73F.js +112 -0
- package/dist/chunk-PAAWLLZX.js +74 -0
- package/dist/chunk-PFXFQQRT.js +339 -0
- package/dist/chunk-PFZO3C6H.js +14 -0
- package/dist/chunk-PHH7LD45.js +113 -0
- package/dist/chunk-QRTG4XTI.js +188 -0
- package/dist/chunk-QVOVMXJR.js +1351 -0
- package/dist/chunk-RCQYT2I4.js +757 -0
- package/dist/chunk-RD6DEE36.js +1178 -0
- package/dist/chunk-RJIZEJ42.js +30 -0
- package/dist/chunk-RPOA7IAE.js +150 -0
- package/dist/chunk-SN2DQRL6.js +1172 -0
- package/dist/chunk-SQJVFEBV.js +41 -0
- package/dist/chunk-SQP64RCS.js +5391 -0
- package/dist/chunk-SVT4RNTR.js +49 -0
- package/dist/chunk-SWUFN7XM.js +43 -0
- package/dist/chunk-SXMVYC5H.js +174 -0
- package/dist/chunk-SZ6AYUIZ.js +23 -0
- package/dist/chunk-T3KGZBU5.js +3171 -0
- package/dist/chunk-TBRL2RCC.js +9 -0
- package/dist/chunk-TRT2HRWZ.js +18 -0
- package/dist/chunk-TYW2GI5I.js +1077 -0
- package/dist/chunk-UIWONWVG.js +4959 -0
- package/dist/chunk-VB3H5WWB.js +151 -0
- package/dist/chunk-W4A6QA3D.js +258 -0
- package/dist/chunk-WBPVKEEE.js +227 -0
- package/dist/chunk-WEBMSQP2.js +123 -0
- package/dist/chunk-WOEZV3Q4.js +333 -0
- package/dist/chunk-WQQON3SV.js +473 -0
- package/dist/chunk-WQTOVMGV.js +119 -0
- package/dist/chunk-WZO23AWO.js +2779 -0
- package/dist/chunk-XBDP4QPW.js +7 -0
- package/dist/chunk-XEBHSJLT.js +103 -0
- package/dist/chunk-XQ2ECNK3.js +1 -0
- package/dist/chunk-XQ2XGIBF.js +2086 -0
- package/dist/chunk-Y2GE5TSI.js +355 -0
- package/dist/chunk-YBUJCZ57.js +351 -0
- package/dist/chunk-YNCVSFGF.js +149 -0
- package/dist/chunk-YUPMXOGP.js +282 -0
- package/dist/chunk-YY6APYUM.js +49 -0
- package/dist/chunk-Z2IJUO45.js +691 -0
- package/dist/chunk-ZEHUCJHY.js +129 -0
- package/dist/chunk-ZYU2YOJ6.js +1496 -0
- package/dist/chunk-ZZ4V3WIZ.js +163 -0
- package/dist/coordination/agents/index.js +145 -6260
- package/dist/coordination/index.js +365 -34323
- package/dist/coordination/mailbox-project-server.js +48 -3220
- package/dist/coordination/mailbox-types.d.ts +13 -1
- package/dist/coordination/provider-status-tracker.d.ts +4 -0
- package/dist/coordination/sqlite-mailbox.d.ts +2 -1
- package/dist/core/agent.d.ts +14 -1
- package/dist/core/index.js +267 -12479
- package/dist/core/model-ref.js +5 -23
- package/dist/core/provider-runner.d.ts +36 -1
- package/dist/design/index.js +50 -1087
- package/dist/execution/index.d.ts +1 -1
- package/dist/execution/index.js +1599 -21887
- package/dist/execution/prompt-enhancer.js +16 -535
- package/dist/execution/retry-policy.d.ts +31 -1
- package/dist/extension/index.js +7 -311
- package/dist/goal/index.js +33 -3435
- package/dist/hooks/index.js +14 -1138
- package/dist/hq/index.js +112 -5139
- package/dist/hq/protocol.js +21 -668
- package/dist/index.js +1410 -92655
- package/dist/infrastructure/index.js +64 -4811
- package/dist/kernel/events/provider-events.d.ts +15 -0
- package/dist/kernel/events/wrongtrace-events.d.ts +26 -0
- package/dist/kernel/events.d.ts +16 -7
- package/dist/kernel/index.js +14 -992
- package/dist/models/index.js +40 -1117
- package/dist/notifications/index.js +3 -108
- package/dist/observability/index.js +17 -279
- package/dist/plugin/index.js +584 -14835
- package/dist/prompts/index.js +14 -948
- package/dist/registry/index.js +9 -822
- package/dist/registry-R23UBE7H.js +14 -0
- package/dist/replay/index.js +6 -84
- package/dist/review-finding-store-DKAV3AS6.js +21 -0
- package/dist/review-report-store-OWY3EC3N.js +19 -0
- package/dist/security/index.js +114 -2202
- package/dist/session-catalog/index.js +36 -2103
- package/dist/session-catalog/project-server.js +42 -1435
- package/dist/skills/index.js +35 -1578
- package/dist/storage/index.js +182 -15600
- package/dist/tasking/index.js +10 -676
- package/dist/tools/index.js +52 -9589
- package/dist/types/config/autonomy.d.ts +5 -0
- package/dist/types/config/tools.d.ts +2 -2
- package/dist/types/config/ui.d.ts +1 -1
- package/dist/types/errors.d.ts +18 -0
- package/dist/types/index.js +121 -1341
- package/dist/types/provider-runner.d.ts +8 -0
- package/dist/types/session-markers.js +8 -144
- package/dist/utils/error.js +3 -4
- package/dist/utils/expect-defined.js +3 -9
- package/dist/utils/heap-watchdog.js +6 -706
- package/dist/utils/index.js +269 -5685
- package/dist/utils/sage-output-block.js +5 -42
- package/dist/wiring/proxy-rewrite.d.ts +92 -4
- package/dist/wiring/proxy-rewrite.js +20 -61
- package/dist/worktree/index.js +6 -887
- package/package.json +4 -4
|
@@ -0,0 +1,663 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DefaultConfigLoader
|
|
3
|
+
} from "./chunk-IQ35HMQL.js";
|
|
4
|
+
import {
|
|
5
|
+
DefaultSecretVault,
|
|
6
|
+
migratePlaintextSecrets
|
|
7
|
+
} from "./chunk-6AKOTGLM.js";
|
|
8
|
+
import {
|
|
9
|
+
DefaultLogger,
|
|
10
|
+
noOpLogger
|
|
11
|
+
} from "./chunk-WBPVKEEE.js";
|
|
12
|
+
import {
|
|
13
|
+
promptCacheHitRatio
|
|
14
|
+
} from "./chunk-NFAYHPRH.js";
|
|
15
|
+
import {
|
|
16
|
+
activateProjectStateGuard
|
|
17
|
+
} from "./chunk-CQQL4ZOQ.js";
|
|
18
|
+
import {
|
|
19
|
+
safeParse
|
|
20
|
+
} from "./chunk-RPOA7IAE.js";
|
|
21
|
+
import {
|
|
22
|
+
ensureProjectGitignore,
|
|
23
|
+
ensureProjectIdentity,
|
|
24
|
+
readProjectIdentity
|
|
25
|
+
} from "./chunk-4XV6IR37.js";
|
|
26
|
+
import {
|
|
27
|
+
writeErr
|
|
28
|
+
} from "./chunk-4VWO3ZXL.js";
|
|
29
|
+
import {
|
|
30
|
+
atomicWrite
|
|
31
|
+
} from "./chunk-7ZHZE5EO.js";
|
|
32
|
+
import {
|
|
33
|
+
canonicalProjectRoot,
|
|
34
|
+
resolveWstackPaths,
|
|
35
|
+
safeProfileName
|
|
36
|
+
} from "./chunk-YNCVSFGF.js";
|
|
37
|
+
import {
|
|
38
|
+
normalizeTokenSavingTier
|
|
39
|
+
} from "./chunk-KJ2ZTQSL.js";
|
|
40
|
+
import {
|
|
41
|
+
toErrorMessage
|
|
42
|
+
} from "./chunk-TBRL2RCC.js";
|
|
43
|
+
|
|
44
|
+
// src/infrastructure/path-resolver.ts
|
|
45
|
+
import * as fs from "node:fs";
|
|
46
|
+
import * as os from "node:os";
|
|
47
|
+
import * as path from "node:path";
|
|
48
|
+
var PROJECT_MARKERS = [
|
|
49
|
+
".git",
|
|
50
|
+
"package.json",
|
|
51
|
+
"pnpm-workspace.yaml",
|
|
52
|
+
"go.mod",
|
|
53
|
+
"Cargo.toml",
|
|
54
|
+
"pyproject.toml",
|
|
55
|
+
// Use AGENTS.md, not the bare .wrongstack directory. A bare .wrongstack/
|
|
56
|
+
// directory can be the global config directory (~/.wrongstack), which is
|
|
57
|
+
// NOT a project marker. Only .wrongstack/AGENTS.md signals a real
|
|
58
|
+
// WrongStack project.
|
|
59
|
+
".wrongstack/AGENTS.md"
|
|
60
|
+
];
|
|
61
|
+
var DefaultPathResolver = class {
|
|
62
|
+
projectRoot;
|
|
63
|
+
cwd;
|
|
64
|
+
constructor(cwd = process.cwd()) {
|
|
65
|
+
this.cwd = path.resolve(cwd);
|
|
66
|
+
this.projectRoot = this.detectProjectRoot(this.cwd);
|
|
67
|
+
}
|
|
68
|
+
detectProjectRoot(start) {
|
|
69
|
+
let dir = path.resolve(start);
|
|
70
|
+
const root = path.parse(dir).root;
|
|
71
|
+
const home = path.resolve(os.homedir());
|
|
72
|
+
const startPath = path.resolve(start);
|
|
73
|
+
while (dir !== root) {
|
|
74
|
+
if (dir === home && dir !== startPath) {
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
for (const marker of PROJECT_MARKERS) {
|
|
78
|
+
try {
|
|
79
|
+
fs.accessSync(path.join(dir, marker));
|
|
80
|
+
return dir;
|
|
81
|
+
} catch {
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const parent = path.dirname(dir);
|
|
85
|
+
if (parent === dir) break;
|
|
86
|
+
dir = parent;
|
|
87
|
+
}
|
|
88
|
+
return startPath;
|
|
89
|
+
}
|
|
90
|
+
resolve(input) {
|
|
91
|
+
const abs = path.isAbsolute(input) ? input : path.resolve(this.cwd, input);
|
|
92
|
+
let real;
|
|
93
|
+
try {
|
|
94
|
+
real = fs.realpathSync(abs);
|
|
95
|
+
} catch {
|
|
96
|
+
real = path.normalize(abs);
|
|
97
|
+
}
|
|
98
|
+
return real;
|
|
99
|
+
}
|
|
100
|
+
isInsideRoot(absPath) {
|
|
101
|
+
const normalized = path.normalize(absPath);
|
|
102
|
+
const root = path.normalize(this.projectRoot);
|
|
103
|
+
if (normalized === root) return true;
|
|
104
|
+
const rel = path.relative(root, normalized);
|
|
105
|
+
return !rel.startsWith("..") && !path.isAbsolute(rel);
|
|
106
|
+
}
|
|
107
|
+
ensureInsideRoot(absPath) {
|
|
108
|
+
const resolved = this.resolve(absPath);
|
|
109
|
+
if (!this.isInsideRoot(resolved)) {
|
|
110
|
+
const display = path.isAbsolute(absPath) ? path.basename(absPath) : absPath;
|
|
111
|
+
const err = new Error(`Path "${display}" resolves outside the project root`);
|
|
112
|
+
err.fullPath = absPath;
|
|
113
|
+
err.projectRoot = this.projectRoot;
|
|
114
|
+
throw err;
|
|
115
|
+
}
|
|
116
|
+
return resolved;
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// src/boot.ts
|
|
121
|
+
import * as fs2 from "node:fs/promises";
|
|
122
|
+
import * as os2 from "node:os";
|
|
123
|
+
import * as path2 from "node:path";
|
|
124
|
+
async function bootConfig(options = {}) {
|
|
125
|
+
const {
|
|
126
|
+
flags = {},
|
|
127
|
+
appLabel = "wstack",
|
|
128
|
+
loadSyncConfig = true,
|
|
129
|
+
skipIdentityValidation = false
|
|
130
|
+
} = options;
|
|
131
|
+
const cwd = typeof flags["cwd"] === "string" ? path2.resolve(flags["cwd"]) : process.cwd();
|
|
132
|
+
const pathResolver = new DefaultPathResolver(cwd);
|
|
133
|
+
const projectRoot = pathResolver.projectRoot;
|
|
134
|
+
const projectIdentityRoot = canonicalProjectRoot(projectRoot);
|
|
135
|
+
const userHome = os2.homedir();
|
|
136
|
+
const wpaths = resolveWstackPaths({ projectRoot });
|
|
137
|
+
assertProjectRootOutsideStateDir(projectRoot, wpaths.globalRoot);
|
|
138
|
+
await activateProjectStateGuard(projectRoot);
|
|
139
|
+
await fs2.mkdir(wpaths.globalRoot, { recursive: true });
|
|
140
|
+
await fs2.mkdir(wpaths.profilesDir, { recursive: true });
|
|
141
|
+
await fs2.mkdir(wpaths.projectDir, { recursive: true });
|
|
142
|
+
await fs2.mkdir(wpaths.projectSessions, { recursive: true });
|
|
143
|
+
let registeredProjectId;
|
|
144
|
+
try {
|
|
145
|
+
registeredProjectId = (await readProjectIdentity(projectRoot))?.projectId;
|
|
146
|
+
} catch {
|
|
147
|
+
}
|
|
148
|
+
await writeProjectMeta(wpaths, projectIdentityRoot, registeredProjectId);
|
|
149
|
+
await registerProjectInManifest(
|
|
150
|
+
wpaths,
|
|
151
|
+
projectIdentityRoot,
|
|
152
|
+
void 0,
|
|
153
|
+
cwd !== projectIdentityRoot ? cwd : void 0,
|
|
154
|
+
registeredProjectId
|
|
155
|
+
);
|
|
156
|
+
await ensureProjectGitignore(projectRoot).catch(() => void 0);
|
|
157
|
+
await migrateLegacyConfig(wpaths);
|
|
158
|
+
await migrateProfileFiles(wpaths);
|
|
159
|
+
cleanupStaleProjects(wpaths).catch((err) => {
|
|
160
|
+
noOpLogger.debug("cleanupStaleProjects failed", { err });
|
|
161
|
+
});
|
|
162
|
+
const bootLogger = new DefaultLogger({ stderr: true });
|
|
163
|
+
const vault = new DefaultSecretVault({ keyFile: wpaths.secretsKey, logger: bootLogger });
|
|
164
|
+
const bootstrapProfilePath = typeof wpaths.profileConfig === "function" ? wpaths.profileConfig(wpaths.profileName) : null;
|
|
165
|
+
const secretFiles = [wpaths.projectLocalConfig].filter(Boolean);
|
|
166
|
+
if (bootstrapProfilePath) secretFiles.push(bootstrapProfilePath);
|
|
167
|
+
for (const file of secretFiles) {
|
|
168
|
+
try {
|
|
169
|
+
const { migrated } = await migratePlaintextSecrets(file, vault, noOpLogger);
|
|
170
|
+
if (migrated > 0) {
|
|
171
|
+
writeErr(`[${appLabel}] Encrypted ${migrated} plaintext secret(s) in ${file}
|
|
172
|
+
`);
|
|
173
|
+
}
|
|
174
|
+
} catch {
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
const configLoader = new DefaultConfigLoader({ paths: wpaths, vault, logger: bootLogger });
|
|
178
|
+
let config;
|
|
179
|
+
try {
|
|
180
|
+
config = await configLoader.load({ cliFlags: flagsToConfigPatch(flags) });
|
|
181
|
+
} catch (err) {
|
|
182
|
+
if (skipIdentityValidation && err instanceof Error && err.message.includes("no provider configured")) {
|
|
183
|
+
console.warn(
|
|
184
|
+
JSON.stringify({
|
|
185
|
+
level: "warn",
|
|
186
|
+
event: "boot.no_provider_configured",
|
|
187
|
+
app: appLabel,
|
|
188
|
+
message: "No provider configured \u2014 setup screen will be shown",
|
|
189
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
190
|
+
})
|
|
191
|
+
);
|
|
192
|
+
try {
|
|
193
|
+
config = await configLoader.load({
|
|
194
|
+
cliFlags: flagsToConfigPatch(flags),
|
|
195
|
+
skipIdentityValidation: true
|
|
196
|
+
});
|
|
197
|
+
} catch (fallbackErr) {
|
|
198
|
+
console.warn(
|
|
199
|
+
JSON.stringify({
|
|
200
|
+
level: "warn",
|
|
201
|
+
event: "boot.config_fallback",
|
|
202
|
+
message: `Config load fallback triggered: ${toErrorMessage(fallbackErr)}`,
|
|
203
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
204
|
+
})
|
|
205
|
+
);
|
|
206
|
+
config = Object.freeze({});
|
|
207
|
+
}
|
|
208
|
+
} else {
|
|
209
|
+
throw err;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if (loadSyncConfig) {
|
|
213
|
+
const syncConfig = await configLoader.loadSyncConfig();
|
|
214
|
+
if (syncConfig) {
|
|
215
|
+
config = Object.freeze({ ...config, sync: syncConfig });
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (!config.hq?.projectAlias) {
|
|
219
|
+
try {
|
|
220
|
+
await ensureProjectIdentity(projectRoot);
|
|
221
|
+
} catch (error) {
|
|
222
|
+
bootLogger.warn?.("Could not initialize .wrongstack/project.json", {
|
|
223
|
+
event: "project.identity_init_failed",
|
|
224
|
+
error: toErrorMessage(error)
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
let committedProjectId;
|
|
229
|
+
try {
|
|
230
|
+
committedProjectId = (await readProjectIdentity(projectRoot))?.projectId;
|
|
231
|
+
} catch {
|
|
232
|
+
}
|
|
233
|
+
if (committedProjectId !== registeredProjectId) {
|
|
234
|
+
await writeProjectMeta(wpaths, projectIdentityRoot, committedProjectId);
|
|
235
|
+
await registerProjectInManifest(
|
|
236
|
+
wpaths,
|
|
237
|
+
projectIdentityRoot,
|
|
238
|
+
void 0,
|
|
239
|
+
cwd !== projectIdentityRoot ? cwd : void 0,
|
|
240
|
+
committedProjectId
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
const logger = new DefaultLogger({ level: config.log?.level ?? "info", file: wpaths.logFile });
|
|
244
|
+
try {
|
|
245
|
+
const { getProjectSessionRegistry } = await import("./registry-R23UBE7H.js");
|
|
246
|
+
getProjectSessionRegistry(wpaths.globalRoot);
|
|
247
|
+
} catch {
|
|
248
|
+
}
|
|
249
|
+
return {
|
|
250
|
+
cwd,
|
|
251
|
+
projectRoot,
|
|
252
|
+
userHome,
|
|
253
|
+
wpaths,
|
|
254
|
+
pathResolver,
|
|
255
|
+
config,
|
|
256
|
+
vault,
|
|
257
|
+
logger,
|
|
258
|
+
globalConfigPath: wpaths.globalConfig
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
function isEnabledFlag(value) {
|
|
262
|
+
if (value === true) return true;
|
|
263
|
+
if (typeof value !== "string") return false;
|
|
264
|
+
const normalized = value.trim().toLowerCase();
|
|
265
|
+
return normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "on";
|
|
266
|
+
}
|
|
267
|
+
function flagsToConfigPatch(flags) {
|
|
268
|
+
const patch = {};
|
|
269
|
+
if (typeof flags["provider"] === "string") patch.provider = flags["provider"];
|
|
270
|
+
if (typeof flags["model"] === "string") patch.model = flags["model"];
|
|
271
|
+
if (typeof flags["fallback-model"] === "string") {
|
|
272
|
+
const list = flags["fallback-model"].split(",").map((s) => s.trim()).filter(Boolean);
|
|
273
|
+
if (list.length > 0) patch.fallbackModels = list;
|
|
274
|
+
}
|
|
275
|
+
if (typeof flags["cwd"] === "string") patch.cwd = flags["cwd"];
|
|
276
|
+
if (typeof flags["log-level"] === "string") {
|
|
277
|
+
patch.log = { level: flags["log-level"] };
|
|
278
|
+
} else if (flags["verbose"]) {
|
|
279
|
+
patch.log = { level: "debug" };
|
|
280
|
+
} else if (flags["trace"]) {
|
|
281
|
+
patch.log = { level: "trace" };
|
|
282
|
+
}
|
|
283
|
+
if (flags["no-yolo"] === true) patch.yolo = false;
|
|
284
|
+
else if (flags["yolo"]) patch.yolo = true;
|
|
285
|
+
if (flags["no-features"]) {
|
|
286
|
+
patch.features = {
|
|
287
|
+
mcp: false,
|
|
288
|
+
plugins: false,
|
|
289
|
+
memory: false,
|
|
290
|
+
modelsRegistry: false,
|
|
291
|
+
skills: false
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
if (flags["token-saving-mode"]) {
|
|
295
|
+
patch.features ??= {};
|
|
296
|
+
patch.features.tokenSavingMode = true;
|
|
297
|
+
}
|
|
298
|
+
if (isEnabledFlag(flags["system-pro"]) || flags["system-prompt"] === "pro") {
|
|
299
|
+
patch.systemPrompt = { variant: "pro" };
|
|
300
|
+
} else if (isEnabledFlag(flags["system-lite"]) || flags["system-prompt"] === "lite") {
|
|
301
|
+
patch.systemPrompt = { variant: "lite" };
|
|
302
|
+
} else if (flags["system-prompt"] === "default") {
|
|
303
|
+
patch.systemPrompt = { variant: "default" };
|
|
304
|
+
}
|
|
305
|
+
if (typeof flags["token-saving-tier"] === "string") {
|
|
306
|
+
patch.features ??= {};
|
|
307
|
+
patch.features.tokenSavingMode = normalizeTokenSavingTier(
|
|
308
|
+
flags["token-saving-tier"]
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
return patch;
|
|
312
|
+
}
|
|
313
|
+
async function migrateLegacyConfig(wpaths) {
|
|
314
|
+
const rootFp = wpaths.globalConfig;
|
|
315
|
+
let legacyRaw;
|
|
316
|
+
try {
|
|
317
|
+
legacyRaw = await fs2.readFile(rootFp, "utf8");
|
|
318
|
+
} catch {
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
const result = safeParse(legacyRaw);
|
|
322
|
+
if (!result.ok || !result.value || typeof result.value !== "object" || Array.isArray(result.value)) {
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
const activeProfile = safeProfileName(
|
|
326
|
+
typeof result.value["activeProfile"] === "string" ? result.value["activeProfile"] : void 0
|
|
327
|
+
);
|
|
328
|
+
const profileFp = wpaths.profileConfig(activeProfile);
|
|
329
|
+
try {
|
|
330
|
+
await fs2.access(profileFp);
|
|
331
|
+
return;
|
|
332
|
+
} catch (err) {
|
|
333
|
+
if (err.code !== "ENOENT") return;
|
|
334
|
+
}
|
|
335
|
+
await fs2.mkdir(path2.dirname(profileFp), { recursive: true });
|
|
336
|
+
const profileContent = { ...result.value };
|
|
337
|
+
delete profileContent["activeProfile"];
|
|
338
|
+
await atomicWrite(profileFp, JSON.stringify(profileContent, null, 2), { mode: 384 });
|
|
339
|
+
const bootstrap = { version: 1, activeProfile };
|
|
340
|
+
try {
|
|
341
|
+
await atomicWrite(rootFp, JSON.stringify(bootstrap, null, 2), { mode: 384 });
|
|
342
|
+
} catch {
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
var PROFILE_STATE_PAIRS = [
|
|
346
|
+
{
|
|
347
|
+
globalSrc: (w) => path2.join(w.globalRoot, "statusline.json"),
|
|
348
|
+
profileDst: (w, n) => w.profileStatuslineConfig(n)
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
globalSrc: (w) => path2.join(w.globalRoot, "mode.json"),
|
|
352
|
+
profileDst: (w, n) => w.profileModeConfig(n)
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
globalSrc: (w) => path2.join(w.globalRoot, "provider-status.json"),
|
|
356
|
+
profileDst: (w, n) => w.profileProviderStatus(n)
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
globalSrc: (w) => path2.join(w.globalRoot, "update-cache.json"),
|
|
360
|
+
profileDst: (w, n) => w.profileUpdateCache(n)
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
globalSrc: (w) => path2.join(w.globalRoot, "memory.md"),
|
|
364
|
+
profileDst: (w, n) => path2.join(w.profilesDir, n, "memory.md")
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
globalSrc: (w) => path2.join(w.globalRoot, "history"),
|
|
368
|
+
profileDst: (w, n) => path2.join(w.profilesDir, n, "history")
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
globalSrc: (w) => path2.join(w.globalRoot, "sync.json"),
|
|
372
|
+
profileDst: (w, n) => path2.join(w.profilesDir, n, "sync.json")
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
globalSrc: (w) => path2.join(w.globalRoot, "sync-state.json"),
|
|
376
|
+
profileDst: (w, n) => path2.join(w.profilesDir, n, "sync-state.json")
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
globalSrc: (w) => path2.join(w.globalRoot, "prompt-usage.json"),
|
|
380
|
+
profileDst: (w, n) => path2.join(w.profilesDir, n, "prompt-usage.json")
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
globalSrc: (w) => path2.join(w.globalRoot, "custom-context-modes.json"),
|
|
384
|
+
profileDst: (w, n) => path2.join(w.profilesDir, n, "custom-context-modes.json")
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
globalSrc: (w) => path2.join(w.globalRoot, "desktop.json"),
|
|
388
|
+
profileDst: (w, n) => path2.join(w.profilesDir, n, "desktop.json")
|
|
389
|
+
},
|
|
390
|
+
{
|
|
391
|
+
globalSrc: (w) => path2.join(w.globalRoot, "installed-skills.json"),
|
|
392
|
+
profileDst: (w, n) => path2.join(w.profilesDir, n, "installed-skills.json")
|
|
393
|
+
},
|
|
394
|
+
...["skills", "prompts", "instructions", "design-kits", "desktop", "settings"].map(
|
|
395
|
+
(directory) => ({
|
|
396
|
+
globalSrc: (w) => path2.join(w.globalRoot, directory),
|
|
397
|
+
profileDst: (w, n) => path2.join(w.profilesDir, n, directory)
|
|
398
|
+
})
|
|
399
|
+
)
|
|
400
|
+
];
|
|
401
|
+
async function migrateProfileFiles(wpaths) {
|
|
402
|
+
let profileName = wpaths.profileName;
|
|
403
|
+
try {
|
|
404
|
+
const raw = await fs2.readFile(wpaths.globalConfig, "utf8");
|
|
405
|
+
const parsed = safeParse(raw);
|
|
406
|
+
if (parsed.ok && parsed.value && typeof parsed.value.activeProfile === "string") {
|
|
407
|
+
profileName = safeProfileName(parsed.value.activeProfile);
|
|
408
|
+
}
|
|
409
|
+
} catch {
|
|
410
|
+
}
|
|
411
|
+
try {
|
|
412
|
+
await fs2.mkdir(path2.join(wpaths.profilesDir, profileName), { recursive: true });
|
|
413
|
+
} catch {
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
for (const pair of PROFILE_STATE_PAIRS) {
|
|
417
|
+
const src = pair.globalSrc(wpaths);
|
|
418
|
+
const dst = pair.profileDst(wpaths, profileName);
|
|
419
|
+
let srcIsDir;
|
|
420
|
+
try {
|
|
421
|
+
srcIsDir = (await fs2.stat(src)).isDirectory();
|
|
422
|
+
} catch {
|
|
423
|
+
continue;
|
|
424
|
+
}
|
|
425
|
+
try {
|
|
426
|
+
const dstStat = await fs2.stat(dst);
|
|
427
|
+
if (dstStat.isDirectory() === srcIsDir) {
|
|
428
|
+
continue;
|
|
429
|
+
}
|
|
430
|
+
await fs2.rm(dst, { recursive: true, force: true });
|
|
431
|
+
} catch (err) {
|
|
432
|
+
const code = err.code;
|
|
433
|
+
if (code !== "ENOENT") {
|
|
434
|
+
writeErr(`migrateProfileFiles: skipping ${dst} (stat error: ${code ?? "unknown"})
|
|
435
|
+
`);
|
|
436
|
+
continue;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
try {
|
|
440
|
+
if (srcIsDir) {
|
|
441
|
+
await fs2.cp(src, dst, { recursive: true, errorOnExist: false, force: false });
|
|
442
|
+
} else {
|
|
443
|
+
const content = await fs2.readFile(src);
|
|
444
|
+
await fs2.writeFile(dst, content, { mode: 384 });
|
|
445
|
+
}
|
|
446
|
+
} catch {
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
function assertProjectRootOutsideStateDir(projectRoot, globalRoot) {
|
|
451
|
+
const stateNamespace = path2.resolve(globalRoot, "projects");
|
|
452
|
+
const rel = path2.relative(stateNamespace, path2.resolve(projectRoot));
|
|
453
|
+
if (rel.startsWith("..") || path2.isAbsolute(rel)) return;
|
|
454
|
+
throw new Error(
|
|
455
|
+
`Refusing to start: the resolved project root is inside WrongStack's per-project state directory.
|
|
456
|
+
project root: ${projectRoot}
|
|
457
|
+
state dir: ${stateNamespace}
|
|
458
|
+
This usually means a WrongStack process was spawned with a state path as its working directory. Start from a real project directory, or pass --cwd <path>.`
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
async function writeProjectMeta(paths, projectRoot, projectId) {
|
|
462
|
+
try {
|
|
463
|
+
await fs2.mkdir(paths.projectDir, { recursive: true });
|
|
464
|
+
const meta = {
|
|
465
|
+
hash: paths.projectHash,
|
|
466
|
+
slug: paths.projectSlug,
|
|
467
|
+
root: projectRoot,
|
|
468
|
+
...projectId ? { projectId } : {},
|
|
469
|
+
lastSeen: (/* @__PURE__ */ new Date()).toISOString()
|
|
470
|
+
};
|
|
471
|
+
await atomicWrite(paths.projectMeta, JSON.stringify(meta, null, 2));
|
|
472
|
+
} catch {
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
async function registerProjectInManifest(paths, projectRoot, events, workingDir, projectId) {
|
|
476
|
+
const manifestPath = path2.join(paths.globalRoot, "projects.json");
|
|
477
|
+
try {
|
|
478
|
+
const t0 = Date.now();
|
|
479
|
+
const raw = await fs2.readFile(manifestPath, "utf8");
|
|
480
|
+
events?.emit("storage.read", {
|
|
481
|
+
sessionId: "~boot~",
|
|
482
|
+
store: "project",
|
|
483
|
+
filePath: manifestPath,
|
|
484
|
+
operation: "manifest_read",
|
|
485
|
+
outcome: "success",
|
|
486
|
+
durationMs: Date.now() - t0
|
|
487
|
+
});
|
|
488
|
+
try {
|
|
489
|
+
JSON.parse(raw);
|
|
490
|
+
} catch {
|
|
491
|
+
}
|
|
492
|
+
} catch (err) {
|
|
493
|
+
events?.emit("storage.error", {
|
|
494
|
+
sessionId: "~boot~",
|
|
495
|
+
store: "project",
|
|
496
|
+
filePath: manifestPath,
|
|
497
|
+
operation: "manifest_read",
|
|
498
|
+
error: toErrorMessage(err),
|
|
499
|
+
recoverable: true
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
try {
|
|
503
|
+
let manifest;
|
|
504
|
+
try {
|
|
505
|
+
const raw = await fs2.readFile(manifestPath, "utf8");
|
|
506
|
+
manifest = JSON.parse(raw);
|
|
507
|
+
} catch {
|
|
508
|
+
manifest = { projects: [] };
|
|
509
|
+
}
|
|
510
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
511
|
+
const existing = manifest.projects.find((p) => p.root === projectRoot);
|
|
512
|
+
if (existing) {
|
|
513
|
+
existing.lastSeen = now;
|
|
514
|
+
if (projectId) existing.projectId = projectId;
|
|
515
|
+
if (workingDir) existing.lastWorkingDir = workingDir;
|
|
516
|
+
} else {
|
|
517
|
+
const slug = paths.projectSlug;
|
|
518
|
+
const name = path2.basename(projectRoot);
|
|
519
|
+
const entry = {
|
|
520
|
+
name,
|
|
521
|
+
root: projectRoot,
|
|
522
|
+
slug,
|
|
523
|
+
projectId,
|
|
524
|
+
lastSeen: now,
|
|
525
|
+
createdAt: now
|
|
526
|
+
};
|
|
527
|
+
if (workingDir) entry.lastWorkingDir = workingDir;
|
|
528
|
+
manifest.projects.push(entry);
|
|
529
|
+
}
|
|
530
|
+
const writeT0 = Date.now();
|
|
531
|
+
await atomicWrite(manifestPath, JSON.stringify(manifest, null, 2));
|
|
532
|
+
events?.emit("storage.write", {
|
|
533
|
+
sessionId: "~boot~",
|
|
534
|
+
store: "project",
|
|
535
|
+
filePath: manifestPath,
|
|
536
|
+
operation: "manifest_write",
|
|
537
|
+
outcome: "success",
|
|
538
|
+
durationMs: Date.now() - writeT0
|
|
539
|
+
});
|
|
540
|
+
} catch (err) {
|
|
541
|
+
events?.emit("storage.error", {
|
|
542
|
+
sessionId: "~boot~",
|
|
543
|
+
store: "project",
|
|
544
|
+
filePath: manifestPath,
|
|
545
|
+
operation: "manifest_write",
|
|
546
|
+
error: toErrorMessage(err),
|
|
547
|
+
recoverable: false
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
async function cleanupStaleProjects(wpaths) {
|
|
552
|
+
const projectsRoot = path2.dirname(wpaths.projectDir);
|
|
553
|
+
let entries;
|
|
554
|
+
try {
|
|
555
|
+
entries = await fs2.readdir(projectsRoot, { withFileTypes: true });
|
|
556
|
+
} catch {
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
const stateNamespace = path2.resolve(projectsRoot);
|
|
560
|
+
for (const entry of entries) {
|
|
561
|
+
if (!entry.isDirectory()) continue;
|
|
562
|
+
const projectPath = path2.join(projectsRoot, entry.name);
|
|
563
|
+
const metaPath = path2.join(projectPath, "meta.json");
|
|
564
|
+
try {
|
|
565
|
+
const raw = await fs2.readFile(metaPath, "utf8");
|
|
566
|
+
const meta = JSON.parse(raw);
|
|
567
|
+
if (typeof meta.root !== "string") continue;
|
|
568
|
+
const rel = path2.relative(stateNamespace, path2.resolve(meta.root));
|
|
569
|
+
const nested = rel !== "" && !rel.startsWith("..") && !path2.isAbsolute(rel);
|
|
570
|
+
if (nested) {
|
|
571
|
+
await fs2.rm(projectPath, { recursive: true, force: true });
|
|
572
|
+
continue;
|
|
573
|
+
}
|
|
574
|
+
try {
|
|
575
|
+
await fs2.access(meta.root);
|
|
576
|
+
} catch {
|
|
577
|
+
await fs2.rm(projectPath, { recursive: true, force: true });
|
|
578
|
+
}
|
|
579
|
+
} catch {
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
// src/infrastructure/provider-cache-ledger.ts
|
|
585
|
+
var ProviderCacheLedger = class {
|
|
586
|
+
byProvider = /* @__PURE__ */ new Map();
|
|
587
|
+
last = { input: 0, cacheRead: 0, cacheWrite: 0 };
|
|
588
|
+
off;
|
|
589
|
+
constructor(events) {
|
|
590
|
+
this.off = events.on(
|
|
591
|
+
"token.accounted",
|
|
592
|
+
(p) => {
|
|
593
|
+
this.record(p.usage, p.provider, p.deltaUsage);
|
|
594
|
+
}
|
|
595
|
+
);
|
|
596
|
+
}
|
|
597
|
+
record(usage, provider, deltaUsage) {
|
|
598
|
+
const cur = {
|
|
599
|
+
input: usage.input,
|
|
600
|
+
cacheRead: usage.cacheRead ?? 0,
|
|
601
|
+
cacheWrite: usage.cacheWrite ?? 0
|
|
602
|
+
};
|
|
603
|
+
const delta = deltaUsage ? {
|
|
604
|
+
input: deltaUsage.input,
|
|
605
|
+
cacheRead: deltaUsage.cacheRead ?? 0,
|
|
606
|
+
cacheWrite: deltaUsage.cacheWrite ?? 0
|
|
607
|
+
} : {
|
|
608
|
+
input: Math.max(0, cur.input - this.last.input),
|
|
609
|
+
cacheRead: Math.max(0, cur.cacheRead - this.last.cacheRead),
|
|
610
|
+
cacheWrite: Math.max(0, cur.cacheWrite - this.last.cacheWrite)
|
|
611
|
+
};
|
|
612
|
+
this.last = cur;
|
|
613
|
+
const key = provider ?? "unknown";
|
|
614
|
+
const acc = this.byProvider.get(key) ?? { input: 0, cacheRead: 0, cacheWrite: 0 };
|
|
615
|
+
acc.input += delta.input;
|
|
616
|
+
acc.cacheRead += delta.cacheRead;
|
|
617
|
+
acc.cacheWrite += delta.cacheWrite;
|
|
618
|
+
this.byProvider.set(key, acc);
|
|
619
|
+
}
|
|
620
|
+
/** Distinct providers seen this session. */
|
|
621
|
+
providers() {
|
|
622
|
+
return [...this.byProvider.keys()];
|
|
623
|
+
}
|
|
624
|
+
/** Per-provider cache stats, most-cached first. */
|
|
625
|
+
perProvider() {
|
|
626
|
+
const out = [];
|
|
627
|
+
for (const [provider, a] of this.byProvider) {
|
|
628
|
+
out.push({
|
|
629
|
+
provider,
|
|
630
|
+
input: a.input,
|
|
631
|
+
cacheRead: a.cacheRead,
|
|
632
|
+
cacheWrite: a.cacheWrite,
|
|
633
|
+
hitRatio: promptCacheHitRatio({
|
|
634
|
+
input: a.input,
|
|
635
|
+
output: 0,
|
|
636
|
+
cacheRead: a.cacheRead,
|
|
637
|
+
cacheWrite: a.cacheWrite
|
|
638
|
+
})
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
return out.sort((x, y) => y.cacheRead - x.cacheRead);
|
|
642
|
+
}
|
|
643
|
+
/**
|
|
644
|
+
* Unsubscribe from the event bus and release the per-session listener.
|
|
645
|
+
*
|
|
646
|
+
* **The caller MUST invoke `dispose()` on session teardown** — see the
|
|
647
|
+
* constructor's lifecycle warning. Failure to call this method leaves a
|
|
648
|
+
* permanent `token.accounted` listener on the shared EventBus that
|
|
649
|
+
* accumulates unboundedly across session restarts/resumes.
|
|
650
|
+
*/
|
|
651
|
+
dispose() {
|
|
652
|
+
this.off();
|
|
653
|
+
}
|
|
654
|
+
};
|
|
655
|
+
|
|
656
|
+
export {
|
|
657
|
+
DefaultPathResolver,
|
|
658
|
+
bootConfig,
|
|
659
|
+
flagsToConfigPatch,
|
|
660
|
+
assertProjectRootOutsideStateDir,
|
|
661
|
+
ProviderCacheLedger
|
|
662
|
+
};
|
|
663
|
+
//# sourceMappingURL=chunk-JTHKOYWU.js.map
|