siclaw 0.1.0 → 0.1.2
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/README.md +75 -114
- package/dist/agentbox/gateway-client.d.ts +2 -1
- package/dist/agentbox/gateway-client.js +6 -2
- package/dist/agentbox/gateway-client.js.map +1 -1
- package/dist/agentbox/http-server.js +184 -19
- package/dist/agentbox/http-server.js.map +1 -1
- package/dist/agentbox/resource-handlers.d.ts +1 -0
- package/dist/agentbox/resource-handlers.js +23 -23
- package/dist/agentbox/resource-handlers.js.map +1 -1
- package/dist/agentbox/session.js +85 -5
- package/dist/agentbox/session.js.map +1 -1
- package/dist/agentbox-main.d.ts +2 -1
- package/dist/agentbox-main.js +65 -18
- package/dist/agentbox-main.js.map +1 -1
- package/dist/cli-credentials.d.ts +1 -0
- package/dist/cli-credentials.js +109 -0
- package/dist/cli-credentials.js.map +1 -0
- package/dist/cli-first-run.d.ts +11 -0
- package/dist/cli-first-run.js +99 -0
- package/dist/cli-first-run.js.map +1 -0
- package/dist/cli-main.js +33 -11
- package/dist/cli-main.js.map +1 -1
- package/dist/cli-setup.d.ts +5 -11
- package/dist/cli-setup.js +12 -225
- package/dist/cli-setup.js.map +1 -1
- package/dist/core/agent-factory.d.ts +4 -0
- package/dist/core/agent-factory.js +102 -151
- package/dist/core/agent-factory.js.map +1 -1
- package/dist/core/config.d.ts +10 -3
- package/dist/core/config.js +11 -95
- package/dist/core/config.js.map +1 -1
- package/dist/core/extensions/deep-investigation.d.ts +2 -1
- package/dist/core/extensions/deep-investigation.js +144 -24
- package/dist/core/extensions/deep-investigation.js.map +1 -1
- package/dist/core/extensions/setup.d.ts +8 -0
- package/dist/core/extensions/setup.js +669 -0
- package/dist/core/extensions/setup.js.map +1 -0
- package/dist/core/llm-proxy.js +7 -3
- package/dist/core/llm-proxy.js.map +1 -1
- package/dist/core/mcp-client.d.ts +0 -10
- package/dist/core/mcp-client.js +0 -65
- package/dist/core/mcp-client.js.map +1 -1
- package/dist/core/prompt.d.ts +1 -1
- package/dist/core/prompt.js +42 -5
- package/dist/core/prompt.js.map +1 -1
- package/dist/core/provider-presets.d.ts +14 -0
- package/dist/core/provider-presets.js +81 -0
- package/dist/core/provider-presets.js.map +1 -0
- package/dist/cron/cron-coordinator.d.ts +2 -0
- package/dist/cron/cron-coordinator.js +46 -14
- package/dist/cron/cron-coordinator.js.map +1 -1
- package/dist/cron/cron-executor.js +33 -8
- package/dist/cron/cron-executor.js.map +1 -1
- package/dist/cron/cron-scheduler.d.ts +1 -1
- package/dist/cron/gateway-client.d.ts +5 -0
- package/dist/cron/gateway-client.js +43 -8
- package/dist/cron/gateway-client.js.map +1 -1
- package/dist/cron-main.js +39 -9
- package/dist/cron-main.js.map +1 -1
- package/dist/gateway/agentbox/client.d.ts +11 -0
- package/dist/gateway/agentbox/client.js +18 -0
- package/dist/gateway/agentbox/client.js.map +1 -1
- package/dist/gateway/agentbox/k8s-spawner.d.ts +11 -2
- package/dist/gateway/agentbox/k8s-spawner.js +95 -52
- package/dist/gateway/agentbox/k8s-spawner.js.map +1 -1
- package/dist/gateway/agentbox/local-spawner.d.ts +1 -1
- package/dist/gateway/agentbox/local-spawner.js +4 -2
- package/dist/gateway/agentbox/local-spawner.js.map +1 -1
- package/dist/gateway/agentbox/manager.d.ts +0 -10
- package/dist/gateway/agentbox/manager.js +11 -30
- package/dist/gateway/agentbox/manager.js.map +1 -1
- package/dist/gateway/agentbox/types.d.ts +6 -4
- package/dist/gateway/cron/cron-service.d.ts +49 -0
- package/dist/gateway/cron/cron-service.js +259 -0
- package/dist/gateway/cron/cron-service.js.map +1 -0
- package/dist/gateway/db/init-schema.js +44 -0
- package/dist/gateway/db/init-schema.js.map +1 -1
- package/dist/gateway/db/migrate-sqlite.js +73 -4
- package/dist/gateway/db/migrate-sqlite.js.map +1 -1
- package/dist/gateway/db/repositories/chat-repo.d.ts +56 -2
- package/dist/gateway/db/repositories/chat-repo.js +132 -2
- package/dist/gateway/db/repositories/chat-repo.js.map +1 -1
- package/dist/gateway/db/repositories/config-repo.d.ts +31 -2
- package/dist/gateway/db/repositories/config-repo.js +57 -7
- package/dist/gateway/db/repositories/config-repo.js.map +1 -1
- package/dist/gateway/db/repositories/env-repo.d.ts +14 -0
- package/dist/gateway/db/repositories/env-repo.js +15 -2
- package/dist/gateway/db/repositories/env-repo.js.map +1 -1
- package/dist/gateway/db/repositories/model-config-repo.d.ts +1 -1
- package/dist/gateway/db/repositories/model-config-repo.js +26 -12
- package/dist/gateway/db/repositories/model-config-repo.js.map +1 -1
- package/dist/gateway/db/repositories/skill-repo.d.ts +0 -5
- package/dist/gateway/db/repositories/skill-review-repo.d.ts +1 -0
- package/dist/gateway/db/repositories/skill-review-repo.js +4 -1
- package/dist/gateway/db/repositories/skill-review-repo.js.map +1 -1
- package/dist/gateway/db/repositories/skill-version-repo.js +0 -1
- package/dist/gateway/db/repositories/skill-version-repo.js.map +1 -1
- package/dist/gateway/db/repositories/system-config-repo.d.ts +1 -1
- package/dist/gateway/db/repositories/system-config-repo.js +2 -1
- package/dist/gateway/db/repositories/system-config-repo.js.map +1 -1
- package/dist/gateway/db/repositories/user-env-config-repo.d.ts +13 -0
- package/dist/gateway/db/repositories/user-env-config-repo.js +11 -0
- package/dist/gateway/db/repositories/user-env-config-repo.js.map +1 -1
- package/dist/gateway/db/repositories/workspace-repo.d.ts +3 -2
- package/dist/gateway/db/repositories/workspace-repo.js +6 -2
- package/dist/gateway/db/repositories/workspace-repo.js.map +1 -1
- package/dist/gateway/db/schema-mysql.d.ts +473 -51
- package/dist/gateway/db/schema-mysql.js +35 -4
- package/dist/gateway/db/schema-mysql.js.map +1 -1
- package/dist/gateway/db/schema-sqlite.d.ts +522 -57
- package/dist/gateway/db/schema-sqlite.js +38 -6
- package/dist/gateway/db/schema-sqlite.js.map +1 -1
- package/dist/gateway/db/schema.d.ts +471 -51
- package/dist/gateway/db/schema.js +1 -1
- package/dist/gateway/db/schema.js.map +1 -1
- package/dist/gateway/metrics-aggregator.d.ts +65 -0
- package/dist/gateway/metrics-aggregator.js +244 -0
- package/dist/gateway/metrics-aggregator.js.map +1 -0
- package/dist/gateway/plugins/channel-bridge.d.ts +4 -1
- package/dist/gateway/plugins/channel-bridge.js +78 -86
- package/dist/gateway/plugins/channel-bridge.js.map +1 -1
- package/dist/gateway/rpc-methods.d.ts +4 -2
- package/dist/gateway/rpc-methods.js +962 -163
- package/dist/gateway/rpc-methods.js.map +1 -1
- package/dist/gateway/security/cert-manager.d.ts +2 -2
- package/dist/gateway/security/cert-manager.js +4 -2
- package/dist/gateway/security/cert-manager.js.map +1 -1
- package/dist/gateway/server.d.ts +4 -8
- package/dist/gateway/server.js +297 -261
- package/dist/gateway/server.js.map +1 -1
- package/dist/gateway/skills/file-writer.js +17 -11
- package/dist/gateway/skills/file-writer.js.map +1 -1
- package/dist/gateway/skills/script-evaluator.js +12 -9
- package/dist/gateway/skills/script-evaluator.js.map +1 -1
- package/dist/gateway/web/dist/assets/index-0p17ZeTP.js +740 -0
- package/dist/gateway/web/dist/assets/index-9eP6nPUq.js +741 -0
- package/dist/gateway/web/dist/assets/index-9eP6nPUq.js.map +1 -0
- package/dist/gateway/web/dist/assets/index-CAmSY91d.js +675 -0
- package/dist/gateway/web/dist/assets/index-DMFEh8Pp.css +1 -0
- package/dist/gateway/web/dist/assets/index-DyowBCEj.css +1 -0
- package/dist/gateway/web/dist/assets/index-PDK5JJDO.css +1 -0
- package/dist/gateway/web/dist/index.html +2 -2
- package/dist/gateway-main.js +27 -10
- package/dist/gateway-main.js.map +1 -1
- package/dist/memory/embeddings.js +5 -4
- package/dist/memory/embeddings.js.map +1 -1
- package/dist/memory/indexer.d.ts +23 -3
- package/dist/memory/indexer.js +235 -23
- package/dist/memory/indexer.js.map +1 -1
- package/dist/memory/schema.js +15 -1
- package/dist/memory/schema.js.map +1 -1
- package/dist/memory/types.d.ts +18 -0
- package/dist/memory/types.js +6 -1
- package/dist/memory/types.js.map +1 -1
- package/dist/shared/detect-language.d.ts +12 -0
- package/dist/shared/detect-language.js +78 -0
- package/dist/shared/detect-language.js.map +1 -0
- package/dist/shared/diagnostic-events.d.ts +70 -0
- package/dist/shared/diagnostic-events.js +38 -0
- package/dist/shared/diagnostic-events.js.map +1 -0
- package/dist/shared/local-collector.d.ts +56 -0
- package/dist/shared/local-collector.js +284 -0
- package/dist/shared/local-collector.js.map +1 -0
- package/dist/shared/metrics-types.d.ts +64 -0
- package/dist/shared/metrics-types.js +25 -0
- package/dist/shared/metrics-types.js.map +1 -0
- package/dist/shared/metrics.d.ts +19 -0
- package/dist/shared/metrics.js +185 -0
- package/dist/shared/metrics.js.map +1 -0
- package/dist/shared/path-utils.d.ts +15 -0
- package/dist/shared/path-utils.js +23 -0
- package/dist/shared/path-utils.js.map +1 -0
- package/dist/shared/retry.d.ts +35 -0
- package/dist/shared/retry.js +61 -0
- package/dist/shared/retry.js.map +1 -0
- package/dist/tools/command-sets.d.ts +18 -2
- package/dist/tools/command-sets.js +207 -32
- package/dist/tools/command-sets.js.map +1 -1
- package/dist/tools/command-validator.d.ts +56 -0
- package/dist/tools/command-validator.js +357 -0
- package/dist/tools/command-validator.js.map +1 -0
- package/dist/tools/create-skill.js +26 -1
- package/dist/tools/create-skill.js.map +1 -1
- package/dist/tools/credential-list.js +1 -23
- package/dist/tools/credential-list.js.map +1 -1
- package/dist/tools/credential-manager.d.ts +98 -0
- package/dist/tools/credential-manager.js +313 -0
- package/dist/tools/credential-manager.js.map +1 -0
- package/dist/tools/deep-search/engine.js +184 -127
- package/dist/tools/deep-search/engine.js.map +1 -1
- package/dist/tools/deep-search/prompts.d.ts +10 -2
- package/dist/tools/deep-search/prompts.js +37 -36
- package/dist/tools/deep-search/prompts.js.map +1 -1
- package/dist/tools/deep-search/schemas.d.ts +87 -0
- package/dist/tools/deep-search/schemas.js +85 -0
- package/dist/tools/deep-search/schemas.js.map +1 -0
- package/dist/tools/deep-search/sub-agent.d.ts +21 -0
- package/dist/tools/deep-search/sub-agent.js +153 -4
- package/dist/tools/deep-search/sub-agent.js.map +1 -1
- package/dist/tools/deep-search/tool.js +1 -0
- package/dist/tools/deep-search/tool.js.map +1 -1
- package/dist/tools/deep-search/types.d.ts +2 -0
- package/dist/tools/deep-search/types.js.map +1 -1
- package/dist/tools/dp-tools.js +29 -5
- package/dist/tools/dp-tools.js.map +1 -1
- package/dist/tools/exec-utils.d.ts +85 -0
- package/dist/tools/exec-utils.js +294 -0
- package/dist/tools/exec-utils.js.map +1 -0
- package/dist/tools/fork-skill.js +14 -2
- package/dist/tools/fork-skill.js.map +1 -1
- package/dist/tools/investigation-feedback.d.ts +3 -0
- package/dist/tools/investigation-feedback.js +71 -0
- package/dist/tools/investigation-feedback.js.map +1 -0
- package/dist/tools/manage-schedule.js +16 -6
- package/dist/tools/manage-schedule.js.map +1 -1
- package/dist/tools/netns-script.js +27 -281
- package/dist/tools/netns-script.js.map +1 -1
- package/dist/tools/node-exec.d.ts +2 -14
- package/dist/tools/node-exec.js +18 -225
- package/dist/tools/node-exec.js.map +1 -1
- package/dist/tools/node-script.js +14 -168
- package/dist/tools/node-script.js.map +1 -1
- package/dist/tools/pod-exec.d.ts +1 -1
- package/dist/tools/pod-exec.js +10 -26
- package/dist/tools/pod-exec.js.map +1 -1
- package/dist/tools/pod-nsenter-exec.js +21 -225
- package/dist/tools/pod-nsenter-exec.js.map +1 -1
- package/dist/tools/pod-script.js +10 -19
- package/dist/tools/pod-script.js.map +1 -1
- package/dist/tools/restricted-bash.d.ts +1 -17
- package/dist/tools/restricted-bash.js +38 -252
- package/dist/tools/restricted-bash.js.map +1 -1
- package/dist/tools/run-skill.d.ts +3 -1
- package/dist/tools/run-skill.js +21 -1
- package/dist/tools/run-skill.js.map +1 -1
- package/dist/tools/script-resolver.d.ts +3 -1
- package/dist/tools/script-resolver.js +74 -30
- package/dist/tools/script-resolver.js.map +1 -1
- package/dist/tools/update-skill.js +17 -6
- package/dist/tools/update-skill.js.map +1 -1
- package/package.json +8 -6
- package/siclaw.mjs +10 -1
- package/skills/core/cluster-events/SKILL.md +1 -1
- package/skills/core/deep-investigation/SKILL.md +11 -0
- package/skills/core/deployment-rollout-debug/SKILL.md +1 -1
- package/skills/core/dns-debug/SKILL.md +1 -0
- package/skills/core/meta.json +12 -1
- package/skills/core/networkpolicy-debug/SKILL.md +332 -0
- package/skills/core/node-logs/scripts/get-node-logs.sh +19 -9
- package/skills/core/pod-pending-debug/SKILL.md +1 -0
- package/skills/core/quota-debug/SKILL.md +203 -0
- package/skills/core/service-debug/SKILL.md +1 -0
- package/skills/core/statefulset-debug/SKILL.md +280 -0
- package/skills/core/volcano-diagnose-pod/SKILL.md +196 -0
- package/skills/core/volcano-diagnose-pod/scripts/diagnose-pod.sh +175 -0
- package/skills/core/volcano-gang-scheduling/SKILL.md +299 -0
- package/skills/core/volcano-job-diagnose/SKILL.md +319 -0
- package/skills/core/volcano-job-diagnose/scripts/diagnose-job.sh +253 -0
- package/skills/core/volcano-node-resources/SKILL.md +334 -0
- package/skills/core/volcano-node-resources/scripts/get-node-resources.sh +281 -0
- package/skills/core/volcano-queue-diagnose/SKILL.md +294 -0
- package/skills/core/volcano-queue-diagnose/scripts/diagnose-queue.sh +283 -0
- package/skills/core/volcano-resource-insufficient/SKILL.md +315 -0
- package/skills/core/volcano-scheduler-config/SKILL.md +371 -0
- package/skills/core/volcano-scheduler-config/scripts/get-scheduler-config.sh +297 -0
- package/skills/core/volcano-scheduler-logs/SKILL.md +241 -0
- package/skills/core/volcano-scheduler-logs/scripts/get-scheduler-logs.sh +159 -0
- package/skills/platform/create-skill/SKILL.md +35 -3
- package/skills/platform/manage-skill/SKILL.md +9 -2
- package/skills/platform/update-skill/SKILL.md +17 -6
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CronService — In-process cron scheduler for Gateway
|
|
3
|
+
*
|
|
4
|
+
* Replaces the standalone cron process. Runs timers directly in the
|
|
5
|
+
* Gateway process and calls configRepo for DB access (no HTTP proxy).
|
|
6
|
+
* Job execution delegates to /api/internal/agent-prompt on localhost.
|
|
7
|
+
*/
|
|
8
|
+
import { CronScheduler, type CronJobRow } from "../../cron/cron-scheduler.js";
|
|
9
|
+
import type { ConfigRepository } from "../db/repositories/config-repo.js";
|
|
10
|
+
import type { NotificationRepository } from "../db/repositories/notification-repo.js";
|
|
11
|
+
export type SendToUserFn = (userId: string, event: string, payload: Record<string, unknown>) => void;
|
|
12
|
+
export declare class CronService {
|
|
13
|
+
readonly scheduler: CronScheduler;
|
|
14
|
+
/** Channel notification callback — set by gateway-main after construction */
|
|
15
|
+
onNotify?: (data: {
|
|
16
|
+
userId: string;
|
|
17
|
+
jobName: string;
|
|
18
|
+
result: string;
|
|
19
|
+
resultText: string;
|
|
20
|
+
error?: string;
|
|
21
|
+
}) => void;
|
|
22
|
+
private configRepo;
|
|
23
|
+
private notifRepo;
|
|
24
|
+
private sendToUser;
|
|
25
|
+
private gatewayPort;
|
|
26
|
+
private staleLockTimer;
|
|
27
|
+
private purgeTimer;
|
|
28
|
+
private sessionPurgeTimer;
|
|
29
|
+
constructor(opts: {
|
|
30
|
+
configRepo: ConfigRepository;
|
|
31
|
+
notifRepo: NotificationRepository;
|
|
32
|
+
sendToUser: SendToUserFn;
|
|
33
|
+
gatewayPort: number;
|
|
34
|
+
});
|
|
35
|
+
/** Load all active jobs and start background timers */
|
|
36
|
+
start(): Promise<void>;
|
|
37
|
+
/** Execute a single cron job */
|
|
38
|
+
private execute;
|
|
39
|
+
/** Record run history + push notification */
|
|
40
|
+
private recordResult;
|
|
41
|
+
/** Add or update a job in the scheduler */
|
|
42
|
+
addOrUpdate(job: CronJobRow): void;
|
|
43
|
+
/** Cancel a job from the scheduler */
|
|
44
|
+
cancel(jobId: string): void;
|
|
45
|
+
/** Stop all timers and clean up */
|
|
46
|
+
stop(): void;
|
|
47
|
+
private purgeNotifications;
|
|
48
|
+
private purgeSessions;
|
|
49
|
+
}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CronService — In-process cron scheduler for Gateway
|
|
3
|
+
*
|
|
4
|
+
* Replaces the standalone cron process. Runs timers directly in the
|
|
5
|
+
* Gateway process and calls configRepo for DB access (no HTTP proxy).
|
|
6
|
+
* Job execution delegates to /api/internal/agent-prompt on localhost.
|
|
7
|
+
*/
|
|
8
|
+
import crypto from "node:crypto";
|
|
9
|
+
import { CronScheduler } from "../../cron/cron-scheduler.js";
|
|
10
|
+
const EXECUTION_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
|
|
11
|
+
const STALE_LOCK_CLEANUP_MS = 6 * 60 * 1000; // 6 min
|
|
12
|
+
const PURGE_INTERVAL_MS = 24 * 60 * 60 * 1000; // 24 hours
|
|
13
|
+
const NOTIFICATION_RETENTION_DAYS = 30;
|
|
14
|
+
const SESSION_SOFT_DELETE_DAYS = 180;
|
|
15
|
+
const SESSION_HARD_DELETE_DAYS = 30;
|
|
16
|
+
const STATS_RETENTION_DAYS = 90;
|
|
17
|
+
export class CronService {
|
|
18
|
+
scheduler;
|
|
19
|
+
/** Channel notification callback — set by gateway-main after construction */
|
|
20
|
+
onNotify;
|
|
21
|
+
configRepo;
|
|
22
|
+
notifRepo;
|
|
23
|
+
sendToUser;
|
|
24
|
+
gatewayPort;
|
|
25
|
+
staleLockTimer = null;
|
|
26
|
+
purgeTimer = null;
|
|
27
|
+
sessionPurgeTimer = null;
|
|
28
|
+
constructor(opts) {
|
|
29
|
+
this.configRepo = opts.configRepo;
|
|
30
|
+
this.notifRepo = opts.notifRepo;
|
|
31
|
+
this.sendToUser = opts.sendToUser;
|
|
32
|
+
this.gatewayPort = opts.gatewayPort;
|
|
33
|
+
this.scheduler = new CronScheduler((job) => this.execute(job));
|
|
34
|
+
}
|
|
35
|
+
/** Load all active jobs and start background timers */
|
|
36
|
+
async start() {
|
|
37
|
+
// Load all active jobs
|
|
38
|
+
const jobs = await this.configRepo.listAllActiveCronJobs();
|
|
39
|
+
for (const job of jobs) {
|
|
40
|
+
this.scheduler.addOrUpdate(job);
|
|
41
|
+
}
|
|
42
|
+
console.log(`[cron-service] Loaded ${jobs.length} active jobs`);
|
|
43
|
+
// Stale lock cleanup every 6 minutes
|
|
44
|
+
this.staleLockTimer = setInterval(async () => {
|
|
45
|
+
try {
|
|
46
|
+
await this.configRepo.clearStaleLocks(STALE_LOCK_CLEANUP_MS);
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
console.warn("[cron-service] clearStaleLocks failed:", err instanceof Error ? err.message : err);
|
|
50
|
+
}
|
|
51
|
+
}, STALE_LOCK_CLEANUP_MS);
|
|
52
|
+
this.staleLockTimer.unref();
|
|
53
|
+
// Daily notification purge
|
|
54
|
+
this.purgeNotifications();
|
|
55
|
+
this.purgeTimer = setInterval(() => this.purgeNotifications(), PURGE_INTERVAL_MS);
|
|
56
|
+
this.purgeTimer.unref();
|
|
57
|
+
// Daily session purge
|
|
58
|
+
this.purgeSessions();
|
|
59
|
+
this.sessionPurgeTimer = setInterval(() => this.purgeSessions(), PURGE_INTERVAL_MS);
|
|
60
|
+
this.sessionPurgeTimer.unref();
|
|
61
|
+
console.log("[cron-service] Started");
|
|
62
|
+
}
|
|
63
|
+
/** Execute a single cron job */
|
|
64
|
+
async execute(job) {
|
|
65
|
+
// Re-validate from DB
|
|
66
|
+
const current = await this.configRepo.getCronJobById(job.id);
|
|
67
|
+
if (!current || current.status !== "active") {
|
|
68
|
+
console.log(`[cron-service] Job ${job.id} no longer active, skipping`);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
// Acquire execution lock
|
|
72
|
+
const executionId = crypto.randomUUID();
|
|
73
|
+
const locked = await this.configRepo.lockJobForExecution(job.id, executionId);
|
|
74
|
+
if (!locked) {
|
|
75
|
+
console.log(`[cron-service] Job ${job.id} already locked, skipping`);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const workspaceId = current.workspaceId ?? undefined;
|
|
79
|
+
console.log(`[cron-service] Executing job ${job.id} (${job.name}) for user ${job.userId}${workspaceId ? ` ws=${workspaceId}` : ""}`);
|
|
80
|
+
try {
|
|
81
|
+
const sessionId = `cron-${job.id}-${Date.now()}`;
|
|
82
|
+
const prompt = buildCronPrompt(current);
|
|
83
|
+
const resp = await fetch(`http://localhost:${this.gatewayPort}/api/internal/agent-prompt`, {
|
|
84
|
+
method: "POST",
|
|
85
|
+
headers: { "Content-Type": "application/json" },
|
|
86
|
+
body: JSON.stringify({
|
|
87
|
+
userId: current.userId,
|
|
88
|
+
sessionId,
|
|
89
|
+
text: prompt,
|
|
90
|
+
timeoutMs: EXECUTION_TIMEOUT_MS,
|
|
91
|
+
caller: "cron",
|
|
92
|
+
workspaceId,
|
|
93
|
+
}),
|
|
94
|
+
signal: AbortSignal.timeout(EXECUTION_TIMEOUT_MS + 10_000),
|
|
95
|
+
});
|
|
96
|
+
const data = await resp.json();
|
|
97
|
+
if (!resp.ok || data.status !== "success") {
|
|
98
|
+
throw new Error(data.error || `agent-prompt returned status=${data.status} http=${resp.status}`);
|
|
99
|
+
}
|
|
100
|
+
const resultText = data.resultText || "";
|
|
101
|
+
// Record success
|
|
102
|
+
try {
|
|
103
|
+
await this.configRepo.updateCronJobRun(job.id, "success");
|
|
104
|
+
}
|
|
105
|
+
catch (e) {
|
|
106
|
+
console.warn(`[cron-service] updateCronJobRun failed for ${job.id}:`, e instanceof Error ? e.message : e);
|
|
107
|
+
}
|
|
108
|
+
console.log(`[cron-service] Job ${job.id} completed in ${data.durationMs}ms, resultText length=${resultText.length}`);
|
|
109
|
+
// Write run record + notification
|
|
110
|
+
await this.recordResult(job, "success", resultText, undefined, data.durationMs);
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
console.error(`[cron-service] Job ${job.id} failed:`, err);
|
|
114
|
+
try {
|
|
115
|
+
await this.configRepo.updateCronJobRun(job.id, "failure");
|
|
116
|
+
}
|
|
117
|
+
catch (e) {
|
|
118
|
+
console.warn(`[cron-service] updateCronJobRun failed for ${job.id}:`, e instanceof Error ? e.message : e);
|
|
119
|
+
}
|
|
120
|
+
await this.recordResult(job, "failure", "", err instanceof Error ? err.message : String(err));
|
|
121
|
+
}
|
|
122
|
+
finally {
|
|
123
|
+
try {
|
|
124
|
+
await this.configRepo.unlockJob(job.id, executionId);
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
console.warn(`[cron-service] Failed to unlock job ${job.id}:`, err instanceof Error ? err.message : err);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/** Record run history + push notification */
|
|
132
|
+
async recordResult(job, result, resultText, error, durationMs) {
|
|
133
|
+
// Persist run record
|
|
134
|
+
try {
|
|
135
|
+
await this.configRepo.insertCronJobRun({
|
|
136
|
+
jobId: job.id,
|
|
137
|
+
status: result,
|
|
138
|
+
resultText: resultText || undefined,
|
|
139
|
+
error,
|
|
140
|
+
durationMs,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
catch (runErr) {
|
|
144
|
+
console.warn("[cron-service] Failed to insert cron run:", runErr instanceof Error ? runErr.message : runErr);
|
|
145
|
+
}
|
|
146
|
+
// Create notification
|
|
147
|
+
const notifType = result === "success" ? "cron_success" : "cron_failure";
|
|
148
|
+
const notifMessage = result === "success" ? resultText : (error || "Unknown error");
|
|
149
|
+
const notifId = await this.notifRepo.create({
|
|
150
|
+
userId: job.userId,
|
|
151
|
+
type: notifType,
|
|
152
|
+
title: job.name,
|
|
153
|
+
message: notifMessage,
|
|
154
|
+
relatedId: job.id,
|
|
155
|
+
});
|
|
156
|
+
// Push via WebSocket
|
|
157
|
+
this.sendToUser(job.userId, "notification", {
|
|
158
|
+
id: notifId,
|
|
159
|
+
type: notifType,
|
|
160
|
+
title: job.name,
|
|
161
|
+
message: notifMessage,
|
|
162
|
+
relatedId: job.id,
|
|
163
|
+
isRead: false,
|
|
164
|
+
createdAt: new Date().toISOString(),
|
|
165
|
+
});
|
|
166
|
+
// Channel notification callback
|
|
167
|
+
if (this.onNotify) {
|
|
168
|
+
this.onNotify({
|
|
169
|
+
userId: job.userId,
|
|
170
|
+
jobName: job.name,
|
|
171
|
+
result,
|
|
172
|
+
resultText,
|
|
173
|
+
error,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/** Add or update a job in the scheduler */
|
|
178
|
+
addOrUpdate(job) {
|
|
179
|
+
this.scheduler.addOrUpdate(job);
|
|
180
|
+
}
|
|
181
|
+
/** Cancel a job from the scheduler */
|
|
182
|
+
cancel(jobId) {
|
|
183
|
+
this.scheduler.cancel(jobId);
|
|
184
|
+
}
|
|
185
|
+
/** Stop all timers and clean up */
|
|
186
|
+
stop() {
|
|
187
|
+
this.scheduler.stop();
|
|
188
|
+
if (this.staleLockTimer) {
|
|
189
|
+
clearInterval(this.staleLockTimer);
|
|
190
|
+
this.staleLockTimer = null;
|
|
191
|
+
}
|
|
192
|
+
if (this.purgeTimer) {
|
|
193
|
+
clearInterval(this.purgeTimer);
|
|
194
|
+
this.purgeTimer = null;
|
|
195
|
+
}
|
|
196
|
+
if (this.sessionPurgeTimer) {
|
|
197
|
+
clearInterval(this.sessionPurgeTimer);
|
|
198
|
+
this.sessionPurgeTimer = null;
|
|
199
|
+
}
|
|
200
|
+
console.log("[cron-service] Stopped");
|
|
201
|
+
}
|
|
202
|
+
async purgeNotifications() {
|
|
203
|
+
try {
|
|
204
|
+
const resp = await fetch(`http://localhost:${this.gatewayPort}/api/internal/notifications/purge`, {
|
|
205
|
+
method: "POST",
|
|
206
|
+
headers: { "Content-Type": "application/json" },
|
|
207
|
+
body: JSON.stringify({ retentionDays: NOTIFICATION_RETENTION_DAYS }),
|
|
208
|
+
signal: AbortSignal.timeout(10_000),
|
|
209
|
+
});
|
|
210
|
+
const data = await resp.json();
|
|
211
|
+
console.log(`[cron-service] Notification purge: deleted=${data.deleted ?? 0}`);
|
|
212
|
+
}
|
|
213
|
+
catch (err) {
|
|
214
|
+
console.warn("[cron-service] Notification purge failed:", err instanceof Error ? err.message : err);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
async purgeSessions() {
|
|
218
|
+
try {
|
|
219
|
+
const resp = await fetch(`http://localhost:${this.gatewayPort}/api/internal/sessions/purge`, {
|
|
220
|
+
method: "POST",
|
|
221
|
+
headers: { "Content-Type": "application/json" },
|
|
222
|
+
body: JSON.stringify({
|
|
223
|
+
statsRetentionDays: STATS_RETENTION_DAYS,
|
|
224
|
+
softDeleteInactiveDays: SESSION_SOFT_DELETE_DAYS,
|
|
225
|
+
hardDeleteAfterDays: SESSION_HARD_DELETE_DAYS,
|
|
226
|
+
}),
|
|
227
|
+
signal: AbortSignal.timeout(30_000),
|
|
228
|
+
});
|
|
229
|
+
const data = (await resp.json());
|
|
230
|
+
console.log(`[cron-service] Session purge: softDeleted=${data.softDeleted}, ` +
|
|
231
|
+
`statsPurged=${data.statsPurged}, sessionsPurged=${data.sessionsPurged}`);
|
|
232
|
+
}
|
|
233
|
+
catch (err) {
|
|
234
|
+
console.warn("[cron-service] Session purge failed:", err instanceof Error ? err.message : err);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
function buildCronPrompt(job) {
|
|
239
|
+
const parts = [
|
|
240
|
+
`[System: You are executing an automated scheduled task in NON-INTERACTIVE mode.
|
|
241
|
+
|
|
242
|
+
Rules:
|
|
243
|
+
- Perform the task described below directly and report the result.
|
|
244
|
+
- Do NOT ask the user any questions or request confirmations — there is no user to respond.
|
|
245
|
+
- If multiple environments, hosts, or credentials are available, operate on ALL of them unless the task description specifies a particular target.
|
|
246
|
+
- Do NOT create, modify, delete, pause, or manage any schedules.
|
|
247
|
+
- Keep the output concise and structured.
|
|
248
|
+
- Respond in the same language as the task name and description below.]`,
|
|
249
|
+
`Task: ${job.name}`,
|
|
250
|
+
];
|
|
251
|
+
if (job.description) {
|
|
252
|
+
parts.push(`Instructions: ${job.description}`);
|
|
253
|
+
}
|
|
254
|
+
if (job.skillId) {
|
|
255
|
+
parts.push(`Execute skill: ${job.skillId}`);
|
|
256
|
+
}
|
|
257
|
+
return parts.join("\n\n");
|
|
258
|
+
}
|
|
259
|
+
//# sourceMappingURL=cron-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron-service.js","sourceRoot":"","sources":["../../../src/gateway/cron/cron-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -48,6 +48,9 @@ const DDL_STATEMENTS = [
|
|
|
48
48
|
tool_input TEXT,
|
|
49
49
|
metadata JSON DEFAULT NULL,
|
|
50
50
|
timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
51
|
+
user_id VARCHAR(64),
|
|
52
|
+
outcome VARCHAR(16),
|
|
53
|
+
duration_ms INT,
|
|
51
54
|
FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
|
|
52
55
|
)`,
|
|
53
56
|
`CREATE TABLE IF NOT EXISTS skills (
|
|
@@ -95,7 +98,18 @@ const DDL_STATEMENTS = [
|
|
|
95
98
|
locked_by VARCHAR(64),
|
|
96
99
|
locked_at TIMESTAMP NULL,
|
|
97
100
|
env_id VARCHAR(64),
|
|
101
|
+
workspace_id VARCHAR(64),
|
|
98
102
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
103
|
+
)`,
|
|
104
|
+
`CREATE TABLE IF NOT EXISTS cron_job_runs (
|
|
105
|
+
id VARCHAR(64) PRIMARY KEY,
|
|
106
|
+
job_id VARCHAR(64) NOT NULL,
|
|
107
|
+
status VARCHAR(20) NOT NULL,
|
|
108
|
+
result_text TEXT,
|
|
109
|
+
error TEXT,
|
|
110
|
+
duration_ms INT,
|
|
111
|
+
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
112
|
+
FOREIGN KEY (job_id) REFERENCES cron_jobs(id) ON DELETE CASCADE
|
|
99
113
|
)`,
|
|
100
114
|
`CREATE TABLE IF NOT EXISTS cron_instances (
|
|
101
115
|
instance_id VARCHAR(64) PRIMARY KEY,
|
|
@@ -128,6 +142,7 @@ const DDL_STATEMENTS = [
|
|
|
128
142
|
id VARCHAR(64) PRIMARY KEY,
|
|
129
143
|
name VARCHAR(255) NOT NULL,
|
|
130
144
|
is_test BOOLEAN NOT NULL DEFAULT FALSE,
|
|
145
|
+
api_server VARCHAR(512) NOT NULL DEFAULT '',
|
|
131
146
|
created_by VARCHAR(32),
|
|
132
147
|
allowed_servers TEXT,
|
|
133
148
|
default_kubeconfig LONGTEXT,
|
|
@@ -244,6 +259,7 @@ const DDL_STATEMENTS = [
|
|
|
244
259
|
user_id VARCHAR(32) NOT NULL,
|
|
245
260
|
name VARCHAR(100) NOT NULL,
|
|
246
261
|
is_default BOOLEAN NOT NULL DEFAULT FALSE,
|
|
262
|
+
env_type VARCHAR(10) NOT NULL DEFAULT 'prod',
|
|
247
263
|
config_json JSON,
|
|
248
264
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
249
265
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
@@ -316,6 +332,22 @@ const DDL_STATEMENTS = [
|
|
|
316
332
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
317
333
|
FOREIGN KEY (created_by) REFERENCES users(id)
|
|
318
334
|
)`,
|
|
335
|
+
`CREATE TABLE IF NOT EXISTS session_stats (
|
|
336
|
+
id VARCHAR(64) PRIMARY KEY,
|
|
337
|
+
session_id VARCHAR(64) NOT NULL,
|
|
338
|
+
user_id VARCHAR(32) NOT NULL,
|
|
339
|
+
provider VARCHAR(64),
|
|
340
|
+
model VARCHAR(128),
|
|
341
|
+
input_tokens INT DEFAULT 0,
|
|
342
|
+
output_tokens INT DEFAULT 0,
|
|
343
|
+
cache_read_tokens INT DEFAULT 0,
|
|
344
|
+
cache_write_tokens INT DEFAULT 0,
|
|
345
|
+
duration_ms INT DEFAULT 0,
|
|
346
|
+
prompt_count INT DEFAULT 0,
|
|
347
|
+
tool_call_count INT DEFAULT 0,
|
|
348
|
+
skill_call_count INT DEFAULT 0,
|
|
349
|
+
created_at BIGINT NOT NULL
|
|
350
|
+
)`,
|
|
319
351
|
];
|
|
320
352
|
// Indexes — handled separately since MySQL lacks CREATE INDEX IF NOT EXISTS
|
|
321
353
|
const INDEX_STATEMENTS = [
|
|
@@ -333,6 +365,13 @@ const INDEX_STATEMENTS = [
|
|
|
333
365
|
`ALTER TABLE skill_versions ADD INDEX idx_skill_versions_skill (skill_id, version)`,
|
|
334
366
|
`ALTER TABLE skill_contents ADD INDEX idx_skill_contents_skill (skill_id)`,
|
|
335
367
|
`ALTER TABLE credentials ADD INDEX idx_credentials_user (user_id, type)`,
|
|
368
|
+
`ALTER TABLE session_stats ADD INDEX idx_session_stats_created (created_at)`,
|
|
369
|
+
`ALTER TABLE session_stats ADD INDEX idx_session_stats_user (user_id, created_at)`,
|
|
370
|
+
`ALTER TABLE messages ADD INDEX idx_messages_audit (role, user_id, timestamp, id)`,
|
|
371
|
+
`ALTER TABLE messages ADD INDEX idx_messages_tool_name (tool_name)`,
|
|
372
|
+
`ALTER TABLE cron_job_runs ADD INDEX idx_cron_job_runs_job (job_id, created_at)`,
|
|
373
|
+
`ALTER TABLE cron_jobs ADD INDEX idx_cron_jobs_status_assigned (status, assigned_to)`,
|
|
374
|
+
`ALTER TABLE cron_instances ADD INDEX idx_cron_instances_heartbeat (heartbeat_at)`,
|
|
336
375
|
];
|
|
337
376
|
export async function initSchema(db) {
|
|
338
377
|
if (isSqlite())
|
|
@@ -351,6 +390,11 @@ export async function initSchema(db) {
|
|
|
351
390
|
`ALTER TABLE skills MODIFY COLUMN scope ENUM('builtin','team','personal') NOT NULL DEFAULT 'personal'`,
|
|
352
391
|
`ALTER TABLE skills MODIFY COLUMN review_status ENUM('draft','pending','approved') NOT NULL DEFAULT 'draft'`,
|
|
353
392
|
`ALTER TABLE skills ADD COLUMN labels_json JSON NULL`,
|
|
393
|
+
// ADR-011: environment isolation
|
|
394
|
+
`ALTER TABLE workspaces ADD COLUMN env_type VARCHAR(10) NOT NULL DEFAULT 'prod' AFTER is_default`,
|
|
395
|
+
`ALTER TABLE environments ADD COLUMN api_server VARCHAR(512) NOT NULL DEFAULT '' AFTER is_test`,
|
|
396
|
+
`ALTER TABLE cron_jobs ADD COLUMN workspace_id VARCHAR(64)`,
|
|
397
|
+
`ALTER TABLE cron_jobs ADD CONSTRAINT fk_cron_jobs_workspace FOREIGN KEY (workspace_id) REFERENCES workspaces(id)`,
|
|
354
398
|
];
|
|
355
399
|
for (const stmt of MIGRATIONS) {
|
|
356
400
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init-schema.js","sourceRoot":"","sources":["../../../src/gateway/db/init-schema.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1D,MAAM,cAAc,GAAG;IACrB;;;;;;;;IAQE;IAEF;;;;;;;;IAQE;IAEF;;;;;;;;;;;;IAYE;IAEF
|
|
1
|
+
{"version":3,"file":"init-schema.js","sourceRoot":"","sources":["../../../src/gateway/db/init-schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -44,7 +44,10 @@ const DDL_STATEMENTS = [
|
|
|
44
44
|
tool_name TEXT,
|
|
45
45
|
tool_input TEXT,
|
|
46
46
|
metadata TEXT,
|
|
47
|
-
timestamp INTEGER NOT NULL DEFAULT (unixepoch())
|
|
47
|
+
timestamp INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
48
|
+
user_id TEXT,
|
|
49
|
+
outcome TEXT,
|
|
50
|
+
duration_ms INTEGER
|
|
48
51
|
)`,
|
|
49
52
|
`CREATE TABLE IF NOT EXISTS skills (
|
|
50
53
|
id TEXT PRIMARY KEY,
|
|
@@ -88,7 +91,17 @@ const DDL_STATEMENTS = [
|
|
|
88
91
|
assigned_to TEXT,
|
|
89
92
|
locked_by TEXT,
|
|
90
93
|
locked_at INTEGER,
|
|
91
|
-
env_id TEXT
|
|
94
|
+
env_id TEXT,
|
|
95
|
+
workspace_id TEXT
|
|
96
|
+
)`,
|
|
97
|
+
`CREATE TABLE IF NOT EXISTS cron_job_runs (
|
|
98
|
+
id TEXT PRIMARY KEY,
|
|
99
|
+
job_id TEXT NOT NULL REFERENCES cron_jobs(id) ON DELETE CASCADE,
|
|
100
|
+
status TEXT NOT NULL,
|
|
101
|
+
result_text TEXT,
|
|
102
|
+
error TEXT,
|
|
103
|
+
duration_ms INTEGER,
|
|
104
|
+
created_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
92
105
|
)`,
|
|
93
106
|
`CREATE TABLE IF NOT EXISTS cron_instances (
|
|
94
107
|
instance_id TEXT PRIMARY KEY,
|
|
@@ -118,6 +131,7 @@ const DDL_STATEMENTS = [
|
|
|
118
131
|
id TEXT PRIMARY KEY,
|
|
119
132
|
name TEXT NOT NULL,
|
|
120
133
|
is_test INTEGER NOT NULL DEFAULT 0,
|
|
134
|
+
api_server TEXT NOT NULL DEFAULT '',
|
|
121
135
|
created_by TEXT,
|
|
122
136
|
allowed_servers TEXT,
|
|
123
137
|
default_kubeconfig TEXT,
|
|
@@ -225,6 +239,7 @@ const DDL_STATEMENTS = [
|
|
|
225
239
|
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
226
240
|
name TEXT NOT NULL,
|
|
227
241
|
is_default INTEGER NOT NULL DEFAULT 0,
|
|
242
|
+
env_type TEXT NOT NULL DEFAULT 'prod',
|
|
228
243
|
config_json TEXT,
|
|
229
244
|
created_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
230
245
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
@@ -271,6 +286,22 @@ const DDL_STATEMENTS = [
|
|
|
271
286
|
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
272
287
|
created_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
273
288
|
UNIQUE (provider_id, model_id)
|
|
289
|
+
)`,
|
|
290
|
+
`CREATE TABLE IF NOT EXISTS session_stats (
|
|
291
|
+
id TEXT PRIMARY KEY,
|
|
292
|
+
session_id TEXT NOT NULL,
|
|
293
|
+
user_id TEXT NOT NULL,
|
|
294
|
+
provider TEXT,
|
|
295
|
+
model TEXT,
|
|
296
|
+
input_tokens INTEGER DEFAULT 0,
|
|
297
|
+
output_tokens INTEGER DEFAULT 0,
|
|
298
|
+
cache_read_tokens INTEGER DEFAULT 0,
|
|
299
|
+
cache_write_tokens INTEGER DEFAULT 0,
|
|
300
|
+
duration_ms INTEGER DEFAULT 0,
|
|
301
|
+
prompt_count INTEGER DEFAULT 0,
|
|
302
|
+
tool_call_count INTEGER DEFAULT 0,
|
|
303
|
+
skill_call_count INTEGER DEFAULT 0,
|
|
304
|
+
created_at INTEGER NOT NULL
|
|
274
305
|
)`,
|
|
275
306
|
`CREATE TABLE IF NOT EXISTS mcp_servers (
|
|
276
307
|
id TEXT PRIMARY KEY,
|
|
@@ -304,6 +335,13 @@ const INDEX_STATEMENTS = [
|
|
|
304
335
|
`CREATE INDEX IF NOT EXISTS idx_skill_versions_skill ON skill_versions(skill_id, version)`,
|
|
305
336
|
`CREATE INDEX IF NOT EXISTS idx_skill_contents_skill ON skill_contents(skill_id)`,
|
|
306
337
|
`CREATE INDEX IF NOT EXISTS idx_credentials_user ON credentials(user_id, type)`,
|
|
338
|
+
`CREATE INDEX IF NOT EXISTS idx_session_stats_created ON session_stats(created_at)`,
|
|
339
|
+
`CREATE INDEX IF NOT EXISTS idx_session_stats_user ON session_stats(user_id, created_at)`,
|
|
340
|
+
`CREATE INDEX IF NOT EXISTS idx_messages_audit ON messages(role, user_id, timestamp, id)`,
|
|
341
|
+
`CREATE INDEX IF NOT EXISTS idx_messages_tool_name ON messages(tool_name)`,
|
|
342
|
+
`CREATE INDEX IF NOT EXISTS idx_cron_job_runs_job ON cron_job_runs(job_id, created_at)`,
|
|
343
|
+
`CREATE INDEX IF NOT EXISTS idx_cron_jobs_status_assigned ON cron_jobs(status, assigned_to)`,
|
|
344
|
+
`CREATE INDEX IF NOT EXISTS idx_cron_instances_heartbeat ON cron_instances(heartbeat_at)`,
|
|
307
345
|
];
|
|
308
346
|
export async function runSqliteMigrations(db) {
|
|
309
347
|
console.log("[db] Running SQLite migrations...");
|
|
@@ -313,6 +351,34 @@ export async function runSqliteMigrations(db) {
|
|
|
313
351
|
for (const ddl of DDL_STATEMENTS) {
|
|
314
352
|
sdb.run(sql.raw(ddl));
|
|
315
353
|
}
|
|
354
|
+
// Schema migrations — handle existing databases missing new columns.
|
|
355
|
+
// Must run BEFORE index creation, since some indexes reference new columns.
|
|
356
|
+
const MIGRATIONS = [
|
|
357
|
+
// ADR-011: environment isolation
|
|
358
|
+
`ALTER TABLE workspaces ADD COLUMN env_type TEXT NOT NULL DEFAULT 'prod'`,
|
|
359
|
+
`ALTER TABLE environments ADD COLUMN api_server TEXT NOT NULL DEFAULT ''`,
|
|
360
|
+
`ALTER TABLE cron_jobs ADD COLUMN workspace_id TEXT`,
|
|
361
|
+
];
|
|
362
|
+
// Backfill: copy allowedServers[0] → apiServer for rows that haven't been set
|
|
363
|
+
const BACKFILLS = [
|
|
364
|
+
`UPDATE environments SET api_server = TRIM(SUBSTR(allowed_servers, 1, CASE WHEN INSTR(allowed_servers, ',') > 0 THEN INSTR(allowed_servers, ',') - 1 ELSE LENGTH(allowed_servers) END)) WHERE api_server = '' AND allowed_servers != ''`,
|
|
365
|
+
];
|
|
366
|
+
for (const stmt of MIGRATIONS) {
|
|
367
|
+
try {
|
|
368
|
+
sdb.run(sql.raw(stmt));
|
|
369
|
+
}
|
|
370
|
+
catch (_err) {
|
|
371
|
+
// Ignore "duplicate column name" errors (column already exists)
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
for (const stmt of BACKFILLS) {
|
|
375
|
+
try {
|
|
376
|
+
sdb.run(sql.raw(stmt));
|
|
377
|
+
}
|
|
378
|
+
catch (_err) {
|
|
379
|
+
// Backfill may fail on empty tables — safe to ignore
|
|
380
|
+
}
|
|
381
|
+
}
|
|
316
382
|
for (const ddl of INDEX_STATEMENTS) {
|
|
317
383
|
sdb.run(sql.raw(ddl));
|
|
318
384
|
}
|
|
@@ -325,9 +391,12 @@ export async function runSqliteMigrations(db) {
|
|
|
325
391
|
UPDATE mcp_servers SET updated_at = unixepoch() WHERE id = NEW.id;
|
|
326
392
|
END
|
|
327
393
|
`));
|
|
328
|
-
// Seed default embedding config if not present
|
|
394
|
+
// Seed default embedding config if not present (empty = unconfigured)
|
|
329
395
|
sdb.run(sql.raw(`INSERT OR IGNORE INTO embedding_config (id, provider_name, model, dimensions, updated_at)
|
|
330
|
-
VALUES ('default', '
|
|
396
|
+
VALUES ('default', '', '', 1024, ${Math.floor(Date.now() / 1000)})`));
|
|
397
|
+
// Clean up old seed that hardcoded BAAI/bge-m3 as default
|
|
398
|
+
sdb.run(sql.raw(`UPDATE embedding_config SET provider_name = '', model = ''
|
|
399
|
+
WHERE id = 'default' AND provider_name = 'default' AND model = 'BAAI/bge-m3'`));
|
|
331
400
|
// Persist schema changes to disk immediately (sql.js is in-memory)
|
|
332
401
|
flushSqliteDb();
|
|
333
402
|
console.log("[db] SQLite migrations complete");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate-sqlite.js","sourceRoot":"","sources":["../../../src/gateway/db/migrate-sqlite.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAElC,MAAM,cAAc,GAAG;IACrB;;;;;;;;IAQE;IAEF;;;;;;;IAOE;IAEF;;;;;;;;;;;IAWE;IAEF
|
|
1
|
+
{"version":3,"file":"migrate-sqlite.js","sourceRoot":"","sources":["../../../src/gateway/db/migrate-sqlite.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,7 +15,6 @@ export declare class ChatRepository {
|
|
|
15
15
|
lastActiveAt: Date;
|
|
16
16
|
messageCount: number;
|
|
17
17
|
deletedAt: Date | null;
|
|
18
|
-
s3Key: string | null;
|
|
19
18
|
}[]>;
|
|
20
19
|
getSession(sessionId: string): Promise<{
|
|
21
20
|
id: string;
|
|
@@ -27,7 +26,6 @@ export declare class ChatRepository {
|
|
|
27
26
|
lastActiveAt: Date;
|
|
28
27
|
messageCount: number;
|
|
29
28
|
deletedAt: Date | null;
|
|
30
|
-
s3Key: string | null;
|
|
31
29
|
}>;
|
|
32
30
|
createSession(userId: string, title?: string, workspaceId?: string): Promise<{
|
|
33
31
|
id: `${string}-${string}-${string}-${string}-${string}`;
|
|
@@ -51,6 +49,9 @@ export declare class ChatRepository {
|
|
|
51
49
|
toolInput: string | null;
|
|
52
50
|
metadata: Record<string, unknown> | null;
|
|
53
51
|
timestamp: Date;
|
|
52
|
+
userId: string | null;
|
|
53
|
+
outcome: string | null;
|
|
54
|
+
durationMs: number | null;
|
|
54
55
|
}[]>;
|
|
55
56
|
appendMessage(msg: {
|
|
56
57
|
sessionId: string;
|
|
@@ -59,6 +60,59 @@ export declare class ChatRepository {
|
|
|
59
60
|
toolName?: string;
|
|
60
61
|
toolInput?: string;
|
|
61
62
|
metadata?: Record<string, unknown>;
|
|
63
|
+
userId?: string;
|
|
64
|
+
outcome?: "success" | "error" | "blocked";
|
|
65
|
+
durationMs?: number;
|
|
62
66
|
}): Promise<`${string}-${string}-${string}-${string}-${string}`>;
|
|
67
|
+
getMessageById(messageId: string): Promise<{
|
|
68
|
+
id: string;
|
|
69
|
+
sessionId: string;
|
|
70
|
+
role: "user" | "assistant" | "tool";
|
|
71
|
+
content: string;
|
|
72
|
+
toolName: string | null;
|
|
73
|
+
toolInput: string | null;
|
|
74
|
+
metadata: Record<string, unknown> | null;
|
|
75
|
+
timestamp: Date;
|
|
76
|
+
userId: string | null;
|
|
77
|
+
outcome: string | null;
|
|
78
|
+
durationMs: number | null;
|
|
79
|
+
}>;
|
|
80
|
+
queryAuditLogs(opts: {
|
|
81
|
+
userId?: string;
|
|
82
|
+
userName?: string;
|
|
83
|
+
toolName?: string;
|
|
84
|
+
outcome?: string;
|
|
85
|
+
startDate?: number;
|
|
86
|
+
endDate?: number;
|
|
87
|
+
cursorTs?: number;
|
|
88
|
+
cursorId?: string;
|
|
89
|
+
limit: number;
|
|
90
|
+
}): Promise<{
|
|
91
|
+
id: string;
|
|
92
|
+
userId: string | null;
|
|
93
|
+
userName: string | null;
|
|
94
|
+
toolName: string | null;
|
|
95
|
+
toolInput: string | null;
|
|
96
|
+
outcome: string | null;
|
|
97
|
+
durationMs: number | null;
|
|
98
|
+
timestamp: Date;
|
|
99
|
+
}[]>;
|
|
100
|
+
private static readonly BATCH_SIZE;
|
|
101
|
+
/**
|
|
102
|
+
* Soft-delete inactive sessions (no activity for `inactiveDays`).
|
|
103
|
+
* Only targets sessions that haven't been deleted yet.
|
|
104
|
+
*/
|
|
105
|
+
softDeleteInactiveSessions(inactiveDays: number): Promise<number>;
|
|
106
|
+
/**
|
|
107
|
+
* Hard-delete sessions that were soft-deleted more than `deletedDays` ago.
|
|
108
|
+
* Messages are cleaned up automatically via FK CASCADE.
|
|
109
|
+
*/
|
|
110
|
+
purgeDeletedSessions(deletedDays: number): Promise<number>;
|
|
111
|
+
/**
|
|
112
|
+
* Hard-delete session_stats older than `retentionDays`.
|
|
113
|
+
* Note: sessionStats.createdAt is a raw epoch number in milliseconds
|
|
114
|
+
* (no mode:"timestamp"), so we compare with numeric ms, not Date.
|
|
115
|
+
*/
|
|
116
|
+
purgeOldSessionStats(retentionDays: number): Promise<number>;
|
|
63
117
|
updateMetadata(userId: string, messageId: string, metadata: Record<string, unknown>): Promise<void>;
|
|
64
118
|
}
|