@cydm/pie 1.0.7 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -5
- package/dist/builtin/extensions/ask-user/index.js +1 -1
- package/dist/builtin/extensions/init/index.js +70 -68
- package/dist/builtin/extensions/plan-mode/index.js +1 -1
- package/dist/builtin/extensions/subagent/index.js +10 -65
- package/dist/builtin/extensions/todo/index.js +1 -1
- package/dist/builtin/skills/browser-tools/SKILL.md +14 -14
- package/dist/chunks/{chunk-BHNULR7U.js → chunk-6WD2NFIC.js} +822 -430
- package/dist/chunks/chunk-NTYHFBUA.js +36 -0
- package/dist/chunks/{chunk-GDTN4UPJ.js → chunk-ZRONUKTW.js} +297 -9
- package/dist/cli.js +554 -486
- package/package.json +2 -2
- package/dist/builtin/skills/pie-unity-rpc/SKILL.md +0 -121
- package/dist/builtin/skills/pie-unity-rpc/pie-unity-rpc.js +0 -417
package/dist/cli.js
CHANGED
|
@@ -1,17 +1,29 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
|
-
createCliHostCapabilities
|
|
5
|
-
|
|
4
|
+
createCliHostCapabilities,
|
|
5
|
+
createCliWebResearchHealthStore,
|
|
6
|
+
getAgentDir,
|
|
7
|
+
getBuiltinDir,
|
|
8
|
+
getConfigDir,
|
|
9
|
+
getCustomThemesDir,
|
|
10
|
+
getLogsDir,
|
|
11
|
+
getPackageDir,
|
|
12
|
+
getRuntimeLogPath,
|
|
13
|
+
getSessionsDir,
|
|
14
|
+
getSettingsPath,
|
|
15
|
+
getThemesDir,
|
|
16
|
+
migrateConfigFromAgentDir
|
|
17
|
+
} from "./chunks/chunk-ZRONUKTW.js";
|
|
6
18
|
import {
|
|
19
|
+
AGENTS_CONTEXT_FILE_NAME,
|
|
7
20
|
AgentSessionController,
|
|
8
21
|
BUILTIN_TOOL_CAPABILITY_METADATA,
|
|
9
22
|
SessionTraceSnapshotWriter,
|
|
10
23
|
abortExecutionState,
|
|
11
24
|
attachAgentEventsToSessionTrace,
|
|
12
25
|
buildExecutionReminder,
|
|
13
|
-
|
|
14
|
-
buildKnowledgeIndexSection,
|
|
26
|
+
buildProjectContextSection,
|
|
15
27
|
buildToolsPromptSection,
|
|
16
28
|
calculateTotalTokens,
|
|
17
29
|
continueExecutionState,
|
|
@@ -21,11 +33,9 @@ import {
|
|
|
21
33
|
createExecutionStateStore,
|
|
22
34
|
createPolicyEnforcedTools,
|
|
23
35
|
createReadFileUnderstandingHandler,
|
|
24
|
-
createReadResourceCapability,
|
|
25
|
-
createReadSkillCapability,
|
|
26
|
-
createResolveResourceCapability,
|
|
27
36
|
createSessionManager,
|
|
28
37
|
createSharedFileSystemTools,
|
|
38
|
+
createSharedWebSearchTool,
|
|
29
39
|
createTodoWidgetView,
|
|
30
40
|
evaluateTodoClosureAfterAbort,
|
|
31
41
|
evaluateTodoClosureAfterCompletedTurn,
|
|
@@ -35,13 +45,14 @@ import {
|
|
|
35
45
|
hasInteractionHandler,
|
|
36
46
|
maybeAdvanceTodoExecutionState,
|
|
37
47
|
modalityForReadFileUnderstandingKind,
|
|
48
|
+
pauseExecutionState,
|
|
38
49
|
registerInteractionHandler,
|
|
39
50
|
requestInteraction,
|
|
40
51
|
restoreExecutionState,
|
|
41
52
|
selectToolsForRuntimePolicy,
|
|
42
53
|
shouldPreserveExecutionStateForUserText,
|
|
43
54
|
supersedeExecutionState
|
|
44
|
-
} from "./chunks/chunk-
|
|
55
|
+
} from "./chunks/chunk-6WD2NFIC.js";
|
|
45
56
|
import {
|
|
46
57
|
Deref,
|
|
47
58
|
Errors,
|
|
@@ -76,6 +87,9 @@ import {
|
|
|
76
87
|
sortToolModelCandidatesByCapability,
|
|
77
88
|
type_exports
|
|
78
89
|
} from "./chunks/chunk-A5JSJAPK.js";
|
|
90
|
+
import {
|
|
91
|
+
resolveCliProjectRoot
|
|
92
|
+
} from "./chunks/chunk-NTYHFBUA.js";
|
|
79
93
|
import {
|
|
80
94
|
__commonJS,
|
|
81
95
|
__require,
|
|
@@ -1883,7 +1897,7 @@ var require_core = __commonJS({
|
|
|
1883
1897
|
return match && match.index === 0;
|
|
1884
1898
|
}
|
|
1885
1899
|
var BACKREF_RE = /\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;
|
|
1886
|
-
function
|
|
1900
|
+
function join19(regexps, separator = "|") {
|
|
1887
1901
|
let numCaptures = 0;
|
|
1888
1902
|
return regexps.map((regex) => {
|
|
1889
1903
|
numCaptures += 1;
|
|
@@ -2187,7 +2201,7 @@ var require_core = __commonJS({
|
|
|
2187
2201
|
this.exec = () => null;
|
|
2188
2202
|
}
|
|
2189
2203
|
const terminators = this.regexes.map((el) => el[1]);
|
|
2190
|
-
this.matcherRe = langRe(
|
|
2204
|
+
this.matcherRe = langRe(join19(terminators), true);
|
|
2191
2205
|
this.lastIndex = 0;
|
|
2192
2206
|
}
|
|
2193
2207
|
/** @param {string} s */
|
|
@@ -14049,7 +14063,7 @@ var require_http = __commonJS({
|
|
|
14049
14063
|
return joined;
|
|
14050
14064
|
}
|
|
14051
14065
|
function http(hljs) {
|
|
14052
|
-
const
|
|
14066
|
+
const VERSION = "HTTP/(2|1\\.[01])";
|
|
14053
14067
|
const HEADER_NAME = /[A-Za-z][A-Za-z0-9-]*/;
|
|
14054
14068
|
const HEADER = {
|
|
14055
14069
|
className: "attribute",
|
|
@@ -14082,12 +14096,12 @@ var require_http = __commonJS({
|
|
|
14082
14096
|
contains: [
|
|
14083
14097
|
// response
|
|
14084
14098
|
{
|
|
14085
|
-
begin: "^(?=" +
|
|
14099
|
+
begin: "^(?=" + VERSION + " \\d{3})",
|
|
14086
14100
|
end: /$/,
|
|
14087
14101
|
contains: [
|
|
14088
14102
|
{
|
|
14089
14103
|
className: "meta",
|
|
14090
|
-
begin:
|
|
14104
|
+
begin: VERSION
|
|
14091
14105
|
},
|
|
14092
14106
|
{
|
|
14093
14107
|
className: "number",
|
|
@@ -14102,7 +14116,7 @@ var require_http = __commonJS({
|
|
|
14102
14116
|
},
|
|
14103
14117
|
// request
|
|
14104
14118
|
{
|
|
14105
|
-
begin: "(?=^[A-Z]+ (.*?) " +
|
|
14119
|
+
begin: "(?=^[A-Z]+ (.*?) " + VERSION + "$)",
|
|
14106
14120
|
end: /$/,
|
|
14107
14121
|
contains: [
|
|
14108
14122
|
{
|
|
@@ -14114,7 +14128,7 @@ var require_http = __commonJS({
|
|
|
14114
14128
|
},
|
|
14115
14129
|
{
|
|
14116
14130
|
className: "meta",
|
|
14117
|
-
begin:
|
|
14131
|
+
begin: VERSION
|
|
14118
14132
|
},
|
|
14119
14133
|
{
|
|
14120
14134
|
className: "keyword",
|
|
@@ -50554,7 +50568,7 @@ var ProcessTerminal = class {
|
|
|
50554
50568
|
const timeLeft = endTime - now;
|
|
50555
50569
|
if (timeLeft <= 0) break;
|
|
50556
50570
|
if (now - lastDataTime >= idleMs) break;
|
|
50557
|
-
await new Promise((
|
|
50571
|
+
await new Promise((resolve4) => setTimeout(resolve4, Math.min(idleMs, timeLeft)));
|
|
50558
50572
|
}
|
|
50559
50573
|
} finally {
|
|
50560
50574
|
process.stdin.removeListener("data", onData);
|
|
@@ -50629,120 +50643,8 @@ var ProcessTerminal = class {
|
|
|
50629
50643
|
};
|
|
50630
50644
|
|
|
50631
50645
|
// src/keybindings.ts
|
|
50632
|
-
import { existsSync
|
|
50633
|
-
import { join as
|
|
50634
|
-
|
|
50635
|
-
// src/config.ts
|
|
50636
|
-
import { existsSync, mkdirSync as mkdirSync2, readFileSync, renameSync } from "fs";
|
|
50637
|
-
import { homedir as homedir2 } from "os";
|
|
50638
|
-
import { dirname as dirname2, join as join2 } from "path";
|
|
50639
|
-
import { fileURLToPath } from "url";
|
|
50640
|
-
var __filename = fileURLToPath(import.meta.url);
|
|
50641
|
-
var __dirname = dirname2(__filename);
|
|
50642
|
-
var isBunRuntime = !!process.versions.bun;
|
|
50643
|
-
function getPackageDir() {
|
|
50644
|
-
const envDir = process.env.PIE_PACKAGE_DIR;
|
|
50645
|
-
if (envDir) {
|
|
50646
|
-
if (envDir === "~") return homedir2();
|
|
50647
|
-
if (envDir.startsWith("~/")) return homedir2() + envDir.slice(1);
|
|
50648
|
-
return envDir;
|
|
50649
|
-
}
|
|
50650
|
-
let dir = __dirname;
|
|
50651
|
-
while (dir !== dirname2(dir)) {
|
|
50652
|
-
if (existsSync(join2(dir, "package.json"))) {
|
|
50653
|
-
return dir;
|
|
50654
|
-
}
|
|
50655
|
-
dir = dirname2(dir);
|
|
50656
|
-
}
|
|
50657
|
-
return __dirname;
|
|
50658
|
-
}
|
|
50659
|
-
function getThemesDir() {
|
|
50660
|
-
const packageDir = getPackageDir();
|
|
50661
|
-
const srcOrDist = existsSync(join2(packageDir, "src")) ? "src" : "dist";
|
|
50662
|
-
return join2(packageDir, srcOrDist, "theme");
|
|
50663
|
-
}
|
|
50664
|
-
function getBuiltinDir() {
|
|
50665
|
-
const packageDir = getPackageDir();
|
|
50666
|
-
const distBuiltinDir = join2(packageDir, "dist", "builtin");
|
|
50667
|
-
if (existsSync(distBuiltinDir)) {
|
|
50668
|
-
return distBuiltinDir;
|
|
50669
|
-
}
|
|
50670
|
-
return join2(packageDir, "builtin");
|
|
50671
|
-
}
|
|
50672
|
-
function getPackageJsonPath() {
|
|
50673
|
-
return join2(getPackageDir(), "package.json");
|
|
50674
|
-
}
|
|
50675
|
-
var pkg = JSON.parse(readFileSync(getPackageJsonPath(), "utf-8"));
|
|
50676
|
-
var CONFIG_DIR_NAME = ".pie";
|
|
50677
|
-
var VERSION = pkg.version;
|
|
50678
|
-
var ENV_AGENT_DIR = "PIE_CODING_AGENT_DIR";
|
|
50679
|
-
function getConfigDir() {
|
|
50680
|
-
const envDir = process.env[ENV_AGENT_DIR];
|
|
50681
|
-
if (envDir) {
|
|
50682
|
-
if (envDir === "~") return homedir2();
|
|
50683
|
-
if (envDir.startsWith("~/")) return homedir2() + envDir.slice(1);
|
|
50684
|
-
return envDir;
|
|
50685
|
-
}
|
|
50686
|
-
return join2(homedir2(), CONFIG_DIR_NAME);
|
|
50687
|
-
}
|
|
50688
|
-
function getAgentDir() {
|
|
50689
|
-
return getConfigDir();
|
|
50690
|
-
}
|
|
50691
|
-
function getCustomThemesDir() {
|
|
50692
|
-
return join2(getConfigDir(), "themes");
|
|
50693
|
-
}
|
|
50694
|
-
function getSettingsPath() {
|
|
50695
|
-
return join2(getConfigDir(), "settings.json");
|
|
50696
|
-
}
|
|
50697
|
-
function getSessionsDir() {
|
|
50698
|
-
return join2(getConfigDir(), "sessions");
|
|
50699
|
-
}
|
|
50700
|
-
function getLogsDir() {
|
|
50701
|
-
return join2(getConfigDir(), "logs");
|
|
50702
|
-
}
|
|
50703
|
-
function getRuntimeLogPath() {
|
|
50704
|
-
return join2(getLogsDir(), "pie-cli.log");
|
|
50705
|
-
}
|
|
50706
|
-
function migrateConfigFromAgentDir() {
|
|
50707
|
-
const oldAgentDir = join2(homedir2(), CONFIG_DIR_NAME, "agent");
|
|
50708
|
-
const newConfigDir = getConfigDir();
|
|
50709
|
-
if (!existsSync(oldAgentDir)) {
|
|
50710
|
-
return;
|
|
50711
|
-
}
|
|
50712
|
-
if (!existsSync(newConfigDir)) {
|
|
50713
|
-
mkdirSync2(newConfigDir, { recursive: true });
|
|
50714
|
-
}
|
|
50715
|
-
const filesToMigrate = [
|
|
50716
|
-
"keybindings.json",
|
|
50717
|
-
"settings.json",
|
|
50718
|
-
"pie-debug.log"
|
|
50719
|
-
];
|
|
50720
|
-
for (const file of filesToMigrate) {
|
|
50721
|
-
const oldPath = join2(oldAgentDir, file);
|
|
50722
|
-
const newPath = file === "pie-debug.log" ? getRuntimeLogPath() : join2(newConfigDir, file);
|
|
50723
|
-
if (existsSync(oldPath) && !existsSync(newPath)) {
|
|
50724
|
-
try {
|
|
50725
|
-
if (file === "pie-debug.log") {
|
|
50726
|
-
mkdirSync2(getLogsDir(), { recursive: true });
|
|
50727
|
-
}
|
|
50728
|
-
renameSync(oldPath, newPath);
|
|
50729
|
-
console.log(`[Config] Migrated ${file} to ${newPath}`);
|
|
50730
|
-
} catch (e) {
|
|
50731
|
-
}
|
|
50732
|
-
}
|
|
50733
|
-
}
|
|
50734
|
-
const oldThemesDir = join2(oldAgentDir, "themes");
|
|
50735
|
-
const newThemesDir = getCustomThemesDir();
|
|
50736
|
-
if (existsSync(oldThemesDir) && !existsSync(newThemesDir)) {
|
|
50737
|
-
try {
|
|
50738
|
-
renameSync(oldThemesDir, newThemesDir);
|
|
50739
|
-
console.log(`[Config] Migrated themes to ${newThemesDir}`);
|
|
50740
|
-
} catch (e) {
|
|
50741
|
-
}
|
|
50742
|
-
}
|
|
50743
|
-
}
|
|
50744
|
-
|
|
50745
|
-
// src/keybindings.ts
|
|
50646
|
+
import { existsSync, readFileSync } from "fs";
|
|
50647
|
+
import { join as join2 } from "path";
|
|
50746
50648
|
var DEFAULT_APP_KEYBINDINGS = {
|
|
50747
50649
|
interrupt: "escape",
|
|
50748
50650
|
clear: "ctrl+c",
|
|
@@ -50804,7 +50706,7 @@ var KeybindingsManager = class _KeybindingsManager {
|
|
|
50804
50706
|
* Create from config file and set up editor keybindings.
|
|
50805
50707
|
*/
|
|
50806
50708
|
static create(agentDir = getAgentDir()) {
|
|
50807
|
-
const configPath =
|
|
50709
|
+
const configPath = join2(agentDir, "keybindings.json");
|
|
50808
50710
|
const config = _KeybindingsManager.loadFromFile(configPath);
|
|
50809
50711
|
const manager = new _KeybindingsManager(config);
|
|
50810
50712
|
const editorConfig = {};
|
|
@@ -50823,9 +50725,9 @@ var KeybindingsManager = class _KeybindingsManager {
|
|
|
50823
50725
|
return new _KeybindingsManager(config);
|
|
50824
50726
|
}
|
|
50825
50727
|
static loadFromFile(path26) {
|
|
50826
|
-
if (!
|
|
50728
|
+
if (!existsSync(path26)) return {};
|
|
50827
50729
|
try {
|
|
50828
|
-
return JSON.parse(
|
|
50730
|
+
return JSON.parse(readFileSync(path26, "utf-8"));
|
|
50829
50731
|
} catch {
|
|
50830
50732
|
return {};
|
|
50831
50733
|
}
|
|
@@ -50876,21 +50778,70 @@ var KeybindingsManager = class _KeybindingsManager {
|
|
|
50876
50778
|
// src/project-knowledge.ts
|
|
50877
50779
|
import fs3 from "node:fs";
|
|
50878
50780
|
import path2 from "node:path";
|
|
50879
|
-
function
|
|
50880
|
-
const
|
|
50881
|
-
|
|
50882
|
-
|
|
50883
|
-
|
|
50884
|
-
|
|
50885
|
-
|
|
50886
|
-
|
|
50887
|
-
|
|
50781
|
+
function collectAncestorAgentsFiles(cwd) {
|
|
50782
|
+
const resolvedCwd = path2.resolve(cwd || process.cwd());
|
|
50783
|
+
const projectRoot = resolveCliProjectRoot(resolvedCwd);
|
|
50784
|
+
const candidates = [];
|
|
50785
|
+
let current = resolvedCwd;
|
|
50786
|
+
while (true) {
|
|
50787
|
+
candidates.unshift(path2.join(current, AGENTS_CONTEXT_FILE_NAME));
|
|
50788
|
+
if (current === projectRoot) {
|
|
50789
|
+
break;
|
|
50790
|
+
}
|
|
50791
|
+
const parent = path2.dirname(current);
|
|
50792
|
+
if (parent === current) {
|
|
50793
|
+
break;
|
|
50794
|
+
}
|
|
50795
|
+
current = parent;
|
|
50796
|
+
}
|
|
50797
|
+
const files = [];
|
|
50798
|
+
for (const candidate of candidates) {
|
|
50799
|
+
if (!fs3.existsSync(candidate)) {
|
|
50800
|
+
continue;
|
|
50801
|
+
}
|
|
50802
|
+
try {
|
|
50803
|
+
files.push({
|
|
50804
|
+
path: path2.relative(resolvedCwd, candidate) || AGENTS_CONTEXT_FILE_NAME,
|
|
50805
|
+
content: fs3.readFileSync(candidate, "utf-8")
|
|
50806
|
+
});
|
|
50807
|
+
} catch {
|
|
50808
|
+
}
|
|
50809
|
+
}
|
|
50810
|
+
return files;
|
|
50811
|
+
}
|
|
50812
|
+
function buildCliProjectContextSection(cwd) {
|
|
50813
|
+
return buildProjectContextSection(collectAncestorAgentsFiles(cwd));
|
|
50814
|
+
}
|
|
50815
|
+
|
|
50816
|
+
// src/file-access-context.ts
|
|
50817
|
+
import * as path3 from "node:path";
|
|
50818
|
+
function uniqueNormalizedPaths(paths) {
|
|
50819
|
+
const seen = /* @__PURE__ */ new Set();
|
|
50820
|
+
const result = [];
|
|
50821
|
+
for (const entry of paths) {
|
|
50822
|
+
const trimmed = String(entry || "").trim();
|
|
50823
|
+
if (!trimmed) continue;
|
|
50824
|
+
const normalized = path3.normalize(trimmed);
|
|
50825
|
+
if (seen.has(normalized)) continue;
|
|
50826
|
+
seen.add(normalized);
|
|
50827
|
+
result.push(normalized);
|
|
50888
50828
|
}
|
|
50829
|
+
return result;
|
|
50830
|
+
}
|
|
50831
|
+
function buildCliFileAccessOptions(params) {
|
|
50832
|
+
return {
|
|
50833
|
+
accessRoots: uniqueNormalizedPaths([
|
|
50834
|
+
resolveCliProjectRoot(params.cwd),
|
|
50835
|
+
params.configDir,
|
|
50836
|
+
...params.skills.map((skill) => skill.baseDir)
|
|
50837
|
+
]),
|
|
50838
|
+
allowlistedDirs: params.allowlistedDirs
|
|
50839
|
+
};
|
|
50889
50840
|
}
|
|
50890
50841
|
|
|
50891
50842
|
// src/theme/theme.ts
|
|
50892
50843
|
import * as fs4 from "node:fs";
|
|
50893
|
-
import * as
|
|
50844
|
+
import * as path4 from "node:path";
|
|
50894
50845
|
|
|
50895
50846
|
// ../../node_modules/@sinclair/typebox/build/esm/compiler/compiler.mjs
|
|
50896
50847
|
var TypeCheck = class {
|
|
@@ -51777,8 +51728,8 @@ var BUILTIN_THEMES;
|
|
|
51777
51728
|
function getBuiltinThemes() {
|
|
51778
51729
|
if (!BUILTIN_THEMES) {
|
|
51779
51730
|
const themesDir = getThemesDir();
|
|
51780
|
-
const darkPath =
|
|
51781
|
-
const lightPath =
|
|
51731
|
+
const darkPath = path4.join(themesDir, "dark.json");
|
|
51732
|
+
const lightPath = path4.join(themesDir, "light.json");
|
|
51782
51733
|
BUILTIN_THEMES = {
|
|
51783
51734
|
dark: JSON.parse(fs4.readFileSync(darkPath, "utf-8")),
|
|
51784
51735
|
light: JSON.parse(fs4.readFileSync(lightPath, "utf-8"))
|
|
@@ -51858,7 +51809,7 @@ function loadThemeJson(name) {
|
|
|
51858
51809
|
throw new Error(`Theme "${name}" does not have a source path for export`);
|
|
51859
51810
|
}
|
|
51860
51811
|
const customThemesDir = getCustomThemesDir();
|
|
51861
|
-
const themePath =
|
|
51812
|
+
const themePath = path4.join(customThemesDir, `${name}.json`);
|
|
51862
51813
|
if (!fs4.existsSync(themePath)) {
|
|
51863
51814
|
throw new Error(`Theme not found: ${name}`);
|
|
51864
51815
|
}
|
|
@@ -51975,7 +51926,7 @@ function startThemeWatcher() {
|
|
|
51975
51926
|
return;
|
|
51976
51927
|
}
|
|
51977
51928
|
const customThemesDir = getCustomThemesDir();
|
|
51978
|
-
const themeFile =
|
|
51929
|
+
const themeFile = path4.join(customThemesDir, `${currentThemeName}.json`);
|
|
51979
51930
|
if (!fs4.existsSync(themeFile)) {
|
|
51980
51931
|
return;
|
|
51981
51932
|
}
|
|
@@ -52165,36 +52116,7 @@ function getEditorTheme() {
|
|
|
52165
52116
|
|
|
52166
52117
|
// src/skills/loader.ts
|
|
52167
52118
|
import * as fs5 from "fs";
|
|
52168
|
-
import * as
|
|
52169
|
-
function inferResourceKind(resourcePath) {
|
|
52170
|
-
const lower = resourcePath.toLowerCase();
|
|
52171
|
-
if (lower.endsWith(".md")) return "document";
|
|
52172
|
-
if (lower.endsWith(".js") || lower.endsWith(".mjs") || lower.endsWith(".sh") || lower.endsWith(".py")) return "script";
|
|
52173
|
-
return void 0;
|
|
52174
|
-
}
|
|
52175
|
-
function extractResourceRefs(content) {
|
|
52176
|
-
const refs = /* @__PURE__ */ new Map();
|
|
52177
|
-
const patterns = [
|
|
52178
|
-
/`((?:references|scripts|assets|examples)\/[^`\n]+)`/g,
|
|
52179
|
-
/\b((?:references|scripts|assets|examples)\/[A-Za-z0-9._/-]+)/g,
|
|
52180
|
-
/`(\.?\/[A-Za-z0-9._/-]+\.[A-Za-z0-9]+)`/g
|
|
52181
|
-
];
|
|
52182
|
-
for (const pattern of patterns) {
|
|
52183
|
-
for (const match of content.matchAll(pattern)) {
|
|
52184
|
-
const rawPath = String(match[1] || "").trim().replace(/\\/g, "/");
|
|
52185
|
-
if (!rawPath) continue;
|
|
52186
|
-
const normalizedPath = rawPath.replace(/^\.\/+/, "");
|
|
52187
|
-
if (!normalizedPath || normalizedPath.startsWith("/") || normalizedPath.includes("..")) continue;
|
|
52188
|
-
if (!refs.has(normalizedPath)) {
|
|
52189
|
-
refs.set(normalizedPath, {
|
|
52190
|
-
path: normalizedPath,
|
|
52191
|
-
kind: inferResourceKind(normalizedPath)
|
|
52192
|
-
});
|
|
52193
|
-
}
|
|
52194
|
-
}
|
|
52195
|
-
}
|
|
52196
|
-
return Array.from(refs.values());
|
|
52197
|
-
}
|
|
52119
|
+
import * as path5 from "path";
|
|
52198
52120
|
function parseSkillDescription(content) {
|
|
52199
52121
|
const frontmatterMatch = content.match(/^---\n[\s\S]*?description:\s*["']?(.+?)["']?(?:\n|$)/m);
|
|
52200
52122
|
if (frontmatterMatch) return frontmatterMatch[1].trim();
|
|
@@ -52218,9 +52140,9 @@ function loadSkillsFromDir(dir, source) {
|
|
|
52218
52140
|
const entries = fs5.readdirSync(dir, { withFileTypes: true });
|
|
52219
52141
|
for (const entry of entries) {
|
|
52220
52142
|
if (entry.name.startsWith(".")) continue;
|
|
52221
|
-
const fullPath =
|
|
52143
|
+
const fullPath = path5.join(dir, entry.name);
|
|
52222
52144
|
if (entry.isDirectory()) {
|
|
52223
|
-
const skillMdPath =
|
|
52145
|
+
const skillMdPath = path5.join(fullPath, "SKILL.md");
|
|
52224
52146
|
if (fs5.existsSync(skillMdPath)) {
|
|
52225
52147
|
try {
|
|
52226
52148
|
const content = fs5.readFileSync(skillMdPath, "utf-8");
|
|
@@ -52231,8 +52153,7 @@ function loadSkillsFromDir(dir, source) {
|
|
|
52231
52153
|
content,
|
|
52232
52154
|
filePath: skillMdPath,
|
|
52233
52155
|
source,
|
|
52234
|
-
baseDir: fullPath
|
|
52235
|
-
resourceRefs: extractResourceRefs(content)
|
|
52156
|
+
baseDir: fullPath
|
|
52236
52157
|
});
|
|
52237
52158
|
} catch (e) {
|
|
52238
52159
|
diagnostics.push({
|
|
@@ -52253,8 +52174,7 @@ function loadSkillsFromDir(dir, source) {
|
|
|
52253
52174
|
content,
|
|
52254
52175
|
filePath: fullPath,
|
|
52255
52176
|
source,
|
|
52256
|
-
baseDir: dir
|
|
52257
|
-
resourceRefs: extractResourceRefs(content)
|
|
52177
|
+
baseDir: dir
|
|
52258
52178
|
});
|
|
52259
52179
|
} catch (e) {
|
|
52260
52180
|
diagnostics.push({
|
|
@@ -52441,84 +52361,8 @@ function validateSkillName(name) {
|
|
|
52441
52361
|
return { valid: true };
|
|
52442
52362
|
}
|
|
52443
52363
|
|
|
52444
|
-
// src/skills/runtime.ts
|
|
52445
|
-
import * as fs6 from "node:fs";
|
|
52446
|
-
import * as path5 from "node:path";
|
|
52447
|
-
function resolveSkill(skills, name) {
|
|
52448
|
-
return skills.find((entry) => entry.name === name) ?? null;
|
|
52449
|
-
}
|
|
52450
|
-
function resolveSkillResource(skill, resourcePath) {
|
|
52451
|
-
const trimmed = String(resourcePath || "").trim().replace(/\\/g, "/");
|
|
52452
|
-
if (!trimmed || trimmed.startsWith("/") || /^[A-Za-z]:\//.test(trimmed)) {
|
|
52453
|
-
return null;
|
|
52454
|
-
}
|
|
52455
|
-
const segments = trimmed.split("/").filter(Boolean);
|
|
52456
|
-
if (segments.some((segment) => segment === "..")) {
|
|
52457
|
-
return null;
|
|
52458
|
-
}
|
|
52459
|
-
const absolutePath = path5.resolve(skill.baseDir, ...segments);
|
|
52460
|
-
const relativePath = path5.relative(skill.baseDir, absolutePath).replace(/\\/g, "/");
|
|
52461
|
-
if (relativePath.startsWith("../") || relativePath === "..") {
|
|
52462
|
-
return null;
|
|
52463
|
-
}
|
|
52464
|
-
return absolutePath;
|
|
52465
|
-
}
|
|
52466
|
-
function createCliReadSkillTool(skills) {
|
|
52467
|
-
return createReadSkillCapability({
|
|
52468
|
-
resolveSkill(name) {
|
|
52469
|
-
const skill = resolveSkill(skills, name);
|
|
52470
|
-
if (!skill) {
|
|
52471
|
-
return null;
|
|
52472
|
-
}
|
|
52473
|
-
return {
|
|
52474
|
-
name: skill.name,
|
|
52475
|
-
content: skill.content,
|
|
52476
|
-
resources: skill.resourceRefs
|
|
52477
|
-
};
|
|
52478
|
-
}
|
|
52479
|
-
}).tool;
|
|
52480
|
-
}
|
|
52481
|
-
function createCliReadResourceTool(skills) {
|
|
52482
|
-
return createReadResourceCapability({
|
|
52483
|
-
resolveResource(owner, resourcePath) {
|
|
52484
|
-
const skill = resolveSkill(skills, owner);
|
|
52485
|
-
if (!skill) {
|
|
52486
|
-
return null;
|
|
52487
|
-
}
|
|
52488
|
-
const absolutePath = resolveSkillResource(skill, resourcePath);
|
|
52489
|
-
if (!absolutePath || !fs6.existsSync(absolutePath) || !fs6.statSync(absolutePath).isFile()) {
|
|
52490
|
-
return null;
|
|
52491
|
-
}
|
|
52492
|
-
return {
|
|
52493
|
-
owner: skill.name,
|
|
52494
|
-
path: resourcePath.replace(/\\/g, "/").replace(/^\.\/+/, ""),
|
|
52495
|
-
content: fs6.readFileSync(absolutePath, "utf8")
|
|
52496
|
-
};
|
|
52497
|
-
}
|
|
52498
|
-
}).tool;
|
|
52499
|
-
}
|
|
52500
|
-
function createCliResolveResourceTool(skills) {
|
|
52501
|
-
return createResolveResourceCapability({
|
|
52502
|
-
resolveResource(owner, resourcePath) {
|
|
52503
|
-
const skill = resolveSkill(skills, owner);
|
|
52504
|
-
if (!skill) {
|
|
52505
|
-
return null;
|
|
52506
|
-
}
|
|
52507
|
-
const absolutePath = resolveSkillResource(skill, resourcePath);
|
|
52508
|
-
if (!absolutePath || !fs6.existsSync(absolutePath) || !fs6.statSync(absolutePath).isFile()) {
|
|
52509
|
-
return null;
|
|
52510
|
-
}
|
|
52511
|
-
return {
|
|
52512
|
-
owner: skill.name,
|
|
52513
|
-
path: resourcePath.replace(/\\/g, "/").replace(/^\.\/+/, ""),
|
|
52514
|
-
resolvedPath: absolutePath
|
|
52515
|
-
};
|
|
52516
|
-
}
|
|
52517
|
-
}).tool;
|
|
52518
|
-
}
|
|
52519
|
-
|
|
52520
52364
|
// src/debug/file-logger.ts
|
|
52521
|
-
import * as
|
|
52365
|
+
import * as fs6 from "fs";
|
|
52522
52366
|
import * as path6 from "path";
|
|
52523
52367
|
var FileLogger = class {
|
|
52524
52368
|
config = {
|
|
@@ -52560,8 +52404,8 @@ var FileLogger = class {
|
|
|
52560
52404
|
this.config.filePath = filePath;
|
|
52561
52405
|
}
|
|
52562
52406
|
const dir = path6.dirname(this.config.filePath);
|
|
52563
|
-
if (!
|
|
52564
|
-
|
|
52407
|
+
if (!fs6.existsSync(dir)) {
|
|
52408
|
+
fs6.mkdirSync(dir, { recursive: true });
|
|
52565
52409
|
}
|
|
52566
52410
|
this.log("file-logger", `File logging enabled: ${this.config.filePath}`);
|
|
52567
52411
|
}
|
|
@@ -52599,8 +52443,8 @@ var FileLogger = class {
|
|
|
52599
52443
|
this.buffer = [];
|
|
52600
52444
|
this.bufferIndex = 0;
|
|
52601
52445
|
this.totalLines = 0;
|
|
52602
|
-
if (
|
|
52603
|
-
|
|
52446
|
+
if (fs6.existsSync(this.config.filePath)) {
|
|
52447
|
+
fs6.writeFileSync(this.config.filePath, "");
|
|
52604
52448
|
}
|
|
52605
52449
|
}
|
|
52606
52450
|
/**
|
|
@@ -52641,8 +52485,8 @@ var FileLogger = class {
|
|
|
52641
52485
|
*/
|
|
52642
52486
|
getStats() {
|
|
52643
52487
|
let size = 0;
|
|
52644
|
-
if (
|
|
52645
|
-
const stats =
|
|
52488
|
+
if (fs6.existsSync(this.config.filePath)) {
|
|
52489
|
+
const stats = fs6.statSync(this.config.filePath);
|
|
52646
52490
|
size = stats.size;
|
|
52647
52491
|
}
|
|
52648
52492
|
return {
|
|
@@ -52656,11 +52500,11 @@ var FileLogger = class {
|
|
|
52656
52500
|
* Read last N lines from file (fallback when buffer is not enough)
|
|
52657
52501
|
*/
|
|
52658
52502
|
readLastLines(count) {
|
|
52659
|
-
if (!
|
|
52503
|
+
if (!fs6.existsSync(this.config.filePath)) {
|
|
52660
52504
|
return [];
|
|
52661
52505
|
}
|
|
52662
52506
|
try {
|
|
52663
|
-
const content =
|
|
52507
|
+
const content = fs6.readFileSync(this.config.filePath, "utf-8");
|
|
52664
52508
|
const lines = content.split("\n").filter(Boolean);
|
|
52665
52509
|
return lines.slice(-count);
|
|
52666
52510
|
} catch {
|
|
@@ -52678,10 +52522,10 @@ var FileLogger = class {
|
|
|
52678
52522
|
const entry = this.formatEntry(level, module, message, data);
|
|
52679
52523
|
try {
|
|
52680
52524
|
const dir = path6.dirname(this.config.filePath);
|
|
52681
|
-
if (!
|
|
52682
|
-
|
|
52525
|
+
if (!fs6.existsSync(dir)) {
|
|
52526
|
+
fs6.mkdirSync(dir, { recursive: true });
|
|
52683
52527
|
}
|
|
52684
|
-
|
|
52528
|
+
fs6.appendFileSync(this.config.filePath, entry + "\n");
|
|
52685
52529
|
} catch {
|
|
52686
52530
|
return;
|
|
52687
52531
|
}
|
|
@@ -52770,7 +52614,7 @@ function flushEarlyLogs() {
|
|
|
52770
52614
|
|
|
52771
52615
|
// src/capabilities/read-file-understanding.ts
|
|
52772
52616
|
import * as path15 from "node:path";
|
|
52773
|
-
import * as
|
|
52617
|
+
import * as fs14 from "node:fs/promises";
|
|
52774
52618
|
|
|
52775
52619
|
// src/core/provider-capabilities.ts
|
|
52776
52620
|
var PLATFORM_DISPLAY_NAMES = {
|
|
@@ -52796,7 +52640,7 @@ function getProviderDisplayName(platform2) {
|
|
|
52796
52640
|
}
|
|
52797
52641
|
|
|
52798
52642
|
// src/files/adapters/kimi-adapter.ts
|
|
52799
|
-
import * as
|
|
52643
|
+
import * as fs7 from "node:fs";
|
|
52800
52644
|
import * as path7 from "node:path";
|
|
52801
52645
|
|
|
52802
52646
|
// src/files/errors.ts
|
|
@@ -52937,14 +52781,14 @@ var KimiFileAdapter = class {
|
|
|
52937
52781
|
const fileName = options.sourceName || path7.basename(filePath);
|
|
52938
52782
|
const mimeType = options.mimeType || this.guessMimeType(fileName);
|
|
52939
52783
|
const purpose = this.detectPurpose(filePath, options.purpose, mimeType);
|
|
52940
|
-
const stats =
|
|
52784
|
+
const stats = fs7.statSync(filePath);
|
|
52941
52785
|
if (stats.size > this.capabilities.maxFileSize) {
|
|
52942
52786
|
throw new FileManagerError(
|
|
52943
52787
|
"FILE_TOO_LARGE" /* FILE_TOO_LARGE */,
|
|
52944
52788
|
`File size ${(stats.size / 1024 / 1024).toFixed(1)}MB exceeds Kimi limit of 100MB`
|
|
52945
52789
|
);
|
|
52946
52790
|
}
|
|
52947
|
-
const fileBuffer =
|
|
52791
|
+
const fileBuffer = fs7.readFileSync(filePath);
|
|
52948
52792
|
const file = new File([fileBuffer], fileName, { type: mimeType });
|
|
52949
52793
|
const formData = new FormData();
|
|
52950
52794
|
formData.append("file", file);
|
|
@@ -53158,7 +53002,7 @@ var KimiFileAdapter = class {
|
|
|
53158
53002
|
};
|
|
53159
53003
|
|
|
53160
53004
|
// src/files/adapters/gemini-adapter.ts
|
|
53161
|
-
import * as
|
|
53005
|
+
import * as fs8 from "node:fs";
|
|
53162
53006
|
import * as path8 from "node:path";
|
|
53163
53007
|
import { Readable } from "node:stream";
|
|
53164
53008
|
var GeminiFileAdapter = class {
|
|
@@ -53216,7 +53060,7 @@ var GeminiFileAdapter = class {
|
|
|
53216
53060
|
// Upload
|
|
53217
53061
|
// ============================================================================
|
|
53218
53062
|
async upload(filePath, options = {}) {
|
|
53219
|
-
const stats =
|
|
53063
|
+
const stats = fs8.statSync(filePath);
|
|
53220
53064
|
if (stats.size > this.capabilities.maxFileSize) {
|
|
53221
53065
|
throw new FileManagerError(
|
|
53222
53066
|
"FILE_TOO_LARGE" /* FILE_TOO_LARGE */,
|
|
@@ -53255,7 +53099,7 @@ var GeminiFileAdapter = class {
|
|
|
53255
53099
|
"No upload URL received"
|
|
53256
53100
|
);
|
|
53257
53101
|
}
|
|
53258
|
-
const fileStream = Readable.toWeb(
|
|
53102
|
+
const fileStream = Readable.toWeb(fs8.createReadStream(filePath));
|
|
53259
53103
|
const uploadResponse = await fetch(uploadUrl, {
|
|
53260
53104
|
method: "POST",
|
|
53261
53105
|
headers: {
|
|
@@ -53459,7 +53303,7 @@ var GeminiFileAdapter = class {
|
|
|
53459
53303
|
};
|
|
53460
53304
|
|
|
53461
53305
|
// src/files/adapters/openai-compatible-files-adapter.ts
|
|
53462
|
-
import * as
|
|
53306
|
+
import * as fs9 from "node:fs";
|
|
53463
53307
|
import * as path9 from "node:path";
|
|
53464
53308
|
var OpenAICompatibleFilesAdapter = class {
|
|
53465
53309
|
constructor(apiKey, baseUrl, extraHeaders = {}) {
|
|
@@ -53488,14 +53332,14 @@ var OpenAICompatibleFilesAdapter = class {
|
|
|
53488
53332
|
async upload(filePath, options = {}) {
|
|
53489
53333
|
const fileName = options.sourceName || path9.basename(filePath);
|
|
53490
53334
|
const mimeType = options.mimeType || guessMimeType(fileName);
|
|
53491
|
-
const stats =
|
|
53335
|
+
const stats = fs9.statSync(filePath);
|
|
53492
53336
|
if (stats.size > this.capabilities.maxFileSize) {
|
|
53493
53337
|
throw new FileManagerError(
|
|
53494
53338
|
"FILE_TOO_LARGE" /* FILE_TOO_LARGE */,
|
|
53495
53339
|
`File size ${(stats.size / 1024 / 1024).toFixed(1)}MB exceeds OpenAI-compatible Files limit of ${this.capabilities.maxFileSize / 1024 / 1024}MB`
|
|
53496
53340
|
);
|
|
53497
53341
|
}
|
|
53498
|
-
const file = new File([
|
|
53342
|
+
const file = new File([fs9.readFileSync(filePath)], fileName, { type: mimeType });
|
|
53499
53343
|
const formData = new FormData();
|
|
53500
53344
|
formData.append("file", file);
|
|
53501
53345
|
formData.append("purpose", options.purpose && options.purpose !== "auto" ? options.purpose : "file-extract");
|
|
@@ -53628,12 +53472,12 @@ function guessMimeType(filename) {
|
|
|
53628
53472
|
}
|
|
53629
53473
|
|
|
53630
53474
|
// src/files/file-manager.ts
|
|
53631
|
-
import * as
|
|
53475
|
+
import * as fs13 from "node:fs";
|
|
53632
53476
|
import * as path14 from "node:path";
|
|
53633
53477
|
import * as crypto2 from "node:crypto";
|
|
53634
53478
|
|
|
53635
53479
|
// src/files/file-cache.ts
|
|
53636
|
-
import * as
|
|
53480
|
+
import * as fs10 from "node:fs";
|
|
53637
53481
|
import * as path11 from "node:path";
|
|
53638
53482
|
import * as crypto from "node:crypto";
|
|
53639
53483
|
|
|
@@ -53780,22 +53624,22 @@ var FileCache = class _FileCache {
|
|
|
53780
53624
|
// Directory Management
|
|
53781
53625
|
// ============================================================================
|
|
53782
53626
|
ensureDirectories() {
|
|
53783
|
-
if (!
|
|
53784
|
-
|
|
53627
|
+
if (!fs10.existsSync(this.baseDir)) {
|
|
53628
|
+
fs10.mkdirSync(this.baseDir, { recursive: true });
|
|
53785
53629
|
}
|
|
53786
|
-
if (!
|
|
53787
|
-
|
|
53630
|
+
if (!fs10.existsSync(this.dataDir)) {
|
|
53631
|
+
fs10.mkdirSync(this.dataDir, { recursive: true });
|
|
53788
53632
|
}
|
|
53789
53633
|
}
|
|
53790
53634
|
// ============================================================================
|
|
53791
53635
|
// Index Management
|
|
53792
53636
|
// ============================================================================
|
|
53793
53637
|
loadIndex() {
|
|
53794
|
-
if (!
|
|
53638
|
+
if (!fs10.existsSync(this.indexPath)) {
|
|
53795
53639
|
return { version: CACHE_VERSION, files: {}, pathHints: {} };
|
|
53796
53640
|
}
|
|
53797
53641
|
try {
|
|
53798
|
-
const data = JSON.parse(
|
|
53642
|
+
const data = JSON.parse(fs10.readFileSync(this.indexPath, "utf-8"));
|
|
53799
53643
|
if (data.version !== CACHE_VERSION) {
|
|
53800
53644
|
cacheLogger.warn(`Index version mismatch: ${data.version} vs ${CACHE_VERSION}`);
|
|
53801
53645
|
}
|
|
@@ -53811,7 +53655,7 @@ var FileCache = class _FileCache {
|
|
|
53811
53655
|
}
|
|
53812
53656
|
saveIndex() {
|
|
53813
53657
|
try {
|
|
53814
|
-
|
|
53658
|
+
fs10.writeFileSync(this.indexPath, JSON.stringify(this.index, null, 2));
|
|
53815
53659
|
} catch (err) {
|
|
53816
53660
|
cacheLogger.error(" Failed to save index:", err);
|
|
53817
53661
|
throw err;
|
|
@@ -53821,11 +53665,11 @@ var FileCache = class _FileCache {
|
|
|
53821
53665
|
// Hash Computation
|
|
53822
53666
|
// ============================================================================
|
|
53823
53667
|
async computeHash(filePath) {
|
|
53824
|
-
return new Promise((
|
|
53668
|
+
return new Promise((resolve4, reject) => {
|
|
53825
53669
|
const hash = crypto.createHash("sha256");
|
|
53826
|
-
const stream =
|
|
53670
|
+
const stream = fs10.createReadStream(filePath);
|
|
53827
53671
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
53828
|
-
stream.on("end", () =>
|
|
53672
|
+
stream.on("end", () => resolve4(hash.digest("hex")));
|
|
53829
53673
|
stream.on("error", reject);
|
|
53830
53674
|
});
|
|
53831
53675
|
}
|
|
@@ -53838,8 +53682,8 @@ var FileCache = class _FileCache {
|
|
|
53838
53682
|
getStoragePath(hash) {
|
|
53839
53683
|
const subdir = hash.slice(0, 2);
|
|
53840
53684
|
const fullDir = path11.join(this.dataDir, subdir);
|
|
53841
|
-
if (!
|
|
53842
|
-
|
|
53685
|
+
if (!fs10.existsSync(fullDir)) {
|
|
53686
|
+
fs10.mkdirSync(fullDir, { recursive: true });
|
|
53843
53687
|
}
|
|
53844
53688
|
return path11.join(fullDir, hash);
|
|
53845
53689
|
}
|
|
@@ -53851,11 +53695,11 @@ var FileCache = class _FileCache {
|
|
|
53851
53695
|
const hash = await this.computeHash(sourcePath);
|
|
53852
53696
|
const storagePath = this.getStoragePath(hash);
|
|
53853
53697
|
this.rememberPathHint(sourcePath, hash, name);
|
|
53854
|
-
if (
|
|
53698
|
+
if (fs10.existsSync(storagePath)) {
|
|
53855
53699
|
return { hash, localPath: storagePath };
|
|
53856
53700
|
}
|
|
53857
|
-
|
|
53858
|
-
const stat2 =
|
|
53701
|
+
fs10.copyFileSync(sourcePath, storagePath);
|
|
53702
|
+
const stat2 = fs10.statSync(storagePath);
|
|
53859
53703
|
this.index.files[hash] = {
|
|
53860
53704
|
hash,
|
|
53861
53705
|
name,
|
|
@@ -53872,10 +53716,10 @@ var FileCache = class _FileCache {
|
|
|
53872
53716
|
async storeBuffer(data, name, mimeType) {
|
|
53873
53717
|
const hash = this.computeHashSync(data);
|
|
53874
53718
|
const storagePath = this.getStoragePath(hash);
|
|
53875
|
-
if (
|
|
53719
|
+
if (fs10.existsSync(storagePath)) {
|
|
53876
53720
|
return { hash, localPath: storagePath };
|
|
53877
53721
|
}
|
|
53878
|
-
|
|
53722
|
+
fs10.writeFileSync(storagePath, data);
|
|
53879
53723
|
this.index.files[hash] = {
|
|
53880
53724
|
hash,
|
|
53881
53725
|
name,
|
|
@@ -53947,7 +53791,7 @@ var FileCache = class _FileCache {
|
|
|
53947
53791
|
getPathHint(filePath) {
|
|
53948
53792
|
try {
|
|
53949
53793
|
const resolvedPath = this.getResolvedHintPath(filePath);
|
|
53950
|
-
const stat2 =
|
|
53794
|
+
const stat2 = fs10.statSync(resolvedPath);
|
|
53951
53795
|
if (!stat2.isFile()) return void 0;
|
|
53952
53796
|
const normalizedMtimeMs = this.normalizeHintMtimeMs(stat2.mtimeMs);
|
|
53953
53797
|
const key = this.getPathHintKey(resolvedPath);
|
|
@@ -53977,7 +53821,7 @@ var FileCache = class _FileCache {
|
|
|
53977
53821
|
rememberPathHint(filePath, hash, name) {
|
|
53978
53822
|
try {
|
|
53979
53823
|
const resolvedPath = this.getResolvedHintPath(filePath);
|
|
53980
|
-
const stat2 =
|
|
53824
|
+
const stat2 = fs10.statSync(resolvedPath);
|
|
53981
53825
|
if (!stat2.isFile()) return;
|
|
53982
53826
|
const entry = this.index.files[hash];
|
|
53983
53827
|
const normalizedMtimeMs = this.normalizeHintMtimeMs(stat2.mtimeMs);
|
|
@@ -54036,8 +53880,8 @@ var FileCache = class _FileCache {
|
|
|
54036
53880
|
entry = entry || this.index.files[hash];
|
|
54037
53881
|
if (!entry) return;
|
|
54038
53882
|
const localPath = path11.join(this.dataDir, entry.localPath);
|
|
54039
|
-
if (
|
|
54040
|
-
|
|
53883
|
+
if (fs10.existsSync(localPath)) {
|
|
53884
|
+
fs10.unlinkSync(localPath);
|
|
54041
53885
|
}
|
|
54042
53886
|
delete this.index.files[hash];
|
|
54043
53887
|
if (this.index.pathHints) {
|
|
@@ -54052,8 +53896,8 @@ var FileCache = class _FileCache {
|
|
|
54052
53896
|
clear() {
|
|
54053
53897
|
for (const entry of Object.values(this.index.files)) {
|
|
54054
53898
|
const localPath = path11.join(this.dataDir, entry.localPath);
|
|
54055
|
-
if (
|
|
54056
|
-
|
|
53899
|
+
if (fs10.existsSync(localPath)) {
|
|
53900
|
+
fs10.unlinkSync(localPath);
|
|
54057
53901
|
}
|
|
54058
53902
|
}
|
|
54059
53903
|
this.index = { version: CACHE_VERSION, files: {}, pathHints: {} };
|
|
@@ -54141,7 +53985,7 @@ var FileCache = class _FileCache {
|
|
|
54141
53985
|
getResolvedHintPath(filePath) {
|
|
54142
53986
|
const resolvedPath = resolvePath(filePath);
|
|
54143
53987
|
try {
|
|
54144
|
-
return
|
|
53988
|
+
return fs10.realpathSync.native ? fs10.realpathSync.native(resolvedPath) : fs10.realpathSync(resolvedPath);
|
|
54145
53989
|
} catch {
|
|
54146
53990
|
return resolvedPath;
|
|
54147
53991
|
}
|
|
@@ -54149,7 +53993,7 @@ var FileCache = class _FileCache {
|
|
|
54149
53993
|
};
|
|
54150
53994
|
|
|
54151
53995
|
// src/files/session-file-manager.ts
|
|
54152
|
-
import * as
|
|
53996
|
+
import * as fs11 from "node:fs";
|
|
54153
53997
|
import * as path12 from "node:path";
|
|
54154
53998
|
var INITIAL_REFRESH_BACKOFF_MS = 6e4;
|
|
54155
53999
|
var MAX_REFRESH_BACKOFF_MS = 60 * 60 * 1e3;
|
|
@@ -54174,15 +54018,15 @@ var SessionFileManager = class {
|
|
|
54174
54018
|
// Directory Management
|
|
54175
54019
|
// ============================================================================
|
|
54176
54020
|
ensureDirectories() {
|
|
54177
|
-
if (!
|
|
54178
|
-
|
|
54021
|
+
if (!fs11.existsSync(this.sessionsDir)) {
|
|
54022
|
+
fs11.mkdirSync(this.sessionsDir, { recursive: true });
|
|
54179
54023
|
}
|
|
54180
54024
|
}
|
|
54181
54025
|
// ============================================================================
|
|
54182
54026
|
// State Management
|
|
54183
54027
|
// ============================================================================
|
|
54184
54028
|
loadState() {
|
|
54185
|
-
if (!
|
|
54029
|
+
if (!fs11.existsSync(this.statePath)) {
|
|
54186
54030
|
return {
|
|
54187
54031
|
sessionId: this.sessionId,
|
|
54188
54032
|
lastSyncedAt: 0,
|
|
@@ -54190,7 +54034,7 @@ var SessionFileManager = class {
|
|
|
54190
54034
|
};
|
|
54191
54035
|
}
|
|
54192
54036
|
try {
|
|
54193
|
-
return JSON.parse(
|
|
54037
|
+
return JSON.parse(fs11.readFileSync(this.statePath, "utf-8"));
|
|
54194
54038
|
} catch (err) {
|
|
54195
54039
|
sessionLogger.error(" Failed to load state:", err);
|
|
54196
54040
|
return {
|
|
@@ -54203,12 +54047,12 @@ var SessionFileManager = class {
|
|
|
54203
54047
|
saveState() {
|
|
54204
54048
|
try {
|
|
54205
54049
|
if (Object.keys(this.state.files).length === 0) {
|
|
54206
|
-
if (
|
|
54207
|
-
|
|
54050
|
+
if (fs11.existsSync(this.statePath)) {
|
|
54051
|
+
fs11.unlinkSync(this.statePath);
|
|
54208
54052
|
}
|
|
54209
54053
|
return;
|
|
54210
54054
|
}
|
|
54211
|
-
|
|
54055
|
+
fs11.writeFileSync(this.statePath, JSON.stringify(this.state, null, 2));
|
|
54212
54056
|
} catch (err) {
|
|
54213
54057
|
sessionLogger.error(" Failed to save state:", err);
|
|
54214
54058
|
}
|
|
@@ -54354,7 +54198,7 @@ var SessionFileManager = class {
|
|
|
54354
54198
|
return { success: false, coolingDown: true };
|
|
54355
54199
|
}
|
|
54356
54200
|
const localPath = this.fileCache.getLocalPath(entry.hash);
|
|
54357
|
-
if (!localPath || !
|
|
54201
|
+
if (!localPath || !fs11.existsSync(localPath)) {
|
|
54358
54202
|
sessionLogger.warn(`Local file not found for ${fileId}`);
|
|
54359
54203
|
entry.status = "expired";
|
|
54360
54204
|
entry.error = "Local file missing";
|
|
@@ -54505,15 +54349,15 @@ var SessionFileManager = class {
|
|
|
54505
54349
|
// Static Utilities
|
|
54506
54350
|
// ============================================================================
|
|
54507
54351
|
static cleanupOldSessions(sessionsDir, maxAge = 30 * 24 * 60 * 60 * 1e3) {
|
|
54508
|
-
if (!
|
|
54352
|
+
if (!fs11.existsSync(sessionsDir)) return;
|
|
54509
54353
|
const now = Date.now();
|
|
54510
|
-
const files =
|
|
54354
|
+
const files = fs11.readdirSync(sessionsDir);
|
|
54511
54355
|
for (const file of files) {
|
|
54512
54356
|
if (!file.endsWith(".json")) continue;
|
|
54513
54357
|
const filePath = path12.join(sessionsDir, file);
|
|
54514
|
-
const stat2 =
|
|
54358
|
+
const stat2 = fs11.statSync(filePath);
|
|
54515
54359
|
if (now - stat2.mtime.getTime() > maxAge) {
|
|
54516
|
-
|
|
54360
|
+
fs11.unlinkSync(filePath);
|
|
54517
54361
|
sessionLogger.debug(`Cleaned up old session: ${file}`);
|
|
54518
54362
|
}
|
|
54519
54363
|
}
|
|
@@ -54521,7 +54365,7 @@ var SessionFileManager = class {
|
|
|
54521
54365
|
};
|
|
54522
54366
|
|
|
54523
54367
|
// src/files/ffmpeg-processor.ts
|
|
54524
|
-
import * as
|
|
54368
|
+
import * as fs12 from "node:fs";
|
|
54525
54369
|
import * as path13 from "node:path";
|
|
54526
54370
|
import { spawn } from "node:child_process";
|
|
54527
54371
|
var FFmpegProcessor = class {
|
|
@@ -54535,17 +54379,17 @@ var FFmpegProcessor = class {
|
|
|
54535
54379
|
// Detection
|
|
54536
54380
|
// ============================================================================
|
|
54537
54381
|
async checkAvailability() {
|
|
54538
|
-
return new Promise((
|
|
54382
|
+
return new Promise((resolve4) => {
|
|
54539
54383
|
const proc = spawn(this.ffmpegPath, ["-version"]);
|
|
54540
|
-
proc.on("error", () =>
|
|
54541
|
-
proc.on("exit", (code) =>
|
|
54384
|
+
proc.on("error", () => resolve4(false));
|
|
54385
|
+
proc.on("exit", (code) => resolve4(code === 0));
|
|
54542
54386
|
});
|
|
54543
54387
|
}
|
|
54544
54388
|
// ============================================================================
|
|
54545
54389
|
// Video Analysis
|
|
54546
54390
|
// ============================================================================
|
|
54547
54391
|
async analyzeVideo(videoPath) {
|
|
54548
|
-
return new Promise((
|
|
54392
|
+
return new Promise((resolve4, reject) => {
|
|
54549
54393
|
const args = [
|
|
54550
54394
|
"-v",
|
|
54551
54395
|
"error",
|
|
@@ -54574,7 +54418,7 @@ var FFmpegProcessor = class {
|
|
|
54574
54418
|
}
|
|
54575
54419
|
try {
|
|
54576
54420
|
const info = this.parseProbeOutput(stdout, videoPath);
|
|
54577
|
-
|
|
54421
|
+
resolve4(info);
|
|
54578
54422
|
} catch (err) {
|
|
54579
54423
|
reject(err);
|
|
54580
54424
|
}
|
|
@@ -54657,7 +54501,7 @@ var FFmpegProcessor = class {
|
|
|
54657
54501
|
onProgress?.(percent);
|
|
54658
54502
|
}
|
|
54659
54503
|
});
|
|
54660
|
-
const outputStat =
|
|
54504
|
+
const outputStat = fs12.statSync(outputPath);
|
|
54661
54505
|
return {
|
|
54662
54506
|
type: "video",
|
|
54663
54507
|
output: outputPath,
|
|
@@ -54689,7 +54533,7 @@ var FFmpegProcessor = class {
|
|
|
54689
54533
|
async extractKeyframes(inputPath, outputDir, info, opts, onProgress) {
|
|
54690
54534
|
const interval = Math.floor(info.duration / opts.keyframeCount);
|
|
54691
54535
|
const framesDir = path13.join(outputDir, `keyframes_${Date.now()}`);
|
|
54692
|
-
|
|
54536
|
+
fs12.mkdirSync(framesDir, { recursive: true });
|
|
54693
54537
|
const outputPattern = path13.join(framesDir, "frame_%03d.jpg");
|
|
54694
54538
|
const args = [
|
|
54695
54539
|
"-i",
|
|
@@ -54708,10 +54552,10 @@ var FFmpegProcessor = class {
|
|
|
54708
54552
|
onProgress?.(percent);
|
|
54709
54553
|
}
|
|
54710
54554
|
});
|
|
54711
|
-
let frames =
|
|
54555
|
+
let frames = fs12.readdirSync(framesDir).filter((f) => f.endsWith(".jpg")).sort().map((f) => path13.join(framesDir, f));
|
|
54712
54556
|
if (frames.length < opts.keyframeCount / 2) {
|
|
54713
|
-
|
|
54714
|
-
|
|
54557
|
+
fs12.rmSync(framesDir, { recursive: true, force: true });
|
|
54558
|
+
fs12.mkdirSync(framesDir, { recursive: true });
|
|
54715
54559
|
const uniformArgs = [
|
|
54716
54560
|
"-i",
|
|
54717
54561
|
inputPath,
|
|
@@ -54727,10 +54571,10 @@ var FFmpegProcessor = class {
|
|
|
54727
54571
|
onProgress?.(percent);
|
|
54728
54572
|
}
|
|
54729
54573
|
});
|
|
54730
|
-
frames =
|
|
54574
|
+
frames = fs12.readdirSync(framesDir).filter((f) => f.endsWith(".jpg")).sort().map((f) => path13.join(framesDir, f));
|
|
54731
54575
|
}
|
|
54732
54576
|
const totalOutputSize = frames.reduce(
|
|
54733
|
-
(sum, f) => sum +
|
|
54577
|
+
(sum, f) => sum + fs12.statSync(f).size,
|
|
54734
54578
|
0
|
|
54735
54579
|
);
|
|
54736
54580
|
return {
|
|
@@ -54769,7 +54613,7 @@ var FFmpegProcessor = class {
|
|
|
54769
54613
|
// FFmpeg Execution
|
|
54770
54614
|
// ============================================================================
|
|
54771
54615
|
runFFmpeg(args) {
|
|
54772
|
-
return new Promise((
|
|
54616
|
+
return new Promise((resolve4, reject) => {
|
|
54773
54617
|
const proc = spawn(this.ffmpegPath, args);
|
|
54774
54618
|
let stderr = "";
|
|
54775
54619
|
proc.stderr.on("data", (data) => {
|
|
@@ -54784,7 +54628,7 @@ var FFmpegProcessor = class {
|
|
|
54784
54628
|
)
|
|
54785
54629
|
);
|
|
54786
54630
|
} else {
|
|
54787
|
-
|
|
54631
|
+
resolve4();
|
|
54788
54632
|
}
|
|
54789
54633
|
});
|
|
54790
54634
|
proc.on("error", (err) => {
|
|
@@ -54801,7 +54645,7 @@ var FFmpegProcessor = class {
|
|
|
54801
54645
|
// Progress Monitoring (for future use)
|
|
54802
54646
|
// ============================================================================
|
|
54803
54647
|
async runWithProgress(args, onProgress) {
|
|
54804
|
-
return new Promise((
|
|
54648
|
+
return new Promise((resolve4, reject) => {
|
|
54805
54649
|
const progressArgs = [
|
|
54806
54650
|
...args,
|
|
54807
54651
|
"-progress",
|
|
@@ -54831,7 +54675,7 @@ var FFmpegProcessor = class {
|
|
|
54831
54675
|
)
|
|
54832
54676
|
);
|
|
54833
54677
|
} else {
|
|
54834
|
-
|
|
54678
|
+
resolve4();
|
|
54835
54679
|
}
|
|
54836
54680
|
});
|
|
54837
54681
|
});
|
|
@@ -54950,8 +54794,8 @@ var FileManager = class {
|
|
|
54950
54794
|
directoryListingCache = /* @__PURE__ */ new Map();
|
|
54951
54795
|
authFingerprint;
|
|
54952
54796
|
ensureDirectories() {
|
|
54953
|
-
if (!
|
|
54954
|
-
|
|
54797
|
+
if (!fs13.existsSync(this.tempDir)) {
|
|
54798
|
+
fs13.mkdirSync(this.tempDir, { recursive: true });
|
|
54955
54799
|
}
|
|
54956
54800
|
}
|
|
54957
54801
|
// ============================================================================
|
|
@@ -54982,7 +54826,7 @@ var FileManager = class {
|
|
|
54982
54826
|
async stageLocal(filePath, options = {}) {
|
|
54983
54827
|
const resolvedPath = resolvePath(filePath);
|
|
54984
54828
|
const sourceName = options.sourceName || path14.basename(resolvedPath);
|
|
54985
|
-
if (!
|
|
54829
|
+
if (!fs13.existsSync(resolvedPath)) {
|
|
54986
54830
|
throw new FileManagerError(
|
|
54987
54831
|
"LOCAL_FILE_MISSING" /* LOCAL_FILE_MISSING */,
|
|
54988
54832
|
`File not found: ${filePath}`
|
|
@@ -54997,7 +54841,7 @@ var FileManager = class {
|
|
|
54997
54841
|
this.fileCache.rememberPathHint(resolvedPath, hash, sourceName);
|
|
54998
54842
|
this.invalidateDirectoryListingCacheForPath(resolvedPath);
|
|
54999
54843
|
const entry = this.fileCache.getByHash(hash);
|
|
55000
|
-
const size = entry?.size ??
|
|
54844
|
+
const size = entry?.size ?? fs13.statSync(resolvedPath).size;
|
|
55001
54845
|
return {
|
|
55002
54846
|
success: true,
|
|
55003
54847
|
hash,
|
|
@@ -55012,7 +54856,7 @@ var FileManager = class {
|
|
|
55012
54856
|
async upload(filePath, options = {}) {
|
|
55013
54857
|
const resolvedPath = resolvePath(filePath);
|
|
55014
54858
|
const sourceName = options.sourceName || path14.basename(resolvedPath);
|
|
55015
|
-
if (!
|
|
54859
|
+
if (!fs13.existsSync(resolvedPath)) {
|
|
55016
54860
|
throw new FileManagerError(
|
|
55017
54861
|
"LOCAL_FILE_MISSING" /* LOCAL_FILE_MISSING */,
|
|
55018
54862
|
`File not found: ${filePath}`
|
|
@@ -55093,7 +54937,7 @@ var FileManager = class {
|
|
|
55093
54937
|
// ============================================================================
|
|
55094
54938
|
async uploadPic(filePath, options = {}) {
|
|
55095
54939
|
const resolvedPath = resolvePath(filePath);
|
|
55096
|
-
if (!
|
|
54940
|
+
if (!fs13.existsSync(resolvedPath)) {
|
|
55097
54941
|
throw new FileManagerError(
|
|
55098
54942
|
"LOCAL_FILE_MISSING" /* LOCAL_FILE_MISSING */,
|
|
55099
54943
|
`File not found: ${filePath}`
|
|
@@ -55123,7 +54967,7 @@ var FileManager = class {
|
|
|
55123
54967
|
this.fileCache.rememberPathHint(resolvedPath, result.hash, path14.basename(resolvedPath));
|
|
55124
54968
|
this.invalidateDirectoryListingCacheForPath(resolvedPath);
|
|
55125
54969
|
try {
|
|
55126
|
-
|
|
54970
|
+
fs13.unlinkSync(optimizedPath);
|
|
55127
54971
|
} catch {
|
|
55128
54972
|
}
|
|
55129
54973
|
return result;
|
|
@@ -55133,7 +54977,7 @@ var FileManager = class {
|
|
|
55133
54977
|
// ============================================================================
|
|
55134
54978
|
async uploadVideo(filePath, options = {}) {
|
|
55135
54979
|
const resolvedPath = resolvePath(filePath);
|
|
55136
|
-
if (!
|
|
54980
|
+
if (!fs13.existsSync(resolvedPath)) {
|
|
55137
54981
|
throw new FileManagerError(
|
|
55138
54982
|
"LOCAL_FILE_MISSING" /* LOCAL_FILE_MISSING */,
|
|
55139
54983
|
`File not found: ${filePath}`
|
|
@@ -55527,13 +55371,13 @@ var FileManager = class {
|
|
|
55527
55371
|
cleanupTempFiles(output) {
|
|
55528
55372
|
try {
|
|
55529
55373
|
if (typeof output === "string") {
|
|
55530
|
-
if (
|
|
55531
|
-
|
|
55374
|
+
if (fs13.existsSync(output)) {
|
|
55375
|
+
fs13.unlinkSync(output);
|
|
55532
55376
|
}
|
|
55533
55377
|
} else {
|
|
55534
55378
|
for (const file of output) {
|
|
55535
|
-
if (
|
|
55536
|
-
|
|
55379
|
+
if (fs13.existsSync(file)) {
|
|
55380
|
+
fs13.unlinkSync(file);
|
|
55537
55381
|
}
|
|
55538
55382
|
}
|
|
55539
55383
|
}
|
|
@@ -55565,7 +55409,7 @@ var FileManager = class {
|
|
|
55565
55409
|
}];
|
|
55566
55410
|
}
|
|
55567
55411
|
const localPath = this.fileCache.getLocalPath(entry.hash);
|
|
55568
|
-
if (localPath &&
|
|
55412
|
+
if (localPath && fs13.existsSync(localPath)) {
|
|
55569
55413
|
return [{
|
|
55570
55414
|
fileId,
|
|
55571
55415
|
name: cacheEntry.name,
|
|
@@ -55662,7 +55506,7 @@ var FileManager = class {
|
|
|
55662
55506
|
directories: []
|
|
55663
55507
|
};
|
|
55664
55508
|
try {
|
|
55665
|
-
const entries =
|
|
55509
|
+
const entries = fs13.readdirSync(resolvedDir, { withFileTypes: true });
|
|
55666
55510
|
for (const entry of entries) {
|
|
55667
55511
|
if (!entry.name || entry.name.startsWith(".")) {
|
|
55668
55512
|
continue;
|
|
@@ -55676,7 +55520,7 @@ var FileManager = class {
|
|
|
55676
55520
|
let isFile = entry.isFile();
|
|
55677
55521
|
if (entry.isSymbolicLink()) {
|
|
55678
55522
|
try {
|
|
55679
|
-
const targetStat =
|
|
55523
|
+
const targetStat = fs13.statSync(fullPath);
|
|
55680
55524
|
isDirectory = targetStat.isDirectory();
|
|
55681
55525
|
isFile = targetStat.isFile();
|
|
55682
55526
|
} catch {
|
|
@@ -55694,7 +55538,7 @@ var FileManager = class {
|
|
|
55694
55538
|
if (!type) {
|
|
55695
55539
|
continue;
|
|
55696
55540
|
}
|
|
55697
|
-
const stat2 =
|
|
55541
|
+
const stat2 = fs13.statSync(fullPath);
|
|
55698
55542
|
listing.files.push({
|
|
55699
55543
|
name: entry.name,
|
|
55700
55544
|
path: fullPath,
|
|
@@ -55793,7 +55637,7 @@ function isInlineMediaRequest(request) {
|
|
|
55793
55637
|
return request.kind === "image" || request.kind === "video";
|
|
55794
55638
|
}
|
|
55795
55639
|
async function prepareInlineMediaContent(params) {
|
|
55796
|
-
const stat2 = await
|
|
55640
|
+
const stat2 = await fs14.stat(params.request.absolutePath);
|
|
55797
55641
|
const limitMb = getCapabilityLimitMb(params.model, params.request.kind);
|
|
55798
55642
|
const limitBytes = limitMb * 1024 * 1024;
|
|
55799
55643
|
if (stat2.size > limitBytes) {
|
|
@@ -55801,7 +55645,7 @@ async function prepareInlineMediaContent(params) {
|
|
|
55801
55645
|
`${params.request.kind} understanding for ${params.model.provider}/${params.model.id} supports inline files up to ${limitMb}MB; ${path15.basename(params.request.displayPath)} is ${(stat2.size / 1024 / 1024).toFixed(1)}MB. Configure a model with a file upload adapter, or compress/trim the file before reading it.`
|
|
55802
55646
|
);
|
|
55803
55647
|
}
|
|
55804
|
-
const data = await
|
|
55648
|
+
const data = await fs14.readFile(params.request.absolutePath, "base64");
|
|
55805
55649
|
const content = params.request.kind === "video" ? [{ type: "video", data, mimeType: params.request.mimeType }] : [{ type: "image", data, mimeType: params.request.mimeType }];
|
|
55806
55650
|
return {
|
|
55807
55651
|
content,
|
|
@@ -55821,7 +55665,7 @@ async function waitForReady(params) {
|
|
|
55821
55665
|
if (status.status === "error" || status.status === "expired") {
|
|
55822
55666
|
throw new Error(`Uploaded file is not ready: ${status.status}${status.error ? ` (${status.error})` : ""}`);
|
|
55823
55667
|
}
|
|
55824
|
-
await new Promise((
|
|
55668
|
+
await new Promise((resolve4) => setTimeout(resolve4, 1500));
|
|
55825
55669
|
}
|
|
55826
55670
|
throw new Error("Timed out waiting for uploaded file to become ready");
|
|
55827
55671
|
}
|
|
@@ -55957,7 +55801,7 @@ var ExecutionStateManager = class {
|
|
|
55957
55801
|
case "aborted":
|
|
55958
55802
|
return "Todo run aborted. Cleared the remaining todo list.";
|
|
55959
55803
|
case "failed_turn":
|
|
55960
|
-
return "Todo run failed during the latest turn.
|
|
55804
|
+
return "Todo run failed during the latest turn. Preserved the todo list and paused automatic continuation.";
|
|
55961
55805
|
case "max_attempts":
|
|
55962
55806
|
return "Todo run reached the maximum follow-up attempts and was cleared as failed.";
|
|
55963
55807
|
case "stagnated":
|
|
@@ -56075,6 +55919,18 @@ var ExecutionStateManager = class {
|
|
|
56075
55919
|
return { changed: false };
|
|
56076
55920
|
}
|
|
56077
55921
|
const decision = evaluateTodoClosureAfterFailedTurn(previous.loop);
|
|
55922
|
+
if (decision.action === "pause_failed") {
|
|
55923
|
+
const paused = pauseExecutionState({
|
|
55924
|
+
...previous,
|
|
55925
|
+
loop: decision.loop
|
|
55926
|
+
}, this.summarizeFailure(decision.reason));
|
|
55927
|
+
this.store.replace(paused);
|
|
55928
|
+
return {
|
|
55929
|
+
changed: true,
|
|
55930
|
+
terminalStatus: "paused",
|
|
55931
|
+
terminalSummary: paused.failureSummary || void 0
|
|
55932
|
+
};
|
|
55933
|
+
}
|
|
56078
55934
|
if (decision.action === "clear_failed") {
|
|
56079
55935
|
this.clearWithSummary(this.summarizeFailure(decision.reason));
|
|
56080
55936
|
return {
|
|
@@ -56086,6 +55942,14 @@ var ExecutionStateManager = class {
|
|
|
56086
55942
|
}
|
|
56087
55943
|
return { changed: false };
|
|
56088
55944
|
}
|
|
55945
|
+
resumePausedTodo() {
|
|
55946
|
+
const previous = this.store.read();
|
|
55947
|
+
if (previous.mode !== "todo" || previous.lifecycle !== "paused" || previous.steps.length === 0) {
|
|
55948
|
+
return { changed: false };
|
|
55949
|
+
}
|
|
55950
|
+
const next = this.store.replace(continueExecutionState(previous));
|
|
55951
|
+
return { changed: !this.unchanged(previous, next) };
|
|
55952
|
+
}
|
|
56089
55953
|
markAwaitingContinuationStalled() {
|
|
56090
55954
|
const previous = this.store.read();
|
|
56091
55955
|
if (previous.mode !== "todo" || !previous.awaitingContinuation) {
|
|
@@ -56123,7 +55987,7 @@ var ExecutionStateManager = class {
|
|
|
56123
55987
|
return null;
|
|
56124
55988
|
}
|
|
56125
55989
|
if (shouldPreserveExecutionStateForUserText(text)) {
|
|
56126
|
-
if (state.lifecycle === "aborted") {
|
|
55990
|
+
if (state.lifecycle === "paused" || state.lifecycle === "aborted") {
|
|
56127
55991
|
this.store.replace(continueExecutionState(state));
|
|
56128
55992
|
return "continued";
|
|
56129
55993
|
}
|
|
@@ -56151,7 +56015,7 @@ var ExecutionStateManager = class {
|
|
|
56151
56015
|
};
|
|
56152
56016
|
|
|
56153
56017
|
// src/session-trace.ts
|
|
56154
|
-
import * as
|
|
56018
|
+
import * as fs15 from "node:fs";
|
|
56155
56019
|
import * as path16 from "node:path";
|
|
56156
56020
|
var SessionTraceWriter = class extends SessionTraceSnapshotWriter {
|
|
56157
56021
|
constructor(sessionsDir, sessionManager) {
|
|
@@ -56159,9 +56023,9 @@ var SessionTraceWriter = class extends SessionTraceSnapshotWriter {
|
|
|
56159
56023
|
getSessionId: () => sessionManager.getActiveSessionId(),
|
|
56160
56024
|
loadTrace: (sessionId) => {
|
|
56161
56025
|
const tracePath = path16.join(sessionsDir, `${sessionId}.trace.json`);
|
|
56162
|
-
if (!
|
|
56026
|
+
if (!fs15.existsSync(tracePath)) return null;
|
|
56163
56027
|
try {
|
|
56164
|
-
return JSON.parse(
|
|
56028
|
+
return JSON.parse(fs15.readFileSync(tracePath, "utf8"));
|
|
56165
56029
|
} catch {
|
|
56166
56030
|
return null;
|
|
56167
56031
|
}
|
|
@@ -56169,8 +56033,8 @@ var SessionTraceWriter = class extends SessionTraceSnapshotWriter {
|
|
|
56169
56033
|
saveTrace: (trace) => {
|
|
56170
56034
|
const tracePath = path16.join(sessionsDir, `${trace.sessionId}.trace.json`);
|
|
56171
56035
|
const tempPath = `${tracePath}.tmp`;
|
|
56172
|
-
|
|
56173
|
-
|
|
56036
|
+
fs15.writeFileSync(tempPath, JSON.stringify(trace, null, 2), "utf8");
|
|
56037
|
+
fs15.renameSync(tempPath, tracePath);
|
|
56174
56038
|
}
|
|
56175
56039
|
});
|
|
56176
56040
|
this.sessionsDir = sessionsDir;
|
|
@@ -56777,7 +56641,7 @@ async function handleCacheTest(host) {
|
|
|
56777
56641
|
host.chatContainer.addChild(new Text(theme.fg("dim", ` ${summarizeUsage(result1.usage)}`), 1, 0));
|
|
56778
56642
|
host.chatContainer.addChild(new Text(theme.fg("dim", " Waiting 2s before replaying identical request..."), 1, 0));
|
|
56779
56643
|
host.ui.requestRender();
|
|
56780
|
-
await new Promise((
|
|
56644
|
+
await new Promise((resolve4) => setTimeout(resolve4, 2e3));
|
|
56781
56645
|
host.chatContainer.addChild(new Text(theme.fg("accent", "Request 2/2: replaying identical request..."), 1, 0));
|
|
56782
56646
|
host.ui.requestRender();
|
|
56783
56647
|
result2 = await completeSimple(model, context, options);
|
|
@@ -58860,7 +58724,7 @@ async function handleForkCommand(host) {
|
|
|
58860
58724
|
}
|
|
58861
58725
|
|
|
58862
58726
|
// src/commands/interactive-skill-commands.ts
|
|
58863
|
-
import * as
|
|
58727
|
+
import * as fs16 from "fs";
|
|
58864
58728
|
import * as os3 from "os";
|
|
58865
58729
|
import * as path17 from "path";
|
|
58866
58730
|
|
|
@@ -59204,7 +59068,7 @@ function expandSkillCommand(host, text) {
|
|
|
59204
59068
|
const skill = host.skills.find((s) => s.name === skillName);
|
|
59205
59069
|
if (!skill) return text;
|
|
59206
59070
|
try {
|
|
59207
|
-
const content =
|
|
59071
|
+
const content = fs16.readFileSync(skill.filePath, "utf-8");
|
|
59208
59072
|
const body = host.stripFrontmatter(content).trim();
|
|
59209
59073
|
const skillBlock = `<skill name="${skill.name}" location="${skill.filePath}">
|
|
59210
59074
|
References are relative to ${skill.baseDir}.
|
|
@@ -59274,13 +59138,13 @@ async function handleSkillsCreate(host, args) {
|
|
|
59274
59138
|
const skillDir = path17.join(skillsDir, name);
|
|
59275
59139
|
const skillFile = path17.join(skillDir, "SKILL.md");
|
|
59276
59140
|
console.error(`[SkillsCreate] Creating at: ${skillFile}`);
|
|
59277
|
-
if (
|
|
59141
|
+
if (fs16.existsSync(skillDir)) {
|
|
59278
59142
|
host.showError(`Skill "${name}" already exists at ${skillDir}`);
|
|
59279
59143
|
return;
|
|
59280
59144
|
}
|
|
59281
|
-
|
|
59145
|
+
fs16.mkdirSync(skillDir, { recursive: true });
|
|
59282
59146
|
const template = createSkillTemplate(name, description);
|
|
59283
|
-
|
|
59147
|
+
fs16.writeFileSync(skillFile, template, "utf-8");
|
|
59284
59148
|
console.error(`[SkillsCreate] Successfully created skill`);
|
|
59285
59149
|
host.chatContainer.addChild(new Spacer(1));
|
|
59286
59150
|
host.chatContainer.addChild(new Text(theme.fg("accent", `\u2713 Created skill: ${name}`), 1, 0));
|
|
@@ -60024,6 +59888,29 @@ async function handleCompactCommand(host) {
|
|
|
60024
59888
|
}
|
|
60025
59889
|
}
|
|
60026
59890
|
|
|
59891
|
+
// src/runtime/footer-lifecycle.ts
|
|
59892
|
+
function messageRole(event) {
|
|
59893
|
+
return String(event.message.role);
|
|
59894
|
+
}
|
|
59895
|
+
function formatFooterLifecycleEvent(event) {
|
|
59896
|
+
switch (event.type) {
|
|
59897
|
+
case "message_start":
|
|
59898
|
+
return `message_start(${messageRole(event)})`;
|
|
59899
|
+
case "message_end":
|
|
59900
|
+
return `message_end(${messageRole(event)})`;
|
|
59901
|
+
case "message_update":
|
|
59902
|
+
return event.message.role === "assistant" ? event.assistantMessageEvent.type : "message_update";
|
|
59903
|
+
case "tool_execution_start":
|
|
59904
|
+
return `tool_execution_start(${event.toolName})`;
|
|
59905
|
+
case "tool_execution_update":
|
|
59906
|
+
return `tool_execution_update(${event.toolName})`;
|
|
59907
|
+
case "tool_execution_end":
|
|
59908
|
+
return `tool_execution_end(${event.toolName})`;
|
|
59909
|
+
default:
|
|
59910
|
+
return event.type;
|
|
59911
|
+
}
|
|
59912
|
+
}
|
|
59913
|
+
|
|
60027
59914
|
// src/runtime/interactive-runtime-events.ts
|
|
60028
59915
|
function bindInteractiveRuntimeEvents(host) {
|
|
60029
59916
|
host.agent.subscribe((event) => {
|
|
@@ -60046,7 +59933,7 @@ function bindInteractiveRuntimeEvents(host) {
|
|
|
60046
59933
|
break;
|
|
60047
59934
|
case "message_end":
|
|
60048
59935
|
if (process.env.PIE_DEBUG_FOOTER) {
|
|
60049
|
-
console.error(`[Footer Debug]
|
|
59936
|
+
console.error(`[Footer Debug] ${formatFooterLifecycleEvent(event)}`);
|
|
60050
59937
|
}
|
|
60051
59938
|
host.logDebug("message:end", { stopReason: event.message.role === "assistant" ? event.message.stopReason : void 0 });
|
|
60052
59939
|
handleMessageEnd(host, event);
|
|
@@ -60248,7 +60135,7 @@ function handleMessageStart(host, event) {
|
|
|
60248
60135
|
host.chatContainer.addChild(host.streamingComponent);
|
|
60249
60136
|
host.sessionTrace.updateAssistantMessage(event.message);
|
|
60250
60137
|
}
|
|
60251
|
-
host.footer.setState({ lifecycleEvent:
|
|
60138
|
+
host.footer.setState({ lifecycleEvent: formatFooterLifecycleEvent(event) });
|
|
60252
60139
|
host.emitExtensionEvent({ type: "message:start", message: event.message });
|
|
60253
60140
|
host.safeRequestRender();
|
|
60254
60141
|
}
|
|
@@ -60259,7 +60146,7 @@ function handleMessageUpdate(host, event) {
|
|
|
60259
60146
|
host.pendingRender = true;
|
|
60260
60147
|
return;
|
|
60261
60148
|
}
|
|
60262
|
-
host.footer.setState({ lifecycleEvent:
|
|
60149
|
+
host.footer.setState({ lifecycleEvent: formatFooterLifecycleEvent(event) });
|
|
60263
60150
|
const message = event.message;
|
|
60264
60151
|
let textContent = "";
|
|
60265
60152
|
let thinkingContent = "";
|
|
@@ -60333,7 +60220,7 @@ function handleToolStart(host, event) {
|
|
|
60333
60220
|
if (toolComponent) {
|
|
60334
60221
|
}
|
|
60335
60222
|
}
|
|
60336
|
-
host.footer.setState({ lifecycleEvent:
|
|
60223
|
+
host.footer.setState({ lifecycleEvent: formatFooterLifecycleEvent(event) });
|
|
60337
60224
|
host.emitExtensionEvent({
|
|
60338
60225
|
type: "tool:execution:start",
|
|
60339
60226
|
toolCallId: event.toolCallId,
|
|
@@ -60358,7 +60245,7 @@ function handleToolUpdate(host, event) {
|
|
|
60358
60245
|
host.ui.requestRender();
|
|
60359
60246
|
}
|
|
60360
60247
|
}
|
|
60361
|
-
host.footer.setState({ lifecycleEvent:
|
|
60248
|
+
host.footer.setState({ lifecycleEvent: formatFooterLifecycleEvent(event) });
|
|
60362
60249
|
host.emitExtensionEvent({
|
|
60363
60250
|
type: "tool:execution:update",
|
|
60364
60251
|
toolCallId: event.toolCallId,
|
|
@@ -60391,7 +60278,7 @@ function handleToolEnd(host, event) {
|
|
|
60391
60278
|
void host.refreshTodoWidget();
|
|
60392
60279
|
}
|
|
60393
60280
|
}
|
|
60394
|
-
host.footer.setState({ lifecycleEvent:
|
|
60281
|
+
host.footer.setState({ lifecycleEvent: formatFooterLifecycleEvent(event) });
|
|
60395
60282
|
host.emitExtensionEvent({
|
|
60396
60283
|
type: "tool:execution:end",
|
|
60397
60284
|
toolCallId: event.toolCallId,
|
|
@@ -60403,7 +60290,7 @@ function handleToolEnd(host, event) {
|
|
|
60403
60290
|
}
|
|
60404
60291
|
function handleMessageEnd(host, event) {
|
|
60405
60292
|
host.streamingComponent = void 0;
|
|
60406
|
-
host.footer.setState({ lifecycleEvent:
|
|
60293
|
+
host.footer.setState({ lifecycleEvent: formatFooterLifecycleEvent(event) });
|
|
60407
60294
|
host.emitExtensionEvent({ type: "message:end", message: event.message });
|
|
60408
60295
|
host.safeRequestRender();
|
|
60409
60296
|
}
|
|
@@ -60668,7 +60555,7 @@ function setupInteractiveEditorSubmitHandler(host) {
|
|
|
60668
60555
|
host.chatContainer.addChild(userMsg);
|
|
60669
60556
|
host.editor.setText("");
|
|
60670
60557
|
host.ui.requestRender();
|
|
60671
|
-
await new Promise((
|
|
60558
|
+
await new Promise((resolve4) => setImmediate(resolve4));
|
|
60672
60559
|
let finalContent = messageContent;
|
|
60673
60560
|
const reminderPrefix = host.executionReminder;
|
|
60674
60561
|
const combinedPrefix = [reminderPrefix].filter((value) => Boolean(value)).join("");
|
|
@@ -60704,7 +60591,7 @@ function setupInteractiveEditorSubmitHandler(host) {
|
|
|
60704
60591
|
}
|
|
60705
60592
|
|
|
60706
60593
|
// src/input/interactive-file-pipeline.ts
|
|
60707
|
-
import * as
|
|
60594
|
+
import * as fs19 from "fs";
|
|
60708
60595
|
import * as path20 from "path";
|
|
60709
60596
|
|
|
60710
60597
|
// src/components/file-picker.ts
|
|
@@ -60926,7 +60813,7 @@ var FilePickerComponent = class extends Container {
|
|
|
60926
60813
|
};
|
|
60927
60814
|
|
|
60928
60815
|
// src/files/commands/file-commands.ts
|
|
60929
|
-
import * as
|
|
60816
|
+
import * as fs17 from "node:fs";
|
|
60930
60817
|
import * as path18 from "node:path";
|
|
60931
60818
|
var FileCommands = class {
|
|
60932
60819
|
context;
|
|
@@ -60943,7 +60830,7 @@ var FileCommands = class {
|
|
|
60943
60830
|
return;
|
|
60944
60831
|
}
|
|
60945
60832
|
const filePath = resolvePath(parsed.path);
|
|
60946
|
-
if (!
|
|
60833
|
+
if (!fs17.existsSync(filePath)) {
|
|
60947
60834
|
this.context.showError(`File not found: ${parsed.path}`);
|
|
60948
60835
|
return;
|
|
60949
60836
|
}
|
|
@@ -60982,7 +60869,7 @@ var FileCommands = class {
|
|
|
60982
60869
|
return;
|
|
60983
60870
|
}
|
|
60984
60871
|
const resolvedPath = resolvePath(filePath);
|
|
60985
|
-
if (!
|
|
60872
|
+
if (!fs17.existsSync(resolvedPath)) {
|
|
60986
60873
|
this.context.showError(`File not found: ${filePath}`);
|
|
60987
60874
|
return;
|
|
60988
60875
|
}
|
|
@@ -61013,7 +60900,7 @@ var FileCommands = class {
|
|
|
61013
60900
|
return;
|
|
61014
60901
|
}
|
|
61015
60902
|
const resolvedPath = resolvePath(parsed.path);
|
|
61016
|
-
if (!
|
|
60903
|
+
if (!fs17.existsSync(resolvedPath)) {
|
|
61017
60904
|
this.context.showError(`File not found: ${parsed.path}`);
|
|
61018
60905
|
return;
|
|
61019
60906
|
}
|
|
@@ -61491,7 +61378,7 @@ var FileStatusMonitor = class {
|
|
|
61491
61378
|
};
|
|
61492
61379
|
|
|
61493
61380
|
// src/files/mention/mention-handler.ts
|
|
61494
|
-
import * as
|
|
61381
|
+
import * as fs18 from "node:fs";
|
|
61495
61382
|
import * as path19 from "node:path";
|
|
61496
61383
|
var MentionHandler = class {
|
|
61497
61384
|
fileManager;
|
|
@@ -61861,8 +61748,8 @@ var MentionHandler = class {
|
|
|
61861
61748
|
}
|
|
61862
61749
|
if (this.isPath(query)) {
|
|
61863
61750
|
const resolvedPath = resolvePath(query);
|
|
61864
|
-
if (
|
|
61865
|
-
const stats =
|
|
61751
|
+
if (fs18.existsSync(resolvedPath)) {
|
|
61752
|
+
const stats = fs18.statSync(resolvedPath);
|
|
61866
61753
|
if (stats.isFile()) {
|
|
61867
61754
|
const type = FileCache.getFileTypeFromName(resolvedPath);
|
|
61868
61755
|
const name = path19.basename(resolvedPath);
|
|
@@ -61886,7 +61773,7 @@ var MentionHandler = class {
|
|
|
61886
61773
|
return void 0;
|
|
61887
61774
|
}
|
|
61888
61775
|
const queryPath = this.isPath(query) ? resolvePath(query) : void 0;
|
|
61889
|
-
const filter = queryPath ?
|
|
61776
|
+
const filter = queryPath ? fs18.existsSync(queryPath) && fs18.statSync(queryPath).isDirectory() ? "" : path19.basename(queryPath) : query;
|
|
61890
61777
|
const entries = this.fileManager.listPathEntries(currentDir, filter);
|
|
61891
61778
|
const options = [];
|
|
61892
61779
|
const homeDir = process.env.HOME || "";
|
|
@@ -61927,7 +61814,7 @@ var MentionHandler = class {
|
|
|
61927
61814
|
getBrowserDirectory(query = this.currentQuery) {
|
|
61928
61815
|
if (this.isPath(query)) {
|
|
61929
61816
|
const resolvedPath = resolvePath(query);
|
|
61930
|
-
if (
|
|
61817
|
+
if (fs18.existsSync(resolvedPath) && fs18.statSync(resolvedPath).isDirectory()) {
|
|
61931
61818
|
return resolvedPath;
|
|
61932
61819
|
}
|
|
61933
61820
|
return path19.dirname(resolvedPath);
|
|
@@ -62291,13 +62178,13 @@ function convertPreparedAttachmentItems(items) {
|
|
|
62291
62178
|
break;
|
|
62292
62179
|
case "image": {
|
|
62293
62180
|
if (!item.data && !item.path) return void 0;
|
|
62294
|
-
const data = item.data ??
|
|
62181
|
+
const data = item.data ?? fs19.readFileSync(item.path, "base64");
|
|
62295
62182
|
converted.push({ type: "image", data, mimeType: item.mimeType });
|
|
62296
62183
|
break;
|
|
62297
62184
|
}
|
|
62298
62185
|
case "video": {
|
|
62299
62186
|
if (!item.data && !item.path) return void 0;
|
|
62300
|
-
const data = item.data ??
|
|
62187
|
+
const data = item.data ?? fs19.readFileSync(item.path, "base64");
|
|
62301
62188
|
converted.push({ type: "video", data, mimeType: item.mimeType });
|
|
62302
62189
|
break;
|
|
62303
62190
|
}
|
|
@@ -62688,6 +62575,7 @@ function buildCodingAgentGuidelinesSection(tools = []) {
|
|
|
62688
62575
|
const hasGrep = toolNames.has("grep_text");
|
|
62689
62576
|
const hasFind = toolNames.has("find_files");
|
|
62690
62577
|
const hasBash = toolNames.has("bash");
|
|
62578
|
+
const hasWebResearch = toolNames.has("web_research");
|
|
62691
62579
|
const hasWebSearch = toolNames.has("web_search");
|
|
62692
62580
|
const hasWebFetch = toolNames.has("web_fetch");
|
|
62693
62581
|
const hasCodeIntel = toolNames.has("code_intel");
|
|
@@ -62702,11 +62590,17 @@ function buildCodingAgentGuidelinesSection(tools = []) {
|
|
|
62702
62590
|
if (hasGrep || hasFind || hasList) {
|
|
62703
62591
|
guidelines.push("Prefer grep_text, find_files, and list_dir for workspace exploration when they are sufficient.");
|
|
62704
62592
|
}
|
|
62705
|
-
if (
|
|
62593
|
+
if (hasWebResearch) {
|
|
62594
|
+
guidelines.push("Use web_research for general public web research, current information, official docs, news, releases, issues, or webpage summaries; it searches, fetches, and returns cited sources.");
|
|
62595
|
+
guidelines.push("When web_research returns fetched sources that answer the request, synthesize the answer from that pack instead of calling web_search or web_fetch again.");
|
|
62596
|
+
}
|
|
62597
|
+
if (hasWebSearch && !hasWebResearch) {
|
|
62706
62598
|
guidelines.push("Use web_search for public web research and grep_text/find_files/list_dir for local workspace search.");
|
|
62707
62599
|
}
|
|
62708
|
-
if (hasWebFetch) {
|
|
62600
|
+
if (hasWebFetch && !hasWebResearch) {
|
|
62709
62601
|
guidelines.push("After web_search identifies a public source, use web_fetch to read the chosen URL before relying on it; also use web_fetch for user-supplied URLs.");
|
|
62602
|
+
} else if (hasWebResearch && hasWebSearch && hasWebFetch) {
|
|
62603
|
+
guidelines.push("Use web_search and web_fetch directly only when you need low-level control over exact queries or URLs.");
|
|
62710
62604
|
}
|
|
62711
62605
|
if (hasCodeIntel) {
|
|
62712
62606
|
guidelines.push("Use code_intel for JS/TS diagnostics, definitions, references, symbols, or hover when type or symbol information matters before editing.");
|
|
@@ -63537,8 +63431,21 @@ function createInteractiveAgentSessionController(host) {
|
|
|
63537
63431
|
} else if (event.type === "retry_start") {
|
|
63538
63432
|
host.showStatus(`Retrying request (attempt ${event.attempt}/${event.maxRetries})...`);
|
|
63539
63433
|
} else if (event.type === "retry_succeeded") {
|
|
63434
|
+
const outcome = host.executionState.resumePausedTodo();
|
|
63435
|
+
if (outcome.changed) {
|
|
63436
|
+
host.sessionTrace.noteRuntimeEvent("todo_resumed_after_retry", {
|
|
63437
|
+
lifecycle: host.executionState.read().lifecycle,
|
|
63438
|
+
currentStepId: host.executionState.read().currentStepId
|
|
63439
|
+
});
|
|
63440
|
+
host.persistExecutionState();
|
|
63441
|
+
void host.refreshTodoWidget();
|
|
63442
|
+
}
|
|
63540
63443
|
host.showStatus("Retry succeeded");
|
|
63541
63444
|
} else if (event.type === "retry_exhausted") {
|
|
63445
|
+
const state = host.executionState.read();
|
|
63446
|
+
if (state.mode === "todo" && state.lifecycle === "paused" && state.steps.length > 0) {
|
|
63447
|
+
host.showStatus("Todo list preserved. Send 'continue' when you want to resume it.");
|
|
63448
|
+
}
|
|
63542
63449
|
host.showError(`Request failed after ${event.maxRetries} retries: ${event.errorMessage}`);
|
|
63543
63450
|
} else if (event.type === "runtime_guard_triggered") {
|
|
63544
63451
|
host.sessionTrace.noteStalled("runtime_guard_triggered", {
|
|
@@ -63770,7 +63677,7 @@ async function handleDirectBash(host, command) {
|
|
|
63770
63677
|
}
|
|
63771
63678
|
host.ui.requestRender();
|
|
63772
63679
|
});
|
|
63773
|
-
return new Promise((
|
|
63680
|
+
return new Promise((resolve4) => {
|
|
63774
63681
|
child.on("close", (code) => {
|
|
63775
63682
|
if (code !== 0) {
|
|
63776
63683
|
outputContainer.addChild(new Spacer(1));
|
|
@@ -63778,7 +63685,7 @@ async function handleDirectBash(host, command) {
|
|
|
63778
63685
|
}
|
|
63779
63686
|
host.chatContainer.addChild(new Spacer(1));
|
|
63780
63687
|
host.ui.requestRender();
|
|
63781
|
-
|
|
63688
|
+
resolve4();
|
|
63782
63689
|
});
|
|
63783
63690
|
});
|
|
63784
63691
|
}
|
|
@@ -63854,11 +63761,11 @@ function installInteractiveInteractionHandler(host) {
|
|
|
63854
63761
|
if (!("timeoutMs" in request) || !request.timeoutMs || request.timeoutMs <= 0) {
|
|
63855
63762
|
return { value: await promise, timedOut: false };
|
|
63856
63763
|
}
|
|
63857
|
-
return await new Promise((
|
|
63858
|
-
const timer = setTimeout(() =>
|
|
63764
|
+
return await new Promise((resolve4, reject) => {
|
|
63765
|
+
const timer = setTimeout(() => resolve4({ timedOut: true }), request.timeoutMs);
|
|
63859
63766
|
promise.then((value) => {
|
|
63860
63767
|
clearTimeout(timer);
|
|
63861
|
-
|
|
63768
|
+
resolve4({ value, timedOut: false });
|
|
63862
63769
|
}).catch((error) => {
|
|
63863
63770
|
clearTimeout(timer);
|
|
63864
63771
|
reject(error);
|
|
@@ -63958,15 +63865,15 @@ function showExtensionNotification(host, message, type = "info") {
|
|
|
63958
63865
|
host.ui.requestRender();
|
|
63959
63866
|
}
|
|
63960
63867
|
function showExtensionSelector(host, title, options, opts) {
|
|
63961
|
-
return new Promise((
|
|
63868
|
+
return new Promise((resolve4) => {
|
|
63962
63869
|
host.showStatus(`Waiting for selection: ${title}`);
|
|
63963
63870
|
if (opts?.signal?.aborted) {
|
|
63964
|
-
|
|
63871
|
+
resolve4(void 0);
|
|
63965
63872
|
return;
|
|
63966
63873
|
}
|
|
63967
63874
|
const onAbort = () => {
|
|
63968
63875
|
host.restoreEditor();
|
|
63969
|
-
|
|
63876
|
+
resolve4(void 0);
|
|
63970
63877
|
};
|
|
63971
63878
|
opts?.signal?.addEventListener("abort", onAbort, { once: true });
|
|
63972
63879
|
const selector = new ExtensionSelectorComponent(
|
|
@@ -63975,12 +63882,12 @@ function showExtensionSelector(host, title, options, opts) {
|
|
|
63975
63882
|
(option) => {
|
|
63976
63883
|
opts?.signal?.removeEventListener("abort", onAbort);
|
|
63977
63884
|
host.restoreEditor();
|
|
63978
|
-
|
|
63885
|
+
resolve4(option);
|
|
63979
63886
|
},
|
|
63980
63887
|
() => {
|
|
63981
63888
|
opts?.signal?.removeEventListener("abort", onAbort);
|
|
63982
63889
|
host.restoreEditor();
|
|
63983
|
-
|
|
63890
|
+
resolve4(void 0);
|
|
63984
63891
|
}
|
|
63985
63892
|
);
|
|
63986
63893
|
host.editorContainer.clear();
|
|
@@ -63996,15 +63903,15 @@ ${message}`, ["Yes", "No"], opts);
|
|
|
63996
63903
|
return result === "Yes";
|
|
63997
63904
|
}
|
|
63998
63905
|
function showExtensionInput(host, title, placeholder, opts) {
|
|
63999
|
-
return new Promise((
|
|
63906
|
+
return new Promise((resolve4) => {
|
|
64000
63907
|
host.showStatus(`Waiting for input: ${title}`);
|
|
64001
63908
|
if (opts?.signal?.aborted) {
|
|
64002
|
-
|
|
63909
|
+
resolve4(void 0);
|
|
64003
63910
|
return;
|
|
64004
63911
|
}
|
|
64005
63912
|
const onAbort = () => {
|
|
64006
63913
|
host.restoreEditor();
|
|
64007
|
-
|
|
63914
|
+
resolve4(void 0);
|
|
64008
63915
|
};
|
|
64009
63916
|
opts?.signal?.addEventListener("abort", onAbort, { once: true });
|
|
64010
63917
|
const input = new ExtensionInputComponent(
|
|
@@ -64013,12 +63920,12 @@ function showExtensionInput(host, title, placeholder, opts) {
|
|
|
64013
63920
|
(value) => {
|
|
64014
63921
|
opts?.signal?.removeEventListener("abort", onAbort);
|
|
64015
63922
|
host.restoreEditor();
|
|
64016
|
-
|
|
63923
|
+
resolve4(value);
|
|
64017
63924
|
},
|
|
64018
63925
|
() => {
|
|
64019
63926
|
opts?.signal?.removeEventListener("abort", onAbort);
|
|
64020
63927
|
host.restoreEditor();
|
|
64021
|
-
|
|
63928
|
+
resolve4(void 0);
|
|
64022
63929
|
}
|
|
64023
63930
|
);
|
|
64024
63931
|
host.editorContainer.clear();
|
|
@@ -64029,7 +63936,7 @@ function showExtensionInput(host, title, placeholder, opts) {
|
|
|
64029
63936
|
});
|
|
64030
63937
|
}
|
|
64031
63938
|
function showExtensionEditor(host, title, prefill) {
|
|
64032
|
-
return new Promise((
|
|
63939
|
+
return new Promise((resolve4) => {
|
|
64033
63940
|
host.showStatus(`Waiting for input: ${title}`);
|
|
64034
63941
|
const container = new Container();
|
|
64035
63942
|
container.addChild(new Text(theme.bold(theme.fg("accent", title)), 0, 0));
|
|
@@ -64051,12 +63958,12 @@ function showExtensionEditor(host, title, prefill) {
|
|
|
64051
63958
|
preview: value.slice(0, 120)
|
|
64052
63959
|
});
|
|
64053
63960
|
host.restoreEditor();
|
|
64054
|
-
|
|
63961
|
+
resolve4(value);
|
|
64055
63962
|
};
|
|
64056
63963
|
editor.onEscape = () => {
|
|
64057
63964
|
host.logDebug("extension:editor:cancel", { title });
|
|
64058
63965
|
host.restoreEditor();
|
|
64059
|
-
|
|
63966
|
+
resolve4(void 0);
|
|
64060
63967
|
};
|
|
64061
63968
|
container.addChild(editor);
|
|
64062
63969
|
container.addChild(new Spacer(1));
|
|
@@ -64070,14 +63977,14 @@ function showExtensionEditor(host, title, prefill) {
|
|
|
64070
63977
|
}
|
|
64071
63978
|
function showExtensionCustom(host, factory, options) {
|
|
64072
63979
|
const savedText = host.editor.getText();
|
|
64073
|
-
return new Promise((
|
|
63980
|
+
return new Promise((resolve4, reject) => {
|
|
64074
63981
|
let closed = false;
|
|
64075
63982
|
const close = (result) => {
|
|
64076
63983
|
if (closed) return;
|
|
64077
63984
|
closed = true;
|
|
64078
63985
|
host.restoreEditor();
|
|
64079
63986
|
host.editor.setText(savedText);
|
|
64080
|
-
|
|
63987
|
+
resolve4(result);
|
|
64081
63988
|
};
|
|
64082
63989
|
Promise.resolve(factory(host.ui, theme, close)).then((component) => {
|
|
64083
63990
|
if (closed) return;
|
|
@@ -64151,7 +64058,7 @@ var AttachmentResolver = class {
|
|
|
64151
64058
|
};
|
|
64152
64059
|
|
|
64153
64060
|
// src/extensions/loader.ts
|
|
64154
|
-
import * as
|
|
64061
|
+
import * as fs20 from "node:fs";
|
|
64155
64062
|
import * as os4 from "os";
|
|
64156
64063
|
import * as path21 from "path";
|
|
64157
64064
|
import { pathToFileURL } from "node:url";
|
|
@@ -64335,7 +64242,7 @@ function normalizeExtensionImportPath(extensionPath) {
|
|
|
64335
64242
|
}
|
|
64336
64243
|
async function loadExtension(extensionPath, cwd, uiContext, abortFn, isIdleFn, hasUI, actions) {
|
|
64337
64244
|
const resolvedPath = resolvePath2(extensionPath, cwd);
|
|
64338
|
-
if (!
|
|
64245
|
+
if (!fs20.existsSync(resolvedPath)) {
|
|
64339
64246
|
return { extension: null, error: `Extension not found: ${extensionPath}` };
|
|
64340
64247
|
}
|
|
64341
64248
|
try {
|
|
@@ -64356,12 +64263,12 @@ async function loadExtension(extensionPath, cwd, uiContext, abortFn, isIdleFn, h
|
|
|
64356
64263
|
}
|
|
64357
64264
|
}
|
|
64358
64265
|
function discoverExtensionsInDir(dir) {
|
|
64359
|
-
if (!
|
|
64266
|
+
if (!fs20.existsSync(dir)) {
|
|
64360
64267
|
return [];
|
|
64361
64268
|
}
|
|
64362
64269
|
const discovered = [];
|
|
64363
64270
|
try {
|
|
64364
|
-
const entries =
|
|
64271
|
+
const entries = fs20.readdirSync(dir, { withFileTypes: true });
|
|
64365
64272
|
for (const entry of entries) {
|
|
64366
64273
|
const entryPath = path21.join(dir, entry.name);
|
|
64367
64274
|
if (entry.isFile() && (entry.name.endsWith(".cjs") || entry.name.endsWith(".js") || entry.name.endsWith(".ts"))) {
|
|
@@ -64370,16 +64277,16 @@ function discoverExtensionsInDir(dir) {
|
|
|
64370
64277
|
}
|
|
64371
64278
|
if (entry.isDirectory()) {
|
|
64372
64279
|
const packageJsonPath = path21.join(entryPath, "package.json");
|
|
64373
|
-
if (
|
|
64280
|
+
if (fs20.existsSync(packageJsonPath)) {
|
|
64374
64281
|
try {
|
|
64375
|
-
const
|
|
64376
|
-
const manifest =
|
|
64282
|
+
const pkg = JSON.parse(fs20.readFileSync(packageJsonPath, "utf-8"));
|
|
64283
|
+
const manifest = pkg.pie;
|
|
64377
64284
|
if (manifest?.main) {
|
|
64378
64285
|
const mainPath = path21.resolve(entryPath, manifest.main);
|
|
64379
|
-
if (
|
|
64286
|
+
if (fs20.existsSync(mainPath)) {
|
|
64380
64287
|
discovered.push({
|
|
64381
64288
|
entryPath: mainPath,
|
|
64382
|
-
manifestName: manifest.name ||
|
|
64289
|
+
manifestName: manifest.name || pkg.name
|
|
64383
64290
|
});
|
|
64384
64291
|
continue;
|
|
64385
64292
|
}
|
|
@@ -64388,17 +64295,17 @@ function discoverExtensionsInDir(dir) {
|
|
|
64388
64295
|
}
|
|
64389
64296
|
}
|
|
64390
64297
|
const indexCjs = path21.join(entryPath, "index.cjs");
|
|
64391
|
-
if (
|
|
64298
|
+
if (fs20.existsSync(indexCjs)) {
|
|
64392
64299
|
discovered.push({ entryPath: indexCjs });
|
|
64393
64300
|
continue;
|
|
64394
64301
|
}
|
|
64395
64302
|
const indexJs = path21.join(entryPath, "index.js");
|
|
64396
|
-
if (
|
|
64303
|
+
if (fs20.existsSync(indexJs)) {
|
|
64397
64304
|
discovered.push({ entryPath: indexJs });
|
|
64398
64305
|
continue;
|
|
64399
64306
|
}
|
|
64400
64307
|
const indexTs = path21.join(entryPath, "index.ts");
|
|
64401
|
-
if (
|
|
64308
|
+
if (fs20.existsSync(indexTs)) {
|
|
64402
64309
|
discovered.push({ entryPath: indexTs });
|
|
64403
64310
|
continue;
|
|
64404
64311
|
}
|
|
@@ -64447,11 +64354,11 @@ async function loadExtensions(configuredPaths, cwd, uiContext, abortFn, isIdleFn
|
|
|
64447
64354
|
}
|
|
64448
64355
|
for (const p of configuredPaths) {
|
|
64449
64356
|
const resolved = resolvePath2(p, cwd);
|
|
64450
|
-
if (!
|
|
64357
|
+
if (!fs20.existsSync(resolved)) {
|
|
64451
64358
|
errors.push({ path: p, error: `Extension path not found: ${p}` });
|
|
64452
64359
|
continue;
|
|
64453
64360
|
}
|
|
64454
|
-
if (!
|
|
64361
|
+
if (!fs20.statSync(resolved).isDirectory()) {
|
|
64455
64362
|
errors.push({ path: p, error: `Extension path must be a directory: ${p}` });
|
|
64456
64363
|
continue;
|
|
64457
64364
|
}
|
|
@@ -65200,7 +65107,7 @@ var InteractiveMode = class {
|
|
|
65200
65107
|
this.skills = options.skills;
|
|
65201
65108
|
this.originalTools = [...options.tools];
|
|
65202
65109
|
this.skillsSection = formatSkillsForPrompt(options.skills);
|
|
65203
|
-
this.knowledgeSection =
|
|
65110
|
+
this.knowledgeSection = buildCliProjectContextSection(options.cwd);
|
|
65204
65111
|
}
|
|
65205
65112
|
options;
|
|
65206
65113
|
get runtimeEventHost() {
|
|
@@ -65241,10 +65148,15 @@ var InteractiveMode = class {
|
|
|
65241
65148
|
}
|
|
65242
65149
|
rebuildSkillAwareTools(sourceTools) {
|
|
65243
65150
|
const preservedTools = sourceTools.filter(
|
|
65244
|
-
(tool) => !CLI_FILESYSTEM_TOOL_NAMES.includes(tool.name)
|
|
65151
|
+
(tool) => !CLI_FILESYSTEM_TOOL_NAMES.includes(tool.name)
|
|
65245
65152
|
);
|
|
65246
65153
|
const fileSystemToolOptions = (allowlistedDirs) => ({
|
|
65247
|
-
|
|
65154
|
+
...buildCliFileAccessOptions({
|
|
65155
|
+
cwd: this.options.cwd,
|
|
65156
|
+
configDir: this.options.configDir,
|
|
65157
|
+
skills: this.skills,
|
|
65158
|
+
allowlistedDirs
|
|
65159
|
+
}),
|
|
65248
65160
|
configDir: this.options.configDir,
|
|
65249
65161
|
getAgentModel: () => this.options.model,
|
|
65250
65162
|
getSessionId: () => this.sessionManager.getActiveSessionId() || void 0,
|
|
@@ -65257,9 +65169,6 @@ var InteractiveMode = class {
|
|
|
65257
65169
|
});
|
|
65258
65170
|
const normalFsTools = createCliFileSystemTools(this.options.cwd, fileSystemToolOptions([this.options.configDir]));
|
|
65259
65171
|
const currentFsTools = this.yoloMode ? createCliFileSystemTools(this.options.cwd, fileSystemToolOptions(["/"])) : normalFsTools;
|
|
65260
|
-
const readSkillTool = createCliReadSkillTool(this.skills);
|
|
65261
|
-
const readResourceTool = createCliReadResourceTool(this.skills);
|
|
65262
|
-
const resolveResourceTool = createCliResolveResourceTool(this.skills);
|
|
65263
65172
|
const getPolicyContext = () => ({
|
|
65264
65173
|
mode: this.planModeEnabled ? "plan" : "normal",
|
|
65265
65174
|
yoloMode: this.yoloMode,
|
|
@@ -65267,11 +65176,11 @@ var InteractiveMode = class {
|
|
|
65267
65176
|
});
|
|
65268
65177
|
return {
|
|
65269
65178
|
currentTools: createPolicyEnforcedTools(
|
|
65270
|
-
[...currentFsTools,
|
|
65179
|
+
[...currentFsTools, ...preservedTools],
|
|
65271
65180
|
{ getContext: getPolicyContext }
|
|
65272
65181
|
),
|
|
65273
65182
|
originalTools: createPolicyEnforcedTools(
|
|
65274
|
-
[...normalFsTools,
|
|
65183
|
+
[...normalFsTools, ...preservedTools],
|
|
65275
65184
|
{ getContext: getPolicyContext }
|
|
65276
65185
|
)
|
|
65277
65186
|
};
|
|
@@ -65765,8 +65674,8 @@ function parseCliInvocation(args) {
|
|
|
65765
65674
|
}
|
|
65766
65675
|
|
|
65767
65676
|
// src/cli.ts
|
|
65768
|
-
import { mkdirSync as
|
|
65769
|
-
import * as
|
|
65677
|
+
import { mkdirSync as mkdirSync11, existsSync as existsSync17 } from "fs";
|
|
65678
|
+
import * as fs25 from "fs";
|
|
65770
65679
|
import * as path25 from "path";
|
|
65771
65680
|
|
|
65772
65681
|
// src/logging/runtime-logger.ts
|
|
@@ -65904,7 +65813,7 @@ var AuthStorage = class {
|
|
|
65904
65813
|
};
|
|
65905
65814
|
|
|
65906
65815
|
// src/core/settings-manager.ts
|
|
65907
|
-
import * as
|
|
65816
|
+
import * as fs21 from "fs";
|
|
65908
65817
|
var SettingsManager = class {
|
|
65909
65818
|
settingsPath;
|
|
65910
65819
|
legacyConfigPath;
|
|
@@ -65918,9 +65827,9 @@ var SettingsManager = class {
|
|
|
65918
65827
|
this.legacyConfig = this.loadLegacyConfigFile();
|
|
65919
65828
|
}
|
|
65920
65829
|
readJson(filePath) {
|
|
65921
|
-
if (!
|
|
65830
|
+
if (!fs21.existsSync(filePath)) return null;
|
|
65922
65831
|
try {
|
|
65923
|
-
return JSON.parse(
|
|
65832
|
+
return JSON.parse(fs21.readFileSync(filePath, "utf-8"));
|
|
65924
65833
|
} catch {
|
|
65925
65834
|
return null;
|
|
65926
65835
|
}
|
|
@@ -65932,15 +65841,15 @@ var SettingsManager = class {
|
|
|
65932
65841
|
return this.readJson(this.legacyConfigPath) || {};
|
|
65933
65842
|
}
|
|
65934
65843
|
ensureDir() {
|
|
65935
|
-
|
|
65844
|
+
fs21.mkdirSync(getConfigDir(), { recursive: true });
|
|
65936
65845
|
}
|
|
65937
65846
|
writeSettings() {
|
|
65938
65847
|
this.ensureDir();
|
|
65939
|
-
|
|
65848
|
+
fs21.writeFileSync(this.settingsPath, JSON.stringify(this.settings, null, 2));
|
|
65940
65849
|
}
|
|
65941
65850
|
writeLegacyConfig() {
|
|
65942
65851
|
this.ensureDir();
|
|
65943
|
-
|
|
65852
|
+
fs21.writeFileSync(this.legacyConfigPath, JSON.stringify(this.legacyConfig, null, 2));
|
|
65944
65853
|
}
|
|
65945
65854
|
getLegacyApiKey() {
|
|
65946
65855
|
return this.legacyConfig.apiKey;
|
|
@@ -65992,7 +65901,7 @@ var SettingsManager = class {
|
|
|
65992
65901
|
};
|
|
65993
65902
|
|
|
65994
65903
|
// src/core/model-registry.ts
|
|
65995
|
-
import * as
|
|
65904
|
+
import * as fs22 from "fs";
|
|
65996
65905
|
import * as path22 from "path";
|
|
65997
65906
|
function validateProfileConfig(profileId, profileConfig) {
|
|
65998
65907
|
const missing = [];
|
|
@@ -66055,11 +65964,11 @@ var ModelRegistry = class {
|
|
|
66055
65964
|
this.modelOrder = [];
|
|
66056
65965
|
this.configDefaults = void 0;
|
|
66057
65966
|
this.usingExternalProviders = false;
|
|
66058
|
-
if (!
|
|
65967
|
+
if (!fs22.existsSync(this.modelsPath)) {
|
|
66059
65968
|
return;
|
|
66060
65969
|
}
|
|
66061
65970
|
try {
|
|
66062
|
-
const raw = JSON.parse(
|
|
65971
|
+
const raw = JSON.parse(fs22.readFileSync(this.modelsPath, "utf-8"));
|
|
66063
65972
|
if (raw && typeof raw === "object" && "providers" in raw) {
|
|
66064
65973
|
throw new Error('Legacy models.json format is no longer supported. Use top-level "profiles".');
|
|
66065
65974
|
}
|
|
@@ -66308,11 +66217,12 @@ var ModelRegistry = class {
|
|
|
66308
66217
|
// src/doctor.ts
|
|
66309
66218
|
import { spawnSync } from "node:child_process";
|
|
66310
66219
|
import { createRequire } from "node:module";
|
|
66311
|
-
import * as
|
|
66220
|
+
import * as fs23 from "node:fs";
|
|
66312
66221
|
import * as os5 from "node:os";
|
|
66313
66222
|
import * as path23 from "node:path";
|
|
66314
66223
|
import { delimiter } from "node:path";
|
|
66315
66224
|
var require2 = createRequire(import.meta.url);
|
|
66225
|
+
var UNITY_INSTANCE_MAX_AGE_SEC = 120;
|
|
66316
66226
|
function checkStatus(checks) {
|
|
66317
66227
|
return {
|
|
66318
66228
|
pass: checks.filter((check) => check.status === "pass").length,
|
|
@@ -66344,19 +66254,19 @@ function checkShell() {
|
|
|
66344
66254
|
}
|
|
66345
66255
|
function canWriteDirectory(dir) {
|
|
66346
66256
|
try {
|
|
66347
|
-
|
|
66257
|
+
fs23.mkdirSync(dir, { recursive: true });
|
|
66348
66258
|
const probe = path23.join(dir, `.pie-doctor-${process.pid}-${Date.now()}`);
|
|
66349
|
-
|
|
66350
|
-
|
|
66259
|
+
fs23.writeFileSync(probe, "ok", "utf8");
|
|
66260
|
+
fs23.rmSync(probe, { force: true });
|
|
66351
66261
|
return { ok: true };
|
|
66352
66262
|
} catch (error) {
|
|
66353
66263
|
return { ok: false, error: error instanceof Error ? error.message : String(error) };
|
|
66354
66264
|
}
|
|
66355
66265
|
}
|
|
66356
66266
|
function isExecutable(candidate) {
|
|
66357
|
-
if (!candidate || !
|
|
66267
|
+
if (!candidate || !fs23.existsSync(candidate)) return false;
|
|
66358
66268
|
try {
|
|
66359
|
-
|
|
66269
|
+
fs23.accessSync(candidate, fs23.constants.X_OK);
|
|
66360
66270
|
return true;
|
|
66361
66271
|
} catch {
|
|
66362
66272
|
return os5.platform() === "win32";
|
|
@@ -66434,7 +66344,7 @@ function checkPlaywrightBrowser() {
|
|
|
66434
66344
|
} catch {
|
|
66435
66345
|
executablePath = void 0;
|
|
66436
66346
|
}
|
|
66437
|
-
if (executablePath &&
|
|
66347
|
+
if (executablePath && fs23.existsSync(executablePath)) {
|
|
66438
66348
|
return {
|
|
66439
66349
|
id: "playwright_browser",
|
|
66440
66350
|
label: "Playwright browser",
|
|
@@ -66452,37 +66362,98 @@ function checkPlaywrightBrowser() {
|
|
|
66452
66362
|
details: { expectedExecutablePath: executablePath, skillWrapper }
|
|
66453
66363
|
};
|
|
66454
66364
|
}
|
|
66365
|
+
function isRecord2(value) {
|
|
66366
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
66367
|
+
}
|
|
66368
|
+
function hasRequiredUnityIdentityFields(instance) {
|
|
66369
|
+
return typeof instance.instanceId === "string" && instance.instanceId.trim().length > 0 && typeof instance.projectPath === "string" && instance.projectPath.trim().length > 0 && Number(instance.port || 0) > 0 && Number(instance.pid || 0) > 0 && Number(instance.lastSeenUnix || 0) > 0;
|
|
66370
|
+
}
|
|
66371
|
+
function isProcessAlive(pid) {
|
|
66372
|
+
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
66373
|
+
try {
|
|
66374
|
+
process.kill(pid, 0);
|
|
66375
|
+
return true;
|
|
66376
|
+
} catch (error) {
|
|
66377
|
+
return error?.code === "EPERM";
|
|
66378
|
+
}
|
|
66379
|
+
}
|
|
66380
|
+
function isLiveUnityInstance(instance, nowUnix = Math.floor(Date.now() / 1e3)) {
|
|
66381
|
+
if (!hasRequiredUnityIdentityFields(instance)) return false;
|
|
66382
|
+
const lastSeenUnix = Number(instance.lastSeenUnix || 0);
|
|
66383
|
+
if (nowUnix - lastSeenUnix > UNITY_INSTANCE_MAX_AGE_SEC) return false;
|
|
66384
|
+
return isProcessAlive(Number(instance.pid || 0));
|
|
66385
|
+
}
|
|
66455
66386
|
function checkUnityRegistry() {
|
|
66456
|
-
const
|
|
66457
|
-
if (!
|
|
66387
|
+
const registryDir = path23.join(os5.homedir(), ".pie-unity", "instances");
|
|
66388
|
+
if (!fs23.existsSync(registryDir)) {
|
|
66458
66389
|
return {
|
|
66459
66390
|
id: "unity_bridge",
|
|
66460
66391
|
label: "Unity bridge",
|
|
66461
66392
|
status: "warn",
|
|
66462
|
-
message: "No pie-unity registry found. This is fine unless you plan to control Unity from Pie.",
|
|
66463
|
-
details: {
|
|
66393
|
+
message: "No pie-unity instance registry directory found. This is fine unless you plan to control Unity from Pie.",
|
|
66394
|
+
details: { registryDir }
|
|
66464
66395
|
};
|
|
66465
66396
|
}
|
|
66466
66397
|
try {
|
|
66467
|
-
const
|
|
66468
|
-
const
|
|
66398
|
+
const nowUnix = Math.floor(Date.now() / 1e3);
|
|
66399
|
+
const files = fs23.readdirSync(registryDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => path23.join(registryDir, entry.name));
|
|
66400
|
+
let malformedFiles = 0;
|
|
66401
|
+
let invalidFiles = 0;
|
|
66402
|
+
const liveInstances = files.map((filePath) => {
|
|
66403
|
+
try {
|
|
66404
|
+
const parsed = JSON.parse(fs23.readFileSync(filePath, "utf8").replace(/^\uFEFF/, ""));
|
|
66405
|
+
if (!isRecord2(parsed)) {
|
|
66406
|
+
invalidFiles += 1;
|
|
66407
|
+
return null;
|
|
66408
|
+
}
|
|
66409
|
+
if (!isLiveUnityInstance(parsed, nowUnix)) {
|
|
66410
|
+
invalidFiles += 1;
|
|
66411
|
+
return null;
|
|
66412
|
+
}
|
|
66413
|
+
return parsed;
|
|
66414
|
+
} catch {
|
|
66415
|
+
malformedFiles += 1;
|
|
66416
|
+
return null;
|
|
66417
|
+
}
|
|
66418
|
+
}).filter((item) => Boolean(item));
|
|
66469
66419
|
return {
|
|
66470
66420
|
id: "unity_bridge",
|
|
66471
66421
|
label: "Unity bridge",
|
|
66472
|
-
status:
|
|
66473
|
-
message:
|
|
66474
|
-
details: {
|
|
66422
|
+
status: liveInstances.length > 0 ? "pass" : "warn",
|
|
66423
|
+
message: liveInstances.length > 0 ? `Found ${liveInstances.length} live pie-unity instance(s).` : "pie-unity instance registry directory exists but has no live readable instances.",
|
|
66424
|
+
details: {
|
|
66425
|
+
registryDir,
|
|
66426
|
+
liveInstances: liveInstances.length,
|
|
66427
|
+
totalFiles: files.length,
|
|
66428
|
+
malformedFiles,
|
|
66429
|
+
invalidOrStaleFiles: invalidFiles
|
|
66430
|
+
}
|
|
66475
66431
|
};
|
|
66476
66432
|
} catch (error) {
|
|
66477
66433
|
return {
|
|
66478
66434
|
id: "unity_bridge",
|
|
66479
66435
|
label: "Unity bridge",
|
|
66480
66436
|
status: "warn",
|
|
66481
|
-
message: `Could not read pie-unity registry: ${error instanceof Error ? error.message : String(error)}`,
|
|
66482
|
-
details: {
|
|
66437
|
+
message: `Could not read pie-unity instance registry directory: ${error instanceof Error ? error.message : String(error)}`,
|
|
66438
|
+
details: { registryDir }
|
|
66483
66439
|
};
|
|
66484
66440
|
}
|
|
66485
66441
|
}
|
|
66442
|
+
function checkPieUnityRpcSkill() {
|
|
66443
|
+
return {
|
|
66444
|
+
id: "pie_unity_rpc_skill",
|
|
66445
|
+
label: "Pie Unity RPC skill",
|
|
66446
|
+
status: "pass",
|
|
66447
|
+
message: "pie-unity-rpc is package-contained. Use the helper from the current Unity project's resolved com.pie.agent package.",
|
|
66448
|
+
details: {
|
|
66449
|
+
lookupOrder: [
|
|
66450
|
+
"Packages/com.pie.agent/Skills/pie-unity-rpc",
|
|
66451
|
+
"Library/PackageCache/com.pie.agent@*/Skills/pie-unity-rpc",
|
|
66452
|
+
"Library/PackageCache/com.pie.agent*/Skills/pie-unity-rpc"
|
|
66453
|
+
]
|
|
66454
|
+
}
|
|
66455
|
+
};
|
|
66456
|
+
}
|
|
66486
66457
|
async function runDoctor() {
|
|
66487
66458
|
const checks = [];
|
|
66488
66459
|
const settings = new SettingsManager();
|
|
@@ -66506,7 +66477,7 @@ async function runDoctor() {
|
|
|
66506
66477
|
let lockPath;
|
|
66507
66478
|
while (dir !== path23.dirname(dir)) {
|
|
66508
66479
|
const candidate = path23.join(dir, "package-lock.json");
|
|
66509
|
-
if (
|
|
66480
|
+
if (fs23.existsSync(candidate)) {
|
|
66510
66481
|
lockPath = candidate;
|
|
66511
66482
|
break;
|
|
66512
66483
|
}
|
|
@@ -66571,6 +66542,26 @@ async function runDoctor() {
|
|
|
66571
66542
|
preferredWebSearchCapability: webSearchCandidates[0]?.model?.webSearch?.type
|
|
66572
66543
|
}
|
|
66573
66544
|
});
|
|
66545
|
+
const webResearchHealth = createCliWebResearchHealthStore(getConfigDir()).loadProviderHealth();
|
|
66546
|
+
checks.push({
|
|
66547
|
+
id: "web_research_health",
|
|
66548
|
+
label: "Web research provider health",
|
|
66549
|
+
status: webResearchHealth.length > 0 ? "pass" : "warn",
|
|
66550
|
+
message: webResearchHealth.length > 0 ? `Loaded health for ${webResearchHealth.length} web research route(s).` : "No web research provider health has been recorded yet. Run verify:web or use web_research once to populate route quality data.",
|
|
66551
|
+
details: {
|
|
66552
|
+
routes: webResearchHealth.slice(0, 8).map((entry) => ({
|
|
66553
|
+
routeKey: entry.routeKey,
|
|
66554
|
+
attempts: entry.attempts,
|
|
66555
|
+
successRate: entry.attempts ? entry.successes / entry.attempts : 0,
|
|
66556
|
+
lowQualityRate: entry.attempts ? entry.lowQuality / entry.attempts : 0,
|
|
66557
|
+
rateLimited: entry.rateLimited,
|
|
66558
|
+
timeouts: entry.timeouts,
|
|
66559
|
+
averageLatencyMs: entry.attempts ? Math.round(entry.totalDurationMs / entry.attempts) : 0,
|
|
66560
|
+
averageSourceCount: entry.attempts ? entry.totalSources / entry.attempts : 0,
|
|
66561
|
+
updatedAt: entry.updatedAt
|
|
66562
|
+
}))
|
|
66563
|
+
}
|
|
66564
|
+
});
|
|
66574
66565
|
checks.push({
|
|
66575
66566
|
id: "tool_model_routes",
|
|
66576
66567
|
label: "Tool model routes",
|
|
@@ -66596,6 +66587,7 @@ async function runDoctor() {
|
|
|
66596
66587
|
checks.push(checkPlaywrightCli());
|
|
66597
66588
|
checks.push(checkPlaywrightBrowser());
|
|
66598
66589
|
checks.push(checkUnityRegistry());
|
|
66590
|
+
checks.push(checkPieUnityRpcSkill());
|
|
66599
66591
|
const runtimeLog = getRuntimeLogPath();
|
|
66600
66592
|
checks.push({
|
|
66601
66593
|
id: "runtime_log",
|
|
@@ -66652,7 +66644,7 @@ Disable or narrow capabilities:
|
|
|
66652
66644
|
}
|
|
66653
66645
|
|
|
66654
66646
|
// src/commands/models-config.ts
|
|
66655
|
-
import * as
|
|
66647
|
+
import * as fs24 from "node:fs";
|
|
66656
66648
|
import * as path24 from "node:path";
|
|
66657
66649
|
function getDefaultModelsPath() {
|
|
66658
66650
|
return path24.join(getConfigDir(), "models.json");
|
|
@@ -66758,16 +66750,16 @@ function initModelsConfig(options = {}) {
|
|
|
66758
66750
|
if (options.stdout) {
|
|
66759
66751
|
return { path: targetPath, content, wrote: false };
|
|
66760
66752
|
}
|
|
66761
|
-
if (
|
|
66753
|
+
if (fs24.existsSync(targetPath) && !options.force) {
|
|
66762
66754
|
throw new Error(`models.json already exists: ${targetPath}. Use --force to overwrite, or --stdout to print the template.`);
|
|
66763
66755
|
}
|
|
66764
|
-
|
|
66765
|
-
|
|
66756
|
+
fs24.mkdirSync(path24.dirname(targetPath), { recursive: true });
|
|
66757
|
+
fs24.writeFileSync(targetPath, content, "utf8");
|
|
66766
66758
|
return { path: targetPath, content, wrote: true };
|
|
66767
66759
|
}
|
|
66768
66760
|
function validateModelsConfig(options = {}) {
|
|
66769
66761
|
const modelsPath = resolveModelsPath(options.path);
|
|
66770
|
-
if (!
|
|
66762
|
+
if (!fs24.existsSync(modelsPath)) {
|
|
66771
66763
|
return {
|
|
66772
66764
|
ok: false,
|
|
66773
66765
|
path: modelsPath,
|
|
@@ -66822,6 +66814,73 @@ function validateModelsConfig(options = {}) {
|
|
|
66822
66814
|
toolModelRoutes
|
|
66823
66815
|
};
|
|
66824
66816
|
}
|
|
66817
|
+
async function probeModelsConfig(options) {
|
|
66818
|
+
const registry = new ModelRegistry(new AuthStorage(), resolveModelsPath(options.path));
|
|
66819
|
+
const loadError = registry.getLoadError();
|
|
66820
|
+
if (loadError) {
|
|
66821
|
+
return {
|
|
66822
|
+
purpose: options.probe,
|
|
66823
|
+
status: "failed",
|
|
66824
|
+
attempts: [],
|
|
66825
|
+
message: `Cannot probe invalid models.json: ${loadError}`
|
|
66826
|
+
};
|
|
66827
|
+
}
|
|
66828
|
+
if (options.probe !== "web_search") {
|
|
66829
|
+
return {
|
|
66830
|
+
purpose: options.probe,
|
|
66831
|
+
status: "skipped",
|
|
66832
|
+
attempts: [],
|
|
66833
|
+
message: `Unsupported probe: ${options.probe}`
|
|
66834
|
+
};
|
|
66835
|
+
}
|
|
66836
|
+
const candidates = registry.resolveToolModelCandidates("web_search").filter((route) => route.model);
|
|
66837
|
+
if (candidates.length === 0) {
|
|
66838
|
+
return {
|
|
66839
|
+
purpose: options.probe,
|
|
66840
|
+
status: "failed",
|
|
66841
|
+
attempts: [],
|
|
66842
|
+
message: "No configured model declares webSearch capability."
|
|
66843
|
+
};
|
|
66844
|
+
}
|
|
66845
|
+
const attempts = [];
|
|
66846
|
+
for (const candidate of candidates.slice(0, 3)) {
|
|
66847
|
+
const route = `${candidate.model?.provider}/${candidate.model?.id}:${candidate.model?.webSearch?.type}:${candidate.routeSource}`;
|
|
66848
|
+
const tool = createSharedWebSearchTool({
|
|
66849
|
+
getModel: () => candidate.model,
|
|
66850
|
+
getApiKey: () => candidate.apiKey,
|
|
66851
|
+
getMode: () => "live",
|
|
66852
|
+
resolveToolModelCandidates: () => [candidate]
|
|
66853
|
+
});
|
|
66854
|
+
try {
|
|
66855
|
+
const result = await tool.execute("models_probe_web_search", { query: "Pie web search capability probe current official source" });
|
|
66856
|
+
const details = result.details;
|
|
66857
|
+
attempts.push({
|
|
66858
|
+
route,
|
|
66859
|
+
status: result.isError ? "failed" : "passed",
|
|
66860
|
+
sourceCount: Number(details?.sourceCount || 0),
|
|
66861
|
+
failureCategory: details?.failureCategory,
|
|
66862
|
+
durationSeconds: details?.durationSeconds,
|
|
66863
|
+
message: result.content.find((item) => item.type === "text")?.text?.slice(0, 240)
|
|
66864
|
+
});
|
|
66865
|
+
if (!result.isError && Number(details?.sourceCount || 0) > 0) break;
|
|
66866
|
+
} catch (error) {
|
|
66867
|
+
attempts.push({
|
|
66868
|
+
route,
|
|
66869
|
+
status: "failed",
|
|
66870
|
+
sourceCount: 0,
|
|
66871
|
+
failureCategory: "provider_compat",
|
|
66872
|
+
message: error instanceof Error ? error.message : String(error)
|
|
66873
|
+
});
|
|
66874
|
+
}
|
|
66875
|
+
}
|
|
66876
|
+
const passed = attempts.some((attempt) => attempt.status === "passed" && attempt.sourceCount > 0);
|
|
66877
|
+
return {
|
|
66878
|
+
purpose: options.probe,
|
|
66879
|
+
status: passed ? "passed" : "failed",
|
|
66880
|
+
attempts,
|
|
66881
|
+
message: passed ? `web_search probe passed using ${attempts.find((attempt) => attempt.status === "passed")?.route}.` : "web_search probe failed for all configured candidate routes."
|
|
66882
|
+
};
|
|
66883
|
+
}
|
|
66825
66884
|
function parseModelsCommandArgs(args) {
|
|
66826
66885
|
const parsed = { force: false, stdout: false };
|
|
66827
66886
|
for (let i = 0; i < args.length; i += 1) {
|
|
@@ -66830,6 +66889,12 @@ function parseModelsCommandArgs(args) {
|
|
|
66830
66889
|
parsed.force = true;
|
|
66831
66890
|
} else if (arg === "--stdout") {
|
|
66832
66891
|
parsed.stdout = true;
|
|
66892
|
+
} else if (arg === "--probe" && args[i + 1]) {
|
|
66893
|
+
parsed.probe = args[i + 1] === "web_search" ? "web_search" : void 0;
|
|
66894
|
+
i += 1;
|
|
66895
|
+
} else if (arg.startsWith("--probe=")) {
|
|
66896
|
+
const value = arg.slice("--probe=".length);
|
|
66897
|
+
parsed.probe = value === "web_search" ? "web_search" : void 0;
|
|
66833
66898
|
} else if (arg === "--path" && args[i + 1]) {
|
|
66834
66899
|
parsed.path = args[i + 1];
|
|
66835
66900
|
i += 1;
|
|
@@ -66846,8 +66911,8 @@ var logError = (msg, err) => {
|
|
|
66846
66911
|
const logPath = getRuntimeLogPath();
|
|
66847
66912
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
66848
66913
|
const stack = err instanceof Error ? err.stack || "" : "";
|
|
66849
|
-
|
|
66850
|
-
|
|
66914
|
+
fs25.mkdirSync(path25.dirname(logPath), { recursive: true });
|
|
66915
|
+
fs25.appendFileSync(logPath, `[${timestamp}] ${msg}
|
|
66851
66916
|
${stack}
|
|
66852
66917
|
|
|
66853
66918
|
`);
|
|
@@ -66860,8 +66925,8 @@ var SKILLS_DIR = path25.join(CONFIG_DIR, "skills");
|
|
|
66860
66925
|
var BUILTIN_DIR = getBuiltinDir();
|
|
66861
66926
|
var BUILTIN_SKILLS_DIR = path25.join(BUILTIN_DIR, "skills");
|
|
66862
66927
|
var BUILTIN_EXTENSIONS_DIR = path25.join(BUILTIN_DIR, "extensions");
|
|
66863
|
-
if (!
|
|
66864
|
-
|
|
66928
|
+
if (!existsSync17(SKILLS_DIR)) {
|
|
66929
|
+
mkdirSync11(SKILLS_DIR, { recursive: true });
|
|
66865
66930
|
}
|
|
66866
66931
|
function maskApiKey2(key) {
|
|
66867
66932
|
if (key.length <= 6) return "***";
|
|
@@ -66916,7 +66981,7 @@ async function runDoctorCommand(args) {
|
|
|
66916
66981
|
process.exitCode = 1;
|
|
66917
66982
|
}
|
|
66918
66983
|
}
|
|
66919
|
-
function runModelsCommand(args) {
|
|
66984
|
+
async function runModelsCommand(args) {
|
|
66920
66985
|
const subcommand = args[0] || "help";
|
|
66921
66986
|
const parsed = parseModelsCommandArgs(args.slice(1));
|
|
66922
66987
|
if (subcommand === "init") {
|
|
@@ -66958,11 +67023,19 @@ function runModelsCommand(args) {
|
|
|
66958
67023
|
if (result.toolModelRoutes && result.toolModelRoutes.length > 0) {
|
|
66959
67024
|
console.log(`Tool model routes: ${result.toolModelRoutes.join(", ")}`);
|
|
66960
67025
|
}
|
|
67026
|
+
if (parsed.probe) {
|
|
67027
|
+
const probe = await probeModelsConfig({ path: parsed.path, probe: parsed.probe });
|
|
67028
|
+
console.log(`Probe ${probe.purpose}: ${probe.message}`);
|
|
67029
|
+
for (const attempt of probe.attempts) {
|
|
67030
|
+
console.log(`- ${attempt.status} ${attempt.route} sources=${attempt.sourceCount}${attempt.failureCategory ? ` failure=${attempt.failureCategory}` : ""}`);
|
|
67031
|
+
}
|
|
67032
|
+
if (probe.status === "failed") process.exitCode = 1;
|
|
67033
|
+
}
|
|
66961
67034
|
return;
|
|
66962
67035
|
}
|
|
66963
67036
|
console.log(`Usage:
|
|
66964
67037
|
pie models init [--path <path>] [--force] [--stdout]
|
|
66965
|
-
pie models validate [--path <path>]`);
|
|
67038
|
+
pie models validate [--path <path>] [--probe web_search]`);
|
|
66966
67039
|
}
|
|
66967
67040
|
function createNoOpExtensionUIContext() {
|
|
66968
67041
|
return {
|
|
@@ -67174,24 +67247,19 @@ async function startChat(initialPrompt, testCommand) {
|
|
|
67174
67247
|
getApiKey: () => interactiveOptions?.apiKey ?? apiKey,
|
|
67175
67248
|
getWebSearchMode: () => settingsManager.getWebSearchMode(),
|
|
67176
67249
|
resolveToolModel: (purpose) => modelRegistry.resolveToolModel(purpose, interactiveOptions?.model ?? model),
|
|
67177
|
-
resolveToolModelCandidates: (purpose) => modelRegistry.resolveToolModelCandidates(purpose, interactiveOptions?.model ?? model)
|
|
67250
|
+
resolveToolModelCandidates: (purpose) => modelRegistry.resolveToolModelCandidates(purpose, interactiveOptions?.model ?? model),
|
|
67251
|
+
configDir: CONFIG_DIR
|
|
67178
67252
|
});
|
|
67179
67253
|
const fileSystemToolOptions = {
|
|
67180
|
-
allowlistedDirs: [CONFIG_DIR],
|
|
67254
|
+
...buildCliFileAccessOptions({ cwd, configDir: CONFIG_DIR, skills, allowlistedDirs: [CONFIG_DIR] }),
|
|
67181
67255
|
configDir: CONFIG_DIR,
|
|
67182
67256
|
getAgentModel: () => interactiveOptions?.model ?? model,
|
|
67183
67257
|
getSessionId: () => sessionManager.getActiveSessionId() || void 0,
|
|
67184
67258
|
resolveToolModel: (purpose) => modelRegistry.resolveToolModel(purpose, interactiveOptions?.model ?? model),
|
|
67185
67259
|
getPolicyContext: () => ({ mode: "normal", confirmationPolicy: "allow" })
|
|
67186
67260
|
};
|
|
67187
|
-
const readSkillTool = createCliReadSkillTool(skills);
|
|
67188
|
-
const readResourceTool = createCliReadResourceTool(skills);
|
|
67189
|
-
const resolveResourceTool = createCliResolveResourceTool(skills);
|
|
67190
67261
|
const tools = createPolicyEnforcedTools([
|
|
67191
67262
|
...createCliFileSystemTools(cwd, fileSystemToolOptions),
|
|
67192
|
-
readSkillTool,
|
|
67193
|
-
readResourceTool,
|
|
67194
|
-
resolveResourceTool,
|
|
67195
67263
|
...cliHostCapabilities.tools
|
|
67196
67264
|
], {
|
|
67197
67265
|
getContext: () => ({ mode: "normal", confirmationPolicy: "allow" })
|
|
@@ -67201,7 +67269,7 @@ async function startChat(initialPrompt, testCommand) {
|
|
|
67201
67269
|
console.log(`[CLI] ${diag.message}`);
|
|
67202
67270
|
}
|
|
67203
67271
|
const skillsSection = formatSkillsForPrompt(skills);
|
|
67204
|
-
const knowledgeSection =
|
|
67272
|
+
const knowledgeSection = buildCliProjectContextSection(cwd);
|
|
67205
67273
|
if (initialPrompt) {
|
|
67206
67274
|
if (initialModel.unconfigured) {
|
|
67207
67275
|
const errorText = initialModel.warning || "No models are configured. Add one in ~/.pie/models.json before sending messages.";
|
|
@@ -67353,9 +67421,9 @@ async function startChat(initialPrompt, testCommand) {
|
|
|
67353
67421
|
flushEarlyLogs();
|
|
67354
67422
|
if (testCommand) {
|
|
67355
67423
|
console.log(`[TEST] Auto-executing command: ${testCommand}`);
|
|
67356
|
-
await new Promise((
|
|
67424
|
+
await new Promise((resolve4) => setTimeout(resolve4, 500));
|
|
67357
67425
|
await interactive.executeCommand(testCommand);
|
|
67358
|
-
await new Promise((
|
|
67426
|
+
await new Promise((resolve4) => setTimeout(resolve4, 2e3));
|
|
67359
67427
|
console.log("[TEST] Command executed, exiting...");
|
|
67360
67428
|
process.exit(0);
|
|
67361
67429
|
return;
|
|
@@ -67378,7 +67446,7 @@ async function main() {
|
|
|
67378
67446
|
}
|
|
67379
67447
|
if (args[0] === "models") {
|
|
67380
67448
|
try {
|
|
67381
|
-
runModelsCommand(args.slice(1));
|
|
67449
|
+
await runModelsCommand(args.slice(1));
|
|
67382
67450
|
} catch (error) {
|
|
67383
67451
|
console.error(error instanceof Error ? error.message : String(error));
|
|
67384
67452
|
process.exitCode = 1;
|