@triflux/remote 10.1.0 → 10.26.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/hub/pipe.mjs +239 -121
- package/hub/public/dashboard.html +61 -0
- package/hub/server.mjs +2179 -709
- package/hub/store-adapter.mjs +59 -26
- package/hub/store.mjs +356 -153
- package/hub/team/agent-map.json +26 -7
- package/hub/team/ansi.mjs +245 -146
- package/hub/team/backend.mjs +78 -17
- package/hub/team/build-worker-prompt.mjs +73 -0
- package/hub/team/check-mcp-hub.mjs +49 -0
- package/hub/team/claude-daemon-control.mjs +1130 -0
- package/hub/team/claude-native-bridge.mjs +1011 -0
- package/hub/team/claude-session-projection.mjs +74 -0
- package/hub/team/cli/commands/attach.mjs +57 -37
- package/hub/team/cli/commands/control.mjs +29 -8
- package/hub/team/cli/commands/debug.mjs +95 -74
- package/hub/team/cli/commands/focus.mjs +80 -53
- package/hub/team/cli/commands/interrupt.mjs +18 -6
- package/hub/team/cli/commands/kill.mjs +16 -5
- package/hub/team/cli/commands/list.mjs +31 -24
- package/hub/team/cli/commands/send.mjs +19 -6
- package/hub/team/cli/commands/start/index.mjs +151 -33
- package/hub/team/cli/commands/start/parse-args.mjs +97 -13
- package/hub/team/cli/commands/start/start-headless.mjs +155 -37
- package/hub/team/cli/commands/start/start-in-process.mjs +50 -40
- package/hub/team/cli/commands/start/start-mux.mjs +122 -73
- package/hub/team/cli/commands/start/start-wt.mjs +86 -69
- package/hub/team/cli/commands/status.mjs +43 -14
- package/hub/team/cli/commands/stop.mjs +11 -4
- package/hub/team/cli/commands/task.mjs +8 -3
- package/hub/team/cli/commands/tasks.mjs +13 -13
- package/hub/team/cli/help.mjs +1 -1
- package/hub/team/cli/index.mjs +2 -2
- package/hub/team/cli/manifest.mjs +38 -8
- package/hub/team/cli/render.mjs +52 -30
- package/hub/team/cli/services/attach-fallback.mjs +74 -54
- package/hub/team/cli/services/hub-client.mjs +44 -16
- package/hub/team/cli/services/member-selector.mjs +37 -30
- package/hub/team/cli/services/native-control.mjs +144 -116
- package/hub/team/cli/services/runtime-mode.mjs +61 -4
- package/hub/team/cli/services/state-store.mjs +66 -9
- package/hub/team/cli/services/task-model.mjs +40 -30
- package/hub/team/codex-review.mjs +521 -0
- package/hub/team/conductor-mesh-bridge.mjs +25 -24
- package/hub/team/conductor-registry.mjs +121 -0
- package/hub/team/conductor.mjs +1379 -671
- package/hub/team/consensus-meta.mjs +176 -0
- package/hub/team/dashboard-anchor.mjs +4 -5
- package/hub/team/dashboard-layout.mjs +3 -1
- package/hub/team/dashboard-open.mjs +20 -118
- package/hub/team/dashboard.mjs +76 -28
- package/hub/team/event-log.mjs +18 -10
- package/hub/team/execution-mode.mjs +256 -0
- package/hub/team/extract-completion-payload.mjs +110 -0
- package/hub/team/git-preflight.mjs +286 -0
- package/hub/team/handoff.mjs +49 -18
- package/hub/team/headless-bridge-session.mjs +17 -0
- package/hub/team/headless.mjs +2213 -1156
- package/hub/team/health-probe.mjs +232 -69
- package/hub/team/interactive-native-launcher.mjs +106 -0
- package/hub/team/interactive-native-worker.mjs +80 -0
- package/hub/team/interactive-tui-transport.mjs +465 -0
- package/hub/team/launcher-template.mjs +49 -17
- package/hub/team/lead-control.mjs +91 -4
- package/hub/team/mcp-selector.mjs +145 -0
- package/hub/team/native-supervisor.mjs +90 -26
- package/hub/team/native.mjs +120 -42
- package/hub/team/nativeProxy.mjs +184 -113
- package/hub/team/notify.mjs +147 -78
- package/hub/team/orchestrator.mjs +173 -161
- package/hub/team/pane.mjs +43 -20
- package/hub/team/process-cleanup.mjs +69 -25
- package/hub/team/psmux.mjs +1022 -281
- package/hub/team/recovery-store.mjs +149 -0
- package/hub/team/remote-probe.mjs +68 -52
- package/hub/team/remote-session.mjs +131 -59
- package/hub/team/remote-watcher.mjs +61 -33
- package/hub/team/retry-state-machine.mjs +336 -0
- package/hub/team/routing.mjs +51 -25
- package/hub/team/runtime-strategy.mjs +200 -0
- package/hub/team/schemas/worker-completion.json +39 -0
- package/hub/team/sentinel-capture.mjs +127 -0
- package/hub/team/session-sync.mjs +153 -6
- package/hub/team/session.mjs +574 -611
- package/hub/team/shared.mjs +13 -13
- package/hub/team/staleState.mjs +72 -30
- package/hub/team/swarm-cli.mjs +390 -0
- package/hub/team/swarm-hypervisor.mjs +1544 -193
- package/hub/team/swarm-intent.mjs +216 -0
- package/hub/team/swarm-locks.mjs +140 -25
- package/hub/team/swarm-planner.mjs +121 -21
- package/hub/team/swarm-preflight.mjs +319 -0
- package/hub/team/swarm-reconciler.mjs +128 -23
- package/hub/team/synapse-cli.mjs +458 -0
- package/hub/team/synapse-http.mjs +60 -0
- package/hub/team/synapse-registry.mjs +329 -0
- package/hub/team/terminal-opener.mjs +216 -0
- package/hub/team/tui-core.mjs +292 -0
- package/hub/team/tui-lite.mjs +237 -148
- package/hub/team/tui-remote-adapter.mjs +18 -34
- package/hub/team/tui-synapse.mjs +223 -0
- package/hub/team/tui-viewer.mjs +108 -48
- package/hub/team/tui-widgets.mjs +262 -0
- package/hub/team/tui.mjs +931 -439
- package/hub/team/worker-completion-validator.mjs +84 -0
- package/hub/team/worker-sandbox.mjs +97 -0
- package/hub/team/worker-signal.mjs +263 -0
- package/hub/team/worker-signal.types.d.ts +52 -0
- package/hub/team/worktree-lifecycle.mjs +517 -63
- package/hub/team/wt-manager.mjs +297 -26
- package/hub/tools.mjs +477 -252
- package/hub/tray.mjs +411 -368
- package/hub/workers/antigravity-route-worker.mjs +169 -0
- package/hub/workers/claude-worker.mjs +162 -118
- package/hub/workers/codex-app-server-worker.mjs +1015 -0
- package/hub/workers/codex-mcp.mjs +724 -507
- package/hub/workers/delegator-mcp.mjs +570 -499
- package/hub/workers/factory.mjs +103 -21
- package/hub/workers/gemini-worker.mjs +126 -284
- package/hub/workers/interface.mjs +24 -2
- package/hub/workers/lib/jsonrpc-stdio.mjs +463 -0
- package/hub/workers/worker-utils.mjs +23 -17
- package/package.json +4 -3
- package/scripts/lib/agent-json.mjs +27 -0
- package/scripts/lib/async.mjs +174 -0
- package/scripts/lib/claudemd-scanner.mjs +223 -0
- package/scripts/lib/cli-agy.mjs +62 -0
- package/scripts/lib/cli-claude.mjs +78 -0
- package/scripts/lib/cli-codex.mjs +199 -0
- package/scripts/lib/cli-gemini.mjs +37 -0
- package/scripts/lib/codex-recovery.sh +50 -0
- package/scripts/lib/context.mjs +67 -0
- package/scripts/lib/cross-review-utils.mjs +59 -0
- package/scripts/lib/doctor-env-checks.mjs +121 -0
- package/scripts/lib/dynamic-route-cli.mjs +107 -0
- package/scripts/lib/env-probe.mjs +269 -0
- package/scripts/lib/env.mjs +14 -0
- package/scripts/lib/gemini-profiles.mjs +119 -0
- package/scripts/lib/handoff.mjs +187 -0
- package/scripts/lib/hook-utils.mjs +16 -0
- package/scripts/lib/hub.mjs +48 -0
- package/scripts/lib/keyword-rules.mjs +195 -0
- package/scripts/lib/logger.mjs +105 -0
- package/scripts/lib/mcp-filter.mjs +883 -0
- package/scripts/lib/mcp-gateway-health-check.mjs +159 -0
- package/scripts/lib/mcp-gateway-servers.mjs +70 -0
- package/scripts/lib/mcp-gateway-wrapper-check.mjs +35 -0
- package/scripts/lib/mcp-guard-engine.mjs +2120 -0
- package/scripts/lib/mcp-health.mjs +773 -0
- package/scripts/lib/mcp-manifest.mjs +89 -0
- package/scripts/lib/mcp-server-catalog.mjs +355 -0
- package/scripts/lib/pid.mjs +63 -0
- package/scripts/lib/process-utils.mjs +26 -0
- package/scripts/lib/psmux-info.mjs +224 -0
- package/scripts/lib/quota.mjs +47 -0
- package/scripts/lib/remote-spawn-transfer.mjs +226 -0
- package/scripts/lib/skill-state.mjs +220 -0
- package/scripts/lib/skill-template.mjs +375 -0
- package/scripts/lib/team.mjs +75 -0
- package/scripts/lib/timeout.mjs +66 -0
- package/scripts/lib/tmp.mjs +26 -0
- package/scripts/lib/toml.mjs +113 -0
package/hub/tools.mjs
CHANGED
|
@@ -2,22 +2,20 @@
|
|
|
2
2
|
// register/status/publish/ask/poll/handoff/HITL + team proxy
|
|
3
3
|
// 모든 도구 응답: { ok: boolean, error?: { code, message }, data?: ... }
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { createPipeline, ensurePipelineTable } from "@triflux/core/hub/pipeline/index.mjs";
|
|
6
6
|
import {
|
|
7
|
-
ensurePipelineTable,
|
|
8
|
-
createPipeline,
|
|
9
|
-
} from '@triflux/core/hub/pipeline/index.mjs';
|
|
10
|
-
import {
|
|
11
|
-
readPipelineState,
|
|
12
7
|
initPipelineState,
|
|
13
8
|
listPipelineStates,
|
|
14
|
-
|
|
9
|
+
readPipelineState,
|
|
10
|
+
} from "@triflux/core/hub/pipeline/state.mjs";
|
|
11
|
+
import { sendInputToConductorSession } from "./team/conductor-registry.mjs";
|
|
12
|
+
import { getTeamBridge } from "@triflux/core/hub/team-bridge.mjs";
|
|
15
13
|
|
|
16
|
-
const TEAM_BRIDGE_NOT_REGISTERED =
|
|
14
|
+
const TEAM_BRIDGE_NOT_REGISTERED = "bridge_not_registered";
|
|
17
15
|
|
|
18
16
|
function getTeamBridgeMethod(methodName) {
|
|
19
17
|
const method = getTeamBridge()?.[methodName];
|
|
20
|
-
return typeof method ===
|
|
18
|
+
return typeof method === "function" ? method : null;
|
|
21
19
|
}
|
|
22
20
|
|
|
23
21
|
function teamInfoFallback(args = {}) {
|
|
@@ -86,7 +84,7 @@ function teamSendMessageFallback(args = {}) {
|
|
|
86
84
|
ok: true,
|
|
87
85
|
data: {
|
|
88
86
|
message_id: null,
|
|
89
|
-
recipient: args.to ??
|
|
87
|
+
recipient: args.to ?? "team-lead",
|
|
90
88
|
inbox_file: null,
|
|
91
89
|
queued_at: null,
|
|
92
90
|
unread_count: 0,
|
|
@@ -110,10 +108,13 @@ export function createTools(store, router, hitl, pipe = null) {
|
|
|
110
108
|
return async (args) => {
|
|
111
109
|
try {
|
|
112
110
|
const result = await fn(args);
|
|
113
|
-
return { content: [{ type:
|
|
111
|
+
return { content: [{ type: "text", text: JSON.stringify(result) }] };
|
|
114
112
|
} catch (e) {
|
|
115
113
|
const err = { ok: false, error: { code, message: e.message } };
|
|
116
|
-
return {
|
|
114
|
+
return {
|
|
115
|
+
content: [{ type: "text", text: JSON.stringify(err) }],
|
|
116
|
+
isError: true,
|
|
117
|
+
};
|
|
117
118
|
}
|
|
118
119
|
};
|
|
119
120
|
}
|
|
@@ -121,22 +122,40 @@ export function createTools(store, router, hitl, pipe = null) {
|
|
|
121
122
|
return [
|
|
122
123
|
// ── 1. register ──
|
|
123
124
|
{
|
|
124
|
-
name:
|
|
125
|
-
description:
|
|
125
|
+
name: "register",
|
|
126
|
+
description: "에이전트를 허브에 등록하고 lease를 발급받습니다",
|
|
126
127
|
inputSchema: {
|
|
127
|
-
type:
|
|
128
|
-
required: [
|
|
128
|
+
type: "object",
|
|
129
|
+
required: [
|
|
130
|
+
"agent_id",
|
|
131
|
+
"cli",
|
|
132
|
+
"capabilities",
|
|
133
|
+
"topics",
|
|
134
|
+
"heartbeat_ttl_ms",
|
|
135
|
+
],
|
|
129
136
|
properties: {
|
|
130
|
-
agent_id:
|
|
131
|
-
cli:
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
+
agent_id: { type: "string", pattern: "^[a-zA-Z0-9._:-]{3,64}$" },
|
|
138
|
+
cli: {
|
|
139
|
+
type: "string",
|
|
140
|
+
enum: ["codex", "antigravity", "gemini", "claude", "other"],
|
|
141
|
+
},
|
|
142
|
+
pid: { type: "integer", minimum: 1 },
|
|
143
|
+
capabilities: {
|
|
144
|
+
type: "array",
|
|
145
|
+
items: { type: "string" },
|
|
146
|
+
minItems: 1,
|
|
147
|
+
maxItems: 64,
|
|
148
|
+
},
|
|
149
|
+
topics: { type: "array", items: { type: "string" }, maxItems: 64 },
|
|
150
|
+
metadata: { type: "object" },
|
|
151
|
+
heartbeat_ttl_ms: {
|
|
152
|
+
type: "integer",
|
|
153
|
+
minimum: 10000,
|
|
154
|
+
maximum: 7200000,
|
|
155
|
+
},
|
|
137
156
|
},
|
|
138
157
|
},
|
|
139
|
-
handler: wrap(
|
|
158
|
+
handler: wrap("REGISTER_FAILED", (args) => {
|
|
140
159
|
const data = router.registerAgent(args);
|
|
141
160
|
return { ok: true, data };
|
|
142
161
|
}),
|
|
@@ -144,88 +163,128 @@ export function createTools(store, router, hitl, pipe = null) {
|
|
|
144
163
|
|
|
145
164
|
// ── 2. status ──
|
|
146
165
|
{
|
|
147
|
-
name:
|
|
148
|
-
description:
|
|
166
|
+
name: "status",
|
|
167
|
+
description: "허브, 에이전트, 큐, 트레이스 상태를 조회합니다",
|
|
149
168
|
inputSchema: {
|
|
150
|
-
type:
|
|
169
|
+
type: "object",
|
|
151
170
|
properties: {
|
|
152
|
-
scope:
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
171
|
+
scope: {
|
|
172
|
+
type: "string",
|
|
173
|
+
enum: ["hub", "agent", "queue", "trace"],
|
|
174
|
+
default: "hub",
|
|
175
|
+
},
|
|
176
|
+
agent_id: { type: "string" },
|
|
177
|
+
trace_id: { type: "string" },
|
|
178
|
+
include_metrics: { type: "boolean", default: true },
|
|
156
179
|
},
|
|
157
180
|
},
|
|
158
|
-
handler: wrap(
|
|
159
|
-
return router.getStatus(args.scope ||
|
|
181
|
+
handler: wrap("STATUS_FAILED", (args) => {
|
|
182
|
+
return router.getStatus(args.scope || "hub", args);
|
|
160
183
|
}),
|
|
161
184
|
},
|
|
162
185
|
|
|
163
186
|
// ── 3. publish ──
|
|
164
187
|
{
|
|
165
|
-
name:
|
|
166
|
-
description:
|
|
188
|
+
name: "publish",
|
|
189
|
+
description:
|
|
190
|
+
'이벤트 또는 응답 메시지를 발행합니다. to에 "topic:XXX" 지정 시 구독자 전체 fanout',
|
|
167
191
|
inputSchema: {
|
|
168
|
-
type:
|
|
169
|
-
required: [
|
|
192
|
+
type: "object",
|
|
193
|
+
required: ["from", "to", "topic", "payload"],
|
|
170
194
|
properties: {
|
|
171
|
-
from:
|
|
172
|
-
to:
|
|
173
|
-
topic:
|
|
174
|
-
priority:
|
|
175
|
-
ttl_ms:
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
195
|
+
from: { type: "string", pattern: "^[a-zA-Z0-9._:-]{3,64}$" },
|
|
196
|
+
to: { type: "string" },
|
|
197
|
+
topic: { type: "string", pattern: "^[a-zA-Z0-9._:-]+$" },
|
|
198
|
+
priority: { type: "integer", minimum: 1, maximum: 9, default: 5 },
|
|
199
|
+
ttl_ms: {
|
|
200
|
+
type: "integer",
|
|
201
|
+
minimum: 1000,
|
|
202
|
+
maximum: 86400000,
|
|
203
|
+
default: 300000,
|
|
204
|
+
},
|
|
205
|
+
payload: { type: "object" },
|
|
206
|
+
trace_id: { type: "string" },
|
|
207
|
+
correlation_id: { type: "string" },
|
|
179
208
|
},
|
|
180
209
|
},
|
|
181
|
-
handler: wrap(
|
|
210
|
+
handler: wrap("PUBLISH_FAILED", (args) => {
|
|
182
211
|
return router.handlePublish(args);
|
|
183
212
|
}),
|
|
184
213
|
},
|
|
185
214
|
|
|
186
215
|
// ── 4. ask ──
|
|
187
216
|
{
|
|
188
|
-
name:
|
|
189
|
-
description:
|
|
217
|
+
name: "ask",
|
|
218
|
+
description:
|
|
219
|
+
"다른 에이전트에게 질문합니다. await_response_ms > 0이면 짧은 폴링으로 응답 대기",
|
|
190
220
|
inputSchema: {
|
|
191
|
-
type:
|
|
192
|
-
required: [
|
|
221
|
+
type: "object",
|
|
222
|
+
required: ["from", "to", "topic", "question"],
|
|
193
223
|
properties: {
|
|
194
|
-
from:
|
|
195
|
-
to:
|
|
196
|
-
topic:
|
|
197
|
-
question:
|
|
198
|
-
context_refs:
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
224
|
+
from: { type: "string", pattern: "^[a-zA-Z0-9._:-]{3,64}$" },
|
|
225
|
+
to: { type: "string" },
|
|
226
|
+
topic: { type: "string", pattern: "^[a-zA-Z0-9._:-]+$" },
|
|
227
|
+
question: { type: "string", minLength: 1, maxLength: 20000 },
|
|
228
|
+
context_refs: {
|
|
229
|
+
type: "array",
|
|
230
|
+
items: { type: "string" },
|
|
231
|
+
maxItems: 32,
|
|
232
|
+
},
|
|
233
|
+
payload: { type: "object" },
|
|
234
|
+
priority: { type: "integer", minimum: 1, maximum: 9, default: 5 },
|
|
235
|
+
ttl_ms: {
|
|
236
|
+
type: "integer",
|
|
237
|
+
minimum: 1000,
|
|
238
|
+
maximum: 86400000,
|
|
239
|
+
default: 300000,
|
|
240
|
+
},
|
|
241
|
+
await_response_ms: {
|
|
242
|
+
type: "integer",
|
|
243
|
+
minimum: 0,
|
|
244
|
+
maximum: 30000,
|
|
245
|
+
default: 0,
|
|
246
|
+
},
|
|
247
|
+
trace_id: { type: "string" },
|
|
248
|
+
correlation_id: { type: "string" },
|
|
205
249
|
},
|
|
206
250
|
},
|
|
207
|
-
handler: wrap(
|
|
251
|
+
handler: wrap("ASK_FAILED", async (args) => {
|
|
208
252
|
return await router.handleAsk(args);
|
|
209
253
|
}),
|
|
210
254
|
},
|
|
211
255
|
|
|
212
256
|
// ── 5. poll_messages ──
|
|
213
257
|
{
|
|
214
|
-
name:
|
|
215
|
-
description:
|
|
258
|
+
name: "poll_messages",
|
|
259
|
+
description:
|
|
260
|
+
"Deprecated. poll_messages 대신 Named Pipe subscribe/publish 채널을 사용합니다",
|
|
216
261
|
inputSchema: {
|
|
217
|
-
type:
|
|
218
|
-
required: [
|
|
262
|
+
type: "object",
|
|
263
|
+
required: ["agent_id"],
|
|
219
264
|
properties: {
|
|
220
|
-
agent_id:
|
|
221
|
-
wait_ms:
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
265
|
+
agent_id: { type: "string", pattern: "^[a-zA-Z0-9._:-]{3,64}$" },
|
|
266
|
+
wait_ms: {
|
|
267
|
+
type: "integer",
|
|
268
|
+
minimum: 0,
|
|
269
|
+
maximum: 30000,
|
|
270
|
+
default: 1000,
|
|
271
|
+
},
|
|
272
|
+
max_messages: {
|
|
273
|
+
type: "integer",
|
|
274
|
+
minimum: 1,
|
|
275
|
+
maximum: 100,
|
|
276
|
+
default: 20,
|
|
277
|
+
},
|
|
278
|
+
include_topics: {
|
|
279
|
+
type: "array",
|
|
280
|
+
items: { type: "string" },
|
|
281
|
+
maxItems: 64,
|
|
282
|
+
},
|
|
283
|
+
ack_ids: { type: "array", items: { type: "string" }, maxItems: 100 },
|
|
284
|
+
auto_ack: { type: "boolean", default: false },
|
|
226
285
|
},
|
|
227
286
|
},
|
|
228
|
-
handler: wrap(
|
|
287
|
+
handler: wrap("POLL_DEPRECATED", async (args) => {
|
|
229
288
|
const replay = router.drainAgent(args.agent_id, {
|
|
230
289
|
max_messages: args.max_messages,
|
|
231
290
|
include_topics: args.include_topics,
|
|
@@ -237,13 +296,14 @@ export function createTools(store, router, hitl, pipe = null) {
|
|
|
237
296
|
return {
|
|
238
297
|
ok: false,
|
|
239
298
|
error: {
|
|
240
|
-
code:
|
|
241
|
-
message:
|
|
299
|
+
code: "POLL_DEPRECATED",
|
|
300
|
+
message:
|
|
301
|
+
"poll_messages는 deprecated 되었습니다. pipe subscribe/publish 채널을 사용하세요.",
|
|
242
302
|
},
|
|
243
303
|
data: {
|
|
244
304
|
pipe_path: pipe?.path || null,
|
|
245
|
-
delivery_mode:
|
|
246
|
-
protocol:
|
|
305
|
+
delivery_mode: "pipe_push",
|
|
306
|
+
protocol: "ndjson",
|
|
247
307
|
replay: {
|
|
248
308
|
messages: replay,
|
|
249
309
|
count: replay.length,
|
|
@@ -256,275 +316,394 @@ export function createTools(store, router, hitl, pipe = null) {
|
|
|
256
316
|
|
|
257
317
|
// ── 6. handoff ──
|
|
258
318
|
{
|
|
259
|
-
name:
|
|
260
|
-
description:
|
|
319
|
+
name: "handoff",
|
|
320
|
+
description:
|
|
321
|
+
"다른 에이전트에게 작업을 인계합니다. acceptance_criteria로 완료 기준 지정 가능",
|
|
261
322
|
inputSchema: {
|
|
262
|
-
type:
|
|
263
|
-
required: [
|
|
323
|
+
type: "object",
|
|
324
|
+
required: ["from", "to", "topic", "task"],
|
|
264
325
|
properties: {
|
|
265
|
-
from:
|
|
266
|
-
to:
|
|
267
|
-
topic:
|
|
268
|
-
task:
|
|
269
|
-
acceptance_criteria: {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
326
|
+
from: { type: "string", pattern: "^[a-zA-Z0-9._:-]{3,64}$" },
|
|
327
|
+
to: { type: "string" },
|
|
328
|
+
topic: { type: "string", pattern: "^[a-zA-Z0-9._:-]+$" },
|
|
329
|
+
task: { type: "string", minLength: 1, maxLength: 20000 },
|
|
330
|
+
acceptance_criteria: {
|
|
331
|
+
type: "array",
|
|
332
|
+
items: { type: "string" },
|
|
333
|
+
maxItems: 32,
|
|
334
|
+
},
|
|
335
|
+
context_refs: {
|
|
336
|
+
type: "array",
|
|
337
|
+
items: { type: "string" },
|
|
338
|
+
maxItems: 32,
|
|
339
|
+
},
|
|
340
|
+
priority: { type: "integer", minimum: 1, maximum: 9, default: 5 },
|
|
341
|
+
ttl_ms: {
|
|
342
|
+
type: "integer",
|
|
343
|
+
minimum: 1000,
|
|
344
|
+
maximum: 86400000,
|
|
345
|
+
default: 600000,
|
|
346
|
+
},
|
|
347
|
+
trace_id: { type: "string" },
|
|
348
|
+
correlation_id: { type: "string" },
|
|
275
349
|
},
|
|
276
350
|
},
|
|
277
|
-
handler: wrap(
|
|
351
|
+
handler: wrap("HANDOFF_FAILED", (args) => {
|
|
278
352
|
return router.handleHandoff(args);
|
|
279
353
|
}),
|
|
280
354
|
},
|
|
281
355
|
|
|
282
356
|
// ── 7. assign_async ──
|
|
283
357
|
{
|
|
284
|
-
name:
|
|
285
|
-
description:
|
|
358
|
+
name: "assign_async",
|
|
359
|
+
description:
|
|
360
|
+
"AWS CAO 스타일 비차단 assign job을 생성하고 워커에게 실시간 전달합니다",
|
|
286
361
|
inputSchema: {
|
|
287
|
-
type:
|
|
288
|
-
required: [
|
|
362
|
+
type: "object",
|
|
363
|
+
required: ["supervisor_agent", "worker_agent", "task"],
|
|
289
364
|
properties: {
|
|
290
|
-
supervisor_agent: {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
365
|
+
supervisor_agent: {
|
|
366
|
+
type: "string",
|
|
367
|
+
pattern: "^[a-zA-Z0-9._:-]{3,64}$",
|
|
368
|
+
},
|
|
369
|
+
worker_agent: { type: "string", pattern: "^[a-zA-Z0-9._:-]{3,64}$" },
|
|
370
|
+
topic: {
|
|
371
|
+
type: "string",
|
|
372
|
+
pattern: "^[a-zA-Z0-9._:-]+$",
|
|
373
|
+
default: "assign.job",
|
|
374
|
+
},
|
|
375
|
+
task: { type: "string", minLength: 1, maxLength: 20000 },
|
|
376
|
+
payload: { type: "object" },
|
|
377
|
+
priority: { type: "integer", minimum: 1, maximum: 9, default: 5 },
|
|
378
|
+
ttl_ms: {
|
|
379
|
+
type: "integer",
|
|
380
|
+
minimum: 1000,
|
|
381
|
+
maximum: 86400000,
|
|
382
|
+
default: 600000,
|
|
383
|
+
},
|
|
384
|
+
timeout_ms: {
|
|
385
|
+
type: "integer",
|
|
386
|
+
minimum: 1000,
|
|
387
|
+
maximum: 86400000,
|
|
388
|
+
default: 600000,
|
|
389
|
+
},
|
|
390
|
+
max_retries: { type: "integer", minimum: 0, maximum: 20, default: 0 },
|
|
391
|
+
trace_id: { type: "string" },
|
|
392
|
+
correlation_id: { type: "string" },
|
|
301
393
|
},
|
|
302
394
|
},
|
|
303
|
-
handler: wrap(
|
|
395
|
+
handler: wrap("ASSIGN_ASYNC_FAILED", (args) => {
|
|
304
396
|
return router.assignAsync(args);
|
|
305
397
|
}),
|
|
306
398
|
},
|
|
307
399
|
|
|
308
400
|
// ── 8. assign_result ──
|
|
309
401
|
{
|
|
310
|
-
name:
|
|
311
|
-
description:
|
|
402
|
+
name: "assign_result",
|
|
403
|
+
description:
|
|
404
|
+
"assign job의 진행/완료 결과를 보고합니다. completed + metadata.result 관례를 지원합니다",
|
|
312
405
|
inputSchema: {
|
|
313
|
-
type:
|
|
314
|
-
required: [
|
|
406
|
+
type: "object",
|
|
407
|
+
required: ["job_id", "status"],
|
|
315
408
|
properties: {
|
|
316
|
-
job_id: { type:
|
|
317
|
-
worker_agent: { type:
|
|
318
|
-
status: {
|
|
319
|
-
|
|
409
|
+
job_id: { type: "string", minLength: 1, maxLength: 128 },
|
|
410
|
+
worker_agent: { type: "string", pattern: "^[a-zA-Z0-9._:-]{3,64}$" },
|
|
411
|
+
status: {
|
|
412
|
+
type: "string",
|
|
413
|
+
enum: [
|
|
414
|
+
"queued",
|
|
415
|
+
"running",
|
|
416
|
+
"in_progress",
|
|
417
|
+
"completed",
|
|
418
|
+
"succeeded",
|
|
419
|
+
"success",
|
|
420
|
+
"failed",
|
|
421
|
+
"error",
|
|
422
|
+
"timed_out",
|
|
423
|
+
"timeout",
|
|
424
|
+
],
|
|
425
|
+
},
|
|
426
|
+
attempt: { type: "integer", minimum: 1 },
|
|
320
427
|
result: {},
|
|
321
428
|
error: {},
|
|
322
|
-
metadata: { type:
|
|
323
|
-
payload: { type:
|
|
429
|
+
metadata: { type: "object" },
|
|
430
|
+
payload: { type: "object" },
|
|
324
431
|
},
|
|
325
432
|
},
|
|
326
|
-
handler: wrap(
|
|
433
|
+
handler: wrap("ASSIGN_RESULT_FAILED", (args) => {
|
|
327
434
|
return router.reportAssignResult(args);
|
|
328
435
|
}),
|
|
329
436
|
},
|
|
330
437
|
|
|
331
438
|
// ── 9. assign_status ──
|
|
332
439
|
{
|
|
333
|
-
name:
|
|
334
|
-
description:
|
|
440
|
+
name: "assign_status",
|
|
441
|
+
description:
|
|
442
|
+
"assign job 단건 상태 또는 supervisor/worker/status 기준 목록을 조회합니다",
|
|
335
443
|
inputSchema: {
|
|
336
|
-
type:
|
|
444
|
+
type: "object",
|
|
337
445
|
properties: {
|
|
338
|
-
job_id: { type:
|
|
339
|
-
supervisor_agent: {
|
|
340
|
-
|
|
341
|
-
|
|
446
|
+
job_id: { type: "string", minLength: 1, maxLength: 128 },
|
|
447
|
+
supervisor_agent: {
|
|
448
|
+
type: "string",
|
|
449
|
+
pattern: "^[a-zA-Z0-9._:-]{3,64}$",
|
|
450
|
+
},
|
|
451
|
+
worker_agent: { type: "string", pattern: "^[a-zA-Z0-9._:-]{3,64}$" },
|
|
452
|
+
status: {
|
|
453
|
+
type: "string",
|
|
454
|
+
enum: ["queued", "running", "succeeded", "failed", "timed_out"],
|
|
455
|
+
},
|
|
342
456
|
statuses: {
|
|
343
|
-
type:
|
|
344
|
-
items: {
|
|
457
|
+
type: "array",
|
|
458
|
+
items: {
|
|
459
|
+
type: "string",
|
|
460
|
+
enum: ["queued", "running", "succeeded", "failed", "timed_out"],
|
|
461
|
+
},
|
|
345
462
|
maxItems: 8,
|
|
346
463
|
},
|
|
347
|
-
trace_id: { type:
|
|
348
|
-
correlation_id: { type:
|
|
349
|
-
limit: { type:
|
|
464
|
+
trace_id: { type: "string" },
|
|
465
|
+
correlation_id: { type: "string" },
|
|
466
|
+
limit: { type: "integer", minimum: 1, maximum: 100, default: 50 },
|
|
350
467
|
},
|
|
351
468
|
},
|
|
352
|
-
handler: wrap(
|
|
469
|
+
handler: wrap("ASSIGN_STATUS_FAILED", (args) => {
|
|
353
470
|
return router.getAssignStatus(args);
|
|
354
471
|
}),
|
|
355
472
|
},
|
|
356
473
|
|
|
357
474
|
// ── 10. request_human_input ──
|
|
358
475
|
{
|
|
359
|
-
name:
|
|
360
|
-
description:
|
|
476
|
+
name: "request_human_input",
|
|
477
|
+
description:
|
|
478
|
+
"사용자에게 입력을 요청합니다 (CAPTCHA, 승인, 자격증명, 선택, 텍스트)",
|
|
361
479
|
inputSchema: {
|
|
362
|
-
type:
|
|
363
|
-
required: [
|
|
480
|
+
type: "object",
|
|
481
|
+
required: [
|
|
482
|
+
"requester_agent",
|
|
483
|
+
"kind",
|
|
484
|
+
"prompt",
|
|
485
|
+
"requested_schema",
|
|
486
|
+
"deadline_ms",
|
|
487
|
+
"default_action",
|
|
488
|
+
],
|
|
364
489
|
properties: {
|
|
365
|
-
requester_agent:
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
490
|
+
requester_agent: {
|
|
491
|
+
type: "string",
|
|
492
|
+
pattern: "^[a-zA-Z0-9._:-]{3,64}$",
|
|
493
|
+
},
|
|
494
|
+
kind: {
|
|
495
|
+
type: "string",
|
|
496
|
+
enum: ["captcha", "approval", "credential", "choice", "text"],
|
|
497
|
+
},
|
|
498
|
+
prompt: { type: "string", minLength: 1, maxLength: 20000 },
|
|
499
|
+
requested_schema: { type: "object" },
|
|
500
|
+
deadline_ms: { type: "integer", minimum: 1000 },
|
|
501
|
+
default_action: {
|
|
502
|
+
type: "string",
|
|
503
|
+
enum: ["decline", "cancel", "timeout_continue"],
|
|
504
|
+
},
|
|
505
|
+
channel_preference: {
|
|
506
|
+
type: "string",
|
|
507
|
+
enum: ["terminal", "pipe", "file_polling"],
|
|
508
|
+
default: "terminal",
|
|
509
|
+
},
|
|
510
|
+
trace_id: { type: "string" },
|
|
511
|
+
correlation_id: { type: "string" },
|
|
374
512
|
},
|
|
375
513
|
},
|
|
376
|
-
handler: wrap(
|
|
514
|
+
handler: wrap("HITL_REQUEST_FAILED", (args) => {
|
|
377
515
|
return hitl.requestHumanInput(args);
|
|
378
516
|
}),
|
|
379
517
|
},
|
|
380
518
|
|
|
381
519
|
// ── 11. submit_human_input ──
|
|
382
520
|
{
|
|
383
|
-
name:
|
|
384
|
-
description:
|
|
521
|
+
name: "submit_human_input",
|
|
522
|
+
description: "사용자 입력 요청에 응답합니다 (accept, decline, cancel)",
|
|
385
523
|
inputSchema: {
|
|
386
|
-
type:
|
|
387
|
-
required: [
|
|
524
|
+
type: "object",
|
|
525
|
+
required: ["request_id", "action"],
|
|
388
526
|
properties: {
|
|
389
|
-
request_id:
|
|
390
|
-
action:
|
|
391
|
-
content:
|
|
392
|
-
submitted_by: { type:
|
|
527
|
+
request_id: { type: "string" },
|
|
528
|
+
action: { type: "string", enum: ["accept", "decline", "cancel"] },
|
|
529
|
+
content: { type: "object" },
|
|
530
|
+
submitted_by: { type: "string", default: "human" },
|
|
393
531
|
},
|
|
394
532
|
},
|
|
395
|
-
handler: wrap(
|
|
533
|
+
handler: wrap("HITL_SUBMIT_FAILED", (args) => {
|
|
396
534
|
return hitl.submitHumanInput(args);
|
|
397
535
|
}),
|
|
398
536
|
},
|
|
399
537
|
|
|
400
538
|
// ── 12. team_info ──
|
|
401
539
|
{
|
|
402
|
-
name:
|
|
403
|
-
description:
|
|
540
|
+
name: "team_info",
|
|
541
|
+
description: "Claude Native Teams 메타/멤버/경로 정보를 조회합니다",
|
|
404
542
|
inputSchema: {
|
|
405
|
-
type:
|
|
406
|
-
required: [
|
|
543
|
+
type: "object",
|
|
544
|
+
required: ["team_name"],
|
|
407
545
|
properties: {
|
|
408
|
-
team_name: {
|
|
409
|
-
|
|
410
|
-
|
|
546
|
+
team_name: {
|
|
547
|
+
type: "string",
|
|
548
|
+
minLength: 1,
|
|
549
|
+
maxLength: 128,
|
|
550
|
+
pattern: "^[a-z0-9][a-z0-9-]*$",
|
|
551
|
+
},
|
|
552
|
+
include_members: { type: "boolean", default: true },
|
|
553
|
+
include_paths: { type: "boolean", default: true },
|
|
411
554
|
},
|
|
412
555
|
},
|
|
413
|
-
handler: wrap(
|
|
414
|
-
const teamInfo = getTeamBridgeMethod(
|
|
556
|
+
handler: wrap("TEAM_INFO_FAILED", (args) => {
|
|
557
|
+
const teamInfo = getTeamBridgeMethod("teamInfo");
|
|
415
558
|
return teamInfo ? teamInfo(args) : teamInfoFallback(args);
|
|
416
559
|
}),
|
|
417
560
|
},
|
|
418
561
|
|
|
419
562
|
// ── 13. team_task_list ──
|
|
420
563
|
{
|
|
421
|
-
name:
|
|
422
|
-
description:
|
|
564
|
+
name: "team_task_list",
|
|
565
|
+
description:
|
|
566
|
+
"Claude Native Teams task 목록을 owner/status 조건으로 조회합니다. 실패 판정은 completed + metadata.result도 함께 확인해야 합니다",
|
|
423
567
|
inputSchema: {
|
|
424
|
-
type:
|
|
425
|
-
required: [
|
|
568
|
+
type: "object",
|
|
569
|
+
required: ["team_name"],
|
|
426
570
|
properties: {
|
|
427
|
-
team_name: { type:
|
|
428
|
-
owner: { type:
|
|
571
|
+
team_name: { type: "string", pattern: "^[a-z0-9][a-z0-9-]*$" },
|
|
572
|
+
owner: { type: "string" },
|
|
429
573
|
statuses: {
|
|
430
|
-
type:
|
|
431
|
-
items: {
|
|
574
|
+
type: "array",
|
|
575
|
+
items: {
|
|
576
|
+
type: "string",
|
|
577
|
+
enum: [
|
|
578
|
+
"pending",
|
|
579
|
+
"in_progress",
|
|
580
|
+
"completed",
|
|
581
|
+
"failed",
|
|
582
|
+
"deleted",
|
|
583
|
+
],
|
|
584
|
+
},
|
|
432
585
|
maxItems: 8,
|
|
433
586
|
},
|
|
434
|
-
include_internal: { type:
|
|
435
|
-
limit: { type:
|
|
587
|
+
include_internal: { type: "boolean", default: false },
|
|
588
|
+
limit: { type: "integer", minimum: 1, maximum: 1000, default: 200 },
|
|
436
589
|
},
|
|
437
590
|
},
|
|
438
|
-
handler: wrap(
|
|
439
|
-
const teamTaskList = getTeamBridgeMethod(
|
|
591
|
+
handler: wrap("TEAM_TASK_LIST_FAILED", (args) => {
|
|
592
|
+
const teamTaskList = getTeamBridgeMethod("teamTaskList");
|
|
440
593
|
return teamTaskList ? teamTaskList(args) : teamTaskListFallback(args);
|
|
441
594
|
}),
|
|
442
595
|
},
|
|
443
596
|
|
|
444
597
|
// ── 14. team_task_update ──
|
|
445
598
|
{
|
|
446
|
-
name:
|
|
447
|
-
description:
|
|
599
|
+
name: "team_task_update",
|
|
600
|
+
description:
|
|
601
|
+
'Claude Native Teams task를 claim/update 합니다. status: "failed" 입력은 completed + metadata.result="failed"로 정규화됩니다',
|
|
448
602
|
inputSchema: {
|
|
449
|
-
type:
|
|
450
|
-
required: [
|
|
603
|
+
type: "object",
|
|
604
|
+
required: ["team_name", "task_id"],
|
|
451
605
|
properties: {
|
|
452
|
-
team_name: { type:
|
|
453
|
-
task_id: { type:
|
|
454
|
-
claim: { type:
|
|
455
|
-
owner: { type:
|
|
456
|
-
status: {
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
606
|
+
team_name: { type: "string", pattern: "^[a-z0-9][a-z0-9-]*$" },
|
|
607
|
+
task_id: { type: "string", minLength: 1, maxLength: 64 },
|
|
608
|
+
claim: { type: "boolean", default: false },
|
|
609
|
+
owner: { type: "string" },
|
|
610
|
+
status: {
|
|
611
|
+
type: "string",
|
|
612
|
+
enum: ["pending", "in_progress", "completed", "failed", "deleted"],
|
|
613
|
+
},
|
|
614
|
+
subject: { type: "string" },
|
|
615
|
+
description: { type: "string" },
|
|
616
|
+
activeForm: { type: "string" },
|
|
617
|
+
add_blocks: { type: "array", items: { type: "string" } },
|
|
618
|
+
add_blocked_by: { type: "array", items: { type: "string" } },
|
|
619
|
+
metadata_patch: { type: "object" },
|
|
620
|
+
if_match_mtime_ms: { type: "number" },
|
|
621
|
+
actor: { type: "string" },
|
|
465
622
|
},
|
|
466
623
|
},
|
|
467
|
-
handler: wrap(
|
|
468
|
-
const teamTaskUpdate = getTeamBridgeMethod(
|
|
469
|
-
return teamTaskUpdate
|
|
624
|
+
handler: wrap("TEAM_TASK_UPDATE_FAILED", (args) => {
|
|
625
|
+
const teamTaskUpdate = getTeamBridgeMethod("teamTaskUpdate");
|
|
626
|
+
return teamTaskUpdate
|
|
627
|
+
? teamTaskUpdate(args)
|
|
628
|
+
: teamTaskUpdateFallback(args);
|
|
470
629
|
}),
|
|
471
630
|
},
|
|
472
631
|
|
|
473
632
|
// ── 15. team_send_message ──
|
|
474
633
|
{
|
|
475
|
-
name:
|
|
476
|
-
description:
|
|
634
|
+
name: "team_send_message",
|
|
635
|
+
description: "Claude Native Teams inbox에 메시지를 append 합니다",
|
|
477
636
|
inputSchema: {
|
|
478
|
-
type:
|
|
479
|
-
required: [
|
|
637
|
+
type: "object",
|
|
638
|
+
required: ["team_name", "from", "text"],
|
|
480
639
|
properties: {
|
|
481
|
-
team_name: { type:
|
|
482
|
-
from: { type:
|
|
483
|
-
to: { type:
|
|
484
|
-
text: { type:
|
|
485
|
-
summary: { type:
|
|
486
|
-
color: { type:
|
|
640
|
+
team_name: { type: "string", pattern: "^[a-z0-9][a-z0-9-]*$" },
|
|
641
|
+
from: { type: "string", minLength: 1, maxLength: 128 },
|
|
642
|
+
to: { type: "string", default: "team-lead" },
|
|
643
|
+
text: { type: "string", minLength: 1, maxLength: 200000 },
|
|
644
|
+
summary: { type: "string", maxLength: 1000 },
|
|
645
|
+
color: { type: "string", default: "blue" },
|
|
487
646
|
},
|
|
488
647
|
},
|
|
489
|
-
handler: wrap(
|
|
490
|
-
const teamSendMessage = getTeamBridgeMethod(
|
|
491
|
-
return teamSendMessage
|
|
648
|
+
handler: wrap("TEAM_SEND_MESSAGE_FAILED", (args) => {
|
|
649
|
+
const teamSendMessage = getTeamBridgeMethod("teamSendMessage");
|
|
650
|
+
return teamSendMessage
|
|
651
|
+
? teamSendMessage(args)
|
|
652
|
+
: teamSendMessageFallback(args);
|
|
492
653
|
}),
|
|
493
654
|
},
|
|
494
655
|
|
|
495
656
|
// ── 16. pipeline_state ──
|
|
496
657
|
{
|
|
497
|
-
name:
|
|
498
|
-
description:
|
|
658
|
+
name: "pipeline_state",
|
|
659
|
+
description: "파이프라인 상태를 조회합니다 (--thorough 모드)",
|
|
499
660
|
inputSchema: {
|
|
500
|
-
type:
|
|
501
|
-
required: [
|
|
661
|
+
type: "object",
|
|
662
|
+
required: ["team_name"],
|
|
502
663
|
properties: {
|
|
503
|
-
team_name: { type:
|
|
664
|
+
team_name: { type: "string", pattern: "^[a-z0-9][a-z0-9-]*$" },
|
|
504
665
|
},
|
|
505
666
|
},
|
|
506
|
-
handler: wrap(
|
|
667
|
+
handler: wrap("PIPELINE_STATE_FAILED", (args) => {
|
|
507
668
|
ensurePipelineTable(store.db);
|
|
508
669
|
const state = readPipelineState(store.db, args.team_name);
|
|
509
670
|
return state
|
|
510
671
|
? { ok: true, data: state }
|
|
511
|
-
: {
|
|
672
|
+
: {
|
|
673
|
+
ok: false,
|
|
674
|
+
error: {
|
|
675
|
+
code: "PIPELINE_NOT_FOUND",
|
|
676
|
+
message: `파이프라인 없음: ${args.team_name}`,
|
|
677
|
+
},
|
|
678
|
+
};
|
|
512
679
|
}),
|
|
513
680
|
},
|
|
514
681
|
|
|
515
682
|
// ── 17. pipeline_advance ──
|
|
516
683
|
{
|
|
517
|
-
name:
|
|
518
|
-
description:
|
|
684
|
+
name: "pipeline_advance",
|
|
685
|
+
description:
|
|
686
|
+
"파이프라인을 다음 단계로 전이합니다 (전이 규칙 + fix loop 바운딩 적용)",
|
|
519
687
|
inputSchema: {
|
|
520
|
-
type:
|
|
521
|
-
required: [
|
|
688
|
+
type: "object",
|
|
689
|
+
required: ["team_name", "phase"],
|
|
522
690
|
properties: {
|
|
523
|
-
team_name: { type:
|
|
524
|
-
phase: {
|
|
691
|
+
team_name: { type: "string", pattern: "^[a-z0-9][a-z0-9-]*$" },
|
|
692
|
+
phase: {
|
|
693
|
+
type: "string",
|
|
694
|
+
enum: [
|
|
695
|
+
"plan",
|
|
696
|
+
"prd",
|
|
697
|
+
"exec",
|
|
698
|
+
"verify",
|
|
699
|
+
"fix",
|
|
700
|
+
"complete",
|
|
701
|
+
"failed",
|
|
702
|
+
],
|
|
703
|
+
},
|
|
525
704
|
},
|
|
526
705
|
},
|
|
527
|
-
handler: wrap(
|
|
706
|
+
handler: wrap("PIPELINE_ADVANCE_FAILED", (args) => {
|
|
528
707
|
ensurePipelineTable(store.db);
|
|
529
708
|
const pipeline = createPipeline(store.db, args.team_name);
|
|
530
709
|
return pipeline.advance(args.phase);
|
|
@@ -533,18 +712,18 @@ export function createTools(store, router, hitl, pipe = null) {
|
|
|
533
712
|
|
|
534
713
|
// ── 18. pipeline_init ──
|
|
535
714
|
{
|
|
536
|
-
name:
|
|
537
|
-
description:
|
|
715
|
+
name: "pipeline_init",
|
|
716
|
+
description: "새 파이프라인을 초기화합니다 (기존 상태 덮어쓰기)",
|
|
538
717
|
inputSchema: {
|
|
539
|
-
type:
|
|
540
|
-
required: [
|
|
718
|
+
type: "object",
|
|
719
|
+
required: ["team_name"],
|
|
541
720
|
properties: {
|
|
542
|
-
team_name: { type:
|
|
543
|
-
fix_max: { type:
|
|
544
|
-
ralph_max: { type:
|
|
721
|
+
team_name: { type: "string", pattern: "^[a-z0-9][a-z0-9-]*$" },
|
|
722
|
+
fix_max: { type: "integer", minimum: 1, maximum: 20, default: 3 },
|
|
723
|
+
ralph_max: { type: "integer", minimum: 1, maximum: 100, default: 10 },
|
|
545
724
|
},
|
|
546
725
|
},
|
|
547
|
-
handler: wrap(
|
|
726
|
+
handler: wrap("PIPELINE_INIT_FAILED", (args) => {
|
|
548
727
|
ensurePipelineTable(store.db);
|
|
549
728
|
const state = initPipelineState(store.db, args.team_name, {
|
|
550
729
|
fix_max: args.fix_max,
|
|
@@ -556,21 +735,48 @@ export function createTools(store, router, hitl, pipe = null) {
|
|
|
556
735
|
|
|
557
736
|
// ── 19. pipeline_advance_gated (HITL 승인 게이트) ──
|
|
558
737
|
{
|
|
559
|
-
name:
|
|
560
|
-
description:
|
|
738
|
+
name: "pipeline_advance_gated",
|
|
739
|
+
description:
|
|
740
|
+
"HITL 승인 게이트가 포함된 파이프라인 전이. 지정 단계로의 전이 전 사용자 승인을 요청하고, 승인 후 전이를 실행합니다. deadline 초과 시 default_action에 따라 자동 처리됩니다.",
|
|
561
741
|
inputSchema: {
|
|
562
|
-
type:
|
|
563
|
-
required: [
|
|
742
|
+
type: "object",
|
|
743
|
+
required: ["team_name", "phase"],
|
|
564
744
|
properties: {
|
|
565
|
-
team_name: { type:
|
|
566
|
-
phase: {
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
745
|
+
team_name: { type: "string", pattern: "^[a-z0-9][a-z0-9-]*$" },
|
|
746
|
+
phase: {
|
|
747
|
+
type: "string",
|
|
748
|
+
enum: [
|
|
749
|
+
"plan",
|
|
750
|
+
"prd",
|
|
751
|
+
"exec",
|
|
752
|
+
"verify",
|
|
753
|
+
"fix",
|
|
754
|
+
"complete",
|
|
755
|
+
"failed",
|
|
756
|
+
],
|
|
757
|
+
},
|
|
758
|
+
prompt: {
|
|
759
|
+
type: "string",
|
|
760
|
+
description: "사용자에게 표시할 승인 요청 메시지",
|
|
761
|
+
},
|
|
762
|
+
deadline_ms: {
|
|
763
|
+
type: "integer",
|
|
764
|
+
minimum: 5000,
|
|
765
|
+
maximum: 600000,
|
|
766
|
+
default: 120000,
|
|
767
|
+
},
|
|
768
|
+
default_action: {
|
|
769
|
+
type: "string",
|
|
770
|
+
enum: ["timeout_continue", "timeout_abort"],
|
|
771
|
+
default: "timeout_continue",
|
|
772
|
+
},
|
|
773
|
+
requester_agent: {
|
|
774
|
+
type: "string",
|
|
775
|
+
description: "요청자 에이전트 이름",
|
|
776
|
+
},
|
|
571
777
|
},
|
|
572
778
|
},
|
|
573
|
-
handler: wrap(
|
|
779
|
+
handler: wrap("PIPELINE_ADVANCE_GATED_FAILED", (args) => {
|
|
574
780
|
ensurePipelineTable(store.db);
|
|
575
781
|
const pipeline = createPipeline(store.db, args.team_name);
|
|
576
782
|
|
|
@@ -580,23 +786,25 @@ export function createTools(store, router, hitl, pipe = null) {
|
|
|
580
786
|
return {
|
|
581
787
|
ok: false,
|
|
582
788
|
error: {
|
|
583
|
-
code:
|
|
789
|
+
code: "TRANSITION_BLOCKED",
|
|
584
790
|
message: `전이 불가: ${current.phase} → ${args.phase}`,
|
|
585
791
|
},
|
|
586
792
|
};
|
|
587
793
|
}
|
|
588
794
|
|
|
589
795
|
// HITL 승인 요청 생성
|
|
590
|
-
const approvalPrompt =
|
|
796
|
+
const approvalPrompt =
|
|
797
|
+
args.prompt ||
|
|
798
|
+
`파이프라인 ${args.team_name}: ${pipeline.getState().phase} → ${args.phase} 전이를 승인하시겠습니까?`;
|
|
591
799
|
const deadlineMs = args.deadline_ms || 120000;
|
|
592
800
|
const now = Date.now();
|
|
593
801
|
|
|
594
802
|
const hitlResult = hitl.requestHumanInput({
|
|
595
803
|
requester_agent: args.requester_agent || `pipeline:${args.team_name}`,
|
|
596
|
-
kind:
|
|
804
|
+
kind: "approval",
|
|
597
805
|
prompt: approvalPrompt,
|
|
598
806
|
deadline_ms: now + deadlineMs,
|
|
599
|
-
default_action: args.default_action ||
|
|
807
|
+
default_action: args.default_action || "timeout_continue",
|
|
600
808
|
});
|
|
601
809
|
|
|
602
810
|
if (!hitlResult.ok) {
|
|
@@ -612,8 +820,8 @@ export function createTools(store, router, hitl, pipe = null) {
|
|
|
612
820
|
target_phase: args.phase,
|
|
613
821
|
current_phase: pipeline.getState().phase,
|
|
614
822
|
deadline_ms: now + deadlineMs,
|
|
615
|
-
default_action: args.default_action ||
|
|
616
|
-
message: `승인 대기 중. ID: ${hitlResult.data.request_id}. ${Math.round(deadlineMs / 1000)}초 후 ${args.default_action ||
|
|
823
|
+
default_action: args.default_action || "timeout_continue",
|
|
824
|
+
message: `승인 대기 중. ID: ${hitlResult.data.request_id}. ${Math.round(deadlineMs / 1000)}초 후 ${args.default_action || "timeout_continue"} 자동 실행.`,
|
|
617
825
|
},
|
|
618
826
|
};
|
|
619
827
|
}),
|
|
@@ -621,16 +829,33 @@ export function createTools(store, router, hitl, pipe = null) {
|
|
|
621
829
|
|
|
622
830
|
// ── 20. pipeline_list ──
|
|
623
831
|
{
|
|
624
|
-
name:
|
|
625
|
-
description:
|
|
832
|
+
name: "pipeline_list",
|
|
833
|
+
description: "활성 파이프라인 목록을 조회합니다",
|
|
626
834
|
inputSchema: {
|
|
627
|
-
type:
|
|
835
|
+
type: "object",
|
|
628
836
|
properties: {},
|
|
629
837
|
},
|
|
630
|
-
handler: wrap(
|
|
838
|
+
handler: wrap("PIPELINE_LIST_FAILED", () => {
|
|
631
839
|
ensurePipelineTable(store.db);
|
|
632
840
|
return { ok: true, data: listPipelineStates(store.db) };
|
|
633
841
|
}),
|
|
634
842
|
},
|
|
843
|
+
|
|
844
|
+
// ── 21. send_input ──
|
|
845
|
+
{
|
|
846
|
+
name: "send_input",
|
|
847
|
+
description: "Send input text to a worker in INPUT_WAIT state",
|
|
848
|
+
inputSchema: {
|
|
849
|
+
type: "object",
|
|
850
|
+
properties: {
|
|
851
|
+
session_id: { type: "string", description: "Conductor session ID" },
|
|
852
|
+
text: { type: "string", description: "Input text to send" },
|
|
853
|
+
},
|
|
854
|
+
required: ["session_id", "text"],
|
|
855
|
+
},
|
|
856
|
+
handler: wrap("SEND_INPUT_FAILED", (args) => {
|
|
857
|
+
return sendInputToConductorSession(args.session_id, args.text);
|
|
858
|
+
}),
|
|
859
|
+
},
|
|
635
860
|
];
|
|
636
861
|
}
|