conductor-remote 1.129.0 → 1.130.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/dist/assets/AutoModelSettings-DQAuzuHG.js +1 -0
- package/dist/assets/{PierrePatch-DBoBtHa-.js → PierrePatch-CSMuVBjh.js} +1 -1
- package/dist/assets/index-B4mWU6o0.js +67 -0
- package/dist/assets/index-DD0rU7nR.css +1 -0
- package/dist/index.html +2 -2
- package/dist/sw.js +1 -1
- package/dist-node/src/agents/auto-model/config.js +153 -0
- package/dist-node/src/agents/auto-model/decision.js +101 -0
- package/dist-node/src/agents/auto-model/provider.js +228 -0
- package/dist-node/src/agents/auto-model/queue.js +266 -0
- package/dist-node/src/agents/auto-model/types.js +1 -0
- package/dist-node/src/contracts/agent-inputs.js +2 -0
- package/dist-node/src/http/router.js +2 -0
- package/dist-node/src/http/routes/auto-model.js +26 -0
- package/dist-node/src/http/routes/create-workspace.js +36 -1
- package/dist-node/src/http/routes/prompts.js +56 -4
- package/dist-node/src/http/routes/sessions.js +8 -0
- package/dist-node/src/http/routes/state.js +3 -2
- package/dist-node/src/http/routes/workflows.js +7 -0
- package/dist-node/src/http/routes/workspaces.js +3 -1
- package/dist-node/src/http/services/auto-model.js +108 -0
- package/dist-node/src/http/services/delivery.js +7 -2
- package/dist-node/src/http/services.js +3 -0
- package/dist-node/src/mcp/tools/workspaces.js +2 -0
- package/dist-node/src/prefs.js +2 -0
- package/dist-node/src/routes.js +2 -0
- package/dist-node/src/server.js +2 -1
- package/package.json +1 -1
- package/dist/assets/index-D1kDyIDN.js +0 -67
- package/dist/assets/index-q-Z5Zz9y.css +0 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { freezeAutoModelConfig } from "../../agents/auto-model/config.js";
|
|
1
2
|
import { hasAgentSettings, sendPromptSchema } from "../../contracts/agent-inputs.js";
|
|
2
3
|
import { parseInput } from "../../contracts/validation.js";
|
|
3
4
|
import { attachmentPrompt, writeAttachment } from "../../files/attachments.js";
|
|
@@ -71,6 +72,47 @@ export function createPromptsRoutes(services) {
|
|
|
71
72
|
: (reads.listWorkspaces().find(w => w.active_session_id === sessionId) ?? null);
|
|
72
73
|
if (!ws)
|
|
73
74
|
return json(req, res, 404, { error: 'workspace for session not found' });
|
|
75
|
+
const autoJob = services.autoModels?.get(sessionId, ws.id);
|
|
76
|
+
const useAuto = body.auto === true ||
|
|
77
|
+
(body.auto !== false && autoJob?.status === 'draft') ||
|
|
78
|
+
(!!autoJob && ['waiting', 'selecting', 'failed'].includes(autoJob.status));
|
|
79
|
+
if (useAuto) {
|
|
80
|
+
if (!services.autoModels || !services.autoModelConfig || !services.inspectAutoTarget)
|
|
81
|
+
return json(req, res, 503, { error: 'Auto is unavailable.' });
|
|
82
|
+
if (body.queue || requestedAgent)
|
|
83
|
+
return json(req, res, 400, {
|
|
84
|
+
error: 'Auto selects settings for the first message. Omit manual settings and queue mode.'
|
|
85
|
+
});
|
|
86
|
+
try {
|
|
87
|
+
if (!autoJob || ['draft', 'cancelled'].includes(autoJob.status)) {
|
|
88
|
+
const target = services.inspectAutoTarget({ workspaceId: ws.id, sessionId });
|
|
89
|
+
if (target.error)
|
|
90
|
+
return json(req, res, 409, { error: target.error });
|
|
91
|
+
}
|
|
92
|
+
const job = services.autoModels.accept({
|
|
93
|
+
workspaceId: ws.id,
|
|
94
|
+
sessionId,
|
|
95
|
+
text: rawText,
|
|
96
|
+
repo: ws.repo_name ?? '',
|
|
97
|
+
config: autoJob && !['draft', 'cancelled'].includes(autoJob.status)
|
|
98
|
+
? autoJob.config
|
|
99
|
+
: freezeAutoModelConfig(services.autoModelConfig.read(), modelCache.list())
|
|
100
|
+
});
|
|
101
|
+
return json(req, res, job.status === 'delivered' ? 200 : 202, {
|
|
102
|
+
ok: job.status === 'delivered',
|
|
103
|
+
parked: job.status !== 'delivered',
|
|
104
|
+
strategy: actuator.name,
|
|
105
|
+
queued: services.autoModels.pending().find(p => p.sessionId === sessionId)
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
return json(req, res, 409, {
|
|
110
|
+
error: error instanceof Error ? error.message : 'Auto could not accept this prompt.'
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (autoJob?.status === 'draft' && body.auto === false)
|
|
115
|
+
services.autoModels?.cancel(sessionId, ws.id);
|
|
74
116
|
// One deadline for the whole request: settings eat into the send's budget
|
|
75
117
|
// rather than extending it past what the phone said it would wait.
|
|
76
118
|
const deadline = Date.now() + sendBudget(req);
|
|
@@ -338,16 +380,26 @@ export function createPromptsRoutes(services) {
|
|
|
338
380
|
const forgetFirst = routeParam(routes.dismissFirstPrompt, req.method, pathname);
|
|
339
381
|
if (forgetFirst) {
|
|
340
382
|
const workspaceId = forgetFirst;
|
|
341
|
-
|
|
342
|
-
|
|
383
|
+
try {
|
|
384
|
+
if (!services.autoModels?.cancel(undefined, workspaceId) && !firstPrompts.forget(workspaceId))
|
|
385
|
+
return json(req, res, 404, { error: 'no pending prompt' });
|
|
386
|
+
}
|
|
387
|
+
catch (error) {
|
|
388
|
+
return json(req, res, 409, { error: error instanceof Error ? error.message : 'Auto is sending.' });
|
|
389
|
+
}
|
|
343
390
|
return json(req, res, 200, { ok: true });
|
|
344
391
|
}
|
|
345
392
|
// DELETE /api/sessions/:id/prompt — dismiss whatever is parked for this chat
|
|
346
393
|
const forgetParked = routeParam(routes.dismissParkedPrompt, req.method, pathname);
|
|
347
394
|
if (forgetParked) {
|
|
348
395
|
const sessionId = forgetParked;
|
|
349
|
-
|
|
350
|
-
|
|
396
|
+
try {
|
|
397
|
+
if (!services.autoModels?.cancel(sessionId) && !parkedPrompts.forgetSession(sessionId))
|
|
398
|
+
return json(req, res, 404, { error: 'no parked prompt' });
|
|
399
|
+
}
|
|
400
|
+
catch (error) {
|
|
401
|
+
return json(req, res, 409, { error: error instanceof Error ? error.message : 'Auto is sending.' });
|
|
402
|
+
}
|
|
351
403
|
return json(req, res, 200, { ok: true });
|
|
352
404
|
}
|
|
353
405
|
return NOT_HANDLED;
|
|
@@ -12,6 +12,14 @@ export function createSessionsRoutes(services) {
|
|
|
12
12
|
const { json, reads, workflowFrozenError, locateChat, modelCache, readBody, applyAgentPatch, actuator, sleep, attachmentHeaderName, readAttachmentBody } = services;
|
|
13
13
|
return async (req, res, url) => {
|
|
14
14
|
const { pathname } = url;
|
|
15
|
+
const changingAgent = routeParam(routes.agent, req.method, pathname) ?? routeParam(routes.defaultModel, req.method, pathname);
|
|
16
|
+
if (changingAgent) {
|
|
17
|
+
const auto = services.autoModels?.get(changingAgent);
|
|
18
|
+
if (auto && ['selecting', 'waiting', 'failed'].includes(auto.status))
|
|
19
|
+
return json(req, res, 409, {
|
|
20
|
+
error: 'Auto owns the initial settings until this submission is delivered or dismissed.'
|
|
21
|
+
});
|
|
22
|
+
}
|
|
15
23
|
// PWA presentation only: preserve both real tabs and all their original messages.
|
|
16
24
|
const joinHistoryOf = routeParam(routes.joinChatHistory, req.method, pathname);
|
|
17
25
|
if (joinHistoryOf) {
|
|
@@ -29,9 +29,10 @@ export function createStateRoutes(services) {
|
|
|
29
29
|
// Prompts parked for the lock screen ride the same way, one list per workspace,
|
|
30
30
|
// each entry naming its chat (src/delivery/parked.ts).
|
|
31
31
|
const parked = parkedPrompts.list();
|
|
32
|
+
const auto = services.autoModels?.pending() ?? [];
|
|
32
33
|
for (const ws of workspaces) {
|
|
33
|
-
ws.pending_prompt = firstPrompts.get(ws.id);
|
|
34
|
-
const mine = parked.filter(p => p.workspaceId === ws.id);
|
|
34
|
+
ws.pending_prompt = firstPrompts.get(ws.id) ?? auto.find(p => p.workspaceId === ws.id && !p.sessionId);
|
|
35
|
+
const mine = [...parked, ...auto.filter((p) => !!p.sessionId)].filter(p => p.workspaceId === ws.id);
|
|
35
36
|
if (mine.length)
|
|
36
37
|
ws.parked_prompts = mine;
|
|
37
38
|
}
|
|
@@ -47,6 +47,13 @@ export function createWorkflowsRoutes(services) {
|
|
|
47
47
|
throw new WorkflowCoordinatorError('workflow_incompatible_relay', `Workflow is disabled because ${orchestrationUnavailableReason()}.`, { status: 409 });
|
|
48
48
|
}
|
|
49
49
|
const request = parseStartWorkflowRequest(await workflowRequestBody(req));
|
|
50
|
+
if (request.target.kind === 'existing_session') {
|
|
51
|
+
const auto = services.autoModels?.get(request.target.sessionId, request.target.workspaceId);
|
|
52
|
+
if (auto && ['waiting', 'selecting', 'failed'].includes(auto.status))
|
|
53
|
+
return json(req, res, 409, { error: 'Dismiss the Auto submission before starting Workflow.' });
|
|
54
|
+
if (auto?.status === 'draft')
|
|
55
|
+
services.autoModels?.cancel(request.target.sessionId, request.target.workspaceId);
|
|
56
|
+
}
|
|
50
57
|
const replay = orchestration.getIdempotentMutation('start_workflow', request.clientId, {
|
|
51
58
|
objective: request.objective,
|
|
52
59
|
target: request.target
|
|
@@ -28,7 +28,9 @@ export function createWorkspacesRoutes(services) {
|
|
|
28
28
|
attachWorkflowState([enriched]);
|
|
29
29
|
const sessionRoles = { ...(roles?.sessions ?? {}), ...(enriched?.session_roles ?? {}) };
|
|
30
30
|
return json(req, res, 200, {
|
|
31
|
-
sessions: reads
|
|
31
|
+
sessions: reads
|
|
32
|
+
.listSessions(listSessionsIn)
|
|
33
|
+
.map(session => ({ ...session, auto_model: services.autoModels?.state(session.id, listSessionsIn) })),
|
|
32
34
|
chat_history: services.chatHistory.forWorkspace(listSessionsIn),
|
|
33
35
|
...(Object.keys(sessionRoles).length ? { session_roles: sessionRoles } : {})
|
|
34
36
|
});
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { AutoModelConfigStore } from "../../agents/auto-model/config.js";
|
|
3
|
+
import { chooseAutoModel, routingInput } from "../../agents/auto-model/decision.js";
|
|
4
|
+
import { runRouter } from "../../agents/auto-model/provider.js";
|
|
5
|
+
import { AutoModelQueue } from "../../agents/auto-model/queue.js";
|
|
6
|
+
import { roleModelIssues } from "../../agents/roles.js";
|
|
7
|
+
import { stateDir } from "../../config.js";
|
|
8
|
+
import { materializeStagedAttachments } from "../../files/staged-attachments.js";
|
|
9
|
+
import { modelAgentType } from "../../shared.js";
|
|
10
|
+
import { lockBlocked, screenLocked } from "../../writes/guards.js";
|
|
11
|
+
import { uiTurn, withUiPriority } from "../../writes/ui-lock.js";
|
|
12
|
+
export function createAutoModelServices(services) {
|
|
13
|
+
const { reads, modelCache, delegationStore, workflowOwningSession, firstPrompts, parkedPrompts, applyAgentPatch, deliverPrompt, STAGED_ATTACHMENTS_DIR } = services;
|
|
14
|
+
const autoModelConfig = new AutoModelConfigStore(path.join(stateDir(), 'auto-model.json'));
|
|
15
|
+
const received = (job) => !!(job.sessionId &&
|
|
16
|
+
job.cursor &&
|
|
17
|
+
reads.deliveryReceiptSince(job.sessionId, job.text, {
|
|
18
|
+
rowid: job.cursor.rowid,
|
|
19
|
+
outboxIds: new Set(job.cursor.outboxIds)
|
|
20
|
+
}));
|
|
21
|
+
function inspect(job) {
|
|
22
|
+
const ws = reads.getWorkspace(job.workspaceId);
|
|
23
|
+
if (!ws)
|
|
24
|
+
return { ready: false, error: 'The Auto workspace is no longer available.' };
|
|
25
|
+
const sessions = reads.listSessions(ws.id);
|
|
26
|
+
const session = job.sessionId
|
|
27
|
+
? sessions.find(s => s.id === job.sessionId)
|
|
28
|
+
: sessions.length === 1
|
|
29
|
+
? sessions[0]
|
|
30
|
+
: undefined;
|
|
31
|
+
const target = { ready: ws.state === 'ready', worktree: ws.worktree, sessionId: session?.id };
|
|
32
|
+
if (!session)
|
|
33
|
+
return {
|
|
34
|
+
...target,
|
|
35
|
+
error: sessions.length > 1 || job.sessionId ? 'The Auto chat is missing or ambiguous.' : undefined
|
|
36
|
+
};
|
|
37
|
+
const roles = delegationStore(ws)?.sessionRoles();
|
|
38
|
+
if (workflowOwningSession(session.id) || roles?.sessions[session.id] || roles?.warning) {
|
|
39
|
+
return { ...target, error: 'Auto is unavailable in a chat owned by a Workflow or delegation.' };
|
|
40
|
+
}
|
|
41
|
+
if (firstPrompts.get(ws.id) || parkedPrompts.list().some(p => p.sessionId === session.id)) {
|
|
42
|
+
return { ...target, error: 'Resolve this chat’s pending prompt before using Auto.' };
|
|
43
|
+
}
|
|
44
|
+
if (session.last_user_message_at ||
|
|
45
|
+
(session.status && session.status !== 'idle') ||
|
|
46
|
+
session.background_tasks.length ||
|
|
47
|
+
reads.deliveryCursor(session.id).outboxIds.size ||
|
|
48
|
+
reads.getMessages(session.id).entries.some(entry => entry.role === 'user')) {
|
|
49
|
+
return { ...target, obsolete: true, error: 'Auto is available only before the first message in an idle chat.' };
|
|
50
|
+
}
|
|
51
|
+
return target;
|
|
52
|
+
}
|
|
53
|
+
const autoModels = new AutoModelQueue(path.join(stateDir(), 'auto-model-prompts'), {
|
|
54
|
+
inspect,
|
|
55
|
+
received,
|
|
56
|
+
locked: async () => (await screenLocked()) === true,
|
|
57
|
+
cursor: sessionId => {
|
|
58
|
+
const cursor = reads.deliveryCursor(sessionId);
|
|
59
|
+
return { rowid: cursor.rowid, outboxIds: [...cursor.outboxIds] };
|
|
60
|
+
},
|
|
61
|
+
materialize: (job, worktree) => materializeStagedAttachments(STAGED_ATTACHMENTS_DIR, worktree, job.attachmentIds),
|
|
62
|
+
choose: (job, worktree) => chooseAutoModel(job.config, routingInput(job.text, job.repo, worktree), (prompt, images, signal) => runRouter(job.config.router, prompt, images, signal)),
|
|
63
|
+
deliver: (job, current, dispatch) => withUiPriority('background', () => uiTurn(async () => {
|
|
64
|
+
if (!current())
|
|
65
|
+
return { ok: false, error: 'Auto cancelled.' };
|
|
66
|
+
if (received(job))
|
|
67
|
+
return { ok: true };
|
|
68
|
+
const target = inspect(job);
|
|
69
|
+
if (target.error)
|
|
70
|
+
return { ok: false, error: target.error, cancelled: target.obsolete };
|
|
71
|
+
const ws = reads.getWorkspace(job.workspaceId);
|
|
72
|
+
if (!ws || !job.sessionId || !job.decision || !job.cursor)
|
|
73
|
+
return { ok: false, error: 'Auto’s saved target is incomplete.' };
|
|
74
|
+
const { model, effort, fast } = job.decision;
|
|
75
|
+
// A vanished selected profile must remain a visible failure, never a silent reroute.
|
|
76
|
+
const issues = roleModelIssues({ version: 1, roles: { selected: { model, effort, fast } } }, modelCache.list());
|
|
77
|
+
if (issues.length)
|
|
78
|
+
return {
|
|
79
|
+
ok: false,
|
|
80
|
+
error: 'The saved Auto model is no longer available. Dismiss this submission and choose another model.'
|
|
81
|
+
};
|
|
82
|
+
dispatch();
|
|
83
|
+
const applied = await applyAgentPatch(ws, job.sessionId, {
|
|
84
|
+
model,
|
|
85
|
+
effort,
|
|
86
|
+
fast,
|
|
87
|
+
...(modelAgentType(model) === 'claude' ? { plan: false } : {})
|
|
88
|
+
});
|
|
89
|
+
if (!applied.ok)
|
|
90
|
+
return { ok: false, error: applied.error, blocked: lockBlocked(applied.error) };
|
|
91
|
+
if (received(job))
|
|
92
|
+
return { ok: true };
|
|
93
|
+
const fresh = inspect(job);
|
|
94
|
+
if (fresh.error || !current())
|
|
95
|
+
return { ok: false, error: fresh.error ?? 'Auto cancelled.', cancelled: fresh.obsolete };
|
|
96
|
+
const result = await deliverPrompt(ws, job.sessionId, job.text, undefined, false, {
|
|
97
|
+
rowid: job.cursor.rowid,
|
|
98
|
+
outboxIds: new Set(job.cursor.outboxIds)
|
|
99
|
+
});
|
|
100
|
+
return { ok: result.ok, error: result.error, blocked: lockBlocked(result.error) };
|
|
101
|
+
}))
|
|
102
|
+
});
|
|
103
|
+
services.setAdditionalStagedReferences(() => autoModels
|
|
104
|
+
.list()
|
|
105
|
+
.filter(job => !['delivered', 'cancelled'].includes(job.status))
|
|
106
|
+
.flatMap(job => job.attachmentIds));
|
|
107
|
+
return { autoModels, autoModelConfig, inspectAutoTarget: inspect };
|
|
108
|
+
}
|
|
@@ -292,8 +292,12 @@ export function createDeliveryServices(services) {
|
|
|
292
292
|
/** Unreferenced pre-workspace uploads get one week for an offline device to reconnect. */
|
|
293
293
|
const STAGED_ATTACHMENT_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
|
|
294
294
|
const STAGED_ATTACHMENT_SWEEP_MS = 6 * 60 * 60 * 1000;
|
|
295
|
+
let additionalStagedReferences = () => [];
|
|
296
|
+
function setAdditionalStagedReferences(read) {
|
|
297
|
+
additionalStagedReferences = read;
|
|
298
|
+
}
|
|
295
299
|
function referencedStagedAttachments() {
|
|
296
|
-
const referenced = new Set();
|
|
300
|
+
const referenced = new Set(additionalStagedReferences());
|
|
297
301
|
for (const draft of Object.values(readPrefs().drafts)) {
|
|
298
302
|
if (draft.deleted)
|
|
299
303
|
continue;
|
|
@@ -422,6 +426,7 @@ export function createDeliveryServices(services) {
|
|
|
422
426
|
sendOnce,
|
|
423
427
|
PARKED_ERROR,
|
|
424
428
|
sweepStagedAttachments,
|
|
425
|
-
STAGED_ATTACHMENT_SWEEP_MS
|
|
429
|
+
STAGED_ATTACHMENT_SWEEP_MS,
|
|
430
|
+
setAdditionalStagedReferences
|
|
426
431
|
};
|
|
427
432
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createAutoModelServices } from "./services/auto-model.js";
|
|
1
2
|
import { createBaseServices } from "./services/base.js";
|
|
2
3
|
import { createDelegationsServices } from "./services/delegations.js";
|
|
3
4
|
import { createDeliveryServices } from "./services/delivery.js";
|
|
@@ -17,11 +18,13 @@ export function createRelayServices() {
|
|
|
17
18
|
const delivery = createDeliveryServices({ ...base });
|
|
18
19
|
const delegations = createDelegationsServices({ ...base, ...delivery });
|
|
19
20
|
const workflowState = createWorkflowStateServices({ ...base, ...responses });
|
|
21
|
+
const autoModel = createAutoModelServices({ ...base, ...delivery, ...workflowState });
|
|
20
22
|
const workflowProbes = createWorkflowProbesServices({ ...base, ...delivery });
|
|
21
23
|
const workflow = createWorkflowServices({ ...base, ...workflowProbes, ...delivery, ...delegations });
|
|
22
24
|
const files = createFilesServices({ ...responses, ...base });
|
|
23
25
|
return {
|
|
24
26
|
...base,
|
|
27
|
+
...autoModel,
|
|
25
28
|
...responses,
|
|
26
29
|
...mcp,
|
|
27
30
|
...voice,
|
|
@@ -86,6 +86,8 @@ export function createListReposTool(call) {
|
|
|
86
86
|
}
|
|
87
87
|
const createWorkspaceInputSchema = createWorkspaceSchema
|
|
88
88
|
.omit({
|
|
89
|
+
// Auto is selected in the PWA; keep this tool's explicit agent settings contract.
|
|
90
|
+
auto: true,
|
|
89
91
|
send: true,
|
|
90
92
|
sendImmediately: true,
|
|
91
93
|
attachmentIds: true
|
package/dist-node/src/prefs.js
CHANGED
|
@@ -32,6 +32,8 @@ function sanitizeAgent(raw) {
|
|
|
32
32
|
if (!value)
|
|
33
33
|
return {};
|
|
34
34
|
const agent = {};
|
|
35
|
+
if (typeof value.auto === 'boolean')
|
|
36
|
+
agent.auto = value.auto;
|
|
35
37
|
if (typeof value.model === 'string' && value.model.length <= MAX_AGENT_LABEL_LENGTH)
|
|
36
38
|
agent.model = value.model;
|
|
37
39
|
if (isAgentEffort(value.effort))
|
package/dist-node/src/routes.js
CHANGED
|
@@ -103,6 +103,8 @@ export const routes = {
|
|
|
103
103
|
pushTest: flat('POST', '/api/push/test'),
|
|
104
104
|
/** Global picker-backed delegated-role definitions. */
|
|
105
105
|
roles: flat('GET', '/api/roles'),
|
|
106
|
+
autoModelConfig: flat('GET', '/api/auto-model'),
|
|
107
|
+
updateAutoModelConfig: flat('PATCH', '/api/auto-model'),
|
|
106
108
|
updateRoles: flat('PATCH', '/api/roles'),
|
|
107
109
|
/** Active and failed jobs; optionally filtered with `?workspaceId=`. */
|
|
108
110
|
delegations: flat('GET', '/api/delegations'),
|
package/dist-node/src/server.js
CHANGED
|
@@ -7,7 +7,7 @@ import { createRelayServices } from "./http/services.js";
|
|
|
7
7
|
import { startNotifier } from "./notifications/notify.js";
|
|
8
8
|
import { voicePort } from "./voice/config.js";
|
|
9
9
|
const services = createRelayServices();
|
|
10
|
-
const { cfg, voiceServer, voiceBroker, voiceHistory, orchestration, relayIdentity, recoverUiLease, wakeWorkflows, actuator, firstPrompts, sweepStagedAttachments, STAGED_ATTACHMENT_SWEEP_MS, parkedPrompts, delegationQueue, liveDelegationStores, devServers, reads, sessionPoller } = services;
|
|
10
|
+
const { cfg, voiceServer, voiceBroker, voiceHistory, orchestration, relayIdentity, recoverUiLease, wakeWorkflows, actuator, firstPrompts, autoModels, sweepStagedAttachments, STAGED_ATTACHMENT_SWEEP_MS, parkedPrompts, delegationQueue, liveDelegationStores, devServers, reads, sessionPoller } = services;
|
|
11
11
|
const server = createRelayServer(services);
|
|
12
12
|
server.listen(cfg.port, cfg.host, () => {
|
|
13
13
|
voiceServer.listen(voicePort(), '127.0.0.1', () => {
|
|
@@ -51,6 +51,7 @@ server.listen(cfg.port, cfg.host, () => {
|
|
|
51
51
|
// Pick up any first prompt the previous process was still holding — an auto-update
|
|
52
52
|
// restart lands mid-setup often enough that this is the normal path, not a rare one.
|
|
53
53
|
firstPrompts.start();
|
|
54
|
+
autoModels.start();
|
|
54
55
|
// New Workspace uploads are host-side so another device can restore their pills.
|
|
55
56
|
// Sweep only week-old directories absent from both a draft and the delivery queue.
|
|
56
57
|
sweepStagedAttachments();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "conductor-remote",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.130.1",
|
|
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.",
|