looply-cli 0.5.3 → 0.5.5

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.
Files changed (122) hide show
  1. package/dist/.src-hash +1 -1
  2. package/dist/agent-exec.d.ts +10 -5
  3. package/dist/agent-exec.d.ts.map +1 -1
  4. package/dist/agent-exec.js.map +1 -1
  5. package/dist/autonomy-controller.d.ts +14 -1
  6. package/dist/autonomy-controller.d.ts.map +1 -1
  7. package/dist/autonomy-controller.js +55 -2
  8. package/dist/autonomy-controller.js.map +1 -1
  9. package/dist/autonomy-store.d.ts +35 -2
  10. package/dist/autonomy-store.d.ts.map +1 -1
  11. package/dist/autonomy-store.js +27 -2
  12. package/dist/autonomy-store.js.map +1 -1
  13. package/dist/autonomy-tick.d.ts +25 -2
  14. package/dist/autonomy-tick.d.ts.map +1 -1
  15. package/dist/autonomy-tick.js +145 -4
  16. package/dist/autonomy-tick.js.map +1 -1
  17. package/dist/bin.d.ts.map +1 -1
  18. package/dist/bin.js +112 -82
  19. package/dist/bin.js.map +1 -1
  20. package/dist/checkout-carry.d.ts.map +1 -1
  21. package/dist/checkout-carry.js +12 -0
  22. package/dist/checkout-carry.js.map +1 -1
  23. package/dist/config.d.ts +41 -0
  24. package/dist/config.d.ts.map +1 -1
  25. package/dist/config.js +64 -8
  26. package/dist/config.js.map +1 -1
  27. package/dist/coordinator-state.d.ts +14 -0
  28. package/dist/coordinator-state.d.ts.map +1 -1
  29. package/dist/coordinator-state.js +29 -0
  30. package/dist/coordinator-state.js.map +1 -1
  31. package/dist/daemon-cmd.d.ts +1 -1
  32. package/dist/daemon-cmd.d.ts.map +1 -1
  33. package/dist/daemon-cmd.js +69 -33
  34. package/dist/daemon-cmd.js.map +1 -1
  35. package/dist/daemon.d.ts +15 -1
  36. package/dist/daemon.d.ts.map +1 -1
  37. package/dist/daemon.js +21 -3
  38. package/dist/daemon.js.map +1 -1
  39. package/dist/git-driver.d.ts +6 -0
  40. package/dist/git-driver.d.ts.map +1 -1
  41. package/dist/git-driver.js +12 -0
  42. package/dist/git-driver.js.map +1 -1
  43. package/dist/index-for-head.js +1 -1
  44. package/dist/index-for-head.js.map +1 -1
  45. package/dist/init-detect.d.ts.map +1 -1
  46. package/dist/init-detect.js +1 -1
  47. package/dist/init-detect.js.map +1 -1
  48. package/dist/machine-run-slots.d.ts +59 -0
  49. package/dist/machine-run-slots.d.ts.map +1 -0
  50. package/dist/machine-run-slots.js +140 -0
  51. package/dist/machine-run-slots.js.map +1 -0
  52. package/dist/model-routing.d.ts +52 -7
  53. package/dist/model-routing.d.ts.map +1 -1
  54. package/dist/model-routing.js +84 -14
  55. package/dist/model-routing.js.map +1 -1
  56. package/dist/model-settings.d.ts +67 -0
  57. package/dist/model-settings.d.ts.map +1 -0
  58. package/dist/model-settings.js +177 -0
  59. package/dist/model-settings.js.map +1 -0
  60. package/dist/model-transport.d.ts +8 -0
  61. package/dist/model-transport.d.ts.map +1 -1
  62. package/dist/model-transport.js +6 -3
  63. package/dist/model-transport.js.map +1 -1
  64. package/dist/programme-mode.d.ts +6 -0
  65. package/dist/programme-mode.d.ts.map +1 -1
  66. package/dist/programme-mode.js +23 -0
  67. package/dist/programme-mode.js.map +1 -1
  68. package/dist/project-index-store.d.ts +19 -1
  69. package/dist/project-index-store.d.ts.map +1 -1
  70. package/dist/project-index-store.js +40 -5
  71. package/dist/project-index-store.js.map +1 -1
  72. package/dist/project-terminal.d.ts +25 -0
  73. package/dist/project-terminal.d.ts.map +1 -0
  74. package/dist/project-terminal.js +46 -0
  75. package/dist/project-terminal.js.map +1 -0
  76. package/dist/provider-cmd.d.ts +13 -4
  77. package/dist/provider-cmd.d.ts.map +1 -1
  78. package/dist/provider-cmd.js +111 -11
  79. package/dist/provider-cmd.js.map +1 -1
  80. package/dist/provider-ready.d.ts +15 -2
  81. package/dist/provider-ready.d.ts.map +1 -1
  82. package/dist/provider-ready.js +46 -2
  83. package/dist/provider-ready.js.map +1 -1
  84. package/dist/providers.d.ts.map +1 -1
  85. package/dist/providers.js +4 -0
  86. package/dist/providers.js.map +1 -1
  87. package/dist/pursuit-ending.d.ts +57 -0
  88. package/dist/pursuit-ending.d.ts.map +1 -0
  89. package/dist/pursuit-ending.js +128 -0
  90. package/dist/pursuit-ending.js.map +1 -0
  91. package/dist/run-base.d.ts +84 -0
  92. package/dist/run-base.d.ts.map +1 -0
  93. package/dist/run-base.js +142 -0
  94. package/dist/run-base.js.map +1 -0
  95. package/dist/run-cmd.d.ts.map +1 -1
  96. package/dist/run-cmd.js +46 -5
  97. package/dist/run-cmd.js.map +1 -1
  98. package/dist/run-ended.d.ts +16 -0
  99. package/dist/run-ended.d.ts.map +1 -1
  100. package/dist/run-ended.js +30 -0
  101. package/dist/run-ended.js.map +1 -1
  102. package/dist/run-ending-locator.d.ts +10 -0
  103. package/dist/run-ending-locator.d.ts.map +1 -1
  104. package/dist/run-ending-locator.js +45 -0
  105. package/dist/run-ending-locator.js.map +1 -1
  106. package/dist/run-launcher.d.ts +30 -1
  107. package/dist/run-launcher.d.ts.map +1 -1
  108. package/dist/run-launcher.js +60 -2
  109. package/dist/run-launcher.js.map +1 -1
  110. package/dist/server-client.d.ts +16 -2
  111. package/dist/server-client.d.ts.map +1 -1
  112. package/dist/server-client.js +9 -0
  113. package/dist/server-client.js.map +1 -1
  114. package/dist/setup.d.ts.map +1 -1
  115. package/dist/setup.js +17 -0
  116. package/dist/setup.js.map +1 -1
  117. package/dist/workspace-provisioner.d.ts +2 -0
  118. package/dist/workspace-provisioner.d.ts.map +1 -1
  119. package/dist/workspace-provisioner.js +27 -1
  120. package/dist/workspace-provisioner.js.map +1 -1
  121. package/package.json +54 -54
  122. package/win/HandleProbe.cs +116 -116
@@ -1 +1 @@
1
- {"version":3,"file":"init-detect.js","sourceRoot":"","sources":["../src/init-detect.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"init-detect.js","sourceRoot":"","sources":["../src/init-detect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import { type ProbeFn } from './run-lease';
2
+ /**
3
+ * HOW MANY AUTONOMOUS RUNS THIS COMPUTER HAS, ACROSS EVERY REPOSITORY IT SERVES.
4
+ *
5
+ * `looply serve` runs one daemon per repository, and each daemon's coordinator
6
+ * bounds only its own project (`machine.max_parallel_runs`). A PC serving 27
7
+ * repositories at 3 each could otherwise launch 81 agent sessions at once. This
8
+ * is the one number they share: `machine.max_runs_on_machine` (default 4).
9
+ *
10
+ * ─────────────────────────────────────────────────────────────────────────────
11
+ * ONE FILE PER SLOT, IN `~/.looply/machine-runs/`.
12
+ *
13
+ * A slot is CLAIMED before a launch (pending, holding the daemon's pid) and
14
+ * BOUND to the child's pid once it is spawned. A slot frees itself: a bound
15
+ * slot whose pid is dead, or a pending slot older than `PENDING_TTL_MS`, is not
16
+ * counted and is swept on the next claim. Nothing has to remember to release,
17
+ * so a crashed run or daemon cannot leak capacity for longer than one probe.
18
+ *
19
+ * Claims are serialised by the shared exclusive lock, so two daemons cannot
20
+ * both see the last free slot and both take it.
21
+ *
22
+ * ⚠️ A CLAIM IS ASKED BEFORE A TRY IS SPENT. The launcher's `busyFor` takes it
23
+ * (see `run-launcher.ts`), and `busyFor` runs before `reserveLaunch` in the
24
+ * tick, so "the machine is full" is a queue — never a failed attempt. A claim
25
+ * is idempotent per request: asking again for the same request refreshes it.
26
+ *
27
+ * ⚠️ AN UNKNOWN LIVENESS COUNTS AS ALIVE, the direction that cannot overshoot.
28
+ */
29
+ /** A claim that never became a run stops holding a slot after this. */
30
+ export declare const PENDING_TTL_MS: number;
31
+ export interface MachineSlot {
32
+ readonly key: string;
33
+ readonly pid: number;
34
+ readonly pending: boolean;
35
+ readonly at: string;
36
+ /** Which repository the run is for — for a person reading the directory. */
37
+ readonly repo?: string;
38
+ }
39
+ export interface MachineRunSlots {
40
+ /** Take (or refresh) a slot for `key`; null when taken, else why the machine is full. */
41
+ claim(key: string): string | null;
42
+ /** The launch happened: the slot now lives as long as `pid` does. */
43
+ bind(key: string, pid: number): void;
44
+ /** The launch did not happen. */
45
+ release(key: string): void;
46
+ /** Live slots right now, `key` excluded when given. */
47
+ inUse(except?: string): number;
48
+ readonly cap: number;
49
+ }
50
+ export interface MachineRunSlotDeps {
51
+ readonly home?: string;
52
+ readonly now?: () => number;
53
+ readonly probe?: ProbeFn;
54
+ readonly pid?: number;
55
+ readonly repo?: string;
56
+ }
57
+ export declare function machineSlotsDir(home?: string): string;
58
+ export declare function machineRunSlots(cap: number, deps?: MachineRunSlotDeps): MachineRunSlots;
59
+ //# sourceMappingURL=machine-run-slots.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"machine-run-slots.d.ts","sourceRoot":"","sources":["../src/machine-run-slots.ts"],"names":[],"mappings":"AAKA,OAAO,EAAa,KAAK,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,uEAAuE;AACvE,eAAO,MAAM,cAAc,QAAa,CAAC;AAEzC,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,yFAAyF;IACzF,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAClC,qEAAqE;IACrE,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,iCAAiC;IACjC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,uDAAuD;IACvD,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,eAAe,CAAC,IAAI,GAAE,MAAkB,GAAG,MAAM,CAEhE;AAID,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,kBAAuB,GAAG,eAAe,CA8F3F"}
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PENDING_TTL_MS = void 0;
4
+ exports.machineSlotsDir = machineSlotsDir;
5
+ exports.machineRunSlots = machineRunSlots;
6
+ const node_crypto_1 = require("node:crypto");
7
+ const node_fs_1 = require("node:fs");
8
+ const node_os_1 = require("node:os");
9
+ const node_path_1 = require("node:path");
10
+ const exclusive_lock_1 = require("./exclusive-lock");
11
+ const run_lease_1 = require("./run-lease");
12
+ /**
13
+ * HOW MANY AUTONOMOUS RUNS THIS COMPUTER HAS, ACROSS EVERY REPOSITORY IT SERVES.
14
+ *
15
+ * `looply serve` runs one daemon per repository, and each daemon's coordinator
16
+ * bounds only its own project (`machine.max_parallel_runs`). A PC serving 27
17
+ * repositories at 3 each could otherwise launch 81 agent sessions at once. This
18
+ * is the one number they share: `machine.max_runs_on_machine` (default 4).
19
+ *
20
+ * ─────────────────────────────────────────────────────────────────────────────
21
+ * ONE FILE PER SLOT, IN `~/.looply/machine-runs/`.
22
+ *
23
+ * A slot is CLAIMED before a launch (pending, holding the daemon's pid) and
24
+ * BOUND to the child's pid once it is spawned. A slot frees itself: a bound
25
+ * slot whose pid is dead, or a pending slot older than `PENDING_TTL_MS`, is not
26
+ * counted and is swept on the next claim. Nothing has to remember to release,
27
+ * so a crashed run or daemon cannot leak capacity for longer than one probe.
28
+ *
29
+ * Claims are serialised by the shared exclusive lock, so two daemons cannot
30
+ * both see the last free slot and both take it.
31
+ *
32
+ * ⚠️ A CLAIM IS ASKED BEFORE A TRY IS SPENT. The launcher's `busyFor` takes it
33
+ * (see `run-launcher.ts`), and `busyFor` runs before `reserveLaunch` in the
34
+ * tick, so "the machine is full" is a queue — never a failed attempt. A claim
35
+ * is idempotent per request: asking again for the same request refreshes it.
36
+ *
37
+ * ⚠️ AN UNKNOWN LIVENESS COUNTS AS ALIVE, the direction that cannot overshoot.
38
+ */
39
+ /** A claim that never became a run stops holding a slot after this. */
40
+ exports.PENDING_TTL_MS = 3 * 60_000;
41
+ function machineSlotsDir(home = (0, node_os_1.homedir)()) {
42
+ return (0, node_path_1.join)(home, '.looply', 'machine-runs');
43
+ }
44
+ const fileOf = (key) => `${(0, node_crypto_1.createHash)('sha256').update(key).digest('hex').slice(0, 32)}.json`;
45
+ function machineRunSlots(cap, deps = {}) {
46
+ const dir = machineSlotsDir(deps.home);
47
+ const now = deps.now ?? (() => Date.now());
48
+ const probe = deps.probe ?? run_lease_1.nodeProbe;
49
+ const me = deps.pid ?? process.pid;
50
+ const limit = Math.max(1, Math.floor(cap));
51
+ const read = () => {
52
+ let names;
53
+ try {
54
+ names = (0, node_fs_1.readdirSync)(dir).filter((n) => n.endsWith('.json'));
55
+ }
56
+ catch {
57
+ return [];
58
+ }
59
+ const out = [];
60
+ for (const file of names) {
61
+ try {
62
+ const raw = JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(dir, file), 'utf8'));
63
+ if (typeof raw.key !== 'string' || typeof raw.pid !== 'number' || typeof raw.at !== 'string')
64
+ continue;
65
+ out.push({ file, slot: { key: raw.key, pid: raw.pid, pending: raw.pending === true, at: raw.at, ...(raw.repo === undefined ? {} : { repo: raw.repo }) } });
66
+ }
67
+ catch {
68
+ // A torn write is not a run. The claim that wrote it rewrites it.
69
+ }
70
+ }
71
+ return out;
72
+ };
73
+ const live = (s) => {
74
+ if (s.pending) {
75
+ const at = Date.parse(s.at);
76
+ if (!Number.isFinite(at) || now() - at > exports.PENDING_TTL_MS)
77
+ return false;
78
+ }
79
+ return probe(s.pid) !== 'dead';
80
+ };
81
+ const write = (slot) => {
82
+ (0, node_fs_1.mkdirSync)(dir, { recursive: true });
83
+ const target = (0, node_path_1.join)(dir, fileOf(slot.key));
84
+ const tmp = `${target}.${me}.tmp`;
85
+ (0, node_fs_1.writeFileSync)(tmp, `${JSON.stringify(slot)}\n`, 'utf8');
86
+ (0, node_fs_1.renameSync)(tmp, target);
87
+ };
88
+ const inUse = (except) => read().filter(({ slot }) => slot.key !== except && live(slot)).length;
89
+ return {
90
+ cap: limit,
91
+ inUse,
92
+ claim(key) {
93
+ try {
94
+ (0, node_fs_1.mkdirSync)(dir, { recursive: true });
95
+ }
96
+ catch {
97
+ // Fall through: the lock below refuses, and a refusal is a wait.
98
+ }
99
+ return (0, exclusive_lock_1.withExclusiveLock)((0, node_path_1.join)(dir, 'claim.lock'), () => {
100
+ const all = read();
101
+ for (const { file, slot } of all) {
102
+ if (!live(slot)) {
103
+ try {
104
+ (0, node_fs_1.rmSync)((0, node_path_1.join)(dir, file), { force: true });
105
+ }
106
+ catch {
107
+ /* swept next time */
108
+ }
109
+ }
110
+ }
111
+ const mine = all.find(({ slot }) => slot.key === key);
112
+ if (mine !== undefined && !mine.slot.pending && live(mine.slot))
113
+ return null; // already running
114
+ const others = all.filter(({ slot }) => slot.key !== key && live(slot)).length;
115
+ if (others >= limit) {
116
+ return `this computer already has ${others} autonomous run(s) going across its repositories and its ceiling is ${limit} (machine.max_runs_on_machine)`;
117
+ }
118
+ write({ key, pid: me, pending: true, at: new Date(now()).toISOString(), ...(deps.repo === undefined ? {} : { repo: deps.repo }) });
119
+ return null;
120
+ }, (why) => `the machine-wide run count could not be checked (${why})`);
121
+ },
122
+ bind(key, pid) {
123
+ try {
124
+ write({ key, pid, pending: false, at: new Date(now()).toISOString(), ...(deps.repo === undefined ? {} : { repo: deps.repo }) });
125
+ }
126
+ catch {
127
+ // A slot that cannot be bound expires as pending; the run goes on.
128
+ }
129
+ },
130
+ release(key) {
131
+ try {
132
+ (0, node_fs_1.rmSync)((0, node_path_1.join)(dir, fileOf(key)), { force: true });
133
+ }
134
+ catch {
135
+ /* expires on its own */
136
+ }
137
+ },
138
+ };
139
+ }
140
+ //# sourceMappingURL=machine-run-slots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"machine-run-slots.js","sourceRoot":"","sources":["../src/machine-run-slots.ts"],"names":[],"mappings":";;;AAmEA,0CAEC;AAID,0CA8FC;AAvKD,6CAAyC;AACzC,qCAAkG;AAClG,qCAAkC;AAClC,yCAAiC;AACjC,qDAAqD;AACrD,2CAAsD;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,uEAAuE;AAC1D,QAAA,cAAc,GAAG,CAAC,GAAG,MAAM,CAAC;AA+BzC,SAAgB,eAAe,CAAC,OAAe,IAAA,iBAAO,GAAE;IACtD,OAAO,IAAA,gBAAI,EAAC,IAAI,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,MAAM,GAAG,CAAC,GAAW,EAAU,EAAE,CAAC,GAAG,IAAA,wBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC;AAE9G,SAAgB,eAAe,CAAC,GAAW,EAAE,OAA2B,EAAE;IACxE,MAAM,GAAG,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,qBAAS,CAAC;IACtC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IACnC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IAE3C,MAAM,IAAI,GAAG,GAA+C,EAAE;QAC5D,IAAI,KAAe,CAAC;QACpB,IAAI,CAAC;YACH,KAAK,GAAG,IAAA,qBAAW,EAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;QAC9D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,GAAG,GAA+C,EAAE,CAAC;QAC3D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAA,sBAAY,EAAC,IAAA,gBAAI,EAAC,GAAG,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAyB,CAAC;gBACtF,IAAI,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,EAAE,KAAK,QAAQ;oBAAE,SAAS;gBACvG,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,KAAK,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;YAC7J,CAAC;YAAC,MAAM,CAAC;gBACP,kEAAkE;YACpE,CAAC;QACH,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC,CAAC;IAEF,MAAM,IAAI,GAAG,CAAC,CAAc,EAAW,EAAE;QACvC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;YACd,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC5B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,sBAAc;gBAAE,OAAO,KAAK,CAAC;QACxE,CAAC;QACD,OAAO,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC;IACjC,CAAC,CAAC;IAEF,MAAM,KAAK,GAAG,CAAC,IAAiB,EAAQ,EAAE;QACxC,IAAA,mBAAS,EAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,IAAA,gBAAI,EAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3C,MAAM,GAAG,GAAG,GAAG,MAAM,IAAI,EAAE,MAAM,CAAC;QAClC,IAAA,uBAAa,EAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACxD,IAAA,oBAAU,EAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC1B,CAAC,CAAC;IAEF,MAAM,KAAK,GAAG,CAAC,MAAe,EAAU,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;IAEjH,OAAO;QACL,GAAG,EAAE,KAAK;QACV,KAAK;QACL,KAAK,CAAC,GAAG;YACP,IAAI,CAAC;gBACH,IAAA,mBAAS,EAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACtC,CAAC;YAAC,MAAM,CAAC;gBACP,iEAAiE;YACnE,CAAC;YACD,OAAO,IAAA,kCAAiB,EACtB,IAAA,gBAAI,EAAC,GAAG,EAAE,YAAY,CAAC,EACvB,GAAG,EAAE;gBACH,MAAM,GAAG,GAAG,IAAI,EAAE,CAAC;gBACnB,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,GAAG,EAAE,CAAC;oBACjC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;wBAChB,IAAI,CAAC;4BACH,IAAA,gBAAM,EAAC,IAAA,gBAAI,EAAC,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;wBAC3C,CAAC;wBAAC,MAAM,CAAC;4BACP,qBAAqB;wBACvB,CAAC;oBACH,CAAC;gBACH,CAAC;gBACD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;gBACtD,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;oBAAE,OAAO,IAAI,CAAC,CAAC,kBAAkB;gBAChG,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,KAAK,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;gBAC/E,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;oBACpB,OAAO,6BAA6B,MAAM,uEAAuE,KAAK,gCAAgC,CAAC;gBACzJ,CAAC;gBACD,KAAK,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;gBACnI,OAAO,IAAI,CAAC;YACd,CAAC,EACD,CAAC,GAAG,EAAE,EAAE,CAAC,oDAAoD,GAAG,GAAG,CACpE,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,GAAG,EAAE,GAAG;YACX,IAAI,CAAC;gBACH,KAAK,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;YAClI,CAAC;YAAC,MAAM,CAAC;gBACP,mEAAmE;YACrE,CAAC;QACH,CAAC;QACD,OAAO,CAAC,GAAG;YACT,IAAI,CAAC;gBACH,IAAA,gBAAM,EAAC,IAAA,gBAAI,EAAC,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAClD,CAAC;YAAC,MAAM,CAAC;gBACP,wBAAwB;YAC1B,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -23,15 +23,21 @@
23
23
  * time, before a run starts, with the reason — not at round one after the first
24
24
  * call has been paid for.
25
25
  */
26
+ import { type AgentEffort, type AgentSettings } from '@looply/core';
26
27
  /** The roles that drive a model, in the order a round meets them. */
27
28
  export declare const MODEL_ROLES: readonly ["implementer", "verifier", "scanner", "brain"];
28
29
  export type ModelRole = (typeof MODEL_ROLES)[number];
29
30
  /** The keys `agent.models` may carry: every role, plus the one that covers the rest. */
30
31
  export declare const MODEL_KEYS: readonly ["default", "implementer", "verifier", "scanner", "brain"];
31
32
  export type ModelKey = (typeof MODEL_KEYS)[number];
32
- /** `--effort`, as Claude Code spells it. Checked against `claude --help` on 2026-09-13. */
33
+ /**
34
+ * `--effort`, as Claude Code spells it. Checked against `claude --help` on
35
+ * 2026-09-13. Declared in core, so the server refuses exactly what this does.
36
+ */
33
37
  export declare const EFFORT_LEVELS: readonly ["low", "medium", "high", "xhigh", "max"];
34
- export type Effort = (typeof EFFORT_LEVELS)[number];
38
+ export type Effort = AgentEffort;
39
+ /** `agent.effort` written as a map: `default` covers any role not named. */
40
+ export type RoleEfforts = Partial<Record<ModelKey, Effort>>;
35
41
  /**
36
42
  * Role → model id. `default` covers any role not named; a role named here wins.
37
43
  * Every value is one model id, passed as one argument — never a flag string.
@@ -46,17 +52,56 @@ export type RoleModels = Partial<Record<ModelKey, string>>;
46
52
  * one should not be able to step around a cost rule with a capital letter.
47
53
  */
48
54
  export declare function isBrainOnlyModel(model: string): boolean;
49
- /** The model a role runs under this configuration, or undefined to leave it to the provider. */
55
+ /** The model config.yaml names for a role, or undefined when it names none. */
50
56
  export declare function modelFor(role: ModelRole, models: RoleModels | undefined): string | undefined;
57
+ /**
58
+ * The effort config.yaml names for a role. `agent.effort` is either one level
59
+ * for every role (the original shape, still byte-compatible) or a map with an
60
+ * optional `default`.
61
+ */
62
+ export declare function effortFor(role: ModelRole, effort: Effort | RoleEfforts | undefined): Effort | undefined;
63
+ /** Where a resolved value came from, as `looply doctor` prints it. */
64
+ export type SettingSource = 'config.yaml' | 'remote' | 'default';
65
+ export interface ResolvedRole {
66
+ model: string;
67
+ effort: Effort;
68
+ modelFrom: SettingSource;
69
+ effortFrom: SettingSource;
70
+ }
71
+ /**
72
+ * The model and effort a role runs on the BUILT-IN provider, field by field:
73
+ *
74
+ * config.yaml > remote project settings > DEFAULT_AGENT_SETTINGS
75
+ *
76
+ * config.yaml wins because it is a person's decision written in the repository
77
+ * on the machine itself; remote settings (console, integrations) fill what the
78
+ * file leaves unsaid; the built-in table fills the rest. Model and effort are
79
+ * resolved independently, so a file naming only an effort still takes the
80
+ * remote or default model.
81
+ *
82
+ * ⚠️ A remote Fable model for a non-brain role is ignored here even though the
83
+ * validator refuses it at the API: the cache is a file on disk, and the rule
84
+ * is cheap to hold twice.
85
+ */
86
+ export declare function resolveRole(role: ModelRole, spec: {
87
+ models?: RoleModels;
88
+ effort?: Effort | RoleEfforts;
89
+ }, remote?: AgentSettings | null): ResolvedRole;
51
90
  /**
52
91
  * The arguments that put a role on its model, ready to splice into a Claude
53
- * Code command line. Empty when nothing is configured, so a project that says
54
- * nothing about models produces the byte-identical invocation it did before.
92
+ * Code command line.
93
+ *
94
+ * ⚠️ CHANGED DELIBERATELY: this used to be EMPTY when nothing was configured,
95
+ * so the provider's own default ran (whatever Claude Code happened to pick on
96
+ * that machine). Every built-in turn now names its model and effort — from
97
+ * config.yaml, the project's remote settings, or `DEFAULT_AGENT_SETTINGS` — so
98
+ * what a role runs is a Looply decision that `looply doctor` can print, not an
99
+ * accident of the machine. Only ever called on the built-in branch.
55
100
  */
56
101
  export declare function modelArgs(role: ModelRole, spec: {
57
102
  models?: RoleModels;
58
- effort?: Effort;
59
- }): string[];
103
+ effort?: Effort | RoleEfforts;
104
+ }, remote?: AgentSettings | null): string[];
60
105
  export type RoleModelsCheck = {
61
106
  ok: true;
62
107
  } | {
@@ -1 +1 @@
1
- {"version":3,"file":"model-routing.d.ts","sourceRoot":"","sources":["../src/model-routing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,qEAAqE;AACrE,eAAO,MAAM,WAAW,0DAA2D,CAAC;AACpF,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD,wFAAwF;AACxF,eAAO,MAAM,UAAU,qEAAuC,CAAC;AAC/D,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnD,2FAA2F;AAC3F,eAAO,MAAM,aAAa,oDAAqD,CAAC;AAChF,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpD;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;AAE3D;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,gGAAgG;AAChG,wBAAgB,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAE5F;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,SAAS,EACf,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,UAAU,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7C,MAAM,EAAE,CAMV;AAED,MAAM,MAAM,eAAe,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzF;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,eAAe,CAiCnE"}
1
+ {"version":3,"file":"model-routing.d.ts","sourceRoot":"","sources":["../src/model-routing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,aAAa,EACnB,MAAM,cAAc,CAAC;AAEtB,qEAAqE;AACrE,eAAO,MAAM,WAAW,0DAA2D,CAAC;AACpF,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD,wFAAwF;AACxF,eAAO,MAAM,UAAU,qEAAuC,CAAC;AAC/D,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnD;;;GAGG;AACH,eAAO,MAAM,aAAa,oDAAgB,CAAC;AAC3C,MAAM,MAAM,MAAM,GAAG,WAAW,CAAC;AAEjC,4EAA4E;AAC5E,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;AAE5D;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;AAE3D;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,+EAA+E;AAC/E,wBAAgB,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAE5F;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAIvG;AAED,sEAAsE;AACtE,MAAM,MAAM,aAAa,GAAG,aAAa,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEjE,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,aAAa,CAAC;IACzB,UAAU,EAAE,aAAa,CAAC;CAC3B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,SAAS,EACf,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,UAAU,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,GAAG,WAAW,CAAA;CAAE,EAC5D,MAAM,CAAC,EAAE,aAAa,GAAG,IAAI,GAC5B,YAAY,CAkCd;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,SAAS,EACf,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,UAAU,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,GAAG,WAAW,CAAA;CAAE,EAC5D,MAAM,CAAC,EAAE,aAAa,GAAG,IAAI,GAC5B,MAAM,EAAE,CAGV;AAED,MAAM,MAAM,eAAe,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzF;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,eAAe,CAiCnE"}
@@ -28,14 +28,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
28
28
  exports.EFFORT_LEVELS = exports.MODEL_KEYS = exports.MODEL_ROLES = void 0;
29
29
  exports.isBrainOnlyModel = isBrainOnlyModel;
30
30
  exports.modelFor = modelFor;
31
+ exports.effortFor = effortFor;
32
+ exports.resolveRole = resolveRole;
31
33
  exports.modelArgs = modelArgs;
32
34
  exports.checkRoleModels = checkRoleModels;
35
+ const core_1 = require("@looply/core");
33
36
  /** The roles that drive a model, in the order a round meets them. */
34
37
  exports.MODEL_ROLES = ['implementer', 'verifier', 'scanner', 'brain'];
35
38
  /** The keys `agent.models` may carry: every role, plus the one that covers the rest. */
36
39
  exports.MODEL_KEYS = ['default', ...exports.MODEL_ROLES];
37
- /** `--effort`, as Claude Code spells it. Checked against `claude --help` on 2026-09-13. */
38
- exports.EFFORT_LEVELS = ['low', 'medium', 'high', 'xhigh', 'max'];
40
+ /**
41
+ * `--effort`, as Claude Code spells it. Checked against `claude --help` on
42
+ * 2026-09-13. Declared in core, so the server refuses exactly what this does.
43
+ */
44
+ exports.EFFORT_LEVELS = core_1.AGENT_EFFORTS;
39
45
  /**
40
46
  * Which model ids may only be the brain's.
41
47
  *
@@ -45,25 +51,89 @@ exports.EFFORT_LEVELS = ['low', 'medium', 'high', 'xhigh', 'max'];
45
51
  * one should not be able to step around a cost rule with a capital letter.
46
52
  */
47
53
  function isBrainOnlyModel(model) {
48
- return /fable/i.test(model);
54
+ return (0, core_1.isBrainOnlyModelId)(model);
49
55
  }
50
- /** The model a role runs under this configuration, or undefined to leave it to the provider. */
56
+ /** The model config.yaml names for a role, or undefined when it names none. */
51
57
  function modelFor(role, models) {
52
58
  return models?.[role] ?? models?.default;
53
59
  }
60
+ /**
61
+ * The effort config.yaml names for a role. `agent.effort` is either one level
62
+ * for every role (the original shape, still byte-compatible) or a map with an
63
+ * optional `default`.
64
+ */
65
+ function effortFor(role, effort) {
66
+ if (effort === undefined)
67
+ return undefined;
68
+ if (typeof effort === 'string')
69
+ return effort;
70
+ return effort[role] ?? effort.default;
71
+ }
72
+ /**
73
+ * The model and effort a role runs on the BUILT-IN provider, field by field:
74
+ *
75
+ * config.yaml > remote project settings > DEFAULT_AGENT_SETTINGS
76
+ *
77
+ * config.yaml wins because it is a person's decision written in the repository
78
+ * on the machine itself; remote settings (console, integrations) fill what the
79
+ * file leaves unsaid; the built-in table fills the rest. Model and effort are
80
+ * resolved independently, so a file naming only an effort still takes the
81
+ * remote or default model.
82
+ *
83
+ * ⚠️ A remote Fable model for a non-brain role is ignored here even though the
84
+ * validator refuses it at the API: the cache is a file on disk, and the rule
85
+ * is cheap to hold twice.
86
+ */
87
+ function resolveRole(role, spec, remote) {
88
+ const fallback = core_1.DEFAULT_AGENT_SETTINGS[role];
89
+ const fromRemote = remote?.[role];
90
+ let model;
91
+ let modelFrom;
92
+ const configured = modelFor(role, spec.models);
93
+ const remoteModel = fromRemote?.model;
94
+ if (configured !== undefined) {
95
+ model = configured;
96
+ modelFrom = 'config.yaml';
97
+ }
98
+ else if (remoteModel !== undefined && (role === 'brain' || !(0, core_1.isBrainOnlyModelId)(remoteModel))) {
99
+ model = remoteModel;
100
+ modelFrom = 'remote';
101
+ }
102
+ else {
103
+ model = fallback.model;
104
+ modelFrom = 'default';
105
+ }
106
+ let effort;
107
+ let effortFrom;
108
+ const configuredEffort = effortFor(role, spec.effort);
109
+ if (configuredEffort !== undefined) {
110
+ effort = configuredEffort;
111
+ effortFrom = 'config.yaml';
112
+ }
113
+ else if (fromRemote?.effort !== undefined) {
114
+ effort = fromRemote.effort;
115
+ effortFrom = 'remote';
116
+ }
117
+ else {
118
+ effort = fallback.effort;
119
+ effortFrom = 'default';
120
+ }
121
+ return { model, effort, modelFrom, effortFrom };
122
+ }
54
123
  /**
55
124
  * The arguments that put a role on its model, ready to splice into a Claude
56
- * Code command line. Empty when nothing is configured, so a project that says
57
- * nothing about models produces the byte-identical invocation it did before.
125
+ * Code command line.
126
+ *
127
+ * ⚠️ CHANGED DELIBERATELY: this used to be EMPTY when nothing was configured,
128
+ * so the provider's own default ran (whatever Claude Code happened to pick on
129
+ * that machine). Every built-in turn now names its model and effort — from
130
+ * config.yaml, the project's remote settings, or `DEFAULT_AGENT_SETTINGS` — so
131
+ * what a role runs is a Looply decision that `looply doctor` can print, not an
132
+ * accident of the machine. Only ever called on the built-in branch.
58
133
  */
59
- function modelArgs(role, spec) {
60
- const out = [];
61
- const model = modelFor(role, spec.models);
62
- if (model !== undefined)
63
- out.push('--model', model);
64
- if (spec.effort !== undefined)
65
- out.push('--effort', spec.effort);
66
- return out;
134
+ function modelArgs(role, spec, remote) {
135
+ const r = resolveRole(role, spec, remote);
136
+ return ['--model', r.model, '--effort', r.effort];
67
137
  }
68
138
  /**
69
139
  * Is this `agent.models` block one looply will drive?
@@ -1 +1 @@
1
- {"version":3,"file":"model-routing.js","sourceRoot":"","sources":["../src/model-routing.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;;;AA4BH,4CAEC;AAGD,4BAEC;AAOD,8BASC;AAWD,0CAiCC;AA7FD,qEAAqE;AACxD,QAAA,WAAW,GAAG,CAAC,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,CAAU,CAAC;AAGpF,wFAAwF;AAC3E,QAAA,UAAU,GAAG,CAAC,SAAS,EAAE,GAAG,mBAAW,CAAU,CAAC;AAG/D,2FAA2F;AAC9E,QAAA,aAAa,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAU,CAAC;AAShF;;;;;;;GAOG;AACH,SAAgB,gBAAgB,CAAC,KAAa;IAC5C,OAAO,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED,gGAAgG;AAChG,SAAgB,QAAQ,CAAC,IAAe,EAAE,MAA8B;IACtE,OAAO,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,MAAM,EAAE,OAAO,CAAC;AAC3C,CAAC;AAED;;;;GAIG;AACH,SAAgB,SAAS,CACvB,IAAe,EACf,IAA8C;IAE9C,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1C,IAAI,KAAK,KAAK,SAAS;QAAE,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACpD,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;QAAE,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACjE,OAAO,GAAG,CAAC;AACb,CAAC;AAID;;;;;;GAMG;AACH,SAAgB,eAAe,CAAC,MAAkB;IAChD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,IAAI,CAAE,kBAAgC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACrD,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,GAAG,EAAE,gBAAgB,GAAG,EAAE;gBAC1B,OAAO,EAAE,iBAAiB,GAAG,cAAc,kBAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;aACnE,CAAC;QACJ,CAAC;QACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACrD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,gBAAgB,GAAG,EAAE,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC;QAClF,CAAC;QACD,2EAA2E;QAC3E,8CAA8C;QAC9C,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACrB,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,GAAG,EAAE,gBAAgB,GAAG,EAAE;gBAC1B,OAAO,EAAE,mCAAmC,KAAK,kCAAkC;aACpF,CAAC;QACJ,CAAC;QACD,IAAI,GAAG,KAAK,OAAO,IAAI,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/C,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,GAAG,EAAE,gBAAgB,GAAG,EAAE;gBAC1B,OAAO,EACL,SAAS,KAAK,yCAAyC;oBACvD,mFAAmF;oBACnF,2FAA2F;aAC9F,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACtB,CAAC"}
1
+ {"version":3,"file":"model-routing.js","sourceRoot":"","sources":["../src/model-routing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ import { type AgentSettings } from '@looply/core';
2
+ import { type Effort, type RoleEfforts, type RoleModels } from './model-routing';
3
+ /**
4
+ * THE PROJECT'S REMOTE MODEL SETTINGS, AS THIS MACHINE LAST HEARD THEM.
5
+ *
6
+ * The server holds per-project model/effort choices (set from the console or
7
+ * by an integration). The standalone daemon pulls them on start and every few
8
+ * minutes and writes them HERE; every built-in model turn — a daemon-launched
9
+ * run, `looply run`, `scan`, `verify` — reads this file at launch time.
10
+ *
11
+ * Why a cached file rather than a field on a payload the run already fetches:
12
+ * a run may start with the server unreachable, and a machine that goes offline
13
+ * must keep running the models it was last told to — not silently fall back to
14
+ * the defaults mid-night. One writer (the daemon), many readers, and a reader
15
+ * that finds nothing, or something malformed, gets the defaults.
16
+ *
17
+ * The value is re-validated on every read with the same core rule the server
18
+ * applies on write, so a hand-edited or corrupted file cannot put a Fable
19
+ * model on an agent role or smuggle a flag into the command line.
20
+ */
21
+ export declare const AGENT_SETTINGS_FILE = "agent-settings.json";
22
+ /** How often the daemon asks the server. */
23
+ export declare const DEFAULT_AGENT_SETTINGS_POLL_MS: number;
24
+ export interface AgentSettingsCache {
25
+ /** Null means "back to defaults", which is an answer, not an absence. */
26
+ settings: AgentSettings | null;
27
+ /** When the server says the settings last changed. */
28
+ updatedAt: string | null;
29
+ /** When this machine last heard it. */
30
+ fetchedAt: string;
31
+ }
32
+ /** The cached answer, or null when there is none or it does not validate. */
33
+ export declare function readAgentSettingsCache(stateDir: string): AgentSettingsCache | null;
34
+ /** Atomic: a reader never sees half a file. */
35
+ export declare function writeAgentSettingsCache(stateDir: string, value: AgentSettingsCache): void;
36
+ /**
37
+ * The remote settings that apply to a project directory (a worktree resolves
38
+ * to its repository's shared state), or null. Never throws: a model turn must
39
+ * not fail because a cache could not be read — it runs the defaults instead.
40
+ */
41
+ export declare function remoteAgentSettingsFor(projectDir: string): AgentSettings | null;
42
+ export interface AgentSettingsPullDeps {
43
+ /** `GET /v1/projects/:id/agent-settings`. */
44
+ fetch(): Promise<unknown>;
45
+ stateDir: string;
46
+ log(line: string): void;
47
+ now(): number;
48
+ }
49
+ export type AgentSettingsPullResult = 'updated' | 'unchanged' | 'failed';
50
+ /**
51
+ * One pull: ask the server, and write the cache when the answer changed.
52
+ *
53
+ * A failure keeps whatever the cache holds — an outage must not reset a
54
+ * machine to defaults. Offline is reported by the heartbeat already; anything
55
+ * else (an older server without the route, a malformed answer) is said once
56
+ * per outage rather than every five minutes.
57
+ */
58
+ export declare function makeAgentSettingsPull(deps: AgentSettingsPullDeps): () => Promise<AgentSettingsPullResult>;
59
+ /**
60
+ * The lines `looply doctor` and `looply status` print: per role, the model and
61
+ * effort and where each came from.
62
+ */
63
+ export declare function describeModelRouting(spec: {
64
+ models?: RoleModels;
65
+ effort?: Effort | RoleEfforts;
66
+ }, builtIn: boolean, remote: AgentSettings | null): string[];
67
+ //# sourceMappingURL=model-settings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-settings.d.ts","sourceRoot":"","sources":["../src/model-settings.ts"],"names":[],"mappings":"AAEA,OAAO,EAAyB,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAEzE,OAAO,EAA4B,KAAK,MAAM,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG3G;;;;;;;;;;;;;;;;;GAiBG;AAEH,eAAO,MAAM,mBAAmB,wBAAwB,CAAC;AAEzD,4CAA4C;AAC5C,eAAO,MAAM,8BAA8B,QAAa,CAAC;AAEzD,MAAM,WAAW,kBAAkB;IACjC,yEAAyE;IACzE,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;IAC/B,sDAAsD;IACtD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,6EAA6E;AAC7E,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CAoBlF;AAED,+CAA+C;AAC/C,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAMzF;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAM/E;AAED,MAAM,WAAW,qBAAqB;IACpC,6CAA6C;IAC7C,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,GAAG,IAAI,MAAM,CAAC;CACf;AAED,MAAM,MAAM,uBAAuB,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;AAEzE;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,qBAAqB,GAAG,MAAM,OAAO,CAAC,uBAAuB,CAAC,CA4DzG;AAYD;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,UAAU,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,GAAG,WAAW,CAAA;CAAE,EAC5D,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,aAAa,GAAG,IAAI,GAC3B,MAAM,EAAE,CAeV"}