@sideboard-ai/core 0.1.190 → 0.1.192
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/dist/{abletime-J3EGHIAV.js → abletime-53T7G667.js} +3 -1
- package/dist/{abletime-CAFQ4GEG.js → abletime-JFMBCSIQ.js} +3 -1
- package/dist/{agents-5OBZETUV.js → agents-T5VBB6X3.js} +2 -2
- package/dist/{agents-DTPVTDB5.js → agents-TXGQIK2E.js} +2 -2
- package/dist/{chunk-TEJU6UJY.js → chunk-4M2AK3O5.js} +126 -20
- package/dist/{chunk-XXEIF2IL.js → chunk-7NSXGL6L.js} +3 -3
- package/dist/{chunk-IAOXW6RI.js → chunk-FZ3G5TXM.js} +23 -16
- package/dist/{chunk-Z6TW3A5P.js → chunk-NF6ENGHS.js} +24 -17
- package/dist/{chunk-OLDZXO53.js → chunk-TWSCTJCR.js} +2 -2
- package/dist/{chunk-KEVY4GEK.js → chunk-UBQIELFS.js} +123 -20
- package/dist/{chunk-VIODP5PT.js → chunk-VV7UT3E2.js} +3 -3
- package/dist/{chunk-GBWKMWUQ.js → chunk-WHD4JNTN.js} +2 -2
- package/dist/{coordinator-prompt-LWKOL3AZ.js → coordinator-prompt-PNUDN4DW.js} +1 -1
- package/dist/{coordinator-prompt-MSC44OOM.js → coordinator-prompt-S4HHFSLI.js} +1 -1
- package/dist/{global-workspace-6G5JJH2E.js → global-workspace-2BVCJUAL.js} +1 -1
- package/dist/{global-workspace-XATJTV3N.js → global-workspace-JTBBH2K5.js} +1 -1
- package/dist/index.cjs +565 -57
- package/dist/index.d.cts +96 -6
- package/dist/index.d.ts +96 -6
- package/dist/index.js +422 -30
- package/dist/mcp/run-stdio.cjs +543 -57
- package/dist/mcp/run-stdio.js +407 -30
- package/dist/{orchestrator-BHJELEFM.js → orchestrator-4G76BOHH.js} +5 -3
- package/dist/{orchestrator-HWNGCDGW.js → orchestrator-LWEZ74RK.js} +5 -3
- package/dist/{workspaces-LMFCRXTT.js → workspaces-OY7D5RPU.js} +1 -1
- package/dist/{workspaces-FWKPWSXV.js → workspaces-ZYPME3YD.js} +1 -1
- package/package.json +1 -1
|
@@ -13,14 +13,31 @@ import {
|
|
|
13
13
|
// src/integrations/abletime-mcp.ts
|
|
14
14
|
var DEFAULT_ABLETIME_HOST = "https://track.abletime.com";
|
|
15
15
|
var ABLETIME_MCP_PATH = "/api/public/v2/mcp";
|
|
16
|
+
var ABLETIME_MCP_PM_PATH = "/api/public/v2/mcp/pm";
|
|
16
17
|
var MCP_PROTOCOL_VERSION = "2025-03-26";
|
|
18
|
+
var ABLETIME_PM_TOOL_NAMES = [
|
|
19
|
+
"set_task_assignee",
|
|
20
|
+
"set_task_priority",
|
|
21
|
+
"set_task_stage",
|
|
22
|
+
"set_task_dependency",
|
|
23
|
+
"set_task_blocked",
|
|
24
|
+
"set_task_locked",
|
|
25
|
+
"set_task_schedule",
|
|
26
|
+
"clear_task_schedule",
|
|
27
|
+
"archive_task",
|
|
28
|
+
"delete_task"
|
|
29
|
+
];
|
|
30
|
+
function abletimeToolUsesPm(name) {
|
|
31
|
+
return ABLETIME_PM_TOOL_NAMES.includes(name);
|
|
32
|
+
}
|
|
17
33
|
function normalizeAbleTimeHost(raw) {
|
|
18
34
|
const trimmed = raw?.trim() || DEFAULT_ABLETIME_HOST;
|
|
19
35
|
const withScheme = /^https?:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
|
|
20
36
|
return withScheme.replace(/\/+$/, "");
|
|
21
37
|
}
|
|
22
|
-
function abletimeMcpUrl(host) {
|
|
23
|
-
|
|
38
|
+
function abletimeMcpUrl(host, opts) {
|
|
39
|
+
const path = opts?.pm ? ABLETIME_MCP_PM_PATH : ABLETIME_MCP_PATH;
|
|
40
|
+
return `${normalizeAbleTimeHost(host)}${path}`;
|
|
24
41
|
}
|
|
25
42
|
function rewriteAbleTimeError(message) {
|
|
26
43
|
if (/INTEGRATION_AGENT_ACCESS_DISABLED|agent access/i.test(message)) {
|
|
@@ -98,7 +115,8 @@ async function abletimeMcpRequest(method, params, opts) {
|
|
|
98
115
|
throw new Error("AbleTime is not connected \u2014 paste a personal access token in Account settings");
|
|
99
116
|
}
|
|
100
117
|
const url = abletimeMcpUrl(
|
|
101
|
-
opts?.host ?? (opts?.token ? DEFAULT_ABLETIME_HOST : getAbleTimeHost())
|
|
118
|
+
opts?.host ?? (opts?.token ? DEFAULT_ABLETIME_HOST : getAbleTimeHost()),
|
|
119
|
+
{ pm: opts?.pm }
|
|
102
120
|
);
|
|
103
121
|
const res = await httpFetch(url, {
|
|
104
122
|
method: "POST",
|
|
@@ -162,7 +180,8 @@ async function callAbleTimeTool(name, args = {}, opts) {
|
|
|
162
180
|
if (!opts?.token && !isAbleTimeConnected()) {
|
|
163
181
|
throw new Error("AbleTime is not connected \u2014 paste a personal access token in Account settings");
|
|
164
182
|
}
|
|
165
|
-
const
|
|
183
|
+
const requestOpts = { ...opts, pm: opts?.pm ?? abletimeToolUsesPm(name) };
|
|
184
|
+
const call = () => abletimeMcpRequest("tools/call", { name, arguments: args }, requestOpts).then((result) => {
|
|
166
185
|
return unwrapToolResult(result);
|
|
167
186
|
});
|
|
168
187
|
try {
|
|
@@ -170,7 +189,7 @@ async function callAbleTimeTool(name, args = {}, opts) {
|
|
|
170
189
|
} catch (err) {
|
|
171
190
|
const message = err instanceof Error ? err.message : String(err);
|
|
172
191
|
if (/initialize|session|not initialized|-32000/i.test(message)) {
|
|
173
|
-
await initializeIfNeeded(
|
|
192
|
+
await initializeIfNeeded(requestOpts);
|
|
174
193
|
return await call();
|
|
175
194
|
}
|
|
176
195
|
throw err instanceof Error ? new Error(rewriteAbleTimeError(err.message)) : err;
|
|
@@ -426,39 +445,122 @@ async function commentAbleTimeTask(input, opts) {
|
|
|
426
445
|
body: rec ? firstString(rec, ["body", "text", "comment"]) || body : body
|
|
427
446
|
};
|
|
428
447
|
}
|
|
448
|
+
function isAbleTimeNoneToken(value) {
|
|
449
|
+
if (value == null) return true;
|
|
450
|
+
const s = value.trim();
|
|
451
|
+
return !s || /^(none|clear|unschedule|null)$/i.test(s);
|
|
452
|
+
}
|
|
453
|
+
function taskIdArgs(id) {
|
|
454
|
+
return { id, task_id: id, task: id };
|
|
455
|
+
}
|
|
456
|
+
function ableTimeDependencyTarget(thisId, type, relatedId) {
|
|
457
|
+
const s = type.trim().toLowerCase().replace(/[\s_-]+/g, "");
|
|
458
|
+
if (s === "none" || s === "clear" || s === "null") {
|
|
459
|
+
return { taskId: thisId, dependsOn: null };
|
|
460
|
+
}
|
|
461
|
+
if (s === "blockedby" || s === "blocked" || s === "dependson" || s === "waiton") {
|
|
462
|
+
return { taskId: thisId, dependsOn: relatedId };
|
|
463
|
+
}
|
|
464
|
+
if (s === "blocks" || s === "blocking") {
|
|
465
|
+
return { taskId: relatedId, dependsOn: thisId };
|
|
466
|
+
}
|
|
467
|
+
throw new Error(
|
|
468
|
+
`AbleTime relation type must be blocks or blockedBy (got ${type}). AbleTime models one wait-on dependency.`
|
|
469
|
+
);
|
|
470
|
+
}
|
|
471
|
+
async function setAbleTimeTaskDependency(taskId, dependsOn, opts) {
|
|
472
|
+
const args = {
|
|
473
|
+
...taskIdArgs(taskId)
|
|
474
|
+
};
|
|
475
|
+
if (dependsOn) {
|
|
476
|
+
args.depends_on = dependsOn;
|
|
477
|
+
args.depends_on_id = dependsOn;
|
|
478
|
+
args.dependency = dependsOn;
|
|
479
|
+
args.dependency_id = dependsOn;
|
|
480
|
+
args.blocked_by = dependsOn;
|
|
481
|
+
args.wait_on = dependsOn;
|
|
482
|
+
args.related_task_id = dependsOn;
|
|
483
|
+
} else {
|
|
484
|
+
args.depends_on = null;
|
|
485
|
+
args.dependency = null;
|
|
486
|
+
args.blocked_by = null;
|
|
487
|
+
args.clear = true;
|
|
488
|
+
}
|
|
489
|
+
await callAbleTimeTool("set_task_dependency", args, opts);
|
|
490
|
+
}
|
|
429
491
|
async function updateAbleTimeTask(input, opts) {
|
|
430
492
|
const id = input.id.trim();
|
|
431
493
|
if (!id) throw new Error("AbleTime task id is required");
|
|
432
494
|
const title = input.title?.trim();
|
|
433
495
|
const description = input.description;
|
|
434
496
|
const state = input.state?.trim();
|
|
435
|
-
|
|
436
|
-
|
|
497
|
+
const addRelations = input.relations?.length ? input.relations : void 0;
|
|
498
|
+
const removeRelations = input.removeRelations?.length ? input.removeRelations : void 0;
|
|
499
|
+
const updateArgs = { ...taskIdArgs(id) };
|
|
500
|
+
if (title) updateArgs.title = title;
|
|
501
|
+
if (description !== void 0) updateArgs.description = description;
|
|
502
|
+
if (input.labels !== void 0) {
|
|
503
|
+
updateArgs.tags = input.labels;
|
|
504
|
+
updateArgs.labels = input.labels;
|
|
505
|
+
updateArgs.tag_names = input.labels;
|
|
506
|
+
}
|
|
507
|
+
if (input.project !== void 0) {
|
|
508
|
+
const projectName = (input.project ?? "").trim();
|
|
509
|
+
if (isAbleTimeNoneToken(projectName)) {
|
|
510
|
+
throw new Error("AbleTime tasks stay in a project \u2014 pass a project name or id");
|
|
511
|
+
}
|
|
512
|
+
const project = await resolveAbleTimeProject(projectName, opts);
|
|
513
|
+
updateArgs.project = project.id;
|
|
514
|
+
updateArgs.project_id = project.id;
|
|
515
|
+
}
|
|
516
|
+
if (input.parent !== void 0) {
|
|
517
|
+
if (isAbleTimeNoneToken(input.parent)) {
|
|
518
|
+
updateArgs.parent = null;
|
|
519
|
+
updateArgs.parent_id = null;
|
|
520
|
+
updateArgs.related_task_id = null;
|
|
521
|
+
} else {
|
|
522
|
+
const parent = (input.parent ?? "").trim();
|
|
523
|
+
updateArgs.parent = parent;
|
|
524
|
+
updateArgs.parent_id = parent;
|
|
525
|
+
updateArgs.related_task_id = parent;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
const hasUpdateFields = Boolean(title) || description !== void 0 || input.labels !== void 0 || input.project !== void 0 || input.parent !== void 0;
|
|
529
|
+
if (!hasUpdateFields && !state && !addRelations && !removeRelations) {
|
|
530
|
+
throw new Error(
|
|
531
|
+
"abletime_update_task needs at least one of title, description, state, labels, project, parent, relations, removeRelations"
|
|
532
|
+
);
|
|
437
533
|
}
|
|
438
534
|
if (state) {
|
|
439
535
|
await callAbleTimeTool(
|
|
440
536
|
"set_task_state",
|
|
441
|
-
{ id,
|
|
537
|
+
{ ...taskIdArgs(id), state },
|
|
442
538
|
opts
|
|
443
539
|
).catch(async () => {
|
|
444
540
|
await callAbleTimeTool(
|
|
445
541
|
"update_task",
|
|
446
|
-
{
|
|
542
|
+
{ ...updateArgs, state },
|
|
447
543
|
opts
|
|
448
544
|
);
|
|
449
545
|
});
|
|
450
546
|
}
|
|
451
|
-
if (
|
|
452
|
-
await callAbleTimeTool(
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
);
|
|
547
|
+
if (hasUpdateFields) {
|
|
548
|
+
await callAbleTimeTool("update_task", updateArgs, opts);
|
|
549
|
+
}
|
|
550
|
+
for (const rel of removeRelations ?? []) {
|
|
551
|
+
const related = rel.issue.trim() || id;
|
|
552
|
+
const target = ableTimeDependencyTarget(id, rel.type, related);
|
|
553
|
+
await setAbleTimeTaskDependency(target.taskId, null, opts);
|
|
554
|
+
}
|
|
555
|
+
for (const rel of addRelations ?? []) {
|
|
556
|
+
const related = rel.issue.trim();
|
|
557
|
+
if (!related) throw new Error("AbleTime relations.issue is required (id or CRM-232)");
|
|
558
|
+
const target = ableTimeDependencyTarget(id, rel.type, related);
|
|
559
|
+
if (!target.dependsOn) {
|
|
560
|
+
await setAbleTimeTaskDependency(target.taskId, null, opts);
|
|
561
|
+
continue;
|
|
562
|
+
}
|
|
563
|
+
await setAbleTimeTaskDependency(target.taskId, target.dependsOn, opts);
|
|
462
564
|
}
|
|
463
565
|
return getAbleTimeTask(id, opts);
|
|
464
566
|
}
|
|
@@ -551,6 +653,7 @@ export {
|
|
|
551
653
|
getAbleTimeTask,
|
|
552
654
|
createAbleTimeTask,
|
|
553
655
|
commentAbleTimeTask,
|
|
656
|
+
ableTimeDependencyTarget,
|
|
554
657
|
updateAbleTimeTask,
|
|
555
658
|
ensureAbleTimeTask,
|
|
556
659
|
listAbleTimeAssignedIssues,
|
|
@@ -395,8 +395,8 @@ var COORDINATOR_TOOL_PLAYBOOK = [
|
|
|
395
395
|
"- start_board_card \u2014 same as create_thread for a ticket/PR/named branch (attaches issue text when resolvable). Then send_to_thread.",
|
|
396
396
|
"- fork_worktree \u2014 fork a worktree chat into a NEW git worktree + chat (transcript attached); optional agent; leave model unset (Auto) unless you have a reason. Not for orchestration chats.",
|
|
397
397
|
"- fork_chat \u2014 fork a worktree chat (same worktree tab) OR a Global orchestration chat (new orchestration tab); optional agent; leave model unset (Auto) unless you have a reason. Remote coordinators: use this to continue another orchestration chat on a different agent after session limits.",
|
|
398
|
-
"- send_to_thread \u2014
|
|
399
|
-
"- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply (includes last-turn usage / costUsd when the child agent reported it). wait_for_turn returns within ~45s even if the child is still working (MCP clients kill longer tool calls). stillRunning is the source of truth \u2014 if it is false, the child is not working; do not tell the user it is running or \u201Cwaiting for a gate,\u201D even if status still says running/queued. If stillRunning is true, progress is a live snapshot of tools/thinking \u2014 call wait_for_turn again. status=queued with no lastActivityAt means the child has not started yet (concurrency cap) \u2014 keep waiting; do not force_stop or
|
|
398
|
+
"- send_to_thread \u2014 steer a prompt (start/continue a chat turn; Settings \u2192 Follow-up, default steer: interrupt and start now). force_stop: true only to replace a wrong in-flight request and clear the inbox \u2014 never to check in, resume after a halt notice, or because wait_for_turn returned stillRunning (that interrupts the child mid-thought)",
|
|
399
|
+
"- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply (includes last-turn usage / costUsd when the child agent reported it). wait_for_turn returns within ~45s even if the child is still working (MCP clients kill longer tool calls). stillRunning is the source of truth \u2014 if it is false, the child is not working; do not tell the user it is running or \u201Cwaiting for a gate,\u201D even if status still says running/queued. If stillRunning is true, progress is a live snapshot of tools/thinking \u2014 call wait_for_turn again. status=queued with no lastActivityAt means the child has not started yet (concurrency cap) \u2014 keep waiting; do not force_stop or send_to_thread a check-in (that steers / interrupts). Do not send \u201Care you stuck?\u201D or assume a hang while lastActivityAt is recent. If stillRunning stays true across many waits with the same lastActivityAt, the child is stuck \u2014 tell the user; do not invent a gate. On status error, lastError (and text) is the failure \u2014 switch agent, tell the user, or retry; do not treat empty text as success. On status stopped or broken (or incomplete=true), the child was interrupted or died \u2014 resume with send_to_thread or tell the user; never treat stopped as a finished turn. Sideboard also injects a notice into this chat when a child stops unexpectedly.",
|
|
400
400
|
"- stop_thread \u2014 force-stop: kill in-flight turn AND clear queued prompts (do not leave stale queue after an interrupt)",
|
|
401
401
|
"- archive_thread / restore_thread \u2014 archive (tears down worktree when last tab) or restore",
|
|
402
402
|
"Setup / run:",
|
|
@@ -406,7 +406,7 @@ var COORDINATOR_TOOL_PLAYBOOK = [
|
|
|
406
406
|
"- get_diff \u2014 compact diff summary",
|
|
407
407
|
"- get_pr_checks \u2014 snapshot of a worktree thread's PR checks (null = no PR). Use this to inspect status. If the user gave a goal, the worktree agent watches with `gh pr checks --watch` \u2014 do not poll for the human.",
|
|
408
408
|
'- request_review \u2014 open a Review chat tab on a worktree thread (attaches .claude/skills/review/SKILL.md when present, else .context/review.md copied from .sideboard/review.md / stock; sends "Review changes in this workspace."); then wait_for_turn (loop while stillRunning) / get_turn_result on the returned id. The review stays in that chat so they can read it and type next steps \u2014 do not tell the child to comment or update the PR or ticket.',
|
|
409
|
-
"- ask_git \u2014 commit & push, open a draft PR, mark ready for review, resolve conflicts, or merge. When the worktree is clean, Sideboard pushes / opens the PR itself. When dirty, it
|
|
409
|
+
"- ask_git \u2014 commit & push, open a draft PR, mark ready for review, resolve conflicts, or merge. When the worktree is clean, Sideboard pushes / opens the PR itself. When dirty, it steers the worktree agent \u2014 then wait_for_turn (loop while stillRunning). Prefer this over paraphrasing. If ask_git / get_thread lastError says the GraphQL/PR body is too long, the branch is already pushed \u2014 send_to_thread so the worktree agent runs `gh pr create --body-file` with a short description. Do not invent SSH or auth failures from that error. If the user gave a goal (Greptile 5/5, CI green), send_to_thread that goal so the worktree agent enters the watch-fix-push loop \u2014 do not tell the human to poll.",
|
|
410
410
|
'- Merge (`ask_git` action=merge / send_to_thread "Merge PR.") only when the user explicitly asked to merge that PR. Do not merge because the work looks done, CI is green, or a typical flow includes it.',
|
|
411
411
|
'- Or send_to_thread with those exact phrases: "Commit and push.", "Commit, push, and open a draft PR.", "Ready for review.", "Merge the remote branch (main) into your branch and resolve conflicts. Then, commit and push your changes.", "Merge PR." (draft PRs: `gh pr create --draft -R <origin-owner/name>` using the workspace `github:` slug \u2014 never upstream). Never run git/gh from this orchestration cwd, and never merge the PR yourself.',
|
|
412
412
|
"Process guides:",
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "./chunk-Y4MIXGPA.js";
|
|
12
12
|
import {
|
|
13
13
|
isOrchestratorThread
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-7NSXGL6L.js";
|
|
15
15
|
import {
|
|
16
16
|
codexUnattendedGitConfigArgs,
|
|
17
17
|
mergeAgentGitAuthEnv,
|
|
@@ -2390,7 +2390,7 @@ var claudeAdapter = {
|
|
|
2390
2390
|
);
|
|
2391
2391
|
}
|
|
2392
2392
|
const mode = permissionMode(thread);
|
|
2393
|
-
const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-
|
|
2393
|
+
const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-2BVCJUAL.js");
|
|
2394
2394
|
const isOrchestrator = isOrchestratorThread2(thread);
|
|
2395
2395
|
const injectedServers = await buildInjectedMcpServers({
|
|
2396
2396
|
includeSideboard: true,
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
orchestratorSessionPoisonedByBuiltins,
|
|
18
18
|
slackCoordinatorSourceRef,
|
|
19
19
|
takenTeamSlugsForOrchestration
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-7NSXGL6L.js";
|
|
21
21
|
import "./chunk-XBLN52RZ.js";
|
|
22
22
|
import "./chunk-D6JWYJ4P.js";
|
|
23
23
|
import "./chunk-GOZ6T3AG.js";
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
orchestratorSessionPoisonedByBuiltins,
|
|
16
16
|
slackCoordinatorSourceRef,
|
|
17
17
|
takenTeamSlugsForOrchestration
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-VV7UT3E2.js";
|
|
19
19
|
import "./chunk-WXKXSZN4.js";
|
|
20
20
|
import "./chunk-6K64FJDD.js";
|
|
21
21
|
import "./chunk-J7LQVLFQ.js";
|