@rallycry/conveyor-mcp 4.3.21 → 4.3.22

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.
@@ -686,6 +686,12 @@ var ConveyorConnection = class {
686
686
  deleteTag(id) {
687
687
  return this.callService("tagService", "deleteTag", { id });
688
688
  }
689
+ previewTagMerge(params) {
690
+ return this.callService("tagService", "previewTagMerge", params);
691
+ }
692
+ mergeTag(params) {
693
+ return this.callService("tagService", "mergeTag", params);
694
+ }
689
695
  listPriorities(projectId) {
690
696
  return this.callService("priorityService", "listByProject", {
691
697
  projectId: this.resolveProjectId(projectId)
@@ -764,4 +770,4 @@ var ConveyorConnection = class {
764
770
  export {
765
771
  ConveyorConnection
766
772
  };
767
- //# sourceMappingURL=chunk-IHKZRJIH.js.map
773
+ //# sourceMappingURL=chunk-QGY4IDYB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/connection.ts","../../shared/dist/socket-core/index.js"],"sourcesContent":["/* oxlint-disable max-lines -- central MCP socket client; split after service-call helpers are extracted */\nimport { io, type Socket } from \"socket.io-client\";\nimport { buildConveyorSocketOptions, callWithAck } from \"@project/shared/socket-core\";\n\nexport interface ConveyorMcpConfig {\n apiUrl: string;\n projectToken: string;\n projectId?: string;\n /**\n * Optional default board (sub-project) scope. When set, unqualified\n * task create/list/search default to this board instead of the whole\n * project — so a connection scoped to a board lands cards on that board.\n */\n subProjectId?: string;\n}\n\n/** Actions a connection is authorized for, mirrors ConveyorCapability in @project/shared. */\nexport type ConveyorCapability = \"read\" | \"create\" | \"update\" | \"chat\" | \"files\" | \"build\";\n\n/** Immutable id + human name/slug + web URL for one connection scope level. */\nexport interface ConnectionScopeRef {\n id: string;\n name: string;\n slug: string;\n url: string;\n}\n\n/** Result of `get_connection_context` — effective identity + scope + grants. */\nexport interface ConnectionContext {\n account: { userId: string; name: string | null; email: string };\n project: ConnectionScopeRef & {\n githubRepoOwner: string | null;\n githubRepoName: string | null;\n };\n subProject: (ConnectionScopeRef & { rootPath: string | null }) | null;\n role: string;\n capabilities: ConveyorCapability[];\n managementUrls: { board: string; projectSettings: string; memberSettings: string };\n summary: string;\n}\n\n/** One layer of the verify_connection ladder. */\nexport interface VerifyConnectionLayer {\n key: string;\n label: string;\n ok: boolean;\n detail: string;\n}\n\n/** Result of `verify_connection` — a layered, verify-by-scope probe. */\nexport interface VerifyConnectionResult {\n ok: boolean;\n layers: VerifyConnectionLayer[];\n summary: string;\n nextAction: string | null;\n scope: {\n projectId: string;\n projectName: string;\n subProjectId: string | null;\n subProjectName: string | null;\n capabilities: ConveyorCapability[];\n };\n}\n\n/** The project + board a task mutation actually landed on. Returned so a caller\n * can confirm where the write went (name-vs-board-label ambiguity guard). */\nexport interface EffectiveScope {\n projectId: string;\n subProjectId: string | null;\n}\n\n/** One board under the connected project, for list_accessible_subprojects. */\nexport interface AccessibleSubproject {\n id: string;\n name: string;\n slug: string;\n url: string;\n rootPath: string | null;\n role: string;\n capabilities: ConveyorCapability[];\n}\n\n/**\n * Canonical risk levels — kept in lockstep with `RISK_LEVELS` in\n * `@project/shared` (conveyor-mcp is published standalone and does not depend on\n * the shared package, so the vocabulary is duplicated here).\n */\nexport type RiskLevel = \"critical\" | \"high\" | \"medium\" | \"low\";\n\n/** A single PTY output frame broadcast on the `pty:data` room event. */\nexport interface PtyDataChunk {\n sessionId: string;\n seq: number;\n data: string;\n cols?: number;\n rows?: number;\n}\n\n/** Ring-buffer snapshot returned by `ptyAttach` for catch-up replay. */\nexport interface PtyAttachSnapshot {\n sessionId: string;\n chunks: { seq: number; data: string }[];\n cols: number;\n rows: number;\n totalBytes: number;\n}\n\n/**\n * Result of `getActivePtySession`. `sessionId` is null until the cloud agent\n * has booted a PTY and produced at least one ring frame (readiness signal).\n */\nexport interface ActivePtySession {\n sessionId: string | null;\n cols?: number;\n rows?: number;\n}\n\nexport interface WorkspaceAttachInfo {\n taskId: string;\n sessionId: string;\n workspaceRoot: string;\n /** \"codespace\" means preview-only — GitHub owns the VM's forwarded ports, so\n * `tunnelUrl`/`attachToken`/`ssh` are null/absent. Older servers omit it. */\n backend?: \"gke\" | \"codespace\";\n tunnelUrl: string | null;\n attachToken: string | null;\n expiresAt: string;\n previewPorts: Array<{ port: number; label: string }>;\n previewUrls: Record<string, string>;\n ssh?: {\n remotePort: number;\n preferredLocalPort: number;\n username: string;\n };\n}\n\n/** One Cloud Logging entry as returned by the API's queryProjectGcpLogs. */\nexport interface GcpLogEntry {\n timestamp: string;\n severity: string;\n message: string;\n resource: Record<string, string>;\n labels: Record<string, string>;\n resourceType?: string;\n insertId?: string;\n trace?: string;\n httpRequest?: { status?: number; method?: string; url?: string; latencyMs?: number };\n payload?: string;\n payloadTruncated?: boolean;\n}\n\nexport interface GcpLogQueryResult {\n entries: GcpLogEntry[];\n hasMore: boolean;\n nextPageToken?: string;\n scopedServices?: string[];\n error?: string;\n}\n\n/** Loki entries normalize onto the same row shape as Cloud Logging entries. */\nexport interface GrafanaLogQueryResult {\n entries: GcpLogEntry[];\n hasMore: boolean;\n /** The LogQL the server composed or executed — agents can iterate on it. */\n logql?: string;\n error?: string;\n}\n\n/**\n * One row of the project onboarding checklist. Mirrors the API's\n * `ReadinessCheck` (conveyor-mcp is published standalone and does not depend on\n * `@project/shared`, so the shape is duplicated here).\n */\nexport interface OnboardingCheck {\n key: string;\n status: \"ok\" | \"warn\" | \"fail\";\n reason: string;\n fix?: {\n label: string;\n href?: string | null;\n action?: string;\n };\n}\n\n/** Result of `get_onboarding_status` — the project's setup readiness report. */\nexport interface OnboardingStatus {\n ok: boolean;\n checks: OnboardingCheck[];\n bypassedAt: string | null;\n}\n\n/** The single next onboarding step. Mirrors the API's `OnboardingStep`. */\nexport interface OnboardingStep {\n key: string;\n status: \"warn\" | \"fail\";\n title: string;\n reason: string;\n guidance: string;\n autoFixable: boolean;\n fix?: {\n label: string;\n href?: string | null;\n action?: string;\n };\n connectUrls?: Record<string, string>;\n}\n\n/** Result of `get_onboarding_step` — the choose-your-own-adventure step driver.\n * Mirrors the API's `OnboardingStepReport`. */\nexport interface OnboardingStepReport {\n done: boolean;\n ok: boolean;\n bypassedAt: string | null;\n step: OnboardingStep | null;\n remaining: Array<{ key: string; status: \"warn\" | \"fail\"; reason: string }>;\n checks: OnboardingCheck[];\n}\n\nexport interface MoveCardResult {\n cardId: string;\n sourceProjectId: string;\n destinationProjectId: string;\n slug: string;\n clearedFields: string[];\n}\n\nexport interface ProjectConnectUrls {\n gcpConnect: string;\n gcpSettings: string;\n memberSettings: string;\n projectSettings: string;\n setupWizard: string;\n}\n\nexport interface TagSummary {\n id: string;\n name: string;\n color: string;\n description?: string | null;\n}\n\n/** A tag context-path link (rule/doc/file/folder) loaded into agent context. */\nexport interface ContextPathInput {\n type: \"rule\" | \"doc\" | \"file\" | \"folder\";\n path: string;\n label?: string;\n}\n\nexport interface PrioritySummary {\n id: string;\n value: number;\n name: string;\n color: string;\n description?: string | null;\n}\n\nconst NO_PROJECT_SELECTED_MESSAGE =\n \"No Conveyor project selected. Pass projectId to this tool or configure CONVEYOR_PROJECT_ID.\";\n\n/** Auth failures never recover on retry — match them to fail fast with guidance. */\nconst AUTH_ERROR_RE = /token|unauthor|forbidden|not authenticated|invalid auth/i;\n\n/**\n * Turn a raw server error into an actionable message. Most errors pass through\n * unchanged; the common-but-opaque \"Insufficient permissions\" gets the missing\n * context about why (project role too low) and how to fix it.\n */\nfunction enrichToolError(error?: string, fallback?: string): string {\n const base = error ?? fallback ?? \"Request failed\";\n if (/insufficient permissions/i.test(base)) {\n return (\n `${base}: your Conveyor project role can't perform this action. ` +\n `Creating/updating tasks, builds, and PRs requires Moderate access or higher — ` +\n `ask a project admin to raise your role.`\n );\n }\n return base;\n}\n\nexport class ConveyorConnection {\n private socket: Socket | null = null;\n private config: ConveyorMcpConfig;\n\n constructor(config: ConveyorMcpConfig) {\n this.config = config;\n }\n\n get projectId(): string {\n return this.resolveProjectId();\n }\n\n private resolveProjectId(projectId?: string): string {\n const resolved = projectId ?? this.config.projectId;\n if (!resolved) throw new Error(NO_PROJECT_SELECTED_MESSAGE);\n return resolved;\n }\n\n /** The configured default board (CONVEYOR_SUBPROJECT_ID), if any. */\n get defaultSubProjectId(): string | undefined {\n return this.config.subProjectId;\n }\n\n /**\n * Resolve the board scope for a task create/list/search:\n * - `null` explicitly means \"the whole project\" (never fall back to the default).\n * - `undefined` (not passed) falls back to the connection's default board.\n * - a concrete id is used as-is.\n * Returning `undefined` leaves the request unscoped (whole project).\n */\n private resolveSubProjectId(subProjectId?: string | null): string | undefined {\n if (subProjectId === null) return undefined;\n return subProjectId ?? this.config.subProjectId;\n }\n\n private normalizeProjectList(response: unknown): unknown[] {\n if (Array.isArray(response)) return response;\n if (typeof response !== \"object\" || response === null) return [];\n const record = response as Record<string, unknown>;\n if (Array.isArray(record.items)) return record.items;\n if (Array.isArray(record.projects)) return record.projects;\n if (Array.isArray(record.data)) return record.data;\n return [];\n }\n\n connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n let settled = false;\n let attempts = 0;\n const maxAttempts = 15;\n\n this.socket = io(\n this.config.apiUrl,\n buildConveyorSocketOptions({\n projectToken: this.config.projectToken,\n runnerMode: \"project\",\n }),\n );\n\n this.socket.on(\"connect\", () => {\n if (!settled) {\n settled = true;\n // Subscribe to project room for events\n this.socket?.emit(\"projectService:subscribe\", { id: this.config.projectId });\n resolve();\n }\n });\n\n this.socket.on(\"connect_error\", (err) => {\n const message = err?.message ?? \"unknown error\";\n // An auth rejection (e.g. \"Invalid project token\") will never succeed on\n // retry, so fail fast with an actionable message instead of silently\n // retrying for ~30s and then dying with a generic error.\n if (!settled && AUTH_ERROR_RE.test(message)) {\n settled = true;\n this.socket?.close();\n reject(\n new Error(\n `Conveyor rejected the connection: ${message}. The project token is ` +\n `likely invalid or expired — regenerate it in the web app ` +\n `(User Settings → Connect your coding agent) and update CONVEYOR_USER_TOKEN ` +\n `(or legacy CONVEYOR_PROJECT_TOKEN).`,\n ),\n );\n return;\n }\n attempts++;\n if (!settled && attempts >= maxAttempts) {\n settled = true;\n reject(new Error(`Failed to connect to ${this.config.apiUrl}: ${message}`));\n }\n });\n });\n }\n\n // ── Service method call (agentSessionService:*) ─────────────────────\n\n private call<T>(method: string, data: unknown, timeoutMs = 15_000): Promise<T> {\n const socket = this.socket;\n if (!socket) throw new Error(\"Not connected\");\n return callWithAck<T>(socket, `agentSessionService:${method}`, data, {\n timeoutMs,\n makeTimeoutError: () => new Error(`Request timed out: ${method}`),\n makeFailureError: (error) => new Error(enrichToolError(error, `${method} failed`)),\n });\n }\n\n /**\n * Fire-and-forget emit (no ack). The quickdraw-core server method handler\n * invokes the ack callback via optional chaining, so omitting it still runs\n * the full auth/schema/ACL pipeline — it just skips the response round-trip.\n * Used for high-frequency PTY input/resize so each keystroke does not arm a\n * 15s timeout timer.\n */\n private emit(method: string, data: unknown): void {\n const socket = this.socket;\n if (!socket) throw new Error(\"Not connected\");\n socket.emit(`agentSessionService:${method}`, data);\n }\n\n private callService<T>(\n serviceName: string,\n method: string,\n data: unknown,\n timeoutMs = 15_000,\n ): Promise<T> {\n const socket = this.socket;\n if (!socket) throw new Error(\"Not connected\");\n return callWithAck<T>(socket, `${serviceName}:${method}`, data, {\n timeoutMs,\n makeTimeoutError: () => new Error(`Request timed out: ${serviceName}:${method}`),\n makeFailureError: (error) => new Error(enrichToolError(error, `${method} failed`)),\n });\n }\n\n // ── GCP Logs ────────────────────────────────────────────────────────\n\n queryGcpLogs(params: {\n projectId?: string;\n env?: \"prod\" | \"dev\" | \"claudespace\";\n severity?: string;\n services?: string[];\n sqlInstances?: string[];\n allServices?: boolean;\n search?: string;\n filter?: string;\n startTime?: string;\n endTime?: string;\n limit?: number;\n pageToken?: string;\n }): Promise<GcpLogQueryResult> {\n const { projectId, ...rest } = params;\n return this.call(\n \"queryProjectGcpLogs\",\n { projectId: this.resolveProjectId(projectId), ...rest },\n 30_000,\n );\n }\n\n // ── Grafana Logs ────────────────────────────────────────────────────\n\n queryGrafanaLogs(params: {\n projectId?: string;\n env?: \"prod\" | \"dev\";\n services?: string[];\n level?: \"debug\" | \"info\" | \"warn\" | \"error\" | \"fatal\";\n search?: string;\n logql?: string;\n startTime?: string;\n endTime?: string;\n limit?: number;\n }): Promise<GrafanaLogQueryResult> {\n const { projectId, ...rest } = params;\n return this.call(\n \"queryProjectGrafanaLogs\",\n { projectId: this.resolveProjectId(projectId), ...rest },\n 30_000,\n );\n }\n\n // ── Task Queries ────────────────────────────────────────────────────\n\n listTasks(params: {\n projectId?: string;\n status?: string;\n typeFilters?: string[];\n assigneeId?: string;\n unassigned?: boolean;\n subProjectId?: string | null;\n limit?: number;\n }): Promise<unknown[]> {\n const { projectId, subProjectId, ...rest } = params;\n return this.call(\"listProjectTasks\", {\n projectId: this.resolveProjectId(projectId),\n subProjectId: this.resolveSubProjectId(subProjectId),\n ...rest,\n });\n }\n\n getTask(taskId: string, projectId?: string): Promise<unknown> {\n return this.call(\"getProjectTask\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n });\n }\n\n getCardBySlug(slug: string, projectId?: string): Promise<unknown> {\n return this.call(\"getProjectTask\", {\n projectId: this.resolveProjectId(projectId),\n taskId: slug,\n });\n }\n\n searchTasks(params: {\n projectId?: string;\n tagNames?: string[];\n searchQuery?: string;\n statusFilters?: string[];\n typeFilters?: string[];\n assigneeId?: string;\n unassigned?: boolean;\n subProjectId?: string | null;\n limit?: number;\n }): Promise<unknown[]> {\n const { projectId, subProjectId, ...rest } = params;\n return this.call(\"searchProjectTasks\", {\n projectId: this.resolveProjectId(projectId),\n subProjectId: this.resolveSubProjectId(subProjectId),\n ...rest,\n });\n }\n\n // ── Task Mutations ──────────────────────────────────────────────────\n\n async createTask(params: {\n projectId?: string;\n title: string;\n description?: string;\n plan?: string;\n status?: string;\n subProjectId?: string | null;\n tags?: string[];\n }): Promise<{ id: string; slug: string; effectiveScope: EffectiveScope }> {\n const { projectId, subProjectId, tags, ...rest } = params;\n const resolvedProjectId = this.resolveProjectId(projectId);\n const resolvedSubProjectId = this.resolveSubProjectId(subProjectId);\n const result = await this.call<{ id: string; slug: string }>(\"createProjectTask\", {\n projectId: resolvedProjectId,\n subProjectId: resolvedSubProjectId,\n ...rest,\n });\n if (tags && tags.length > 0) {\n await this.assignTagsToTask(result.id, resolvedProjectId, tags);\n }\n return {\n ...result,\n effectiveScope: {\n projectId: resolvedProjectId,\n subProjectId: resolvedSubProjectId ?? null,\n },\n };\n }\n\n async updateTask(params: {\n projectId?: string;\n taskId: string;\n title?: string;\n description?: string;\n plan?: string;\n status?: string;\n risk?: RiskLevel | null;\n assignedUserId?: string | null;\n subProjectId?: string | null;\n addTags?: string[];\n removeTags?: string[];\n }): Promise<{\n id: string;\n status: string | null;\n risk: RiskLevel | null;\n assignedUserId: string | null;\n addedTags: string[];\n removedTags: string[];\n }> {\n const { projectId, addTags, removeTags, ...rest } = params;\n const resolvedProjectId = this.resolveProjectId(projectId);\n\n // A core-field update is only sent when at least one non-tag field changed —\n // UpdateProjectTaskRequestSchema rejects a no-op (tag-only) update.\n const hasCoreUpdate =\n rest.title !== undefined ||\n rest.description !== undefined ||\n rest.plan !== undefined ||\n rest.status !== undefined ||\n rest.risk !== undefined ||\n rest.assignedUserId !== undefined ||\n rest.subProjectId !== undefined;\n\n // Tag mutations route through TagService (same path as the web UI) so the\n // task:tagsAssigned/Removed events, Slack sync, and card re-emit all fire.\n const removedTags = removeTags ?? [];\n const addedTags = addTags ?? [];\n if (removedTags.length > 0) {\n await this.removeTagsFromTask(rest.taskId, resolvedProjectId, removedTags);\n }\n if (addedTags.length > 0) {\n await this.assignTagsToTask(rest.taskId, resolvedProjectId, addedTags);\n }\n\n if (hasCoreUpdate) {\n const result = await this.call<{\n id: string;\n status: string;\n risk: RiskLevel | null;\n assignedUserId: string | null;\n }>(\"updateProjectTask\", { projectId: resolvedProjectId, ...rest });\n return { ...result, addedTags, removedTags };\n }\n\n return {\n id: rest.taskId,\n status: null,\n risk: null,\n assignedUserId: null,\n addedTags,\n removedTags,\n };\n }\n\n /** Resolve tag names to IDs within a project, throwing on any unknown name. */\n private async resolveTagIds(projectId: string, names: string[]): Promise<string[]> {\n if (names.length === 0) return [];\n const tags = await this.listTags(projectId);\n const byName = new Map(tags.map((t) => [t.name.toLowerCase(), t.id]));\n const ids: string[] = [];\n const unknown: string[] = [];\n for (const name of names) {\n const id = byName.get(name.toLowerCase());\n if (id) ids.push(id);\n else unknown.push(name);\n }\n if (unknown.length > 0) {\n const available = tags.map((t) => t.name).join(\", \") || \"(none)\";\n throw new Error(\n `Unknown tag name(s): ${unknown.join(\", \")}. Available tags: ${available}. ` +\n `Create the tag first with manage_tags.`,\n );\n }\n return [...new Set(ids)];\n }\n\n private async assignTagsToTask(\n taskId: string,\n projectId: string,\n names: string[],\n ): Promise<void> {\n const tagIds = await this.resolveTagIds(projectId, names);\n if (tagIds.length === 0) return;\n await this.callService(\"tagService\", \"assignToTask\", { taskId, tagIds });\n }\n\n private async removeTagsFromTask(\n taskId: string,\n projectId: string,\n names: string[],\n ): Promise<void> {\n const tagIds = await this.resolveTagIds(projectId, names);\n if (tagIds.length === 0) return;\n await this.callService(\"tagService\", \"removeFromTask\", { taskId, tagIds });\n }\n\n /** Guarded status transition used by the review tools (approve/request). */\n transitionTaskStatus(params: {\n projectId?: string;\n taskId: string;\n toStatus: string;\n expectedFromStatus?: string;\n risk?: RiskLevel;\n }): Promise<{ id: string; status: string; risk: RiskLevel | null }> {\n const { projectId, ...rest } = params;\n return this.call(\"transitionProjectTaskStatus\", {\n projectId: this.resolveProjectId(projectId),\n ...rest,\n });\n }\n\n moveCard(params: {\n projectId?: string;\n taskId: string;\n destinationProjectId: string;\n }): Promise<MoveCardResult> {\n const { projectId, ...rest } = params;\n return this.call(\"moveProjectCard\", {\n projectId: this.resolveProjectId(projectId),\n ...rest,\n });\n }\n\n // ── Reviewers & Members ─────────────────────────────────────────────\n\n addReviewer(params: {\n projectId?: string;\n taskId: string;\n userId: string;\n }): Promise<{ taskId: string; reviewers: Array<{ userId: string; name: string | null }> }> {\n const { projectId, ...rest } = params;\n return this.call(\"addProjectTaskReviewer\", {\n projectId: this.resolveProjectId(projectId),\n ...rest,\n });\n }\n\n removeReviewer(params: {\n projectId?: string;\n taskId: string;\n userId: string;\n }): Promise<{ taskId: string; reviewers: Array<{ userId: string; name: string | null }> }> {\n const { projectId, ...rest } = params;\n return this.call(\"removeProjectTaskReviewer\", {\n projectId: this.resolveProjectId(projectId),\n ...rest,\n });\n }\n\n listProjectMembers(\n projectId?: string,\n ): Promise<Array<{ userId: string; name: string | null; email: string; level: string }>> {\n return this.call(\"listProjectMembers\", {\n projectId: this.resolveProjectId(projectId),\n });\n }\n\n async listProjects(): Promise<unknown[]> {\n const response = await this.call(\"listAccessibleProjects\", { pageSize: 100 });\n return this.normalizeProjectList(response);\n }\n\n // ── Build Management ────────────────────────────────────────────────\n\n startBuild(taskId: string, projectId?: string): Promise<{ taskId: string; status: string }> {\n return this.call(\"startProjectBuild\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n });\n }\n\n stopBuild(taskId: string, projectId?: string): Promise<{ taskId: string; stopped: boolean }> {\n return this.call(\"stopProjectBuild\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n });\n }\n\n sleepTask(\n taskId: string,\n projectId?: string,\n ): Promise<{ taskId: string; codespaceStatus: string }> {\n return this.callService(\"cloudBuildService\", \"sleepCloudBuild\", {\n taskId,\n projectId: this.resolveProjectId(projectId),\n });\n }\n\n resumeTask(taskId: string, projectId?: string): Promise<{ status: string }> {\n return this.callService(\"cloudBuildService\", \"wakeCodespace\", {\n taskId,\n projectId: this.resolveProjectId(projectId),\n });\n }\n\n deleteTaskEnvironment(\n taskId: string,\n projectId?: string,\n ): Promise<{ taskId: string; status: string }> {\n return this.callService(\"cloudBuildService\", \"deleteTaskEnvironment\", {\n taskId,\n projectId: this.resolveProjectId(projectId),\n });\n }\n\n getBuildStatus(\n taskId: string,\n projectId?: string,\n ): Promise<{\n session: { status: string | null; agentRunnerStatus: string | null } | null;\n }> {\n // Uses getProjectTask and extracts the session field\n return this.call<Record<string, unknown>>(\"getProjectTask\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n }).then((task) => ({\n session:\n (task?.session as {\n status: string | null;\n agentRunnerStatus: string | null;\n }) ?? null,\n }));\n }\n\n getWorkspaceAttachInfo(taskId: string, sshPublicKey?: string): Promise<WorkspaceAttachInfo> {\n return this.callService(\"cloudBuildService\", \"getWorkspaceAttachInfo\", {\n taskId,\n sshPublicKey,\n });\n }\n\n // ── Chat ────────────────────────────────────────────────────────────\n\n getTaskChat(taskId: string, limit?: number, projectId?: string): Promise<unknown[]> {\n // Uses getProjectTask and extracts chatMessages\n return this.call<Record<string, unknown>>(\"getProjectTask\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n }).then((task) => {\n const messages = (task?.chatMessages ?? []) as unknown[];\n return limit ? messages.slice(-limit) : messages;\n });\n }\n\n postToTaskChat(\n taskId: string,\n content: string,\n projectId?: string,\n ): Promise<{ messageId: string }> {\n return this.call(\"postToProjectTaskChat\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n content,\n });\n }\n\n // ── CLI History ─────────────────────────────────────────────────────\n\n getTaskCli(\n taskId: string,\n limit?: number,\n source?: string,\n projectId?: string,\n ): Promise<{ type: string; data: Record<string, unknown>; timestamp: string }[]> {\n return this.call(\"getProjectTaskCli\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n limit,\n source,\n });\n }\n\n // ── Session / Pod State ─────────────────────────────────────────────\n\n getTaskSessions(\n taskId: string,\n projectId?: string,\n ): Promise<\n Array<{\n taskId: string;\n slug: string;\n title: string;\n type: string;\n status: string;\n codeReviewStatus: string | null;\n codeReviewAttempts: number;\n workspaces: Array<{\n id: string;\n purpose: string;\n desiredState: string;\n observedState: string;\n branch: string | null;\n checkoutRef: string | null;\n createdAt: string;\n updatedAt: string;\n pod: { name: string; namespace: string; phase: string; imageUri: string | null } | null;\n sessions: Array<{\n id: string;\n role: string;\n mode: string;\n status: string;\n userId: string;\n leaseUntil: string | null;\n createdAt: string;\n }>;\n }>;\n sessions: Array<{\n id: string;\n provider: string;\n instanceName: string | null;\n status: string;\n agentRunnerStatus: string | null;\n lastHeartbeatAt: string | null;\n agentRunningAt: string | null;\n lastAgentEvent: string | null;\n deletionRequestedAt: string | null;\n deletionAttempts: number;\n createdAt: string;\n stoppedAt: string | null;\n }>;\n }>\n > {\n return this.call(\"getProjectTaskSessions\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n });\n }\n\n // ── Project Info ────────────────────────────────────────────────────\n\n listTags(projectId?: string): Promise<\n {\n id: string;\n name: string;\n color: string;\n description: string | null;\n parentTagIds: string[];\n childTagIds: string[];\n hasOverview: boolean;\n /** Rule/doc/file/folder links the tag wires into agent context; `[]` when none. */\n contextPaths: ContextPathInput[];\n }[]\n > {\n return this.call(\"listProjectTags\", {\n projectId: this.resolveProjectId(projectId),\n });\n }\n\n getTag(params: { projectId?: string; tag: string }): Promise<unknown> {\n return this.call(\"getProjectTag\", {\n projectId: this.resolveProjectId(params.projectId),\n tag: params.tag,\n });\n }\n\n getProjectSummary(projectId?: string): Promise<unknown> {\n return this.call(\"getProjectSummary\", {\n projectId: this.resolveProjectId(projectId),\n });\n }\n\n // ── Connection Scope & Verification ─────────────────────────────────\n\n /** Effective account/project/board identity + capabilities for this token. */\n getConnectionContext(projectId?: string): Promise<ConnectionContext> {\n return this.call(\"getConnectionContext\", {\n projectId: this.resolveProjectId(projectId),\n subProjectId: this.config.subProjectId ?? null,\n });\n }\n\n /** Layered verify-by-scope probe (auth → account → project → board →\n * capabilities → read). Proves create/update on the intended board. */\n verifyConnection(params?: {\n projectId?: string;\n intendedActions?: ConveyorCapability[];\n }): Promise<VerifyConnectionResult> {\n return this.call(\"verifyConnection\", {\n projectId: this.resolveProjectId(params?.projectId),\n subProjectId: this.config.subProjectId ?? null,\n intendedActions: params?.intendedActions,\n });\n }\n\n /** Boards under the connected project with id/name/slug/url/role/capabilities. */\n listAccessibleSubprojects(projectId?: string): Promise<AccessibleSubproject[]> {\n return this.call(\"listAccessibleSubprojects\", {\n projectId: this.resolveProjectId(projectId),\n });\n }\n\n getOnboardingStatus(projectId?: string): Promise<OnboardingStatus> {\n // Each readiness probe fans out to GitHub / GCP, so allow more headroom\n // than the default request timeout.\n return this.call(\n \"getProjectOnboardingStatus\",\n { projectId: this.resolveProjectId(projectId) },\n 30_000,\n );\n }\n\n getOnboardingStep(projectId?: string): Promise<OnboardingStepReport> {\n // Reuses the same readiness probes (GitHub / GCP fan-out), so allow the same\n // extended timeout as get_onboarding_status.\n return this.call(\n \"getProjectOnboardingStep\",\n { projectId: this.resolveProjectId(projectId) },\n 30_000,\n );\n }\n\n // ── Review Flow ─────────────────────────────────────────────────────\n\n async approveTask(\n taskId: string,\n projectId?: string,\n risk?: RiskLevel,\n ): Promise<{ status: string }> {\n const targetProjectId = this.resolveProjectId(projectId);\n // Determine next status based on current status\n const task = (await this.call(\"getProjectTask\", {\n projectId: targetProjectId,\n taskId,\n })) as { status: string } | null;\n\n if (!task) throw new Error(\"Task not found\");\n\n const nextStatus = task.status === \"ReviewPR\" ? \"ReviewDev\" : \"Complete\";\n\n // Guarded transition; approval attempts a raise-only \"low\" risk by default.\n const result = await this.transitionTaskStatus({\n projectId: targetProjectId,\n taskId,\n toStatus: nextStatus,\n expectedFromStatus: task.status,\n risk: risk ?? \"low\",\n });\n return { status: result.status };\n }\n\n async requestChanges(\n taskId: string,\n feedback: string,\n projectId?: string,\n risk?: RiskLevel,\n ): Promise<void> {\n const targetProjectId = this.resolveProjectId(projectId);\n const task = (await this.call(\"getProjectTask\", {\n projectId: targetProjectId,\n taskId,\n })) as { status: string } | null;\n if (!task) throw new Error(\"Task not found\");\n\n // Post feedback to task chat then move to InProgress via the guarded\n // transition; requested changes attempt a raise-only \"medium\" risk.\n await this.postToTaskChat(taskId, feedback, targetProjectId);\n await this.transitionTaskStatus({\n projectId: targetProjectId,\n taskId,\n toStatus: \"InProgress\",\n expectedFromStatus: task.status,\n risk: risk ?? \"medium\",\n });\n }\n\n approveAndMergePR(\n childTaskId: string,\n projectId?: string,\n ): Promise<{ merged: boolean; childTaskId: string; prNumber: number }> {\n return this.call(\"approveProjectMergePR\", {\n projectId: this.resolveProjectId(projectId),\n childTaskId,\n });\n }\n\n // ── File Attachments ────────────────────────────────────────────────\n\n listTaskFiles(taskId: string, projectId?: string): Promise<unknown[]> {\n return this.call(\"listProjectTaskFiles\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n });\n }\n\n getAttachment(\n taskId: string,\n fileId: string,\n opts?: { offset?: number; maxBytes?: number; projectId?: string },\n ): Promise<unknown> {\n const payload: Record<string, unknown> = {\n projectId: this.resolveProjectId(opts?.projectId),\n taskId,\n fileId,\n };\n if (opts?.offset !== undefined) payload.offset = opts.offset;\n if (opts?.maxBytes !== undefined) payload.maxBytes = opts.maxBytes;\n return this.call(\"getProjectAttachment\", payload);\n }\n\n requestFileUpload(\n taskId: string,\n params: { fileName: string; mimeType: string; fileSize: number; projectId?: string },\n ): Promise<{ fileId: string; uploadUrl: string }> {\n const { projectId, ...rest } = params;\n return this.call(\"requestProjectFileUpload\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n ...rest,\n });\n }\n\n confirmFileUpload(\n taskId: string,\n fileId: string,\n comment?: string,\n projectId?: string,\n ): Promise<{ fileId: string; fileName: string; downloadUrl?: string; messageId?: string }> {\n const payload: Record<string, unknown> = {\n projectId: this.resolveProjectId(projectId),\n taskId,\n fileId,\n };\n if (comment !== undefined) payload.comment = comment;\n // Confirm verifies the object in GCS before marking it uploaded — allow\n // extra headroom for the storage round-trips.\n return this.call(\"confirmProjectFileUpload\", payload, 30_000);\n }\n\n // ── Releases ────────────────────────────────────────────────────────\n\n createRelease(\n taskIds?: string[],\n projectId?: string,\n ): Promise<{ taskId: string; version: string }> {\n // Full releases create the release branch + PR against GitHub synchronously;\n // allow the same headroom as createPullRequest.\n return this.call(\n \"createProjectRelease\",\n { projectId: this.resolveProjectId(projectId), taskIds },\n 45_000,\n );\n }\n\n addTasksToRelease(\n taskIds: string[],\n projectId?: string,\n ): Promise<{ releaseTaskId: string; added: number; releaseBranchUpdated: boolean }> {\n // Adding cards also merges the latest dev into the release branch on\n // GitHub — allow the same headroom as createRelease.\n return this.call(\n \"addTasksToProjectRelease\",\n { projectId: this.resolveProjectId(projectId), taskIds },\n 45_000,\n );\n }\n\n // ── Pull Requests ───────────────────────────────────────────────────\n\n createPullRequest(params: {\n projectId?: string;\n taskId: string;\n title: string;\n body: string;\n head?: string;\n base?: string;\n }): Promise<{ prNumber: number; prUrl: string }> {\n const { projectId, ...rest } = params;\n // PR creation makes several sequential GitHub API calls (token, create,\n // existing-PR lookup); allow more headroom than the default request timeout.\n return this.call(\n \"createProjectPullRequest\",\n { projectId: this.resolveProjectId(projectId), ...rest },\n 45_000,\n );\n }\n\n // ── Subtasks ────────────────────────────────────────────────────────\n\n async createSubtask(params: {\n projectId?: string;\n parentTaskId: string;\n title: string;\n description?: string;\n plan?: string;\n ordinal?: number;\n storyPointValue?: number;\n followParentStatus?: boolean;\n dependsOn?: string[];\n tags?: string[];\n }): Promise<{ id: string; slug: string }> {\n const { projectId, tags, ...rest } = params;\n const resolvedProjectId = this.resolveProjectId(projectId);\n const result = await this.call<{ id: string; slug: string }>(\"createProjectSubtask\", {\n projectId: resolvedProjectId,\n ...rest,\n });\n if (tags && tags.length > 0) {\n await this.assignTagsToTask(result.id, resolvedProjectId, tags);\n }\n return result;\n }\n\n updateSubtask(params: {\n projectId?: string;\n subtaskId: string;\n title?: string;\n description?: string;\n plan?: string;\n status?: string;\n ordinal?: number;\n storyPointValue?: number;\n followParentStatus?: boolean;\n dependsOn?: string[];\n }): Promise<{ id: string; status: string }> {\n const { projectId, ...rest } = params;\n return this.call(\"updateProjectSubtask\", {\n projectId: this.resolveProjectId(projectId),\n ...rest,\n });\n }\n\n listSubtasks(taskId: string, projectId?: string): Promise<unknown[]> {\n return this.call(\"listProjectSubtasks\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n });\n }\n\n deleteSubtask(subtaskId: string, projectId?: string): Promise<{ deleted: boolean }> {\n return this.call(\"deleteProjectSubtask\", {\n projectId: this.resolveProjectId(projectId),\n subtaskId,\n });\n }\n\n // ── Dependencies ────────────────────────────────────────────────────\n\n getDependencies(taskId: string, projectId?: string): Promise<unknown[]> {\n return this.call(\"getProjectTaskDependencies\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n });\n }\n\n addDependency(params: {\n projectId?: string;\n taskId: string;\n dependsOnSlugOrId: string;\n }): Promise<{ success: boolean }> {\n const { projectId, ...rest } = params;\n return this.call(\"addProjectTaskDependency\", {\n projectId: this.resolveProjectId(projectId),\n ...rest,\n });\n }\n\n removeDependency(params: {\n projectId?: string;\n taskId: string;\n dependsOnSlugOrId: string;\n }): Promise<{ success: boolean }> {\n const { projectId, ...rest } = params;\n return this.call(\"removeProjectTaskDependency\", {\n projectId: this.resolveProjectId(projectId),\n ...rest,\n });\n }\n\n // ── Manual Test Checklist ───────────────────────────────────────────\n\n listManualTests(\n taskId: string,\n projectId?: string,\n ): Promise<\n Array<{\n id: string;\n type: string;\n title: string;\n ordinal: number;\n createdAt: string;\n checked: boolean;\n failures: Array<{ userName: string | null; reason: string | null; createdAt: string }>;\n }>\n > {\n return this.call(\"listProjectManualTests\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n });\n }\n\n setManualTests(\n taskId: string,\n items: Array<{ title: string }>,\n projectId?: string,\n ): Promise<{ created: number; skipped: number }> {\n return this.call(\"setProjectManualTests\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n items,\n });\n }\n\n editManualTest(\n taskId: string,\n title: string,\n newTitle: string,\n projectId?: string,\n ): Promise<{ updated: boolean }> {\n return this.call(\"editProjectManualTest\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n title,\n newTitle,\n });\n }\n\n removeManualTest(\n taskId: string,\n title: string,\n projectId?: string,\n ): Promise<{ removed: boolean }> {\n return this.call(\"removeProjectManualTest\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n title,\n });\n }\n\n approveManualTest(\n taskId: string,\n title: string,\n projectId?: string,\n ): Promise<{ approved: boolean }> {\n return this.call(\"approveProjectManualTest\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n title,\n });\n }\n\n rejectManualTest(\n taskId: string,\n title: string,\n reason: string,\n projectId?: string,\n ): Promise<{ rejected: boolean }> {\n return this.call(\"rejectProjectManualTest\", {\n projectId: this.resolveProjectId(projectId),\n taskId,\n title,\n reason,\n });\n }\n\n queryManualTests(params: {\n projectId?: string;\n cardStatuses?: string[];\n testStatuses?: Array<\"open\" | \"approved\" | \"rejected\">;\n }): Promise<\n Array<{\n taskId: string;\n slug: string;\n title: string;\n status: string;\n tests: Array<{\n id: string;\n title: string;\n status: \"open\" | \"approved\" | \"rejected\";\n failures: Array<{ userName: string | null; reason: string | null; createdAt: string }>;\n }>;\n }>\n > {\n const { projectId, ...rest } = params;\n return this.call(\"queryProjectManualTests\", {\n projectId: this.resolveProjectId(projectId),\n ...rest,\n });\n }\n\n // ── Project Configuration ──────────────────────────────────────────\n\n getConnectUrls(projectId?: string): Promise<ProjectConnectUrls> {\n return this.call(\"getProjectConnectUrls\", { projectId: this.resolveProjectId(projectId) });\n }\n\n updateProjectConfig(params: {\n projectId?: string;\n name?: string;\n description?: string;\n settings?: Record<string, unknown>;\n }): Promise<unknown> {\n const { projectId, ...rest } = params;\n return this.callService(\"projectService\", \"updateProject\", {\n id: this.resolveProjectId(projectId),\n ...rest,\n });\n }\n\n updateProjectAgentDefaults(params: {\n projectId?: string;\n defaultPmAgentId?: string | null;\n defaultTaskAgentId?: string | null;\n defaultReviewerAgentId?: string | null;\n helperAgentId?: string | null;\n }): Promise<unknown> {\n const { projectId, ...rest } = params;\n return this.callService(\"projectService\", \"updateProjectDefaults\", {\n id: this.resolveProjectId(projectId),\n ...rest,\n });\n }\n\n listTagsDetailed(projectId?: string): Promise<TagSummary[]> {\n return this.callService(\"tagService\", \"listTagsWithCounts\", {\n projectId: this.resolveProjectId(projectId),\n });\n }\n\n createTag(params: {\n projectId?: string;\n name: string;\n color?: string;\n description?: string;\n overview?: string;\n /** Parents to link at create time (multi-parent DAG). */\n parentTagIds?: string[];\n contextPaths?: ContextPathInput[];\n }): Promise<{ id: string }> {\n const { projectId, ...rest } = params;\n return this.callService(\"tagService\", \"createTag\", {\n projectId: this.resolveProjectId(projectId),\n ...rest,\n });\n }\n\n updateTag(params: {\n id: string;\n name?: string;\n color?: string;\n description?: string;\n overview?: string | null;\n parentTagIds?: string[];\n reason?: string;\n contextPaths?: ContextPathInput[];\n }): Promise<unknown> {\n return this.callService(\"tagService\", \"updateTag\", params);\n }\n\n deleteTag(id: string): Promise<unknown> {\n return this.callService(\"tagService\", \"deleteTag\", { id });\n }\n\n previewTagMerge(params: { sourceTagId: string; targetTagId: string }): Promise<unknown> {\n return this.callService(\"tagService\", \"previewTagMerge\", params);\n }\n\n mergeTag(params: {\n sourceTagId: string;\n targetTagId: string;\n reason?: string;\n }): Promise<unknown> {\n return this.callService(\"tagService\", \"mergeTag\", params);\n }\n\n listPriorities(projectId?: string): Promise<PrioritySummary[]> {\n return this.callService(\"priorityService\", \"listByProject\", {\n projectId: this.resolveProjectId(projectId),\n });\n }\n\n createPriority(params: {\n projectId?: string;\n value: number;\n name: string;\n color: string;\n description?: string;\n }): Promise<{ id: string }> {\n const { projectId, ...rest } = params;\n return this.callService(\"priorityService\", \"createPriority\", {\n projectId: this.resolveProjectId(projectId),\n ...rest,\n });\n }\n\n updatePriority(params: {\n id: string;\n value?: number;\n name?: string;\n color?: string;\n description?: string;\n }): Promise<unknown> {\n return this.callService(\"priorityService\", \"updatePriority\", params);\n }\n\n deletePriority(id: string): Promise<unknown> {\n return this.callService(\"priorityService\", \"deletePriority\", { id });\n }\n\n // ── Suggestions ─────────────────────────────────────────────────────\n\n createSuggestion(params: {\n projectId?: string;\n title: string;\n description?: string;\n tagNames?: string[];\n }): Promise<{ id: string; merged: boolean; mergedIntoId?: string }> {\n const { projectId, ...rest } = params;\n return this.call(\"createProjectSuggestion\", {\n projectId: this.resolveProjectId(projectId),\n ...rest,\n });\n }\n\n // ── PTY Tunnel Relay (reuses the S2 pty:* envelope) ─────────────────\n\n /**\n * Poll target: returns the active cloud PTY session for a task once its ring\n * buffer has frames. `sessionId` is resolved server-side from `taskId` (never\n * accepted from the wire), preserving the one-active-session-per-task invariant.\n */\n getActivePtySession(taskId: string): Promise<ActivePtySession> {\n return this.call(\"getActivePtySession\", { taskId });\n }\n\n /** Fetch the ring-buffer snapshot for catch-up replay on (re)attach. */\n ptyAttach(sessionId: string): Promise<PtyAttachSnapshot> {\n return this.call(\"ptyAttach\", { sessionId });\n }\n\n /**\n * Join the session room so `pty:data` frames are delivered. Uses the standard\n * quickdraw-core subscribe envelope; \"Read\" is sufficient for output streaming.\n */\n subscribeToSession(sessionId: string): void {\n const socket = this.socket;\n if (!socket) throw new Error(\"Not connected\");\n socket.emit(\"agentSessionService:subscribe\", {\n entryId: sessionId,\n requiredLevel: \"Read\",\n });\n }\n\n /** Relay a stdin chunk to the cloud PTY (raw utf8, fire-and-forget). */\n ptyInput(sessionId: string, data: string): void {\n this.emit(\"ptyInput\", { sessionId, data });\n }\n\n /** Relay a terminal resize to the cloud PTY (fire-and-forget). */\n ptyResize(sessionId: string, cols: number, rows: number): void {\n this.emit(\"ptyResize\", { sessionId, cols, rows });\n }\n\n /** Subscribe to raw PTY output frames. Returns an unsubscribe function. */\n onPtyData(handler: (chunk: PtyDataChunk) => void): () => void {\n const socket = this.socket;\n if (!socket) throw new Error(\"Not connected\");\n socket.on(\"pty:data\", handler as (...args: unknown[]) => void);\n return () => {\n socket.off(\"pty:data\", handler as (...args: unknown[]) => void);\n };\n }\n\n // ── Connection lifecycle ────────────────────────────────────────────\n\n disconnect(): void {\n this.socket?.disconnect();\n this.socket = null;\n }\n}\n","// src/socket-core/socket-options.ts\nfunction buildConveyorSocketOptions(auth) {\n return {\n auth,\n transports: [\"websocket\"],\n reconnection: true,\n reconnectionAttempts: Infinity,\n reconnectionDelay: 2e3,\n reconnectionDelayMax: 3e4,\n randomizationFactor: 0.3,\n extraHeaders: { \"ngrok-skip-browser-warning\": \"true\" }\n };\n}\n\n// src/socket-core/call-with-ack.ts\nfunction callWithAck(socket, event, payload, options) {\n const { timeoutMs, requireData = false, makeTimeoutError, makeFailureError } = options;\n return new Promise((resolve, reject) => {\n let settled = false;\n const timer = setTimeout(() => {\n if (settled) return;\n settled = true;\n reject(makeTimeoutError());\n }, timeoutMs);\n socket.emit(event, payload, (response) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n if (response.success && (!requireData || response.data !== void 0)) {\n resolve(response.data);\n } else {\n reject(makeFailureError(response.error));\n }\n });\n });\n}\nfunction waitForConnected(socket, timeoutMs, makeTimeoutError) {\n if (socket.connected) return Promise.resolve();\n return new Promise((resolve, reject) => {\n const cleanup = () => {\n clearTimeout(timer);\n socket.off(\"connect\", onConnect);\n };\n const onConnect = () => {\n cleanup();\n resolve();\n };\n const timer = setTimeout(() => {\n cleanup();\n reject(makeTimeoutError());\n }, timeoutMs);\n socket.once(\"connect\", onConnect);\n });\n}\nexport {\n buildConveyorSocketOptions,\n callWithAck,\n waitForConnected\n};\n"],"mappings":"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","names":[]}
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ConveyorConnection
4
- } from "./chunk-IHKZRJIH.js";
4
+ } from "./chunk-QGY4IDYB.js";
5
5
 
6
6
  // src/cli.ts
7
7
  import { createRequire } from "module";
@@ -275,11 +275,11 @@ var readTaskChatContract = defineToolContract({
275
275
  var listTagsContract = defineToolContract({
276
276
  name: "list_tags",
277
277
  agent: {
278
- description: "List the project glossary: every tag's id, name, color, description, parent/child tag ids, and whether it carries a full overview (fetch that with get_tag). Use the ids with get_tag / update_tag.",
278
+ description: "List the project glossary: every tag's id, name, color, description, parent/child tag ids, its contextPaths (the rule/doc/file/folder links it wires into agent context \u2014 `[]` means none), and whether it carries a full overview (fetch that with get_tag). The context links ship inline, so you only need get_tag for a term's full overview. Use the ids with get_tag / update_tag.",
279
279
  fields: {}
280
280
  },
281
281
  mcp: {
282
- description: "List all project tags with names, IDs, colors, descriptions, hierarchy (parent/child ids), and a hasOverview flag (full overviews via get_tag). Pass projectId to target a specific project; otherwise the configured default project is used.",
282
+ description: "List all project tags with names, IDs, colors, descriptions, hierarchy (parent/child ids), contextPaths (the rule/doc/file/folder links each tag wires into agent context \u2014 `[]` means none), and a hasOverview flag. Context links ship inline; call get_tag only for a term's full overview. Pass projectId to target a specific project; otherwise the configured default project is used.",
283
283
  fields: {
284
284
  projectId: mcpProjectId
285
285
  }
@@ -949,64 +949,81 @@ function registerUpdateProjectSettings(server2, conn2) {
949
949
  );
950
950
  }
951
951
  var contextPathSchema = z4.object({
952
- type: z4.enum(["rule", "doc", "file", "folder"]).describe("Kind of context link \u2014 a rule/doc file, a source file, or a folder"),
952
+ type: z4.enum(["rule", "doc", "file", "folder"]).describe(
953
+ "Kind of context link \u2014 a rule/doc file, a source file, or a folder. All paths are repo-relative; doc marks a synced project doc, which resolves from the workspace like rule/file"
954
+ ),
953
955
  path: z4.string().describe("Repo-relative path, e.g. '.claude/rules/refactor-verification.md'"),
954
956
  label: z4.string().optional().describe("Optional human-readable label for the link")
955
957
  });
958
+ var MANAGE_TAGS_DESCRIPTION = "List, create, update, delete, or merge project tags \u2014 the project glossary. create requires name (optional color/description/overview/parentTagIds/contextPaths); update/delete/merge require the tag id. description (\u2264255) is the summary; overview is the full markdown spec (read with get_tag); parentTagIds is the multi-parent hierarchy \u2014 set it on create, or replace the full set on update; contextPaths wire files/rules/docs into the agent context of any card carrying the tag (replace-set \u2014 pass the full list, [] clears). merge absorbs the tag in id into targetTagId: cards and hierarchy edges move to the target, the target keeps its own description/overview/links, and the absorbed tag is deleted. Use mergePreview first to see the counts. Pass reason on updates and merges \u2014 it lands in the tag's revision history. Mutations require a Moderate project role.";
959
+ var MANAGE_TAGS_SHAPE = {
960
+ action: z4.enum(["list", "create", "update", "delete", "mergePreview", "merge"]).describe("Operation to perform"),
961
+ projectId: z4.string().optional().describe("Target Conveyor project ID (list/create)"),
962
+ id: z4.string().optional().describe("Tag ID (update/delete/mergePreview/merge)"),
963
+ targetTagId: z4.string().optional().describe("Surviving tag ID for mergePreview/merge \u2014 the tag in id is absorbed into this one"),
964
+ name: z4.string().optional().describe("Tag name"),
965
+ color: z4.string().optional().describe("Hex color, e.g. #ff0000"),
966
+ description: z4.string().optional().describe("Tag description \u2014 the \u2264255-char summary"),
967
+ overview: z4.string().nullable().optional().describe("Full markdown glossary body (update: null clears). Only used on create/update."),
968
+ parentTagIds: z4.array(z4.string()).max(25).optional().describe(
969
+ "Parent tag ids (multi-parent hierarchy). Honored on create; replace-set on update: pass the full list, [] clears."
970
+ ),
971
+ reason: z4.string().optional().describe("One line on why (update/merge) \u2014 recorded in the tag's revision history"),
972
+ contextPaths: z4.array(contextPathSchema).max(20).optional().describe(
973
+ "Context links (rules/docs/files/folders) auto-loaded into the agent context of cards with this tag. Replace-set: the full list replaces the tag's existing links; pass [] to clear. Only used on create/update."
974
+ )
975
+ };
976
+ function createTagFrom(conn2, params) {
977
+ if (!params.name) return Promise.resolve(textResult("name is required for create."));
978
+ return conn2.createTag({
979
+ projectId: params.projectId,
980
+ name: params.name,
981
+ ...definedEntries({
982
+ color: params.color,
983
+ description: params.description,
984
+ overview: params.overview ?? void 0,
985
+ parentTagIds: params.parentTagIds,
986
+ contextPaths: params.contextPaths
987
+ })
988
+ }).then(jsonResult);
989
+ }
990
+ function updateTagFrom(conn2, id, params) {
991
+ return conn2.updateTag({
992
+ id,
993
+ ...definedEntries({
994
+ name: params.name,
995
+ color: params.color,
996
+ description: params.description,
997
+ overview: params.overview,
998
+ parentTagIds: params.parentTagIds,
999
+ reason: params.reason,
1000
+ contextPaths: params.contextPaths
1001
+ })
1002
+ }).then(jsonResult);
1003
+ }
1004
+ function mergeTagFrom(conn2, id, params) {
1005
+ const targetTagId = params.targetTagId;
1006
+ if (!targetTagId) {
1007
+ return Promise.resolve(textResult(`targetTagId is required for ${params.action}.`));
1008
+ }
1009
+ if (params.action === "mergePreview") {
1010
+ return conn2.previewTagMerge({ sourceTagId: id, targetTagId }).then(jsonResult);
1011
+ }
1012
+ return conn2.mergeTag({ sourceTagId: id, targetTagId, ...definedEntries({ reason: params.reason }) }).then(jsonResult);
1013
+ }
956
1014
  function registerManageTags(server2, conn2) {
957
1015
  server2.tool(
958
1016
  "manage_tags",
959
- "List, create, update, or delete project tags \u2014 the project glossary. create requires name (optional color/description/overview/contextPaths); update/delete require the tag id. description (\u2264255) is the summary; overview is the full markdown spec (read with get_tag); parentTagIds is the multi-parent hierarchy (replace-set); contextPaths wire files/rules/docs into the agent context of any card carrying the tag (replace-set \u2014 pass the full list, [] clears). Pass reason on updates \u2014 it lands in the tag's revision history. Mutations require a Moderate project role.",
960
- {
961
- action: z4.enum(["list", "create", "update", "delete"]).describe("Operation to perform"),
962
- projectId: z4.string().optional().describe("Target Conveyor project ID (list/create)"),
963
- id: z4.string().optional().describe("Tag ID (update/delete)"),
964
- name: z4.string().optional().describe("Tag name"),
965
- color: z4.string().optional().describe("Hex color, e.g. #ff0000"),
966
- description: z4.string().optional().describe("Tag description \u2014 the \u2264255-char summary"),
967
- overview: z4.string().nullable().optional().describe("Full markdown glossary body (update: null clears). Only used on create/update."),
968
- parentTagIds: z4.array(z4.string()).max(25).optional().describe(
969
- "Parent tag ids (multi-parent hierarchy). Replace-set on update: pass the full list, [] clears."
970
- ),
971
- reason: z4.string().optional().describe("One line on why (update) \u2014 recorded in the tag's revision history"),
972
- contextPaths: z4.array(contextPathSchema).max(20).optional().describe(
973
- "Context links (rules/docs/files/folders) auto-loaded into the agent context of cards with this tag. Replace-set: the full list replaces the tag's existing links; pass [] to clear. Only used on create/update."
974
- )
975
- },
1017
+ MANAGE_TAGS_DESCRIPTION,
1018
+ MANAGE_TAGS_SHAPE,
976
1019
  async (params) => {
977
- const { action, projectId: projectId2, id, name, color, description, overview, parentTagIds, reason, contextPaths } = params;
978
- if (action === "list") return jsonResult(await conn2.listTagsDetailed(projectId2));
979
- if (action === "create") {
980
- if (!name) return textResult("name is required for create.");
981
- return jsonResult(
982
- await conn2.createTag({
983
- projectId: projectId2,
984
- name,
985
- ...definedEntries({
986
- color,
987
- description,
988
- overview: overview ?? void 0,
989
- contextPaths
990
- })
991
- })
992
- );
993
- }
1020
+ const { action, id } = params;
1021
+ if (action === "list") return jsonResult(await conn2.listTagsDetailed(params.projectId));
1022
+ if (action === "create") return createTagFrom(conn2, params);
994
1023
  if (!id) return textResult(`id is required for ${action}.`);
995
1024
  if (action === "delete") return jsonResult(await conn2.deleteTag(id));
996
- return jsonResult(
997
- await conn2.updateTag({
998
- id,
999
- ...definedEntries({
1000
- name,
1001
- color,
1002
- description,
1003
- overview,
1004
- parentTagIds,
1005
- reason,
1006
- contextPaths
1007
- })
1008
- })
1009
- );
1025
+ if (action === "mergePreview" || action === "merge") return mergeTagFrom(conn2, id, params);
1026
+ return updateTagFrom(conn2, id, params);
1010
1027
  }
1011
1028
  );
1012
1029
  }