@wrongstack/core 0.107.2 → 0.119.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/{agent-bridge-mOxbpFcg.d.ts → agent-bridge-PRAbEX-9.d.ts} +1 -1
- package/dist/{agent-subagent-runner-DukQLUcS.d.ts → agent-subagent-runner-DXWImnNV.d.ts} +7 -8
- package/dist/{brain-Dfv4Y82E.d.ts → brain-NZZqL8sn.d.ts} +1 -1
- package/dist/{compactor-DXLxLcmU.d.ts → compactor-C3stu664.d.ts} +1 -1
- package/dist/{config-BSU-6vah.d.ts → config-DZV9VK9n.d.ts} +104 -3
- package/dist/{context-CNRYfhUv.d.ts → context-hvXINa6a.d.ts} +31 -1
- package/dist/coordination/index.d.ts +12 -13
- package/dist/coordination/index.js +198 -0
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +27 -28
- package/dist/defaults/index.js +346 -86
- package/dist/defaults/index.js.map +1 -1
- package/dist/execution/index.d.ts +16 -17
- package/dist/execution/index.js +266 -12
- package/dist/execution/index.js.map +1 -1
- package/dist/extension/index.d.ts +6 -7
- package/dist/{goal-preamble-CI8lxeY1.d.ts → goal-preamble-COpt55W8.d.ts} +10 -10
- package/dist/{goal-store-ht0VmR1A.d.ts → goal-store-CV9Yz2X_.d.ts} +11 -0
- package/dist/{index-DIKEcfgC.d.ts → index-4VVHuTZF.d.ts} +7 -6
- package/dist/{index-BWRN6wOb.d.ts → index-Cj3le7TI.d.ts} +9 -10
- package/dist/index.d.ts +41 -42
- package/dist/index.js +372 -118
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +6 -7
- package/dist/kernel/index.d.ts +10 -11
- package/dist/llm-selector-Bmx4PsVM.d.ts +58 -0
- package/dist/{mcp-servers-CXCsANdY.d.ts → mcp-servers-CofNHOqn.d.ts} +3 -3
- package/dist/{mode-ARA3HrkY.d.ts → mode-CZlO9iU1.d.ts} +1 -1
- package/dist/models/index.d.ts +157 -53
- package/dist/models/index.js +423 -1
- package/dist/models/index.js.map +1 -1
- package/dist/{models-registry-DU64QxQa.d.ts → models-registry-BzlsjKcy.d.ts} +1 -1
- package/dist/{multi-agent-coordinator-51LvnXkD.d.ts → multi-agent-coordinator-CmDmUgq2.d.ts} +1 -1
- package/dist/{null-fleet-bus-D09hMzFQ.d.ts → null-fleet-bus-CyH2YqP4.d.ts} +6 -6
- package/dist/observability/index.d.ts +2 -2
- package/dist/{parallel-eternal-engine-CUtmM_0V.d.ts → parallel-eternal-engine-uxVm4y4V.d.ts} +11 -10
- package/dist/{path-resolver-DDJiMAtX.d.ts → path-resolver-gfoGxpdd.d.ts} +3 -3
- package/dist/{permission-BDv7z0mk.d.ts → permission-DhLrgA30.d.ts} +1 -1
- package/dist/{permission-policy-dF74EpDp.d.ts → permission-policy-DGOvne7i.d.ts} +2 -2
- package/dist/{pipeline-BqiA_UMr.d.ts → pipeline-CqF7uju2.d.ts} +2 -2
- package/dist/{plan-templates-BdDxl9cI.d.ts → plan-templates-DoKhzenv.d.ts} +6 -6
- package/dist/{provider-runner-BUunikwY.d.ts → provider-runner-BPlI5sPZ.d.ts} +3 -3
- package/dist/{retry-policy-BcmuT_V0.d.ts → retry-policy-B4Q-FZgE.d.ts} +1 -1
- package/dist/sdd/index.d.ts +8 -9
- package/dist/sdd/index.js +198 -0
- package/dist/sdd/index.js.map +1 -1
- package/dist/{secret-vault-DrOhc2i5.d.ts → secret-vault-B7GnL6o9.d.ts} +1 -1
- package/dist/security/index.d.ts +4 -4
- package/dist/{selector-C7wcdqMA.d.ts → selector-BakeMnWR.d.ts} +1 -1
- package/dist/{session-event-bridge-BpJ5trO9.d.ts → session-event-bridge-DE5Oekwx.d.ts} +1 -1
- package/dist/{session-reader-DDz1Ek4V.d.ts → session-reader-DFC81-4p.d.ts} +1 -1
- package/dist/storage/index.d.ts +12 -13
- package/dist/storage/index.js +147 -88
- package/dist/storage/index.js.map +1 -1
- package/dist/types/index.d.ts +20 -21
- package/dist/types/index.js +35 -1
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +3 -4
- package/dist/utils/index.js +2 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/{wstack-paths-_lqjzErq.d.ts → wstack-paths-DD50Omgn.d.ts} +3 -0
- package/package.json +1 -1
- package/dist/models-registry-B6_KfS65.d.ts +0 -95
package/dist/security/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { D as DefaultSecretScrubber, a as DefaultSecretVault, S as SecretVaultOptions, d as decryptConfigSecrets, e as encryptConfigSecrets, m as migratePlaintextSecrets, r as rewriteConfigEncrypted } from '../secret-vault-
|
|
2
|
-
export { A as AutoApprovePermissionPolicy, D as DefaultPermissionPolicy, P as PermissionPolicyOptions } from '../permission-policy-
|
|
3
|
-
import '../permission-
|
|
4
|
-
import '../context-
|
|
1
|
+
export { D as DefaultSecretScrubber, a as DefaultSecretVault, S as SecretVaultOptions, d as decryptConfigSecrets, e as encryptConfigSecrets, m as migratePlaintextSecrets, r as rewriteConfigEncrypted } from '../secret-vault-B7GnL6o9.js';
|
|
2
|
+
export { A as AutoApprovePermissionPolicy, D as DefaultPermissionPolicy, P as PermissionPolicyOptions } from '../permission-policy-DGOvne7i.js';
|
|
3
|
+
import '../permission-DhLrgA30.js';
|
|
4
|
+
import '../context-hvXINa6a.js';
|
|
5
5
|
import '../secret-vault-DoISxaKO.js';
|
|
6
6
|
import '../input-reader-E-ffP2ee.js';
|
|
7
7
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { g as ContentBlock, S as SessionEvent, h as SessionMetadata, i as SessionStore } from './context-
|
|
1
|
+
import { g as ContentBlock, S as SessionEvent, h as SessionMetadata, i as SessionStore } from './context-hvXINa6a.js';
|
|
2
2
|
|
|
3
3
|
type AttachmentKind = 'text' | 'image' | 'file';
|
|
4
4
|
interface AttachmentMeta {
|
package/dist/storage/index.d.ts
CHANGED
|
@@ -1,22 +1,21 @@
|
|
|
1
|
-
import { M as MemoryBackend, j as FileMemoryBackendOptions } from '../plan-templates-
|
|
2
|
-
export { A as AbandonedSession, a as AttachmentStoreOptions, C as ConfigLoaderOptions, b as ConfigMigration, c as ConfigMigrationError, d as ConfigSource, D as DEFAULT_CONFIG_MIGRATIONS, e as DefaultAttachmentStore, f as DefaultConfigLoader, g as DefaultConfigStore, h as DefaultMemoryStore, i as DefaultSessionStore, F as FileMemoryBackend, k as MemoryStoreOptions, l as MigrationContext, m as MigrationResult, P as PersistedQueueItem, n as PlanFile, o as PlanItem, p as PlanTemplate, Q as QueueStore, R as RecoveryLock, q as RecoveryLockOptions, S as SessionAnalyzer, r as SessionStoreOptions, T as TodosCheckpointFile, s as addPlanItem, t as attachPlanCheckpoint, u as attachTodosCheckpoint, v as clearPlan, w as deriveTodosFromPlanItem, x as emptyPlan, y as formatPlan, z as formatPlanTemplates, B as getPlanTemplate, E as listPlanTemplates, G as loadPlan, H as loadTodosCheckpoint, I as parseEntries, J as removePlanItem, K as runConfigMigrations, L as savePlan, N as saveTodosCheckpoint, O as setPlanItemStatus } from '../plan-templates-
|
|
3
|
-
import { M as MemoryScope, k as MemoryEntry, l as MemoryStore } from '../brain-
|
|
4
|
-
import { l as AgentExtension, j as AfterRunHook } from '../index-
|
|
5
|
-
import { P as Provider, R as Request, b as Response, S as SessionEvent } from '../context-
|
|
6
|
-
export { D as DefaultSessionReader, f as DefaultSessionReaderOptions, S as SessionReader } from '../session-reader-
|
|
1
|
+
import { M as MemoryBackend, j as FileMemoryBackendOptions } from '../plan-templates-DoKhzenv.js';
|
|
2
|
+
export { A as AbandonedSession, a as AttachmentStoreOptions, C as ConfigLoaderOptions, b as ConfigMigration, c as ConfigMigrationError, d as ConfigSource, D as DEFAULT_CONFIG_MIGRATIONS, e as DefaultAttachmentStore, f as DefaultConfigLoader, g as DefaultConfigStore, h as DefaultMemoryStore, i as DefaultSessionStore, F as FileMemoryBackend, k as MemoryStoreOptions, l as MigrationContext, m as MigrationResult, P as PersistedQueueItem, n as PlanFile, o as PlanItem, p as PlanTemplate, Q as QueueStore, R as RecoveryLock, q as RecoveryLockOptions, S as SessionAnalyzer, r as SessionStoreOptions, T as TodosCheckpointFile, s as addPlanItem, t as attachPlanCheckpoint, u as attachTodosCheckpoint, v as clearPlan, w as deriveTodosFromPlanItem, x as emptyPlan, y as formatPlan, z as formatPlanTemplates, B as getPlanTemplate, E as listPlanTemplates, G as loadPlan, H as loadTodosCheckpoint, I as parseEntries, J as removePlanItem, K as runConfigMigrations, L as savePlan, N as saveTodosCheckpoint, O as setPlanItemStatus } from '../plan-templates-DoKhzenv.js';
|
|
3
|
+
import { M as MemoryScope, k as MemoryEntry, l as MemoryStore } from '../brain-NZZqL8sn.js';
|
|
4
|
+
import { l as AgentExtension, j as AfterRunHook } from '../index-4VVHuTZF.js';
|
|
5
|
+
import { P as Provider, R as Request, b as Response, S as SessionEvent } from '../context-hvXINa6a.js';
|
|
6
|
+
export { D as DefaultSessionReader, f as DefaultSessionReaderOptions, S as SessionReader } from '../session-reader-DFC81-4p.js';
|
|
7
7
|
import { S as SessionRewinder, C as CheckpointInfo, a as RewindResultExtended } from '../session-rewinder-C9HnMkhP.js';
|
|
8
8
|
import { T as TaskItem } from '../task-format-vGOIftmK.js';
|
|
9
9
|
export { a as DirectorStateCheckpoint, D as DirectorStateSnapshot, b as DirectorSubagentState, c as DirectorTaskState, l as loadDirectorState } from '../director-state-BfeCUbmk.js';
|
|
10
|
-
export { G as GoalFile, J as JournalEntry, M as MAX_JOURNAL_ENTRIES, a as MAX_PROGRESS_HISTORY, P as ProgressSnapshot, b as appendJournal, e as emptyGoal, f as formatGoal, g as goalFilePath, l as loadGoal, p as parseProgressFromText, r as recordProgress, s as saveGoal, c as setProgress, d as summarizeUsage } from '../goal-store-
|
|
11
|
-
import { W as WstackPaths } from '../wstack-paths-
|
|
12
|
-
import {
|
|
13
|
-
export { A as AuditLevel, C as CORE_RECONSTRUCT_EVENTS, a as STANDARD_AUDIT_EVENTS, S as SessionEventBridge, b as SessionEventBridgeOptions, c as SessionSamplingOptions, T as ToolProgressSamplingOptions, d as createSessionEventBridge, r as resolveAuditLevel, e as resolveSessionLoggingConfig } from '../session-event-bridge-
|
|
14
|
-
import '../permission-
|
|
10
|
+
export { G as GoalFile, J as JournalEntry, M as MAX_JOURNAL_ENTRIES, a as MAX_PROGRESS_HISTORY, P as ProgressSnapshot, b as appendJournal, e as emptyGoal, f as formatGoal, g as goalFilePath, l as loadGoal, p as parseProgressFromText, r as recordProgress, s as saveGoal, c as setProgress, d as summarizeUsage } from '../goal-store-CV9Yz2X_.js';
|
|
11
|
+
import { W as WstackPaths } from '../wstack-paths-DD50Omgn.js';
|
|
12
|
+
import { B as SyncCategory, k as SyncConfig } from '../config-DZV9VK9n.js';
|
|
13
|
+
export { A as AuditLevel, C as CORE_RECONSTRUCT_EVENTS, a as STANDARD_AUDIT_EVENTS, S as SessionEventBridge, b as SessionEventBridgeOptions, c as SessionSamplingOptions, T as ToolProgressSamplingOptions, d as createSessionEventBridge, r as resolveAuditLevel, e as resolveSessionLoggingConfig } from '../session-event-bridge-DE5Oekwx.js';
|
|
14
|
+
import '../permission-DhLrgA30.js';
|
|
15
15
|
import '../secret-vault-DoISxaKO.js';
|
|
16
16
|
import '../logger-B63L5bTg.js';
|
|
17
|
-
import '../pipeline-
|
|
17
|
+
import '../pipeline-CqF7uju2.js';
|
|
18
18
|
import '../observability-D-HZN_mF.js';
|
|
19
|
-
import '../models-registry-B6_KfS65.js';
|
|
20
19
|
import '../task-graph-u1q9Jkyk.js';
|
|
21
20
|
|
|
22
21
|
interface GraphNode {
|
package/dist/storage/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { randomBytes, randomUUID, createHash } from 'crypto';
|
|
2
2
|
import * as fsp from 'fs/promises';
|
|
3
|
-
import * as
|
|
3
|
+
import * as path12 from 'path';
|
|
4
4
|
import * as os from 'os';
|
|
5
5
|
import { hostname } from 'os';
|
|
6
6
|
|
|
@@ -12,9 +12,9 @@ function expectDefined(value, label) {
|
|
|
12
12
|
return value;
|
|
13
13
|
}
|
|
14
14
|
async function atomicWrite(targetPath, content, opts = {}) {
|
|
15
|
-
const dir =
|
|
15
|
+
const dir = path12.dirname(targetPath);
|
|
16
16
|
await fsp.mkdir(dir, { recursive: true });
|
|
17
|
-
const tmp =
|
|
17
|
+
const tmp = path12.join(dir, `.${path12.basename(targetPath)}.${randomBytes(6).toString("hex")}.tmp`);
|
|
18
18
|
try {
|
|
19
19
|
if (typeof content === "string") {
|
|
20
20
|
await fsp.writeFile(tmp, content, { flag: "wx", encoding: opts.encoding ?? "utf8" });
|
|
@@ -53,9 +53,9 @@ async function ensureDir(dir) {
|
|
|
53
53
|
await fsp.mkdir(dir, { recursive: true });
|
|
54
54
|
}
|
|
55
55
|
async function withFileLock(targetPath, fn, opts = {}) {
|
|
56
|
-
const dir =
|
|
56
|
+
const dir = path12.dirname(targetPath);
|
|
57
57
|
await fsp.mkdir(dir, { recursive: true });
|
|
58
|
-
const lockPath =
|
|
58
|
+
const lockPath = path12.join(dir, `.${path12.basename(targetPath)}.lock`);
|
|
59
59
|
const timeoutMs = opts.timeoutMs ?? 5e3;
|
|
60
60
|
const staleMs = opts.staleMs ?? 3e4;
|
|
61
61
|
const started = Date.now();
|
|
@@ -233,11 +233,11 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
233
233
|
}
|
|
234
234
|
/** Absolute path to the session index file. */
|
|
235
235
|
get indexFile() {
|
|
236
|
-
return
|
|
236
|
+
return path12.join(this.dir, "_index.jsonl");
|
|
237
237
|
}
|
|
238
238
|
/** Join session ID to its absolute path within the store directory. */
|
|
239
239
|
sessionPath(id, ext) {
|
|
240
|
-
return
|
|
240
|
+
return path12.join(this.dir, `${id}${ext}`);
|
|
241
241
|
}
|
|
242
242
|
/**
|
|
243
243
|
* Ensure the directory implied by the session ID exists. When the ID
|
|
@@ -245,7 +245,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
245
245
|
* subdirectory so sessions group naturally by day.
|
|
246
246
|
*/
|
|
247
247
|
async ensureShardDir(id) {
|
|
248
|
-
const dirPath =
|
|
248
|
+
const dirPath = path12.dirname(path12.join(this.dir, id));
|
|
249
249
|
await ensureDir(dirPath);
|
|
250
250
|
return dirPath;
|
|
251
251
|
}
|
|
@@ -253,7 +253,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
253
253
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
254
254
|
const id = meta.id && meta.id.length > 0 ? meta.id : generateSessionId(startedAt, meta.model ?? meta.provider);
|
|
255
255
|
const shardDir = await this.ensureShardDir(id);
|
|
256
|
-
const file =
|
|
256
|
+
const file = path12.join(shardDir, `${path12.basename(id)}.jsonl`);
|
|
257
257
|
let handle;
|
|
258
258
|
try {
|
|
259
259
|
handle = await fsp.open(file, "a", 384);
|
|
@@ -461,7 +461,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
461
461
|
continue;
|
|
462
462
|
if (entry.isDirectory()) {
|
|
463
463
|
const childPrefix = depth === 0 ? entry.name : `${prefix}/${entry.name}`;
|
|
464
|
-
ids.push(...await this.collectSessionIds(
|
|
464
|
+
ids.push(...await this.collectSessionIds(path12.join(dir, entry.name), childPrefix, depth + 1));
|
|
465
465
|
} else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
466
466
|
if (entry.name === "_index.jsonl") continue;
|
|
467
467
|
const base = entry.name.replace(/\.jsonl$/, "");
|
|
@@ -495,12 +495,12 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
495
495
|
async deleteSession(id) {
|
|
496
496
|
await fsp.unlink(this.sessionPath(id, ".jsonl")).catch(() => void 0);
|
|
497
497
|
await fsp.unlink(this.sessionPath(id, ".summary.json")).catch(() => void 0);
|
|
498
|
-
const shardDir =
|
|
499
|
-
const base =
|
|
498
|
+
const shardDir = path12.dirname(path12.join(this.dir, id));
|
|
499
|
+
const base = path12.basename(id);
|
|
500
500
|
for (const ext of [".plan.json", ".todos.json"]) {
|
|
501
|
-
await fsp.unlink(
|
|
501
|
+
await fsp.unlink(path12.join(shardDir, `${base}${ext}`)).catch(() => void 0);
|
|
502
502
|
}
|
|
503
|
-
const sessDir =
|
|
503
|
+
const sessDir = path12.join(shardDir, base);
|
|
504
504
|
await fsp.rm(sessDir, { recursive: true, force: true }).catch(() => void 0);
|
|
505
505
|
await this.writeTombstone(id);
|
|
506
506
|
}
|
|
@@ -512,7 +512,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
512
512
|
let deleted = 0;
|
|
513
513
|
let activeSessionId = null;
|
|
514
514
|
try {
|
|
515
|
-
const raw = await fsp.readFile(
|
|
515
|
+
const raw = await fsp.readFile(path12.join(this.dir, "active.json"), "utf8");
|
|
516
516
|
const active = JSON.parse(raw);
|
|
517
517
|
activeSessionId = active.sessionId ?? null;
|
|
518
518
|
} catch {
|
|
@@ -520,11 +520,11 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
520
520
|
const entries = await fsp.readdir(this.dir, { withFileTypes: true }).catch(() => []);
|
|
521
521
|
for (const entry of entries) {
|
|
522
522
|
if (!entry.isDirectory()) continue;
|
|
523
|
-
const dateDir =
|
|
523
|
+
const dateDir = path12.join(this.dir, entry.name);
|
|
524
524
|
const files = await fsp.readdir(dateDir, { withFileTypes: true }).catch(() => []);
|
|
525
525
|
for (const file of files) {
|
|
526
526
|
if (!file.isFile() || !file.name.endsWith(".jsonl")) continue;
|
|
527
|
-
const jsonlPath =
|
|
527
|
+
const jsonlPath = path12.join(dateDir, file.name);
|
|
528
528
|
try {
|
|
529
529
|
const stat5 = await fsp.stat(jsonlPath);
|
|
530
530
|
if (stat5.mtimeMs >= cutoff) continue;
|
|
@@ -542,7 +542,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
542
542
|
}
|
|
543
543
|
for (const entry of entries) {
|
|
544
544
|
if (!entry.isDirectory()) continue;
|
|
545
|
-
const dateDir =
|
|
545
|
+
const dateDir = path12.join(this.dir, entry.name);
|
|
546
546
|
try {
|
|
547
547
|
const remaining = await fsp.readdir(dateDir);
|
|
548
548
|
if (remaining.length === 0) {
|
|
@@ -707,7 +707,7 @@ var FileSessionWriter = class {
|
|
|
707
707
|
this.meta = meta;
|
|
708
708
|
this.events = events;
|
|
709
709
|
this.resumed = opts.resumed ?? false;
|
|
710
|
-
this.manifestFile = opts.dir ?
|
|
710
|
+
this.manifestFile = opts.dir ? path12.join(opts.dir, `${path12.basename(id)}.summary.json`) : "";
|
|
711
711
|
this.filePath = opts.filePath ?? "";
|
|
712
712
|
this.secretScrubber = opts.secretScrubber;
|
|
713
713
|
this.onCloseCb = opts.onClose;
|
|
@@ -1027,7 +1027,7 @@ function userInputTitle(content) {
|
|
|
1027
1027
|
var QueueStore = class {
|
|
1028
1028
|
file;
|
|
1029
1029
|
constructor(opts) {
|
|
1030
|
-
this.file =
|
|
1030
|
+
this.file = path12.join(opts.dir, "queue.json");
|
|
1031
1031
|
}
|
|
1032
1032
|
async write(items) {
|
|
1033
1033
|
if (items.length === 0) {
|
|
@@ -1094,7 +1094,7 @@ var DefaultAttachmentStore = class {
|
|
|
1094
1094
|
let data = input.data;
|
|
1095
1095
|
if (this.spoolDir && bytes >= this.spoolThreshold) {
|
|
1096
1096
|
await fsp.mkdir(this.spoolDir, { recursive: true });
|
|
1097
|
-
spooledPath =
|
|
1097
|
+
spooledPath = path12.join(this.spoolDir, `${id}.bin`);
|
|
1098
1098
|
await atomicWrite(spooledPath, input.data, {
|
|
1099
1099
|
encoding: input.kind === "image" ? "base64" : "utf8"
|
|
1100
1100
|
});
|
|
@@ -1305,7 +1305,7 @@ var FileMemoryBackend = class {
|
|
|
1305
1305
|
}
|
|
1306
1306
|
async remember(scope, entry, filePath) {
|
|
1307
1307
|
const file = this.resolveFile(filePath, scope);
|
|
1308
|
-
await ensureDir(
|
|
1308
|
+
await ensureDir(path12.dirname(file));
|
|
1309
1309
|
let existing = "";
|
|
1310
1310
|
try {
|
|
1311
1311
|
existing = await fsp.readFile(file, "utf8");
|
|
@@ -1322,39 +1322,41 @@ ${line}`;
|
|
|
1322
1322
|
}
|
|
1323
1323
|
async forget(scope, query, filePath) {
|
|
1324
1324
|
const file = this.resolveFile(filePath, scope);
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
const
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1325
|
+
return withFileLock(file, async () => {
|
|
1326
|
+
let existing;
|
|
1327
|
+
try {
|
|
1328
|
+
existing = await fsp.readFile(file, "utf8");
|
|
1329
|
+
} catch {
|
|
1330
|
+
return 0;
|
|
1331
|
+
}
|
|
1332
|
+
const needle = query.toLowerCase();
|
|
1333
|
+
const idMatcher = /mem_\d+_\w+/;
|
|
1334
|
+
let removed = 0;
|
|
1335
|
+
const lines = existing.split("\n").filter((line) => {
|
|
1336
|
+
const trimmed = line.trim();
|
|
1337
|
+
if (!trimmed.startsWith("- ")) return true;
|
|
1338
|
+
if (idMatcher.test(query)) {
|
|
1339
|
+
const entryIdMatch = /mem_\d+_\w+/.exec(trimmed);
|
|
1340
|
+
if (entryIdMatch && entryIdMatch[0] === query) {
|
|
1341
|
+
removed++;
|
|
1342
|
+
return false;
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
if (trimmed.toLowerCase().includes(needle)) {
|
|
1340
1346
|
removed++;
|
|
1341
1347
|
return false;
|
|
1342
1348
|
}
|
|
1349
|
+
return true;
|
|
1350
|
+
});
|
|
1351
|
+
if (removed > 0) {
|
|
1352
|
+
if (lines.length === 0 || lines.length === 1 && !lines[0]?.trim()) {
|
|
1353
|
+
await atomicWrite(file, "");
|
|
1354
|
+
} else {
|
|
1355
|
+
await atomicWrite(file, lines.join("\n"));
|
|
1356
|
+
}
|
|
1343
1357
|
}
|
|
1344
|
-
|
|
1345
|
-
removed++;
|
|
1346
|
-
return false;
|
|
1347
|
-
}
|
|
1348
|
-
return true;
|
|
1358
|
+
return removed;
|
|
1349
1359
|
});
|
|
1350
|
-
if (removed > 0) {
|
|
1351
|
-
if (lines.length === 0 || lines.length === 1 && !lines[0]?.trim()) {
|
|
1352
|
-
await atomicWrite(file, "");
|
|
1353
|
-
} else {
|
|
1354
|
-
await atomicWrite(file, lines.join("\n"));
|
|
1355
|
-
}
|
|
1356
|
-
}
|
|
1357
|
-
return removed;
|
|
1358
1360
|
}
|
|
1359
1361
|
async readAll(scope, filePath) {
|
|
1360
1362
|
const file = this.resolveFile(filePath, scope);
|
|
@@ -2067,7 +2069,7 @@ var SessionMemoryConsolidator = class {
|
|
|
2067
2069
|
for (const op of parsed.operations) {
|
|
2068
2070
|
switch (op.action) {
|
|
2069
2071
|
case "add": {
|
|
2070
|
-
if (op.text
|
|
2072
|
+
if (op.text?.trim()) {
|
|
2071
2073
|
await this.memoryStore.remember(op.text.trim(), void 0, {
|
|
2072
2074
|
type: op.type,
|
|
2073
2075
|
tags: op.tags,
|
|
@@ -2439,12 +2441,14 @@ var DefaultConfigLoader = class {
|
|
|
2439
2441
|
}
|
|
2440
2442
|
async load(opts = {}) {
|
|
2441
2443
|
let cfg = { ...BEHAVIOR_DEFAULTS };
|
|
2442
|
-
const [global, local] = await Promise.all([
|
|
2444
|
+
const [global, local, inProject] = await Promise.all([
|
|
2443
2445
|
this.readJson(this.paths.globalConfig),
|
|
2444
|
-
this.readJson(this.paths.projectLocalConfig)
|
|
2446
|
+
this.readJson(this.paths.projectLocalConfig),
|
|
2447
|
+
this.readJson(this.paths.inProjectConfig)
|
|
2445
2448
|
]);
|
|
2446
2449
|
cfg = deepMerge(cfg, global);
|
|
2447
2450
|
cfg = deepMerge(cfg, local);
|
|
2451
|
+
cfg = deepMerge(cfg, inProject);
|
|
2448
2452
|
for (const [key, fn] of Object.entries(ENV_MAP)) {
|
|
2449
2453
|
const v = process.env[key];
|
|
2450
2454
|
if (v) fn(cfg, v);
|
|
@@ -2643,7 +2647,7 @@ var RecoveryLock = class {
|
|
|
2643
2647
|
sessionStore;
|
|
2644
2648
|
probe;
|
|
2645
2649
|
constructor(opts) {
|
|
2646
|
-
this.file =
|
|
2650
|
+
this.file = path12.join(opts.dir, LOCK_FILE);
|
|
2647
2651
|
this.pid = opts.pid ?? process.pid;
|
|
2648
2652
|
this.hostname = opts.hostname ?? os.hostname();
|
|
2649
2653
|
this.maxAgeMs = opts.maxAgeMs ?? DEFAULT_MAX_AGE_MS;
|
|
@@ -2701,7 +2705,7 @@ var RecoveryLock = class {
|
|
|
2701
2705
|
* null return before calling this.
|
|
2702
2706
|
*/
|
|
2703
2707
|
async write(sessionId) {
|
|
2704
|
-
await ensureDir(
|
|
2708
|
+
await ensureDir(path12.dirname(this.file));
|
|
2705
2709
|
const lock = {
|
|
2706
2710
|
v: 1,
|
|
2707
2711
|
sessionId,
|
|
@@ -3188,7 +3192,7 @@ var AnnotationsStore = class {
|
|
|
3188
3192
|
if (!sessionId || sessionId.includes("/") || sessionId.includes("\\") || sessionId.includes("..")) {
|
|
3189
3193
|
throw new Error(`Invalid sessionId: ${sessionId}`);
|
|
3190
3194
|
}
|
|
3191
|
-
return
|
|
3195
|
+
return path12.join(this.dir, `${sessionId}.annotations.json`);
|
|
3192
3196
|
}
|
|
3193
3197
|
async readFile(sessionId) {
|
|
3194
3198
|
const fp = this.filePath(sessionId);
|
|
@@ -3345,7 +3349,7 @@ var ReplayLogStore = class {
|
|
|
3345
3349
|
out.push({
|
|
3346
3350
|
sessionId,
|
|
3347
3351
|
entryCount: all.length,
|
|
3348
|
-
path:
|
|
3352
|
+
path: path12.join(this.dir, name)
|
|
3349
3353
|
});
|
|
3350
3354
|
}
|
|
3351
3355
|
return out.sort((a, b) => a.sessionId.localeCompare(b.sessionId));
|
|
@@ -3355,7 +3359,7 @@ var ReplayLogStore = class {
|
|
|
3355
3359
|
if (!sessionId || sessionId.includes("/") || sessionId.includes("\\") || sessionId.includes("..")) {
|
|
3356
3360
|
throw new Error(`Invalid sessionId: ${sessionId}`);
|
|
3357
3361
|
}
|
|
3358
|
-
return
|
|
3362
|
+
return path12.join(this.dir, `${sessionId}.replay.jsonl`);
|
|
3359
3363
|
}
|
|
3360
3364
|
async readAll(sessionId) {
|
|
3361
3365
|
const fp = this.filePath(sessionId);
|
|
@@ -3544,7 +3548,7 @@ var SessionRecovery = class {
|
|
|
3544
3548
|
if (!sessionId || sessionId.includes("/") || sessionId.includes("\\") || sessionId.includes("..")) {
|
|
3545
3549
|
throw new Error(`Invalid sessionId: ${sessionId}`);
|
|
3546
3550
|
}
|
|
3547
|
-
return
|
|
3551
|
+
return path12.join(this.dir, `${sessionId}.jsonl`);
|
|
3548
3552
|
}
|
|
3549
3553
|
};
|
|
3550
3554
|
var GENESIS_PREV = "0".repeat(64);
|
|
@@ -3667,7 +3671,7 @@ var ToolAuditLog = class {
|
|
|
3667
3671
|
if (!sessionId || sessionId.includes("/") || sessionId.includes("\\") || sessionId.includes("..")) {
|
|
3668
3672
|
throw new Error(`Invalid sessionId: ${sessionId}`);
|
|
3669
3673
|
}
|
|
3670
|
-
return
|
|
3674
|
+
return path12.join(this.dir, `${sessionId}.audit.jsonl`);
|
|
3671
3675
|
}
|
|
3672
3676
|
async readAll(sessionId) {
|
|
3673
3677
|
const fp = this.filePath(sessionId);
|
|
@@ -3852,7 +3856,7 @@ var DefaultSessionRewinder = class {
|
|
|
3852
3856
|
sessionsDir;
|
|
3853
3857
|
projectRoot;
|
|
3854
3858
|
async listCheckpoints(sessionId) {
|
|
3855
|
-
const file =
|
|
3859
|
+
const file = path12.join(this.sessionsDir, `${sessionId}.jsonl`);
|
|
3856
3860
|
const raw = await fsp.readFile(file, "utf8");
|
|
3857
3861
|
const events = parseEvents(raw);
|
|
3858
3862
|
const fileCountMap = /* @__PURE__ */ new Map();
|
|
@@ -3877,7 +3881,7 @@ var DefaultSessionRewinder = class {
|
|
|
3877
3881
|
return checkpoints;
|
|
3878
3882
|
}
|
|
3879
3883
|
async rewindToCheckpoint(sessionId, checkpointIndex) {
|
|
3880
|
-
const file =
|
|
3884
|
+
const file = path12.join(this.sessionsDir, `${sessionId}.jsonl`);
|
|
3881
3885
|
const raw = await fsp.readFile(file, "utf8");
|
|
3882
3886
|
const events = parseEvents(raw);
|
|
3883
3887
|
let targetIdx = -1;
|
|
@@ -3912,7 +3916,7 @@ var DefaultSessionRewinder = class {
|
|
|
3912
3916
|
return { ...result, toPromptIndex: checkpointIndex, removedEvents };
|
|
3913
3917
|
}
|
|
3914
3918
|
async rewindLastN(sessionId, n) {
|
|
3915
|
-
const file =
|
|
3919
|
+
const file = path12.join(this.sessionsDir, `${sessionId}.jsonl`);
|
|
3916
3920
|
const raw = await fsp.readFile(file, "utf8");
|
|
3917
3921
|
const events = parseEvents(raw);
|
|
3918
3922
|
const checkpoints = [];
|
|
@@ -3941,7 +3945,7 @@ var DefaultSessionRewinder = class {
|
|
|
3941
3945
|
return { ...result, toPromptIndex: targetIndex, removedEvents: snapshotsToRevert.length };
|
|
3942
3946
|
}
|
|
3943
3947
|
async rewindToStart(sessionId) {
|
|
3944
|
-
const file =
|
|
3948
|
+
const file = path12.join(this.sessionsDir, `${sessionId}.jsonl`);
|
|
3945
3949
|
const raw = await fsp.readFile(file, "utf8");
|
|
3946
3950
|
const events = parseEvents(raw);
|
|
3947
3951
|
const allSnapshots = [];
|
|
@@ -3977,10 +3981,10 @@ async function revertSnapshots(snapshots, projectRoot) {
|
|
|
3977
3981
|
for (const snapshot of snapshots) {
|
|
3978
3982
|
for (const file of snapshot.files) {
|
|
3979
3983
|
try {
|
|
3980
|
-
const absPath =
|
|
3981
|
-
const root =
|
|
3982
|
-
const rel =
|
|
3983
|
-
if (rel.startsWith("..") ||
|
|
3984
|
+
const absPath = path12.resolve(file.path);
|
|
3985
|
+
const root = path12.resolve(projectRoot);
|
|
3986
|
+
const rel = path12.relative(root, absPath);
|
|
3987
|
+
if (rel.startsWith("..") || path12.isAbsolute(rel)) {
|
|
3984
3988
|
errors.push(`${file.path}: path resolves outside project root \u2014 skipping`);
|
|
3985
3989
|
continue;
|
|
3986
3990
|
}
|
|
@@ -4560,6 +4564,58 @@ var color = {
|
|
|
4560
4564
|
bgRed: wrap("41", "49"),
|
|
4561
4565
|
bgGreen: wrap("42", "49")
|
|
4562
4566
|
};
|
|
4567
|
+
function projectHash(absRoot) {
|
|
4568
|
+
return createHash("sha256").update(path12.resolve(absRoot)).digest("hex").slice(0, 12);
|
|
4569
|
+
}
|
|
4570
|
+
function projectSlug(absRoot) {
|
|
4571
|
+
const base = slugify(path12.basename(absRoot));
|
|
4572
|
+
const hash = createHash("sha256").update(path12.resolve(absRoot)).digest("hex").slice(0, 6);
|
|
4573
|
+
return `${base}-${hash}`;
|
|
4574
|
+
}
|
|
4575
|
+
function slugify(name) {
|
|
4576
|
+
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40) || "project";
|
|
4577
|
+
}
|
|
4578
|
+
function resolveWstackPaths(opts) {
|
|
4579
|
+
const home = opts.userHome ?? os.homedir();
|
|
4580
|
+
const globalRoot = opts.globalRoot ?? path12.join(home, ".wrongstack");
|
|
4581
|
+
const hash = projectHash(opts.projectRoot);
|
|
4582
|
+
const slug = projectSlug(opts.projectRoot);
|
|
4583
|
+
const projectDir = path12.join(globalRoot, "projects", slug);
|
|
4584
|
+
return {
|
|
4585
|
+
globalRoot,
|
|
4586
|
+
configDir: globalRoot,
|
|
4587
|
+
globalConfig: path12.join(globalRoot, "config.json"),
|
|
4588
|
+
secretsKey: path12.join(globalRoot, ".key"),
|
|
4589
|
+
globalMemory: path12.join(globalRoot, "memory.md"),
|
|
4590
|
+
globalSkills: path12.join(globalRoot, "skills"),
|
|
4591
|
+
globalPrompts: path12.join(globalRoot, "prompts"),
|
|
4592
|
+
cacheDir: path12.join(globalRoot, "cache"),
|
|
4593
|
+
modelsCache: path12.join(globalRoot, "cache", "models.dev.json"),
|
|
4594
|
+
modelsOverlayCache: path12.join(globalRoot, "cache", "models-overlay.json"),
|
|
4595
|
+
historyFile: path12.join(globalRoot, "history"),
|
|
4596
|
+
logFile: path12.join(globalRoot, "logs", "wrongstack.log"),
|
|
4597
|
+
projectDir,
|
|
4598
|
+
projectCodebaseIndex: path12.join(projectDir, "codebase-index"),
|
|
4599
|
+
projectMemory: path12.join(projectDir, "memory.md"),
|
|
4600
|
+
projectSessions: path12.join(projectDir, "sessions"),
|
|
4601
|
+
projectTrust: path12.join(projectDir, "trust.json"),
|
|
4602
|
+
projectMeta: path12.join(projectDir, "meta.json"),
|
|
4603
|
+
projectLocalConfig: path12.join(projectDir, "config.local.json"),
|
|
4604
|
+
inProjectConfig: path12.join(opts.projectRoot, ".wrongstack", "config.json"),
|
|
4605
|
+
inProjectAgentsFile: path12.join(opts.projectRoot, ".wrongstack", "AGENTS.md"),
|
|
4606
|
+
inProjectSkills: path12.join(opts.projectRoot, ".wrongstack", "skills"),
|
|
4607
|
+
inProjectWorktrees: path12.join(opts.projectRoot, ".wrongstack", "worktrees"),
|
|
4608
|
+
projectHash: hash,
|
|
4609
|
+
projectSlug: slug,
|
|
4610
|
+
projectGoal: path12.join(projectDir, "goal.json"),
|
|
4611
|
+
projectSpecs: path12.join(projectDir, "specs"),
|
|
4612
|
+
projectTaskGraphs: path12.join(projectDir, "task-graphs"),
|
|
4613
|
+
projectSddSession: path12.join(projectDir, "sdd-session.json"),
|
|
4614
|
+
projectPlan: path12.join(projectDir, "plan.json"),
|
|
4615
|
+
projectAutophase: path12.join(projectDir, "autophase"),
|
|
4616
|
+
syncConfig: path12.join(globalRoot, "sync.json")
|
|
4617
|
+
};
|
|
4618
|
+
}
|
|
4563
4619
|
|
|
4564
4620
|
// src/types/errors.ts
|
|
4565
4621
|
var ERROR_CODES = {
|
|
@@ -4614,23 +4670,26 @@ var FsError = class extends WrongStackError {
|
|
|
4614
4670
|
// src/storage/goal-store.ts
|
|
4615
4671
|
var MAX_JOURNAL_ENTRIES = 500;
|
|
4616
4672
|
function goalFilePath(projectRoot) {
|
|
4617
|
-
|
|
4618
|
-
return path2.join(os.homedir(), ".wrongstack", "projects", hash, "goal.json");
|
|
4673
|
+
return resolveWstackPaths({ projectRoot }).projectGoal;
|
|
4619
4674
|
}
|
|
4620
4675
|
async function loadGoal(filePath) {
|
|
4621
4676
|
let raw;
|
|
4622
4677
|
try {
|
|
4623
4678
|
raw = await fsp.readFile(filePath, "utf8");
|
|
4624
|
-
} catch {
|
|
4625
|
-
|
|
4679
|
+
} catch (err) {
|
|
4680
|
+
const code = err.code;
|
|
4681
|
+
if (code === "ENOENT") return null;
|
|
4682
|
+
throw err;
|
|
4626
4683
|
}
|
|
4627
4684
|
try {
|
|
4628
4685
|
const parsed = JSON.parse(raw);
|
|
4629
4686
|
if (parsed?.version !== 1 || typeof parsed.goal !== "string" || !Array.isArray(parsed.journal)) {
|
|
4687
|
+
console.warn(`[goal-store] Corrupt goal.json at ${filePath} \u2014 invalid schema. Consider deleting it and re-creating.`);
|
|
4630
4688
|
return null;
|
|
4631
4689
|
}
|
|
4632
4690
|
return parsed;
|
|
4633
4691
|
} catch {
|
|
4692
|
+
console.warn(`[goal-store] Corrupt goal.json at ${filePath} \u2014 JSON parse failed. Consider deleting it and re-creating.`);
|
|
4634
4693
|
return null;
|
|
4635
4694
|
}
|
|
4636
4695
|
}
|
|
@@ -4779,7 +4838,7 @@ function computeTrend(history) {
|
|
|
4779
4838
|
const recent = history.slice(-5);
|
|
4780
4839
|
const deltas = [];
|
|
4781
4840
|
for (let i = 1; i < recent.length; i++) {
|
|
4782
|
-
deltas.push(recent[i]
|
|
4841
|
+
deltas.push((recent[i]?.progress ?? 0) - (recent[i - 1]?.progress ?? 0));
|
|
4783
4842
|
}
|
|
4784
4843
|
if (deltas.length < 2) return void 0;
|
|
4785
4844
|
const avgDelta = deltas.reduce((a, b) => a + b, 0) / deltas.length;
|
|
@@ -4801,7 +4860,7 @@ var DefaultPromptStore = class {
|
|
|
4801
4860
|
if (!file.endsWith(".json")) continue;
|
|
4802
4861
|
try {
|
|
4803
4862
|
const raw = JSON.parse(
|
|
4804
|
-
await fsp.readFile(
|
|
4863
|
+
await fsp.readFile(path12.join(this.dir, file), "utf8")
|
|
4805
4864
|
);
|
|
4806
4865
|
entries.push(raw.entry);
|
|
4807
4866
|
} catch {
|
|
@@ -4814,7 +4873,7 @@ var DefaultPromptStore = class {
|
|
|
4814
4873
|
);
|
|
4815
4874
|
}
|
|
4816
4875
|
async get(id) {
|
|
4817
|
-
const file =
|
|
4876
|
+
const file = path12.join(this.dir, `${id}.json`);
|
|
4818
4877
|
try {
|
|
4819
4878
|
const raw = JSON.parse(await fsp.readFile(file, "utf8"));
|
|
4820
4879
|
return raw.entry;
|
|
@@ -4824,12 +4883,12 @@ var DefaultPromptStore = class {
|
|
|
4824
4883
|
}
|
|
4825
4884
|
async save(entry) {
|
|
4826
4885
|
await ensureDir(this.dir);
|
|
4827
|
-
const file =
|
|
4886
|
+
const file = path12.join(this.dir, `${entry.id}.json`);
|
|
4828
4887
|
const raw = { version: 1, entry };
|
|
4829
4888
|
await atomicWrite(file, JSON.stringify(raw, null, 2));
|
|
4830
4889
|
}
|
|
4831
4890
|
async delete(id) {
|
|
4832
|
-
const file =
|
|
4891
|
+
const file = path12.join(this.dir, `${id}.json`);
|
|
4833
4892
|
try {
|
|
4834
4893
|
await fsp.unlink(file);
|
|
4835
4894
|
return true;
|
|
@@ -4863,7 +4922,7 @@ var CloudSync = class {
|
|
|
4863
4922
|
this.paths = paths;
|
|
4864
4923
|
this.getConfig = getConfig;
|
|
4865
4924
|
this.setConfig = setConfig;
|
|
4866
|
-
this.statePath =
|
|
4925
|
+
this.statePath = path12.join(paths.globalRoot, "sync-state.json");
|
|
4867
4926
|
}
|
|
4868
4927
|
paths;
|
|
4869
4928
|
getConfig;
|
|
@@ -4970,7 +5029,7 @@ var CloudSync = class {
|
|
|
4970
5029
|
const rel = segments.slice(2).join("/");
|
|
4971
5030
|
const destPath = resolvePulledCategoryPath(cat, localPath, rel, entry.path);
|
|
4972
5031
|
const blobData = await this.getBlob(token, owner, repoName, entry.sha);
|
|
4973
|
-
await fsp.mkdir(
|
|
5032
|
+
await fsp.mkdir(path12.dirname(destPath), { recursive: true });
|
|
4974
5033
|
await fsp.writeFile(destPath, Buffer.from(blobData, "base64"));
|
|
4975
5034
|
}
|
|
4976
5035
|
const localRev = await this.hashLocalCategories(cfg.categories);
|
|
@@ -5077,7 +5136,7 @@ var CloudSync = class {
|
|
|
5077
5136
|
const files = await this.walkDir(localPath, localPath);
|
|
5078
5137
|
for (const file of files) {
|
|
5079
5138
|
const content = await fsp.readFile(file, "utf8");
|
|
5080
|
-
const rel =
|
|
5139
|
+
const rel = path12.relative(localPath, file).replace(/\\/g, "/");
|
|
5081
5140
|
entries.push({ path: `data/${cat}/${rel}`, content, mode: "100644" });
|
|
5082
5141
|
hashes.push(content);
|
|
5083
5142
|
}
|
|
@@ -5134,7 +5193,7 @@ var CloudSync = class {
|
|
|
5134
5193
|
const results = [];
|
|
5135
5194
|
const entries = await fsp.readdir(dir, { withFileTypes: true });
|
|
5136
5195
|
for (const entry of entries) {
|
|
5137
|
-
const full =
|
|
5196
|
+
const full = path12.join(dir, entry.name);
|
|
5138
5197
|
if (entry.isDirectory()) {
|
|
5139
5198
|
results.push(...await this.walkDir(full, base));
|
|
5140
5199
|
} else {
|
|
@@ -5151,15 +5210,15 @@ function resolvePulledCategoryPath(cat, localPath, rel, remotePath) {
|
|
|
5151
5210
|
return localPath;
|
|
5152
5211
|
}
|
|
5153
5212
|
if (!rel) return localPath;
|
|
5154
|
-
const normalizedRel =
|
|
5155
|
-
const traversesUp = normalizedRel === ".." || normalizedRel.startsWith(`..${
|
|
5156
|
-
if (
|
|
5213
|
+
const normalizedRel = path12.normalize(rel);
|
|
5214
|
+
const traversesUp = normalizedRel === ".." || normalizedRel.startsWith(`..${path12.sep}`);
|
|
5215
|
+
if (path12.isAbsolute(normalizedRel) || traversesUp) {
|
|
5157
5216
|
throw new Error(`Refusing CloudSync path traversal: ${remotePath}`);
|
|
5158
5217
|
}
|
|
5159
|
-
const dest =
|
|
5160
|
-
const root =
|
|
5161
|
-
const relative3 =
|
|
5162
|
-
if (relative3.startsWith("..") ||
|
|
5218
|
+
const dest = path12.resolve(localPath, normalizedRel);
|
|
5219
|
+
const root = path12.resolve(localPath);
|
|
5220
|
+
const relative3 = path12.relative(root, dest);
|
|
5221
|
+
if (relative3.startsWith("..") || path12.isAbsolute(relative3)) {
|
|
5163
5222
|
throw new Error(`Refusing CloudSync path outside category root: ${remotePath}`);
|
|
5164
5223
|
}
|
|
5165
5224
|
return dest;
|