agent-orchestrator-mcp-server 0.7.6 → 0.7.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-orchestrator-mcp-server",
3
- "version": "0.7.6",
3
+ "version": "0.7.9",
4
4
  "description": "Local implementation of agent-orchestrator MCP server",
5
5
  "main": "build/index.js",
6
6
  "type": "module",
@@ -29,7 +29,7 @@
29
29
  "stage-publish": "npm version"
30
30
  },
31
31
  "dependencies": {
32
- "@modelcontextprotocol/sdk": "^1.26.0",
32
+ "@modelcontextprotocol/sdk": "^1.29.0",
33
33
  "zod": "^3.24.1"
34
34
  },
35
35
  "devDependencies": {
@@ -241,8 +241,8 @@ export function createIntegrationMockOrchestratorClient(initialMockData) {
241
241
  if (!session) {
242
242
  throw new Error(`API Error (404): Session not found`);
243
243
  }
244
- if (session.status !== 'needs_input') {
245
- throw new Error(`API Error (422): Session must be in needs_input state to sleep`);
244
+ if (session.status !== 'needs_input' && session.status !== 'running') {
245
+ throw new Error(`API Error (422): Session must be in needs_input or running state to sleep (current: ${session.status})`);
246
246
  }
247
247
  session.status = 'waiting';
248
248
  session.updated_at = new Date().toISOString();
@@ -633,7 +633,7 @@ export function createIntegrationMockOrchestratorClient(initialMockData) {
633
633
  return {
634
634
  id: 1,
635
635
  name: data.name,
636
- trigger_type: data.trigger_type,
636
+ trigger_type: data.trigger_type || 'schedule',
637
637
  status: data.status || 'enabled',
638
638
  agent_root_name: data.agent_root_name,
639
639
  prompt_template: data.prompt_template,
@@ -642,7 +642,7 @@ export function createIntegrationMockOrchestratorClient(initialMockData) {
642
642
  mcp_servers: data.mcp_servers || [],
643
643
  configuration: data.configuration || {},
644
644
  schedule_description: null,
645
- last_session_id: null,
645
+ last_session_id: data.last_session_id ?? null,
646
646
  last_triggered_at: null,
647
647
  last_polled_at: null,
648
648
  sessions_created_count: 0,
@@ -16,7 +16,7 @@ function buildToolDescription() {
16
16
  - **Claude Code \`ScheduleWakeup\` tool**: Does not integrate with AO's session lifecycle — it won't transition the session to sleeping/waiting state or create an AO trigger, so AO cannot track or manage the wake-up.
17
17
  - **Claude Code \`Monitor\` tool**: Same problem — it operates outside AO's session state management.
18
18
 
19
- This tool does both: it properly transitions the session to sleeping (waiting) state so AO can reclaim resources, AND creates a one-time AO trigger to resume the session at the specified time.
19
+ This tool creates a one-time AO wake-up trigger bound to the target session. The AO API atomically transitions the session to sleeping (waiting) state as part of creating the trigger, so AO can reclaim resources and the trigger is guaranteed to resume the correct session at the specified time.
20
20
 
21
21
  **Current server time:** ${utcNow} (UTC). Use this as your reference point when calculating wake-up times.
22
22
 
@@ -28,16 +28,15 @@ This tool does both: it properly transitions the session to sleeping (waiting) s
28
28
  - If you omit timezone, wake_at is treated as UTC.
29
29
 
30
30
  **Parameters:**
31
- - **session_id**: The session to wake up (must be in needs_input state)
31
+ - **session_id**: The session to wake up. Works from either \`needs_input\` or \`running\` state — if you call this tool from within your own currently-running session, the sleep transition is recorded and takes effect after the current turn ends.
32
32
  - **wake_at**: ISO 8601 datetime without offset for when to wake up (e.g., "2026-04-15T14:30:00")
33
33
  - **timezone**: IANA timezone for interpreting wake_at (default: "UTC", e.g., "America/New_York")
34
34
  - **prompt**: The prompt to send when waking up the session
35
35
 
36
36
  **What happens:**
37
- 1. Validates the session is in needs_input state
38
- 2. Puts the session to sleep (waiting status)
39
- 3. Creates a one-time schedule trigger that fires at the specified time
40
- 4. The trigger resumes the session with the provided prompt`;
37
+ 1. Creates a one-time schedule trigger bound to this session that fires at the specified time.
38
+ 2. As a side effect of creating the trigger, the AO API transitions the session to sleeping (waiting) status — immediately if currently \`needs_input\`, or after the current turn ends if currently \`running\`.
39
+ 3. At the scheduled time, the trigger resumes the session with the provided prompt.`;
41
40
  }
42
41
  export function wakeMeUpLaterTool(_server, clientFactory) {
43
42
  return {
@@ -48,7 +47,7 @@ export function wakeMeUpLaterTool(_server, clientFactory) {
48
47
  properties: {
49
48
  session_id: {
50
49
  oneOf: [{ type: 'string' }, { type: 'number' }],
51
- description: 'Session ID (numeric) or slug (string). Must be in needs_input state.',
50
+ description: 'Session ID (numeric) or slug (string). Accepts sessions in needs_input or running state — from a running session, the sleep takes effect after the current turn ends.',
52
51
  },
53
52
  wake_at: {
54
53
  type: 'string',
@@ -83,30 +82,49 @@ export function wakeMeUpLaterTool(_server, clientFactory) {
83
82
  };
84
83
  }
85
84
  const session = await client.getSession(session_id);
86
- if (session.status !== 'needs_input') {
85
+ // Reject states the Rails API can't auto-sleep from. `needs_input`
86
+ // immediate sleep; `running` → deferred sleep via pending_sleep metadata;
87
+ // `waiting` → already dormant, trigger fires normally. Anything else
88
+ // (failed, archived) would silently no-op the auto-sleep and leave the
89
+ // caller with a trigger targeting a session that can't be woken.
90
+ const WAKEABLE_STATUSES = ['needs_input', 'running', 'waiting'];
91
+ if (!WAKEABLE_STATUSES.includes(session.status)) {
87
92
  return {
88
93
  content: [
89
94
  {
90
95
  type: 'text',
91
- text: `Error: Session must be in "needs_input" state to sleep (current: "${session.status}"). Only idle sessions can be scheduled for a delayed wake-up.`,
96
+ text: `Error: Session ${session.id} is in "${session.status}" state and cannot be scheduled for wake-up. Only sessions in ${WAKEABLE_STATUSES.join(', ')} can be woken up.`,
92
97
  },
93
98
  ],
94
99
  isError: true,
95
100
  };
96
101
  }
97
- const sleepingSession = await client.sleepSession(session_id);
102
+ // The Rails Trigger model requires agent_root_name, but for per-session
103
+ // wake-up triggers (reuse_session + last_session_id + one-time schedule)
104
+ // the value is never used to spawn a session — the target session is
105
+ // always reused. Prefer the canonical metadata value. The agent_type
106
+ // fallback is a best-effort for pre-migration sessions without an
107
+ // agent_root_key; if agent_type isn't a registered agent root, the
108
+ // createTrigger call will fail loudly with a 422 rather than proceed
109
+ // with a bad value — which is what we want.
110
+ const agentRootName = session.metadata?.agent_root_key || session.agent_type;
98
111
  let trigger;
99
112
  try {
100
113
  trigger = await client.createTrigger({
101
- name: `Wake session #${sleepingSession.id} at ${wake_at}`,
102
- trigger_type: 'schedule',
103
- agent_root_name: session.agent_type,
114
+ name: `Wake session #${session.id} at ${wake_at}`,
115
+ agent_root_name: agentRootName,
104
116
  prompt_template: prompt,
105
117
  reuse_session: true,
106
- configuration: {
107
- scheduled_at: wake_at,
108
- timezone,
109
- },
118
+ last_session_id: session.id,
119
+ trigger_conditions_attributes: [
120
+ {
121
+ condition_type: 'schedule',
122
+ configuration: {
123
+ scheduled_at: wake_at,
124
+ timezone,
125
+ },
126
+ },
127
+ ],
110
128
  });
111
129
  }
112
130
  catch (triggerError) {
@@ -114,28 +132,21 @@ export function wakeMeUpLaterTool(_server, clientFactory) {
114
132
  content: [
115
133
  {
116
134
  type: 'text',
117
- text: `Error: Session ${sleepingSession.id} was put to sleep (waiting status) but trigger creation failed: ${triggerError instanceof Error ? triggerError.message : 'Unknown error'}. The session is now in "waiting" state and needs manual intervention (use action_session with "restart" or "follow_up" to recover).`,
135
+ text: `Error: Trigger creation failed: ${triggerError instanceof Error ? triggerError.message : 'Unknown error'}. The session is still in its original state no changes were made.`,
118
136
  },
119
137
  ],
120
138
  isError: true,
121
139
  };
122
140
  }
123
- await client.updateSession(session_id, {
124
- custom_metadata: {
125
- ...session.custom_metadata,
126
- wake_trigger_id: trigger.id,
127
- },
128
- });
129
141
  const lines = [
130
142
  '## Wake-Up Scheduled Successfully',
131
143
  '',
132
- `- **Session ID:** ${sleepingSession.id}`,
133
- `- **Session Status:** ${sleepingSession.status}`,
144
+ `- **Session ID:** ${session.id}`,
134
145
  `- **Wake At:** ${wake_at} (${timezone})`,
135
146
  `- **Trigger ID:** ${trigger.id}`,
136
147
  `- **Trigger Name:** ${trigger.name}`,
137
148
  '',
138
- '**You must end your conversation turn now.** The session is sleeping and will be automatically resumed at the scheduled time with the provided prompt.',
149
+ '**You must end your conversation turn now.** The session will be automatically transitioned to waiting (immediately if currently needs_input; after the current turn ends if currently running) and resumed at the scheduled time with the provided prompt.',
139
150
  '',
140
151
  '⚠️ **Warning:** If you do not end your conversation turn, the session may still be running when the scheduled wake-up fires. A wake-up cannot be delivered to a session that is not in a wakeable (sleeping/waiting) state — it will be silently dropped, and you will never receive it.',
141
152
  ];
package/shared/types.d.ts CHANGED
@@ -251,9 +251,13 @@ export interface TriggerChannelsResponse {
251
251
  num_members: number;
252
252
  }>;
253
253
  }
254
+ export interface TriggerConditionAttributes {
255
+ condition_type: 'slack' | 'schedule' | 'ao_event';
256
+ configuration: Record<string, unknown>;
257
+ }
254
258
  export interface CreateTriggerRequest {
255
259
  name: string;
256
- trigger_type: TriggerType;
260
+ trigger_type?: TriggerType;
257
261
  agent_root_name: string;
258
262
  prompt_template: string;
259
263
  status?: TriggerStatus;
@@ -261,6 +265,8 @@ export interface CreateTriggerRequest {
261
265
  reuse_session?: boolean;
262
266
  mcp_servers?: string[];
263
267
  configuration?: Record<string, unknown>;
268
+ last_session_id?: number;
269
+ trigger_conditions_attributes?: TriggerConditionAttributes[];
264
270
  }
265
271
  export interface UpdateTriggerRequest {
266
272
  name?: string;