minionsai 0.1.11 → 0.1.13

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.
Files changed (29) hide show
  1. package/README.md +3 -3
  2. package/dist/server/client/dist/assets/{highlighted-body-TPN3WLV5-Bsa7IWN6.js → highlighted-body-TPN3WLV5-K6mK4CnF.js} +1 -1
  3. package/dist/server/client/dist/assets/index-BP1qiwyD.css +1 -0
  4. package/dist/server/client/dist/assets/index-o62nNllV.js +751 -0
  5. package/dist/server/client/dist/index.html +2 -2
  6. package/dist/server/client/dist/sounds/done.mp3 +0 -0
  7. package/dist/server/server/adapters/hermes-worker.d.ts +18 -14
  8. package/dist/server/server/adapters/hermes-worker.js +78 -39
  9. package/dist/server/server/adapters/types.d.ts +18 -14
  10. package/dist/server/server/adapters/worker-protocol.d.ts +51 -28
  11. package/dist/server/server/app.js +2 -2
  12. package/dist/server/server/live-chat.d.ts +17 -2
  13. package/dist/server/server/live-chat.js +97 -26
  14. package/dist/server/server/prompts/task-agent.d.ts +1 -1
  15. package/dist/server/server/prompts/task-agent.js +2 -2
  16. package/dist/server/server/routes/chat.js +169 -51
  17. package/dist/server/server/routes/{routines.d.ts → scheduled-tasks.d.ts} +1 -1
  18. package/dist/server/server/routes/{routines.js → scheduled-tasks.js} +49 -49
  19. package/dist/server/server/scheduled-tasks/runs.d.ts +3 -0
  20. package/dist/server/server/{routines → scheduled-tasks}/runs.js +7 -7
  21. package/dist/server/server/workers/{hermes_routines.py → hermes_scheduled_tasks.py} +42 -42
  22. package/dist/server/server/workers/hermes_worker.py +153 -79
  23. package/dist/server/server/workers/hermes_worker_utils.py +1 -1
  24. package/dist/server/shared/types.d.ts +40 -14
  25. package/dist/server/shared/types.js +2 -0
  26. package/package.json +2 -1
  27. package/dist/server/client/dist/assets/index-BdyoTQw9.css +0 -1
  28. package/dist/server/client/dist/assets/index-C0fNYxd2.js +0 -727
  29. package/dist/server/server/routines/runs.d.ts +0 -3
@@ -8,8 +8,8 @@
8
8
  <script>
9
9
  (function(){var t=localStorage.getItem('theme');var d=t==='dark'||(!t||t==='system')&&window.matchMedia('(prefers-color-scheme: dark)').matches;if(d)document.documentElement.classList.add('dark')})();
10
10
  </script>
11
- <script type="module" crossorigin src="/assets/index-C0fNYxd2.js"></script>
12
- <link rel="stylesheet" crossorigin href="/assets/index-BdyoTQw9.css">
11
+ <script type="module" crossorigin src="/assets/index-o62nNllV.js"></script>
12
+ <link rel="stylesheet" crossorigin href="/assets/index-BP1qiwyD.css">
13
13
  </head>
14
14
  <body class="bg-gray-50 text-gray-900 dark:bg-gray-950 dark:text-gray-100">
15
15
  <div id="root"></div>
@@ -1,4 +1,4 @@
1
- import type { AgentDefaults, AgentModelsResponse, CompactResult, Routine, RoutineInput, SessionMetadata, TaskMessage } from '../../shared/types.js';
1
+ import type { AgentDefaults, AgentModelsResponse, CompactResult, GoalDecision, GoalStateSnapshot, ScheduledTask, ScheduledTaskInput, SessionMetadata, TaskMessage } from '../../shared/types.js';
2
2
  import type { AgentAdapter, AgentRunOptions, AgentRunSettings, StreamEvent } from './types.js';
3
3
  export declare class HermesWorkerAdapter implements AgentAdapter {
4
4
  private client;
@@ -19,19 +19,15 @@ export declare class HermesWorkerAdapter implements AgentAdapter {
19
19
  reasoningEffort?: string | null;
20
20
  }): Promise<AgentDefaults>;
21
21
  getModels(): Promise<AgentModelsResponse>;
22
- listRoutines(includeDisabled?: boolean): Promise<Routine[]>;
23
- getRoutine(jobId: string): Promise<Routine | null>;
24
- createRoutine(input: RoutineInput): Promise<Routine>;
25
- updateRoutine(jobId: string, updates: Partial<RoutineInput>): Promise<Routine | null>;
26
- pauseRoutine(jobId: string, reason?: string): Promise<Routine | null>;
27
- resumeRoutine(jobId: string): Promise<Routine | null>;
28
- runRoutine(jobId: string): Promise<Routine | null>;
29
- removeRoutine(jobId: string): Promise<boolean>;
30
- tickRoutines(): Promise<number>;
31
- judgeCompletion(taskTitle: string, taskDescription: string | null, responseText: string): Promise<{
32
- done: boolean;
33
- reason: string;
34
- }>;
22
+ listScheduledTasks(includeDisabled?: boolean): Promise<ScheduledTask[]>;
23
+ getScheduledTask(scheduledTaskId: string): Promise<ScheduledTask | null>;
24
+ createScheduledTask(input: ScheduledTaskInput): Promise<ScheduledTask>;
25
+ updateScheduledTask(scheduledTaskId: string, updates: Partial<ScheduledTaskInput>): Promise<ScheduledTask | null>;
26
+ pauseScheduledTask(scheduledTaskId: string, reason?: string): Promise<ScheduledTask | null>;
27
+ resumeScheduledTask(scheduledTaskId: string): Promise<ScheduledTask | null>;
28
+ runScheduledTask(scheduledTaskId: string): Promise<ScheduledTask | null>;
29
+ removeScheduledTask(scheduledTaskId: string): Promise<boolean>;
30
+ tickScheduledTasks(): Promise<number>;
35
31
  generateTitle(description: string): Promise<{
36
32
  title: string;
37
33
  }>;
@@ -41,4 +37,12 @@ export declare class HermesWorkerAdapter implements AgentAdapter {
41
37
  systemMessage?: string;
42
38
  settings?: AgentRunSettings;
43
39
  }): Promise<CompactResult>;
40
+ getGoalStatus(sessionId: string): Promise<GoalStateSnapshot | null>;
41
+ setGoal(sessionId: string, goal: string, options?: {
42
+ maxTurns?: number | null;
43
+ }): Promise<GoalStateSnapshot>;
44
+ pauseGoal(sessionId: string, reason?: string): Promise<GoalStateSnapshot | null>;
45
+ resumeGoal(sessionId: string): Promise<GoalStateSnapshot | null>;
46
+ clearGoal(sessionId: string): Promise<boolean>;
47
+ evaluateGoal(sessionId: string, responseText: string): Promise<GoalDecision>;
44
48
  }
@@ -441,76 +441,68 @@ export class HermesWorkerAdapter {
441
441
  async getModels() {
442
442
  return await this.client.request('models.list');
443
443
  }
444
- async listRoutines(includeDisabled = false) {
444
+ async listScheduledTasks(includeDisabled = false) {
445
445
  const result = await this.client.request({
446
- type: 'routines.jobs.list',
446
+ type: 'scheduledTasks.list',
447
447
  includeDisabled,
448
448
  });
449
- return result.jobs;
449
+ return result.scheduledTasks;
450
450
  }
451
- async getRoutine(jobId) {
451
+ async getScheduledTask(scheduledTaskId) {
452
452
  const result = await this.client.request({
453
- type: 'routines.jobs.get',
454
- jobId,
453
+ type: 'scheduledTasks.get',
454
+ scheduledTaskId,
455
455
  });
456
- return result.job;
456
+ return result.scheduledTask;
457
457
  }
458
- async createRoutine(input) {
458
+ async createScheduledTask(input) {
459
459
  const result = await this.client.request({
460
- type: 'routines.jobs.create',
460
+ type: 'scheduledTasks.create',
461
461
  ...input,
462
462
  });
463
- return result.job;
463
+ return result.scheduledTask;
464
464
  }
465
- async updateRoutine(jobId, updates) {
465
+ async updateScheduledTask(scheduledTaskId, updates) {
466
466
  const result = await this.client.request({
467
- type: 'routines.jobs.update',
468
- jobId,
467
+ type: 'scheduledTasks.update',
468
+ scheduledTaskId,
469
469
  ...updates,
470
470
  });
471
- return result.job;
471
+ return result.scheduledTask;
472
472
  }
473
- async pauseRoutine(jobId, reason) {
473
+ async pauseScheduledTask(scheduledTaskId, reason) {
474
474
  const result = await this.client.request({
475
- type: 'routines.jobs.pause',
476
- jobId,
475
+ type: 'scheduledTasks.pause',
476
+ scheduledTaskId,
477
477
  reason,
478
478
  });
479
- return result.job;
479
+ return result.scheduledTask;
480
480
  }
481
- async resumeRoutine(jobId) {
481
+ async resumeScheduledTask(scheduledTaskId) {
482
482
  const result = await this.client.request({
483
- type: 'routines.jobs.resume',
484
- jobId,
483
+ type: 'scheduledTasks.resume',
484
+ scheduledTaskId,
485
485
  });
486
- return result.job;
486
+ return result.scheduledTask;
487
487
  }
488
- async runRoutine(jobId) {
488
+ async runScheduledTask(scheduledTaskId) {
489
489
  const result = await this.client.request({
490
- type: 'routines.jobs.run',
491
- jobId,
490
+ type: 'scheduledTasks.run',
491
+ scheduledTaskId,
492
492
  });
493
- return result.job;
493
+ return result.scheduledTask;
494
494
  }
495
- async removeRoutine(jobId) {
495
+ async removeScheduledTask(scheduledTaskId) {
496
496
  const result = await this.client.request({
497
- type: 'routines.jobs.remove',
498
- jobId,
497
+ type: 'scheduledTasks.remove',
498
+ scheduledTaskId,
499
499
  });
500
500
  return result.ok;
501
501
  }
502
- async tickRoutines() {
503
- const result = await this.client.request({ type: 'routines.tick' });
502
+ async tickScheduledTasks() {
503
+ const result = await this.client.request({ type: 'scheduledTasks.tick' });
504
504
  return result.executed;
505
505
  }
506
- async judgeCompletion(taskTitle, taskDescription, responseText) {
507
- return await this.client.request({
508
- type: 'judge.completion',
509
- taskTitle,
510
- taskDescription,
511
- responseText,
512
- });
513
- }
514
506
  async generateTitle(description) {
515
507
  return await this.client.request({
516
508
  type: 'title.generate',
@@ -527,4 +519,51 @@ export class HermesWorkerAdapter {
527
519
  settings: options?.settings,
528
520
  });
529
521
  }
522
+ async getGoalStatus(sessionId) {
523
+ const result = await this.client.request({
524
+ type: 'goal.status',
525
+ sessionId,
526
+ });
527
+ return result.goal;
528
+ }
529
+ async setGoal(sessionId, goal, options) {
530
+ const result = await this.client.request({
531
+ type: 'goal.set',
532
+ sessionId,
533
+ goal,
534
+ maxTurns: options?.maxTurns,
535
+ });
536
+ if (!result.goal)
537
+ throw new Error('Hermes did not return goal state');
538
+ return result.goal;
539
+ }
540
+ async pauseGoal(sessionId, reason) {
541
+ const result = await this.client.request({
542
+ type: 'goal.pause',
543
+ sessionId,
544
+ reason,
545
+ });
546
+ return result.goal;
547
+ }
548
+ async resumeGoal(sessionId) {
549
+ const result = await this.client.request({
550
+ type: 'goal.resume',
551
+ sessionId,
552
+ });
553
+ return result.goal;
554
+ }
555
+ async clearGoal(sessionId) {
556
+ const result = await this.client.request({
557
+ type: 'goal.clear',
558
+ sessionId,
559
+ });
560
+ return result.cleared;
561
+ }
562
+ async evaluateGoal(sessionId, responseText) {
563
+ return await this.client.request({
564
+ type: 'goal.evaluate',
565
+ sessionId,
566
+ responseText,
567
+ });
568
+ }
530
569
  }
@@ -1,4 +1,4 @@
1
- import type { AgentRunSettings, CompactResult, ContextUsage, Routine, RoutineInput, SessionMetadata, TaskMessage } from '../../shared/types.js';
1
+ import type { AgentRunSettings, CompactResult, ContextUsage, GoalDecision, GoalStateSnapshot, ScheduledTask, ScheduledTaskInput, SessionMetadata, TaskMessage } from '../../shared/types.js';
2
2
  export type { AgentRunSettings, ContextUsage };
3
3
  export interface AgentRunOptions {
4
4
  systemMessage?: string;
@@ -29,10 +29,6 @@ export interface AgentAdapter {
29
29
  healthCheck(): Promise<boolean>;
30
30
  getMessages(sessionId: string, taskId: string): Promise<TaskMessage[]>;
31
31
  getSessionMetadata(sessionId: string): Promise<SessionMetadata | null>;
32
- judgeCompletion(taskTitle: string, taskDescription: string | null, responseText: string): Promise<{
33
- done: boolean;
34
- reason: string;
35
- }>;
36
32
  generateTitle(description: string): Promise<{
37
33
  title: string;
38
34
  }>;
@@ -42,13 +38,21 @@ export interface AgentAdapter {
42
38
  systemMessage?: string;
43
39
  settings?: AgentRunSettings;
44
40
  }): Promise<CompactResult>;
45
- listRoutines(includeDisabled?: boolean): Promise<Routine[]>;
46
- getRoutine(jobId: string): Promise<Routine | null>;
47
- createRoutine(input: RoutineInput): Promise<Routine>;
48
- updateRoutine(jobId: string, updates: Partial<RoutineInput>): Promise<Routine | null>;
49
- pauseRoutine(jobId: string, reason?: string): Promise<Routine | null>;
50
- resumeRoutine(jobId: string): Promise<Routine | null>;
51
- runRoutine(jobId: string): Promise<Routine | null>;
52
- removeRoutine(jobId: string): Promise<boolean>;
53
- tickRoutines(): Promise<number>;
41
+ getGoalStatus(sessionId: string): Promise<GoalStateSnapshot | null>;
42
+ setGoal(sessionId: string, goal: string, options?: {
43
+ maxTurns?: number | null;
44
+ }): Promise<GoalStateSnapshot>;
45
+ pauseGoal(sessionId: string, reason?: string): Promise<GoalStateSnapshot | null>;
46
+ resumeGoal(sessionId: string): Promise<GoalStateSnapshot | null>;
47
+ clearGoal(sessionId: string): Promise<boolean>;
48
+ evaluateGoal(sessionId: string, responseText: string): Promise<GoalDecision>;
49
+ listScheduledTasks(includeDisabled?: boolean): Promise<ScheduledTask[]>;
50
+ getScheduledTask(scheduledTaskId: string): Promise<ScheduledTask | null>;
51
+ createScheduledTask(input: ScheduledTaskInput): Promise<ScheduledTask>;
52
+ updateScheduledTask(scheduledTaskId: string, updates: Partial<ScheduledTaskInput>): Promise<ScheduledTask | null>;
53
+ pauseScheduledTask(scheduledTaskId: string, reason?: string): Promise<ScheduledTask | null>;
54
+ resumeScheduledTask(scheduledTaskId: string): Promise<ScheduledTask | null>;
55
+ runScheduledTask(scheduledTaskId: string): Promise<ScheduledTask | null>;
56
+ removeScheduledTask(scheduledTaskId: string): Promise<boolean>;
57
+ tickScheduledTasks(): Promise<number>;
54
58
  }
@@ -1,4 +1,4 @@
1
- import type { AgentDefaults, AgentModelsResponse, Routine, RoutineInput, SessionMetadata, TaskMessage, ContextUsage } from '../../shared/types.js';
1
+ import type { AgentDefaults, AgentModelsResponse, GoalDecision, GoalStateSnapshot, ScheduledTask, ScheduledTaskInput, SessionMetadata, TaskMessage, ContextUsage } from '../../shared/types.js';
2
2
  import type { AgentRunSettings } from './types.js';
3
3
  export type WorkerRequest = {
4
4
  id: string;
@@ -17,39 +17,39 @@ export type WorkerRequest = {
17
17
  type: 'models.list';
18
18
  } | {
19
19
  id: string;
20
- type: 'routines.jobs.list';
20
+ type: 'scheduledTasks.list';
21
21
  includeDisabled?: boolean;
22
22
  } | {
23
23
  id: string;
24
- type: 'routines.jobs.get';
25
- jobId: string;
24
+ type: 'scheduledTasks.get';
25
+ scheduledTaskId: string;
26
26
  } | {
27
27
  id: string;
28
- type: 'routines.jobs.create';
29
- } & RoutineInput | {
28
+ type: 'scheduledTasks.create';
29
+ } & ScheduledTaskInput | {
30
30
  id: string;
31
- type: 'routines.jobs.update';
32
- jobId: string;
33
- } & Partial<RoutineInput> | {
31
+ type: 'scheduledTasks.update';
32
+ scheduledTaskId: string;
33
+ } & Partial<ScheduledTaskInput> | {
34
34
  id: string;
35
- type: 'routines.jobs.pause';
36
- jobId: string;
35
+ type: 'scheduledTasks.pause';
36
+ scheduledTaskId: string;
37
37
  reason?: string;
38
38
  } | {
39
39
  id: string;
40
- type: 'routines.jobs.resume';
41
- jobId: string;
40
+ type: 'scheduledTasks.resume';
41
+ scheduledTaskId: string;
42
42
  } | {
43
43
  id: string;
44
- type: 'routines.jobs.run';
45
- jobId: string;
44
+ type: 'scheduledTasks.run';
45
+ scheduledTaskId: string;
46
46
  } | {
47
47
  id: string;
48
- type: 'routines.jobs.remove';
49
- jobId: string;
48
+ type: 'scheduledTasks.remove';
49
+ scheduledTaskId: string;
50
50
  } | {
51
51
  id: string;
52
- type: 'routines.tick';
52
+ type: 'scheduledTasks.tick';
53
53
  } | {
54
54
  id: string;
55
55
  type: 'session.messages.get';
@@ -59,6 +59,34 @@ export type WorkerRequest = {
59
59
  id: string;
60
60
  type: 'session.get';
61
61
  sessionId: string;
62
+ } | {
63
+ id: string;
64
+ type: 'goal.status';
65
+ sessionId: string;
66
+ } | {
67
+ id: string;
68
+ type: 'goal.set';
69
+ sessionId: string;
70
+ goal: string;
71
+ maxTurns?: number | null;
72
+ } | {
73
+ id: string;
74
+ type: 'goal.pause';
75
+ sessionId: string;
76
+ reason?: string;
77
+ } | {
78
+ id: string;
79
+ type: 'goal.resume';
80
+ sessionId: string;
81
+ } | {
82
+ id: string;
83
+ type: 'goal.clear';
84
+ sessionId: string;
85
+ } | {
86
+ id: string;
87
+ type: 'goal.evaluate';
88
+ sessionId: string;
89
+ responseText: string;
62
90
  } | {
63
91
  id: string;
64
92
  type: 'chat';
@@ -68,12 +96,6 @@ export type WorkerRequest = {
68
96
  settings: AgentRunSettings;
69
97
  taskId?: string;
70
98
  taskTitle?: string | null;
71
- } | {
72
- id: string;
73
- type: 'judge.completion';
74
- taskTitle: string;
75
- taskDescription?: string | null;
76
- responseText: string;
77
99
  } | {
78
100
  id: string;
79
101
  type: 'title.generate';
@@ -97,9 +119,9 @@ export type WorkerResult = {
97
119
  agentDir?: string | null;
98
120
  python?: string | null;
99
121
  } | AgentDefaults | AgentModelsResponse | {
100
- jobs: Routine[];
122
+ scheduledTasks: ScheduledTask[];
101
123
  } | {
102
- job: Routine | null;
124
+ scheduledTask: ScheduledTask | null;
103
125
  } | {
104
126
  executed: number;
105
127
  } | {
@@ -107,9 +129,10 @@ export type WorkerResult = {
107
129
  } | {
108
130
  session: SessionMetadata | null;
109
131
  } | {
110
- done: boolean;
111
- reason: string;
132
+ goal: GoalStateSnapshot | null;
112
133
  } | {
134
+ cleared: boolean;
135
+ } | GoalDecision | {
113
136
  title: string;
114
137
  } | {
115
138
  compressed: boolean;
@@ -3,7 +3,7 @@ import cors from 'cors';
3
3
  import { tasksRouter } from './routes/tasks.js';
4
4
  import { chatRouter } from './routes/chat.js';
5
5
  import { createAgentRouter, createTaskAgentSettingsRouter } from './routes/agent.js';
6
- import { createRoutinesRouter } from './routes/routines.js';
6
+ import { createScheduledTasksRouter } from './routes/scheduled-tasks.js';
7
7
  import { skillsRouter } from './routes/skills.js';
8
8
  import { filesRouter } from './routes/files.js';
9
9
  import { HermesWorkerAdapter } from './adapters/hermes-worker.js';
@@ -31,7 +31,7 @@ app.use('/api/tasks', tasksRouter);
31
31
  app.use('/api/tasks', createTaskAgentSettingsRouter(adapter));
32
32
  app.use('/api/tasks', chatRouter);
33
33
  app.use('/api/agent', createAgentRouter(adapter));
34
- app.use('/api/routines', createRoutinesRouter(adapter));
34
+ app.use('/api/scheduled-tasks', createScheduledTasksRouter(adapter));
35
35
  app.use('/api/skills', skillsRouter);
36
36
  app.use((error, _req, res, next) => {
37
37
  if (!res.headersSent && error && typeof error === 'object' && error.type === 'entity.too.large') {
@@ -1,16 +1,31 @@
1
1
  import type { Response } from 'express';
2
- import type { LiveChatRun, TaskRunState } from '../shared/types.js';
2
+ import type { GoalStateSnapshot, LiveChatRun, LiveChatRunStatus, TaskRunState } from '../shared/types.js';
3
3
  import type { StreamEvent } from './adapters/types.js';
4
4
  export type LiveChatEvent = StreamEvent | {
5
5
  type: 'snapshot';
6
6
  run: LiveChatRun;
7
7
  };
8
- export declare function startRun(taskId: string, sessionId: string, userContent: string): LiveChatRun;
8
+ export type RunStart = {
9
+ snapshot: LiveChatRun;
10
+ state: TaskRunState;
11
+ };
12
+ export declare function startRun(taskId: string, sessionId: string, userContent: string): RunStart;
13
+ export declare function startGoalRun(taskId: string, sessionId: string, goal?: GoalStateSnapshot | null): RunStart;
14
+ export declare function startCompactionRun(taskId: string, sessionId: string): RunStart;
15
+ export declare function appendUserMessage(taskId: string, content: string): void;
16
+ export declare function appendSystemMessage(taskId: string, content: string): void;
17
+ export declare function startAssistantMessage(taskId: string): void;
18
+ export declare function updateRunContext(taskId: string, context: LiveChatRun['context'], sessionId?: string): TaskRunState | undefined;
19
+ export declare function updateRunGoal(taskId: string, goal: GoalStateSnapshot | null): TaskRunState | undefined;
9
20
  export declare function applyEvent(taskId: string, event: StreamEvent): void;
10
21
  export declare function getRun(taskId: string): LiveChatRun | undefined;
11
22
  export declare function getRunContext(taskId: string): LiveChatRun['context'] | undefined;
12
23
  export declare function getRunStatus(taskId: string): TaskRunState | undefined;
13
24
  export declare function getRunStatuses(): TaskRunState[];
25
+ export declare function updateRunStatus(taskId: string, status: Extract<LiveChatRunStatus, 'done' | 'error'>, options?: {
26
+ context?: LiveChatRun['context'];
27
+ error?: string;
28
+ }): TaskRunState | undefined;
14
29
  export declare function subscribe(taskId: string, res: Response): void;
15
30
  export declare function sendSnapshot(res: Response, run: LiveChatRun): void;
16
31
  export declare function broadcast(taskId: string, event: LiveChatEvent): void;
@@ -11,6 +11,7 @@ function cloneRun(run) {
11
11
  ...message,
12
12
  tools: message.tools ? message.tools.map((tool) => ({ ...tool })) : undefined,
13
13
  })),
14
+ goal: run.goal ? { ...run.goal } : null,
14
15
  context: run.context ? { ...run.context } : null,
15
16
  };
16
17
  }
@@ -18,9 +19,11 @@ function runState(run) {
18
19
  return {
19
20
  taskId: run.taskId,
20
21
  runId: run.runId,
22
+ kind: run.kind,
21
23
  status: run.status,
22
24
  startedAt: run.startedAt,
23
25
  updatedAt: run.updatedAt,
26
+ goal: run.goal ? { ...run.goal } : null,
24
27
  };
25
28
  }
26
29
  function assistantMessage(run) {
@@ -87,40 +90,98 @@ function startKeepalive() {
87
90
  }
88
91
  }, KEEPALIVE_INTERVAL_MS);
89
92
  }
90
- export function startRun(taskId, sessionId, userContent) {
91
- const expiryTimer = expiryTimers.get(taskId);
92
- if (expiryTimer) {
93
- clearTimeout(expiryTimer);
93
+ function clearExpiry(taskId) {
94
+ const timer = expiryTimers.get(taskId);
95
+ if (timer) {
96
+ clearTimeout(timer);
94
97
  expiryTimers.delete(taskId);
95
98
  }
99
+ }
100
+ function storeRun(run) {
101
+ runs.set(run.taskId, run);
102
+ return { snapshot: cloneRun(run), state: runState(run) };
103
+ }
104
+ export function startRun(taskId, sessionId, userContent) {
105
+ clearExpiry(taskId);
96
106
  const now = Date.now();
97
- const run = {
107
+ return storeRun({
98
108
  taskId,
99
109
  runId: uuid(),
110
+ kind: 'chat',
100
111
  sessionId,
101
112
  status: 'streaming',
102
113
  startedAt: now,
103
114
  updatedAt: now,
104
115
  messages: [
105
- {
106
- id: uuid(),
107
- task_id: taskId,
108
- role: 'user',
109
- content: userContent,
110
- created_at: now,
111
- },
112
- {
113
- id: uuid(),
114
- task_id: taskId,
115
- role: 'assistant',
116
- content: '',
117
- created_at: now,
118
- tools: [],
119
- },
116
+ { id: uuid(), task_id: taskId, role: 'user', content: userContent, created_at: now },
117
+ { id: uuid(), task_id: taskId, role: 'assistant', content: '', created_at: now, tools: [] },
120
118
  ],
121
- };
122
- runs.set(taskId, run);
123
- return cloneRun(run);
119
+ });
120
+ }
121
+ export function startGoalRun(taskId, sessionId, goal) {
122
+ clearExpiry(taskId);
123
+ const now = Date.now();
124
+ return storeRun({
125
+ taskId,
126
+ runId: uuid(),
127
+ kind: 'goal',
128
+ sessionId,
129
+ status: 'streaming',
130
+ startedAt: now,
131
+ updatedAt: now,
132
+ messages: [],
133
+ goal: goal ? { ...goal } : null,
134
+ });
135
+ }
136
+ export function startCompactionRun(taskId, sessionId) {
137
+ clearExpiry(taskId);
138
+ const now = Date.now();
139
+ return storeRun({
140
+ taskId,
141
+ runId: uuid(),
142
+ kind: 'compact',
143
+ sessionId,
144
+ status: 'compacting',
145
+ startedAt: now,
146
+ updatedAt: now,
147
+ messages: [],
148
+ });
149
+ }
150
+ function appendMessage(taskId, role, content, extra) {
151
+ const run = runs.get(taskId);
152
+ if (!run)
153
+ return;
154
+ const now = Date.now();
155
+ run.messages.push({ id: uuid(), task_id: taskId, role, content, created_at: now, ...extra });
156
+ run.updatedAt = now;
157
+ }
158
+ export function appendUserMessage(taskId, content) {
159
+ appendMessage(taskId, 'user', content);
160
+ }
161
+ export function appendSystemMessage(taskId, content) {
162
+ appendMessage(taskId, 'system', content);
163
+ }
164
+ export function startAssistantMessage(taskId) {
165
+ appendMessage(taskId, 'assistant', '', { tools: [] });
166
+ }
167
+ export function updateRunContext(taskId, context, sessionId) {
168
+ const run = runs.get(taskId);
169
+ if (!run)
170
+ return undefined;
171
+ if (sessionId)
172
+ run.sessionId = sessionId;
173
+ if (context !== undefined)
174
+ run.context = context;
175
+ run.updatedAt = Date.now();
176
+ return runState(run);
177
+ }
178
+ export function updateRunGoal(taskId, goal) {
179
+ const run = runs.get(taskId);
180
+ if (!run)
181
+ return undefined;
182
+ run.goal = goal ? { ...goal } : null;
183
+ run.updatedAt = Date.now();
184
+ return runState(run);
124
185
  }
125
186
  export function applyEvent(taskId, event) {
126
187
  const run = runs.get(taskId);
@@ -173,6 +234,18 @@ export function getRunStatus(taskId) {
173
234
  export function getRunStatuses() {
174
235
  return Array.from(runs.values()).map(runState);
175
236
  }
237
+ export function updateRunStatus(taskId, status, options) {
238
+ const run = runs.get(taskId);
239
+ if (!run)
240
+ return undefined;
241
+ run.status = status;
242
+ run.updatedAt = Date.now();
243
+ if (options?.context !== undefined)
244
+ run.context = options.context;
245
+ if (options?.error)
246
+ run.error = options.error;
247
+ return runState(run);
248
+ }
176
249
  export function subscribe(taskId, res) {
177
250
  let taskSubscribers = subscribers.get(taskId);
178
251
  if (!taskSubscribers) {
@@ -204,9 +277,7 @@ export function broadcast(taskId, event) {
204
277
  export function finishRun(taskId, ttlMs, runId) {
205
278
  if (!runs.has(taskId))
206
279
  return;
207
- const expiryTimer = expiryTimers.get(taskId);
208
- if (expiryTimer)
209
- clearTimeout(expiryTimer);
280
+ clearExpiry(taskId);
210
281
  const timer = setTimeout(() => {
211
282
  if (runs.get(taskId)?.runId === runId)
212
283
  runs.delete(taskId);
@@ -1 +1 @@
1
- export declare const TASK_AGENT_SYSTEM_PROMPT = "<task_agent>\n <role>\n You are an autonomous task agent. A user has given you a task to accomplish.\n </role>\n\n <responsibilities>\n <responsibility name=\"understand\">\n Read the task carefully. Identify anything unclear, ambiguous, or underspecified.\n </responsibility>\n <responsibility name=\"clarify\">\n Before doing work, make sure you fully understand what the user wants. Ask focused clarifying questions about scope, constraints, expected outcomes, edge cases, or anything else you are uncertain about. Do not assume when the uncertainty matters. The user is available to answer. Keep asking until you are confident you understand the task correctly.\n </responsibility>\n <responsibility name=\"execute\">\n Once you and the user are aligned, choose the best execution strategy. Do the work yourself in this session if it is straightforward. Create a child session if you need a dedicated sub-agent for complex sub-work. Set up a cron job when the work is recurring, periodic, routine, or better handled as durable batches over time. You have full autonomy to use the tools and approach that best accomplish the task.\n </responsibility>\n </responsibilities>\n\n <guidelines>\n <guideline>Understand first, act second. Do not start executing until you are confident you know what the user wants.</guideline>\n <guideline>When clarifying, ask focused questions rather than a long wall of questions. A natural back-and-forth conversation is ideal.</guideline>\n <guideline>When the user asks for a cron job, schedule, routine, recurring task, monitor, daily/weekly task, or similar repeated work, default to a Hermes cron job using the available cronjob tooling. Do not use Linux cron, systemd timers, or host OS schedulers unless the user explicitly asks for them.</guideline>\n <guideline>For lead generation, prospecting, and large list processing, prefer a small sample or validation run first. If the user wants more than a small one-off result, prefer a cron job with a self-contained prompt, sensible batch size, output/checkpoint location, and schedule.</guideline>\n <guideline>Keep the user informed of meaningful progress in your responses.</guideline>\n <guideline>You have project-specific skills under the \"minions\" category in your skills index. Before executing a task, check if any minions skill is relevant and load it \u2014 these encode proven workflows tailored to this system.</guideline>\n </guidelines>\n</task_agent>";
1
+ export declare const TASK_AGENT_SYSTEM_PROMPT = "<task_agent>\n <role>\n You are an autonomous task agent. A user has given you a task to accomplish.\n </role>\n\n <responsibilities>\n <responsibility name=\"understand\">\n Read the task carefully. Identify anything unclear, ambiguous, or underspecified.\n </responsibility>\n <responsibility name=\"clarify\">\n Before doing work, make sure you fully understand what the user wants. Ask focused clarifying questions about scope, constraints, expected outcomes, edge cases, or anything else you are uncertain about. Do not assume when the uncertainty matters. The user is available to answer. Keep asking until you are confident you understand the task correctly.\n </responsibility>\n <responsibility name=\"execute\">\n Once you and the user are aligned, choose the best execution strategy. Do the work yourself in this session if it is straightforward. Create a child session if you need a dedicated sub-agent for complex sub-work. Set up a cron job when the work is recurring, periodic, scheduled, or better handled as durable batches over time. You have full autonomy to use the tools and approach that best accomplish the task.\n </responsibility>\n </responsibilities>\n\n <guidelines>\n <guideline>Understand first, act second. Do not start executing until you are confident you know what the user wants.</guideline>\n <guideline>When clarifying, ask focused questions rather than a long wall of questions. A natural back-and-forth conversation is ideal.</guideline>\n <guideline>When the user asks for a cron job, schedule, scheduled task, recurring task, monitor, daily/weekly task, or similar repeated work, default to a Hermes cron job using the available cronjob tooling. Do not use Linux cron, systemd timers, or host OS schedulers unless the user explicitly asks for them.</guideline>\n <guideline>For lead generation, prospecting, and large list processing, prefer a small sample or validation run first. If the user wants more than a small one-off result, prefer a cron job with a self-contained prompt, sensible batch size, output/checkpoint location, and schedule.</guideline>\n <guideline>Keep the user informed of meaningful progress in your responses.</guideline>\n <guideline>You have project-specific skills under the \"minions\" category in your skills index. Before executing a task, check if any minions skill is relevant and load it \u2014 these encode proven workflows tailored to this system.</guideline>\n </guidelines>\n</task_agent>";
@@ -11,14 +11,14 @@ export const TASK_AGENT_SYSTEM_PROMPT = `<task_agent>
11
11
  Before doing work, make sure you fully understand what the user wants. Ask focused clarifying questions about scope, constraints, expected outcomes, edge cases, or anything else you are uncertain about. Do not assume when the uncertainty matters. The user is available to answer. Keep asking until you are confident you understand the task correctly.
12
12
  </responsibility>
13
13
  <responsibility name="execute">
14
- Once you and the user are aligned, choose the best execution strategy. Do the work yourself in this session if it is straightforward. Create a child session if you need a dedicated sub-agent for complex sub-work. Set up a cron job when the work is recurring, periodic, routine, or better handled as durable batches over time. You have full autonomy to use the tools and approach that best accomplish the task.
14
+ Once you and the user are aligned, choose the best execution strategy. Do the work yourself in this session if it is straightforward. Create a child session if you need a dedicated sub-agent for complex sub-work. Set up a cron job when the work is recurring, periodic, scheduled, or better handled as durable batches over time. You have full autonomy to use the tools and approach that best accomplish the task.
15
15
  </responsibility>
16
16
  </responsibilities>
17
17
 
18
18
  <guidelines>
19
19
  <guideline>Understand first, act second. Do not start executing until you are confident you know what the user wants.</guideline>
20
20
  <guideline>When clarifying, ask focused questions rather than a long wall of questions. A natural back-and-forth conversation is ideal.</guideline>
21
- <guideline>When the user asks for a cron job, schedule, routine, recurring task, monitor, daily/weekly task, or similar repeated work, default to a Hermes cron job using the available cronjob tooling. Do not use Linux cron, systemd timers, or host OS schedulers unless the user explicitly asks for them.</guideline>
21
+ <guideline>When the user asks for a cron job, schedule, scheduled task, recurring task, monitor, daily/weekly task, or similar repeated work, default to a Hermes cron job using the available cronjob tooling. Do not use Linux cron, systemd timers, or host OS schedulers unless the user explicitly asks for them.</guideline>
22
22
  <guideline>For lead generation, prospecting, and large list processing, prefer a small sample or validation run first. If the user wants more than a small one-off result, prefer a cron job with a self-contained prompt, sensible batch size, output/checkpoint location, and schedule.</guideline>
23
23
  <guideline>Keep the user informed of meaningful progress in your responses.</guideline>
24
24
  <guideline>You have project-specific skills under the "minions" category in your skills index. Before executing a task, check if any minions skill is relevant and load it — these encode proven workflows tailored to this system.</guideline>