Fork dsh-cron-tasks as dsh-ops-cron with DSH/IM delivery.

Agent cron_* jobs default to IM when created from a WhatsApp session with a matching delivery target; otherwise DSH sidebar sessions. Fire path soft-calls ctx.dshIm.send for summaries.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-09-05 21:48:17 +08:00
parent 4447404361
commit 2f08136adf
17 changed files with 472 additions and 285 deletions

View file

@ -8,18 +8,19 @@ const root = join(dirname(fileURLToPath(import.meta.url)), '..')
test('installable bundle declares host apply, client half, unique id, and no @deepseek-ai runtime deps', async () => {
const pkg = JSON.parse(await readFile(join(root, 'package.json'), 'utf8'))
assert.equal(pkg.name, '@dsh-external/dsh-cron-tasks')
assert.equal(pkg.name, 'dsh-ops-cron')
assert.equal(pkg.dsh.bundle.patch, './cordis.patch.yml')
assert.equal(pkg.dsh.client.platform, 'web')
assert.ok(pkg.exports['./client'])
assert.equal(pkg.main, 'lib/index.js')
assert.ok(!pkg.dependencies || !Object.keys(pkg.dependencies).some((id) => id.startsWith('@deepseek-ai/')))
const patch = await readFile(join(root, 'cordis.patch.yml'), 'utf8')
assert.match(patch, /id:\s*dsh-cron-tasks/)
assert.match(patch, /id:\s*dsh-ops-cron/)
const index = await readFile(join(root, 'lib/index.js'), 'utf8')
assert.match(index, /export function apply\(/)
assert.match(index, /registerCronTools/)
assert.match(index, /inject\(\['tools'\]/)
assert.match(index, /getDshIm/)
const tools = await readFile(join(root, 'lib/tools.js'), 'utf8')
assert.match(tools, /name: 'cron_create'/)
assert.match(tools, /name: 'cron_list'/)
@ -28,9 +29,9 @@ test('installable bundle declares host apply, client half, unique id, and no @de
assert.match(tools, /hour/)
assert.match(tools, /Current local time/)
assert.match(tools, /source: 'runtime'/)
assert.match(tools, /current session cwd/)
assert.match(tools, /resolveCreateDelivery/)
assert.match(tools, /im_bot_id/)
assert.match(tools, /resolveCreateCwd/)
assert.match(tools, /Working directory: if the user is chatting in a workspace/)
assert.match(tools, /after_minutes/)
assert.match(tools, /Extra schedule fields are ignored/)
assert.doesNotMatch(tools, /pass only one of expr, at, or hour/)
@ -40,80 +41,26 @@ test('installable bundle declares host apply, client half, unique id, and no @de
assert.doesNotMatch(tools, /from ['"]@deepseek-ai\//)
const host = await readFile(join(root, 'lib/host.js'), 'utf8')
assert.match(host, /agentDefaultModel/)
assert.match(host, /system-prompt\/assemble/)
assert.match(host, /agentOptions/)
assert.match(host, /nextRunAt === null/)
assert.match(host, /deliverRunToIm/)
assert.match(host, /PLUGIN_NAME = 'dsh-ops-cron'/)
assert.match(host, /API_PREFIX = '\/dsh-ops-cron'/)
assert.match(host, /resolveSessionPlacement/)
assert.match(host, /adoptSessionIntoWorkspace/)
assert.match(host, /attachLiveSessionToWorkspace/)
assert.match(host, /listWorkspaceChoices/)
assert.match(host, /\/workspaces/)
assert.match(host, /listModelChoices/)
assert.match(host, /resolveJobModel/)
assert.match(host, /\/models/)
assert.doesNotMatch(host, /from ['"]@deepseek-ai\//)
const client = await readFile(join(root, 'lib/client.js'), 'utf8')
assert.match(client, /定时任务/)
assert.match(client, /运维定时/)
assert.match(client, /dsh-ops-cron/)
assert.match(client, /settings\.plugin\.item/)
assert.match(client, /新建会话/)
assert.match(client, /logoRow/)
assert.match(client, /dsh-ct-entry/)
assert.match(client, /centerCol/)
assert.match(client, /data-dsh-ct-host/)
assert.match(client, /_collapsed"\]\[data-dsh-ct-mode=on\] \.dsh-ct-region/)
assert.match(client, /listRoot\.parentElement !== region\) region\.appendChild\(listRoot\)/)
assert.match(client, /jobStamp/)
assert.doesNotMatch(client, /\[data-dsh-ct-mode=on\] \.dsh-ct-region\{display:flex !important;animation:/)
assert.match(client, /visibility:hidden/)
assert.match(client, /createPortal\(editor, paneHost\)/)
assert.match(client, /sidebarCollapsed/)
assert.match(client, /_collapsed/)
assert.match(client, /width:36px/)
assert.match(client, /data-collapsed/)
assert.match(client, /translate\(-50%, -50%\)/)
assert.match(client, /返回工作区/)
assert.match(client, /runs\/\$\{run\.id\}\/open/)
assert.match(client, /regionArea/)
assert.match(client, /sessions\.open\(/)
assert.match(client, /getService\(ctx, faces, 'sessions'\)/)
assert.match(client, /workspaceSkin/)
assert.match(client, /IconFolderOpen16/)
assert.match(client, /IconProjectAddOutline16/)
assert.match(client, /IconPlayOutline16/)
assert.match(client, /IconPauseOutline16/)
assert.match(client, /IconSearchOutline16/)
assert.match(client, /searchPlaceholder/)
assert.match(client, /\/conceal/)
assert.match(client, /shouldPromoteCronFork/)
assert.match(client, /workspaceTitleFromCronFork/)
assert.match(client, /leaveCronMode/)
assert.match(client, /fork rename failed/)
assert.match(client, /sessions\/\$\{encodeURIComponent\(row\.id\)\}\/adopt/)
assert.match(client, /sessions\.length > 0 && visible\.length === 0/)
assert.match(client, /未分组|未分类/)
assert.match(client, /expanded\[job\.id\] === true/)
assert.match(client, /inject = \['slots', 'locale', 'settingsScope'\]/)
assert.doesNotMatch(client, /inject = \[[^\]]*sessions[^\]]*\]/)
assert.match(client, /工作目录/)
assert.match(client, /cwdRecent/)
assert.match(client, /cwdCustom/)
assert.match(client, /deliveryKind/)
assert.match(client, /imBotId/)
assert.match(client, /imTargetId/)
assert.match(client, /CwdField/)
assert.match(client, /ModelField/)
assert.match(client, /api\('\/models'\)/)
assert.match(tools, /resolveCreateModel/)
assert.match(tools, /snapshots the current session model/)
assert.match(client, /api\('\/workspaces'\)/)
assert.match(client, /atToLocalInput/)
assert.match(client, /localInputToAt/)
assert.match(client, /inject = \['slots', 'locale', 'settingsScope'\]/)
const delivery = await readFile(join(root, 'lib/delivery.js'), 'utf8')
assert.match(delivery, /resolveCreateDelivery/)
assert.match(delivery, /deliverRunToIm/)
const prd = await readFile(join(root, 'docs/PRD.md'), 'utf8')
assert.match(prd, /左侧侧边栏「新会话」按钮正下方的「定时任务」入口/)
assert.match(prd, /设置页「插件配置」里的定时任务设置/)
assert.match(prd, /定时任务历史/)
assert.match(prd, /chicheng-cron/)
assert.match(prd, /dsh-automation/)
assert.match(prd, /cronjob-dsh-plugin/)
assert.match(prd, /dsh-cron/)
assert.match(prd, /dsh-schedule-tasks/)
assert.match(prd, /定时任务/)
assert.match(prd, /dsh-schedule/)
assert.match(prd, /非目标/)
})