@goodandready/dsh-cron 0.3.16 → 0.3.18
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/lib/client.js +807 -787
- package/lib/cron-tool.js +4 -0
- package/lib/http-utils.js +7 -1
- package/lib/runner.js +25 -9
- package/package.json +1 -1
package/lib/cron-tool.js
CHANGED
|
@@ -152,6 +152,10 @@ export const cronToolParameters = {
|
|
|
152
152
|
enum: ['default', 'read-only', 'workspace-write', 'full'],
|
|
153
153
|
description: 'Permission preset applied to the task session (only used for agent session tasks: llm, skill, workflow)',
|
|
154
154
|
},
|
|
155
|
+
sessionTitle: {
|
|
156
|
+
type: 'string',
|
|
157
|
+
description: 'Custom session title template for isolated agent runs (supports {{date}} placeholder, e.g. "{{date}} [Daily] Report")',
|
|
158
|
+
},
|
|
155
159
|
requireApproval: {
|
|
156
160
|
type: 'boolean',
|
|
157
161
|
description: 'Require explicit human approval before execution (#318)',
|
package/lib/http-utils.js
CHANGED
|
@@ -78,10 +78,16 @@ export function parseJsonBody(req, limit = MAX_BODY_BYTES) {
|
|
|
78
78
|
|
|
79
79
|
/**
|
|
80
80
|
* Safe helper to get the DSH connection service from context or request (#357).
|
|
81
|
+
* Defensively degrades when context is a Cordis proxy throwing without inject (#366, GH #13).
|
|
81
82
|
*/
|
|
82
83
|
export function getConnection(ctx) {
|
|
83
84
|
if (!ctx) return null;
|
|
84
|
-
|
|
85
|
+
try {
|
|
86
|
+
return Reflect.get(ctx, 'connection') || ctx.connection || null;
|
|
87
|
+
} catch (_err) {
|
|
88
|
+
// Degrade gracefully if context is a Cordis proxy throwing without inject (GH #13)
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
85
91
|
}
|
|
86
92
|
|
|
87
93
|
export function getDshConnection(req, options = {}) {
|
package/lib/runner.js
CHANGED
|
@@ -38,15 +38,19 @@ export {
|
|
|
38
38
|
* Resolves the effective target session ID taking into account rotation policies (#143).
|
|
39
39
|
* Supports {{date}} interpolation, 'daily' rotation (adds -YYYY-MM-DD), and 'weekly' rotation (-YYYY-Www).
|
|
40
40
|
*/
|
|
41
|
+
export function formatDateYmd(date = new Date()) {
|
|
42
|
+
const yyyy = date.getFullYear();
|
|
43
|
+
const mm = String(date.getMonth() + 1).padStart(2, '0');
|
|
44
|
+
const dd = String(date.getDate()).padStart(2, '0');
|
|
45
|
+
return `${yyyy}-${mm}-${dd}`;
|
|
46
|
+
}
|
|
47
|
+
|
|
41
48
|
export function resolveTargetSessionId(targetSessionId, resetPolicy = 'never', date = new Date()) {
|
|
42
49
|
if (!targetSessionId || typeof targetSessionId !== 'string') return null;
|
|
43
50
|
let baseId = targetSessionId.trim();
|
|
44
51
|
if (!baseId) return null;
|
|
45
52
|
|
|
46
|
-
const
|
|
47
|
-
const mm = String(date.getMonth() + 1).padStart(2, '0');
|
|
48
|
-
const dd = String(date.getDate()).padStart(2, '0');
|
|
49
|
-
const yyyymmdd = `${yyyy}-${mm}-${dd}`;
|
|
53
|
+
const yyyymmdd = formatDateYmd(date);
|
|
50
54
|
|
|
51
55
|
if (baseId.includes('{{date}}')) {
|
|
52
56
|
return baseId.replaceAll('{{date}}', yyyymmdd);
|
|
@@ -282,8 +286,11 @@ export class SessionRunner {
|
|
|
282
286
|
/** Legacy session service path; falls back to the bare report. */
|
|
283
287
|
async _runLegacySession(task) {
|
|
284
288
|
try {
|
|
289
|
+
const ymd = formatDateYmd();
|
|
290
|
+
const explicit = task.sessionTitle ? String(task.sessionTitle).trim().replaceAll('{{date}}', ymd) : '';
|
|
291
|
+
const legacyTitle = explicit || `[Cron] ${ymd} ${task.title}`;
|
|
285
292
|
const session = await this.ctx.session.create({
|
|
286
|
-
title:
|
|
293
|
+
title: legacyTitle,
|
|
287
294
|
ephemeral: task.delivery === 'isolated',
|
|
288
295
|
});
|
|
289
296
|
if (session && typeof session.send === 'function') {
|
|
@@ -659,13 +666,22 @@ export class SessionRunner {
|
|
|
659
666
|
|
|
660
667
|
const explicitTitle = task.sessionTitle ? String(task.sessionTitle).trim() : '';
|
|
661
668
|
const taskTitle = task.title ? String(task.title).trim() : '';
|
|
662
|
-
const
|
|
669
|
+
const ymd = formatDateYmd();
|
|
670
|
+
|
|
671
|
+
let label = '';
|
|
672
|
+
if (explicitTitle) {
|
|
673
|
+
label = explicitTitle.replaceAll('{{date}}', ymd);
|
|
674
|
+
} else if (taskTitle.startsWith('[')) {
|
|
675
|
+
label = taskTitle.replaceAll('{{date}}', ymd);
|
|
676
|
+
} else if (taskTitle) {
|
|
677
|
+
label = `${ymd} ${taskTitle}`;
|
|
678
|
+
}
|
|
663
679
|
|
|
664
|
-
if (!label) return;
|
|
680
|
+
if (!label.trim()) return;
|
|
665
681
|
if (isResumed && !explicitTitle) return;
|
|
666
682
|
|
|
667
|
-
sessionTitle.rename(session, label);
|
|
668
|
-
logger.info(`[dsh-cron] assigned session title "${label}" for session ${session.id}`);
|
|
683
|
+
sessionTitle.rename(session, label.trim());
|
|
684
|
+
logger.info(`[dsh-cron] assigned session title "${label.trim()}" for session ${session.id}`);
|
|
669
685
|
} catch (titleErr) {
|
|
670
686
|
logger.debug?.(`[dsh-cron] could not rename session ${session?.id}: ${titleErr.message}`);
|
|
671
687
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodandready/dsh-cron",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.18",
|
|
4
4
|
"description": "Background automation runner for DSH: isolated agent runs, script/HTTP/SSH/Docker runtimes, cost guard, notifications, heartbeats.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|