mirror of
https://github.com/hansjone/dsh-ops-cron.git
synced 2026-10-09 04:13:14 +08:00
Inherit agent presets and auto-bind IM delivery targets (0.1.7).
Cron jobs created from WhatsApp can omit bot/target ids and reuse chat overrides; sidebar/agent preset pins persist on fire. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
2f08136adf
commit
2e690c30c8
15 changed files with 830 additions and 82 deletions
85
lib/host.js
85
lib/host.js
|
|
@ -8,7 +8,7 @@ import { mkdir } from 'node:fs/promises'
|
|||
import { homedir } from 'node:os'
|
||||
import { basename, join } from 'node:path'
|
||||
import { claimOccurrence, executeClaimedRun, extractAssistantText, interruptActiveRuns, publicJob, settleRun, TITLE_PREFIX } from './fire.js'
|
||||
import { deliverRunToIm } from './delivery.js'
|
||||
import { deliverRunToIm, mergeDeliveryMention } from './delivery.js'
|
||||
import { workspaceVisibleIds } from './isolation.js'
|
||||
import { decideDispatch, nextFire, validateSchedule } from './scheduler.js'
|
||||
import {
|
||||
|
|
@ -174,7 +174,10 @@ export function createHostService(options = {}) {
|
|||
provider: patch.provider !== undefined ? patch.provider : job.provider,
|
||||
model: patch.model !== undefined ? patch.model : job.model,
|
||||
reasoningEffort: patch.reasoningEffort !== undefined ? patch.reasoningEffort : job.reasoningEffort,
|
||||
delivery: patch.delivery !== undefined ? patch.delivery : job.delivery,
|
||||
agentPreset: patch.agentPreset !== undefined ? patch.agentPreset : job.agentPreset,
|
||||
delivery: patch.delivery !== undefined
|
||||
? mergeDeliveryMention(job.delivery, patch.delivery)
|
||||
: job.delivery,
|
||||
}
|
||||
const record = createJobRecord(nextInput, current, t)
|
||||
record.createdAt = job.createdAt
|
||||
|
|
@ -375,6 +378,14 @@ export function createHostService(options = {}) {
|
|||
return
|
||||
}
|
||||
|
||||
if (path === `${API_PREFIX}/presets` && method === 'GET') {
|
||||
const catalog = typeof sessionPort?.listPresets === 'function'
|
||||
? await sessionPort.listPresets()
|
||||
: { items: [], current: null }
|
||||
write(200, { ok: true, ...catalog })
|
||||
return
|
||||
}
|
||||
|
||||
if (path === `${API_PREFIX}/workspaces` && method === 'GET') {
|
||||
const workspaces = typeof sessionPort?.listWorkspaces === 'function'
|
||||
? await sessionPort.listWorkspaces()
|
||||
|
|
@ -383,6 +394,35 @@ export function createHostService(options = {}) {
|
|||
return
|
||||
}
|
||||
|
||||
if (path === `${API_PREFIX}/im-catalog` && method === 'GET') {
|
||||
const dshIm = getDshIm()
|
||||
if (!dshIm || typeof dshIm.listDeliveryCatalog !== 'function') {
|
||||
write(200, {
|
||||
ok: true,
|
||||
available: false,
|
||||
options: [],
|
||||
hint: 'dsh-im-ops missing or outdated — install ≥ops.24 for delivery picker',
|
||||
})
|
||||
return
|
||||
}
|
||||
try {
|
||||
const options = await dshIm.listDeliveryCatalog()
|
||||
write(200, {
|
||||
ok: true,
|
||||
available: true,
|
||||
options: Array.isArray(options) ? options : [],
|
||||
})
|
||||
} catch (error) {
|
||||
write(200, {
|
||||
ok: true,
|
||||
available: false,
|
||||
options: [],
|
||||
hint: error instanceof Error ? error.message : String(error),
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (path === `${API_PREFIX}/jobs` && method === 'GET') {
|
||||
const state = await snapshot()
|
||||
write(200, { ok: true, jobs: listJobs(state).map(jobView) })
|
||||
|
|
@ -766,6 +806,35 @@ export async function listModelChoices(ctx) {
|
|||
return { groups, current: currentDefaultModel(ctx) }
|
||||
}
|
||||
|
||||
export async function listPresetChoices(ctx) {
|
||||
const presets = tryGet(ctx, 'agentPresets')
|
||||
if (!presets || typeof presets.list !== 'function') {
|
||||
return { items: [], current: null }
|
||||
}
|
||||
let items = []
|
||||
try {
|
||||
const listed = await presets.list()
|
||||
const rows = Array.isArray(listed) ? listed : (Array.isArray(listed?.items) ? listed.items : [])
|
||||
items = rows.map((row) => ({
|
||||
id: String(row?.id || '').trim(),
|
||||
name: String(row?.name || row?.displayName || row?.id || '').trim(),
|
||||
})).filter((row) => row.id)
|
||||
} catch {
|
||||
items = []
|
||||
}
|
||||
let current = null
|
||||
if (typeof presets.resolve === 'function') {
|
||||
try {
|
||||
const resolved = await presets.resolve()
|
||||
const id = typeof resolved?.id === 'string' ? resolved.id.trim() : ''
|
||||
if (id) current = { id, name: String(resolved?.name || id) }
|
||||
} catch {
|
||||
current = null
|
||||
}
|
||||
}
|
||||
return { items, current }
|
||||
}
|
||||
|
||||
export async function resolveJobModel(ctx, job) {
|
||||
const provider = typeof job?.provider === 'string' ? job.provider.trim() : ''
|
||||
const model = typeof job?.model === 'string' ? job.model.trim() : ''
|
||||
|
|
@ -838,7 +907,7 @@ export function bindModelSelection(agentCtx, selection) {
|
|||
})
|
||||
}
|
||||
|
||||
async function composeCronAgent(ctx, selection) {
|
||||
async function composeCronAgent(ctx, selection, job) {
|
||||
const presets = tryGet(ctx, 'agentPresets')
|
||||
if (!presets || typeof presets.resolve !== 'function' || typeof presets.mount !== 'function') {
|
||||
return {
|
||||
|
|
@ -847,7 +916,10 @@ async function composeCronAgent(ctx, selection) {
|
|||
},
|
||||
}
|
||||
}
|
||||
const resolved = await presets.resolve()
|
||||
const wanted = typeof job?.agentPreset === 'string' ? job.agentPreset.trim() : ''
|
||||
const resolved = wanted
|
||||
? await presets.resolve(wanted)
|
||||
: await presets.resolve()
|
||||
const presetId = resolved?.id
|
||||
return {
|
||||
agentPreset: presetId,
|
||||
|
|
@ -871,7 +943,7 @@ export function makeLiveSessionPort(ctx) {
|
|||
const cwd = placement.cwd || defaultCwd()
|
||||
await mkdir(cwd, { recursive: true })
|
||||
const selection = await resolveJobModel(ctx, job)
|
||||
const composition = await composeCronAgent(ctx, selection)
|
||||
const composition = await composeCronAgent(ctx, selection, job)
|
||||
const handle = await agents.create({
|
||||
sessionId,
|
||||
agentOptions: {
|
||||
|
|
@ -935,6 +1007,9 @@ export function makeLiveSessionPort(ctx) {
|
|||
async listModels() {
|
||||
return listModelChoices(ctx)
|
||||
},
|
||||
async listPresets() {
|
||||
return listPresetChoices(ctx)
|
||||
},
|
||||
async waitForTurn(sessionId) {
|
||||
const entry = handles.get(sessionId)
|
||||
const agents = tryGet(ctx, 'agents')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue