@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@d3ara1n/pi-scout",
3
- "version": "1.1.0",
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
- const envDir = process.env.PI_AGENT_DIR;
16
- if (envDir) return envDir;
17
- return path.join(os.homedir(), ".pi", "agent");
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
- try {
22
- if (!fs.existsSync(filePath)) return {};
23
- const content = fs.readFileSync(filePath, "utf-8");
24
- return JSON.parse(content);
25
- } catch {
26
- return {};
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
- function merge(target: any, source: any): any {
31
- if (!source || typeof source !== "object") return target;
32
- if (!target || typeof target !== "object") return source;
33
- const result = { ...target };
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 from merged settings.
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
- const globalSettings = readSettingsFile(path.join(getAgentDir(), "settings.json"));
50
- const projectSettings = cwd
51
- ? readSettingsFile(path.join(cwd, ".pi", "settings.json"))
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
- const raw = settings?.scout;
56
- if (!raw) return DEFAULT_CONFIG;
57
-
58
- return {
59
- enabled: raw.enabled ?? DEFAULT_CONFIG.enabled,
60
- sideAgentRole: raw.sideAgentRole ?? DEFAULT_CONFIG.sideAgentRole,
61
- maxSelectedSkills: raw.maxSelectedSkills ?? DEFAULT_CONFIG.maxSelectedSkills,
62
- modules: {
63
- skillRouter: raw.modules?.skillRouter ?? DEFAULT_CONFIG.modules.skillRouter,
64
- modelRouter: raw.modules?.modelRouter ?? DEFAULT_CONFIG.modules.modelRouter,
65
- shortCircuit: raw.modules?.shortCircuit ?? DEFAULT_CONFIG.modules.shortCircuit,
66
- },
67
- shortCircuit: {
68
- trivialAck: raw.shortCircuit?.trivialAck ?? DEFAULT_CONFIG.shortCircuit.trivialAck,
69
- maxAckLength: raw.shortCircuit?.maxAckLength ?? DEFAULT_CONFIG.shortCircuit.maxAckLength,
70
- ackPhrases: Array.isArray(raw.shortCircuit?.ackPhrases)
71
- ? raw.shortCircuit.ackPhrases.filter((p: any) => typeof p === "string")
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
  }