@amenophis1er/foreman 0.1.1 → 0.1.2

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": "@amenophis1er/foreman",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Autonomous mission runner on the Claude Agent SDK: a director plans, delegates to workers, verifies, and reports — from one dashboard, your phone, or the CLI.",
5
5
  "keywords": [
6
6
  "claude",
@@ -24,7 +24,7 @@
24
24
  "author": "Amen AMOUZOU",
25
25
  "type": "module",
26
26
  "bin": {
27
- "foreman": "./bin/foreman.mjs"
27
+ "foreman": "bin/foreman.mjs"
28
28
  },
29
29
  "files": [
30
30
  "bin",
package/src/server.ts CHANGED
@@ -1131,20 +1131,39 @@ async function startRun(
1131
1131
  await driveRun(projectId, meta);
1132
1132
  }
1133
1133
 
1134
- /** Resumes an interrupted run by restoring the director's session. */
1135
- async function resumeRun(projectId: string, meta: RunMeta): Promise<void> {
1134
+ /**
1135
+ * Resumes an interrupted run by restoring the director's session. `pick`
1136
+ * carries models chosen for this resume (the header's "Resume on…"); a role
1137
+ * it names wins over Settings for that role.
1138
+ */
1139
+ async function resumeRun(projectId: string, meta: RunMeta, pick: {
1140
+ directorModel?: string; directorProviderId?: string; workerModel?: string; workerProviderId?: string;
1141
+ } = {}): Promise<void> {
1136
1142
  const sessionId = meta.directorSessionId;
1137
1143
  // Resume re-reads Settings, so changing models or tool policy after a
1138
1144
  // failure takes effect on the retry. A director session cannot switch
1139
1145
  // model mid-session, so a changed director model restarts the session
1140
1146
  // fresh (the mission doc carries the state forward).
1141
- const settings = await effectiveSettings(projectId);
1147
+ const base = await effectiveSettings(projectId);
1148
+ const settings = {
1149
+ ...base,
1150
+ ...(pick.directorModel ? { directorModel: modelChoice(pick.directorModel), directorProviderId: pick.directorProviderId } : {}),
1151
+ ...(pick.workerModel ? { workerModel: modelChoice(pick.workerModel), workerProviderId: pick.workerProviderId } : {}),
1152
+ };
1153
+ // A model is picked together with the provider that serves it, so a
1154
+ // change of either moves the role. Without the provider following the
1155
+ // model, "resume on Sonnet" after a Codex usage limit went back through
1156
+ // the Codex gateway — which remapped the unknown id to its own default and
1157
+ // hit the same 429. The provider id is left undefined when Settings does
1158
+ // not pin one, which means the project's own provider, as at start.
1142
1159
  const directorChanged =
1143
- settings.directorModel !== undefined && settings.directorModel !== meta.directorModel;
1160
+ (settings.directorModel !== undefined && settings.directorModel !== meta.directorModel)
1161
+ || (settings.directorModel !== undefined && settings.directorProviderId !== meta.directorProviderId);
1144
1162
  const workerChanged =
1145
- settings.workerModel !== undefined && settings.workerModel !== meta.workerModel;
1146
- if (directorChanged) meta.directorModel = settings.directorModel;
1147
- if (workerChanged) meta.workerModel = settings.workerModel;
1163
+ (settings.workerModel !== undefined && settings.workerModel !== meta.workerModel)
1164
+ || (settings.workerModel !== undefined && settings.workerProviderId !== meta.workerProviderId);
1165
+ if (directorChanged) { meta.directorModel = settings.directorModel; meta.directorProviderId = settings.directorProviderId; }
1166
+ if (workerChanged) { meta.workerModel = settings.workerModel; meta.workerProviderId = settings.workerProviderId; }
1148
1167
  meta.toolPolicy = settings.toolPolicy;
1149
1168
  meta.autoAllowReadOnly = settings.autoAllowReadOnly;
1150
1169
  meta.status = 'running';
@@ -1863,7 +1882,14 @@ const server = http.createServer(async (req, res) => {
1863
1882
  if (!reserveProject(meta.projectId)) {
1864
1883
  return json(res, 409, { error: 'this project already has an active mission' });
1865
1884
  }
1866
- void resumeRun(meta.projectId, meta);
1885
+ // "Resume on…": models picked for this resume, ahead of Settings. A
1886
+ // model without a provider id means the project's own provider.
1887
+ const str = (v: unknown) => (typeof v === 'string' && v.trim() ? v.trim() : undefined);
1888
+ const overrides = {
1889
+ directorModel: str(resumeBody.directorModel), directorProviderId: str(resumeBody.directorProviderId),
1890
+ workerModel: str(resumeBody.workerModel), workerProviderId: str(resumeBody.workerProviderId),
1891
+ };
1892
+ void resumeRun(meta.projectId, meta, overrides);
1867
1893
  json(res, 200, { ok: true });
1868
1894
 
1869
1895
  } else if (req.method === 'GET' && runEventsMatch) {