CoolFace
Datasetpublic

basant307/AI_Governance_Project

sourceHugging Faceapache-2.0updated 2mo agoView on Hugging Face
0likes45downloads
task-create.ts201 linesDownload Raw Back to tools
1/**2 * @license3 * Copyright 2025 Qwen4 * SPDX-License-Identifier: Apache-2.05 */6 7/**8 * task_create tool — create a new task in the team task list.9 */10 11import type {12  ToolCallConfirmationDetails,13  ToolInfoConfirmationDetails,14  ToolInvocation,15  ToolResult,16} from './tools.js';17import { BaseDeclarativeTool, BaseToolInvocation, Kind } from './tools.js';18import { ToolNames, ToolDisplayNames } from './tool-names.js';19import type { Config } from '../config/config.js';20import type { PermissionDecision } from '../permissions/types.js';21import { resolveActiveTeamName } from '../agents/team/identity.js';22import {23  getPlanRequiredTeammatePreApprovalMessage,24  isPlanRequiredTeammateAwaitingApproval,25} from '../agents/runtime/subagent-plan-tool-policy.js';26import { createTask } from '../agents/team/tasks.js';27 28export interface TaskCreateParams {29  subject: string;30  description: string;31  activeForm?: string;32  metadata?: Record<string, unknown>;33}34 35/** Cap on how much of a task description the confirmation dialog shows. */36const CONFIRMATION_DESCRIPTION_LIMIT = 2000;37 38/**39 * Truncate a task description for the interactive confirmation dialog.40 * Descriptions can be up to 10KB; the dialog needs enough to judge the41 * instruction, not the whole payload.42 */43export function truncateForConfirmation(text: string): string {44  if (text.length <= CONFIRMATION_DESCRIPTION_LIMIT) return text;45  return (46    `${text.slice(0, CONFIRMATION_DESCRIPTION_LIMIT)}\n` +47    `… (${text.length - CONFIRMATION_DESCRIPTION_LIMIT} more characters)`48  );49}50 51class TaskCreateInvocation extends BaseToolInvocation<52  TaskCreateParams,53  ToolResult54> {55  constructor(56    private config: Config,57    params: TaskCreateParams,58  ) {59    super(params);60  }61 62  getDescription(): string {63    return `Create task: ${this.params.subject}`;64  }65 66  /**67   * A task's `description` becomes the prompt an idle teammate auto-claims68   * and executes with full tool access — the same privileged-sink shape as69   * `send_message`, where free-form text turns into a new instruction for70   * another agent. The base default `'allow'` short-circuits the classifier71   * in AUTO mode, so override to `'ask'` to keep that injection path under72   * the classifier / human-in-the-loop.73   */74  override async getDefaultPermission(): Promise<PermissionDecision> {75    return 'ask';76  }77 78  /**79   * Unlike the one-line getDescription() used for transcript rendering,80   * the confirmation prompt must show the instruction text itself: the81   * `description` is what an idle teammate will auto-claim and execute82   * with full tool access, so it is exactly what the human is approving.83   */84  override getConfirmationDetails(85    _abortSignal: AbortSignal,86  ): Promise<ToolCallConfirmationDetails> {87    const details: ToolInfoConfirmationDetails = {88      type: 'info',89      title: 'Confirm TaskCreate',90      prompt:91        `Create task: ${this.params.subject}\n\n` +92        truncateForConfirmation(this.params.description),93      onConfirm: async () => {94        // No-op: persistence is handled by coreToolScheduler via PM rules95      },96    };97    return Promise.resolve(details);98  }99 100  async execute(): Promise<ToolResult> {101    if (isPlanRequiredTeammateAwaitingApproval(this.config)) {102      const msg = getPlanRequiredTeammatePreApprovalMessage(103        ToolNames.TASK_CREATE,104      );105      return {106        llmContent: msg,107        returnDisplay: msg,108        error: { message: msg },109      };110    }111 112    const teamName = resolveActiveTeamName(113      this.config.getTeamContext()?.teamName,114    );115    if (!teamName) {116      const msg = 'No active team. Create a team first.';117      return {118        llmContent: msg,119        returnDisplay: msg,120        error: { message: msg },121      };122    }123 124    const task = await createTask(teamName, {125      subject: this.params.subject,126      description: this.params.description,127      activeForm: this.params.activeForm,128      metadata: this.params.metadata,129    });130 131    const llmContent = `Task #${task.id} created: "${task.subject}"`;132    return { llmContent, returnDisplay: llmContent };133  }134}135 136export class TaskCreateTool extends BaseDeclarativeTool<137  TaskCreateParams,138  ToolResult139> {140  static readonly Name = ToolNames.TASK_CREATE;141 142  constructor(private config: Config) {143    super(144      TaskCreateTool.Name,145      ToolDisplayNames.TASK_CREATE,146      'Create a new task in the team task list. ' +147        'Tasks are automatically assigned to idle teammates.',148      Kind.Other,149      {150        type: 'object',151        properties: {152          subject: {153            type: 'string',154            description: 'Short title for the task.',155            maxLength: 200,156          },157          description: {158            type: 'string',159            description: 'Detailed description of the task.',160            maxLength: 10000,161          },162          activeForm: {163            type: 'string',164            maxLength: 200,165            description:166              'Present tense label for UI ' + '(e.g., "Running tests").',167          },168          metadata: {169            type: 'object',170            description: 'Optional arbitrary metadata.',171          },172        },173        required: ['subject', 'description'],174        additionalProperties: false,175      },176    );177  }178 179  protected createInvocation(180    params: TaskCreateParams,181  ): ToolInvocation<TaskCreateParams, ToolResult> {182    return new TaskCreateInvocation(this.config, params);183  }184 185  /**186   * Forward the task content to the classifier. The base sentinel `''`187   * projects to an empty args object, so without this override the AUTO188   * classifier rules on `task_create({})` — the injected payload that189   * `getDefaultPermission() === 'ask'` exists to inspect would be190   * invisible to it. Mirrors `send_message`'s projection.191   */192  override toAutoClassifierInput(193    params: TaskCreateParams,194  ): Record<string, unknown> {195    return {196      subject: params.subject,197      description: params.description,198    };199  }200}201 
basant307/AI_Governance_Project · CoolFace