@agi-fans/dsh-tui 0.20.0 → 0.22.0
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/CHANGELOG.md +249 -3
- package/lib/chrome/box.d.ts +47 -16
- package/lib/chrome/box.js +172 -130
- package/lib/chrome/box.js.map +1 -1
- package/lib/chrome/code-highlight.d.ts +15 -0
- package/lib/chrome/code-highlight.js +60 -4
- package/lib/chrome/code-highlight.js.map +1 -1
- package/lib/chrome/command-output.d.ts +29 -2
- package/lib/chrome/command-output.js +100 -4
- package/lib/chrome/command-output.js.map +1 -1
- package/lib/chrome/main-screen-renderer.d.ts +18 -0
- package/lib/chrome/main-screen-renderer.js +58 -5
- package/lib/chrome/main-screen-renderer.js.map +1 -1
- package/lib/chrome/markdown.js +30 -10
- package/lib/chrome/markdown.js.map +1 -1
- package/lib/chrome/relative-time.d.ts +17 -0
- package/lib/chrome/relative-time.js +36 -0
- package/lib/chrome/relative-time.js.map +1 -1
- package/lib/chrome/renderer.d.ts +9 -0
- package/lib/chrome/renderer.js +1 -1
- package/lib/chrome/renderer.js.map +1 -1
- package/lib/chrome/secret-mask.d.ts +35 -0
- package/lib/chrome/secret-mask.js +180 -0
- package/lib/chrome/secret-mask.js.map +1 -0
- package/lib/chrome/status-config.d.ts +161 -51
- package/lib/chrome/status-config.js +237 -126
- package/lib/chrome/status-config.js.map +1 -1
- package/lib/chrome/status-line.d.ts +3 -2
- package/lib/chrome/status-line.js +105 -63
- package/lib/chrome/status-line.js.map +1 -1
- package/lib/chrome/terminal-colors.d.ts +85 -0
- package/lib/chrome/terminal-colors.js +230 -0
- package/lib/chrome/terminal-colors.js.map +1 -0
- package/lib/chrome/terminal-images.d.ts +9 -1
- package/lib/chrome/terminal-images.js +27 -4
- package/lib/chrome/terminal-images.js.map +1 -1
- package/lib/chrome/theme.d.ts +32 -9
- package/lib/chrome/theme.js +616 -520
- package/lib/chrome/theme.js.map +1 -1
- package/lib/chrome/tool-args.d.ts +1 -1
- package/lib/chrome/tool-args.js +3 -1
- package/lib/chrome/tool-args.js.map +1 -1
- package/lib/chrome/tool-renderers.d.ts +2 -0
- package/lib/chrome/tool-renderers.js +69 -3
- package/lib/chrome/tool-renderers.js.map +1 -1
- package/lib/chrome/tools-list.d.ts +1 -4
- package/lib/chrome/tools-list.js +1 -41
- package/lib/chrome/tools-list.js.map +1 -1
- package/lib/chrome/welcome-tips.d.ts +20 -7
- package/lib/chrome/welcome-tips.js +22 -41
- package/lib/chrome/welcome-tips.js.map +1 -1
- package/lib/commands/auth-ids.d.ts +25 -0
- package/lib/commands/auth-ids.js +27 -0
- package/lib/commands/auth-ids.js.map +1 -0
- package/lib/commands/auth-input.d.ts +34 -0
- package/lib/commands/auth-input.js +96 -0
- package/lib/commands/auth-input.js.map +1 -0
- package/lib/commands/auth-providers.d.ts +39 -0
- package/lib/commands/auth-providers.js +125 -0
- package/lib/commands/auth-providers.js.map +1 -0
- package/lib/commands/auth.d.ts +16 -22
- package/lib/commands/auth.js +346 -299
- package/lib/commands/auth.js.map +1 -1
- package/lib/commands/btw.d.ts +27 -0
- package/lib/commands/btw.js +59 -0
- package/lib/commands/btw.js.map +1 -0
- package/lib/commands/diff.js +30 -5
- package/lib/commands/diff.js.map +1 -1
- package/lib/commands/export.d.ts +1 -1
- package/lib/commands/export.js +5 -3
- package/lib/commands/export.js.map +1 -1
- package/lib/commands/files.d.ts +17 -1
- package/lib/commands/files.js +69 -61
- package/lib/commands/files.js.map +1 -1
- package/lib/commands/integrations.js +18 -6
- package/lib/commands/integrations.js.map +1 -1
- package/lib/commands/jobs.d.ts +19 -4
- package/lib/commands/jobs.js +50 -7
- package/lib/commands/jobs.js.map +1 -1
- package/lib/commands/model.js +109 -76
- package/lib/commands/model.js.map +1 -1
- package/lib/commands/permission.js +46 -13
- package/lib/commands/permission.js.map +1 -1
- package/lib/commands/plugins.js +196 -42
- package/lib/commands/plugins.js.map +1 -1
- package/lib/commands/schedule.d.ts +29 -0
- package/lib/commands/schedule.js +228 -0
- package/lib/commands/schedule.js.map +1 -0
- package/lib/commands/session-configuration.d.ts +1 -1
- package/lib/commands/session-configuration.js +29 -28
- package/lib/commands/session-configuration.js.map +1 -1
- package/lib/commands/session.js +75 -80
- package/lib/commands/session.js.map +1 -1
- package/lib/commands/terminal.d.ts +24 -4
- package/lib/commands/terminal.js +38 -94
- package/lib/commands/terminal.js.map +1 -1
- package/lib/commands/trajectory.js +4 -1
- package/lib/commands/trajectory.js.map +1 -1
- package/lib/definition.d.ts +150 -11
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/input/actions.d.ts +51 -0
- package/lib/input/actions.js +120 -0
- package/lib/input/actions.js.map +1 -0
- package/lib/input/editor-discovery.js +2 -2
- package/lib/input/editor-discovery.js.map +1 -1
- package/lib/input/editor.d.ts +0 -10
- package/lib/input/editor.js +11 -9
- package/lib/input/editor.js.map +1 -1
- package/lib/input/image-paste.d.ts +19 -1
- package/lib/input/image-paste.js +82 -1
- package/lib/input/image-paste.js.map +1 -1
- package/lib/input/keybindings-config.d.ts +15 -4
- package/lib/input/keybindings-config.js +57 -35
- package/lib/input/keybindings-config.js.map +1 -1
- package/lib/input/keys.d.ts +18 -0
- package/lib/input/keys.js +48 -3
- package/lib/input/keys.js.map +1 -1
- package/lib/input/wheel-scroll.d.ts +46 -0
- package/lib/input/wheel-scroll.js +69 -0
- package/lib/input/wheel-scroll.js.map +1 -0
- package/lib/prompt-intents.d.ts +182 -0
- package/lib/prompt-intents.js +127 -0
- package/lib/prompt-intents.js.map +1 -0
- package/lib/runtime/agent-profile.d.ts +5 -0
- package/lib/runtime/agent-profile.js +12 -0
- package/lib/runtime/agent-profile.js.map +1 -1
- package/lib/runtime/approval-rules.d.ts +59 -0
- package/lib/runtime/approval-rules.js +179 -0
- package/lib/runtime/approval-rules.js.map +1 -0
- package/lib/runtime/btw-policy.d.ts +7 -0
- package/lib/runtime/btw-policy.js +18 -0
- package/lib/runtime/btw-policy.js.map +1 -0
- package/lib/runtime/btw.d.ts +47 -0
- package/lib/runtime/btw.js +200 -0
- package/lib/runtime/btw.js.map +1 -0
- package/lib/runtime/cancellable.d.ts +75 -0
- package/lib/runtime/cancellable.js +76 -0
- package/lib/runtime/cancellable.js.map +1 -0
- package/lib/runtime/composer-images.js +5 -4
- package/lib/runtime/composer-images.js.map +1 -1
- package/lib/runtime/composer-shell.d.ts +30 -0
- package/lib/runtime/composer-shell.js +150 -0
- package/lib/runtime/composer-shell.js.map +1 -0
- package/lib/runtime/file-recovery-local.d.ts +73 -0
- package/lib/runtime/file-recovery-local.js +351 -0
- package/lib/runtime/file-recovery-local.js.map +1 -0
- package/lib/runtime/file-recovery-recording.d.ts +23 -0
- package/lib/runtime/file-recovery-recording.js +131 -0
- package/lib/runtime/file-recovery-recording.js.map +1 -0
- package/lib/runtime/file-recovery-review.d.ts +3 -0
- package/lib/runtime/file-recovery-review.js +130 -0
- package/lib/runtime/file-recovery-review.js.map +1 -0
- package/lib/runtime/file-recovery-store.d.ts +83 -0
- package/lib/runtime/file-recovery-store.js +329 -0
- package/lib/runtime/file-recovery-store.js.map +1 -0
- package/lib/runtime/file-recovery-worker.d.ts +22 -0
- package/lib/runtime/file-recovery-worker.js +153 -0
- package/lib/runtime/file-recovery-worker.js.map +1 -0
- package/lib/runtime/file-review.d.ts +6 -3
- package/lib/runtime/file-review.js +44 -7
- package/lib/runtime/file-review.js.map +1 -1
- package/lib/runtime/herdr-agent.d.ts +4 -13
- package/lib/runtime/herdr-agent.js +19 -63
- package/lib/runtime/herdr-agent.js.map +1 -1
- package/lib/runtime/plain-tui.d.ts +2 -0
- package/lib/runtime/plain-tui.js +7 -1
- package/lib/runtime/plain-tui.js.map +1 -1
- package/lib/runtime/plugin-settings.d.ts +25 -2
- package/lib/runtime/plugin-settings.js +329 -31
- package/lib/runtime/plugin-settings.js.map +1 -1
- package/lib/runtime/provider-local.d.ts +81 -24
- package/lib/runtime/provider-local.js +1807 -608
- package/lib/runtime/provider-local.js.map +1 -1
- package/lib/runtime/runner.js +52 -12
- package/lib/runtime/runner.js.map +1 -1
- package/lib/runtime/session-archive.d.ts +6 -0
- package/lib/runtime/session-archive.js +129 -3
- package/lib/runtime/session-archive.js.map +1 -1
- package/lib/runtime/session-runtime.js +1 -1
- package/lib/runtime/session-runtime.js.map +1 -1
- package/lib/runtime/settings-preferences.d.ts +5 -0
- package/lib/runtime/settings-preferences.js +34 -0
- package/lib/runtime/settings-preferences.js.map +1 -0
- package/lib/runtime/startup-notices.js +2 -0
- package/lib/runtime/startup-notices.js.map +1 -1
- package/lib/runtime/terminal-modes.d.ts +47 -0
- package/lib/runtime/terminal-modes.js +86 -0
- package/lib/runtime/terminal-modes.js.map +1 -0
- package/lib/runtime/terminal-notifications.d.ts +3 -5
- package/lib/runtime/terminal-notifications.js +4 -8
- package/lib/runtime/terminal-notifications.js.map +1 -1
- package/lib/runtime/terminal-probe.d.ts +36 -0
- package/lib/runtime/terminal-probe.js +37 -0
- package/lib/runtime/terminal-probe.js.map +1 -0
- package/lib/runtime/terminal-session.d.ts +57 -0
- package/lib/runtime/terminal-session.js +164 -0
- package/lib/runtime/terminal-session.js.map +1 -0
- package/lib/runtime/terminal-state.d.ts +29 -0
- package/lib/runtime/terminal-state.js +62 -0
- package/lib/runtime/terminal-state.js.map +1 -0
- package/lib/runtime/tool-presentation.js +50 -14
- package/lib/runtime/tool-presentation.js.map +1 -1
- package/lib/session/external-agents.d.ts +5 -0
- package/lib/session/external-agents.js +27 -0
- package/lib/session/external-agents.js.map +1 -0
- package/lib/session/feature-toggles.d.ts +1 -1
- package/lib/session/feature-toggles.js +1 -1
- package/lib/session/interaction-adapter.d.ts +1 -6
- package/lib/session/interaction-adapter.js +95 -18
- package/lib/session/interaction-adapter.js.map +1 -1
- package/lib/session/message-queue.js +1 -1
- package/lib/session/message-queue.js.map +1 -1
- package/lib/session/model-readiness.d.ts +16 -0
- package/lib/session/model-readiness.js +43 -0
- package/lib/session/model-readiness.js.map +1 -0
- package/lib/session/package-metadata.d.ts +8 -0
- package/lib/session/package-metadata.js +8 -0
- package/lib/session/package-metadata.js.map +1 -1
- package/lib/session/project-context.d.ts +5 -0
- package/lib/session/project-context.js +36 -0
- package/lib/session/project-context.js.map +1 -1
- package/lib/session/session-controller.d.ts +10 -13
- package/lib/session/session-controller.js +183 -98
- package/lib/session/session-controller.js.map +1 -1
- package/lib/session/session-library.js +2 -0
- package/lib/session/session-library.js.map +1 -1
- package/lib/session/session-tree.d.ts +3 -0
- package/lib/session/session-tree.js +3 -1
- package/lib/session/session-tree.js.map +1 -1
- package/lib/session/subagent-roster.d.ts +2 -1
- package/lib/session/subagent-roster.js +24 -3
- package/lib/session/subagent-roster.js.map +1 -1
- package/lib/session/subagent-tracker.d.ts +6 -2
- package/lib/session/subagent-tracker.js +49 -2
- package/lib/session/subagent-tracker.js.map +1 -1
- package/lib/session/tui-settings.d.ts +47 -13
- package/lib/session/tui-settings.js +76 -34
- package/lib/session/tui-settings.js.map +1 -1
- package/lib/session/working-directory.d.ts +4 -0
- package/lib/session/working-directory.js +4 -0
- package/lib/session/working-directory.js.map +1 -0
- package/lib/session/worktrees.d.ts +13 -0
- package/lib/session/worktrees.js +49 -0
- package/lib/session/worktrees.js.map +1 -0
- package/lib/views/approval-rule.d.ts +3 -0
- package/lib/views/approval-rule.js +4 -0
- package/lib/views/approval-rule.js.map +1 -0
- package/lib/views/at-complete.d.ts +8 -0
- package/lib/views/at-complete.js +64 -2
- package/lib/views/at-complete.js.map +1 -1
- package/lib/views/autocomplete.d.ts +22 -2
- package/lib/views/autocomplete.js +70 -40
- package/lib/views/autocomplete.js.map +1 -1
- package/lib/views/copy-targets.d.ts +13 -14
- package/lib/views/copy-targets.js +42 -54
- package/lib/views/copy-targets.js.map +1 -1
- package/lib/views/document-reader.js +18 -5
- package/lib/views/document-reader.js.map +1 -1
- package/lib/views/event-views.d.ts +1 -1
- package/lib/views/event-views.js +60 -6
- package/lib/views/event-views.js.map +1 -1
- package/lib/views/file-actions.d.ts +12 -0
- package/lib/views/file-actions.js +72 -0
- package/lib/views/file-actions.js.map +1 -0
- package/lib/views/history-search.js +15 -21
- package/lib/views/history-search.js.map +1 -1
- package/lib/views/hotkeys.d.ts +8 -1
- package/lib/views/hotkeys.js +53 -26
- package/lib/views/hotkeys.js.map +1 -1
- package/lib/views/list-navigation.d.ts +62 -0
- package/lib/views/list-navigation.js +73 -0
- package/lib/views/list-navigation.js.map +1 -0
- package/lib/views/list-view.d.ts +99 -0
- package/lib/views/list-view.js +165 -0
- package/lib/views/list-view.js.map +1 -0
- package/lib/views/prompt-selector.d.ts +34 -4
- package/lib/views/prompt-selector.js +270 -134
- package/lib/views/prompt-selector.js.map +1 -1
- package/lib/views/session-files.d.ts +1 -2
- package/lib/views/session-files.js +1 -11
- package/lib/views/session-files.js.map +1 -1
- package/lib/views/settings-list.d.ts +51 -10
- package/lib/views/settings-list.js +267 -315
- package/lib/views/settings-list.js.map +1 -1
- package/lib/views/trajectory-timeline.d.ts +72 -0
- package/lib/views/trajectory-timeline.js +133 -0
- package/lib/views/trajectory-timeline.js.map +1 -0
- package/lib/views/trajectory.d.ts +15 -4
- package/lib/views/trajectory.js +557 -123
- package/lib/views/trajectory.js.map +1 -1
- package/lib/views/transcript-export.js +9 -0
- package/lib/views/transcript-export.js.map +1 -1
- package/lib/views/transcript-render.d.ts +97 -25
- package/lib/views/transcript-render.js +542 -170
- package/lib/views/transcript-render.js.map +1 -1
- package/lib/views/transcript-search.d.ts +39 -6
- package/lib/views/transcript-search.js +46 -11
- package/lib/views/transcript-search.js.map +1 -1
- package/lib/views/transcript-types.d.ts +63 -5
- package/lib/views/transcript-types.js +23 -11
- package/lib/views/transcript-types.js.map +1 -1
- package/package.json +95 -65
- package/lib/commands/loop.d.ts +0 -52
- package/lib/commands/loop.js +0 -307
- package/lib/commands/loop.js.map +0 -1
- package/lib/commands/steer.d.ts +0 -5
- package/lib/commands/steer.js +0 -24
- package/lib/commands/steer.js.map +0 -1
- package/lib/runtime/terminal-reader.d.ts +0 -11
- package/lib/runtime/terminal-reader.js +0 -87
- package/lib/runtime/terminal-reader.js.map +0 -1
- package/lib/views/agent-hub.d.ts +0 -32
- package/lib/views/agent-hub.js +0 -206
- package/lib/views/agent-hub.js.map +0 -1
- package/lib/views/copy-selector.d.ts +0 -51
- package/lib/views/copy-selector.js +0 -139
- package/lib/views/copy-selector.js.map +0 -1
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Human console over persisted scheduled reminders.
|
|
3
|
+
* `/schedule` lists this Session's active tasks, edits a name or instruction,
|
|
4
|
+
* opens retained delivery records, and deletes a task. Timing changes stay
|
|
5
|
+
* with the model-facing `schedule_update` tool, whose selectors are richer
|
|
6
|
+
* than a terminal form should collect.
|
|
7
|
+
* @module @agi-fans/dsh-tui/command-schedule
|
|
8
|
+
*/
|
|
9
|
+
import { formatRelativeUntil } from "../chrome/relative-time.js";
|
|
10
|
+
import { registerCommands } from "./registration.js";
|
|
11
|
+
import { askPrompt } from "../prompt-intents.js";
|
|
12
|
+
export const name = 'omdsh-command-schedule';
|
|
13
|
+
export const inject = ['commands', 'schedule', 'tui'];
|
|
14
|
+
/** UTC instant rendered without locale dependence. */
|
|
15
|
+
export function formatInstant(iso) {
|
|
16
|
+
const parsed = new Date(iso);
|
|
17
|
+
return Number.isNaN(parsed.getTime()) ? iso : `${parsed.toISOString().slice(0, 16).replace('T', ' ')} UTC`;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The reminder alone, from a catalog entry that also carries its binding.
|
|
21
|
+
*
|
|
22
|
+
* `catalog()` widens a record with the owning session, its liveness, and the last
|
|
23
|
+
* delivery. Those describe the catalog's view, not the reminder, and passing them
|
|
24
|
+
* back as `expected` would make an optimistic update compare fields the record
|
|
25
|
+
* does not have.
|
|
26
|
+
*/
|
|
27
|
+
function recordOf(entry) {
|
|
28
|
+
const { sessionId: _session, status: _status, lastDelivery: _delivery, ...record } = entry;
|
|
29
|
+
return record;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* When a reminder fires, as a reader would ask it.
|
|
33
|
+
*
|
|
34
|
+
* `scheduledAt` is the committed next instant while the reminder is active and
|
|
35
|
+
* the final one after it stops, so an inactive reminder must not be described as
|
|
36
|
+
* pending. The absolute instant stays alongside the relative one: the relative
|
|
37
|
+
* reading answers "how soon", the absolute one is what a reader checks against
|
|
38
|
+
* their own clock or another zone.
|
|
39
|
+
*/
|
|
40
|
+
export function scheduleWhen(record, status, now = Date.now()) {
|
|
41
|
+
const at = formatInstant(record.scheduledAt);
|
|
42
|
+
if (status === 'inactive')
|
|
43
|
+
return `ended · was ${at}`;
|
|
44
|
+
const parsed = Date.parse(record.scheduledAt);
|
|
45
|
+
return Number.isNaN(parsed) ? `next ${at}` : `next ${formatRelativeUntil(parsed, now)} · ${at}`;
|
|
46
|
+
}
|
|
47
|
+
/** One-line rule summary; timing edits remain with `schedule_update`. */
|
|
48
|
+
export function scheduleRule(record) {
|
|
49
|
+
switch (record.kind) {
|
|
50
|
+
case 'after': return `once, ${record.afterSeconds}s after creation`;
|
|
51
|
+
case 'at': return `once at ${formatInstant(record.scheduledAt)}`;
|
|
52
|
+
case 'every': return `every ${record.everySeconds}s`;
|
|
53
|
+
case 'daily': return `daily ${record.time} ${record.timeZone}`;
|
|
54
|
+
case 'weekly': return `weekly ${record.weekdays.join(',')} ${record.time} ${record.timeZone}`;
|
|
55
|
+
case 'cron': return `cron ${record.expression} ${record.timeZone}`;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function historyText(result) {
|
|
59
|
+
if ('code' in result) {
|
|
60
|
+
return result.code === 'schedule_not_found'
|
|
61
|
+
? 'This reminder no longer exists.'
|
|
62
|
+
: 'These delivery records are no longer addressable.';
|
|
63
|
+
}
|
|
64
|
+
if (result.records.length === 0) {
|
|
65
|
+
return 'No deliveries have been recorded yet.\n\nA reminder is recorded after its message reaches this Session\'s durable log.';
|
|
66
|
+
}
|
|
67
|
+
const rows = result.records.map((record) => `| ${formatInstant(record.deliveredAt)} | ${formatInstant(record.scheduledAt)} | ${(record.prompt ?? '—').replace(/\|/gu, '\\|')} |`);
|
|
68
|
+
return [
|
|
69
|
+
`Deliveries · newest first · retention ${result.retention.days} days / ${result.retention.records} records`,
|
|
70
|
+
'',
|
|
71
|
+
'| Delivered | Scheduled | Prompt |',
|
|
72
|
+
'|---|---|---|',
|
|
73
|
+
...rows,
|
|
74
|
+
'',
|
|
75
|
+
...(result.earlierRecordsUnavailable || result.earlierRecordsPruned
|
|
76
|
+
? ['Earlier records are unavailable; they are never reconstructed from the Session log.']
|
|
77
|
+
: []),
|
|
78
|
+
].join('\n');
|
|
79
|
+
}
|
|
80
|
+
function missText(result) {
|
|
81
|
+
if (!('updated' in result) || result.updated)
|
|
82
|
+
return undefined;
|
|
83
|
+
if (!('code' in result))
|
|
84
|
+
return 'The reminder was not updated.';
|
|
85
|
+
switch (result.code) {
|
|
86
|
+
case 'schedule_not_found': return 'This reminder no longer exists.';
|
|
87
|
+
case 'schedule_ended': return 'This reminder has already ended.';
|
|
88
|
+
case 'schedule_conflict': return 'The reminder changed elsewhere; reopen /schedule and try again.';
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async function edit(ctx, invocation, record, field) {
|
|
92
|
+
const value = await ctx.tui.prompt(askPrompt({
|
|
93
|
+
title: field === 'title' ? 'Reminder name' : 'Reminder instruction',
|
|
94
|
+
question: field === 'title' ? 'Rename this reminder' : 'What should the reminder say?',
|
|
95
|
+
detail: field === 'title'
|
|
96
|
+
? 'The name appears in the task list and reminder catalog.'
|
|
97
|
+
: 'The instruction is delivered to this Session when the reminder fires.',
|
|
98
|
+
initialInput: field === 'title' ? record.title : record.prompt,
|
|
99
|
+
signal: invocation.signal,
|
|
100
|
+
}));
|
|
101
|
+
invocation.signal.throwIfAborted();
|
|
102
|
+
if (value === null)
|
|
103
|
+
return { kind: 'success' };
|
|
104
|
+
const result = await ctx.schedule.update({
|
|
105
|
+
sessionId: invocation.agent.session.id,
|
|
106
|
+
id: record.id,
|
|
107
|
+
expected: record,
|
|
108
|
+
...(field === 'title' ? { title: value } : { prompt: value }),
|
|
109
|
+
});
|
|
110
|
+
if ('code' in result && 'message' in result)
|
|
111
|
+
return { kind: 'error', text: result.message };
|
|
112
|
+
const miss = missText(result);
|
|
113
|
+
if (miss !== undefined)
|
|
114
|
+
return { kind: 'error', text: miss };
|
|
115
|
+
if (!('updated' in result) || !result.updated)
|
|
116
|
+
return { kind: 'error', text: 'The reminder was not updated.' };
|
|
117
|
+
return {
|
|
118
|
+
kind: 'success',
|
|
119
|
+
text: `Updated ${field === 'title' ? 'name' : 'instruction'} for "${result.record.title}".`,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
async function manage(ctx, invocation, record, status) {
|
|
123
|
+
for (;;) {
|
|
124
|
+
invocation.signal.throwIfAborted();
|
|
125
|
+
const action = await ctx.tui.prompt({
|
|
126
|
+
title: `Scheduled · ${record.title}`,
|
|
127
|
+
question: `${scheduleRule(record)} · ${scheduleWhen(record, status)}`,
|
|
128
|
+
detail: record.prompt,
|
|
129
|
+
options: [
|
|
130
|
+
{ label: 'View delivery history', value: 'history', description: 'Open the retained delivery records for this reminder.' },
|
|
131
|
+
{ label: 'Edit name', value: 'title', description: 'Rename the reminder without changing its timing.' },
|
|
132
|
+
{ label: 'Edit instruction', value: 'prompt', description: 'Change what is delivered when it fires.' },
|
|
133
|
+
{ label: 'Delete reminder', value: 'delete', description: 'Stop future delivery and remove saved records.' },
|
|
134
|
+
],
|
|
135
|
+
allowCustom: false,
|
|
136
|
+
notify: false,
|
|
137
|
+
signal: invocation.signal,
|
|
138
|
+
});
|
|
139
|
+
invocation.signal.throwIfAborted();
|
|
140
|
+
if (action === null)
|
|
141
|
+
return { kind: 'success' };
|
|
142
|
+
if (action === 'history') {
|
|
143
|
+
const history = await ctx.schedule.history({ sessionId: invocation.agent.session.id, id: record.id, limit: 20 });
|
|
144
|
+
await ctx.tui.prompt({
|
|
145
|
+
title: `Deliveries · ${record.title}`,
|
|
146
|
+
question: scheduleRule(record),
|
|
147
|
+
detail: historyText(history),
|
|
148
|
+
options: [{ label: 'Back', value: 'back' }],
|
|
149
|
+
allowCustom: false,
|
|
150
|
+
notify: false,
|
|
151
|
+
signal: invocation.signal,
|
|
152
|
+
});
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
if (action === 'delete') {
|
|
156
|
+
const confirm = await ctx.tui.prompt({
|
|
157
|
+
title: 'Delete reminder',
|
|
158
|
+
question: `Stop "${record.title}" and remove its saved delivery records?`,
|
|
159
|
+
options: [{ label: 'Keep reminder', value: 'keep' }, { label: 'Delete reminder', value: 'delete' }],
|
|
160
|
+
allowCustom: false,
|
|
161
|
+
notify: false,
|
|
162
|
+
signal: invocation.signal,
|
|
163
|
+
});
|
|
164
|
+
invocation.signal.throwIfAborted();
|
|
165
|
+
if (confirm !== 'delete')
|
|
166
|
+
continue;
|
|
167
|
+
const result = await ctx.schedule.delete({ sessionId: invocation.agent.session.id, id: record.id });
|
|
168
|
+
if (!result.deleted)
|
|
169
|
+
return { kind: 'error', text: 'That reminder is no longer available.' };
|
|
170
|
+
return { kind: 'success', text: `Deleted reminder "${record.title}".` };
|
|
171
|
+
}
|
|
172
|
+
return edit(ctx, invocation, record, action === 'title' ? 'title' : 'prompt');
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
export async function scheduleCommand(ctx, invocation) {
|
|
176
|
+
if (invocation.rawInput.trim() !== '')
|
|
177
|
+
return { kind: 'error', text: 'Usage: /schedule' };
|
|
178
|
+
const sessionId = invocation.agent.session.id;
|
|
179
|
+
// The catalog is the only read that reports whether a reminder can still fire;
|
|
180
|
+
// `list()` returns the records alone, so a stopped one would read as pending.
|
|
181
|
+
const tasks = (await ctx.schedule.catalog()).filter(entry => entry.sessionId === sessionId);
|
|
182
|
+
if (tasks.length === 0) {
|
|
183
|
+
return {
|
|
184
|
+
kind: 'success',
|
|
185
|
+
text: 'No scheduled tasks in this session. Ask the agent to create one with `schedule_create`.',
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
const selected = await ctx.tui.prompt({
|
|
189
|
+
title: 'Scheduled tasks',
|
|
190
|
+
question: tasks.length === 1 ? 'Choose the reminder' : `Choose one of ${tasks.length} reminders`,
|
|
191
|
+
filterable: true,
|
|
192
|
+
allowCustom: false,
|
|
193
|
+
notify: false,
|
|
194
|
+
emptyText: 'No scheduled tasks in this session. Ask the agent to create one with `schedule_create`.',
|
|
195
|
+
signal: invocation.signal,
|
|
196
|
+
options: tasks.map(entry => ({
|
|
197
|
+
label: entry.title,
|
|
198
|
+
value: String(entry.id),
|
|
199
|
+
description: `${scheduleRule(entry)} · ${scheduleWhen(entry, entry.status)}`,
|
|
200
|
+
})),
|
|
201
|
+
});
|
|
202
|
+
invocation.signal.throwIfAborted();
|
|
203
|
+
if (selected === null)
|
|
204
|
+
return { kind: 'success' };
|
|
205
|
+
const record = tasks.find(entry => String(entry.id) === selected);
|
|
206
|
+
if (record === undefined)
|
|
207
|
+
return { kind: 'error', text: 'That reminder is no longer available.' };
|
|
208
|
+
return manage(ctx, invocation, recordOf(record), record.status);
|
|
209
|
+
}
|
|
210
|
+
export function apply(ctx) {
|
|
211
|
+
registerCommands(ctx, [
|
|
212
|
+
{
|
|
213
|
+
name: 'schedule',
|
|
214
|
+
description: 'Inspect, edit, or delete scheduled reminders',
|
|
215
|
+
handler: async (invocation) => {
|
|
216
|
+
try {
|
|
217
|
+
return await scheduleCommand(ctx, invocation);
|
|
218
|
+
}
|
|
219
|
+
catch (error) {
|
|
220
|
+
if (invocation.signal.aborted)
|
|
221
|
+
return { kind: 'error', text: 'Scheduled task action cancelled.' };
|
|
222
|
+
return { kind: 'error', text: error instanceof Error ? error.message : String(error) };
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
], 'omdsh schedule command');
|
|
227
|
+
}
|
|
228
|
+
//# sourceMappingURL=schedule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule.js","sourceRoot":"","sources":["../../src/commands/schedule.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAUH,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAEhD,MAAM,CAAC,MAAM,IAAI,GAAG,wBAAwB,CAAA;AAC5C,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,CAAC,CAAA;AAErD,sDAAsD;AACtD,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAA;IAC5B,OAAO,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAA;AAC5G,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,QAAQ,CAAC,KAAyF;IACzG,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,GAAG,MAAM,EAAE,GAAG,KAAK,CAAA;IAC1F,OAAO,MAAwB,CAAA;AACjC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,MAAsB,EAAE,MAA6B,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IAClG,MAAM,EAAE,GAAG,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;IAC5C,IAAI,MAAM,KAAK,UAAU;QAAE,OAAO,eAAe,EAAE,EAAE,CAAA;IACrD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;IAC7C,OAAO,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,mBAAmB,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,CAAA;AACjG,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,YAAY,CAAC,MAAsB;IACjD,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,OAAO,CAAC,CAAC,OAAO,SAAS,MAAM,CAAC,YAAY,kBAAkB,CAAA;QACnE,KAAK,IAAI,CAAC,CAAC,OAAO,WAAW,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAA;QAChE,KAAK,OAAO,CAAC,CAAC,OAAO,SAAS,MAAM,CAAC,YAAY,GAAG,CAAA;QACpD,KAAK,OAAO,CAAC,CAAC,OAAO,SAAS,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAA;QAC9D,KAAK,QAAQ,CAAC,CAAC,OAAO,UAAU,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAA;QAC7F,KAAK,MAAM,CAAC,CAAC,OAAO,QAAQ,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAA;IACpE,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,MAAqC;IACxD,IAAI,MAAM,IAAI,MAAM,EAAE,CAAC;QACrB,OAAO,MAAM,CAAC,IAAI,KAAK,oBAAoB;YACzC,CAAC,CAAC,iCAAiC;YACnC,CAAC,CAAC,mDAAmD,CAAA;IACzD,CAAC;IACD,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,OAAO,wHAAwH,CAAA;IACjI,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAA8B,EAAE,EAAE,CACjE,KAAK,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;IACvI,OAAO;QACL,yCAAyC,MAAM,CAAC,SAAS,CAAC,IAAI,WAAW,MAAM,CAAC,SAAS,CAAC,OAAO,UAAU;QAC3G,EAAE;QACF,oCAAoC;QACpC,eAAe;QACf,GAAG,IAAI;QACP,EAAE;QACF,GAAG,CAAC,MAAM,CAAC,yBAAyB,IAAI,MAAM,CAAC,oBAAoB;YACjE,CAAC,CAAC,CAAC,qFAAqF,CAAC;YACzF,CAAC,CAAC,EAAE,CAAC;KACR,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACd,CAAC;AAED,SAAS,QAAQ,CAAC,MAA4B;IAC5C,IAAI,CAAC,CAAC,SAAS,IAAI,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO;QAAE,OAAO,SAAS,CAAA;IAC9D,IAAI,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC;QAAE,OAAO,+BAA+B,CAAA;IAC/D,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,oBAAoB,CAAC,CAAC,OAAO,iCAAiC,CAAA;QACnE,KAAK,gBAAgB,CAAC,CAAC,OAAO,kCAAkC,CAAA;QAChE,KAAK,mBAAmB,CAAC,CAAC,OAAO,iEAAiE,CAAA;IACpG,CAAC;AACH,CAAC;AAED,KAAK,UAAU,IAAI,CAAC,GAAY,EAAE,UAA6B,EAAE,MAAsB,EAAE,KAAyB;IAChH,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC;QAC3C,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,sBAAsB;QACnE,QAAQ,EAAE,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,+BAA+B;QACtF,MAAM,EAAE,KAAK,KAAK,OAAO;YACvB,CAAC,CAAC,yDAAyD;YAC3D,CAAC,CAAC,uEAAuE;QAC3E,YAAY,EAAE,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM;QAC9D,MAAM,EAAE,UAAU,CAAC,MAAM;KAC1B,CAAC,CAAC,CAAA;IACH,UAAU,CAAC,MAAM,CAAC,cAAc,EAAE,CAAA;IAClC,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAA;IAC9C,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC;QACvC,SAAS,EAAE,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE;QACtC,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,QAAQ,EAAE,MAAM;QAChB,GAAG,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;KAC9D,CAAC,CAAA;IACF,IAAI,MAAM,IAAI,MAAM,IAAI,SAAS,IAAI,MAAM;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,OAAO,EAAE,CAAA;IAC3F,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAA;IAC7B,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;IAC5D,IAAI,CAAC,CAAC,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,+BAA+B,EAAE,CAAA;IAC9G,OAAO;QACL,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,WAAW,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,SAAS,MAAM,CAAC,MAAM,CAAC,KAAK,IAAI;KAC5F,CAAA;AACH,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,GAAY,EAAE,UAA6B,EAAE,MAAsB,EAAE,MAA6B;IACtH,SAAS,CAAC;QACR,UAAU,CAAC,MAAM,CAAC,cAAc,EAAE,CAAA;QAClC,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC;YAClC,KAAK,EAAE,eAAe,MAAM,CAAC,KAAK,EAAE;YACpC,QAAQ,EAAE,GAAG,YAAY,CAAC,MAAM,CAAC,MAAM,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE;YACrE,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,OAAO,EAAE;gBACP,EAAE,KAAK,EAAE,uBAAuB,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,uDAAuD,EAAE;gBAC1H,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,kDAAkD,EAAE;gBACvG,EAAE,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,yCAAyC,EAAE;gBACtG,EAAE,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,gDAAgD,EAAE;aAC7G;YACD,WAAW,EAAE,KAAK;YAClB,MAAM,EAAE,KAAK;YACb,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAA;QACF,UAAU,CAAC,MAAM,CAAC,cAAc,EAAE,CAAA;QAClC,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAA;QAC/C,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAA;YAChH,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC;gBACnB,KAAK,EAAE,gBAAgB,MAAM,CAAC,KAAK,EAAE;gBACrC,QAAQ,EAAE,YAAY,CAAC,MAAM,CAAC;gBAC9B,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC;gBAC5B,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;gBAC3C,WAAW,EAAE,KAAK;gBAClB,MAAM,EAAE,KAAK;gBACb,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAA;YACF,SAAQ;QACV,CAAC;QACD,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;YACxB,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC;gBACnC,KAAK,EAAE,iBAAiB;gBACxB,QAAQ,EAAE,SAAS,MAAM,CAAC,KAAK,0CAA0C;gBACzE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;gBACnG,WAAW,EAAE,KAAK;gBAClB,MAAM,EAAE,KAAK;gBACb,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAA;YACF,UAAU,CAAC,MAAM,CAAC,cAAc,EAAE,CAAA;YAClC,IAAI,OAAO,KAAK,QAAQ;gBAAE,SAAQ;YAClC,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAA;YACnG,IAAI,CAAC,MAAM,CAAC,OAAO;gBAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,uCAAuC,EAAE,CAAA;YAC5F,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,qBAAqB,MAAM,CAAC,KAAK,IAAI,EAAE,CAAA;QACzE,CAAC;QACD,OAAO,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAA;IAC/E,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,GAAY,EAAE,UAA6B;IAC/E,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAA;IACzF,MAAM,SAAS,GAAG,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAA;IAC7C,+EAA+E;IAC/E,8EAA8E;IAC9E,MAAM,KAAK,GAAG,CAAC,MAAM,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,KAAK,SAAS,CAAC,CAAA;IAC3F,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO;YACL,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,yFAAyF;SAChG,CAAA;IACH,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC;QACpC,KAAK,EAAE,iBAAiB;QACxB,QAAQ,EAAE,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,iBAAiB,KAAK,CAAC,MAAM,YAAY;QAChG,UAAU,EAAE,IAAI;QAChB,WAAW,EAAE,KAAK;QAClB,MAAM,EAAE,KAAK;QACb,SAAS,EAAE,yFAAyF;QACpG,MAAM,EAAE,UAAU,CAAC,MAAM;QACzB,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC3B,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YACvB,WAAW,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC,MAAM,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE;SAC7E,CAAC,CAAC;KACJ,CAAC,CAAA;IACF,UAAU,CAAC,MAAM,CAAC,cAAc,EAAE,CAAA;IAClC,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAA;IACjD,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,QAAQ,CAAC,CAAA;IACjE,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,uCAAuC,EAAE,CAAA;IACjG,OAAO,MAAM,CAAC,GAAG,EAAE,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;AACjE,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,GAAY;IAChC,gBAAgB,CAAC,GAAG,EAAE;QACpB;YACE,IAAI,EAAE,UAAU;YAChB,WAAW,EAAE,8CAA8C;YAC3D,OAAO,EAAE,KAAK,EAAC,UAAU,EAAC,EAAE;gBAC1B,IAAI,CAAC;oBACH,OAAO,MAAM,eAAe,CAAC,GAAG,EAAE,UAAU,CAAC,CAAA;gBAC/C,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO;wBAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,kCAAkC,EAAE,CAAA;oBACjG,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAA;gBACxF,CAAC;YACH,CAAC;SACF;KACF,EAAE,wBAAwB,CAAC,CAAA;AAC9B,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/** Agent composition selection and diagnostics. */
|
|
2
2
|
import type { Context } from '@deepseek-ai/cordis';
|
|
3
3
|
import type { AgentPresetRegistry } from '@deepseek-ai/dsh-agent-preset-registry';
|
|
4
4
|
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
import { formatAgentPreset } from "../session/session-configuration.js";
|
|
1
|
+
/** Agent composition selection and diagnostics. */
|
|
2
|
+
import { isBlankSession, formatAgentPreset } from "../session/session-configuration.js";
|
|
3
3
|
import { registerCommands } from "./registration.js";
|
|
4
4
|
export const name = 'omdsh-command-session-configuration';
|
|
5
|
-
export const inject = ['commands', 'omdshSession', 'tui', 'agentPresets'
|
|
5
|
+
export const inject = ['commands', 'omdshSession', 'tui', 'agentPresets'];
|
|
6
6
|
async function selectAgent(ctx, invocation) {
|
|
7
7
|
const args = invocation.rawInput.trim().split(/\s+/u);
|
|
8
8
|
if (args[0] === 'inspect' && args.length <= 2) {
|
|
@@ -10,6 +10,31 @@ async function selectAgent(ctx, invocation) {
|
|
|
10
10
|
}
|
|
11
11
|
if (invocation.rawInput.trim() !== '')
|
|
12
12
|
return { kind: 'error', text: 'Usage: /agent [inspect [preset-id]]' };
|
|
13
|
+
if (!isBlankSession(invocation.agent.session)) {
|
|
14
|
+
const lockedMessage = 'The Agent preset is fixed for this conversation. Start /new to choose a different preset before sending a message. Use /agent inspect to view its composition.';
|
|
15
|
+
if (ctx.tui.interactive !== true) {
|
|
16
|
+
return { kind: 'success', text: lockedMessage };
|
|
17
|
+
}
|
|
18
|
+
const action = await ctx.tui.prompt({
|
|
19
|
+
title: 'Agent',
|
|
20
|
+
question: 'The Agent preset is fixed for this conversation',
|
|
21
|
+
detail: 'Start /new to choose a different preset before sending a message.',
|
|
22
|
+
options: [
|
|
23
|
+
{ label: 'Close', value: 'close', description: 'Return to the current conversation' },
|
|
24
|
+
{ label: 'Inspect composition', value: 'inspect', description: 'View declared presets and this session’s retained composition' },
|
|
25
|
+
],
|
|
26
|
+
initialValue: 'close',
|
|
27
|
+
allowCustom: false,
|
|
28
|
+
notify: false,
|
|
29
|
+
signal: invocation.signal,
|
|
30
|
+
});
|
|
31
|
+
if (action === 'inspect') {
|
|
32
|
+
const diagnostics = await presetDiagnostics(ctx.agentPresets, invocation.agent);
|
|
33
|
+
// Composition is a report; the transcript is where reports live.
|
|
34
|
+
ctx.tui.commandOutput('Agent composition', diagnostics);
|
|
35
|
+
}
|
|
36
|
+
return { kind: 'success' };
|
|
37
|
+
}
|
|
13
38
|
const controls = ctx.omdshSession.controls(invocation.agent);
|
|
14
39
|
const presets = await ctx.omdshSession.agentPresets();
|
|
15
40
|
if (presets.length === 0)
|
|
@@ -26,6 +51,7 @@ async function selectAgent(ctx, invocation) {
|
|
|
26
51
|
})),
|
|
27
52
|
...(controls.agentPreset === undefined ? {} : { initialValue: controls.agentPreset }),
|
|
28
53
|
allowCustom: false,
|
|
54
|
+
notify: false,
|
|
29
55
|
submitLabel: 'apply',
|
|
30
56
|
signal: invocation.signal,
|
|
31
57
|
});
|
|
@@ -66,34 +92,9 @@ export async function presetDiagnostics(registry, agent, requested) {
|
|
|
66
92
|
])),
|
|
67
93
|
].join('\n');
|
|
68
94
|
}
|
|
69
|
-
async function selectWorkflow(ctx, invocation) {
|
|
70
|
-
if (invocation.rawInput.trim() !== '')
|
|
71
|
-
return { kind: 'error', text: 'Usage: /workflow' };
|
|
72
|
-
const state = ctx.planMode.get(invocation.agent);
|
|
73
|
-
const current = state.pending ?? state.active;
|
|
74
|
-
const selected = await ctx.tui.prompt({
|
|
75
|
-
title: 'Workflow',
|
|
76
|
-
question: 'Choose how this session approaches the next step',
|
|
77
|
-
options: [
|
|
78
|
-
{ label: 'Default', value: 'default', description: `${current ? '' : 'Current · '}Work directly on the request.` },
|
|
79
|
-
{ label: 'Plan', value: 'plan', description: `${current ? 'Current · ' : ''}Explore and present a reviewable plan before implementation.` },
|
|
80
|
-
],
|
|
81
|
-
initialValue: current ? 'plan' : 'default',
|
|
82
|
-
allowCustom: false,
|
|
83
|
-
submitLabel: 'apply',
|
|
84
|
-
signal: invocation.signal,
|
|
85
|
-
});
|
|
86
|
-
if (selected === null)
|
|
87
|
-
return { kind: 'success' };
|
|
88
|
-
const active = selected === 'plan';
|
|
89
|
-
const outcome = ctx.omdshSession.changeWorkflow(invocation.agent, active);
|
|
90
|
-
const suffix = outcome === 'queued' ? ' (next step)' : '';
|
|
91
|
-
return { kind: 'success', text: `Workflow: ${active ? 'Plan' : 'Default'}${suffix}` };
|
|
92
|
-
}
|
|
93
95
|
export function apply(ctx) {
|
|
94
96
|
registerCommands(ctx, [
|
|
95
97
|
{ name: 'agent', description: 'Choose the session Agent preset', handler: invocation => selectAgent(ctx, invocation) },
|
|
96
|
-
{ name: 'workflow', description: 'Choose Default or Plan workflow', handler: invocation => selectWorkflow(ctx, invocation) },
|
|
97
98
|
], 'omdsh session configuration commands');
|
|
98
99
|
}
|
|
99
100
|
//# sourceMappingURL=session-configuration.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-configuration.js","sourceRoot":"","sources":["../../src/commands/session-configuration.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"session-configuration.js","sourceRoot":"","sources":["../../src/commands/session-configuration.ts"],"names":[],"mappings":"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"}
|
package/lib/commands/session.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/** Session lifecycle and inspection commands registered through dsh-commands. */
|
|
2
|
+
import { SessionId } from '@deepseek-ai/dsh-session';
|
|
2
3
|
import { registerCommands } from "./registration.js";
|
|
4
|
+
import { askPrompt, confirmPrompt } from "../prompt-intents.js";
|
|
3
5
|
import { formatRelativeAge } from "../chrome/relative-time.js";
|
|
4
6
|
import { formatPermission, formatTokens } from "../chrome/status-line.js";
|
|
5
7
|
import { formatAgentPreset } from "../session/session-configuration.js";
|
|
@@ -25,25 +27,39 @@ async function newSession(ctx, invocation) {
|
|
|
25
27
|
await ctx.omdshSession.newSession(invocation.agent);
|
|
26
28
|
return { kind: 'success', text: 'Started a new session.' };
|
|
27
29
|
}
|
|
28
|
-
async function resumeSession(ctx, invocation) {
|
|
30
|
+
async function resumeSession(ctx, invocation, search) {
|
|
29
31
|
if (ctx.get('sessionPersistence') === undefined)
|
|
30
32
|
return { kind: 'error', text: 'Session persistence is not configured.' };
|
|
31
33
|
if (invocation.agent.status === 'running') {
|
|
32
34
|
return { kind: 'error', text: 'Finish or interrupt the active turn before resuming another session.' };
|
|
33
35
|
}
|
|
34
36
|
await ctx.omdshSession.refreshRecent();
|
|
35
|
-
let id = invocation.rawInput.trim();
|
|
37
|
+
let id = search === undefined ? invocation.rawInput.trim() : '';
|
|
38
|
+
if (id !== '' && search === undefined) {
|
|
39
|
+
const stored = await ctx.get('sessionPersistence')?.stat(SessionId(id));
|
|
40
|
+
if (stored === undefined) {
|
|
41
|
+
// A non-session argument is a content query; the merged command opens
|
|
42
|
+
// the same searchable library instead of failing an ID lookup.
|
|
43
|
+
if (/^session-[0-9a-z-]+$/u.test(id))
|
|
44
|
+
return { kind: 'error', text: `Session ${id} was not found.` };
|
|
45
|
+
const result = await findSessions(ctx, invocation);
|
|
46
|
+
return result.kind === 'rows' ? resumeSession(ctx, invocation, result) : result;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
36
49
|
if (id === '') {
|
|
37
50
|
const libraryPath = ctx.omdshSession.sessionLibraryPath;
|
|
38
51
|
let archivedView = false;
|
|
39
52
|
let selectedId;
|
|
40
53
|
while (id === '') {
|
|
41
54
|
const library = readSessionLibrary(libraryPath);
|
|
42
|
-
const
|
|
43
|
-
|
|
55
|
+
const inventory = new Map(ctx.omdshSession.recentSessions.map(row => [row.id, row]));
|
|
56
|
+
const source = search === undefined ? ctx.omdshSession.recentSessions : search.rows.map(row => ({ ...row, ...inventory.get(row.id), ...(row.preview === undefined ? {} : { preview: row.preview }) }));
|
|
57
|
+
const recent = sortSessionRows(source.filter(row => library.archived.includes(row.id) === archivedView), library.pinned);
|
|
58
|
+
if ((search?.rows ?? ctx.omdshSession.recentSessions).length === 0)
|
|
44
59
|
return { kind: 'success', text: 'No durable sessions found.' };
|
|
45
60
|
const answer = await ctx.tui.prompt({
|
|
46
|
-
title:
|
|
61
|
+
title: `Session Library${search === undefined ? '' : ' · Search'}${archivedView ? ' · Archived' : ''}`,
|
|
62
|
+
...(search === undefined ? {} : { detail: `Content search: ${search.query} · up to ${SESSION_SEARCH_LIMIT} matches` }),
|
|
47
63
|
notify: false,
|
|
48
64
|
...(selectedId === undefined ? {} : { initialValue: selectedId }),
|
|
49
65
|
question: '',
|
|
@@ -57,6 +73,7 @@ async function resumeSession(ctx, invocation) {
|
|
|
57
73
|
...(library.pinned.includes(row.id) ? ['pinned'] : []),
|
|
58
74
|
formatRelativeAge(row.updatedAt ?? row.createdAt),
|
|
59
75
|
...(row.eventCount === undefined ? [] : [`${row.eventCount} events`]),
|
|
76
|
+
...(row.formatStatus === 'migration-required' ? ['migration required'] : []),
|
|
60
77
|
].join(' · '),
|
|
61
78
|
...(row.status === undefined
|
|
62
79
|
? {}
|
|
@@ -72,12 +89,14 @@ async function resumeSession(ctx, invocation) {
|
|
|
72
89
|
}),
|
|
73
90
|
})),
|
|
74
91
|
actions: [
|
|
92
|
+
...(search === undefined ? [] : [{ key: 'Alt+L', label: 'all sessions', valuePrefix: 'library:', scope: 'list' }]),
|
|
93
|
+
...(ctx.get('sessionQuery') === undefined ? [] : [{ key: 'Alt+S', label: 'search content', valuePrefix: 'search:', scope: 'list' }]),
|
|
75
94
|
{ key: 'r', label: 'rename', valuePrefix: 'rename:' },
|
|
76
95
|
{ key: 'p', label: 'pin/unpin', valuePrefix: 'pin:' },
|
|
77
96
|
{ key: 'Alt+A', label: archivedView ? 'restore' : 'archive', valuePrefix: 'archive:' },
|
|
78
97
|
{ key: 'Alt+V', label: archivedView ? 'active sessions' : 'archived sessions', valuePrefix: 'view:', scope: 'list' },
|
|
79
98
|
],
|
|
80
|
-
presentation: '
|
|
99
|
+
presentation: 'card',
|
|
81
100
|
filterable: true,
|
|
82
101
|
allowCustom: false,
|
|
83
102
|
signal: invocation.signal,
|
|
@@ -85,6 +104,29 @@ async function resumeSession(ctx, invocation) {
|
|
|
85
104
|
if (answer === null)
|
|
86
105
|
return { kind: 'success' };
|
|
87
106
|
invocation.signal.throwIfAborted();
|
|
107
|
+
if (answer === 'library:') {
|
|
108
|
+
search = undefined;
|
|
109
|
+
archivedView = false;
|
|
110
|
+
selectedId = undefined;
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (answer === 'search:') {
|
|
114
|
+
const query = await ctx.tui.prompt(askPrompt({ title: 'Search session content', question: 'Enter search text', signal: invocation.signal }));
|
|
115
|
+
if (query === null || query.trim() === '')
|
|
116
|
+
continue;
|
|
117
|
+
const result = await findSessions(ctx, { ...invocation, rawInput: query });
|
|
118
|
+
if (result.kind === 'rows') {
|
|
119
|
+
search = result;
|
|
120
|
+
archivedView = false;
|
|
121
|
+
selectedId = undefined;
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (result.text !== undefined) {
|
|
125
|
+
ctx.tui.commandOutput('Session search', result.text);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
88
130
|
if (answer === 'view:') {
|
|
89
131
|
archivedView = !archivedView;
|
|
90
132
|
continue;
|
|
@@ -108,13 +150,12 @@ async function resumeSession(ctx, invocation) {
|
|
|
108
150
|
if (row === undefined)
|
|
109
151
|
continue;
|
|
110
152
|
selectedId = target;
|
|
111
|
-
const title = await ctx.tui.prompt({
|
|
153
|
+
const title = await ctx.tui.prompt(askPrompt({
|
|
112
154
|
title: 'Rename Session',
|
|
113
155
|
question: `New title for “${row.title}”`,
|
|
114
156
|
initialInput: row.title,
|
|
115
|
-
allowCustom: true,
|
|
116
157
|
signal: invocation.signal,
|
|
117
|
-
});
|
|
158
|
+
}));
|
|
118
159
|
if (title !== null)
|
|
119
160
|
await ctx.omdshSession.renameSession(invocation.agent, target, title, invocation.signal);
|
|
120
161
|
continue;
|
|
@@ -124,7 +165,23 @@ async function resumeSession(ctx, invocation) {
|
|
|
124
165
|
}
|
|
125
166
|
if (id === invocation.agent.id)
|
|
126
167
|
return { kind: 'success', text: 'That session is already active.' };
|
|
168
|
+
return resumeStoredSession(ctx, invocation, id);
|
|
169
|
+
}
|
|
170
|
+
async function resumeStoredSession(ctx, invocation, id) {
|
|
127
171
|
try {
|
|
172
|
+
const stored = await ctx.get('sessionPersistence')?.stat(SessionId(id));
|
|
173
|
+
if (stored?.formatStatus === 'migration-required' && ctx.tui.interactive === true) {
|
|
174
|
+
const migrate = await confirmPrompt(request => ctx.tui.prompt(request), {
|
|
175
|
+
title: 'Migrate session',
|
|
176
|
+
question: ctx.omdshSession.recentSessions.find(row => row.id === id)?.title ?? id,
|
|
177
|
+
detail: 'Opening this session writes a current-format generation and retains the historical source. Browsing the Session Library does not migrate it.',
|
|
178
|
+
acceptLabel: 'Migrate and resume',
|
|
179
|
+
cancelLabel: null,
|
|
180
|
+
signal: invocation.signal,
|
|
181
|
+
});
|
|
182
|
+
if (!migrate || invocation.signal.aborted)
|
|
183
|
+
return { kind: 'success' };
|
|
184
|
+
}
|
|
128
185
|
await ctx.omdshSession.resumeSession(invocation.agent, id, invocation.signal);
|
|
129
186
|
return { kind: 'success', text: `Resumed ${id}.` };
|
|
130
187
|
}
|
|
@@ -134,8 +191,8 @@ async function resumeSession(ctx, invocation) {
|
|
|
134
191
|
return { kind: 'error', text: 'Resume failed: ' + (error instanceof Error ? error.message : String(error)) };
|
|
135
192
|
}
|
|
136
193
|
}
|
|
137
|
-
/**
|
|
138
|
-
async function
|
|
194
|
+
/** Read session content without replacing the active conversation. */
|
|
195
|
+
async function findSessions(ctx, invocation) {
|
|
139
196
|
if (invocation.agent.status === 'running') {
|
|
140
197
|
return { kind: 'error', text: 'Finish or interrupt the active turn before resuming another session.' };
|
|
141
198
|
}
|
|
@@ -164,40 +221,12 @@ async function searchSessions(ctx, invocation) {
|
|
|
164
221
|
}
|
|
165
222
|
}
|
|
166
223
|
catch { /* title folding is best-effort; the snippet still identifies the hit */ }
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
emptyText: 'No session content matched.',
|
|
171
|
-
options: hits.map(hit => ({
|
|
172
|
-
label: titles.get(hit.header.id) ?? hit.bestMatch.snippet,
|
|
173
|
-
value: hit.header.id,
|
|
224
|
+
return { kind: 'rows', query, rows: hits.map(hit => ({
|
|
225
|
+
id: hit.header.id,
|
|
226
|
+
title: titles.get(hit.header.id) ?? hit.bestMatch.snippet,
|
|
174
227
|
preview: hit.bestMatch.snippet,
|
|
175
|
-
|
|
176
|
-
}))
|
|
177
|
-
presentation: 'fullscreen-list',
|
|
178
|
-
filterable: false,
|
|
179
|
-
allowCustom: false,
|
|
180
|
-
signal: invocation.signal,
|
|
181
|
-
});
|
|
182
|
-
if (answer === null)
|
|
183
|
-
return { kind: 'success' };
|
|
184
|
-
if (answer === invocation.agent.id)
|
|
185
|
-
return { kind: 'success', text: 'That session is already active.' };
|
|
186
|
-
try {
|
|
187
|
-
await ctx.omdshSession.resumeSession(invocation.agent, answer, invocation.signal);
|
|
188
|
-
return { kind: 'success', text: `Resumed ${answer}.` };
|
|
189
|
-
}
|
|
190
|
-
catch (error) {
|
|
191
|
-
if (invocation.signal.aborted)
|
|
192
|
-
return { kind: 'error', text: 'Resume cancelled.' };
|
|
193
|
-
return { kind: 'error', text: 'Resume failed: ' + (error instanceof Error ? error.message : String(error)) };
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
/** `/sessions` opens the library bare, or searches session content when given a query. */
|
|
197
|
-
function sessionsCommand(ctx, invocation) {
|
|
198
|
-
return invocation.rawInput.trim() === ''
|
|
199
|
-
? resumeSession(ctx, invocation)
|
|
200
|
-
: searchSessions(ctx, invocation);
|
|
228
|
+
createdAt: hit.header.createdAt,
|
|
229
|
+
})) };
|
|
201
230
|
}
|
|
202
231
|
function showSession(ctx, invocation) {
|
|
203
232
|
const stats = ctx.omdshSession.stats(invocation.agent);
|
|
@@ -247,25 +276,6 @@ function showContext(ctx, invocation) {
|
|
|
247
276
|
text: contextDiagnosticsMarkdown(ctx.omdshSession.contextDiagnostics(invocation.agent)),
|
|
248
277
|
};
|
|
249
278
|
}
|
|
250
|
-
function showTodo(invocation) {
|
|
251
|
-
if (invocation.rawInput.trim() !== '')
|
|
252
|
-
return { kind: 'error', text: 'Usage: /todo' };
|
|
253
|
-
const event = invocation.agent.session.snapshotEvents().findLast(item => item.type === 'todo/write');
|
|
254
|
-
if (event === undefined)
|
|
255
|
-
return { kind: 'success', text: 'No todo list has been recorded.' };
|
|
256
|
-
return {
|
|
257
|
-
kind: 'success',
|
|
258
|
-
text: [
|
|
259
|
-
`Todo · ${event.data.todos.length} item${event.data.todos.length === 1 ? '' : 's'}`,
|
|
260
|
-
'',
|
|
261
|
-
...event.data.todos.map((todo) => todo.status === 'completed'
|
|
262
|
-
? `- [x] ${todo.content}`
|
|
263
|
-
: todo.status === 'in_progress'
|
|
264
|
-
? `- [ ] **In progress** · ${todo.content}`
|
|
265
|
-
: `- [ ] ${todo.content}`),
|
|
266
|
-
].join('\n'),
|
|
267
|
-
};
|
|
268
|
-
}
|
|
269
279
|
export function apply(ctx) {
|
|
270
280
|
registerCommands(ctx, [
|
|
271
281
|
{ name: 'queue', description: 'Review, edit, delete, and reorder pending messages', handler: async (invocation) => {
|
|
@@ -278,27 +288,12 @@ export function apply(ctx) {
|
|
|
278
288
|
{ name: 'new', description: 'Start a new session', handler: invocation => newSession(ctx, invocation) },
|
|
279
289
|
{
|
|
280
290
|
name: 'resume',
|
|
281
|
-
description: '
|
|
282
|
-
input: { hint: '[session-id]' },
|
|
291
|
+
description: 'Open the Session Library, search session content, or resume by ID',
|
|
292
|
+
input: { hint: '[session-id|query]' },
|
|
283
293
|
handler: invocation => resumeSession(ctx, invocation),
|
|
284
294
|
},
|
|
285
|
-
{
|
|
286
|
-
name: 'sessions',
|
|
287
|
-
description: 'Open the Session Library, or search session content with a query',
|
|
288
|
-
input: { hint: '[query]' },
|
|
289
|
-
handler: invocation => sessionsCommand(ctx, invocation),
|
|
290
|
-
},
|
|
291
|
-
{ name: 'tree', description: 'Browse conversation turns and branches', handler: async (invocation) => {
|
|
292
|
-
if (invocation.rawInput.trim() !== '')
|
|
293
|
-
return { kind: 'error', text: 'Usage: /tree' };
|
|
294
|
-
if (invocation.agent.status !== 'idle')
|
|
295
|
-
return { kind: 'error', text: 'Finish or interrupt the active turn before opening the Session Tree.' };
|
|
296
|
-
await ctx.omdshSession.openSessionTree(invocation.signal);
|
|
297
|
-
return { kind: 'success' };
|
|
298
|
-
} },
|
|
299
295
|
{ name: 'session', description: 'Show current session details', handler: invocation => showSession(ctx, invocation) },
|
|
300
296
|
{ name: 'retry', description: 'Run the most recent human prompt again', handler: invocation => retry(ctx, invocation) },
|
|
301
|
-
{ name: 'todo', description: 'Show the current session todo list', handler: showTodo },
|
|
302
297
|
], 'omdsh session commands');
|
|
303
298
|
}
|
|
304
299
|
//# sourceMappingURL=session.js.map
|