conductor-remote 1.96.2 → 1.96.3
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/README.md +41 -8
- package/dist/assets/index-7EOD11nV.css +1 -0
- package/dist/assets/index-BtAuvfL4.js +52 -0
- package/dist/index.html +2 -2
- package/dist/sw.js +1 -1
- package/dist-node/src/agent-config.js +76 -0
- package/dist-node/src/conductor.applescript +24 -8
- package/dist-node/src/delegations.js +556 -0
- package/dist-node/src/firstprompt.js +15 -1
- package/dist-node/src/mcp-tools.js +182 -8
- package/dist-node/src/notify.js +9 -14
- package/dist-node/src/reads.js +21 -1
- package/dist-node/src/roles.js +195 -0
- package/dist-node/src/routes.js +9 -0
- package/dist-node/src/server.js +731 -53
- package/dist-node/src/session-poller.js +51 -0
- package/dist-node/src/shared.js +89 -0
- package/dist-node/src/workflow.js +33 -0
- package/dist-node/src/writes.js +26 -3
- package/package.json +1 -1
- package/dist/assets/index-35kfVzU0.css +0 -1
- package/dist/assets/index-DS9xqkPd.js +0 -50
package/dist/index.html
CHANGED
|
@@ -25,8 +25,8 @@
|
|
|
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-
|
|
29
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
28
|
+
<script type="module" crossorigin src="/assets/index-BtAuvfL4.js"></script>
|
|
29
|
+
<link rel="stylesheet" crossorigin href="/assets/index-7EOD11nV.css">
|
|
30
30
|
<link rel="manifest" href="/manifest.webmanifest"></head>
|
|
31
31
|
<body>
|
|
32
32
|
<div id="root"></div>
|
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 o=e||("document"in self?document.currentScript.src:"")||location.href;if(s[o])return;let l={};const
|
|
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 o=e||("document"in self?document.currentScript.src:"")||location.href;if(s[o])return;let l={};const t=e=>i(e,o),c={module:{uri:o},exports:l,require:t};s[o]=Promise.all(n.map(e=>c[e]||t(e))).then(e=>(r(...e),l))}}define(["./workbox-9c191d2f"],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:"e7ef44deca46c0539e6ff7bba5eb815e"},{url:"index.html",revision:"679a9174a36942457a716182f6c1d863"},{url:"assets/workbox-window.prod.es5-BBnX5xw4.js",revision:null},{url:"assets/index-BtAuvfL4.js",revision:null},{url:"assets/index-7EOD11nV.css",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\//]}))});
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { modelAgentType, modelLabel, modelPickerLabel, shortModel } from "./shared.js";
|
|
2
|
+
function modelMatches(state, requested, allowPrefix = false) {
|
|
3
|
+
const label = modelPickerLabel(requested).trim();
|
|
4
|
+
const expectedAgentType = modelAgentType(label);
|
|
5
|
+
const actualLabel = modelPickerLabel(modelLabel(state.model, [label]));
|
|
6
|
+
const stored = shortModel(state.model).toLowerCase();
|
|
7
|
+
const wanted = label.toLowerCase();
|
|
8
|
+
const selected = actualLabel.toLowerCase() === wanted ||
|
|
9
|
+
stored === wanted ||
|
|
10
|
+
stored.endsWith(`:${wanted}`) ||
|
|
11
|
+
(allowPrefix && actualLabel.toLowerCase().startsWith(wanted));
|
|
12
|
+
return (!expectedAgentType || state.agentType === expectedAgentType) && selected;
|
|
13
|
+
}
|
|
14
|
+
function matches(state, patch) {
|
|
15
|
+
return ((!patch.model || modelMatches(state, patch.model, true)) &&
|
|
16
|
+
(!patch.effort || state.effort === patch.effort) &&
|
|
17
|
+
(patch.plan === undefined || state.plan === patch.plan) &&
|
|
18
|
+
(patch.fast === undefined || state.fast === patch.fast));
|
|
19
|
+
}
|
|
20
|
+
async function confirm(deps, predicate) {
|
|
21
|
+
const attempts = deps.confirmAttempts ?? 10;
|
|
22
|
+
for (let attempt = 0; attempt < attempts; attempt++) {
|
|
23
|
+
const current = deps.read();
|
|
24
|
+
if (current && predicate(current))
|
|
25
|
+
return current;
|
|
26
|
+
if (attempt + 1 < attempts)
|
|
27
|
+
await deps.wait();
|
|
28
|
+
}
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
function modelFailure(model) {
|
|
32
|
+
const agentType = modelAgentType(model);
|
|
33
|
+
const provider = agentType === 'claude' ? 'Claude' : agentType === 'codex' ? 'Codex' : agentType;
|
|
34
|
+
return provider
|
|
35
|
+
? `Conductor did not record model ${model} on the expected ${provider} provider.`
|
|
36
|
+
: `Conductor did not record model ${model}.`;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Apply one desired role snapshot without holding stale AX references across a
|
|
40
|
+
* provider-changing rerender. The model gets its own UI pass and DB receipt;
|
|
41
|
+
* only then are the new provider's controls reacquired and changed by delta.
|
|
42
|
+
*/
|
|
43
|
+
export async function applyAgentConfig(patch, deps) {
|
|
44
|
+
let current = deps.read();
|
|
45
|
+
if (!current)
|
|
46
|
+
return { ok: false, error: 'the chat is gone' };
|
|
47
|
+
if (patch.model && !modelMatches(current, patch.model)) {
|
|
48
|
+
const requestedModel = patch.model;
|
|
49
|
+
const selected = await deps.write({ model: requestedModel });
|
|
50
|
+
if (!selected.ok)
|
|
51
|
+
return selected;
|
|
52
|
+
// setModel accepts a unique picker prefix. It has already proved uniqueness
|
|
53
|
+
// before this receipt, so the stored full label may legitimately be longer.
|
|
54
|
+
current = await confirm(deps, state => modelMatches(state, requestedModel, true));
|
|
55
|
+
if (!current)
|
|
56
|
+
return { ok: false, error: modelFailure(requestedModel) };
|
|
57
|
+
}
|
|
58
|
+
const controls = {};
|
|
59
|
+
if (patch.effort && current.effort !== patch.effort)
|
|
60
|
+
controls.effort = patch.effort;
|
|
61
|
+
if (patch.plan !== undefined && current.plan !== patch.plan)
|
|
62
|
+
controls.plan = patch.plan;
|
|
63
|
+
if (patch.fast !== undefined && current.fast !== patch.fast)
|
|
64
|
+
controls.toggleFast = true;
|
|
65
|
+
if (Object.keys(controls).length) {
|
|
66
|
+
controls.agentType = current.agentType;
|
|
67
|
+
const applied = await deps.write(controls);
|
|
68
|
+
if (!applied.ok)
|
|
69
|
+
return applied;
|
|
70
|
+
}
|
|
71
|
+
const recorded = await confirm(deps, state => matches(state, patch));
|
|
72
|
+
if (!recorded) {
|
|
73
|
+
return { ok: false, error: 'Conductor did not record every requested agent setting.' };
|
|
74
|
+
}
|
|
75
|
+
return { ok: true };
|
|
76
|
+
}
|
|
@@ -1639,22 +1639,37 @@ end controlNamed
|
|
|
1639
1639
|
|
|
1640
1640
|
on effortButton()
|
|
1641
1641
|
-- The effort control is a button whose *label is its current value*, so it is
|
|
1642
|
-
-- identified by that label rather than a stable name.
|
|
1643
|
-
|
|
1642
|
+
-- identified by that label rather than a stable name. Claude calls its top
|
|
1643
|
+
-- level Ultracode while Codex calls the corresponding level Ultra. Codex's
|
|
1644
|
+
-- None state is the exception: its button has no accessible name at all, so
|
|
1645
|
+
-- accept one (and only one) unnamed button *after* the proven model picker.
|
|
1646
|
+
-- The main composer also contains unnamed attachment/stop buttons before that
|
|
1647
|
+
-- picker, and pressing one of those would be worse than failing.
|
|
1648
|
+
set levels to {"Light", "Low", "Medium", "High", "Extra high", "Max", "Ultracode", "Ultra"}
|
|
1649
|
+
set sawModel to false
|
|
1650
|
+
set unnamed to {}
|
|
1644
1651
|
repeat with entry in my composerControls()
|
|
1645
1652
|
set c to contents of entry
|
|
1646
|
-
if my
|
|
1653
|
+
if (my axRole(c)) is "AXPopUpButton" and (my axName(c)) contains "Change agent" then
|
|
1654
|
+
set sawModel to true
|
|
1655
|
+
else if sawModel and (my axRole(c)) is "AXButton" then
|
|
1656
|
+
set label to my axName(c)
|
|
1657
|
+
if label is in levels then return c
|
|
1658
|
+
if label is "" then set end of unnamed to c
|
|
1659
|
+
end if
|
|
1647
1660
|
end repeat
|
|
1661
|
+
if (count of unnamed) is 1 then return item 1 of unnamed
|
|
1648
1662
|
return missing value
|
|
1649
1663
|
end effortButton
|
|
1650
1664
|
|
|
1651
1665
|
on setEffort(wanted)
|
|
1652
|
-
--
|
|
1653
|
-
--
|
|
1666
|
+
-- Claude owns a six-value ring ending in Ultracode; Codex adds None and ends
|
|
1667
|
+
-- in Ultra. Step around either ring once and confirm the label landed.
|
|
1654
1668
|
set btn to my effortButton()
|
|
1655
1669
|
if btn is missing value then error "couldn't find the effort control"
|
|
1656
|
-
repeat
|
|
1657
|
-
|
|
1670
|
+
repeat 8 times
|
|
1671
|
+
set currentLabel to my axName(btn)
|
|
1672
|
+
if currentLabel is wanted or (wanted is "__UNNAMED_EFFORT__" and currentLabel is "") then return
|
|
1658
1673
|
tell application "System Events" to tell process "Conductor"
|
|
1659
1674
|
perform action "AXPress" of btn
|
|
1660
1675
|
end tell
|
|
@@ -1883,6 +1898,7 @@ on setModel(wanted)
|
|
|
1883
1898
|
if (count of loose) > 1 then error "several models match " & wanted
|
|
1884
1899
|
error "no model named " & wanted
|
|
1885
1900
|
end if
|
|
1901
|
+
set chosenLabel to my firstLine(my tabLabel(chosen))
|
|
1886
1902
|
tell application "System Events" to tell process "Conductor"
|
|
1887
1903
|
perform action "AXPress" of chosen
|
|
1888
1904
|
end tell
|
|
@@ -1893,7 +1909,7 @@ on setModel(wanted)
|
|
|
1893
1909
|
if my tabLabel(c) contains "Change agent" then set popup to c
|
|
1894
1910
|
end repeat
|
|
1895
1911
|
if popup is missing value then error "the model picker vanished"
|
|
1896
|
-
if not my pickerShowsModel(popup,
|
|
1912
|
+
if not my pickerShowsModel(popup, chosenLabel) then error "the model didn't switch to " & chosenLabel
|
|
1897
1913
|
end setModel
|
|
1898
1914
|
|
|
1899
1915
|
on listModels()
|