@d3ara1n/pi-scout 1.1.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/config.ts +36 -48
- package/src/index.ts +331 -320
- package/src/model-switch.ts +17 -17
- package/src/scout-prompt.ts +64 -60
- package/src/short-circuit.test.ts +46 -59
- package/src/short-circuit.ts +105 -37
- package/src/side-agent.ts +65 -66
- package/src/skill-inject.ts +41 -38
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@d3ara1n/pi-scout",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Per-turn side agent decision framework for pi — uses a cheap model to select skills and route models before each conversation turn",
|
|
6
6
|
"main": "src/index.ts",
|
package/src/config.ts
CHANGED
|
@@ -12,64 +12,52 @@ import type { ScoutConfig } from "./types.ts";
|
|
|
12
12
|
import { DEFAULT_CONFIG } from "./types.ts";
|
|
13
13
|
|
|
14
14
|
function getAgentDir(): string {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
const envDir = process.env.PI_AGENT_DIR;
|
|
16
|
+
if (envDir) return envDir;
|
|
17
|
+
return path.join(os.homedir(), ".pi", "agent");
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
function readSettingsFile(filePath: string): any {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
21
|
+
try {
|
|
22
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
23
|
+
return JSON.parse(content);
|
|
24
|
+
} catch {
|
|
25
|
+
return {};
|
|
26
|
+
}
|
|
28
27
|
}
|
|
29
28
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
for (const key of Object.keys(source)) {
|
|
35
|
-
if (source[key] && typeof source[key] === "object" && !Array.isArray(source[key])) {
|
|
36
|
-
result[key] = merge(result[key], source[key]);
|
|
37
|
-
} else {
|
|
38
|
-
result[key] = source[key];
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
return result;
|
|
29
|
+
/** Read the `scout` block from a settings file. */
|
|
30
|
+
function readScout(filePath: string): Record<string, any> | undefined {
|
|
31
|
+
const raw = readSettingsFile(filePath)?.scout;
|
|
32
|
+
return raw && typeof raw === "object" ? raw : undefined;
|
|
42
33
|
}
|
|
43
34
|
|
|
44
35
|
/**
|
|
45
|
-
* Load scout config
|
|
36
|
+
* Load scout config. Project overrides global wholesale; per-field `??
|
|
37
|
+
* DEFAULT` fills any gap. (No field-level merge — project replaces global.)
|
|
46
38
|
* @param cwd - Project working directory
|
|
47
39
|
*/
|
|
48
40
|
export function loadScoutConfig(cwd?: string): ScoutConfig {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const settings = merge(globalSettings, projectSettings);
|
|
41
|
+
const globalRaw = readScout(path.join(getAgentDir(), "settings.json"));
|
|
42
|
+
const projectRaw = cwd ? readScout(path.join(cwd, ".pi", "settings.json")) : undefined;
|
|
43
|
+
const raw = projectRaw ?? globalRaw;
|
|
44
|
+
if (!raw) return DEFAULT_CONFIG;
|
|
54
45
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
: DEFAULT_CONFIG.shortCircuit.ackPhrases,
|
|
73
|
-
},
|
|
74
|
-
};
|
|
46
|
+
return {
|
|
47
|
+
enabled: raw.enabled ?? DEFAULT_CONFIG.enabled,
|
|
48
|
+
sideAgentRole: raw.sideAgentRole ?? DEFAULT_CONFIG.sideAgentRole,
|
|
49
|
+
maxSelectedSkills: raw.maxSelectedSkills ?? DEFAULT_CONFIG.maxSelectedSkills,
|
|
50
|
+
modules: {
|
|
51
|
+
skillRouter: raw.modules?.skillRouter ?? DEFAULT_CONFIG.modules.skillRouter,
|
|
52
|
+
modelRouter: raw.modules?.modelRouter ?? DEFAULT_CONFIG.modules.modelRouter,
|
|
53
|
+
shortCircuit: raw.modules?.shortCircuit ?? DEFAULT_CONFIG.modules.shortCircuit,
|
|
54
|
+
},
|
|
55
|
+
shortCircuit: {
|
|
56
|
+
trivialAck: raw.shortCircuit?.trivialAck ?? DEFAULT_CONFIG.shortCircuit.trivialAck,
|
|
57
|
+
maxAckLength: raw.shortCircuit?.maxAckLength ?? DEFAULT_CONFIG.shortCircuit.maxAckLength,
|
|
58
|
+
ackPhrases: Array.isArray(raw.shortCircuit?.ackPhrases)
|
|
59
|
+
? raw.shortCircuit.ackPhrases.filter((p: any) => typeof p === "string")
|
|
60
|
+
: DEFAULT_CONFIG.shortCircuit.ackPhrases,
|
|
61
|
+
},
|
|
62
|
+
};
|
|
75
63
|
}
|