@cremini/skillpack 1.2.8 → 1.2.10
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/dist/cli.js +222 -106
- package/package.json +2 -3
package/dist/cli.js
CHANGED
|
@@ -9,6 +9,26 @@ var __export = (target, all) => {
|
|
|
9
9
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
+
// src/job-schedule.ts
|
|
13
|
+
function normalizeJobCron(cron2) {
|
|
14
|
+
if (typeof cron2 !== "string") {
|
|
15
|
+
return void 0;
|
|
16
|
+
}
|
|
17
|
+
const normalized = cron2.trim();
|
|
18
|
+
return normalized ? normalized : void 0;
|
|
19
|
+
}
|
|
20
|
+
function hasJobSchedule(jobOrCron) {
|
|
21
|
+
if (typeof jobOrCron === "string" || jobOrCron == null) {
|
|
22
|
+
return !!normalizeJobCron(jobOrCron);
|
|
23
|
+
}
|
|
24
|
+
return !!normalizeJobCron(jobOrCron.cron);
|
|
25
|
+
}
|
|
26
|
+
var init_job_schedule = __esm({
|
|
27
|
+
"src/job-schedule.ts"() {
|
|
28
|
+
"use strict";
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
12
32
|
// src/job-config.ts
|
|
13
33
|
import fs2 from "fs";
|
|
14
34
|
import path2 from "path";
|
|
@@ -27,9 +47,9 @@ function validateScheduledJobConfig(value, sourceLabel, index) {
|
|
|
27
47
|
`Invalid job config from ${sourceLabel}: "jobs[${index}].name" is required`
|
|
28
48
|
);
|
|
29
49
|
}
|
|
30
|
-
if (typeof job.cron !== "string"
|
|
50
|
+
if (job.cron !== void 0 && typeof job.cron !== "string") {
|
|
31
51
|
throw new Error(
|
|
32
|
-
`Invalid job config from ${sourceLabel}: "jobs[${index}].cron"
|
|
52
|
+
`Invalid job config from ${sourceLabel}: "jobs[${index}].cron" must be a string`
|
|
33
53
|
);
|
|
34
54
|
}
|
|
35
55
|
if (typeof job.prompt !== "string" || !job.prompt.trim()) {
|
|
@@ -87,18 +107,25 @@ function validateJobFileShape(value, sourceLabel) {
|
|
|
87
107
|
function normalizeJobFile(jobFile) {
|
|
88
108
|
return {
|
|
89
109
|
jobs: jobFile.jobs.map((job) => ({
|
|
90
|
-
|
|
91
|
-
cron: job.cron.trim(),
|
|
92
|
-
prompt: job.prompt,
|
|
93
|
-
notify: {
|
|
94
|
-
adapter: job.notify.adapter.trim(),
|
|
95
|
-
channelId: job.notify.channelId.trim()
|
|
96
|
-
},
|
|
97
|
-
...job.enabled !== void 0 ? { enabled: job.enabled } : {},
|
|
98
|
-
...job.timezone !== void 0 ? { timezone: job.timezone.trim() } : {}
|
|
110
|
+
...normalizeScheduledJobConfig(job)
|
|
99
111
|
}))
|
|
100
112
|
};
|
|
101
113
|
}
|
|
114
|
+
function normalizeScheduledJobConfig(job) {
|
|
115
|
+
const normalizedCron = normalizeJobCron(job.cron);
|
|
116
|
+
const normalizedTimezone = typeof job.timezone === "string" && job.timezone.trim() ? job.timezone.trim() : void 0;
|
|
117
|
+
return {
|
|
118
|
+
name: job.name.trim(),
|
|
119
|
+
...normalizedCron ? { cron: normalizedCron } : {},
|
|
120
|
+
prompt: job.prompt,
|
|
121
|
+
notify: {
|
|
122
|
+
adapter: job.notify.adapter.trim(),
|
|
123
|
+
channelId: job.notify.channelId.trim()
|
|
124
|
+
},
|
|
125
|
+
...normalizedCron && job.enabled !== void 0 ? { enabled: job.enabled } : {},
|
|
126
|
+
...normalizedCron && normalizedTimezone ? { timezone: normalizedTimezone } : {}
|
|
127
|
+
};
|
|
128
|
+
}
|
|
102
129
|
function loadJobFile(workDir) {
|
|
103
130
|
const filePath = getJobFilePath(workDir);
|
|
104
131
|
if (!fs2.existsSync(filePath)) {
|
|
@@ -119,6 +146,7 @@ var JOB_FILE;
|
|
|
119
146
|
var init_job_config = __esm({
|
|
120
147
|
"src/job-config.ts"() {
|
|
121
148
|
"use strict";
|
|
149
|
+
init_job_schedule();
|
|
122
150
|
JOB_FILE = "job.json";
|
|
123
151
|
}
|
|
124
152
|
});
|
|
@@ -1402,11 +1430,15 @@ function isValidTimezone(tz) {
|
|
|
1402
1430
|
function isValidJobName(name) {
|
|
1403
1431
|
return VALID_JOB_NAME.test(name) && name.length <= 64;
|
|
1404
1432
|
}
|
|
1433
|
+
function isRecurringJob(jobConfig) {
|
|
1434
|
+
return hasJobSchedule(jobConfig);
|
|
1435
|
+
}
|
|
1405
1436
|
var VALID_JOB_NAME, SchedulerAdapter;
|
|
1406
1437
|
var init_scheduler = __esm({
|
|
1407
1438
|
"src/runtime/adapters/scheduler.ts"() {
|
|
1408
1439
|
"use strict";
|
|
1409
1440
|
init_job_config();
|
|
1441
|
+
init_job_schedule();
|
|
1410
1442
|
VALID_JOB_NAME = /^[a-zA-Z0-9][a-zA-Z0-9_-]*$/;
|
|
1411
1443
|
SchedulerAdapter = class {
|
|
1412
1444
|
name = "scheduler";
|
|
@@ -1423,10 +1455,13 @@ var init_scheduler = __esm({
|
|
|
1423
1455
|
const jobConfigs = loadJobFile(this.rootDir).jobs;
|
|
1424
1456
|
let scheduledCount = 0;
|
|
1425
1457
|
let disabledCount = 0;
|
|
1458
|
+
let oneTimeCount = 0;
|
|
1426
1459
|
for (const jc of jobConfigs) {
|
|
1427
1460
|
const result = this.registerJob(jc);
|
|
1428
1461
|
if (result.registered) {
|
|
1429
|
-
if (jc
|
|
1462
|
+
if (!isRecurringJob(jc)) {
|
|
1463
|
+
oneTimeCount++;
|
|
1464
|
+
} else if (jc.enabled === false) {
|
|
1430
1465
|
disabledCount++;
|
|
1431
1466
|
} else {
|
|
1432
1467
|
scheduledCount++;
|
|
@@ -1436,6 +1471,7 @@ var init_scheduler = __esm({
|
|
|
1436
1471
|
const parts = [];
|
|
1437
1472
|
if (scheduledCount > 0) parts.push(`${scheduledCount} active`);
|
|
1438
1473
|
if (disabledCount > 0) parts.push(`${disabledCount} disabled`);
|
|
1474
|
+
if (oneTimeCount > 0) parts.push(`${oneTimeCount} one-time`);
|
|
1439
1475
|
if (parts.length > 0) {
|
|
1440
1476
|
console.log(`[SchedulerAdapter] Started with ${parts.join(", ")} job(s)`);
|
|
1441
1477
|
} else {
|
|
@@ -1450,43 +1486,43 @@ var init_scheduler = __esm({
|
|
|
1450
1486
|
* Does NOT persist – callers decide when to persist.
|
|
1451
1487
|
*/
|
|
1452
1488
|
registerJob(jobConfig) {
|
|
1453
|
-
|
|
1454
|
-
|
|
1489
|
+
const normalizedConfig = normalizeScheduledJobConfig(jobConfig);
|
|
1490
|
+
const normalizedCron = normalizeJobCron(normalizedConfig.cron);
|
|
1491
|
+
if (!isValidJobName(normalizedConfig.name)) {
|
|
1492
|
+
const msg = `[Scheduler] Invalid job name "${normalizedConfig.name}": must match ${VALID_JOB_NAME} and be \u226464 chars`;
|
|
1455
1493
|
console.error(msg);
|
|
1456
1494
|
return { registered: false, message: msg };
|
|
1457
1495
|
}
|
|
1458
|
-
if (
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1496
|
+
if (normalizedCron) {
|
|
1497
|
+
if (!cron.validate(normalizedCron)) {
|
|
1498
|
+
const msg = `[Scheduler] Invalid cron expression for job "${normalizedConfig.name}": ${normalizedCron}`;
|
|
1499
|
+
console.error(msg);
|
|
1500
|
+
return { registered: false, message: msg };
|
|
1501
|
+
}
|
|
1502
|
+
if (normalizedConfig.timezone && !isValidTimezone(normalizedConfig.timezone)) {
|
|
1503
|
+
const msg = `[Scheduler] Invalid timezone for job "${normalizedConfig.name}": ${normalizedConfig.timezone}`;
|
|
1504
|
+
console.error(msg);
|
|
1505
|
+
return { registered: false, message: msg };
|
|
1506
|
+
}
|
|
1467
1507
|
}
|
|
1468
|
-
this.removeFromMap(
|
|
1508
|
+
this.removeFromMap(normalizedConfig.name);
|
|
1469
1509
|
let task = null;
|
|
1470
|
-
if (
|
|
1471
|
-
task =
|
|
1472
|
-
|
|
1473
|
-
()
|
|
1474
|
-
void this.runJob(jobConfig);
|
|
1475
|
-
},
|
|
1476
|
-
{
|
|
1477
|
-
timezone: jobConfig.timezone
|
|
1478
|
-
}
|
|
1510
|
+
if (normalizedCron && normalizedConfig.enabled !== false) {
|
|
1511
|
+
task = this.createCronTask(normalizedConfig);
|
|
1512
|
+
console.log(
|
|
1513
|
+
`[Scheduler] Job "${normalizedConfig.name}" scheduled: ${normalizedCron}${normalizedConfig.timezone ? ` (${normalizedConfig.timezone})` : ""}`
|
|
1479
1514
|
);
|
|
1515
|
+
} else if (normalizedCron) {
|
|
1480
1516
|
console.log(
|
|
1481
|
-
`[Scheduler] Job "${
|
|
1517
|
+
`[Scheduler] Job "${normalizedConfig.name}" registered (disabled)`
|
|
1482
1518
|
);
|
|
1483
1519
|
} else {
|
|
1484
1520
|
console.log(
|
|
1485
|
-
`[Scheduler] Job "${
|
|
1521
|
+
`[Scheduler] Job "${normalizedConfig.name}" registered as one-time (manual trigger only)`
|
|
1486
1522
|
);
|
|
1487
1523
|
}
|
|
1488
|
-
this.jobs.set(
|
|
1489
|
-
config:
|
|
1524
|
+
this.jobs.set(normalizedConfig.name, {
|
|
1525
|
+
config: normalizedConfig,
|
|
1490
1526
|
task,
|
|
1491
1527
|
running: false,
|
|
1492
1528
|
notifyFailed: false
|
|
@@ -1599,10 +1635,11 @@ var init_scheduler = __esm({
|
|
|
1599
1635
|
return { success: false, message: result.message };
|
|
1600
1636
|
}
|
|
1601
1637
|
this.persistJobs();
|
|
1602
|
-
const
|
|
1638
|
+
const recurring = isRecurringJob(jobConfig);
|
|
1639
|
+
const enabled = recurring ? jobConfig.enabled !== false : true;
|
|
1603
1640
|
return {
|
|
1604
1641
|
success: true,
|
|
1605
|
-
message: enabled ? `Job "${jobConfig.name}" created and scheduled.` : `Job "${jobConfig.name}" created (disabled).`
|
|
1642
|
+
message: recurring ? enabled ? `Job "${jobConfig.name}" created and scheduled.` : `Job "${jobConfig.name}" created (disabled).` : `Job "${jobConfig.name}" created as a one-time task.`
|
|
1606
1643
|
};
|
|
1607
1644
|
}
|
|
1608
1645
|
/**
|
|
@@ -1647,17 +1684,15 @@ var init_scheduler = __esm({
|
|
|
1647
1684
|
if (!job) {
|
|
1648
1685
|
return { success: false, message: `Job "${name}" not found.` };
|
|
1649
1686
|
}
|
|
1687
|
+
if (!isRecurringJob(job.config)) {
|
|
1688
|
+
return {
|
|
1689
|
+
success: false,
|
|
1690
|
+
message: `Job "${name}" does not have a schedule and cannot be enabled or disabled.`
|
|
1691
|
+
};
|
|
1692
|
+
}
|
|
1650
1693
|
job.config.enabled = enabled;
|
|
1651
1694
|
if (enabled && !job.task) {
|
|
1652
|
-
job.task =
|
|
1653
|
-
job.config.cron,
|
|
1654
|
-
() => {
|
|
1655
|
-
void this.runJob(job.config);
|
|
1656
|
-
},
|
|
1657
|
-
{
|
|
1658
|
-
timezone: job.config.timezone
|
|
1659
|
-
}
|
|
1660
|
-
);
|
|
1695
|
+
job.task = this.createCronTask(job.config);
|
|
1661
1696
|
} else if (enabled && job.task) {
|
|
1662
1697
|
job.task.start();
|
|
1663
1698
|
} else if (!enabled && job.task) {
|
|
@@ -1703,13 +1738,13 @@ var init_scheduler = __esm({
|
|
|
1703
1738
|
for (const [, job] of this.jobs) {
|
|
1704
1739
|
result.push({
|
|
1705
1740
|
name: job.config.name,
|
|
1706
|
-
cron: job.config.cron,
|
|
1741
|
+
...job.config.cron ? { cron: job.config.cron } : {},
|
|
1707
1742
|
prompt: job.config.prompt,
|
|
1708
1743
|
notify: job.config.notify,
|
|
1709
|
-
enabled: job.config.enabled !== false,
|
|
1710
|
-
timezone: job.config.timezone,
|
|
1711
|
-
lastRunAt: job.lastRunAt,
|
|
1712
|
-
lastError: job.lastError,
|
|
1744
|
+
enabled: isRecurringJob(job.config) ? job.config.enabled !== false : true,
|
|
1745
|
+
...job.config.timezone ? { timezone: job.config.timezone } : {},
|
|
1746
|
+
...job.lastRunAt ? { lastRunAt: job.lastRunAt } : {},
|
|
1747
|
+
...job.lastError ? { lastError: job.lastError } : {},
|
|
1713
1748
|
running: job.running,
|
|
1714
1749
|
notifyFailed: job.notifyFailed
|
|
1715
1750
|
});
|
|
@@ -1749,6 +1784,21 @@ var init_scheduler = __esm({
|
|
|
1749
1784
|
this.jobs.clear();
|
|
1750
1785
|
console.log("[SchedulerAdapter] All jobs stopped.");
|
|
1751
1786
|
}
|
|
1787
|
+
createCronTask(jobConfig) {
|
|
1788
|
+
const cronExpr = normalizeJobCron(jobConfig.cron);
|
|
1789
|
+
if (!cronExpr) {
|
|
1790
|
+
throw new Error(`Job "${jobConfig.name}" does not have a valid cron expression`);
|
|
1791
|
+
}
|
|
1792
|
+
return cron.schedule(
|
|
1793
|
+
cronExpr,
|
|
1794
|
+
() => {
|
|
1795
|
+
void this.runJob(jobConfig);
|
|
1796
|
+
},
|
|
1797
|
+
{
|
|
1798
|
+
timezone: jobConfig.timezone
|
|
1799
|
+
}
|
|
1800
|
+
);
|
|
1801
|
+
}
|
|
1752
1802
|
};
|
|
1753
1803
|
}
|
|
1754
1804
|
});
|
|
@@ -2694,7 +2744,7 @@ var ResultsQueryService = class {
|
|
|
2694
2744
|
constructor(resultStore) {
|
|
2695
2745
|
this.resultStore = resultStore;
|
|
2696
2746
|
}
|
|
2697
|
-
listRecentArtifacts(options = {}) {
|
|
2747
|
+
async listRecentArtifacts(options = {}) {
|
|
2698
2748
|
return this.resultStore.listRecentArtifacts({
|
|
2699
2749
|
channelId: options.channelId,
|
|
2700
2750
|
limit: clampLimit(options.limit, 100, 500),
|
|
@@ -2865,7 +2915,7 @@ var ArtifactPersistenceService = class {
|
|
|
2865
2915
|
this.snapshotService = snapshotService;
|
|
2866
2916
|
this.resultStore = resultStore;
|
|
2867
2917
|
}
|
|
2868
|
-
saveArtifacts(input) {
|
|
2918
|
+
async saveArtifacts(input) {
|
|
2869
2919
|
const declaredAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
2870
2920
|
const snapshots = this.snapshotService.createSnapshots(
|
|
2871
2921
|
input.runId,
|
|
@@ -2873,7 +2923,7 @@ var ArtifactPersistenceService = class {
|
|
|
2873
2923
|
declaredAt
|
|
2874
2924
|
);
|
|
2875
2925
|
try {
|
|
2876
|
-
this.resultStore.insertArtifacts({
|
|
2926
|
+
await this.resultStore.insertArtifacts({
|
|
2877
2927
|
runId: input.runId,
|
|
2878
2928
|
channelId: input.channelId,
|
|
2879
2929
|
artifacts: snapshots
|
|
@@ -2892,7 +2942,7 @@ var ArtifactPersistenceService = class {
|
|
|
2892
2942
|
import fs10 from "fs";
|
|
2893
2943
|
import path10 from "path";
|
|
2894
2944
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
2895
|
-
import
|
|
2945
|
+
import sqlite3 from "sqlite3";
|
|
2896
2946
|
function mapArtifactRow(row) {
|
|
2897
2947
|
return {
|
|
2898
2948
|
artifactId: row.artifact_id,
|
|
@@ -2909,16 +2959,17 @@ function mapArtifactRow(row) {
|
|
|
2909
2959
|
};
|
|
2910
2960
|
}
|
|
2911
2961
|
var ResultStore = class {
|
|
2912
|
-
db;
|
|
2962
|
+
db = null;
|
|
2963
|
+
ready;
|
|
2913
2964
|
constructor(rootDir) {
|
|
2914
2965
|
const dataDir = path10.resolve(rootDir, "data");
|
|
2915
2966
|
fs10.mkdirSync(dataDir, { recursive: true });
|
|
2916
|
-
this.
|
|
2917
|
-
this.db.pragma("journal_mode = WAL");
|
|
2918
|
-
this.initialize();
|
|
2967
|
+
this.ready = this.initialize(path10.join(dataDir, "result-v2.db"));
|
|
2919
2968
|
}
|
|
2920
|
-
initialize() {
|
|
2921
|
-
this.db
|
|
2969
|
+
async initialize(databasePath) {
|
|
2970
|
+
this.db = await openDatabase(databasePath);
|
|
2971
|
+
await this.exec("PRAGMA journal_mode = WAL");
|
|
2972
|
+
await this.exec(`
|
|
2922
2973
|
CREATE TABLE IF NOT EXISTS artifacts (
|
|
2923
2974
|
artifact_id TEXT PRIMARY KEY,
|
|
2924
2975
|
run_id TEXT NOT NULL,
|
|
@@ -2937,11 +2988,12 @@ var ResultStore = class {
|
|
|
2937
2988
|
ON artifacts(channel_id, declared_at DESC);
|
|
2938
2989
|
`);
|
|
2939
2990
|
}
|
|
2940
|
-
insertArtifacts(input) {
|
|
2991
|
+
async insertArtifacts(input) {
|
|
2992
|
+
await this.ready;
|
|
2941
2993
|
if (input.artifacts.length === 0) {
|
|
2942
2994
|
return;
|
|
2943
2995
|
}
|
|
2944
|
-
const insertArtifact =
|
|
2996
|
+
const insertArtifact = `
|
|
2945
2997
|
INSERT INTO artifacts (
|
|
2946
2998
|
artifact_id,
|
|
2947
2999
|
run_id,
|
|
@@ -2955,39 +3007,44 @@ var ResultStore = class {
|
|
|
2955
3007
|
is_primary,
|
|
2956
3008
|
declared_at
|
|
2957
3009
|
) VALUES (
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
3010
|
+
?,
|
|
3011
|
+
?,
|
|
3012
|
+
?,
|
|
3013
|
+
?,
|
|
3014
|
+
?,
|
|
3015
|
+
?,
|
|
3016
|
+
?,
|
|
3017
|
+
?,
|
|
3018
|
+
?,
|
|
3019
|
+
?,
|
|
3020
|
+
?
|
|
2969
3021
|
)
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
3022
|
+
`;
|
|
3023
|
+
await this.exec("BEGIN");
|
|
3024
|
+
try {
|
|
3025
|
+
for (const artifact of input.artifacts) {
|
|
3026
|
+
await this.run(insertArtifact, [
|
|
3027
|
+
randomUUID2(),
|
|
3028
|
+
input.runId,
|
|
3029
|
+
input.channelId,
|
|
3030
|
+
artifact.originalPath,
|
|
3031
|
+
artifact.snapshotPath,
|
|
3032
|
+
artifact.fileName,
|
|
3033
|
+
artifact.mimeType ?? null,
|
|
3034
|
+
artifact.sizeBytes,
|
|
3035
|
+
artifact.title ?? null,
|
|
3036
|
+
artifact.isPrimary ? 1 : 0,
|
|
3037
|
+
artifact.declaredAt
|
|
3038
|
+
]);
|
|
3039
|
+
}
|
|
3040
|
+
await this.exec("COMMIT");
|
|
3041
|
+
} catch (error) {
|
|
3042
|
+
await this.rollback();
|
|
3043
|
+
throw error;
|
|
3044
|
+
}
|
|
2989
3045
|
}
|
|
2990
|
-
listRecentArtifacts(options = {}) {
|
|
3046
|
+
async listRecentArtifacts(options = {}) {
|
|
3047
|
+
await this.ready;
|
|
2991
3048
|
const limit = options.limit ?? 100;
|
|
2992
3049
|
const offset = options.offset ?? 0;
|
|
2993
3050
|
const conditions = [];
|
|
@@ -2997,16 +3054,75 @@ var ResultStore = class {
|
|
|
2997
3054
|
params.push(options.channelId);
|
|
2998
3055
|
}
|
|
2999
3056
|
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
3000
|
-
const rows = this.
|
|
3057
|
+
const rows = await this.all(`
|
|
3001
3058
|
SELECT *
|
|
3002
3059
|
FROM artifacts
|
|
3003
3060
|
${whereClause}
|
|
3004
3061
|
ORDER BY declared_at DESC, rowid DESC
|
|
3005
3062
|
LIMIT ? OFFSET ?
|
|
3006
|
-
|
|
3063
|
+
`, [...params, limit, offset]);
|
|
3007
3064
|
return rows.map(mapArtifactRow);
|
|
3008
3065
|
}
|
|
3066
|
+
getDatabase() {
|
|
3067
|
+
if (!this.db) {
|
|
3068
|
+
throw new Error("Result store database is not ready");
|
|
3069
|
+
}
|
|
3070
|
+
return this.db;
|
|
3071
|
+
}
|
|
3072
|
+
exec(sql) {
|
|
3073
|
+
const db = this.getDatabase();
|
|
3074
|
+
return new Promise((resolve, reject) => {
|
|
3075
|
+
db.exec(sql, (error) => {
|
|
3076
|
+
if (error) {
|
|
3077
|
+
reject(error);
|
|
3078
|
+
return;
|
|
3079
|
+
}
|
|
3080
|
+
resolve();
|
|
3081
|
+
});
|
|
3082
|
+
});
|
|
3083
|
+
}
|
|
3084
|
+
run(sql, params = []) {
|
|
3085
|
+
const db = this.getDatabase();
|
|
3086
|
+
return new Promise((resolve, reject) => {
|
|
3087
|
+
db.run(sql, params, (error) => {
|
|
3088
|
+
if (error) {
|
|
3089
|
+
reject(error);
|
|
3090
|
+
return;
|
|
3091
|
+
}
|
|
3092
|
+
resolve();
|
|
3093
|
+
});
|
|
3094
|
+
});
|
|
3095
|
+
}
|
|
3096
|
+
all(sql, params = []) {
|
|
3097
|
+
const db = this.getDatabase();
|
|
3098
|
+
return new Promise((resolve, reject) => {
|
|
3099
|
+
db.all(sql, params, (error, rows) => {
|
|
3100
|
+
if (error) {
|
|
3101
|
+
reject(error);
|
|
3102
|
+
return;
|
|
3103
|
+
}
|
|
3104
|
+
resolve(rows);
|
|
3105
|
+
});
|
|
3106
|
+
});
|
|
3107
|
+
}
|
|
3108
|
+
async rollback() {
|
|
3109
|
+
try {
|
|
3110
|
+
await this.exec("ROLLBACK");
|
|
3111
|
+
} catch {
|
|
3112
|
+
}
|
|
3113
|
+
}
|
|
3009
3114
|
};
|
|
3115
|
+
function openDatabase(databasePath) {
|
|
3116
|
+
return new Promise((resolve, reject) => {
|
|
3117
|
+
const db = new sqlite3.Database(databasePath, (error) => {
|
|
3118
|
+
if (error) {
|
|
3119
|
+
reject(error);
|
|
3120
|
+
return;
|
|
3121
|
+
}
|
|
3122
|
+
resolve(db);
|
|
3123
|
+
});
|
|
3124
|
+
});
|
|
3125
|
+
}
|
|
3010
3126
|
|
|
3011
3127
|
// src/runtime/artifacts/save-artifacts-tool.ts
|
|
3012
3128
|
import { Type } from "@sinclair/typebox";
|
|
@@ -4495,12 +4611,12 @@ var WebAdapter = class {
|
|
|
4495
4611
|
)
|
|
4496
4612
|
);
|
|
4497
4613
|
});
|
|
4498
|
-
app.get("/api/results/artifacts", (req, res) => {
|
|
4614
|
+
app.get("/api/results/artifacts", async (req, res) => {
|
|
4499
4615
|
if (!resultsQueryService) {
|
|
4500
4616
|
res.status(503).json({ error: "Results query service is not available" });
|
|
4501
4617
|
return;
|
|
4502
4618
|
}
|
|
4503
|
-
res.json(resultsQueryService.listRecentArtifacts({
|
|
4619
|
+
res.json(await resultsQueryService.listRecentArtifacts({
|
|
4504
4620
|
channelId: typeof req.query.channelId === "string" ? req.query.channelId : void 0,
|
|
4505
4621
|
limit: parsePositiveInt(req.query.limit, 100),
|
|
4506
4622
|
offset: parsePositiveInt(req.query.offset, 0)
|
|
@@ -4549,20 +4665,20 @@ var WebAdapter = class {
|
|
|
4549
4665
|
return;
|
|
4550
4666
|
}
|
|
4551
4667
|
const { name, cron: cronExpr, prompt, notify, enabled, timezone } = req.body;
|
|
4552
|
-
if (!name || !
|
|
4668
|
+
if (!name || !prompt || !notify?.adapter || !notify?.channelId) {
|
|
4553
4669
|
res.status(400).json({
|
|
4554
4670
|
success: false,
|
|
4555
|
-
message: "Required fields: name,
|
|
4671
|
+
message: "Required fields: name, prompt, notify.adapter, notify.channelId"
|
|
4556
4672
|
});
|
|
4557
4673
|
return;
|
|
4558
4674
|
}
|
|
4559
4675
|
const result = scheduler.addJob({
|
|
4560
4676
|
name,
|
|
4561
|
-
cron: cronExpr,
|
|
4677
|
+
...typeof cronExpr === "string" ? { cron: cronExpr } : {},
|
|
4562
4678
|
prompt,
|
|
4563
4679
|
notify,
|
|
4564
|
-
enabled
|
|
4565
|
-
timezone
|
|
4680
|
+
...typeof enabled === "boolean" ? { enabled } : {},
|
|
4681
|
+
...typeof timezone === "string" ? { timezone } : {}
|
|
4566
4682
|
});
|
|
4567
4683
|
res.json(result);
|
|
4568
4684
|
});
|
|
@@ -4819,7 +4935,7 @@ var IpcAdapter = class {
|
|
|
4819
4935
|
this.replyError(request.id, "Results query service is not available");
|
|
4820
4936
|
return;
|
|
4821
4937
|
}
|
|
4822
|
-
this.reply(request.id, this.resultsQueryService.listRecentArtifacts({
|
|
4938
|
+
this.reply(request.id, await this.resultsQueryService.listRecentArtifacts({
|
|
4823
4939
|
channelId: request.channelId,
|
|
4824
4940
|
limit: request.limit,
|
|
4825
4941
|
offset: request.offset
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cremini/skillpack",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.10",
|
|
4
4
|
"description": "Pack AI Skills into Local Agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -49,18 +49,17 @@
|
|
|
49
49
|
"@slack/bolt": "^4.6.0",
|
|
50
50
|
"ajv": "^8.17.1",
|
|
51
51
|
"archiver": "^7.0.1",
|
|
52
|
-
"better-sqlite3": "^11.10.0",
|
|
53
52
|
"chalk": "^5.6.2",
|
|
54
53
|
"commander": "^14.0.3",
|
|
55
54
|
"express": "^5.1.0",
|
|
56
55
|
"inquirer": "^13.3.0",
|
|
57
56
|
"node-cron": "^4.2.1",
|
|
58
57
|
"node-telegram-bot-api": "^0.66.0",
|
|
58
|
+
"sqlite3": "^5.1.7",
|
|
59
59
|
"ws": "^8.19.0"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@types/archiver": "^7.0.0",
|
|
63
|
-
"@types/better-sqlite3": "^7.6.13",
|
|
64
63
|
"@types/express": "^5.0.0",
|
|
65
64
|
"@types/inquirer": "^9.0.9",
|
|
66
65
|
"@types/node": "^25.5.0",
|