@wrongstack/core 0.289.0 → 0.291.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/boot.d.ts.map +1 -1
- package/dist/chronicle/domain-adapter.d.ts.map +1 -1
- package/dist/chronicle/index.d.ts +1 -1
- package/dist/chronicle/index.d.ts.map +1 -1
- package/dist/chronicle/index.js +964 -245
- package/dist/chronicle/index.js.map +3 -3
- package/dist/chronicle/journal.d.ts +35 -3
- package/dist/chronicle/journal.d.ts.map +1 -1
- package/dist/chronicle/query.d.ts +8 -5
- package/dist/chronicle/query.d.ts.map +1 -1
- package/dist/chronicle/tool-adapter.d.ts.map +1 -1
- package/dist/coordination/agent-subagent-runner.d.ts +6 -0
- package/dist/coordination/agent-subagent-runner.d.ts.map +1 -1
- package/dist/coordination/agents/phase6-domain.d.ts.map +1 -1
- package/dist/coordination/brain.d.ts +2 -1
- package/dist/coordination/brain.d.ts.map +1 -1
- package/dist/coordination/collab-debug.d.ts +0 -9
- package/dist/coordination/collab-debug.d.ts.map +1 -1
- package/dist/coordination/coordinator/error-classifier.d.ts.map +1 -1
- package/dist/coordination/dep-watcher.d.ts +2 -1
- package/dist/coordination/dep-watcher.d.ts.map +1 -1
- package/dist/coordination/director/director-collab.d.ts +1 -1
- package/dist/coordination/director/director-collab.d.ts.map +1 -1
- package/dist/coordination/director-tools.d.ts.map +1 -1
- package/dist/coordination/director.d.ts +19 -1
- package/dist/coordination/director.d.ts.map +1 -1
- package/dist/coordination/fleet-event-validation.d.ts +0 -7
- package/dist/coordination/fleet-event-validation.d.ts.map +1 -1
- package/dist/coordination/fleet-spawn.d.ts.map +1 -1
- package/dist/coordination/fleet-supervisor.d.ts +1 -1
- package/dist/coordination/fleet-supervisor.d.ts.map +1 -1
- package/dist/coordination/fleet.d.ts +0 -44
- package/dist/coordination/fleet.d.ts.map +1 -1
- package/dist/coordination/index.d.ts +2 -2
- package/dist/coordination/index.d.ts.map +1 -1
- package/dist/coordination/index.js +733 -111
- package/dist/coordination/index.js.map +4 -4
- package/dist/coordination/knowledge-graph.d.ts +2 -1
- package/dist/coordination/knowledge-graph.d.ts.map +1 -1
- package/dist/coordination/large-answer-store.d.ts +0 -6
- package/dist/coordination/large-answer-store.d.ts.map +1 -1
- package/dist/coordination/mail-tools.d.ts.map +1 -1
- package/dist/coordination/mailbox-http-router.d.ts.map +1 -1
- package/dist/coordination/mailbox-message-codec.d.ts +35 -0
- package/dist/coordination/mailbox-message-codec.d.ts.map +1 -1
- package/dist/coordination/mailbox-tool.d.ts +1 -1
- package/dist/coordination/mailbox-tool.d.ts.map +1 -1
- package/dist/coordination/mailbox-types.d.ts +151 -0
- package/dist/coordination/mailbox-types.d.ts.map +1 -1
- package/dist/coordination/provider-status-tracker.d.ts +27 -2
- package/dist/coordination/provider-status-tracker.d.ts.map +1 -1
- package/dist/coordination/subagent-budget.d.ts +2 -1
- package/dist/coordination/subagent-budget.d.ts.map +1 -1
- package/dist/core/agent-response.d.ts +2 -1
- package/dist/core/agent-response.d.ts.map +1 -1
- package/dist/core/agent-tools.d.ts.map +1 -1
- package/dist/core/context.d.ts +51 -0
- package/dist/core/context.d.ts.map +1 -1
- package/dist/core/fallback-model.d.ts +1 -1
- package/dist/core/fallback-model.d.ts.map +1 -1
- package/dist/core/fallback-profile-manager.d.ts +1 -1
- package/dist/core/fallback-profile-manager.d.ts.map +1 -1
- package/dist/core/fleet-pulse.d.ts +2 -1
- package/dist/core/fleet-pulse.d.ts.map +1 -1
- package/dist/core/iteration-limit.d.ts +2 -1
- package/dist/core/iteration-limit.d.ts.map +1 -1
- package/dist/core/mailbox-loop.d.ts +11 -1
- package/dist/core/mailbox-loop.d.ts.map +1 -1
- package/dist/core/model-availability-calendar.d.ts +27 -0
- package/dist/core/model-availability-calendar.d.ts.map +1 -0
- package/dist/core/system-prompt-builder.d.ts +2 -1
- package/dist/core/system-prompt-builder.d.ts.map +1 -1
- package/dist/defaults/index.js +1459 -560
- package/dist/defaults/index.js.map +4 -4
- package/dist/execution/auto-compaction-middleware.d.ts +3 -2
- package/dist/execution/auto-compaction-middleware.d.ts.map +1 -1
- package/dist/execution/enhance-recovery.d.ts +8 -0
- package/dist/execution/enhance-recovery.d.ts.map +1 -1
- package/dist/execution/error-handler.d.ts +2 -2
- package/dist/execution/error-handler.d.ts.map +1 -1
- package/dist/execution/index.js +643 -134
- package/dist/execution/index.js.map +4 -4
- package/dist/execution/intelligent-compactor.d.ts +0 -16
- package/dist/execution/intelligent-compactor.d.ts.map +1 -1
- package/dist/execution/one-shot-llm.d.ts.map +1 -1
- package/dist/execution/retry-policy.d.ts +0 -13
- package/dist/execution/retry-policy.d.ts.map +1 -1
- package/dist/execution/skill-loader.d.ts.map +1 -1
- package/dist/execution/tool-executor.d.ts.map +1 -1
- package/dist/hq/auth-store.d.ts.map +1 -1
- package/dist/hq/index.js +39 -1
- package/dist/hq/index.js.map +3 -3
- package/dist/index.d.ts +32 -30
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22263 -19999
- package/dist/index.js.map +4 -4
- package/dist/infrastructure/index.js +59 -5
- package/dist/infrastructure/index.js.map +2 -2
- package/dist/kernel/events/agent-events.d.ts +2 -0
- package/dist/kernel/events/agent-events.d.ts.map +1 -1
- package/dist/kernel/events/file-events.d.ts +46 -0
- package/dist/kernel/events/file-events.d.ts.map +1 -1
- package/dist/kernel/events/memory-events.d.ts +9 -0
- package/dist/kernel/events/memory-events.d.ts.map +1 -1
- package/dist/kernel/events/provider-events.d.ts +2 -1
- package/dist/kernel/events/provider-events.d.ts.map +1 -1
- package/dist/kernel/events/tool-events.d.ts +25 -0
- package/dist/kernel/events/tool-events.d.ts.map +1 -1
- package/dist/mailbox-attach.d.ts.map +1 -1
- package/dist/plugins/auto-review-plugin.d.ts +10 -0
- package/dist/plugins/auto-review-plugin.d.ts.map +1 -1
- package/dist/plugins/chimera-plugin.d.ts +5 -0
- package/dist/plugins/chimera-plugin.d.ts.map +1 -1
- package/dist/security/index.d.ts +1 -0
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +317 -9
- package/dist/security/index.js.map +4 -4
- package/dist/security/kanban-boundary.d.ts +10 -0
- package/dist/security/kanban-boundary.d.ts.map +1 -0
- package/dist/security/permission-policy.d.ts +8 -1
- package/dist/security/permission-policy.d.ts.map +1 -1
- package/dist/storage/config-loader.d.ts +15 -0
- package/dist/storage/config-loader.d.ts.map +1 -1
- package/dist/storage/index.d.ts +2 -2
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +627 -428
- package/dist/storage/index.js.map +4 -4
- package/dist/storage/memory-consolidator.d.ts +49 -4
- package/dist/storage/memory-consolidator.d.ts.map +1 -1
- package/dist/storage/memory-graph-backend.d.ts +11 -0
- package/dist/storage/memory-graph-backend.d.ts.map +1 -1
- package/dist/storage/provider-config-watcher.d.ts +17 -0
- package/dist/storage/provider-config-watcher.d.ts.map +1 -1
- package/dist/storage/session-event-bridge.d.ts +2 -2
- package/dist/storage/session-event-bridge.d.ts.map +1 -1
- package/dist/tools/fallback-manage-tools.d.ts.map +1 -1
- package/dist/tools/index.js +166 -26
- package/dist/tools/index.js.map +3 -3
- package/dist/types/config.d.ts +12 -4
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/file-event-record.d.ts +68 -0
- package/dist/types/file-event-record.d.ts.map +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +13 -8
- package/dist/types/index.js.map +3 -3
- package/dist/types/permission.d.ts +38 -0
- package/dist/types/permission.d.ts.map +1 -1
- package/dist/types/provider.d.ts +1 -1
- package/dist/types/provider.d.ts.map +1 -1
- package/dist/types/session.d.ts +27 -0
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types/tool-executor.d.ts +2 -0
- package/dist/types/tool-executor.d.ts.map +1 -1
- package/dist/utils/config-backup.d.ts +20 -0
- package/dist/utils/config-backup.d.ts.map +1 -0
- package/dist/utils/index.d.ts +12 -11
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +436 -290
- package/dist/utils/index.js.map +4 -4
- package/dist/utils/message-invariants.d.ts +12 -0
- package/dist/utils/message-invariants.d.ts.map +1 -1
- package/dist/utils/safe-json.d.ts +1 -1
- package/dist/utils/safe-json.d.ts.map +1 -1
- package/dist/utils/term.d.ts +6 -0
- package/dist/utils/term.d.ts.map +1 -1
- package/dist/utils/tool-wire-compact.d.ts +9 -0
- package/dist/utils/tool-wire-compact.d.ts.map +1 -1
- package/dist/utils/wstack-paths.d.ts +21 -1
- package/dist/utils/wstack-paths.d.ts.map +1 -1
- package/instructions/agents/ios.md +113 -0
- package/instructions/llm/memory-consolidator.md +4 -12
- package/instructions/system.md +4 -1
- package/package.json +3 -3
- package/skills/auto-review/SKILL.md +176 -0
- package/skills/mnemosyne/SKILL.md +156 -0
- package/skills/mnemosyne/instructions/agent-prompt.md +200 -0
package/dist/utils/index.js
CHANGED
|
@@ -492,6 +492,12 @@ var TerminalLifecycle = class {
|
|
|
492
492
|
* raw mode. Null when `acquire()` has never been called.
|
|
493
493
|
*/
|
|
494
494
|
_wasRaw = null;
|
|
495
|
+
/**
|
|
496
|
+
* Whether stdin was paused before the TUI took ownership. Readline closes
|
|
497
|
+
* its interface by pausing the shared process stream, so raw mode alone is
|
|
498
|
+
* not enough to make Ink receive bytes during the boot-prompt -> TUI handoff.
|
|
499
|
+
*/
|
|
500
|
+
_wasPaused = null;
|
|
495
501
|
/**
|
|
496
502
|
* Request the process to exit. Set the flag, trigger any registered
|
|
497
503
|
* `onRequestExit` callback (typically Ink's `unmount()`), and arm a
|
|
@@ -543,8 +549,10 @@ var TerminalLifecycle = class {
|
|
|
543
549
|
if (stdin?.isTTY !== true) return false;
|
|
544
550
|
if (typeof stdin.setRawMode !== "function") return false;
|
|
545
551
|
this._wasRaw = stdin.isRaw ?? false;
|
|
552
|
+
this._wasPaused = stdin.isPaused();
|
|
546
553
|
this._stdin = stdin;
|
|
547
554
|
stdin.setRawMode(true);
|
|
555
|
+
stdin.resume();
|
|
548
556
|
this._active = true;
|
|
549
557
|
if (process.platform === "win32") {
|
|
550
558
|
setImmediate(() => {
|
|
@@ -573,9 +581,11 @@ var TerminalLifecycle = class {
|
|
|
573
581
|
const stdin = this._stdin;
|
|
574
582
|
if (stdin?.isTTY === true) {
|
|
575
583
|
stdin.setRawMode?.(this._wasRaw ?? false);
|
|
584
|
+
if (this._wasPaused) stdin.pause();
|
|
576
585
|
}
|
|
577
586
|
this._stdin = void 0;
|
|
578
587
|
this._wasRaw = null;
|
|
588
|
+
this._wasPaused = null;
|
|
579
589
|
}
|
|
580
590
|
/**
|
|
581
591
|
* Synchronously reset all terminal state written by the TUI layer:
|
|
@@ -686,11 +696,42 @@ function stripAnsi(s) {
|
|
|
686
696
|
return s.replace(/\x1b\[[0-9;]*[A-Za-z]/g, "");
|
|
687
697
|
}
|
|
688
698
|
|
|
689
|
-
// src/utils/config-
|
|
699
|
+
// src/utils/config-backup.ts
|
|
690
700
|
import * as fs2 from "node:fs/promises";
|
|
701
|
+
import * as path2 from "node:path";
|
|
702
|
+
function configHistoryDir(globalRoot) {
|
|
703
|
+
return path2.join(globalRoot, "config-history");
|
|
704
|
+
}
|
|
705
|
+
function configSlug(absolutePath, globalRoot) {
|
|
706
|
+
const rel = path2.relative(globalRoot, absolutePath);
|
|
707
|
+
const normalized = rel.replace(/\\/g, "/").replace(/\.json$/i, "");
|
|
708
|
+
return normalized.replace(/\//g, "-");
|
|
709
|
+
}
|
|
710
|
+
async function backupConfigFile(filePath, paths) {
|
|
711
|
+
let currentContent;
|
|
712
|
+
try {
|
|
713
|
+
currentContent = await fs2.readFile(filePath, "utf8");
|
|
714
|
+
if (!currentContent.trim()) return;
|
|
715
|
+
} catch {
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
718
|
+
const now = /* @__PURE__ */ new Date();
|
|
719
|
+
const ts = now.toISOString().replace(/[:.]/g, "-").replace(/Z$/, "");
|
|
720
|
+
const slug = configSlug(filePath, paths.globalRoot);
|
|
721
|
+
const backupDir = configHistoryDir(paths.globalRoot);
|
|
722
|
+
const backupFile = path2.join(backupDir, `${slug}-${ts}.json`);
|
|
723
|
+
try {
|
|
724
|
+
await fs2.mkdir(backupDir, { recursive: true });
|
|
725
|
+
await fs2.writeFile(backupFile, currentContent, { mode: 384, encoding: "utf8" });
|
|
726
|
+
} catch {
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
// src/utils/config-json.ts
|
|
731
|
+
import * as fs3 from "node:fs/promises";
|
|
691
732
|
async function readJsonObjectFile(filePath) {
|
|
692
733
|
try {
|
|
693
|
-
const parsed = JSON.parse(await
|
|
734
|
+
const parsed = JSON.parse(await fs3.readFile(filePath, "utf8"));
|
|
694
735
|
return isJsonObject(parsed) ? parsed : {};
|
|
695
736
|
} catch {
|
|
696
737
|
return {};
|
|
@@ -698,7 +739,7 @@ async function readJsonObjectFile(filePath) {
|
|
|
698
739
|
}
|
|
699
740
|
async function jsonObjectFileExists(filePath) {
|
|
700
741
|
try {
|
|
701
|
-
await
|
|
742
|
+
await fs3.access(filePath);
|
|
702
743
|
return true;
|
|
703
744
|
} catch {
|
|
704
745
|
return false;
|
|
@@ -714,9 +755,9 @@ async function updateJsonObjectFile(filePath, mutator) {
|
|
|
714
755
|
await writeJsonObjectFile(filePath, next);
|
|
715
756
|
return next;
|
|
716
757
|
}
|
|
717
|
-
function getJsonPath(root,
|
|
758
|
+
function getJsonPath(root, path6) {
|
|
718
759
|
let current = root;
|
|
719
|
-
for (const segment of
|
|
760
|
+
for (const segment of path6) {
|
|
720
761
|
if (typeof segment === "number") {
|
|
721
762
|
if (!Array.isArray(current)) return void 0;
|
|
722
763
|
current = current[segment];
|
|
@@ -727,13 +768,13 @@ function getJsonPath(root, path5) {
|
|
|
727
768
|
}
|
|
728
769
|
return current;
|
|
729
770
|
}
|
|
730
|
-
function setJsonPath(root,
|
|
731
|
-
if (
|
|
771
|
+
function setJsonPath(root, path6, value) {
|
|
772
|
+
if (path6.length === 0) {
|
|
732
773
|
if (!isJsonObject(value)) throw new Error("Root config value must be an object");
|
|
733
774
|
return value;
|
|
734
775
|
}
|
|
735
|
-
const parent = ensureJsonParent(root,
|
|
736
|
-
const leaf = lastPathSegment(
|
|
776
|
+
const parent = ensureJsonParent(root, path6);
|
|
777
|
+
const leaf = lastPathSegment(path6);
|
|
737
778
|
if (typeof leaf === "number") {
|
|
738
779
|
if (!Array.isArray(parent)) throw new Error(`Cannot set numeric segment ${leaf} on non-array parent`);
|
|
739
780
|
parent[leaf] = value;
|
|
@@ -743,10 +784,10 @@ function setJsonPath(root, path5, value) {
|
|
|
743
784
|
}
|
|
744
785
|
return root;
|
|
745
786
|
}
|
|
746
|
-
function removeJsonPath(root,
|
|
747
|
-
if (
|
|
748
|
-
const parent = getJsonPath(root,
|
|
749
|
-
const leaf = lastPathSegment(
|
|
787
|
+
function removeJsonPath(root, path6) {
|
|
788
|
+
if (path6.length === 0) return false;
|
|
789
|
+
const parent = getJsonPath(root, path6.slice(0, -1));
|
|
790
|
+
const leaf = lastPathSegment(path6);
|
|
750
791
|
if (typeof leaf === "number") {
|
|
751
792
|
if (!Array.isArray(parent) || leaf < 0 || leaf >= parent.length) return false;
|
|
752
793
|
parent.splice(leaf, 1);
|
|
@@ -756,27 +797,27 @@ function removeJsonPath(root, path5) {
|
|
|
756
797
|
delete parent[leaf];
|
|
757
798
|
return true;
|
|
758
799
|
}
|
|
759
|
-
async function setJsonPathInFile(filePath,
|
|
760
|
-
return updateJsonObjectFile(filePath, (config) => setJsonPath(config,
|
|
800
|
+
async function setJsonPathInFile(filePath, path6, value) {
|
|
801
|
+
return updateJsonObjectFile(filePath, (config) => setJsonPath(config, path6, value));
|
|
761
802
|
}
|
|
762
|
-
async function removeJsonPathInFile(filePath,
|
|
803
|
+
async function removeJsonPathInFile(filePath, path6) {
|
|
763
804
|
return updateJsonObjectFile(filePath, (config) => {
|
|
764
|
-
removeJsonPath(config,
|
|
805
|
+
removeJsonPath(config, path6);
|
|
765
806
|
});
|
|
766
807
|
}
|
|
767
808
|
function isJsonObject(value) {
|
|
768
809
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
769
810
|
}
|
|
770
|
-
function lastPathSegment(
|
|
771
|
-
const segment =
|
|
811
|
+
function lastPathSegment(path6) {
|
|
812
|
+
const segment = path6[path6.length - 1];
|
|
772
813
|
if (segment === void 0) throw new Error("Invalid empty JSON path");
|
|
773
814
|
return segment;
|
|
774
815
|
}
|
|
775
|
-
function ensureJsonParent(root,
|
|
816
|
+
function ensureJsonParent(root, path6) {
|
|
776
817
|
let current = root;
|
|
777
|
-
for (let i = 0; i <
|
|
778
|
-
const segment =
|
|
779
|
-
const nextSegment =
|
|
818
|
+
for (let i = 0; i < path6.length - 1; i += 1) {
|
|
819
|
+
const segment = path6[i];
|
|
820
|
+
const nextSegment = path6[i + 1];
|
|
780
821
|
if (segment === void 0) throw new Error("Invalid empty JSON path segment");
|
|
781
822
|
const nextContainer = typeof nextSegment === "number" ? [] : {};
|
|
782
823
|
if (typeof segment === "number") {
|
|
@@ -793,7 +834,7 @@ function ensureJsonParent(root, path5) {
|
|
|
793
834
|
}
|
|
794
835
|
|
|
795
836
|
// src/utils/context-evidence.ts
|
|
796
|
-
import * as
|
|
837
|
+
import * as path3 from "node:path";
|
|
797
838
|
var MAX_TOOL_CALLS = 80;
|
|
798
839
|
var MAX_FACTS = 40;
|
|
799
840
|
var MAX_ERRORS = 20;
|
|
@@ -1033,10 +1074,10 @@ function addPath(ctx, out, raw) {
|
|
|
1033
1074
|
if (!clean || clean.length > 260) return;
|
|
1034
1075
|
let normalized = clean.replace(/\\/g, "/");
|
|
1035
1076
|
try {
|
|
1036
|
-
const abs =
|
|
1077
|
+
const abs = path3.isAbsolute(clean) ? path3.resolve(clean) : null;
|
|
1037
1078
|
if (abs) {
|
|
1038
|
-
const rel =
|
|
1039
|
-
if (!rel.startsWith("..") && !
|
|
1079
|
+
const rel = path3.relative(ctx.projectRoot, abs);
|
|
1080
|
+
if (!rel.startsWith("..") && !path3.isAbsolute(rel)) {
|
|
1040
1081
|
normalized = rel.replace(/\\/g, "/");
|
|
1041
1082
|
}
|
|
1042
1083
|
}
|
|
@@ -1154,7 +1195,7 @@ function implicitFactFor(metadata) {
|
|
|
1154
1195
|
function metadataReferencedByText(metadata, haystack) {
|
|
1155
1196
|
for (const file of metadata.files) {
|
|
1156
1197
|
const f = file.toLowerCase();
|
|
1157
|
-
const base =
|
|
1198
|
+
const base = path3.basename(file).toLowerCase();
|
|
1158
1199
|
if (f && haystack.includes(f)) return true;
|
|
1159
1200
|
if (base && haystack.includes(base)) return true;
|
|
1160
1201
|
}
|
|
@@ -1860,10 +1901,10 @@ function validateAgainstSchema(value, schema) {
|
|
|
1860
1901
|
return { ok: errors.length === 0, errors };
|
|
1861
1902
|
}
|
|
1862
1903
|
var MAX_SCHEMA_DEPTH = 64;
|
|
1863
|
-
function walk(value, schema,
|
|
1904
|
+
function walk(value, schema, path6, errors, depth) {
|
|
1864
1905
|
if (depth > MAX_SCHEMA_DEPTH) {
|
|
1865
1906
|
errors.push({
|
|
1866
|
-
path:
|
|
1907
|
+
path: path6 || "<root>",
|
|
1867
1908
|
message: `schema nesting exceeds maximum depth (${MAX_SCHEMA_DEPTH})`
|
|
1868
1909
|
});
|
|
1869
1910
|
return;
|
|
@@ -1871,7 +1912,7 @@ function walk(value, schema, path5, errors, depth) {
|
|
|
1871
1912
|
if (schema.enum !== void 0) {
|
|
1872
1913
|
if (!enumIncludes(schema.enum, value)) {
|
|
1873
1914
|
errors.push({
|
|
1874
|
-
path:
|
|
1915
|
+
path: path6 || "<root>",
|
|
1875
1916
|
message: `expected one of ${JSON.stringify(schema.enum)}, got ${JSON.stringify(value)}`
|
|
1876
1917
|
});
|
|
1877
1918
|
return;
|
|
@@ -1880,7 +1921,7 @@ function walk(value, schema, path5, errors, depth) {
|
|
|
1880
1921
|
if (typeof schema.type === "string") {
|
|
1881
1922
|
if (!checkType(value, schema.type)) {
|
|
1882
1923
|
errors.push({
|
|
1883
|
-
path:
|
|
1924
|
+
path: path6 || "<root>",
|
|
1884
1925
|
message: `expected ${schema.type}, got ${describeType(value)} (${previewValue(value)})`
|
|
1885
1926
|
});
|
|
1886
1927
|
return;
|
|
@@ -1892,7 +1933,7 @@ function walk(value, schema, path5, errors, depth) {
|
|
|
1892
1933
|
if (!(req in obj)) {
|
|
1893
1934
|
const expected = schema.properties?.[req]?.type;
|
|
1894
1935
|
errors.push({
|
|
1895
|
-
path: joinPath(
|
|
1936
|
+
path: joinPath(path6, req),
|
|
1896
1937
|
message: `required property missing${typeof expected === "string" ? ` (expected ${expected})` : ""}`
|
|
1897
1938
|
});
|
|
1898
1939
|
}
|
|
@@ -1900,14 +1941,14 @@ function walk(value, schema, path5, errors, depth) {
|
|
|
1900
1941
|
if (schema.properties) {
|
|
1901
1942
|
for (const [key, subSchema] of Object.entries(schema.properties)) {
|
|
1902
1943
|
if (key in obj) {
|
|
1903
|
-
walk(obj[key], subSchema, joinPath(
|
|
1944
|
+
walk(obj[key], subSchema, joinPath(path6, key), errors, depth + 1);
|
|
1904
1945
|
}
|
|
1905
1946
|
}
|
|
1906
1947
|
}
|
|
1907
1948
|
}
|
|
1908
1949
|
if (schema.type === "array" && Array.isArray(value) && schema.items) {
|
|
1909
1950
|
for (let i = 0; i < value.length; i++) {
|
|
1910
|
-
walk(value[i], schema.items, `${
|
|
1951
|
+
walk(value[i], schema.items, `${path6}[${i}]`, errors, depth + 1);
|
|
1911
1952
|
}
|
|
1912
1953
|
}
|
|
1913
1954
|
}
|
|
@@ -2204,9 +2245,23 @@ function mapContent(msg, fn) {
|
|
|
2204
2245
|
}
|
|
2205
2246
|
return { ...msg, content: next };
|
|
2206
2247
|
}
|
|
2248
|
+
function hasMeaningfulContent(content) {
|
|
2249
|
+
if (typeof content === "string") return content.trim().length > 0;
|
|
2250
|
+
for (const block of content) {
|
|
2251
|
+
if (block.type === "text") {
|
|
2252
|
+
if (block.text.trim().length > 0) return true;
|
|
2253
|
+
continue;
|
|
2254
|
+
}
|
|
2255
|
+
if (block.type === "thinking") {
|
|
2256
|
+
if (block.thinking.trim().length > 0 || block.signature) return true;
|
|
2257
|
+
continue;
|
|
2258
|
+
}
|
|
2259
|
+
return true;
|
|
2260
|
+
}
|
|
2261
|
+
return false;
|
|
2262
|
+
}
|
|
2207
2263
|
function isEmptyMessage(msg) {
|
|
2208
|
-
|
|
2209
|
-
return msg.content.length === 0;
|
|
2264
|
+
return !hasMeaningfulContent(msg.content);
|
|
2210
2265
|
}
|
|
2211
2266
|
|
|
2212
2267
|
// src/utils/newline-normalize.ts
|
|
@@ -2279,7 +2334,7 @@ function compileUserRegex(pattern, flags) {
|
|
|
2279
2334
|
|
|
2280
2335
|
// src/utils/safe-json.ts
|
|
2281
2336
|
function safeParse(input, maxBytes = 5e6) {
|
|
2282
|
-
if (input
|
|
2337
|
+
if (Buffer.byteLength(input, "utf8") > maxBytes) {
|
|
2283
2338
|
return { ok: false, error: `Input exceeds limit (${maxBytes} bytes)` };
|
|
2284
2339
|
}
|
|
2285
2340
|
try {
|
|
@@ -2314,7 +2369,7 @@ function safeStringify(value, pretty = false) {
|
|
|
2314
2369
|
}
|
|
2315
2370
|
function sanitizeJsonString(s) {
|
|
2316
2371
|
let out = s.trim();
|
|
2317
|
-
out =
|
|
2372
|
+
out = stripJsonComments(out);
|
|
2318
2373
|
out = out.replace(/,(\s*[}\]])/g, "$1");
|
|
2319
2374
|
out = escapeControlCharsInStrings(out);
|
|
2320
2375
|
try {
|
|
@@ -2372,34 +2427,59 @@ function escapeControlCharsInStrings(s) {
|
|
|
2372
2427
|
}
|
|
2373
2428
|
return out;
|
|
2374
2429
|
}
|
|
2375
|
-
function
|
|
2430
|
+
function stripJsonComments(s) {
|
|
2376
2431
|
let inString = false;
|
|
2432
|
+
let escaped = false;
|
|
2377
2433
|
const chars = [];
|
|
2378
2434
|
let i = 0;
|
|
2379
2435
|
while (i < s.length) {
|
|
2380
2436
|
const c = s.charAt(i);
|
|
2381
|
-
if (
|
|
2382
|
-
inString = !inString;
|
|
2437
|
+
if (inString) {
|
|
2383
2438
|
chars.push(c);
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2439
|
+
if (escaped) {
|
|
2440
|
+
escaped = false;
|
|
2441
|
+
} else if (c === "\\") {
|
|
2442
|
+
escaped = true;
|
|
2443
|
+
} else if (c === '"') {
|
|
2444
|
+
inString = false;
|
|
2445
|
+
}
|
|
2446
|
+
i++;
|
|
2447
|
+
continue;
|
|
2448
|
+
}
|
|
2449
|
+
if (c === '"') {
|
|
2450
|
+
inString = true;
|
|
2387
2451
|
chars.push(c);
|
|
2452
|
+
i++;
|
|
2453
|
+
continue;
|
|
2454
|
+
}
|
|
2455
|
+
if (c === "/" && s.charAt(i + 1) === "/") {
|
|
2456
|
+
while (i < s.length && s.charAt(i) !== "\n") i++;
|
|
2457
|
+
continue;
|
|
2388
2458
|
}
|
|
2459
|
+
if (c === "/" && s.charAt(i + 1) === "*") {
|
|
2460
|
+
const end = s.indexOf("*/", i + 2);
|
|
2461
|
+
if (end === -1) {
|
|
2462
|
+
chars.push(s.slice(i));
|
|
2463
|
+
break;
|
|
2464
|
+
}
|
|
2465
|
+
i = end + 2;
|
|
2466
|
+
continue;
|
|
2467
|
+
}
|
|
2468
|
+
chars.push(c);
|
|
2389
2469
|
i++;
|
|
2390
2470
|
}
|
|
2391
2471
|
return chars.join("");
|
|
2392
2472
|
}
|
|
2393
2473
|
|
|
2394
2474
|
// src/utils/session-scoped-path.ts
|
|
2395
|
-
import * as
|
|
2475
|
+
import * as path4 from "node:path";
|
|
2396
2476
|
function sessionScopedPath(dir, sessionId, suffix) {
|
|
2397
2477
|
if (!sessionId || sessionId.includes("\\") || sessionId.includes("..")) {
|
|
2398
2478
|
throw invalid(sessionId);
|
|
2399
2479
|
}
|
|
2400
|
-
const resolved =
|
|
2401
|
-
const rel =
|
|
2402
|
-
if (rel.startsWith("..") ||
|
|
2480
|
+
const resolved = path4.resolve(dir, `${sessionId}${suffix}`);
|
|
2481
|
+
const rel = path4.relative(path4.resolve(dir), resolved);
|
|
2482
|
+
if (rel.startsWith("..") || path4.isAbsolute(rel)) {
|
|
2403
2483
|
throw invalid(sessionId);
|
|
2404
2484
|
}
|
|
2405
2485
|
return resolved;
|
|
@@ -2413,51 +2493,16 @@ function invalid(sessionId) {
|
|
|
2413
2493
|
});
|
|
2414
2494
|
}
|
|
2415
2495
|
|
|
2416
|
-
// src/utils/slug.ts
|
|
2417
|
-
function slugify(name, fallback = "prompt", maxLen = 64) {
|
|
2418
|
-
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, maxLen).replace(/-+$/g, "") || fallback;
|
|
2419
|
-
}
|
|
2420
|
-
|
|
2421
|
-
// src/utils/ulid.ts
|
|
2422
|
-
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
2423
|
-
var ENCODING = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
|
|
2424
|
-
var ENCODING_LEN = ENCODING.length;
|
|
2425
|
-
var TIME_LEN = 10;
|
|
2426
|
-
var RANDOM_LEN = 16;
|
|
2427
|
-
function encodeTime(now, len) {
|
|
2428
|
-
let mod;
|
|
2429
|
-
let str = "";
|
|
2430
|
-
for (let i = len - 1; i >= 0; i--) {
|
|
2431
|
-
mod = now % ENCODING_LEN;
|
|
2432
|
-
str = ENCODING[mod] + str;
|
|
2433
|
-
now = (now - mod) / ENCODING_LEN;
|
|
2434
|
-
}
|
|
2435
|
-
return str;
|
|
2436
|
-
}
|
|
2437
|
-
function encodeRandom(len) {
|
|
2438
|
-
const bytes = randomBytes2(len);
|
|
2439
|
-
let str = "";
|
|
2440
|
-
for (let i = 0; i < len; i++) {
|
|
2441
|
-
str += ENCODING[bytes[i] % ENCODING_LEN];
|
|
2442
|
-
}
|
|
2443
|
-
return str;
|
|
2444
|
-
}
|
|
2445
|
-
function ulid(seedTime = Date.now()) {
|
|
2446
|
-
return encodeTime(seedTime, TIME_LEN) + encodeRandom(RANDOM_LEN);
|
|
2447
|
-
}
|
|
2448
|
-
function isUlid(value) {
|
|
2449
|
-
if (value.length !== TIME_LEN + RANDOM_LEN) return false;
|
|
2450
|
-
for (const ch of value) {
|
|
2451
|
-
if (!ENCODING.includes(ch)) return false;
|
|
2452
|
-
}
|
|
2453
|
-
return true;
|
|
2454
|
-
}
|
|
2455
|
-
|
|
2456
2496
|
// src/utils/sleep.ts
|
|
2457
2497
|
function sleep(ms) {
|
|
2458
2498
|
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
2459
2499
|
}
|
|
2460
2500
|
|
|
2501
|
+
// src/utils/slug.ts
|
|
2502
|
+
function slugify(name, fallback = "prompt", maxLen = 64) {
|
|
2503
|
+
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, maxLen).replace(/-+$/g, "") || fallback;
|
|
2504
|
+
}
|
|
2505
|
+
|
|
2461
2506
|
// src/utils/string.ts
|
|
2462
2507
|
function truncate(s, max) {
|
|
2463
2508
|
return s.length <= max ? s : `${s.slice(0, max - 1)}\u2026`;
|
|
@@ -2591,41 +2636,6 @@ function hasOpenTodos(todos) {
|
|
|
2591
2636
|
return todos.some((t) => t.status === "pending" || t.status === "in_progress");
|
|
2592
2637
|
}
|
|
2593
2638
|
|
|
2594
|
-
// src/utils/tool-subject.ts
|
|
2595
|
-
var GLOB_METACHARACTERS = /[*?[\]]/g;
|
|
2596
|
-
function escapeGlobSubject(value) {
|
|
2597
|
-
return value.replace(GLOB_METACHARACTERS, (char) => `\\${char}`);
|
|
2598
|
-
}
|
|
2599
|
-
function normalizePathSubject(value) {
|
|
2600
|
-
return escapeGlobSubject(value.replace(/\\/g, "/"));
|
|
2601
|
-
}
|
|
2602
|
-
function isPathSubjectKey(subjectKey) {
|
|
2603
|
-
return subjectKey === "path" || subjectKey === "file" || subjectKey === "files";
|
|
2604
|
-
}
|
|
2605
|
-
function subjectForToolInput(toolName, input, subjectKey) {
|
|
2606
|
-
if (!input || typeof input !== "object") return void 0;
|
|
2607
|
-
const obj = input;
|
|
2608
|
-
if (subjectKey) {
|
|
2609
|
-
const value = obj[subjectKey];
|
|
2610
|
-
if (typeof value === "string") {
|
|
2611
|
-
return isPathSubjectKey(subjectKey) ? normalizePathSubject(value) : escapeGlobSubject(value);
|
|
2612
|
-
}
|
|
2613
|
-
}
|
|
2614
|
-
if (toolName === "bash" && typeof obj.command === "string") {
|
|
2615
|
-
return escapeGlobSubject(obj.command);
|
|
2616
|
-
}
|
|
2617
|
-
if (typeof obj.path === "string") {
|
|
2618
|
-
return normalizePathSubject(obj.path);
|
|
2619
|
-
}
|
|
2620
|
-
if (typeof obj.url === "string") {
|
|
2621
|
-
return escapeGlobSubject(obj.url);
|
|
2622
|
-
}
|
|
2623
|
-
if (typeof obj.name === "string") {
|
|
2624
|
-
return escapeGlobSubject(obj.name);
|
|
2625
|
-
}
|
|
2626
|
-
return void 0;
|
|
2627
|
-
}
|
|
2628
|
-
|
|
2629
2639
|
// src/utils/tool-wire-compact.ts
|
|
2630
2640
|
var TOOL_DESCRIPTION_MAX_CHARS = 400;
|
|
2631
2641
|
var SCHEMA_DESCRIPTION_MAX_CHARS = 120;
|
|
@@ -2642,9 +2652,11 @@ function compactToolDefinitionForWire(tool, opts = {}) {
|
|
|
2642
2652
|
tool.description ?? "",
|
|
2643
2653
|
opts.descriptionMaxChars ?? TOOL_DESCRIPTION_MAX_CHARS
|
|
2644
2654
|
),
|
|
2645
|
-
inputSchema:
|
|
2646
|
-
|
|
2647
|
-
|
|
2655
|
+
inputSchema: normalizeTopLevelToolSchema(
|
|
2656
|
+
compactSchemaDescriptions(
|
|
2657
|
+
tool.inputSchema,
|
|
2658
|
+
opts.schemaDescriptionMaxChars ?? SCHEMA_DESCRIPTION_MAX_CHARS
|
|
2659
|
+
)
|
|
2648
2660
|
)
|
|
2649
2661
|
};
|
|
2650
2662
|
if (useDefaultOptions && typeof tool === "object" && tool !== null) {
|
|
@@ -2652,6 +2664,44 @@ function compactToolDefinitionForWire(tool, opts = {}) {
|
|
|
2652
2664
|
}
|
|
2653
2665
|
return compact;
|
|
2654
2666
|
}
|
|
2667
|
+
function normalizeTopLevelToolSchema(schema) {
|
|
2668
|
+
const combinators = ["oneOf", "anyOf", "allOf"].map((keyword) => ({ keyword, branches: schema[keyword] })).filter(
|
|
2669
|
+
(entry) => Array.isArray(entry.branches)
|
|
2670
|
+
);
|
|
2671
|
+
if (combinators.length === 0) return schema;
|
|
2672
|
+
const out = { ...schema, type: "object" };
|
|
2673
|
+
delete out["oneOf"];
|
|
2674
|
+
delete out["anyOf"];
|
|
2675
|
+
delete out["allOf"];
|
|
2676
|
+
const properties = isRecord(schema["properties"]) ? { ...schema["properties"] } : {};
|
|
2677
|
+
let required = stringSet(schema["required"]);
|
|
2678
|
+
for (const { keyword, branches } of combinators) {
|
|
2679
|
+
const objectBranches = branches.filter(isRecord);
|
|
2680
|
+
for (const branch of objectBranches) {
|
|
2681
|
+
if (isRecord(branch["properties"])) Object.assign(properties, branch["properties"]);
|
|
2682
|
+
}
|
|
2683
|
+
const branchRequired = objectBranches.map((branch) => stringSet(branch["required"]));
|
|
2684
|
+
if (keyword === "allOf") {
|
|
2685
|
+
for (const fields of branchRequired) for (const field of fields) required.add(field);
|
|
2686
|
+
} else if (branchRequired.length > 0) {
|
|
2687
|
+
const common = new Set(
|
|
2688
|
+
[...branchRequired[0]].filter(
|
|
2689
|
+
(field) => branchRequired.slice(1).every((fields) => fields.has(field))
|
|
2690
|
+
)
|
|
2691
|
+
);
|
|
2692
|
+
required = /* @__PURE__ */ new Set([...required, ...common]);
|
|
2693
|
+
}
|
|
2694
|
+
}
|
|
2695
|
+
out["properties"] = properties;
|
|
2696
|
+
if (required.size > 0) out["required"] = [...required];
|
|
2697
|
+
else delete out["required"];
|
|
2698
|
+
return out;
|
|
2699
|
+
}
|
|
2700
|
+
function stringSet(value) {
|
|
2701
|
+
return new Set(
|
|
2702
|
+
Array.isArray(value) ? value.filter((item) => typeof item === "string") : []
|
|
2703
|
+
);
|
|
2704
|
+
}
|
|
2655
2705
|
function compactSchemaDescriptions(schema, maxDescriptionChars = SCHEMA_DESCRIPTION_MAX_CHARS) {
|
|
2656
2706
|
const compact = compactSchemaNode(schema, maxDescriptionChars);
|
|
2657
2707
|
return isRecord(compact) ? compact : { type: "object", properties: {} };
|
|
@@ -2892,6 +2942,114 @@ function resetCalibration(calibrationKey) {
|
|
|
2892
2942
|
_cals.delete(calibrationKey);
|
|
2893
2943
|
}
|
|
2894
2944
|
|
|
2945
|
+
// src/utils/tool-description-mode.ts
|
|
2946
|
+
var DEFAULT_TOOL_DESCRIPTION_MODE = "extend";
|
|
2947
|
+
var ORIGINAL_TOOL_DESCRIPTION = /* @__PURE__ */ Symbol.for("wrongstack.tool.originalDescription");
|
|
2948
|
+
function normalizeToolDescriptionMode(value) {
|
|
2949
|
+
if (typeof value !== "string") return void 0;
|
|
2950
|
+
const raw = value.trim().toLowerCase();
|
|
2951
|
+
if (raw === "extend" || raw === "extended" || raw === "full") return "extend";
|
|
2952
|
+
if (raw === "simple" || raw === "short" || raw === "brief") return "simple";
|
|
2953
|
+
return void 0;
|
|
2954
|
+
}
|
|
2955
|
+
function resolveToolDescriptionMode(modes, toolName) {
|
|
2956
|
+
return normalizeToolDescriptionMode(modes?.[toolName]) ?? DEFAULT_TOOL_DESCRIPTION_MODE;
|
|
2957
|
+
}
|
|
2958
|
+
function simplifyToolDescription(text, opts = {}) {
|
|
2959
|
+
const maxSentences = Math.max(1, opts.maxSentences ?? 2);
|
|
2960
|
+
const maxChars = Math.max(40, opts.maxChars ?? 180);
|
|
2961
|
+
const normalized = text.replace(/\r\n?/g, "\n").split("\n").map((line) => line.trim()).filter(Boolean).join(" ").replace(/\s+/g, " ").trim();
|
|
2962
|
+
if (normalized.length <= maxChars) return normalized;
|
|
2963
|
+
const sentences = normalized.match(/[^.!?]+[.!?]+(?=\s|$)|[^.!?]+$/g) ?? [normalized];
|
|
2964
|
+
const selected = [];
|
|
2965
|
+
for (const sentence of sentences) {
|
|
2966
|
+
selected.push(sentence.trim());
|
|
2967
|
+
const candidate = selected.join(" ");
|
|
2968
|
+
if (selected.length >= maxSentences || candidate.length >= maxChars) break;
|
|
2969
|
+
}
|
|
2970
|
+
const summary = selected.join(" ").trim() || normalized;
|
|
2971
|
+
if (summary.length <= maxChars) return summary;
|
|
2972
|
+
const hardLimit = maxChars - 4;
|
|
2973
|
+
const boundary = findWordBoundary(summary, hardLimit);
|
|
2974
|
+
return `${summary.slice(0, boundary > 0 ? boundary : hardLimit).trimEnd()} ...`;
|
|
2975
|
+
}
|
|
2976
|
+
function applyToolDescriptionModeToTool(tool, mode) {
|
|
2977
|
+
const existingOriginal = getOriginalDescription(tool);
|
|
2978
|
+
if (mode === "extend" && !existingOriginal) return tool;
|
|
2979
|
+
const original = existingOriginal ?? {
|
|
2980
|
+
description: tool.description,
|
|
2981
|
+
usageHint: tool.usageHint
|
|
2982
|
+
};
|
|
2983
|
+
const next = mode === "simple" ? withDescription(tool, {
|
|
2984
|
+
description: simplifyToolDescription(original.description),
|
|
2985
|
+
usageHint: original.usageHint === void 0 ? void 0 : simplifyToolDescription(original.usageHint)
|
|
2986
|
+
}) : withDescription(tool, original);
|
|
2987
|
+
return attachOriginalDescription(next, original);
|
|
2988
|
+
}
|
|
2989
|
+
function setToolDescriptionMode(registry, name, mode) {
|
|
2990
|
+
if (typeof registry.setDescriptionMode === "function") {
|
|
2991
|
+
return registry.setDescriptionMode(name, mode);
|
|
2992
|
+
}
|
|
2993
|
+
if (!registry.get(name) || typeof registry.wrap !== "function") return false;
|
|
2994
|
+
registry.wrap(
|
|
2995
|
+
name,
|
|
2996
|
+
(tool) => applyToolDescriptionModeToTool(tool, mode),
|
|
2997
|
+
"tool-description-mode"
|
|
2998
|
+
);
|
|
2999
|
+
return true;
|
|
3000
|
+
}
|
|
3001
|
+
function getToolDescriptionMode(registry, name) {
|
|
3002
|
+
return registry.getDescriptionMode?.(name) ?? DEFAULT_TOOL_DESCRIPTION_MODE;
|
|
3003
|
+
}
|
|
3004
|
+
function applyToolDescriptionModes(registry, modes) {
|
|
3005
|
+
if (typeof registry.applyDescriptionModes === "function") {
|
|
3006
|
+
return registry.applyDescriptionModes(modes);
|
|
3007
|
+
}
|
|
3008
|
+
const entries = Object.entries(modes ?? {});
|
|
3009
|
+
const missing = [];
|
|
3010
|
+
let applied = 0;
|
|
3011
|
+
for (const [name, rawMode] of entries) {
|
|
3012
|
+
const mode = normalizeToolDescriptionMode(rawMode);
|
|
3013
|
+
if (!mode) continue;
|
|
3014
|
+
if (setToolDescriptionMode(registry, name, mode)) applied++;
|
|
3015
|
+
else missing.push(name);
|
|
3016
|
+
}
|
|
3017
|
+
return { applied, missing };
|
|
3018
|
+
}
|
|
3019
|
+
function getOriginalDescription(tool) {
|
|
3020
|
+
return tool[ORIGINAL_TOOL_DESCRIPTION];
|
|
3021
|
+
}
|
|
3022
|
+
function attachOriginalDescription(tool, original) {
|
|
3023
|
+
Object.defineProperty(tool, ORIGINAL_TOOL_DESCRIPTION, {
|
|
3024
|
+
configurable: true,
|
|
3025
|
+
enumerable: false,
|
|
3026
|
+
value: original,
|
|
3027
|
+
writable: true
|
|
3028
|
+
});
|
|
3029
|
+
return tool;
|
|
3030
|
+
}
|
|
3031
|
+
function withDescription(tool, next) {
|
|
3032
|
+
const copy = {
|
|
3033
|
+
...tool,
|
|
3034
|
+
description: next.description,
|
|
3035
|
+
usageHint: next.usageHint
|
|
3036
|
+
};
|
|
3037
|
+
if (next.usageHint === void 0) {
|
|
3038
|
+
delete copy.usageHint;
|
|
3039
|
+
}
|
|
3040
|
+
return copy;
|
|
3041
|
+
}
|
|
3042
|
+
function findWordBoundary(text, limit) {
|
|
3043
|
+
const semantic = Math.max(
|
|
3044
|
+
text.lastIndexOf(". ", limit),
|
|
3045
|
+
text.lastIndexOf("; ", limit),
|
|
3046
|
+
text.lastIndexOf(", ", limit)
|
|
3047
|
+
);
|
|
3048
|
+
if (semantic > 40) return semantic + 1;
|
|
3049
|
+
const space = text.lastIndexOf(" ", limit);
|
|
3050
|
+
return space > 40 ? space : limit;
|
|
3051
|
+
}
|
|
3052
|
+
|
|
2895
3053
|
// src/utils/tool-output-serializer.ts
|
|
2896
3054
|
var DEFAULT_LIST_LIMIT = 500;
|
|
2897
3055
|
var LOG_ENTRY_LIMIT = 200;
|
|
@@ -3555,114 +3713,6 @@ function isScalar(value) {
|
|
|
3555
3713
|
return value === null || ["string", "number", "boolean"].includes(typeof value);
|
|
3556
3714
|
}
|
|
3557
3715
|
|
|
3558
|
-
// src/utils/tool-description-mode.ts
|
|
3559
|
-
var DEFAULT_TOOL_DESCRIPTION_MODE = "extend";
|
|
3560
|
-
var ORIGINAL_TOOL_DESCRIPTION = /* @__PURE__ */ Symbol.for("wrongstack.tool.originalDescription");
|
|
3561
|
-
function normalizeToolDescriptionMode(value) {
|
|
3562
|
-
if (typeof value !== "string") return void 0;
|
|
3563
|
-
const raw = value.trim().toLowerCase();
|
|
3564
|
-
if (raw === "extend" || raw === "extended" || raw === "full") return "extend";
|
|
3565
|
-
if (raw === "simple" || raw === "short" || raw === "brief") return "simple";
|
|
3566
|
-
return void 0;
|
|
3567
|
-
}
|
|
3568
|
-
function resolveToolDescriptionMode(modes, toolName) {
|
|
3569
|
-
return normalizeToolDescriptionMode(modes?.[toolName]) ?? DEFAULT_TOOL_DESCRIPTION_MODE;
|
|
3570
|
-
}
|
|
3571
|
-
function simplifyToolDescription(text, opts = {}) {
|
|
3572
|
-
const maxSentences = Math.max(1, opts.maxSentences ?? 2);
|
|
3573
|
-
const maxChars = Math.max(40, opts.maxChars ?? 180);
|
|
3574
|
-
const normalized = text.replace(/\r\n?/g, "\n").split("\n").map((line) => line.trim()).filter(Boolean).join(" ").replace(/\s+/g, " ").trim();
|
|
3575
|
-
if (normalized.length <= maxChars) return normalized;
|
|
3576
|
-
const sentences = normalized.match(/[^.!?]+[.!?]+(?=\s|$)|[^.!?]+$/g) ?? [normalized];
|
|
3577
|
-
const selected = [];
|
|
3578
|
-
for (const sentence of sentences) {
|
|
3579
|
-
selected.push(sentence.trim());
|
|
3580
|
-
const candidate = selected.join(" ");
|
|
3581
|
-
if (selected.length >= maxSentences || candidate.length >= maxChars) break;
|
|
3582
|
-
}
|
|
3583
|
-
const summary = selected.join(" ").trim() || normalized;
|
|
3584
|
-
if (summary.length <= maxChars) return summary;
|
|
3585
|
-
const hardLimit = maxChars - 4;
|
|
3586
|
-
const boundary = findWordBoundary(summary, hardLimit);
|
|
3587
|
-
return `${summary.slice(0, boundary > 0 ? boundary : hardLimit).trimEnd()} ...`;
|
|
3588
|
-
}
|
|
3589
|
-
function applyToolDescriptionModeToTool(tool, mode) {
|
|
3590
|
-
const existingOriginal = getOriginalDescription(tool);
|
|
3591
|
-
if (mode === "extend" && !existingOriginal) return tool;
|
|
3592
|
-
const original = existingOriginal ?? {
|
|
3593
|
-
description: tool.description,
|
|
3594
|
-
usageHint: tool.usageHint
|
|
3595
|
-
};
|
|
3596
|
-
const next = mode === "simple" ? withDescription(tool, {
|
|
3597
|
-
description: simplifyToolDescription(original.description),
|
|
3598
|
-
usageHint: original.usageHint === void 0 ? void 0 : simplifyToolDescription(original.usageHint)
|
|
3599
|
-
}) : withDescription(tool, original);
|
|
3600
|
-
return attachOriginalDescription(next, original);
|
|
3601
|
-
}
|
|
3602
|
-
function setToolDescriptionMode(registry, name, mode) {
|
|
3603
|
-
if (typeof registry.setDescriptionMode === "function") {
|
|
3604
|
-
return registry.setDescriptionMode(name, mode);
|
|
3605
|
-
}
|
|
3606
|
-
if (!registry.get(name) || typeof registry.wrap !== "function") return false;
|
|
3607
|
-
registry.wrap(
|
|
3608
|
-
name,
|
|
3609
|
-
(tool) => applyToolDescriptionModeToTool(tool, mode),
|
|
3610
|
-
"tool-description-mode"
|
|
3611
|
-
);
|
|
3612
|
-
return true;
|
|
3613
|
-
}
|
|
3614
|
-
function getToolDescriptionMode(registry, name) {
|
|
3615
|
-
return registry.getDescriptionMode?.(name) ?? DEFAULT_TOOL_DESCRIPTION_MODE;
|
|
3616
|
-
}
|
|
3617
|
-
function applyToolDescriptionModes(registry, modes) {
|
|
3618
|
-
if (typeof registry.applyDescriptionModes === "function") {
|
|
3619
|
-
return registry.applyDescriptionModes(modes);
|
|
3620
|
-
}
|
|
3621
|
-
const entries = Object.entries(modes ?? {});
|
|
3622
|
-
const missing = [];
|
|
3623
|
-
let applied = 0;
|
|
3624
|
-
for (const [name, rawMode] of entries) {
|
|
3625
|
-
const mode = normalizeToolDescriptionMode(rawMode);
|
|
3626
|
-
if (!mode) continue;
|
|
3627
|
-
if (setToolDescriptionMode(registry, name, mode)) applied++;
|
|
3628
|
-
else missing.push(name);
|
|
3629
|
-
}
|
|
3630
|
-
return { applied, missing };
|
|
3631
|
-
}
|
|
3632
|
-
function getOriginalDescription(tool) {
|
|
3633
|
-
return tool[ORIGINAL_TOOL_DESCRIPTION];
|
|
3634
|
-
}
|
|
3635
|
-
function attachOriginalDescription(tool, original) {
|
|
3636
|
-
Object.defineProperty(tool, ORIGINAL_TOOL_DESCRIPTION, {
|
|
3637
|
-
configurable: true,
|
|
3638
|
-
enumerable: false,
|
|
3639
|
-
value: original,
|
|
3640
|
-
writable: true
|
|
3641
|
-
});
|
|
3642
|
-
return tool;
|
|
3643
|
-
}
|
|
3644
|
-
function withDescription(tool, next) {
|
|
3645
|
-
const copy = {
|
|
3646
|
-
...tool,
|
|
3647
|
-
description: next.description,
|
|
3648
|
-
usageHint: next.usageHint
|
|
3649
|
-
};
|
|
3650
|
-
if (next.usageHint === void 0) {
|
|
3651
|
-
delete copy.usageHint;
|
|
3652
|
-
}
|
|
3653
|
-
return copy;
|
|
3654
|
-
}
|
|
3655
|
-
function findWordBoundary(text, limit) {
|
|
3656
|
-
const semantic = Math.max(
|
|
3657
|
-
text.lastIndexOf(". ", limit),
|
|
3658
|
-
text.lastIndexOf("; ", limit),
|
|
3659
|
-
text.lastIndexOf(", ", limit)
|
|
3660
|
-
);
|
|
3661
|
-
if (semantic > 40) return semantic + 1;
|
|
3662
|
-
const space = text.lastIndexOf(" ", limit);
|
|
3663
|
-
return space > 40 ? space : limit;
|
|
3664
|
-
}
|
|
3665
|
-
|
|
3666
3716
|
// src/utils/tool-result-render-mode.ts
|
|
3667
3717
|
var DEFAULT_TOOL_RESULT_RENDER_MODE = "extend";
|
|
3668
3718
|
function normalizeToolResultRenderMode(value) {
|
|
@@ -3700,25 +3750,95 @@ function applyToolResultRenderModes(registry, modes) {
|
|
|
3700
3750
|
return { applied, missing };
|
|
3701
3751
|
}
|
|
3702
3752
|
|
|
3753
|
+
// src/utils/tool-subject.ts
|
|
3754
|
+
var GLOB_METACHARACTERS = /[*?[\]]/g;
|
|
3755
|
+
function escapeGlobSubject(value) {
|
|
3756
|
+
return value.replace(GLOB_METACHARACTERS, (char) => `\\${char}`);
|
|
3757
|
+
}
|
|
3758
|
+
function normalizePathSubject(value) {
|
|
3759
|
+
return escapeGlobSubject(value.replace(/\\/g, "/"));
|
|
3760
|
+
}
|
|
3761
|
+
function isPathSubjectKey(subjectKey) {
|
|
3762
|
+
return subjectKey === "path" || subjectKey === "file" || subjectKey === "files";
|
|
3763
|
+
}
|
|
3764
|
+
function subjectForToolInput(toolName, input, subjectKey) {
|
|
3765
|
+
if (!input || typeof input !== "object") return void 0;
|
|
3766
|
+
const obj = input;
|
|
3767
|
+
if (subjectKey) {
|
|
3768
|
+
const value = obj[subjectKey];
|
|
3769
|
+
if (typeof value === "string") {
|
|
3770
|
+
return isPathSubjectKey(subjectKey) ? normalizePathSubject(value) : escapeGlobSubject(value);
|
|
3771
|
+
}
|
|
3772
|
+
}
|
|
3773
|
+
if (toolName === "bash" && typeof obj.command === "string") {
|
|
3774
|
+
return escapeGlobSubject(obj.command);
|
|
3775
|
+
}
|
|
3776
|
+
if (typeof obj.path === "string") {
|
|
3777
|
+
return normalizePathSubject(obj.path);
|
|
3778
|
+
}
|
|
3779
|
+
if (typeof obj.url === "string") {
|
|
3780
|
+
return escapeGlobSubject(obj.url);
|
|
3781
|
+
}
|
|
3782
|
+
if (typeof obj.name === "string") {
|
|
3783
|
+
return escapeGlobSubject(obj.name);
|
|
3784
|
+
}
|
|
3785
|
+
return void 0;
|
|
3786
|
+
}
|
|
3787
|
+
|
|
3788
|
+
// src/utils/ulid.ts
|
|
3789
|
+
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
3790
|
+
var ENCODING = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
|
|
3791
|
+
var ENCODING_LEN = ENCODING.length;
|
|
3792
|
+
var TIME_LEN = 10;
|
|
3793
|
+
var RANDOM_LEN = 16;
|
|
3794
|
+
function encodeTime(now, len) {
|
|
3795
|
+
let mod;
|
|
3796
|
+
let str = "";
|
|
3797
|
+
for (let i = len - 1; i >= 0; i--) {
|
|
3798
|
+
mod = now % ENCODING_LEN;
|
|
3799
|
+
str = ENCODING[mod] + str;
|
|
3800
|
+
now = (now - mod) / ENCODING_LEN;
|
|
3801
|
+
}
|
|
3802
|
+
return str;
|
|
3803
|
+
}
|
|
3804
|
+
function encodeRandom(len) {
|
|
3805
|
+
const bytes = randomBytes2(len);
|
|
3806
|
+
let str = "";
|
|
3807
|
+
for (let i = 0; i < len; i++) {
|
|
3808
|
+
str += ENCODING[bytes[i] % ENCODING_LEN];
|
|
3809
|
+
}
|
|
3810
|
+
return str;
|
|
3811
|
+
}
|
|
3812
|
+
function ulid(seedTime = Date.now()) {
|
|
3813
|
+
return encodeTime(seedTime, TIME_LEN) + encodeRandom(RANDOM_LEN);
|
|
3814
|
+
}
|
|
3815
|
+
function isUlid(value) {
|
|
3816
|
+
if (value.length !== TIME_LEN + RANDOM_LEN) return false;
|
|
3817
|
+
for (const ch of value) {
|
|
3818
|
+
if (!ENCODING.includes(ch)) return false;
|
|
3819
|
+
}
|
|
3820
|
+
return true;
|
|
3821
|
+
}
|
|
3822
|
+
|
|
3703
3823
|
// src/utils/wstack-paths.ts
|
|
3704
3824
|
import { createHash } from "node:crypto";
|
|
3705
|
-
import * as
|
|
3825
|
+
import * as fs4 from "node:fs";
|
|
3706
3826
|
import * as os from "node:os";
|
|
3707
|
-
import * as
|
|
3827
|
+
import * as path5 from "node:path";
|
|
3708
3828
|
function canonicalProjectRoot(absRoot) {
|
|
3709
|
-
const checkoutRoot =
|
|
3710
|
-
const dotGit =
|
|
3829
|
+
const checkoutRoot = path5.resolve(absRoot);
|
|
3830
|
+
const dotGit = path5.join(checkoutRoot, ".git");
|
|
3711
3831
|
try {
|
|
3712
|
-
if (!
|
|
3713
|
-
const gitDirLine =
|
|
3832
|
+
if (!fs4.statSync(dotGit).isFile()) return checkoutRoot;
|
|
3833
|
+
const gitDirLine = fs4.readFileSync(dotGit, "utf8").trim();
|
|
3714
3834
|
const match = /^gitdir:\s*(.+)$/i.exec(gitDirLine);
|
|
3715
3835
|
if (!match?.[1]) return checkoutRoot;
|
|
3716
|
-
const gitDir =
|
|
3717
|
-
const commonDirFile =
|
|
3718
|
-
if (!
|
|
3719
|
-
const commonDir =
|
|
3720
|
-
if (
|
|
3721
|
-
return
|
|
3836
|
+
const gitDir = path5.resolve(checkoutRoot, match[1].trim());
|
|
3837
|
+
const commonDirFile = path5.join(gitDir, "commondir");
|
|
3838
|
+
if (!fs4.statSync(commonDirFile).isFile()) return checkoutRoot;
|
|
3839
|
+
const commonDir = path5.resolve(gitDir, fs4.readFileSync(commonDirFile, "utf8").trim());
|
|
3840
|
+
if (path5.basename(commonDir).toLowerCase() !== ".git") return checkoutRoot;
|
|
3841
|
+
return path5.dirname(commonDir);
|
|
3722
3842
|
} catch {
|
|
3723
3843
|
return checkoutRoot;
|
|
3724
3844
|
}
|
|
@@ -3728,7 +3848,7 @@ function projectHash(absRoot) {
|
|
|
3728
3848
|
}
|
|
3729
3849
|
function projectSlug(absRoot) {
|
|
3730
3850
|
const identityRoot = canonicalProjectRoot(absRoot);
|
|
3731
|
-
const base = slugify2(
|
|
3851
|
+
const base = slugify2(path5.basename(identityRoot));
|
|
3732
3852
|
const hash = createHash("sha256").update(identityRoot).digest("hex").slice(0, 6);
|
|
3733
3853
|
return `${base}-${hash}`;
|
|
3734
3854
|
}
|
|
@@ -3737,61 +3857,83 @@ function slugify2(name) {
|
|
|
3737
3857
|
}
|
|
3738
3858
|
function wstackGlobalRoot() {
|
|
3739
3859
|
const fromEnv = process.env["WRONGSTACK_HOME"];
|
|
3740
|
-
if (fromEnv && fromEnv.trim().length > 0) return
|
|
3741
|
-
return
|
|
3860
|
+
if (fromEnv && fromEnv.trim().length > 0) return path5.resolve(fromEnv);
|
|
3861
|
+
return path5.join(os.homedir(), ".wrongstack");
|
|
3742
3862
|
}
|
|
3743
3863
|
function resolveWstackPaths(opts) {
|
|
3744
|
-
const globalRoot = opts.globalRoot ?? (opts.userHome ?
|
|
3864
|
+
const globalRoot = opts.globalRoot ?? (opts.userHome ? path5.join(opts.userHome, ".wrongstack") : wstackGlobalRoot());
|
|
3745
3865
|
const homeDir = opts.userHome ?? os.homedir();
|
|
3746
3866
|
const hash = projectHash(opts.projectRoot);
|
|
3747
3867
|
const slug = projectSlug(opts.projectRoot);
|
|
3748
|
-
const projectDir =
|
|
3868
|
+
const projectDir = path5.join(globalRoot, "projects", slug);
|
|
3749
3869
|
return {
|
|
3750
3870
|
globalRoot,
|
|
3751
3871
|
projectRoot: opts.projectRoot,
|
|
3752
3872
|
homeDir,
|
|
3753
3873
|
configDir: globalRoot,
|
|
3754
|
-
globalConfig:
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3874
|
+
globalConfig: path5.join(globalRoot, "config.json"),
|
|
3875
|
+
profilesDir: path5.join(globalRoot, "profiles"),
|
|
3876
|
+
profileConfig: (name) => {
|
|
3877
|
+
const safe = name.replace(/[/\\:]/g, "_").replace(/\.\./g, "_");
|
|
3878
|
+
return path5.join(globalRoot, "profiles", safe || "default", "config.json");
|
|
3879
|
+
},
|
|
3880
|
+
profileStatuslineConfig: (name) => {
|
|
3881
|
+
const safe = name.replace(/[/\\:]/g, "_").replace(/\.\./g, "_");
|
|
3882
|
+
return path5.join(globalRoot, "profiles", safe || "default", "statusline.json");
|
|
3883
|
+
},
|
|
3884
|
+
profileModeConfig: (name) => {
|
|
3885
|
+
const safe = name.replace(/[/\\:]/g, "_").replace(/\.\./g, "_");
|
|
3886
|
+
return path5.join(globalRoot, "profiles", safe || "default", "mode.json");
|
|
3887
|
+
},
|
|
3888
|
+
profileProviderStatus: (name) => {
|
|
3889
|
+
const safe = name.replace(/[/\\:]/g, "_").replace(/\.\./g, "_");
|
|
3890
|
+
return path5.join(globalRoot, "profiles", safe || "default", "provider-status.json");
|
|
3891
|
+
},
|
|
3892
|
+
profileUpdateCache: (name) => {
|
|
3893
|
+
const safe = name.replace(/[/\\:]/g, "_").replace(/\.\./g, "_");
|
|
3894
|
+
return path5.join(globalRoot, "profiles", safe || "default", "update-cache.json");
|
|
3895
|
+
},
|
|
3896
|
+
secretsKey: path5.join(globalRoot, ".key"),
|
|
3897
|
+
globalMemory: path5.join(globalRoot, "memory.md"),
|
|
3898
|
+
globalSkills: path5.join(globalRoot, "skills"),
|
|
3899
|
+
globalClaudeSkills: path5.join(homeDir, ".claude", "skills"),
|
|
3900
|
+
globalDesignKits: path5.join(globalRoot, "design-kits"),
|
|
3901
|
+
globalPrompts: path5.join(globalRoot, "prompts"),
|
|
3902
|
+
globalInstructions: path5.join(globalRoot, "instructions"),
|
|
3903
|
+
promptUsage: path5.join(globalRoot, "prompt-usage.json"),
|
|
3904
|
+
cacheDir: path5.join(globalRoot, "cache"),
|
|
3905
|
+
modelsCache: path5.join(globalRoot, "cache", "models.dev.json"),
|
|
3906
|
+
modelsOverlayCache: path5.join(globalRoot, "cache", "models-overlay.json"),
|
|
3907
|
+
historyFile: path5.join(globalRoot, "history"),
|
|
3908
|
+
logFile: path5.join(globalRoot, "logs", "wrongstack.log"),
|
|
3768
3909
|
projectDir,
|
|
3769
|
-
projectCodebaseIndex:
|
|
3770
|
-
projectMemory:
|
|
3771
|
-
projectSessions:
|
|
3772
|
-
projectTrust:
|
|
3773
|
-
projectMeta:
|
|
3774
|
-
projectLocalConfig:
|
|
3775
|
-
inProjectConfig:
|
|
3776
|
-
inProjectAgentsFile:
|
|
3777
|
-
inProjectSkills:
|
|
3778
|
-
inProjectClaudeSkills:
|
|
3779
|
-
inProjectPrompts:
|
|
3780
|
-
inProjectInstructions:
|
|
3781
|
-
inProjectDesignKits:
|
|
3782
|
-
inProjectWorktrees:
|
|
3910
|
+
projectCodebaseIndex: path5.join(projectDir, "codebase-index"),
|
|
3911
|
+
projectMemory: path5.join(projectDir, "memory.md"),
|
|
3912
|
+
projectSessions: path5.join(projectDir, "sessions"),
|
|
3913
|
+
projectTrust: path5.join(projectDir, "trust.json"),
|
|
3914
|
+
projectMeta: path5.join(projectDir, "meta.json"),
|
|
3915
|
+
projectLocalConfig: path5.join(projectDir, "config.local.json"),
|
|
3916
|
+
inProjectConfig: path5.join(opts.projectRoot, ".wrongstack", "config.json"),
|
|
3917
|
+
inProjectAgentsFile: path5.join(opts.projectRoot, ".wrongstack", "AGENTS.md"),
|
|
3918
|
+
inProjectSkills: path5.join(opts.projectRoot, ".wrongstack", "skills"),
|
|
3919
|
+
inProjectClaudeSkills: path5.join(opts.projectRoot, ".claude", "skills"),
|
|
3920
|
+
inProjectPrompts: path5.join(opts.projectRoot, ".wrongstack", "prompts"),
|
|
3921
|
+
inProjectInstructions: path5.join(opts.projectRoot, ".wrongstack", "instructions"),
|
|
3922
|
+
inProjectDesignKits: path5.join(opts.projectRoot, ".wrongstack", "design-kits"),
|
|
3923
|
+
inProjectWorktrees: path5.join(opts.projectRoot, ".wrongstack", "worktrees"),
|
|
3783
3924
|
projectHash: hash,
|
|
3784
3925
|
projectSlug: slug,
|
|
3785
|
-
projectGoal:
|
|
3786
|
-
projectInputHistory:
|
|
3787
|
-
projectSpecs:
|
|
3788
|
-
projectTaskGraphs:
|
|
3789
|
-
projectSddSession:
|
|
3790
|
-
projectPlan:
|
|
3791
|
-
projectAutophase:
|
|
3792
|
-
projectSddBoards:
|
|
3793
|
-
syncConfig:
|
|
3794
|
-
|
|
3926
|
+
projectGoal: path5.join(projectDir, "goal.json"),
|
|
3927
|
+
projectInputHistory: path5.join(projectDir, "input-history.json"),
|
|
3928
|
+
projectSpecs: path5.join(projectDir, "specs"),
|
|
3929
|
+
projectTaskGraphs: path5.join(projectDir, "task-graphs"),
|
|
3930
|
+
projectSddSession: path5.join(projectDir, "sdd-session.json"),
|
|
3931
|
+
projectPlan: path5.join(projectDir, "plan.json"),
|
|
3932
|
+
projectAutophase: path5.join(projectDir, "autophase"),
|
|
3933
|
+
projectSddBoards: path5.join(projectDir, "sdd-boards"),
|
|
3934
|
+
syncConfig: path5.join(globalRoot, "sync.json"),
|
|
3935
|
+
configHistoryDir: path5.join(globalRoot, "config-history"),
|
|
3936
|
+
projectStatus: (projectHash2) => path5.join(globalRoot, "projects", projectHash2, "status.json")
|
|
3795
3937
|
};
|
|
3796
3938
|
}
|
|
3797
3939
|
export {
|
|
@@ -3810,6 +3952,7 @@ export {
|
|
|
3810
3952
|
assertNever,
|
|
3811
3953
|
assertNotPrivateHost,
|
|
3812
3954
|
atomicWrite,
|
|
3955
|
+
backupConfigFile,
|
|
3813
3956
|
buildChildEnv,
|
|
3814
3957
|
buildCompletedWorkLedgerBlock,
|
|
3815
3958
|
buildContextEvidenceDigest,
|
|
@@ -3826,6 +3969,7 @@ export {
|
|
|
3826
3969
|
completePartialObject,
|
|
3827
3970
|
computeMessageTokens,
|
|
3828
3971
|
computeTaskItemProgress,
|
|
3972
|
+
configHistoryDir,
|
|
3829
3973
|
configureChildEnvGitIdentity,
|
|
3830
3974
|
createContextEvidenceState,
|
|
3831
3975
|
createToolOutputSerializer,
|
|
@@ -3853,6 +3997,7 @@ export {
|
|
|
3853
3997
|
getJsonPath,
|
|
3854
3998
|
getToolDescriptionMode,
|
|
3855
3999
|
getToolResultRenderMode,
|
|
4000
|
+
hasMeaningfulContent,
|
|
3856
4001
|
hasOpenTodos,
|
|
3857
4002
|
isJsonObject,
|
|
3858
4003
|
isPathSubjectKey,
|
|
@@ -3870,6 +4015,7 @@ export {
|
|
|
3870
4015
|
normalizeToLf,
|
|
3871
4016
|
normalizeToolDescriptionMode,
|
|
3872
4017
|
normalizeToolResultRenderMode,
|
|
4018
|
+
normalizeTopLevelToolSchema,
|
|
3873
4019
|
parseIncomingImages,
|
|
3874
4020
|
projectHash,
|
|
3875
4021
|
projectSlug,
|