@brianli/kimaki 0.4.72-brianli.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/bin.js +2 -0
- package/dist/ai-tool-to-genai.js +233 -0
- package/dist/ai-tool-to-genai.test.js +267 -0
- package/dist/ai-tool.js +6 -0
- package/dist/bin.js +87 -0
- package/dist/bot-token.js +121 -0
- package/dist/bot-token.test.js +134 -0
- package/dist/channel-management.js +101 -0
- package/dist/cli-parsing.test.js +89 -0
- package/dist/cli.js +2529 -0
- package/dist/commands/abort.js +82 -0
- package/dist/commands/action-buttons.js +257 -0
- package/dist/commands/add-project.js +114 -0
- package/dist/commands/agent.js +291 -0
- package/dist/commands/ask-question.js +223 -0
- package/dist/commands/compact.js +120 -0
- package/dist/commands/context-usage.js +140 -0
- package/dist/commands/create-new-project.js +118 -0
- package/dist/commands/diff.js +128 -0
- package/dist/commands/file-upload.js +275 -0
- package/dist/commands/fork.js +217 -0
- package/dist/commands/gemini-apikey.js +70 -0
- package/dist/commands/login.js +490 -0
- package/dist/commands/mention-mode.js +51 -0
- package/dist/commands/merge-worktree.js +124 -0
- package/dist/commands/model.js +694 -0
- package/dist/commands/permissions.js +163 -0
- package/dist/commands/queue.js +217 -0
- package/dist/commands/remove-project.js +115 -0
- package/dist/commands/restart-opencode-server.js +116 -0
- package/dist/commands/resume.js +159 -0
- package/dist/commands/run-command.js +79 -0
- package/dist/commands/session-id.js +78 -0
- package/dist/commands/session.js +192 -0
- package/dist/commands/share.js +80 -0
- package/dist/commands/types.js +2 -0
- package/dist/commands/undo-redo.js +159 -0
- package/dist/commands/unset-model.js +152 -0
- package/dist/commands/upgrade.js +42 -0
- package/dist/commands/user-command.js +148 -0
- package/dist/commands/verbosity.js +60 -0
- package/dist/commands/worktree-settings.js +50 -0
- package/dist/commands/worktree.js +299 -0
- package/dist/condense-memory.js +33 -0
- package/dist/config.js +110 -0
- package/dist/database.js +1050 -0
- package/dist/db.js +159 -0
- package/dist/db.test.js +49 -0
- package/dist/discord-api.js +28 -0
- package/dist/discord-auth.js +231 -0
- package/dist/discord-auth.test.js +80 -0
- package/dist/discord-bot.js +997 -0
- package/dist/discord-utils.js +560 -0
- package/dist/discord-utils.test.js +115 -0
- package/dist/errors.js +167 -0
- package/dist/escape-backticks.test.js +429 -0
- package/dist/format-tables.js +122 -0
- package/dist/format-tables.test.js +199 -0
- package/dist/forum-sync/config.js +79 -0
- package/dist/forum-sync/discord-operations.js +154 -0
- package/dist/forum-sync/index.js +5 -0
- package/dist/forum-sync/markdown.js +117 -0
- package/dist/forum-sync/sync-to-discord.js +417 -0
- package/dist/forum-sync/sync-to-files.js +190 -0
- package/dist/forum-sync/types.js +53 -0
- package/dist/forum-sync/watchers.js +307 -0
- package/dist/gateway-consumer.js +232 -0
- package/dist/gateway-consumer.test.js +18 -0
- package/dist/genai-worker-wrapper.js +111 -0
- package/dist/genai-worker.js +311 -0
- package/dist/genai.js +232 -0
- package/dist/generated/browser.js +17 -0
- package/dist/generated/client.js +35 -0
- package/dist/generated/commonInputTypes.js +10 -0
- package/dist/generated/enums.js +30 -0
- package/dist/generated/internal/class.js +41 -0
- package/dist/generated/internal/prismaNamespace.js +239 -0
- package/dist/generated/internal/prismaNamespaceBrowser.js +209 -0
- package/dist/generated/models/bot_api_keys.js +1 -0
- package/dist/generated/models/bot_tokens.js +1 -0
- package/dist/generated/models/channel_agents.js +1 -0
- package/dist/generated/models/channel_directories.js +1 -0
- package/dist/generated/models/channel_mention_mode.js +1 -0
- package/dist/generated/models/channel_models.js +1 -0
- package/dist/generated/models/channel_verbosity.js +1 -0
- package/dist/generated/models/channel_worktrees.js +1 -0
- package/dist/generated/models/forum_sync_configs.js +1 -0
- package/dist/generated/models/global_models.js +1 -0
- package/dist/generated/models/ipc_requests.js +1 -0
- package/dist/generated/models/part_messages.js +1 -0
- package/dist/generated/models/scheduled_tasks.js +1 -0
- package/dist/generated/models/session_agents.js +1 -0
- package/dist/generated/models/session_models.js +1 -0
- package/dist/generated/models/session_start_sources.js +1 -0
- package/dist/generated/models/thread_sessions.js +1 -0
- package/dist/generated/models/thread_worktrees.js +1 -0
- package/dist/generated/models.js +1 -0
- package/dist/heap-monitor.js +95 -0
- package/dist/hrana-server.js +416 -0
- package/dist/hrana-server.test.js +368 -0
- package/dist/image-utils.js +112 -0
- package/dist/interaction-handler.js +327 -0
- package/dist/ipc-polling.js +251 -0
- package/dist/kimaki-digital-twin.e2e.test.js +165 -0
- package/dist/limit-heading-depth.js +25 -0
- package/dist/limit-heading-depth.test.js +105 -0
- package/dist/logger.js +160 -0
- package/dist/markdown.js +342 -0
- package/dist/markdown.test.js +253 -0
- package/dist/message-formatting.js +433 -0
- package/dist/message-formatting.test.js +73 -0
- package/dist/openai-realtime.js +228 -0
- package/dist/opencode-plugin-loading.e2e.test.js +91 -0
- package/dist/opencode-plugin.js +536 -0
- package/dist/opencode-plugin.test.js +98 -0
- package/dist/opencode.js +409 -0
- package/dist/privacy-sanitizer.js +105 -0
- package/dist/runtime-mode.js +51 -0
- package/dist/runtime-mode.test.js +115 -0
- package/dist/sentry.js +127 -0
- package/dist/session-handler/state.js +151 -0
- package/dist/session-handler.js +1874 -0
- package/dist/session-search.js +100 -0
- package/dist/session-search.test.js +40 -0
- package/dist/startup-service.js +153 -0
- package/dist/system-message.js +499 -0
- package/dist/task-runner.js +282 -0
- package/dist/task-schedule.js +191 -0
- package/dist/task-schedule.test.js +71 -0
- package/dist/thinking-utils.js +35 -0
- package/dist/thread-message-queue.e2e.test.js +781 -0
- package/dist/tools.js +359 -0
- package/dist/unnest-code-blocks.js +136 -0
- package/dist/unnest-code-blocks.test.js +641 -0
- package/dist/upgrade.js +114 -0
- package/dist/utils.js +109 -0
- package/dist/voice-handler.js +606 -0
- package/dist/voice.js +304 -0
- package/dist/voice.test.js +187 -0
- package/dist/wait-session.js +94 -0
- package/dist/worker-types.js +4 -0
- package/dist/worktree-utils.js +727 -0
- package/dist/xml.js +92 -0
- package/dist/xml.test.js +32 -0
- package/package.json +82 -0
- package/schema.prisma +246 -0
- package/skills/batch/SKILL.md +87 -0
- package/skills/critique/SKILL.md +129 -0
- package/skills/errore/SKILL.md +589 -0
- package/skills/goke/.prettierrc +5 -0
- package/skills/goke/CHANGELOG.md +40 -0
- package/skills/goke/LICENSE +21 -0
- package/skills/goke/README.md +666 -0
- package/skills/goke/SKILL.md +458 -0
- package/skills/goke/package.json +43 -0
- package/skills/goke/src/__test__/coerce.test.ts +411 -0
- package/skills/goke/src/__test__/index.test.ts +1798 -0
- package/skills/goke/src/__test__/types.test-d.ts +111 -0
- package/skills/goke/src/coerce.ts +547 -0
- package/skills/goke/src/goke.ts +1362 -0
- package/skills/goke/src/index.ts +16 -0
- package/skills/goke/src/mri.ts +164 -0
- package/skills/goke/tsconfig.json +15 -0
- package/skills/jitter/EDITOR.md +219 -0
- package/skills/jitter/EXPORT-INTERNALS.md +309 -0
- package/skills/jitter/SKILL.md +158 -0
- package/skills/jitter/jitter-clipboard.json +1042 -0
- package/skills/jitter/package.json +14 -0
- package/skills/jitter/tsconfig.json +15 -0
- package/skills/jitter/utils/actions.ts +212 -0
- package/skills/jitter/utils/export.ts +114 -0
- package/skills/jitter/utils/index.ts +141 -0
- package/skills/jitter/utils/snapshot.ts +154 -0
- package/skills/jitter/utils/traverse.ts +246 -0
- package/skills/jitter/utils/types.ts +279 -0
- package/skills/jitter/utils/wait.ts +133 -0
- package/skills/playwriter/SKILL.md +31 -0
- package/skills/security-review/SKILL.md +208 -0
- package/skills/simplify/SKILL.md +58 -0
- package/skills/termcast/SKILL.md +945 -0
- package/skills/tuistory/SKILL.md +250 -0
- package/skills/zustand-centralized-state/SKILL.md +582 -0
- package/src/__snapshots__/compact-session-context-no-system.md +35 -0
- package/src/__snapshots__/compact-session-context.md +41 -0
- package/src/__snapshots__/first-session-no-info.md +17 -0
- package/src/__snapshots__/first-session-with-info.md +23 -0
- package/src/__snapshots__/session-1.md +17 -0
- package/src/__snapshots__/session-2.md +5871 -0
- package/src/__snapshots__/session-3.md +17 -0
- package/src/__snapshots__/session-with-tools.md +5871 -0
- package/src/ai-tool-to-genai.test.ts +296 -0
- package/src/ai-tool-to-genai.ts +282 -0
- package/src/ai-tool.ts +39 -0
- package/src/bin.ts +108 -0
- package/src/bot-token.test.ts +171 -0
- package/src/bot-token.ts +159 -0
- package/src/channel-management.ts +172 -0
- package/src/cli-parsing.test.ts +132 -0
- package/src/cli.ts +3605 -0
- package/src/commands/abort.ts +112 -0
- package/src/commands/action-buttons.ts +376 -0
- package/src/commands/add-project.ts +152 -0
- package/src/commands/agent.ts +404 -0
- package/src/commands/ask-question.ts +330 -0
- package/src/commands/compact.ts +157 -0
- package/src/commands/context-usage.ts +199 -0
- package/src/commands/create-new-project.ts +179 -0
- package/src/commands/diff.ts +165 -0
- package/src/commands/file-upload.ts +389 -0
- package/src/commands/fork.ts +320 -0
- package/src/commands/gemini-apikey.ts +104 -0
- package/src/commands/login.ts +634 -0
- package/src/commands/mention-mode.ts +77 -0
- package/src/commands/merge-worktree.ts +177 -0
- package/src/commands/model.ts +961 -0
- package/src/commands/permissions.ts +261 -0
- package/src/commands/queue.ts +296 -0
- package/src/commands/remove-project.ts +155 -0
- package/src/commands/restart-opencode-server.ts +162 -0
- package/src/commands/resume.ts +242 -0
- package/src/commands/run-command.ts +123 -0
- package/src/commands/session-id.ts +109 -0
- package/src/commands/session.ts +250 -0
- package/src/commands/share.ts +106 -0
- package/src/commands/types.ts +25 -0
- package/src/commands/undo-redo.ts +221 -0
- package/src/commands/unset-model.ts +189 -0
- package/src/commands/upgrade.ts +52 -0
- package/src/commands/user-command.ts +193 -0
- package/src/commands/verbosity.ts +88 -0
- package/src/commands/worktree-settings.ts +79 -0
- package/src/commands/worktree.ts +431 -0
- package/src/condense-memory.ts +36 -0
- package/src/config.ts +148 -0
- package/src/database.ts +1530 -0
- package/src/db.test.ts +60 -0
- package/src/db.ts +190 -0
- package/src/discord-api.ts +35 -0
- package/src/discord-bot.ts +1316 -0
- package/src/discord-utils.test.ts +132 -0
- package/src/discord-utils.ts +767 -0
- package/src/errors.ts +213 -0
- package/src/escape-backticks.test.ts +469 -0
- package/src/format-tables.test.ts +223 -0
- package/src/format-tables.ts +145 -0
- package/src/forum-sync/config.ts +92 -0
- package/src/forum-sync/discord-operations.ts +241 -0
- package/src/forum-sync/index.ts +9 -0
- package/src/forum-sync/markdown.ts +176 -0
- package/src/forum-sync/sync-to-discord.ts +595 -0
- package/src/forum-sync/sync-to-files.ts +294 -0
- package/src/forum-sync/types.ts +175 -0
- package/src/forum-sync/watchers.ts +454 -0
- package/src/genai-worker-wrapper.ts +164 -0
- package/src/genai-worker.ts +386 -0
- package/src/genai.ts +321 -0
- package/src/generated/browser.ts +109 -0
- package/src/generated/client.ts +131 -0
- package/src/generated/commonInputTypes.ts +512 -0
- package/src/generated/enums.ts +46 -0
- package/src/generated/internal/class.ts +362 -0
- package/src/generated/internal/prismaNamespace.ts +2251 -0
- package/src/generated/internal/prismaNamespaceBrowser.ts +308 -0
- package/src/generated/models/bot_api_keys.ts +1288 -0
- package/src/generated/models/bot_tokens.ts +1577 -0
- package/src/generated/models/channel_agents.ts +1256 -0
- package/src/generated/models/channel_directories.ts +2104 -0
- package/src/generated/models/channel_mention_mode.ts +1300 -0
- package/src/generated/models/channel_models.ts +1288 -0
- package/src/generated/models/channel_verbosity.ts +1224 -0
- package/src/generated/models/channel_worktrees.ts +1308 -0
- package/src/generated/models/forum_sync_configs.ts +1452 -0
- package/src/generated/models/global_models.ts +1288 -0
- package/src/generated/models/ipc_requests.ts +1485 -0
- package/src/generated/models/part_messages.ts +1302 -0
- package/src/generated/models/scheduled_tasks.ts +2320 -0
- package/src/generated/models/session_agents.ts +1086 -0
- package/src/generated/models/session_models.ts +1114 -0
- package/src/generated/models/session_start_sources.ts +1408 -0
- package/src/generated/models/thread_sessions.ts +1599 -0
- package/src/generated/models/thread_worktrees.ts +1352 -0
- package/src/generated/models.ts +29 -0
- package/src/heap-monitor.ts +121 -0
- package/src/hrana-server.test.ts +428 -0
- package/src/hrana-server.ts +547 -0
- package/src/image-utils.ts +149 -0
- package/src/interaction-handler.ts +461 -0
- package/src/ipc-polling.ts +325 -0
- package/src/kimaki-digital-twin.e2e.test.ts +201 -0
- package/src/limit-heading-depth.test.ts +116 -0
- package/src/limit-heading-depth.ts +26 -0
- package/src/logger.ts +203 -0
- package/src/markdown.test.ts +360 -0
- package/src/markdown.ts +410 -0
- package/src/message-formatting.test.ts +81 -0
- package/src/message-formatting.ts +549 -0
- package/src/openai-realtime.ts +362 -0
- package/src/opencode-plugin-loading.e2e.test.ts +112 -0
- package/src/opencode-plugin.test.ts +108 -0
- package/src/opencode-plugin.ts +652 -0
- package/src/opencode.ts +554 -0
- package/src/privacy-sanitizer.ts +142 -0
- package/src/schema.sql +158 -0
- package/src/sentry.ts +137 -0
- package/src/session-handler/state.ts +232 -0
- package/src/session-handler.ts +2668 -0
- package/src/session-search.test.ts +50 -0
- package/src/session-search.ts +148 -0
- package/src/startup-service.ts +200 -0
- package/src/system-message.ts +568 -0
- package/src/task-runner.ts +425 -0
- package/src/task-schedule.test.ts +84 -0
- package/src/task-schedule.ts +287 -0
- package/src/thinking-utils.ts +61 -0
- package/src/thread-message-queue.e2e.test.ts +997 -0
- package/src/tools.ts +432 -0
- package/src/unnest-code-blocks.test.ts +679 -0
- package/src/unnest-code-blocks.ts +168 -0
- package/src/upgrade.ts +127 -0
- package/src/utils.ts +145 -0
- package/src/voice-handler.ts +852 -0
- package/src/voice.test.ts +219 -0
- package/src/voice.ts +444 -0
- package/src/wait-session.ts +147 -0
- package/src/worker-types.ts +64 -0
- package/src/worktree-utils.ts +988 -0
- package/src/xml.test.ts +38 -0
- package/src/xml.ts +121 -0
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
// Scheduled task parsing utilities for `send --send-at` and task runner execution.
|
|
2
|
+
|
|
3
|
+
import { CronExpressionParser } from 'cron-parser'
|
|
4
|
+
import * as errore from 'errore'
|
|
5
|
+
|
|
6
|
+
export type ScheduledTaskPayload =
|
|
7
|
+
| {
|
|
8
|
+
kind: 'thread'
|
|
9
|
+
threadId: string
|
|
10
|
+
prompt: string
|
|
11
|
+
agent: string | null
|
|
12
|
+
model: string | null
|
|
13
|
+
username: string | null
|
|
14
|
+
userId: string | null
|
|
15
|
+
}
|
|
16
|
+
| {
|
|
17
|
+
kind: 'channel'
|
|
18
|
+
channelId: string
|
|
19
|
+
prompt: string
|
|
20
|
+
name: string | null
|
|
21
|
+
notifyOnly: boolean
|
|
22
|
+
worktreeName: string | null
|
|
23
|
+
agent: string | null
|
|
24
|
+
model: string | null
|
|
25
|
+
username: string | null
|
|
26
|
+
userId: string | null
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type ParsedSendAt =
|
|
30
|
+
| {
|
|
31
|
+
scheduleKind: 'at'
|
|
32
|
+
runAt: Date
|
|
33
|
+
cronExpr: null
|
|
34
|
+
timezone: null
|
|
35
|
+
nextRunAt: Date
|
|
36
|
+
}
|
|
37
|
+
| {
|
|
38
|
+
scheduleKind: 'cron'
|
|
39
|
+
runAt: null
|
|
40
|
+
cronExpr: string
|
|
41
|
+
timezone: string
|
|
42
|
+
nextRunAt: Date
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const UTC_SEND_AT_DATE_REGEX =
|
|
46
|
+
/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d{1,3})?)?Z$/
|
|
47
|
+
|
|
48
|
+
export function getLocalTimeZone(): string {
|
|
49
|
+
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
50
|
+
if (!tz) {
|
|
51
|
+
return 'UTC'
|
|
52
|
+
}
|
|
53
|
+
return tz
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function getPromptPreview(prompt: string): string {
|
|
57
|
+
const normalized = prompt.replace(/\s+/g, ' ').trim()
|
|
58
|
+
if (normalized.length <= 120) {
|
|
59
|
+
return normalized
|
|
60
|
+
}
|
|
61
|
+
return `${normalized.slice(0, 117)}...`
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function parseUtcSendAtDate({
|
|
65
|
+
value,
|
|
66
|
+
now,
|
|
67
|
+
}: {
|
|
68
|
+
value: string
|
|
69
|
+
now: Date
|
|
70
|
+
}): Date | Error | null {
|
|
71
|
+
const looksLikeDate = value.includes('T') || /^\d{4}-\d{2}-\d{2}/.test(value)
|
|
72
|
+
if (!looksLikeDate) {
|
|
73
|
+
return null
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (!UTC_SEND_AT_DATE_REGEX.test(value)) {
|
|
77
|
+
return new Error(
|
|
78
|
+
`--send-at date must be UTC ISO format ending with Z (example: 2026-03-01T09:00:00Z). Received: ${value}`,
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const runAt = new Date(value)
|
|
83
|
+
if (Number.isNaN(runAt.getTime())) {
|
|
84
|
+
return new Error(`Invalid UTC date for --send-at: ${value}`)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (runAt.getTime() <= now.getTime()) {
|
|
88
|
+
return new Error(`--send-at date must be in the future (UTC): ${value}`)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return runAt
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function parseSendAtValue({
|
|
95
|
+
value,
|
|
96
|
+
now,
|
|
97
|
+
timezone,
|
|
98
|
+
}: {
|
|
99
|
+
value: string
|
|
100
|
+
now: Date
|
|
101
|
+
timezone: string
|
|
102
|
+
}): ParsedSendAt | Error {
|
|
103
|
+
const trimmed = value.trim()
|
|
104
|
+
if (!trimmed) {
|
|
105
|
+
return new Error('--send-at cannot be empty')
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const utcDateResult = parseUtcSendAtDate({ value: trimmed, now })
|
|
109
|
+
if (utcDateResult instanceof Error) {
|
|
110
|
+
return utcDateResult
|
|
111
|
+
}
|
|
112
|
+
if (utcDateResult) {
|
|
113
|
+
return {
|
|
114
|
+
scheduleKind: 'at',
|
|
115
|
+
runAt: utcDateResult,
|
|
116
|
+
cronExpr: null,
|
|
117
|
+
timezone: null,
|
|
118
|
+
nextRunAt: utcDateResult,
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const looksLikeCron =
|
|
123
|
+
trimmed.startsWith('@') || trimmed.split(/\s+/).length >= 5
|
|
124
|
+
if (looksLikeCron) {
|
|
125
|
+
const nextRunAtResult = getNextCronRun({
|
|
126
|
+
cronExpr: trimmed,
|
|
127
|
+
timezone,
|
|
128
|
+
from: now,
|
|
129
|
+
})
|
|
130
|
+
if (!(nextRunAtResult instanceof Error)) {
|
|
131
|
+
return {
|
|
132
|
+
scheduleKind: 'cron',
|
|
133
|
+
runAt: null,
|
|
134
|
+
cronExpr: trimmed,
|
|
135
|
+
timezone,
|
|
136
|
+
nextRunAt: nextRunAtResult,
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const cronResult = getNextCronRun({ cronExpr: trimmed, timezone, from: now })
|
|
142
|
+
if (cronResult instanceof Error) {
|
|
143
|
+
return new Error(
|
|
144
|
+
`Invalid --send-at value: "${trimmed}". Use UTC ISO date/time ending in Z or a cron expression.`,
|
|
145
|
+
{
|
|
146
|
+
cause: cronResult,
|
|
147
|
+
},
|
|
148
|
+
)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return {
|
|
152
|
+
scheduleKind: 'cron',
|
|
153
|
+
runAt: null,
|
|
154
|
+
cronExpr: trimmed,
|
|
155
|
+
timezone,
|
|
156
|
+
nextRunAt: cronResult,
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export function getNextCronRun({
|
|
161
|
+
cronExpr,
|
|
162
|
+
timezone,
|
|
163
|
+
from,
|
|
164
|
+
}: {
|
|
165
|
+
cronExpr: string
|
|
166
|
+
timezone: string
|
|
167
|
+
from: Date
|
|
168
|
+
}): Date | Error {
|
|
169
|
+
const parsed = errore.try({
|
|
170
|
+
try: () => {
|
|
171
|
+
return CronExpressionParser.parse(cronExpr, {
|
|
172
|
+
currentDate: from,
|
|
173
|
+
tz: timezone,
|
|
174
|
+
})
|
|
175
|
+
},
|
|
176
|
+
catch: (error) => {
|
|
177
|
+
return new Error(`Invalid cron expression: ${cronExpr}`, { cause: error })
|
|
178
|
+
},
|
|
179
|
+
})
|
|
180
|
+
if (parsed instanceof Error) {
|
|
181
|
+
return parsed
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const next = errore.try({
|
|
185
|
+
try: () => {
|
|
186
|
+
return parsed.next().toDate()
|
|
187
|
+
},
|
|
188
|
+
catch: (error) => {
|
|
189
|
+
return new Error(`Could not compute next run for cron: ${cronExpr}`, {
|
|
190
|
+
cause: error,
|
|
191
|
+
})
|
|
192
|
+
},
|
|
193
|
+
})
|
|
194
|
+
if (next instanceof Error) {
|
|
195
|
+
return next
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return next
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export function serializeScheduledTaskPayload(
|
|
202
|
+
payload: ScheduledTaskPayload,
|
|
203
|
+
): string {
|
|
204
|
+
return JSON.stringify(payload)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
208
|
+
return typeof value === 'object' && value !== null
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function asString(value: unknown): string | null {
|
|
212
|
+
if (typeof value !== 'string') {
|
|
213
|
+
return null
|
|
214
|
+
}
|
|
215
|
+
return value
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export function parseScheduledTaskPayload(
|
|
219
|
+
payloadJson: string,
|
|
220
|
+
): ScheduledTaskPayload | Error {
|
|
221
|
+
const parsed = errore.try({
|
|
222
|
+
try: () => {
|
|
223
|
+
return JSON.parse(payloadJson) as unknown
|
|
224
|
+
},
|
|
225
|
+
catch: (error) => {
|
|
226
|
+
return new Error('Task payload is not valid JSON', { cause: error })
|
|
227
|
+
},
|
|
228
|
+
})
|
|
229
|
+
if (parsed instanceof Error) {
|
|
230
|
+
return parsed
|
|
231
|
+
}
|
|
232
|
+
if (!isRecord(parsed)) {
|
|
233
|
+
return new Error('Task payload must be an object')
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const kind = asString(parsed.kind)
|
|
237
|
+
if (kind === 'thread') {
|
|
238
|
+
const threadId = asString(parsed.threadId)
|
|
239
|
+
const prompt = asString(parsed.prompt)
|
|
240
|
+
const agent = asString(parsed.agent)
|
|
241
|
+
const model = asString(parsed.model)
|
|
242
|
+
const username = asString(parsed.username)
|
|
243
|
+
const userId = asString(parsed.userId)
|
|
244
|
+
if (!threadId || !prompt) {
|
|
245
|
+
return new Error('Thread task payload requires threadId and prompt')
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
kind: 'thread',
|
|
249
|
+
threadId,
|
|
250
|
+
prompt,
|
|
251
|
+
agent,
|
|
252
|
+
model,
|
|
253
|
+
username,
|
|
254
|
+
userId,
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (kind === 'channel') {
|
|
259
|
+
const channelId = asString(parsed.channelId)
|
|
260
|
+
const prompt = asString(parsed.prompt)
|
|
261
|
+
const nameValue = parsed.name
|
|
262
|
+
const name = typeof nameValue === 'string' ? nameValue : null
|
|
263
|
+
const notifyOnly = parsed.notifyOnly === true
|
|
264
|
+
const worktreeName = asString(parsed.worktreeName)
|
|
265
|
+
const agent = asString(parsed.agent)
|
|
266
|
+
const model = asString(parsed.model)
|
|
267
|
+
const username = asString(parsed.username)
|
|
268
|
+
const userId = asString(parsed.userId)
|
|
269
|
+
if (!channelId || !prompt) {
|
|
270
|
+
return new Error('Channel task payload requires channelId and prompt')
|
|
271
|
+
}
|
|
272
|
+
return {
|
|
273
|
+
kind: 'channel',
|
|
274
|
+
channelId,
|
|
275
|
+
prompt,
|
|
276
|
+
name,
|
|
277
|
+
notifyOnly,
|
|
278
|
+
worktreeName,
|
|
279
|
+
agent,
|
|
280
|
+
model,
|
|
281
|
+
username,
|
|
282
|
+
userId,
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return new Error('Task payload has unknown kind')
|
|
287
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Utilities for extracting and matching model variant (thinking level) values
|
|
2
|
+
// from the provider.list() API response. Used by model selector and session handler
|
|
3
|
+
// to validate variant preferences against what the current model actually supports.
|
|
4
|
+
|
|
5
|
+
export type ThinkingProvider = {
|
|
6
|
+
id: string
|
|
7
|
+
models?: Record<string, unknown>
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function getModelVariants(model: unknown): Record<string, unknown> | undefined {
|
|
11
|
+
if (!model || typeof model !== 'object') {
|
|
12
|
+
return undefined
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const variants = (model as { variants?: unknown }).variants
|
|
16
|
+
if (!variants || typeof variants !== 'object') {
|
|
17
|
+
return undefined
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return variants as Record<string, unknown>
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function getThinkingValuesForModel({
|
|
24
|
+
providers,
|
|
25
|
+
providerId,
|
|
26
|
+
modelId,
|
|
27
|
+
}: {
|
|
28
|
+
providers: ThinkingProvider[]
|
|
29
|
+
providerId: string
|
|
30
|
+
modelId: string
|
|
31
|
+
}): string[] {
|
|
32
|
+
const provider = providers.find((candidateProvider) => {
|
|
33
|
+
return candidateProvider.id === providerId
|
|
34
|
+
})
|
|
35
|
+
const model = provider?.models?.[modelId]
|
|
36
|
+
const variants = getModelVariants(model)
|
|
37
|
+
if (!variants) {
|
|
38
|
+
return []
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return Object.keys(variants).filter((variant) => {
|
|
42
|
+
return variant.trim().length > 0
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function matchThinkingValue({
|
|
47
|
+
requestedValue,
|
|
48
|
+
availableValues,
|
|
49
|
+
}: {
|
|
50
|
+
requestedValue: string
|
|
51
|
+
availableValues: string[]
|
|
52
|
+
}): string | undefined {
|
|
53
|
+
const normalizedRequestedValue = requestedValue.trim().toLowerCase()
|
|
54
|
+
if (!normalizedRequestedValue) {
|
|
55
|
+
return undefined
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return availableValues.find((availableValue) => {
|
|
59
|
+
return availableValue.toLowerCase() === normalizedRequestedValue
|
|
60
|
+
})
|
|
61
|
+
}
|