agent-mockingbird 0.0.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/.agents/skills/btca-cli/SKILL.md +64 -0
- package/.agents/skills/btca-cli/agents/openai.yaml +3 -0
- package/.agents/skills/frontend-design/SKILL.md +42 -0
- package/.agents/skills/frontend-design/agents/openai.yaml +3 -0
- package/.env.example +36 -0
- package/.githooks/pre-commit +33 -0
- package/.github/workflows/ci.yml +309 -0
- package/.opencode/bun.lock +18 -0
- package/.opencode/package.json +5 -0
- package/.opencode/tools/agent_type_manager.ts +100 -0
- package/.opencode/tools/config_manager.ts +87 -0
- package/.opencode/tools/cron_manager.ts +145 -0
- package/.opencode/tools/memory_get.ts +43 -0
- package/.opencode/tools/memory_remember.ts +53 -0
- package/.opencode/tools/memory_search.ts +48 -0
- package/AGENTS.md +126 -0
- package/MEMORY.md +2 -0
- package/README.md +451 -0
- package/THIRD_PARTY_NOTICES.md +11 -0
- package/agent-mockingbird.config.example.json +135 -0
- package/apps/server/package.json +32 -0
- package/apps/server/src/backend/agents/bootstrapContext.ts +362 -0
- package/apps/server/src/backend/agents/openclawImport.test.ts +133 -0
- package/apps/server/src/backend/agents/openclawImport.ts +797 -0
- package/apps/server/src/backend/agents/opencodeConfig.ts +428 -0
- package/apps/server/src/backend/agents/service.ts +10 -0
- package/apps/server/src/backend/config/example-config.test.ts +20 -0
- package/apps/server/src/backend/config/orchestration.ts +243 -0
- package/apps/server/src/backend/config/policy.ts +158 -0
- package/apps/server/src/backend/config/schema.test.ts +15 -0
- package/apps/server/src/backend/config/schema.ts +391 -0
- package/apps/server/src/backend/config/semantic.test.ts +34 -0
- package/apps/server/src/backend/config/semantic.ts +149 -0
- package/apps/server/src/backend/config/service.test.ts +75 -0
- package/apps/server/src/backend/config/service.ts +207 -0
- package/apps/server/src/backend/config/smoke.ts +77 -0
- package/apps/server/src/backend/config/store.test.ts +123 -0
- package/apps/server/src/backend/config/store.ts +581 -0
- package/apps/server/src/backend/config/testFixtures.ts +5 -0
- package/apps/server/src/backend/config/types.ts +56 -0
- package/apps/server/src/backend/contracts/events.ts +320 -0
- package/apps/server/src/backend/contracts/runtime.ts +111 -0
- package/apps/server/src/backend/cron/executor.ts +435 -0
- package/apps/server/src/backend/cron/repository.ts +170 -0
- package/apps/server/src/backend/cron/service.ts +660 -0
- package/apps/server/src/backend/cron/storage.ts +92 -0
- package/apps/server/src/backend/cron/types.ts +138 -0
- package/apps/server/src/backend/cron/utils.ts +351 -0
- package/apps/server/src/backend/db/client.ts +20 -0
- package/apps/server/src/backend/db/migrate.ts +40 -0
- package/apps/server/src/backend/db/repository.ts +1762 -0
- package/apps/server/src/backend/db/schema.ts +113 -0
- package/apps/server/src/backend/db/usageDashboard.test.ts +102 -0
- package/apps/server/src/backend/db/wipe.ts +13 -0
- package/apps/server/src/backend/defaults.ts +32 -0
- package/apps/server/src/backend/env.ts +48 -0
- package/apps/server/src/backend/heartbeat/activeHours.ts +45 -0
- package/apps/server/src/backend/heartbeat/defaultJob.ts +88 -0
- package/apps/server/src/backend/heartbeat/heartbeat.test.ts +110 -0
- package/apps/server/src/backend/heartbeat/runtimeService.ts +190 -0
- package/apps/server/src/backend/heartbeat/service.ts +176 -0
- package/apps/server/src/backend/heartbeat/state.test.ts +63 -0
- package/apps/server/src/backend/heartbeat/state.ts +167 -0
- package/apps/server/src/backend/heartbeat/types.ts +54 -0
- package/apps/server/src/backend/http/boundedQueue.test.ts +49 -0
- package/apps/server/src/backend/http/boundedQueue.ts +92 -0
- package/apps/server/src/backend/http/parsers.ts +40 -0
- package/apps/server/src/backend/http/router.ts +61 -0
- package/apps/server/src/backend/http/routes/agentRoutes.ts +67 -0
- package/apps/server/src/backend/http/routes/backgroundRoutes.ts +203 -0
- package/apps/server/src/backend/http/routes/chatRoutes.ts +107 -0
- package/apps/server/src/backend/http/routes/configRoutes.ts +602 -0
- package/apps/server/src/backend/http/routes/cronRoutes.ts +221 -0
- package/apps/server/src/backend/http/routes/dashboardRoutes.ts +308 -0
- package/apps/server/src/backend/http/routes/eventRoutes.ts +7 -0
- package/apps/server/src/backend/http/routes/heartbeatRoutes.test.ts +41 -0
- package/apps/server/src/backend/http/routes/heartbeatRoutes.ts +28 -0
- package/apps/server/src/backend/http/routes/index.ts +101 -0
- package/apps/server/src/backend/http/routes/mcpRoutes.ts +213 -0
- package/apps/server/src/backend/http/routes/memoryRoutes.ts +154 -0
- package/apps/server/src/backend/http/routes/runRoutes.ts +310 -0
- package/apps/server/src/backend/http/routes/runtimeRoutes.ts +197 -0
- package/apps/server/src/backend/http/routes/skillRoutes.ts +112 -0
- package/apps/server/src/backend/http/routes/uiRoutes.test.ts +161 -0
- package/apps/server/src/backend/http/routes/uiRoutes.ts +177 -0
- package/apps/server/src/backend/http/routes/usageRoutes.test.ts +104 -0
- package/apps/server/src/backend/http/routes/usageRoutes.ts +767 -0
- package/apps/server/src/backend/http/schemas.ts +64 -0
- package/apps/server/src/backend/http/sse.ts +144 -0
- package/apps/server/src/backend/integration/backend-core.test.ts +2316 -0
- package/apps/server/src/backend/logging/logger.ts +64 -0
- package/apps/server/src/backend/mcp/service.ts +326 -0
- package/apps/server/src/backend/memory/cli.ts +170 -0
- package/apps/server/src/backend/memory/conceptExpansion.test.ts +28 -0
- package/apps/server/src/backend/memory/conceptExpansion.ts +80 -0
- package/apps/server/src/backend/memory/qmdPort.test.ts +54 -0
- package/apps/server/src/backend/memory/qmdPort.ts +61 -0
- package/apps/server/src/backend/memory/records.test.ts +66 -0
- package/apps/server/src/backend/memory/records.ts +229 -0
- package/apps/server/src/backend/memory/service.ts +2012 -0
- package/apps/server/src/backend/memory/sqliteVec.ts +58 -0
- package/apps/server/src/backend/memory/types.ts +104 -0
- package/apps/server/src/backend/opencode/agentMockingbirdPlugin.test.ts +396 -0
- package/apps/server/src/backend/opencode/client.ts +98 -0
- package/apps/server/src/backend/opencode/models.ts +41 -0
- package/apps/server/src/backend/opencode/systemPrompt.test.ts +146 -0
- package/apps/server/src/backend/opencode/systemPrompt.ts +284 -0
- package/apps/server/src/backend/paths.ts +57 -0
- package/apps/server/src/backend/prompts/service.ts +100 -0
- package/apps/server/src/backend/queue/queue.test.ts +189 -0
- package/apps/server/src/backend/queue/service.ts +177 -0
- package/apps/server/src/backend/queue/types.ts +39 -0
- package/apps/server/src/backend/run/service.ts +576 -0
- package/apps/server/src/backend/run/storage.ts +47 -0
- package/apps/server/src/backend/run/types.ts +44 -0
- package/apps/server/src/backend/runtime/errors.ts +61 -0
- package/apps/server/src/backend/runtime/index.ts +72 -0
- package/apps/server/src/backend/runtime/memoryPromptDedup.test.ts +153 -0
- package/apps/server/src/backend/runtime/memoryPromptDedup.ts +76 -0
- package/apps/server/src/backend/runtime/opencodeRuntime/backgroundMethods.ts +765 -0
- package/apps/server/src/backend/runtime/opencodeRuntime/coreMethods.ts +705 -0
- package/apps/server/src/backend/runtime/opencodeRuntime/eventMethods.ts +503 -0
- package/apps/server/src/backend/runtime/opencodeRuntime/memoryMethods.ts +462 -0
- package/apps/server/src/backend/runtime/opencodeRuntime/promptMethods.ts +1167 -0
- package/apps/server/src/backend/runtime/opencodeRuntime/shared.ts +254 -0
- package/apps/server/src/backend/runtime/opencodeRuntime.test.ts +2899 -0
- package/apps/server/src/backend/runtime/opencodeRuntime.ts +135 -0
- package/apps/server/src/backend/runtime/sessionScope.ts +45 -0
- package/apps/server/src/backend/skills/service.ts +442 -0
- package/apps/server/src/backend/workspace/resolve.ts +27 -0
- package/apps/server/src/cli/agent-mockingbird.mjs +2522 -0
- package/apps/server/src/cli/agent-mockingbird.test.ts +68 -0
- package/apps/server/src/cli/runtime-assets.mjs +269 -0
- package/apps/server/src/cli/runtime-assets.test.ts +52 -0
- package/apps/server/src/cli/runtime-layout.mjs +75 -0
- package/apps/server/src/cli/standaloneBuild.test.ts +19 -0
- package/apps/server/src/cli/standaloneBuild.ts +19 -0
- package/apps/server/src/cli/standaloneCronBinary.test.ts +187 -0
- package/apps/server/src/index.ts +178 -0
- package/apps/server/tsconfig.json +12 -0
- package/backlog.md +5 -0
- package/bin/agent-mockingbird +2522 -0
- package/bin/runtime-layout.mjs +75 -0
- package/build-bin.ts +34 -0
- package/build-cli.mjs +37 -0
- package/build.ts +40 -0
- package/bun-env.d.ts +11 -0
- package/bun.lock +888 -0
- package/bunfig.toml +2 -0
- package/components.json +21 -0
- package/config.json +130 -0
- package/deploy/RELEASE_INSTALL.md +112 -0
- package/deploy/docker-compose.yml +42 -0
- package/deploy/systemd/README.md +46 -0
- package/deploy/systemd/agent-mockingbird.service +28 -0
- package/deploy/systemd/opencode.service +25 -0
- package/docs/legacy-config-ui-reference.md +51 -0
- package/docs/memory-e2e-trace-2026-03-04.md +63 -0
- package/docs/memory-ops.md +96 -0
- package/docs/memory-runtime-contract.md +42 -0
- package/docs/memory-tuning-remote-2026-03-04.md +59 -0
- package/docs/opencode-rebase-workflow-plan.md +614 -0
- package/docs/opencode-startup-sync-plan.md +94 -0
- package/docs/vendor-opencode.md +41 -0
- package/drizzle/0000_famous_turbo.sql +49 -0
- package/drizzle/0001_cron_memory_aux.sql +160 -0
- package/drizzle/0002_runtime_session_bindings.sql +28 -0
- package/drizzle/0003_background_runs.sql +27 -0
- package/drizzle/0004_memory_open_write.sql +63 -0
- package/drizzle/0005_signal_channel.sql +47 -0
- package/drizzle/0006_usage_event_dimensions.sql +7 -0
- package/drizzle/meta/0000_snapshot.json +341 -0
- package/drizzle/meta/_journal.json +55 -0
- package/drizzle.config.ts +14 -0
- package/eslint.config.mjs +77 -0
- package/knip.json +18 -0
- package/memory/2026-03-04.md +4 -0
- package/opencode.lock.json +16 -0
- package/package.json +67 -0
- package/packages/agent-mockingbird-installer/README.md +31 -0
- package/packages/agent-mockingbird-installer/bin/agent-mockingbird-installer.mjs +44 -0
- package/packages/agent-mockingbird-installer/opencode.lock.json +16 -0
- package/packages/agent-mockingbird-installer/package.json +23 -0
- package/packages/contracts/package.json +19 -0
- package/packages/contracts/src/agentTypes.ts +122 -0
- package/packages/contracts/src/cron.ts +146 -0
- package/packages/contracts/src/dashboard.ts +378 -0
- package/packages/contracts/src/index.ts +3 -0
- package/packages/contracts/tsconfig.json +4 -0
- package/patches/opencode/0001-Wafflebot-OpenCode-baseline.patch +2341 -0
- package/patches/opencode/0002-Fix-OpenCode-web-entry-and-settings-icons.patch +104 -0
- package/patches/opencode/0003-fix-app-remove-duplicate-sidebar-mount.patch +32 -0
- package/patches/opencode/0004-Add-heartbeat-settings-and-usage-nav.patch +506 -0
- package/patches/opencode/0005-Use-chart-icon-for-usage-nav.patch +38 -0
- package/patches/opencode/0006-Modernize-cron-settings.patch +399 -0
- package/patches/opencode/0007-Rename-waffle-namespaces-to-mockingbird.patch +1110 -0
- package/patches/opencode/0008-Remove-cron-contract-section.patch +178 -0
- package/patches/opencode/0009-Rework-cron-tab-as-operations-console.patch +414 -0
- package/patches/opencode/0010-Refine-heartbeat-settings-controls.patch +208 -0
- package/runtime-assets/opencode-config/opencode.jsonc +25 -0
- package/runtime-assets/opencode-config/package.json +5 -0
- package/runtime-assets/opencode-config/plugins/agent-mockingbird.ts +715 -0
- package/runtime-assets/workspace/.agents/skills/config-auditor/SKILL.md +25 -0
- package/runtime-assets/workspace/.agents/skills/config-editor/SKILL.md +24 -0
- package/runtime-assets/workspace/.agents/skills/cron-manager/SKILL.md +57 -0
- package/runtime-assets/workspace/.agents/skills/memory-ops/SKILL.md +120 -0
- package/runtime-assets/workspace/.agents/skills/runtime-diagnose/SKILL.md +25 -0
- package/runtime-assets/workspace/AGENTS.md +56 -0
- package/runtime-assets/workspace/MEMORY.md +4 -0
- package/scripts/build-release-bundle.sh +66 -0
- package/scripts/check-ship.ts +383 -0
- package/scripts/dev-opencode.sh +17 -0
- package/scripts/dev-stack-opencode.sh +15 -0
- package/scripts/dev-stack.sh +61 -0
- package/scripts/install-systemd.sh +87 -0
- package/scripts/memory-e2e.sh +76 -0
- package/scripts/memory-trace-e2e.sh +141 -0
- package/scripts/migrate-opencode-env.ts +108 -0
- package/scripts/onboard/bootstrap.sh +32 -0
- package/scripts/opencode-swap.ts +78 -0
- package/scripts/opencode-sync.ts +715 -0
- package/scripts/runtime-assets-sync.mjs +83 -0
- package/scripts/setup-git-hooks.ts +39 -0
- package/tsconfig.json +45 -0
- package/tui.json +98 -0
- package/turbo.json +36 -0
- package/vendor/OPENCODE_VENDOR.md +13 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
From 9ad326e102738b40f41f423a58de68373bfdbbef Mon Sep 17 00:00:00 2001
|
|
2
|
+
From: Matt Campbell <matt@battleshopper.com>
|
|
3
|
+
Date: Thu, 19 Mar 2026 16:50:15 -0500
|
|
4
|
+
Subject: [PATCH 08/10] Remove cron contract section
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
.../src/components/settings-cron-data.test.ts | 23 +---------------
|
|
8
|
+
.../app/src/components/settings-cron-data.ts | 21 +--------------
|
|
9
|
+
packages/app/src/components/settings-cron.tsx | 27 +------------------
|
|
10
|
+
3 files changed, 3 insertions(+), 68 deletions(-)
|
|
11
|
+
|
|
12
|
+
diff --git a/packages/app/src/components/settings-cron-data.test.ts b/packages/app/src/components/settings-cron-data.test.ts
|
|
13
|
+
index c1ec8fcd3..2cc587ed7 100644
|
|
14
|
+
--- a/packages/app/src/components/settings-cron-data.test.ts
|
|
15
|
+
+++ b/packages/app/src/components/settings-cron-data.test.ts
|
|
16
|
+
@@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test"
|
|
17
|
+
import { DEFAULT_JOB, loadCronSettings, serializeCronJobForEdit, type CronJobDefinition } from "./settings-cron-data"
|
|
18
|
+
|
|
19
|
+
describe("loadCronSettings", () => {
|
|
20
|
+
- test("loads jobs, health, and contract without requesting handlers", async () => {
|
|
21
|
+
+ test("loads jobs and health without requesting handlers or contract metadata", async () => {
|
|
22
|
+
const calls: Array<{ path: string; init?: RequestInit }> = []
|
|
23
|
+
const requestJson = async <T>(path: string, init?: RequestInit) => {
|
|
24
|
+
calls.push({ path, init })
|
|
25
|
+
@@ -12,15 +12,6 @@ describe("loadCronSettings", () => {
|
|
26
|
+
if (path === "/api/mockingbird/cron/health") {
|
|
27
|
+
return { health: { enabled: true, jobs: { total: 0, enabled: 0 } } } as T
|
|
28
|
+
}
|
|
29
|
+
- if (path === "/api/mockingbird/cron/manage") {
|
|
30
|
+
- return {
|
|
31
|
+
- contract: {
|
|
32
|
+
- runModes: {
|
|
33
|
+
- agent: { requires: ["agentPromptTemplate"], forbids: ["conditionModulePath"] },
|
|
34
|
+
- },
|
|
35
|
+
- },
|
|
36
|
+
- } as T
|
|
37
|
+
- }
|
|
38
|
+
throw new Error(`Unexpected path: ${path}`)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@@ -29,22 +20,10 @@ describe("loadCronSettings", () => {
|
|
42
|
+
expect(payload).toEqual({
|
|
43
|
+
jobs: [],
|
|
44
|
+
health: { enabled: true, jobs: { total: 0, enabled: 0 } },
|
|
45
|
+
- contract: {
|
|
46
|
+
- runModes: {
|
|
47
|
+
- agent: { requires: ["agentPromptTemplate"], forbids: ["conditionModulePath"] },
|
|
48
|
+
- },
|
|
49
|
+
- },
|
|
50
|
+
})
|
|
51
|
+
expect(calls).toEqual([
|
|
52
|
+
{ path: "/api/mockingbird/cron/jobs", init: undefined },
|
|
53
|
+
{ path: "/api/mockingbird/cron/health", init: undefined },
|
|
54
|
+
- {
|
|
55
|
+
- path: "/api/mockingbird/cron/manage",
|
|
56
|
+
- init: {
|
|
57
|
+
- method: "POST",
|
|
58
|
+
- body: JSON.stringify({ action: "describe_contract" }),
|
|
59
|
+
- },
|
|
60
|
+
- },
|
|
61
|
+
])
|
|
62
|
+
})
|
|
63
|
+
})
|
|
64
|
+
diff --git a/packages/app/src/components/settings-cron-data.ts b/packages/app/src/components/settings-cron-data.ts
|
|
65
|
+
index 2eeab5f94..8c044168f 100644
|
|
66
|
+
--- a/packages/app/src/components/settings-cron-data.ts
|
|
67
|
+
+++ b/packages/app/src/components/settings-cron-data.ts
|
|
68
|
+
@@ -27,16 +27,6 @@ export type CronHealthSnapshot = {
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
-type CronContractMode = {
|
|
73
|
+
- requires?: string[]
|
|
74
|
+
- optional?: string[]
|
|
75
|
+
- forbids?: string[]
|
|
76
|
+
-}
|
|
77
|
+
-
|
|
78
|
+
-export type CronContract = {
|
|
79
|
+
- runModes: Record<string, CronContractMode>
|
|
80
|
+
-}
|
|
81
|
+
-
|
|
82
|
+
type CronJobsResponse = {
|
|
83
|
+
jobs: CronJobDefinition[]
|
|
84
|
+
}
|
|
85
|
+
@@ -45,10 +35,6 @@ type CronHealthResponse = {
|
|
86
|
+
health: CronHealthSnapshot
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
-type CronContractResponse = {
|
|
90
|
+
- contract: CronContract
|
|
91
|
+
-}
|
|
92
|
+
-
|
|
93
|
+
type MockingbirdJson = <T>(path: string, init?: RequestInit) => Promise<T>
|
|
94
|
+
|
|
95
|
+
const DEFAULT_AGENT_JOB = {
|
|
96
|
+
@@ -64,19 +50,14 @@ const DEFAULT_AGENT_JOB = {
|
|
97
|
+
export const DEFAULT_JOB = prettyJson(DEFAULT_AGENT_JOB)
|
|
98
|
+
|
|
99
|
+
export async function loadCronSettings(requestJson: MockingbirdJson = mockingbirdJson) {
|
|
100
|
+
- const [jobs, health, contract] = await Promise.all([
|
|
101
|
+
+ const [jobs, health] = await Promise.all([
|
|
102
|
+
requestJson<CronJobsResponse>("/api/mockingbird/cron/jobs"),
|
|
103
|
+
requestJson<CronHealthResponse>("/api/mockingbird/cron/health"),
|
|
104
|
+
- requestJson<CronContractResponse>("/api/mockingbird/cron/manage", {
|
|
105
|
+
- method: "POST",
|
|
106
|
+
- body: JSON.stringify({ action: "describe_contract" }),
|
|
107
|
+
- }),
|
|
108
|
+
])
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
jobs: jobs.jobs,
|
|
112
|
+
health: health.health,
|
|
113
|
+
- contract: contract.contract,
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
diff --git a/packages/app/src/components/settings-cron.tsx b/packages/app/src/components/settings-cron.tsx
|
|
118
|
+
index 67f282245..f56fef497 100644
|
|
119
|
+
--- a/packages/app/src/components/settings-cron.tsx
|
|
120
|
+
+++ b/packages/app/src/components/settings-cron.tsx
|
|
121
|
+
@@ -3,7 +3,7 @@ import { showToast } from "@opencode-ai/ui/toast"
|
|
122
|
+
import { For, onMount, Show, type Component } from "solid-js"
|
|
123
|
+
import { createStore } from "solid-js/store"
|
|
124
|
+
import { mockingbirdJson } from "@/utils/mockingbird"
|
|
125
|
+
-import { DEFAULT_JOB, loadCronSettings, serializeCronJobForEdit, type CronContract, type CronHealthSnapshot, type CronJobDefinition } from "./settings-cron-data"
|
|
126
|
+
+import { DEFAULT_JOB, loadCronSettings, serializeCronJobForEdit, type CronHealthSnapshot, type CronJobDefinition } from "./settings-cron-data"
|
|
127
|
+
import { MockingbirdCard, MockingbirdMetaRow, MockingbirdNotice, MockingbirdSettingsPage, MockingbirdSettingsSection, MockingbirdTextArea, MockingbirdToolbar } from "./settings-mockingbird-shared"
|
|
128
|
+
|
|
129
|
+
export const SettingsCron: Component = () => {
|
|
130
|
+
@@ -14,7 +14,6 @@ export const SettingsCron: Component = () => {
|
|
131
|
+
error: "",
|
|
132
|
+
jobs: [] as CronJobDefinition[],
|
|
133
|
+
health: null as CronHealthSnapshot | null,
|
|
134
|
+
- contract: null as CronContract | null,
|
|
135
|
+
createText: DEFAULT_JOB,
|
|
136
|
+
editingId: "",
|
|
137
|
+
editText: "",
|
|
138
|
+
@@ -27,7 +26,6 @@ export const SettingsCron: Component = () => {
|
|
139
|
+
const payload = await loadCronSettings()
|
|
140
|
+
setState("jobs", payload.jobs)
|
|
141
|
+
setState("health", payload.health)
|
|
142
|
+
- setState("contract", payload.contract)
|
|
143
|
+
} catch (error) {
|
|
144
|
+
setState("error", error instanceof Error ? error.message : "Failed to load cron jobs")
|
|
145
|
+
} finally {
|
|
146
|
+
@@ -158,29 +156,6 @@ export const SettingsCron: Component = () => {
|
|
147
|
+
)}
|
|
148
|
+
</Show>
|
|
149
|
+
|
|
150
|
+
- <Show when={state.contract}>
|
|
151
|
+
- {(contract) => (
|
|
152
|
+
- <MockingbirdSettingsSection title="Run mode contract" description="Current backend requirements for each cron run mode.">
|
|
153
|
+
- <For each={Object.entries(contract().runModes)}>
|
|
154
|
+
- {([mode, details]) => (
|
|
155
|
+
- <div class="px-4 py-4 border-b border-border-weak-base last:border-none flex flex-col gap-1">
|
|
156
|
+
- <div class="text-14-medium text-text-strong">{mode}</div>
|
|
157
|
+
- <div class="text-12-regular text-text-weak">
|
|
158
|
+
- Requires: {details.requires?.length ? details.requires.join(", ") : "Nothing special"}
|
|
159
|
+
- </div>
|
|
160
|
+
- <Show when={details.optional?.length}>
|
|
161
|
+
- <div class="text-12-regular text-text-weak">Optional: {details.optional?.join(", ")}</div>
|
|
162
|
+
- </Show>
|
|
163
|
+
- <Show when={details.forbids?.length}>
|
|
164
|
+
- <div class="text-12-regular text-text-weak">Forbids: {details.forbids?.join(", ")}</div>
|
|
165
|
+
- </Show>
|
|
166
|
+
- </div>
|
|
167
|
+
- )}
|
|
168
|
+
- </For>
|
|
169
|
+
- </MockingbirdSettingsSection>
|
|
170
|
+
- )}
|
|
171
|
+
- </Show>
|
|
172
|
+
-
|
|
173
|
+
<MockingbirdSettingsSection title="Jobs">
|
|
174
|
+
<Show
|
|
175
|
+
when={state.jobs.length > 0}
|
|
176
|
+
--
|
|
177
|
+
2.53.0
|
|
178
|
+
|
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
From 42e13ff48c3dfa2ff51f90fef6bdf808b1e28f17 Mon Sep 17 00:00:00 2001
|
|
2
|
+
From: Matt Campbell <matt@battleshopper.com>
|
|
3
|
+
Date: Thu, 19 Mar 2026 17:40:25 -0500
|
|
4
|
+
Subject: [PATCH 09/10] Rework cron tab as operations console
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
.../src/components/settings-cron-data.test.ts | 102 +++++++++++-----
|
|
8
|
+
.../app/src/components/settings-cron-data.ts | 65 +++++-----
|
|
9
|
+
packages/app/src/components/settings-cron.tsx | 112 ++++--------------
|
|
10
|
+
3 files changed, 131 insertions(+), 148 deletions(-)
|
|
11
|
+
|
|
12
|
+
diff --git a/packages/app/src/components/settings-cron-data.test.ts b/packages/app/src/components/settings-cron-data.test.ts
|
|
13
|
+
index 2cc587ed7..a81509423 100644
|
|
14
|
+
--- a/packages/app/src/components/settings-cron-data.test.ts
|
|
15
|
+
+++ b/packages/app/src/components/settings-cron-data.test.ts
|
|
16
|
+
@@ -1,5 +1,5 @@
|
|
17
|
+
import { describe, expect, test } from "bun:test"
|
|
18
|
+
-import { DEFAULT_JOB, loadCronSettings, serializeCronJobForEdit, type CronJobDefinition } from "./settings-cron-data"
|
|
19
|
+
+import { describeCronJobTarget, formatCronSchedule, loadCronSettings, type CronJobDefinition } from "./settings-cron-data"
|
|
20
|
+
|
|
21
|
+
describe("loadCronSettings", () => {
|
|
22
|
+
test("loads jobs and health without requesting handlers or contract metadata", async () => {
|
|
23
|
+
@@ -28,48 +28,96 @@ describe("loadCronSettings", () => {
|
|
24
|
+
})
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
-describe("Cron settings payload helpers", () => {
|
|
28
|
+
- test("default job example uses the current agent contract", () => {
|
|
29
|
+
- const parsed = JSON.parse(DEFAULT_JOB)
|
|
30
|
+
- expect(parsed).toMatchObject({
|
|
31
|
+
- name: "Hourly review",
|
|
32
|
+
+describe("Cron settings display helpers", () => {
|
|
33
|
+
+ test("formats every schedules as human intervals", () => {
|
|
34
|
+
+ const job = {
|
|
35
|
+
+ id: "cron-1",
|
|
36
|
+
+ name: "Location tracker",
|
|
37
|
+
+ enabled: true,
|
|
38
|
+
scheduleKind: "every",
|
|
39
|
+
- everyMs: 3_600_000,
|
|
40
|
+
- runMode: "agent",
|
|
41
|
+
- agentPromptTemplate: expect.any(String),
|
|
42
|
+
+ scheduleExpr: null,
|
|
43
|
+
+ everyMs: 120_000,
|
|
44
|
+
+ atIso: null,
|
|
45
|
+
+ timezone: null,
|
|
46
|
+
+ runMode: "conditional_agent",
|
|
47
|
+
+ conditionModulePath: "cron/location-tracker.ts",
|
|
48
|
+
+ conditionDescription: null,
|
|
49
|
+
+ agentPromptTemplate: null,
|
|
50
|
+
+ agentModelOverride: null,
|
|
51
|
+
+ maxAttempts: 3,
|
|
52
|
+
+ retryBackoffMs: 1_000,
|
|
53
|
+
payload: {},
|
|
54
|
+
- })
|
|
55
|
+
- expect(parsed.handlerKey).toBeUndefined()
|
|
56
|
+
+ } satisfies CronJobDefinition
|
|
57
|
+
+
|
|
58
|
+
+ expect(formatCronSchedule(job)).toBe("Every 2m")
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
- test("edit payload excludes deprecated handlerKey", () => {
|
|
62
|
+
+ test("formats cron schedules with timezone", () => {
|
|
63
|
+
const job = {
|
|
64
|
+
- id: "cron-1",
|
|
65
|
+
- name: "Daily review",
|
|
66
|
+
+ id: "cron-2",
|
|
67
|
+
+ name: "Release check",
|
|
68
|
+
enabled: true,
|
|
69
|
+
scheduleKind: "cron",
|
|
70
|
+
- scheduleExpr: "0 9 * * *",
|
|
71
|
+
+ scheduleExpr: "0 16 * * *",
|
|
72
|
+
everyMs: null,
|
|
73
|
+
atIso: null,
|
|
74
|
+
timezone: "America/Chicago",
|
|
75
|
+
- runMode: "background",
|
|
76
|
+
- conditionModulePath: "cron/check.ts",
|
|
77
|
+
- conditionDescription: "Checks for changes",
|
|
78
|
+
+ runMode: "conditional_agent",
|
|
79
|
+
+ conditionModulePath: "cron/release-check.ts",
|
|
80
|
+
+ conditionDescription: null,
|
|
81
|
+
agentPromptTemplate: null,
|
|
82
|
+
agentModelOverride: null,
|
|
83
|
+
maxAttempts: 3,
|
|
84
|
+
retryBackoffMs: 1_000,
|
|
85
|
+
- payload: { channel: "main" },
|
|
86
|
+
+ payload: {},
|
|
87
|
+
} satisfies CronJobDefinition
|
|
88
|
+
|
|
89
|
+
- const parsed = JSON.parse(serializeCronJobForEdit(job)) as Record<string, unknown>
|
|
90
|
+
+ expect(formatCronSchedule(job)).toBe("0 16 * * * (America/Chicago)")
|
|
91
|
+
+ })
|
|
92
|
+
|
|
93
|
+
- expect(parsed).toMatchObject({
|
|
94
|
+
- name: "Daily review",
|
|
95
|
+
- runMode: "background",
|
|
96
|
+
- conditionModulePath: "cron/check.ts",
|
|
97
|
+
- payload: { channel: "main" },
|
|
98
|
+
- })
|
|
99
|
+
- expect(parsed.handlerKey).toBeUndefined()
|
|
100
|
+
+ test("describes code-backed cron targets", () => {
|
|
101
|
+
+ const job = {
|
|
102
|
+
+ id: "cron-3",
|
|
103
|
+
+ name: "WiFi monitor",
|
|
104
|
+
+ enabled: true,
|
|
105
|
+
+ scheduleKind: "every",
|
|
106
|
+
+ scheduleExpr: null,
|
|
107
|
+
+ everyMs: 120_000,
|
|
108
|
+
+ atIso: null,
|
|
109
|
+
+ timezone: null,
|
|
110
|
+
+ runMode: "conditional_agent",
|
|
111
|
+
+ conditionModulePath: "cron/wifi-device-monitor.ts",
|
|
112
|
+
+ conditionDescription: "Checks for nearby devices",
|
|
113
|
+
+ agentPromptTemplate: null,
|
|
114
|
+
+ agentModelOverride: null,
|
|
115
|
+
+ maxAttempts: 3,
|
|
116
|
+
+ retryBackoffMs: 1_000,
|
|
117
|
+
+ payload: {},
|
|
118
|
+
+ } satisfies CronJobDefinition
|
|
119
|
+
+
|
|
120
|
+
+ expect(describeCronJobTarget(job)).toBe("cron/wifi-device-monitor.ts")
|
|
121
|
+
+ })
|
|
122
|
+
+
|
|
123
|
+
+ test("labels prompt-backed agent jobs without exposing editable prompt UI", () => {
|
|
124
|
+
+ const job = {
|
|
125
|
+
+ id: "cron-4",
|
|
126
|
+
+ name: "Summary",
|
|
127
|
+
+ enabled: true,
|
|
128
|
+
+ scheduleKind: "cron",
|
|
129
|
+
+ scheduleExpr: "0 9 * * *",
|
|
130
|
+
+ everyMs: null,
|
|
131
|
+
+ atIso: null,
|
|
132
|
+
+ timezone: "America/Chicago",
|
|
133
|
+
+ runMode: "agent",
|
|
134
|
+
+ conditionModulePath: null,
|
|
135
|
+
+ conditionDescription: null,
|
|
136
|
+
+ agentPromptTemplate: "Summarize",
|
|
137
|
+
+ agentModelOverride: null,
|
|
138
|
+
+ maxAttempts: 3,
|
|
139
|
+
+ retryBackoffMs: 1_000,
|
|
140
|
+
+ payload: {},
|
|
141
|
+
+ } satisfies CronJobDefinition
|
|
142
|
+
+
|
|
143
|
+
+ expect(describeCronJobTarget(job)).toBe("Prompt-backed agent job")
|
|
144
|
+
})
|
|
145
|
+
})
|
|
146
|
+
diff --git a/packages/app/src/components/settings-cron-data.ts b/packages/app/src/components/settings-cron-data.ts
|
|
147
|
+
index 8c044168f..992820096 100644
|
|
148
|
+
--- a/packages/app/src/components/settings-cron-data.ts
|
|
149
|
+
+++ b/packages/app/src/components/settings-cron-data.ts
|
|
150
|
+
@@ -1,4 +1,4 @@
|
|
151
|
+
-import { prettyJson, mockingbirdJson } from "@/utils/mockingbird"
|
|
152
|
+
+import { mockingbirdJson } from "@/utils/mockingbird"
|
|
153
|
+
|
|
154
|
+
export type CronJobDefinition = {
|
|
155
|
+
id: string
|
|
156
|
+
@@ -37,18 +37,6 @@ type CronHealthResponse = {
|
|
157
|
+
|
|
158
|
+
type MockingbirdJson = <T>(path: string, init?: RequestInit) => Promise<T>
|
|
159
|
+
|
|
160
|
+
-const DEFAULT_AGENT_JOB = {
|
|
161
|
+
- name: "Hourly review",
|
|
162
|
+
- enabled: true,
|
|
163
|
+
- scheduleKind: "every",
|
|
164
|
+
- everyMs: 3_600_000,
|
|
165
|
+
- runMode: "agent",
|
|
166
|
+
- agentPromptTemplate: "Review recent workspace activity and summarize anything that needs attention.",
|
|
167
|
+
- payload: {},
|
|
168
|
+
-} as const
|
|
169
|
+
-
|
|
170
|
+
-export const DEFAULT_JOB = prettyJson(DEFAULT_AGENT_JOB)
|
|
171
|
+
-
|
|
172
|
+
export async function loadCronSettings(requestJson: MockingbirdJson = mockingbirdJson) {
|
|
173
|
+
const [jobs, health] = await Promise.all([
|
|
174
|
+
requestJson<CronJobsResponse>("/api/mockingbird/cron/jobs"),
|
|
175
|
+
@@ -61,22 +49,37 @@ export async function loadCronSettings(requestJson: MockingbirdJson = mockingbir
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
-export function serializeCronJobForEdit(job: CronJobDefinition) {
|
|
180
|
+
- return prettyJson({
|
|
181
|
+
- name: job.name,
|
|
182
|
+
- enabled: job.enabled,
|
|
183
|
+
- scheduleKind: job.scheduleKind,
|
|
184
|
+
- scheduleExpr: job.scheduleExpr,
|
|
185
|
+
- everyMs: job.everyMs,
|
|
186
|
+
- atIso: job.atIso,
|
|
187
|
+
- timezone: job.timezone,
|
|
188
|
+
- runMode: job.runMode,
|
|
189
|
+
- conditionModulePath: job.conditionModulePath,
|
|
190
|
+
- conditionDescription: job.conditionDescription,
|
|
191
|
+
- agentPromptTemplate: job.agentPromptTemplate,
|
|
192
|
+
- agentModelOverride: job.agentModelOverride,
|
|
193
|
+
- maxAttempts: job.maxAttempts,
|
|
194
|
+
- retryBackoffMs: job.retryBackoffMs,
|
|
195
|
+
- payload: job.payload,
|
|
196
|
+
- })
|
|
197
|
+
+function formatEveryInterval(everyMs: number | null) {
|
|
198
|
+
+ if (!everyMs || !Number.isFinite(everyMs) || everyMs < 1_000) return "Every custom interval"
|
|
199
|
+
+ if (everyMs % 86_400_000 === 0) return `Every ${everyMs / 86_400_000}d`
|
|
200
|
+
+ if (everyMs % 3_600_000 === 0) return `Every ${everyMs / 3_600_000}h`
|
|
201
|
+
+ if (everyMs % 60_000 === 0) return `Every ${everyMs / 60_000}m`
|
|
202
|
+
+ if (everyMs % 1_000 === 0) return `Every ${everyMs / 1_000}s`
|
|
203
|
+
+ return `Every ${everyMs}ms`
|
|
204
|
+
+}
|
|
205
|
+
+
|
|
206
|
+
+export function formatCronSchedule(job: CronJobDefinition) {
|
|
207
|
+
+ if (job.scheduleKind === "every") {
|
|
208
|
+
+ return formatEveryInterval(job.everyMs)
|
|
209
|
+
+ }
|
|
210
|
+
+
|
|
211
|
+
+ if (job.scheduleKind === "cron") {
|
|
212
|
+
+ const expr = job.scheduleExpr?.trim() || "Missing cron expression"
|
|
213
|
+
+ return job.timezone ? `${expr} (${job.timezone})` : expr
|
|
214
|
+
+ }
|
|
215
|
+
+
|
|
216
|
+
+ const atIso = job.atIso?.trim()
|
|
217
|
+
+ return atIso ? `At ${atIso}` : "No schedule"
|
|
218
|
+
+}
|
|
219
|
+
+
|
|
220
|
+
+export function describeCronJobTarget(job: CronJobDefinition) {
|
|
221
|
+
+ if (job.conditionModulePath?.trim()) {
|
|
222
|
+
+ return job.conditionModulePath
|
|
223
|
+
+ }
|
|
224
|
+
+
|
|
225
|
+
+ if (job.runMode === "agent") {
|
|
226
|
+
+ return "Prompt-backed agent job"
|
|
227
|
+
+ }
|
|
228
|
+
+
|
|
229
|
+
+ return "No code target"
|
|
230
|
+
}
|
|
231
|
+
diff --git a/packages/app/src/components/settings-cron.tsx b/packages/app/src/components/settings-cron.tsx
|
|
232
|
+
index f56fef497..24395d8b5 100644
|
|
233
|
+
--- a/packages/app/src/components/settings-cron.tsx
|
|
234
|
+
+++ b/packages/app/src/components/settings-cron.tsx
|
|
235
|
+
@@ -1,22 +1,19 @@
|
|
236
|
+
import { Button } from "@opencode-ai/ui/button"
|
|
237
|
+
+import { Switch } from "@opencode-ai/ui/switch"
|
|
238
|
+
import { showToast } from "@opencode-ai/ui/toast"
|
|
239
|
+
import { For, onMount, Show, type Component } from "solid-js"
|
|
240
|
+
import { createStore } from "solid-js/store"
|
|
241
|
+
import { mockingbirdJson } from "@/utils/mockingbird"
|
|
242
|
+
-import { DEFAULT_JOB, loadCronSettings, serializeCronJobForEdit, type CronHealthSnapshot, type CronJobDefinition } from "./settings-cron-data"
|
|
243
|
+
-import { MockingbirdCard, MockingbirdMetaRow, MockingbirdNotice, MockingbirdSettingsPage, MockingbirdSettingsSection, MockingbirdTextArea, MockingbirdToolbar } from "./settings-mockingbird-shared"
|
|
244
|
+
+import { describeCronJobTarget, formatCronSchedule, loadCronSettings, type CronHealthSnapshot, type CronJobDefinition } from "./settings-cron-data"
|
|
245
|
+
+import { MockingbirdMetaRow, MockingbirdNotice, MockingbirdSettingsPage, MockingbirdSettingsSection, MockingbirdToolbar } from "./settings-mockingbird-shared"
|
|
246
|
+
|
|
247
|
+
export const SettingsCron: Component = () => {
|
|
248
|
+
const [state, setState] = createStore({
|
|
249
|
+
loading: true,
|
|
250
|
+
- saving: false,
|
|
251
|
+
busyId: "",
|
|
252
|
+
error: "",
|
|
253
|
+
jobs: [] as CronJobDefinition[],
|
|
254
|
+
health: null as CronHealthSnapshot | null,
|
|
255
|
+
- createText: DEFAULT_JOB,
|
|
256
|
+
- editingId: "",
|
|
257
|
+
- editText: "",
|
|
258
|
+
})
|
|
259
|
+
|
|
260
|
+
async function load() {
|
|
261
|
+
@@ -37,55 +34,19 @@ export const SettingsCron: Component = () => {
|
|
262
|
+
await load()
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
- async function createJob() {
|
|
266
|
+
- let payload: unknown
|
|
267
|
+
- try {
|
|
268
|
+
- payload = JSON.parse(state.createText)
|
|
269
|
+
- } catch (error) {
|
|
270
|
+
- setState("error", error instanceof Error ? error.message : "Invalid cron job JSON")
|
|
271
|
+
- return
|
|
272
|
+
- }
|
|
273
|
+
-
|
|
274
|
+
- setState("saving", true)
|
|
275
|
+
+ async function setEnabled(id: string, enabled: boolean) {
|
|
276
|
+
+ setState("busyId", id)
|
|
277
|
+
setState("error", "")
|
|
278
|
+
try {
|
|
279
|
+
- await mockingbirdJson("/api/mockingbird/cron/jobs", {
|
|
280
|
+
- method: "POST",
|
|
281
|
+
- body: JSON.stringify(payload),
|
|
282
|
+
+ await mockingbirdJson(`/api/mockingbird/cron/jobs/${encodeURIComponent(id)}`, {
|
|
283
|
+
+ method: "PATCH",
|
|
284
|
+
+ body: JSON.stringify({ enabled }),
|
|
285
|
+
})
|
|
286
|
+
showToast({
|
|
287
|
+
variant: "success",
|
|
288
|
+
icon: "circle-check",
|
|
289
|
+
- title: "Cron job created",
|
|
290
|
+
- })
|
|
291
|
+
- await refresh()
|
|
292
|
+
- } catch (error) {
|
|
293
|
+
- setState("error", error instanceof Error ? error.message : "Failed to create cron job")
|
|
294
|
+
- } finally {
|
|
295
|
+
- setState("saving", false)
|
|
296
|
+
- }
|
|
297
|
+
- }
|
|
298
|
+
-
|
|
299
|
+
- async function saveEdit() {
|
|
300
|
+
- if (!state.editingId) return
|
|
301
|
+
-
|
|
302
|
+
- let payload: unknown
|
|
303
|
+
- try {
|
|
304
|
+
- payload = JSON.parse(state.editText)
|
|
305
|
+
- } catch (error) {
|
|
306
|
+
- setState("error", error instanceof Error ? error.message : "Invalid cron patch JSON")
|
|
307
|
+
- return
|
|
308
|
+
- }
|
|
309
|
+
-
|
|
310
|
+
- setState("busyId", state.editingId)
|
|
311
|
+
- setState("error", "")
|
|
312
|
+
- try {
|
|
313
|
+
- await mockingbirdJson(`/api/mockingbird/cron/jobs/${encodeURIComponent(state.editingId)}`, {
|
|
314
|
+
- method: "PATCH",
|
|
315
|
+
- body: JSON.stringify(payload),
|
|
316
|
+
+ title: enabled ? "Cron job enabled" : "Cron job disabled",
|
|
317
|
+
})
|
|
318
|
+
- setState("editingId", "")
|
|
319
|
+
- setState("editText", "")
|
|
320
|
+
await refresh()
|
|
321
|
+
} catch (error) {
|
|
322
|
+
setState("error", error instanceof Error ? error.message : "Failed to update cron job")
|
|
323
|
+
@@ -133,10 +94,10 @@ export const SettingsCron: Component = () => {
|
|
324
|
+
return (
|
|
325
|
+
<MockingbirdSettingsPage
|
|
326
|
+
title="Cron"
|
|
327
|
+
- description="Inspect cron health, create jobs, update jobs with JSON patches, and run them immediately."
|
|
328
|
+
+ description="Inspect cron health, enable or disable jobs, run them immediately, and remove them when needed."
|
|
329
|
+
actions={
|
|
330
|
+
<MockingbirdToolbar>
|
|
331
|
+
- <Button variant="ghost" size="large" onClick={() => void refresh()} disabled={state.loading || state.saving}>
|
|
332
|
+
+ <Button variant="ghost" size="large" onClick={() => void refresh()} disabled={state.loading}>
|
|
333
|
+
Refresh
|
|
334
|
+
</Button>
|
|
335
|
+
</MockingbirdToolbar>
|
|
336
|
+
@@ -168,23 +129,23 @@ export const SettingsCron: Component = () => {
|
|
337
|
+
<div class="flex flex-col gap-1">
|
|
338
|
+
<div class="text-14-medium text-text-strong">{job.name}</div>
|
|
339
|
+
<div class="text-12-regular text-text-weak">
|
|
340
|
+
- {job.id} | {job.scheduleKind} | {job.runMode}
|
|
341
|
+
+ {job.id} | {job.runMode} | {job.enabled ? "Enabled" : "Disabled"}
|
|
342
|
+
</div>
|
|
343
|
+
<div class="text-12-regular text-text-weak">
|
|
344
|
+
- {job.scheduleExpr ?? job.everyMs ?? job.atIso ?? "No schedule"}
|
|
345
|
+
+ {formatCronSchedule(job)}
|
|
346
|
+
+ </div>
|
|
347
|
+
+ <div class="text-12-regular text-text-weak">
|
|
348
|
+
+ {describeCronJobTarget(job)}
|
|
349
|
+
</div>
|
|
350
|
+
</div>
|
|
351
|
+
<div class="flex flex-wrap items-center gap-2">
|
|
352
|
+
- <Button
|
|
353
|
+
- variant="ghost"
|
|
354
|
+
- size="large"
|
|
355
|
+
- onClick={() => {
|
|
356
|
+
- setState("editingId", state.editingId === job.id ? "" : job.id)
|
|
357
|
+
- setState("editText", state.editingId === job.id ? "" : serializeCronJobForEdit(job))
|
|
358
|
+
- }}
|
|
359
|
+
+ <Switch
|
|
360
|
+
+ checked={job.enabled}
|
|
361
|
+
+ onChange={(enabled) => void setEnabled(job.id, enabled)}
|
|
362
|
+
+ disabled={state.busyId === job.id}
|
|
363
|
+
>
|
|
364
|
+
- {state.editingId === job.id ? "Close editor" : "Edit JSON"}
|
|
365
|
+
- </Button>
|
|
366
|
+
+ Enabled
|
|
367
|
+
+ </Switch>
|
|
368
|
+
<Button
|
|
369
|
+
variant="ghost"
|
|
370
|
+
size="large"
|
|
371
|
+
@@ -203,40 +164,11 @@ export const SettingsCron: Component = () => {
|
|
372
|
+
</Button>
|
|
373
|
+
</div>
|
|
374
|
+
</div>
|
|
375
|
+
-
|
|
376
|
+
- <Show when={state.editingId === job.id}>
|
|
377
|
+
- <div class="flex flex-col gap-3">
|
|
378
|
+
- <MockingbirdTextArea
|
|
379
|
+
- rows={12}
|
|
380
|
+
- value={state.editText}
|
|
381
|
+
- onInput={(event) => setState("editText", event.currentTarget.value)}
|
|
382
|
+
- />
|
|
383
|
+
- <div class="flex justify-end">
|
|
384
|
+
- <Button size="large" onClick={() => void saveEdit()} disabled={state.busyId === job.id}>
|
|
385
|
+
- Save patch
|
|
386
|
+
- </Button>
|
|
387
|
+
- </div>
|
|
388
|
+
- </div>
|
|
389
|
+
- </Show>
|
|
390
|
+
</div>
|
|
391
|
+
)}
|
|
392
|
+
</For>
|
|
393
|
+
</Show>
|
|
394
|
+
</MockingbirdSettingsSection>
|
|
395
|
+
-
|
|
396
|
+
- <MockingbirdSettingsSection title="Create job" description="Post a complete cron job definition as JSON using the current run mode contract.">
|
|
397
|
+
- <MockingbirdCard
|
|
398
|
+
- footer={
|
|
399
|
+
- <div class="flex justify-end">
|
|
400
|
+
- <Button size="large" onClick={() => void createJob()} disabled={state.saving}>
|
|
401
|
+
- Create job
|
|
402
|
+
- </Button>
|
|
403
|
+
- </div>
|
|
404
|
+
- }
|
|
405
|
+
- >
|
|
406
|
+
- <MockingbirdTextArea rows={16} value={state.createText} onInput={(event) => setState("createText", event.currentTarget.value)} />
|
|
407
|
+
- </MockingbirdCard>
|
|
408
|
+
- </MockingbirdSettingsSection>
|
|
409
|
+
</MockingbirdSettingsPage>
|
|
410
|
+
)
|
|
411
|
+
}
|
|
412
|
+
--
|
|
413
|
+
2.53.0
|
|
414
|
+
|