conductor-remote 1.131.2 → 1.131.4
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/dist/assets/{AutoModelSettings-BeVICf6p.js → AutoModelSettings-SBdRr_mv.js} +1 -1
- package/dist/assets/{PierrePatch-Dzam9HOM.js → PierrePatch-BmY2b7Ei.js} +1 -1
- package/dist/assets/{index-fUZj9cRu.js → index-BAEVNqQy.js} +32 -32
- package/dist/index.html +1 -1
- package/dist/sw.js +1 -1
- package/dist-node/src/agents/roles.js +5 -5
- package/dist-node/src/http/services/delegations.js +6 -6
- package/dist-node/src/http/services/delivery.js +38 -29
- package/dist-node/src/http/services/workflow.js +0 -3
- package/dist-node/src/orchestration/delegation/codec.js +1 -0
- package/dist-node/src/orchestration/delegation/prompt.js +26 -1
- package/dist-node/src/orchestration/delegation/queue.js +2 -1
- package/dist-node/src/shared.js +9 -0
- package/package.json +1 -1
package/dist/index.html
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
<title>Conductor Remote</title>
|
|
26
26
|
<!-- Runs before the module bundle so it can catch a stale shell that fails to boot. -->
|
|
27
27
|
<script src="/self-heal.js"></script>
|
|
28
|
-
<script type="module" crossorigin src="/assets/index-
|
|
28
|
+
<script type="module" crossorigin src="/assets/index-BAEVNqQy.js"></script>
|
|
29
29
|
<link rel="stylesheet" crossorigin href="/assets/index-Dbu5DOed.css">
|
|
30
30
|
<link rel="manifest" href="/manifest.webmanifest"></head>
|
|
31
31
|
<body>
|
package/dist/sw.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
if(!self.define){let e,s={};const i=(i,n)=>(i=new URL(i+".js",n).href,s[i]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=i,e.onload=s,document.head.appendChild(e)}else e=i,importScripts(i),s()}).then(()=>{let e=s[i];if(!e)throw new Error(`Module ${i} didn’t register its module`);return e}));self.define=(n,r)=>{const l=e||("document"in self?document.currentScript.src:"")||location.href;if(s[l])return;let o={};const t=e=>i(e,l),a={module:{uri:l},exports:o,require:t};s[l]=Promise.all(n.map(e=>a[e]||t(e))).then(e=>(r(...e),o))}}define(["./workbox-dcde9eb3"],function(e){"use strict";importScripts("/push-sw.js"),self.addEventListener("message",e=>{e.data&&"SKIP_WAITING"===e.data.type&&self.skipWaiting()}),e.clientsClaim(),e.precacheAndRoute([{url:"self-heal.js",revision:"49bd63adb25a09341f8d2610e8bd3c76"},{url:"push-sw.js",revision:"4e0b714c0ea53e85c167e6d8f5b767aa"},{url:"index.html",revision:"
|
|
1
|
+
if(!self.define){let e,s={};const i=(i,n)=>(i=new URL(i+".js",n).href,s[i]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=i,e.onload=s,document.head.appendChild(e)}else e=i,importScripts(i),s()}).then(()=>{let e=s[i];if(!e)throw new Error(`Module ${i} didn’t register its module`);return e}));self.define=(n,r)=>{const l=e||("document"in self?document.currentScript.src:"")||location.href;if(s[l])return;let o={};const t=e=>i(e,l),a={module:{uri:l},exports:o,require:t};s[l]=Promise.all(n.map(e=>a[e]||t(e))).then(e=>(r(...e),o))}}define(["./workbox-dcde9eb3"],function(e){"use strict";importScripts("/push-sw.js"),self.addEventListener("message",e=>{e.data&&"SKIP_WAITING"===e.data.type&&self.skipWaiting()}),e.clientsClaim(),e.precacheAndRoute([{url:"self-heal.js",revision:"49bd63adb25a09341f8d2610e8bd3c76"},{url:"push-sw.js",revision:"4e0b714c0ea53e85c167e6d8f5b767aa"},{url:"index.html",revision:"e644d471ce76c93e68869452f62ead76"},{url:"assets/workbox-window.prod.es5-BBnX5xw4.js",revision:null},{url:"assets/pierre-shiki-wasm-C8ETeZem.js",revision:null},{url:"assets/pierre-light-480U9XYS.js",revision:null},{url:"assets/pierre-dark-CyvmCCZW.js",revision:null},{url:"assets/index-Dbu5DOed.css",revision:null},{url:"assets/index-BAEVNqQy.js",revision:null},{url:"assets/PierrePatch-BmY2b7Ei.js",revision:null},{url:"assets/AutoModelSettings-SBdRr_mv.js",revision:null},{url:"apple-touch-icon.png",revision:"1127bb396b4648add53dce3f22c92aee"},{url:"icon-192.png",revision:"c5e01ac58768627e18ee7b8b6a9239ef"},{url:"icon-512.png",revision:"a40638c55e310312457a621c9a0002c8"},{url:"icon-maskable-512.png",revision:"a9b0d962686287452216492cd2247499"},{url:"icon.svg",revision:"c1aee186821798733dd477e69a0ef243"},{url:"manifest.webmanifest",revision:"cf88fbc5755108a7fe0616fa160a8a15"}],{}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("/index.html"),{denylist:[/^\/api\//]})),e.registerRoute(({url:e})=>e.pathname.startsWith("/assets/diff-syntax/"),new e.CacheFirst({cacheName:"diff-syntax",plugins:[new e.ExpirationPlugin({maxEntries:32,maxAgeSeconds:31536e3})]}),"GET")});
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import fs from 'node:fs';
|
|
10
10
|
import path from 'node:path';
|
|
11
11
|
import { stateDir } from "../config.js";
|
|
12
|
-
import {
|
|
12
|
+
import { modelAgentType, modelPickerLabel, savedModelCatalog } from "../shared.js";
|
|
13
13
|
export { newestModelSnapshot } from "../shared.js";
|
|
14
14
|
const EFFORTS = new Set(['none', 'low', 'medium', 'high', 'xhigh', 'max', 'ultracode']);
|
|
15
15
|
const ROLE_NAME = /^[a-z][a-z0-9_-]{0,63}$/;
|
|
@@ -138,12 +138,12 @@ function controlIssue(name, role, agentType) {
|
|
|
138
138
|
/** Picker validation stays separate from shape decoding so a vanished model remains editable. */
|
|
139
139
|
export function roleModelIssues(config, groups) {
|
|
140
140
|
const issues = [];
|
|
141
|
-
const models =
|
|
141
|
+
const models = savedModelCatalog(groups);
|
|
142
142
|
for (const [name, role] of Object.entries(config.roles)) {
|
|
143
143
|
if (!models.includes(modelPickerLabel(role.model))) {
|
|
144
144
|
issues.push({
|
|
145
145
|
role: name,
|
|
146
|
-
error: issue('model_missing', `Role ${name} needs an exact model from Conductor's
|
|
146
|
+
error: issue('model_missing', `Role ${name} needs an exact model from Conductor's saved picker catalog; update it in the role editor.`)
|
|
147
147
|
});
|
|
148
148
|
continue;
|
|
149
149
|
}
|
|
@@ -167,10 +167,10 @@ export function resolveRole(config, name, groups) {
|
|
|
167
167
|
return { ok: false, error: issue('role_not_found', `Unknown delegated role ${name}.`) };
|
|
168
168
|
}
|
|
169
169
|
const role = config.roles[name];
|
|
170
|
-
if (!
|
|
170
|
+
if (!savedModelCatalog(groups).includes(modelPickerLabel(role.model))) {
|
|
171
171
|
return {
|
|
172
172
|
ok: false,
|
|
173
|
-
error: issue('model_missing', `Role ${name} needs an exact model from Conductor's
|
|
173
|
+
error: issue('model_missing', `Role ${name} needs an exact model from Conductor's saved picker catalog; update it in the role editor.`)
|
|
174
174
|
};
|
|
175
175
|
}
|
|
176
176
|
const agentType = modelAgentType(role.model);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { writeAttachment } from "../../files/attachments.js";
|
|
2
|
-
import { delegatedPrompt } from "../../orchestration/delegation/prompt.js";
|
|
2
|
+
import { delegatedPrompt, writeDelegatedAssignment } from "../../orchestration/delegation/prompt.js";
|
|
3
3
|
import { DelegationQueue } from "../../orchestration/delegation/queue.js";
|
|
4
4
|
import { delegationReturnAttachment, delegationReturnText } from "../../orchestration/delegation/return.js";
|
|
5
5
|
import { withoutWindowEvidence } from "../../shared.js";
|
|
@@ -60,8 +60,10 @@ export function createDelegationsServices(services) {
|
|
|
60
60
|
return delegationError('opening_failed', 'The Mac is locked — unlock it and try again.');
|
|
61
61
|
}
|
|
62
62
|
let handoff;
|
|
63
|
+
let assignment;
|
|
63
64
|
try {
|
|
64
65
|
handoff = delegationHandoff(job, ws);
|
|
66
|
+
assignment = writeDelegatedAssignment({ ...job, handoff }, ws.worktree);
|
|
65
67
|
}
|
|
66
68
|
catch (err) {
|
|
67
69
|
return delegationError('opening_failed', err instanceof Error ? err.message : String(err), false);
|
|
@@ -70,9 +72,7 @@ export function createDelegationsServices(services) {
|
|
|
70
72
|
if ('error' in opened) {
|
|
71
73
|
return delegationError('opening_failed', opened.result.error ?? 'Conductor did not open a child chat', opened.retryable !== false);
|
|
72
74
|
}
|
|
73
|
-
|
|
74
|
-
return delegationError('opening_failed', 'Conductor opened a tab but did not record its chat id', false);
|
|
75
|
-
return { ok: true, childSessionId: opened.sessionId, handoff };
|
|
75
|
+
return { ok: true, childSessionId: opened.sessionId, handoff, assignment };
|
|
76
76
|
}
|
|
77
77
|
async function configureDelegation(job) {
|
|
78
78
|
const ws = reads.getWorkspace(job.workspaceId);
|
|
@@ -174,7 +174,7 @@ export function createDelegationsServices(services) {
|
|
|
174
174
|
catch (err) {
|
|
175
175
|
return delegationError('state_invalid', err instanceof Error ? err.message : String(err), false);
|
|
176
176
|
}
|
|
177
|
-
const result = await trackedPrompt(ws, job.childSessionId, text, job.sendDelivery, 'send_failed', job.handoff);
|
|
177
|
+
const result = await trackedPrompt(ws, job.childSessionId, text, job.sendDelivery, 'send_failed', job.assignment ?? job.handoff);
|
|
178
178
|
if (!result.ok)
|
|
179
179
|
return result;
|
|
180
180
|
return 'pending' in result
|
|
@@ -280,7 +280,7 @@ export function createDelegationsServices(services) {
|
|
|
280
280
|
const text = returning ? job.returnText : delegatedPrompt(job);
|
|
281
281
|
if (!text)
|
|
282
282
|
return null;
|
|
283
|
-
const receipt = trackedReceipt(sessionId, text, delivery, returning ? job.returnAttachment : job.handoff);
|
|
283
|
+
const receipt = trackedReceipt(sessionId, text, delivery, returning ? job.returnAttachment : (job.assignment ?? job.handoff));
|
|
284
284
|
return receipt
|
|
285
285
|
? { stage: returning ? 'returning' : 'sending', delivery: { ...delivery, messageId: receipt.id } }
|
|
286
286
|
: null;
|
|
@@ -10,7 +10,7 @@ import { readPrefs } from "../../prefs.js";
|
|
|
10
10
|
import { setAgentOptions } from "../../writes/agent-options.js";
|
|
11
11
|
import { newChat } from "../../writes/chats.js";
|
|
12
12
|
import { lockBlocked, retryWontHelp, screenLocked, sendNeverStarted } from "../../writes/guards.js";
|
|
13
|
-
import { withUiPriority } from "../../writes/ui-lock.js";
|
|
13
|
+
import { uiTurn, withUiPriority } from "../../writes/ui-lock.js";
|
|
14
14
|
export function createDeliveryServices(services) {
|
|
15
15
|
const { reads, sleep, actuator, STAGED_ATTACHMENTS_DIR, assignWorkflowRoot, orchestration, stagedAttachmentIdsInObjective, modelCache } = services;
|
|
16
16
|
/**
|
|
@@ -108,38 +108,47 @@ export function createDeliveryServices(services) {
|
|
|
108
108
|
/**
|
|
109
109
|
* Open a chat tab in a workspace and come back with its id.
|
|
110
110
|
*
|
|
111
|
-
*
|
|
112
|
-
* the
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
* `created_at` would hand back theirs.
|
|
111
|
+
* The UI lease spans the baseline, shortcut and DB receipt. Snapshotting before
|
|
112
|
+
* the lease or releasing it before the receipt lets concurrent opens claim each
|
|
113
|
+
* other's tabs. A script exit is only an attempted action; only one new row is
|
|
114
|
+
* success, including when a script fails after its shortcut already took effect.
|
|
116
115
|
*/
|
|
117
116
|
async function openChat(ws) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
117
|
+
return uiTurn(async () => {
|
|
118
|
+
const before = new Set(reads.listSessions(ws.id).map(s => s.id));
|
|
119
|
+
const result = await newChat(ws);
|
|
120
|
+
for (let i = 0; i <= 12; i++) {
|
|
121
|
+
const fresh = reads.listSessions(ws.id).filter(s => !before.has(s.id));
|
|
122
|
+
if (fresh.length > 1) {
|
|
123
|
+
return {
|
|
124
|
+
error: true,
|
|
125
|
+
retryable: false,
|
|
126
|
+
result: {
|
|
127
|
+
ok: false,
|
|
128
|
+
strategy: result.strategy,
|
|
129
|
+
error: 'more than one new chat appeared; refusing to guess which one this request opened'
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
if (fresh[0])
|
|
134
|
+
return { sessionId: fresh[0].id };
|
|
135
|
+
if (i < 12)
|
|
136
|
+
await sleep(500);
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
error: true,
|
|
140
|
+
// A late tab cannot be distinguished from a retry's tab. Do not replay an
|
|
141
|
+
// unconfirmed creation automatically; the user can inspect the workspace.
|
|
142
|
+
retryable: false,
|
|
143
|
+
result: result.ok
|
|
144
|
+
? {
|
|
131
145
|
ok: false,
|
|
132
|
-
strategy:
|
|
133
|
-
error: '
|
|
146
|
+
strategy: result.strategy,
|
|
147
|
+
error: 'Conductor did not confirm a new chat. Check the workspace before trying again.'
|
|
134
148
|
}
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
return { sessionId: fresh[0].id };
|
|
139
|
-
}
|
|
140
|
-
// The tab is almost certainly on screen; only its id is missing. Say so rather than
|
|
141
|
-
// failing the call, so a caller can still tell the user where the work went.
|
|
142
|
-
return { sessionId: null };
|
|
149
|
+
: result
|
|
150
|
+
};
|
|
151
|
+
});
|
|
143
152
|
}
|
|
144
153
|
/**
|
|
145
154
|
* Deliver a prompt to one chat and confirm it landed, retrying until the caller's
|
|
@@ -137,9 +137,6 @@ export function createWorkflowServices(services) {
|
|
|
137
137
|
if ('error' in opened) {
|
|
138
138
|
throw new WorkflowCoordinatorError('workflow_effect_failed', opened.result.error ?? 'Conductor did not open a tracked child chat.', { retryable: opened.retryable !== false });
|
|
139
139
|
}
|
|
140
|
-
if (!opened.sessionId) {
|
|
141
|
-
throw new WorkflowCoordinatorError('workflow_effect_failed', 'Conductor opened a child tab but did not record its exact session ID.');
|
|
142
|
-
}
|
|
143
140
|
return { sessionId: opened.sessionId };
|
|
144
141
|
});
|
|
145
142
|
},
|
|
@@ -171,6 +171,7 @@ export function decodeDelegation(raw) {
|
|
|
171
171
|
createdAt: integer(value.createdAt, 'createdAt'),
|
|
172
172
|
updatedAt: integer(value.updatedAt, 'updatedAt'),
|
|
173
173
|
...(value.handoff === undefined ? {} : { handoff: decodeAttachment(value.handoff) }),
|
|
174
|
+
...(value.assignment === undefined ? {} : { assignment: decodeAttachment(value.assignment) }),
|
|
174
175
|
...(value.sendDelivery === undefined ? {} : { sendDelivery: decodeDelivery(value.sendDelivery, 'sendDelivery') }),
|
|
175
176
|
...(value.sentRowid === undefined ? {} : { sentRowid: integer(value.sentRowid, 'sentRowid', 1) }),
|
|
176
177
|
...(value.completionRowid === undefined
|
|
@@ -1,7 +1,32 @@
|
|
|
1
|
-
import { attachmentPrompt } from "../../files/attachments.js";
|
|
1
|
+
import { attachmentPrompt, writeAttachment } from "../../files/attachments.js";
|
|
2
2
|
import { chatCursor } from "../../transcript/cursor.js";
|
|
3
|
+
/**
|
|
4
|
+
* Conductor's runtime decodes socket chunks independently, so a split UTF-8
|
|
5
|
+
* character can be replaced before the prompt reaches its outbox. Keep new
|
|
6
|
+
* assignments in a file and send only an ASCII reference through that runtime.
|
|
7
|
+
* The reference is persisted with the job before any send. Existing jobs without
|
|
8
|
+
* it must retain the exact inline text used by their saved delivery receipts.
|
|
9
|
+
*/
|
|
10
|
+
export function writeDelegatedAssignment(job, worktree) {
|
|
11
|
+
if (!job.handoff)
|
|
12
|
+
throw new Error('the delegated handoff is missing');
|
|
13
|
+
const body = [
|
|
14
|
+
'# Delegated assignment',
|
|
15
|
+
`Read the parent transcript at ${JSON.stringify(job.handoff.path)} as background context before working.`,
|
|
16
|
+
delegatedPrompt({ ...job, assignment: undefined })
|
|
17
|
+
].join('\n\n');
|
|
18
|
+
const written = writeAttachment(worktree, 'assignment.md', body);
|
|
19
|
+
return { name: written.name, path: written.relPath, bytes: written.bytes, token: written.token };
|
|
20
|
+
}
|
|
3
21
|
/** Ordinary delegation supplies transport context; the saved role and assignment supply the task. */
|
|
4
22
|
export function delegatedPrompt(job) {
|
|
23
|
+
if (job.assignment) {
|
|
24
|
+
return [
|
|
25
|
+
'Read and follow the complete delegated assignment in this UTF-8 file before doing any work:',
|
|
26
|
+
`[Delegated assignment](${encodeURIComponent(job.assignment.path)})`,
|
|
27
|
+
'Read it from the shared worktree, complete the assignment, and put the full result in your final reply.'
|
|
28
|
+
].join('\n\n');
|
|
29
|
+
}
|
|
5
30
|
if (!job.handoff)
|
|
6
31
|
throw new Error('the delegated handoff is missing');
|
|
7
32
|
const parentRead = {
|
|
@@ -26,6 +26,7 @@ export function transitionDelegation(job, status, patch, updatedAt = Date.now())
|
|
|
26
26
|
updatedAt,
|
|
27
27
|
...(patch.childSessionId === undefined ? {} : { childSessionId: patch.childSessionId }),
|
|
28
28
|
...(patch.handoff === undefined ? {} : { handoff: patch.handoff }),
|
|
29
|
+
...(patch.assignment === undefined ? {} : { assignment: patch.assignment }),
|
|
29
30
|
...(patch.sentRowid === undefined ? {} : { sentRowid: patch.sentRowid }),
|
|
30
31
|
...(patch.completionRowid === undefined ? {} : { completionRowid: patch.completionRowid }),
|
|
31
32
|
...(patch.returnCursor === undefined ? {} : { returnCursor: patch.returnCursor }),
|
|
@@ -174,7 +175,7 @@ export class DelegationQueue {
|
|
|
174
175
|
parentSessionId: job.parentSessionId,
|
|
175
176
|
assignedAt: this.now()
|
|
176
177
|
});
|
|
177
|
-
store.put(transitionDelegation(job, 'configuring', { childSessionId: result.childSessionId, handoff: result.handoff }, this.now()));
|
|
178
|
+
store.put(transitionDelegation(job, 'configuring', { childSessionId: result.childSessionId, handoff: result.handoff, assignment: result.assignment }, this.now()));
|
|
178
179
|
return true;
|
|
179
180
|
}
|
|
180
181
|
if (job.status === 'configuring') {
|
package/dist-node/src/shared.js
CHANGED
|
@@ -322,6 +322,15 @@ export function currentModelCatalog(groups) {
|
|
|
322
322
|
}
|
|
323
323
|
return [...models].sort((a, b) => a.localeCompare(b));
|
|
324
324
|
}
|
|
325
|
+
/**
|
|
326
|
+
* Every picker label persisted by the relay, regardless of whether a later menu
|
|
327
|
+
* snapshot retired it. Settings that edit saved choices use this complete list.
|
|
328
|
+
*/
|
|
329
|
+
export function savedModelCatalog(groups) {
|
|
330
|
+
return [
|
|
331
|
+
...new Set(groups.flatMap(group => group.models.map(model => modelPickerLabel(model).trim()).filter(Boolean)))
|
|
332
|
+
].sort((a, b) => a.localeCompare(b));
|
|
333
|
+
}
|
|
325
334
|
/** Stable, case-insensitive grouping shared by every model selector. */
|
|
326
335
|
export function groupModelPickerLabels(models) {
|
|
327
336
|
const grouped = new Map();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "conductor-remote",
|
|
3
|
-
"version": "1.131.
|
|
3
|
+
"version": "1.131.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"packageManager": "yarn@4.15.0",
|
|
6
6
|
"description": "Phone control panel for local Conductor agents. Reads ride SQLite + git; prompts ride Conductor's own dispatch path.",
|