oh-my-codex 0.15.2 → 0.15.3
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/Cargo.lock +5 -5
- package/Cargo.toml +1 -1
- package/dist/agents/__tests__/native-config.test.js +33 -0
- package/dist/agents/__tests__/native-config.test.js.map +1 -1
- package/dist/catalog/__tests__/plugin-bundle-ssot.test.js +9 -1
- package/dist/catalog/__tests__/plugin-bundle-ssot.test.js.map +1 -1
- package/dist/cli/__tests__/doctor-context-window-warning.test.d.ts +2 -0
- package/dist/cli/__tests__/doctor-context-window-warning.test.d.ts.map +1 -0
- package/dist/cli/__tests__/doctor-context-window-warning.test.js +122 -0
- package/dist/cli/__tests__/doctor-context-window-warning.test.js.map +1 -0
- package/dist/cli/__tests__/doctor-warning-copy.test.js +2 -2
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
- package/dist/cli/__tests__/exec.test.js +1 -0
- package/dist/cli/__tests__/exec.test.js.map +1 -1
- package/dist/cli/__tests__/explore.test.js +40 -17
- package/dist/cli/__tests__/explore.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +141 -8
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/mcp-serve.test.js +27 -1
- package/dist/cli/__tests__/mcp-serve.test.js.map +1 -1
- package/dist/cli/__tests__/ralph.test.js +59 -1
- package/dist/cli/__tests__/ralph.test.js.map +1 -1
- package/dist/cli/__tests__/setup-scope.test.js +2 -1
- package/dist/cli/__tests__/setup-scope.test.js.map +1 -1
- package/dist/cli/__tests__/team.test.js +55 -10
- package/dist/cli/__tests__/team.test.js.map +1 -1
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +46 -3
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/index.d.ts +16 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +126 -15
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp-serve.d.ts +1 -0
- package/dist/cli/mcp-serve.d.ts.map +1 -1
- package/dist/cli/mcp-serve.js +8 -0
- package/dist/cli/mcp-serve.js.map +1 -1
- package/dist/cli/ralph.d.ts +2 -0
- package/dist/cli/ralph.d.ts.map +1 -1
- package/dist/cli/ralph.js +17 -1
- package/dist/cli/ralph.js.map +1 -1
- package/dist/cli/team.d.ts +4 -0
- package/dist/cli/team.d.ts.map +1 -1
- package/dist/cli/team.js +47 -22
- package/dist/cli/team.js.map +1 -1
- package/dist/config/__tests__/generator-idempotent.test.js +27 -5
- package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
- package/dist/config/generator.d.ts +11 -2
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +114 -58
- package/dist/config/generator.js.map +1 -1
- package/dist/hooks/__tests__/agents-overlay.test.js +59 -0
- package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
- package/dist/hooks/__tests__/anti-slop-workflow.test.js +109 -18
- package/dist/hooks/__tests__/anti-slop-workflow.test.js.map +1 -1
- package/dist/hooks/agents-overlay.d.ts.map +1 -1
- package/dist/hooks/agents-overlay.js +21 -0
- package/dist/hooks/agents-overlay.js.map +1 -1
- package/dist/hud/__tests__/index.test.js +30 -14
- package/dist/hud/__tests__/index.test.js.map +1 -1
- package/dist/openclaw/__tests__/dispatcher.test.js +1 -1
- package/dist/openclaw/__tests__/dispatcher.test.js.map +1 -1
- package/dist/pipeline/__tests__/stages.test.js +398 -14
- package/dist/pipeline/__tests__/stages.test.js.map +1 -1
- package/dist/pipeline/stages/team-exec.d.ts +8 -4
- package/dist/pipeline/stages/team-exec.d.ts.map +1 -1
- package/dist/pipeline/stages/team-exec.js +198 -13
- package/dist/pipeline/stages/team-exec.js.map +1 -1
- package/dist/planning/__tests__/artifacts.test.js +246 -1
- package/dist/planning/__tests__/artifacts.test.js.map +1 -1
- package/dist/planning/artifact-names.d.ts +13 -0
- package/dist/planning/artifact-names.d.ts.map +1 -0
- package/dist/planning/artifact-names.js +108 -0
- package/dist/planning/artifact-names.js.map +1 -0
- package/dist/planning/artifacts.d.ts +22 -1
- package/dist/planning/artifacts.d.ts.map +1 -1
- package/dist/planning/artifacts.js +165 -50
- package/dist/planning/artifacts.js.map +1 -1
- package/dist/ralph/__tests__/persistence.test.js +21 -1
- package/dist/ralph/__tests__/persistence.test.js.map +1 -1
- package/dist/ralph/persistence.d.ts.map +1 -1
- package/dist/ralph/persistence.js +6 -4
- package/dist/ralph/persistence.js.map +1 -1
- package/dist/scripts/__tests__/codex-native-hook.test.js +352 -2
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +85 -6
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/scripts/codex-native-pre-post.d.ts.map +1 -1
- package/dist/scripts/codex-native-pre-post.js +123 -0
- package/dist/scripts/codex-native-pre-post.js.map +1 -1
- package/dist/scripts/notify-hook/team-worker-posttooluse.js +1 -1
- package/dist/scripts/notify-hook/team-worker-posttooluse.js.map +1 -1
- package/dist/scripts/notify-hook.js +1 -1
- package/dist/scripts/notify-hook.js.map +1 -1
- package/dist/scripts/sync-plugin-mirror.d.ts +1 -0
- package/dist/scripts/sync-plugin-mirror.d.ts.map +1 -1
- package/dist/scripts/sync-plugin-mirror.js +8 -2
- package/dist/scripts/sync-plugin-mirror.js.map +1 -1
- package/dist/state/__tests__/skill-active.test.js +41 -0
- package/dist/state/__tests__/skill-active.test.js.map +1 -1
- package/dist/team/__tests__/api-interop.test.js +220 -0
- package/dist/team/__tests__/api-interop.test.js.map +1 -1
- package/dist/team/__tests__/model-contract.test.js +40 -9
- package/dist/team/__tests__/model-contract.test.js.map +1 -1
- package/dist/team/__tests__/repo-aware-decomposition.test.js +41 -0
- package/dist/team/__tests__/repo-aware-decomposition.test.js.map +1 -1
- package/dist/team/__tests__/runtime-cli.test.js +24 -0
- package/dist/team/__tests__/runtime-cli.test.js.map +1 -1
- package/dist/team/__tests__/runtime.test.js +446 -67
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/state.test.js +13 -0
- package/dist/team/__tests__/state.test.js.map +1 -1
- package/dist/team/__tests__/team-identity.test.d.ts +2 -0
- package/dist/team/__tests__/team-identity.test.d.ts.map +1 -0
- package/dist/team/__tests__/team-identity.test.js +166 -0
- package/dist/team/__tests__/team-identity.test.js.map +1 -0
- package/dist/team/__tests__/tmux-session.test.js +55 -1
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/__tests__/worker-bootstrap.test.js +12 -0
- package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
- package/dist/team/api-interop.d.ts +1 -0
- package/dist/team/api-interop.d.ts.map +1 -1
- package/dist/team/api-interop.js +159 -129
- package/dist/team/api-interop.js.map +1 -1
- package/dist/team/delivery-log.d.ts +1 -1
- package/dist/team/delivery-log.d.ts.map +1 -1
- package/dist/team/delivery-log.js.map +1 -1
- package/dist/team/repo-aware-decomposition.d.ts +3 -0
- package/dist/team/repo-aware-decomposition.d.ts.map +1 -1
- package/dist/team/repo-aware-decomposition.js +2 -0
- package/dist/team/repo-aware-decomposition.js.map +1 -1
- package/dist/team/runtime-cli.d.ts +32 -2
- package/dist/team/runtime-cli.d.ts.map +1 -1
- package/dist/team/runtime-cli.js +78 -26
- package/dist/team/runtime-cli.js.map +1 -1
- package/dist/team/runtime.d.ts +1 -1
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +338 -35
- package/dist/team/runtime.js.map +1 -1
- package/dist/team/state.d.ts +9 -0
- package/dist/team/state.d.ts.map +1 -1
- package/dist/team/state.js +21 -0
- package/dist/team/state.js.map +1 -1
- package/dist/team/team-identity.d.ts +26 -0
- package/dist/team/team-identity.d.ts.map +1 -0
- package/dist/team/team-identity.js +169 -0
- package/dist/team/team-identity.js.map +1 -0
- package/dist/team/tmux-session.d.ts +18 -0
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +61 -1
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/team/worker-bootstrap.d.ts +2 -0
- package/dist/team/worker-bootstrap.d.ts.map +1 -1
- package/dist/team/worker-bootstrap.js +10 -1
- package/dist/team/worker-bootstrap.js.map +1 -1
- package/package.json +1 -1
- package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/oh-my-codex/skills/ai-slop-cleaner/SKILL.md +30 -5
- package/skills/ai-slop-cleaner/SKILL.md +30 -5
- package/src/scripts/__tests__/codex-native-hook.test.ts +398 -2
- package/src/scripts/codex-native-hook.ts +115 -5
- package/src/scripts/codex-native-pre-post.ts +121 -0
- package/src/scripts/notify-hook/team-worker-posttooluse.ts +1 -1
- package/src/scripts/notify-hook.ts +1 -1
- package/src/scripts/sync-plugin-mirror.ts +11 -2
package/dist/team/api-interop.js
CHANGED
|
@@ -10,6 +10,7 @@ import { readLatestTeamProgressEvidenceMs } from './progress-evidence.js';
|
|
|
10
10
|
import { resolveCanonicalTeamStateRoot } from './state-root.js';
|
|
11
11
|
import { buildLeaderMailboxTriggerDirective, buildMailboxTriggerDirective } from './worker-bootstrap.js';
|
|
12
12
|
import { teamBroadcast as broadcastMessage, teamListMailbox as listMailboxMessages, teamMarkMessageDelivered as markMessageDelivered, teamMarkMessageNotified as markMessageNotified, teamListDispatchRequests, teamMarkDispatchRequestNotified, teamMarkDispatchRequestDelivered, teamCreateTask, teamReadTask, teamListTasks, teamUpdateTask, teamClaimTask, teamTransitionTaskStatus, teamReleaseTaskClaim, teamCleanup, teamReadConfig, teamReadManifest, teamReadWorkerStatus, teamReadWorkerHeartbeat, teamUpdateWorkerHeartbeat, teamWriteWorkerInbox, teamWriteWorkerIdentity, teamAppendEvent, teamGetSummary, teamWriteShutdownRequest, teamReadShutdownAck, teamReadMonitorSnapshot, teamReadPhase, teamReadLeaderAttention, teamWriteMonitorSnapshot, teamReadTaskApproval, teamWriteTaskApproval, } from './team-ops.js';
|
|
13
|
+
import { listTeamLookupCandidates, resolveTeamNameForCurrentContext, TeamLookupAmbiguityError } from './team-identity.js';
|
|
13
14
|
const TEAM_UPDATE_TASK_MUTABLE_FIELDS = new Set(['subject', 'description', 'blocked_by', 'requires_code_change']);
|
|
14
15
|
const TEAM_UPDATE_TASK_REQUEST_FIELDS = new Set(['team_name', 'task_id', 'workingDirectory', ...TEAM_UPDATE_TASK_MUTABLE_FIELDS]);
|
|
15
16
|
export const LEGACY_TEAM_MCP_TOOLS = [
|
|
@@ -433,9 +434,9 @@ export function buildLegacyTeamDeprecationHint(legacyName, originalArgs) {
|
|
|
433
434
|
}
|
|
434
435
|
return `Use CLI interop: omx team api ${operation} --input '${payload}' --json`;
|
|
435
436
|
}
|
|
436
|
-
function validateCommonFields(args) {
|
|
437
|
+
function validateCommonFields(args, options = {}) {
|
|
437
438
|
const teamName = String(args.team_name || '').trim();
|
|
438
|
-
if (teamName && !TEAM_NAME_SAFE_PATTERN.test(teamName)) {
|
|
439
|
+
if (!options.skipTeamName && teamName && !TEAM_NAME_SAFE_PATTERN.test(teamName)) {
|
|
439
440
|
throw new Error(`Invalid team_name: "${teamName}". Must match /^[a-z0-9][a-z0-9-]{0,29}$/ (lowercase alphanumeric + hyphens, max 30 chars).`);
|
|
440
441
|
}
|
|
441
442
|
for (const workerField of ['worker', 'from_worker', 'to_worker']) {
|
|
@@ -449,17 +450,43 @@ function validateCommonFields(args) {
|
|
|
449
450
|
throw new Error(`Invalid task_id: "${rawTaskId}". Must be a positive integer (digits only, max 20 digits).`);
|
|
450
451
|
}
|
|
451
452
|
}
|
|
453
|
+
function normalizeTeamDisplayLookupName(value) {
|
|
454
|
+
return value
|
|
455
|
+
.toLowerCase()
|
|
456
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
457
|
+
.replace(/-+/g, '-')
|
|
458
|
+
.replace(/^-|-$/g, '')
|
|
459
|
+
.slice(0, 30)
|
|
460
|
+
.replace(/-$/, '');
|
|
461
|
+
}
|
|
462
|
+
function assertUnsafeTeamNameMatchesKnownDisplay(rawTeamName, cwd) {
|
|
463
|
+
if (TEAM_NAME_SAFE_PATTERN.test(rawTeamName))
|
|
464
|
+
return;
|
|
465
|
+
const normalized = normalizeTeamDisplayLookupName(rawTeamName);
|
|
466
|
+
const matchesKnownDisplay = listTeamLookupCandidates(cwd).some((candidate) => {
|
|
467
|
+
return normalizeTeamDisplayLookupName(candidate.displayName) === normalized
|
|
468
|
+
|| normalizeTeamDisplayLookupName(candidate.requestedName) === normalized;
|
|
469
|
+
});
|
|
470
|
+
if (!matchesKnownDisplay) {
|
|
471
|
+
throw new Error(`Invalid team_name: "${rawTeamName}". Must match /^[a-z0-9][a-z0-9-]{0,29}$/ or resolve to an existing display name.`);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
452
474
|
export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
453
475
|
try {
|
|
454
|
-
validateCommonFields(args);
|
|
455
|
-
const
|
|
456
|
-
|
|
476
|
+
validateCommonFields(args, { skipTeamName: true });
|
|
477
|
+
const rawTeamNameForCwd = String(args.team_name || '').trim();
|
|
478
|
+
if (rawTeamNameForCwd)
|
|
479
|
+
assertUnsafeTeamNameMatchesKnownDisplay(rawTeamNameForCwd, fallbackCwd);
|
|
480
|
+
const resolvedTeamName = rawTeamNameForCwd ? resolveTeamNameForCurrentContext(rawTeamNameForCwd, fallbackCwd) : '';
|
|
481
|
+
const cwd = resolvedTeamName ? resolveTeamWorkingDirectory(resolvedTeamName, fallbackCwd) : fallbackCwd;
|
|
482
|
+
const opArgs = resolvedTeamName ? { ...args, team_name: resolvedTeamName } : args;
|
|
483
|
+
validateCommonFields(opArgs);
|
|
457
484
|
switch (operation) {
|
|
458
485
|
case 'send-message': {
|
|
459
|
-
const teamName = String(
|
|
460
|
-
const fromWorker = String(
|
|
461
|
-
const toWorker = String(
|
|
462
|
-
const body = String(
|
|
486
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
487
|
+
const fromWorker = String(opArgs.from_worker || '').trim();
|
|
488
|
+
const toWorker = String(opArgs.to_worker || '').trim();
|
|
489
|
+
const body = String(opArgs.body || '').trim();
|
|
463
490
|
if (!fromWorker) {
|
|
464
491
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'from_worker is required. You must identify yourself.' } };
|
|
465
492
|
}
|
|
@@ -525,9 +552,9 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
525
552
|
return { ok: true, operation, data: { message, dispatch: outcome } };
|
|
526
553
|
}
|
|
527
554
|
case 'broadcast': {
|
|
528
|
-
const teamName = String(
|
|
529
|
-
const fromWorker = String(
|
|
530
|
-
const body = String(
|
|
555
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
556
|
+
const fromWorker = String(opArgs.from_worker || '').trim();
|
|
557
|
+
const body = String(opArgs.body || '').trim();
|
|
531
558
|
if (!teamName || !fromWorker || !body) {
|
|
532
559
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name, from_worker, body are required' } };
|
|
533
560
|
}
|
|
@@ -535,9 +562,9 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
535
562
|
return { ok: true, operation, data: { count: messages.length, messages } };
|
|
536
563
|
}
|
|
537
564
|
case 'mailbox-list': {
|
|
538
|
-
const teamName = String(
|
|
539
|
-
const worker = String(
|
|
540
|
-
const includeDelivered =
|
|
565
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
566
|
+
const worker = String(opArgs.worker || '').trim();
|
|
567
|
+
const includeDelivered = opArgs.include_delivered !== false;
|
|
541
568
|
if (!teamName || !worker) {
|
|
542
569
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name and worker are required' } };
|
|
543
570
|
}
|
|
@@ -546,9 +573,9 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
546
573
|
return { ok: true, operation, data: { worker, count: messages.length, messages } };
|
|
547
574
|
}
|
|
548
575
|
case 'mailbox-mark-delivered': {
|
|
549
|
-
const teamName = String(
|
|
550
|
-
const worker = String(
|
|
551
|
-
const messageId = String(
|
|
576
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
577
|
+
const worker = String(opArgs.worker || '').trim();
|
|
578
|
+
const messageId = String(opArgs.message_id || '').trim();
|
|
552
579
|
if (!teamName || !worker || !messageId) {
|
|
553
580
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name, worker, message_id are required' } };
|
|
554
581
|
}
|
|
@@ -577,9 +604,9 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
577
604
|
};
|
|
578
605
|
}
|
|
579
606
|
case 'mailbox-mark-notified': {
|
|
580
|
-
const teamName = String(
|
|
581
|
-
const worker = String(
|
|
582
|
-
const messageId = String(
|
|
607
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
608
|
+
const worker = String(opArgs.worker || '').trim();
|
|
609
|
+
const messageId = String(opArgs.message_id || '').trim();
|
|
583
610
|
if (!teamName || !worker || !messageId) {
|
|
584
611
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name, worker, message_id are required' } };
|
|
585
612
|
}
|
|
@@ -587,23 +614,23 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
587
614
|
return { ok: true, operation, data: { worker, message_id: messageId, notified } };
|
|
588
615
|
}
|
|
589
616
|
case 'create-task': {
|
|
590
|
-
const teamName = String(
|
|
591
|
-
const subject = String(
|
|
592
|
-
const description = String(
|
|
617
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
618
|
+
const subject = String(opArgs.subject || '').trim();
|
|
619
|
+
const description = String(opArgs.description || '').trim();
|
|
593
620
|
if (!teamName || !subject || !description) {
|
|
594
621
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name, subject, description are required' } };
|
|
595
622
|
}
|
|
596
|
-
const owner =
|
|
597
|
-
const blockedBy =
|
|
598
|
-
const requiresCodeChange =
|
|
623
|
+
const owner = opArgs.owner;
|
|
624
|
+
const blockedBy = opArgs.blocked_by;
|
|
625
|
+
const requiresCodeChange = opArgs.requires_code_change;
|
|
599
626
|
const task = await teamCreateTask(teamName, {
|
|
600
627
|
subject, description, status: 'pending', owner: owner || undefined, blocked_by: blockedBy, requires_code_change: requiresCodeChange,
|
|
601
628
|
}, cwd);
|
|
602
629
|
return { ok: true, operation, data: { task } };
|
|
603
630
|
}
|
|
604
631
|
case 'read-task': {
|
|
605
|
-
const teamName = String(
|
|
606
|
-
const taskId = String(
|
|
632
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
633
|
+
const taskId = String(opArgs.task_id || '').trim();
|
|
607
634
|
if (!teamName || !taskId) {
|
|
608
635
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name and task_id are required' } };
|
|
609
636
|
}
|
|
@@ -613,7 +640,7 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
613
640
|
: { ok: false, operation, error: { code: 'task_not_found', message: 'task_not_found' } };
|
|
614
641
|
}
|
|
615
642
|
case 'list-tasks': {
|
|
616
|
-
const teamName = String(
|
|
643
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
617
644
|
if (!teamName) {
|
|
618
645
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name is required' } };
|
|
619
646
|
}
|
|
@@ -621,8 +648,8 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
621
648
|
return { ok: true, operation, data: { count: tasks.length, tasks } };
|
|
622
649
|
}
|
|
623
650
|
case 'update-task': {
|
|
624
|
-
const teamName = String(
|
|
625
|
-
const taskId = String(
|
|
651
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
652
|
+
const taskId = String(opArgs.task_id || '').trim();
|
|
626
653
|
if (!teamName || !taskId) {
|
|
627
654
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name and task_id are required' } };
|
|
628
655
|
}
|
|
@@ -637,26 +664,26 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
637
664
|
}
|
|
638
665
|
const updates = {};
|
|
639
666
|
if ('subject' in args) {
|
|
640
|
-
if (typeof
|
|
667
|
+
if (typeof opArgs.subject !== 'string') {
|
|
641
668
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'subject must be a string when provided' } };
|
|
642
669
|
}
|
|
643
|
-
updates.subject =
|
|
670
|
+
updates.subject = opArgs.subject.trim();
|
|
644
671
|
}
|
|
645
672
|
if ('description' in args) {
|
|
646
|
-
if (typeof
|
|
673
|
+
if (typeof opArgs.description !== 'string') {
|
|
647
674
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'description must be a string when provided' } };
|
|
648
675
|
}
|
|
649
|
-
updates.description =
|
|
676
|
+
updates.description = opArgs.description.trim();
|
|
650
677
|
}
|
|
651
678
|
if ('requires_code_change' in args) {
|
|
652
|
-
if (typeof
|
|
679
|
+
if (typeof opArgs.requires_code_change !== 'boolean') {
|
|
653
680
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'requires_code_change must be a boolean when provided' } };
|
|
654
681
|
}
|
|
655
|
-
updates.requires_code_change =
|
|
682
|
+
updates.requires_code_change = opArgs.requires_code_change;
|
|
656
683
|
}
|
|
657
684
|
if ('blocked_by' in args) {
|
|
658
685
|
try {
|
|
659
|
-
updates.blocked_by = parseValidatedTaskIdArray(
|
|
686
|
+
updates.blocked_by = parseValidatedTaskIdArray(opArgs.blocked_by, 'blocked_by');
|
|
660
687
|
}
|
|
661
688
|
catch (error) {
|
|
662
689
|
return { ok: false, operation, error: { code: 'invalid_input', message: error.message } };
|
|
@@ -668,13 +695,13 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
668
695
|
: { ok: false, operation, error: { code: 'task_not_found', message: 'task_not_found' } };
|
|
669
696
|
}
|
|
670
697
|
case 'claim-task': {
|
|
671
|
-
const teamName = String(
|
|
672
|
-
const taskId = String(
|
|
673
|
-
const worker = String(
|
|
698
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
699
|
+
const taskId = String(opArgs.task_id || '').trim();
|
|
700
|
+
const worker = String(opArgs.worker || '').trim();
|
|
674
701
|
if (!teamName || !taskId || !worker) {
|
|
675
702
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name, task_id, worker are required' } };
|
|
676
703
|
}
|
|
677
|
-
const rawExpectedVersion =
|
|
704
|
+
const rawExpectedVersion = opArgs.expected_version;
|
|
678
705
|
if (rawExpectedVersion !== undefined && (!isFiniteInteger(rawExpectedVersion) || rawExpectedVersion < 1)) {
|
|
679
706
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'expected_version must be a positive integer when provided' } };
|
|
680
707
|
}
|
|
@@ -682,13 +709,13 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
682
709
|
return { ok: true, operation, data: result };
|
|
683
710
|
}
|
|
684
711
|
case 'transition-task-status': {
|
|
685
|
-
const teamName = String(
|
|
686
|
-
const taskId = String(
|
|
687
|
-
const from = String(
|
|
688
|
-
const to = String(
|
|
689
|
-
const claimToken = String(
|
|
690
|
-
const transitionResult =
|
|
691
|
-
const transitionError =
|
|
712
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
713
|
+
const taskId = String(opArgs.task_id || '').trim();
|
|
714
|
+
const from = String(opArgs.from || '').trim();
|
|
715
|
+
const to = String(opArgs.to || '').trim();
|
|
716
|
+
const claimToken = String(opArgs.claim_token || '').trim();
|
|
717
|
+
const transitionResult = opArgs.result;
|
|
718
|
+
const transitionError = opArgs.error;
|
|
692
719
|
if (!teamName || !taskId || !from || !to || !claimToken) {
|
|
693
720
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name, task_id, from, to, claim_token are required' } };
|
|
694
721
|
}
|
|
@@ -709,10 +736,10 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
709
736
|
return { ok: true, operation, data: result };
|
|
710
737
|
}
|
|
711
738
|
case 'release-task-claim': {
|
|
712
|
-
const teamName = String(
|
|
713
|
-
const taskId = String(
|
|
714
|
-
const claimToken = String(
|
|
715
|
-
const worker = String(
|
|
739
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
740
|
+
const taskId = String(opArgs.task_id || '').trim();
|
|
741
|
+
const claimToken = String(opArgs.claim_token || '').trim();
|
|
742
|
+
const worker = String(opArgs.worker || '').trim();
|
|
716
743
|
if (!teamName || !taskId || !claimToken || !worker) {
|
|
717
744
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name, task_id, claim_token, worker are required' } };
|
|
718
745
|
}
|
|
@@ -720,7 +747,7 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
720
747
|
return { ok: true, operation, data: result };
|
|
721
748
|
}
|
|
722
749
|
case 'read-config': {
|
|
723
|
-
const teamName = String(
|
|
750
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
724
751
|
if (!teamName)
|
|
725
752
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name is required' } };
|
|
726
753
|
const config = await teamReadConfig(teamName, cwd);
|
|
@@ -729,7 +756,7 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
729
756
|
: { ok: false, operation, error: { code: 'team_not_found', message: 'team_not_found' } };
|
|
730
757
|
}
|
|
731
758
|
case 'read-manifest': {
|
|
732
|
-
const teamName = String(
|
|
759
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
733
760
|
if (!teamName)
|
|
734
761
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name is required' } };
|
|
735
762
|
const manifest = await teamReadManifest(teamName, cwd);
|
|
@@ -738,27 +765,27 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
738
765
|
: { ok: false, operation, error: { code: 'manifest_not_found', message: 'manifest_not_found' } };
|
|
739
766
|
}
|
|
740
767
|
case 'read-worker-status': {
|
|
741
|
-
const teamName = String(
|
|
742
|
-
const worker = String(
|
|
768
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
769
|
+
const worker = String(opArgs.worker || '').trim();
|
|
743
770
|
if (!teamName || !worker)
|
|
744
771
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name and worker are required' } };
|
|
745
772
|
const status = await teamReadWorkerStatus(teamName, worker, cwd);
|
|
746
773
|
return { ok: true, operation, data: { worker, status } };
|
|
747
774
|
}
|
|
748
775
|
case 'read-worker-heartbeat': {
|
|
749
|
-
const teamName = String(
|
|
750
|
-
const worker = String(
|
|
776
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
777
|
+
const worker = String(opArgs.worker || '').trim();
|
|
751
778
|
if (!teamName || !worker)
|
|
752
779
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name and worker are required' } };
|
|
753
780
|
const heartbeat = await teamReadWorkerHeartbeat(teamName, worker, cwd);
|
|
754
781
|
return { ok: true, operation, data: { worker, heartbeat } };
|
|
755
782
|
}
|
|
756
783
|
case 'update-worker-heartbeat': {
|
|
757
|
-
const teamName = String(
|
|
758
|
-
const worker = String(
|
|
759
|
-
const pid =
|
|
760
|
-
const turnCount =
|
|
761
|
-
const alive =
|
|
784
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
785
|
+
const worker = String(opArgs.worker || '').trim();
|
|
786
|
+
const pid = opArgs.pid;
|
|
787
|
+
const turnCount = opArgs.turn_count;
|
|
788
|
+
const alive = opArgs.alive;
|
|
762
789
|
if (!teamName || !worker || typeof pid !== 'number' || typeof turnCount !== 'number' || typeof alive !== 'boolean') {
|
|
763
790
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name, worker, pid, turn_count, alive are required' } };
|
|
764
791
|
}
|
|
@@ -766,9 +793,9 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
766
793
|
return { ok: true, operation, data: { worker } };
|
|
767
794
|
}
|
|
768
795
|
case 'write-worker-inbox': {
|
|
769
|
-
const teamName = String(
|
|
770
|
-
const worker = String(
|
|
771
|
-
const content = String(
|
|
796
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
797
|
+
const worker = String(opArgs.worker || '').trim();
|
|
798
|
+
const content = String(opArgs.content || '').trim();
|
|
772
799
|
if (!teamName || !worker || !content) {
|
|
773
800
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name, worker, content are required' } };
|
|
774
801
|
}
|
|
@@ -776,10 +803,10 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
776
803
|
return { ok: true, operation, data: { worker } };
|
|
777
804
|
}
|
|
778
805
|
case 'write-worker-identity': {
|
|
779
|
-
const teamName = String(
|
|
780
|
-
const worker = String(
|
|
781
|
-
const index =
|
|
782
|
-
const role = String(
|
|
806
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
807
|
+
const worker = String(opArgs.worker || '').trim();
|
|
808
|
+
const index = opArgs.index;
|
|
809
|
+
const role = String(opArgs.role || '').trim();
|
|
783
810
|
if (!teamName || !worker || typeof index !== 'number' || !role) {
|
|
784
811
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name, worker, index, role are required' } };
|
|
785
812
|
}
|
|
@@ -787,21 +814,21 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
787
814
|
name: worker,
|
|
788
815
|
index,
|
|
789
816
|
role,
|
|
790
|
-
assigned_tasks:
|
|
791
|
-
pid:
|
|
792
|
-
pane_id:
|
|
793
|
-
working_dir:
|
|
794
|
-
worktree_path:
|
|
795
|
-
worktree_branch:
|
|
796
|
-
worktree_detached:
|
|
797
|
-
team_state_root:
|
|
817
|
+
assigned_tasks: opArgs.assigned_tasks ?? [],
|
|
818
|
+
pid: opArgs.pid,
|
|
819
|
+
pane_id: opArgs.pane_id,
|
|
820
|
+
working_dir: opArgs.working_dir,
|
|
821
|
+
worktree_path: opArgs.worktree_path,
|
|
822
|
+
worktree_branch: opArgs.worktree_branch,
|
|
823
|
+
worktree_detached: opArgs.worktree_detached,
|
|
824
|
+
team_state_root: opArgs.team_state_root,
|
|
798
825
|
}, cwd);
|
|
799
826
|
return { ok: true, operation, data: { worker } };
|
|
800
827
|
}
|
|
801
828
|
case 'append-event': {
|
|
802
|
-
const teamName = String(
|
|
803
|
-
const eventType = String(
|
|
804
|
-
const worker = String(
|
|
829
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
830
|
+
const eventType = String(opArgs.type || '').trim();
|
|
831
|
+
const worker = String(opArgs.worker || '').trim();
|
|
805
832
|
if (!teamName || !eventType || !worker) {
|
|
806
833
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name, type, worker are required' } };
|
|
807
834
|
}
|
|
@@ -811,29 +838,29 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
811
838
|
const event = await teamAppendEvent(teamName, {
|
|
812
839
|
type: eventType,
|
|
813
840
|
worker,
|
|
814
|
-
task_id:
|
|
815
|
-
message_id:
|
|
816
|
-
reason:
|
|
817
|
-
state:
|
|
818
|
-
prev_state:
|
|
819
|
-
to_worker:
|
|
820
|
-
worker_count: typeof
|
|
821
|
-
source_type:
|
|
822
|
-
metadata: parseOptionalMetadata(
|
|
841
|
+
task_id: opArgs.task_id,
|
|
842
|
+
message_id: opArgs.message_id ?? null,
|
|
843
|
+
reason: opArgs.reason,
|
|
844
|
+
state: opArgs.state,
|
|
845
|
+
prev_state: opArgs.prev_state,
|
|
846
|
+
to_worker: opArgs.to_worker,
|
|
847
|
+
worker_count: typeof opArgs.worker_count === 'number' ? opArgs.worker_count : undefined,
|
|
848
|
+
source_type: opArgs.source_type,
|
|
849
|
+
metadata: parseOptionalMetadata(opArgs.metadata),
|
|
823
850
|
}, cwd);
|
|
824
851
|
return { ok: true, operation, data: { event } };
|
|
825
852
|
}
|
|
826
853
|
case 'read-events': {
|
|
827
|
-
const teamName = String(
|
|
854
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
828
855
|
if (!teamName) {
|
|
829
856
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name is required' } };
|
|
830
857
|
}
|
|
831
|
-
const wakeableOnly = parseOptionalBoolean(
|
|
832
|
-
const eventType = parseOptionalEventType(
|
|
833
|
-
const worker = typeof
|
|
834
|
-
const taskId = typeof
|
|
858
|
+
const wakeableOnly = parseOptionalBoolean(opArgs.wakeable_only, 'wakeable_only');
|
|
859
|
+
const eventType = parseOptionalEventType(opArgs.type);
|
|
860
|
+
const worker = typeof opArgs.worker === 'string' ? opArgs.worker.trim() : '';
|
|
861
|
+
const taskId = typeof opArgs.task_id === 'string' ? opArgs.task_id.trim() : '';
|
|
835
862
|
const events = await readTeamEvents(teamName, cwd, {
|
|
836
|
-
afterEventId: typeof
|
|
863
|
+
afterEventId: typeof opArgs.after_event_id === 'string' ? opArgs.after_event_id.trim() || undefined : undefined,
|
|
837
864
|
wakeableOnly: wakeableOnly ?? false,
|
|
838
865
|
type: eventType ?? undefined,
|
|
839
866
|
worker: worker || undefined,
|
|
@@ -844,24 +871,24 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
844
871
|
operation,
|
|
845
872
|
data: {
|
|
846
873
|
count: events.length,
|
|
847
|
-
cursor: events.at(-1)?.event_id ?? (typeof
|
|
874
|
+
cursor: events.at(-1)?.event_id ?? (typeof opArgs.after_event_id === 'string' ? opArgs.after_event_id.trim() : ''),
|
|
848
875
|
events,
|
|
849
876
|
},
|
|
850
877
|
};
|
|
851
878
|
}
|
|
852
879
|
case 'await-event': {
|
|
853
|
-
const teamName = String(
|
|
880
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
854
881
|
if (!teamName) {
|
|
855
882
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name is required' } };
|
|
856
883
|
}
|
|
857
|
-
const timeoutMs = parseOptionalNonNegativeInteger(
|
|
858
|
-
const pollMs = parseOptionalNonNegativeInteger(
|
|
859
|
-
const wakeableOnly = parseOptionalBoolean(
|
|
860
|
-
const eventType = parseOptionalEventType(
|
|
861
|
-
const worker = typeof
|
|
862
|
-
const taskId = typeof
|
|
884
|
+
const timeoutMs = parseOptionalNonNegativeInteger(opArgs.timeout_ms, 'timeout_ms') ?? 30_000;
|
|
885
|
+
const pollMs = parseOptionalNonNegativeInteger(opArgs.poll_ms, 'poll_ms');
|
|
886
|
+
const wakeableOnly = parseOptionalBoolean(opArgs.wakeable_only, 'wakeable_only');
|
|
887
|
+
const eventType = parseOptionalEventType(opArgs.type);
|
|
888
|
+
const worker = typeof opArgs.worker === 'string' ? opArgs.worker.trim() : '';
|
|
889
|
+
const taskId = typeof opArgs.task_id === 'string' ? opArgs.task_id.trim() : '';
|
|
863
890
|
const result = await waitForTeamEvent(teamName, cwd, {
|
|
864
|
-
afterEventId: typeof
|
|
891
|
+
afterEventId: typeof opArgs.after_event_id === 'string' ? opArgs.after_event_id.trim() || undefined : undefined,
|
|
865
892
|
timeoutMs,
|
|
866
893
|
pollMs: pollMs ?? undefined,
|
|
867
894
|
wakeableOnly: wakeableOnly ?? false,
|
|
@@ -880,7 +907,7 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
880
907
|
};
|
|
881
908
|
}
|
|
882
909
|
case 'read-idle-state': {
|
|
883
|
-
const teamName = String(
|
|
910
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
884
911
|
if (!teamName) {
|
|
885
912
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name is required' } };
|
|
886
913
|
}
|
|
@@ -900,7 +927,7 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
900
927
|
};
|
|
901
928
|
}
|
|
902
929
|
case 'read-stall-state': {
|
|
903
|
-
const teamName = String(
|
|
930
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
904
931
|
if (!teamName) {
|
|
905
932
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name is required' } };
|
|
906
933
|
}
|
|
@@ -943,7 +970,7 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
943
970
|
};
|
|
944
971
|
}
|
|
945
972
|
case 'get-summary': {
|
|
946
|
-
const teamName = String(
|
|
973
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
947
974
|
if (!teamName)
|
|
948
975
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name is required' } };
|
|
949
976
|
const summary = await teamGetSummary(teamName, cwd);
|
|
@@ -952,7 +979,7 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
952
979
|
: { ok: false, operation, error: { code: 'team_not_found', message: 'team_not_found' } };
|
|
953
980
|
}
|
|
954
981
|
case 'cleanup': {
|
|
955
|
-
const teamName = String(
|
|
982
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
956
983
|
if (!teamName)
|
|
957
984
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name is required' } };
|
|
958
985
|
const force = args.force === true;
|
|
@@ -961,16 +988,16 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
961
988
|
return { ok: true, operation, data: { team_name: teamName, cleanup_mode: 'shutdown' } };
|
|
962
989
|
}
|
|
963
990
|
case 'orphan-cleanup': {
|
|
964
|
-
const teamName = String(
|
|
991
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
965
992
|
if (!teamName)
|
|
966
993
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name is required' } };
|
|
967
994
|
await teamCleanup(teamName, cwd);
|
|
968
995
|
return { ok: true, operation, data: { team_name: teamName, cleanup_mode: 'orphan_cleanup' } };
|
|
969
996
|
}
|
|
970
997
|
case 'write-shutdown-request': {
|
|
971
|
-
const teamName = String(
|
|
972
|
-
const worker = String(
|
|
973
|
-
const requestedBy = String(
|
|
998
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
999
|
+
const worker = String(opArgs.worker || '').trim();
|
|
1000
|
+
const requestedBy = String(opArgs.requested_by || '').trim();
|
|
974
1001
|
if (!teamName || !worker || !requestedBy) {
|
|
975
1002
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name, worker, requested_by are required' } };
|
|
976
1003
|
}
|
|
@@ -978,24 +1005,24 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
978
1005
|
return { ok: true, operation, data: { worker } };
|
|
979
1006
|
}
|
|
980
1007
|
case 'read-shutdown-ack': {
|
|
981
|
-
const teamName = String(
|
|
982
|
-
const worker = String(
|
|
1008
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
1009
|
+
const worker = String(opArgs.worker || '').trim();
|
|
983
1010
|
if (!teamName || !worker) {
|
|
984
1011
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name and worker are required' } };
|
|
985
1012
|
}
|
|
986
|
-
const ack = await teamReadShutdownAck(teamName, worker, cwd,
|
|
1013
|
+
const ack = await teamReadShutdownAck(teamName, worker, cwd, opArgs.min_updated_at);
|
|
987
1014
|
return { ok: true, operation, data: { worker, ack } };
|
|
988
1015
|
}
|
|
989
1016
|
case 'read-monitor-snapshot': {
|
|
990
|
-
const teamName = String(
|
|
1017
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
991
1018
|
if (!teamName)
|
|
992
1019
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name is required' } };
|
|
993
1020
|
const snapshot = await teamReadMonitorSnapshot(teamName, cwd);
|
|
994
1021
|
return { ok: true, operation, data: { snapshot } };
|
|
995
1022
|
}
|
|
996
1023
|
case 'write-monitor-snapshot': {
|
|
997
|
-
const teamName = String(
|
|
998
|
-
const snapshot =
|
|
1024
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
1025
|
+
const snapshot = opArgs.snapshot;
|
|
999
1026
|
if (!teamName || !snapshot) {
|
|
1000
1027
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name and snapshot are required' } };
|
|
1001
1028
|
}
|
|
@@ -1003,8 +1030,8 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
1003
1030
|
return { ok: true, operation, data: {} };
|
|
1004
1031
|
}
|
|
1005
1032
|
case 'read-task-approval': {
|
|
1006
|
-
const teamName = String(
|
|
1007
|
-
const taskId = String(
|
|
1033
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
1034
|
+
const taskId = String(opArgs.task_id || '').trim();
|
|
1008
1035
|
if (!teamName || !taskId) {
|
|
1009
1036
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name and task_id are required' } };
|
|
1010
1037
|
}
|
|
@@ -1012,18 +1039,18 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
1012
1039
|
return { ok: true, operation, data: { approval } };
|
|
1013
1040
|
}
|
|
1014
1041
|
case 'write-task-approval': {
|
|
1015
|
-
const teamName = String(
|
|
1016
|
-
const taskId = String(
|
|
1017
|
-
const status = String(
|
|
1018
|
-
const reviewer = String(
|
|
1019
|
-
const decisionReason = String(
|
|
1042
|
+
const teamName = String(opArgs.team_name || '').trim();
|
|
1043
|
+
const taskId = String(opArgs.task_id || '').trim();
|
|
1044
|
+
const status = String(opArgs.status || '').trim();
|
|
1045
|
+
const reviewer = String(opArgs.reviewer || '').trim();
|
|
1046
|
+
const decisionReason = String(opArgs.decision_reason || '').trim();
|
|
1020
1047
|
if (!teamName || !taskId || !status || !reviewer || !decisionReason) {
|
|
1021
1048
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'team_name, task_id, status, reviewer, decision_reason are required' } };
|
|
1022
1049
|
}
|
|
1023
1050
|
if (!TEAM_TASK_APPROVAL_STATUSES.includes(status)) {
|
|
1024
1051
|
return { ok: false, operation, error: { code: 'invalid_input', message: `status must be one of: ${TEAM_TASK_APPROVAL_STATUSES.join(', ')}` } };
|
|
1025
1052
|
}
|
|
1026
|
-
const rawRequired =
|
|
1053
|
+
const rawRequired = opArgs.required;
|
|
1027
1054
|
if (rawRequired !== undefined && typeof rawRequired !== 'boolean') {
|
|
1028
1055
|
return { ok: false, operation, error: { code: 'invalid_input', message: 'required must be a boolean when provided' } };
|
|
1029
1056
|
}
|
|
@@ -1040,6 +1067,9 @@ export async function executeTeamApiOperation(operation, args, fallbackCwd) {
|
|
|
1040
1067
|
}
|
|
1041
1068
|
}
|
|
1042
1069
|
catch (error) {
|
|
1070
|
+
if (error instanceof TeamLookupAmbiguityError) {
|
|
1071
|
+
return { ok: false, operation, error: { code: 'ambiguous_team_name', message: error.message, details: { candidates: error.candidates } } };
|
|
1072
|
+
}
|
|
1043
1073
|
return {
|
|
1044
1074
|
ok: false,
|
|
1045
1075
|
operation,
|