CoolFace
Datasetpublic

basant307/AI_Governance_Project

sourceHugging Faceapache-2.0updated 2mo agoView on Hugging Face
0likes48downloads
task-create.test.ts169 linesDownload Raw Back to tools
1/**2 * @license3 * Copyright 2025 Qwen4 * SPDX-License-Identifier: Apache-2.05 */6 7import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';8import * as fs from 'node:fs/promises';9import * as os from 'node:os';10import * as path from 'node:path';11import { TaskCreateTool } from './task-create.js';12import type { ApprovalMode, Config } from '../config/config.js';13import { runWithTeammateIdentity } from '../agents/team/identity.js';14import { listTasks } from '../agents/team/tasks.js';15 16const DEFAULT_MODE = 'default' as ApprovalMode;17const PLAN_MODE = 'plan' as ApprovalMode;18 19vi.mock('../config/storage.js', () => {20  let mockDir = '/tmp/test';21  return {22    Storage: {23      getGlobalQwenDir: () => mockDir,24    },25    __setMockGlobalDir: (d: string) => {26      mockDir = d;27    },28  };29});30 31// eslint-disable-next-line @typescript-eslint/no-explicit-any32const { __setMockGlobalDir } = (await import('../config/storage.js')) as any;33 34let tmpDir: string;35 36function makeConfig(teamName = 'test-team', approvalMode = DEFAULT_MODE) {37  return {38    getTeamContext: () => ({ teamName }),39    getApprovalMode: () => approvalMode,40  } as unknown as Config;41}42 43function makeConfigNoTeam() {44  return {45    getTeamContext: () => null,46    getApprovalMode: () => DEFAULT_MODE,47  } as unknown as Config;48}49 50beforeEach(async () => {51  tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'task-create-test-'));52  __setMockGlobalDir(tmpDir);53});54 55afterEach(async () => {56  await fs.rm(tmpDir, { recursive: true, force: true });57});58 59describe('TaskCreateTool', () => {60  let tool: TaskCreateTool;61 62  beforeEach(() => {63    tool = new TaskCreateTool(makeConfig());64  });65 66  it('has the correct name', () => {67    expect(tool.name).toBe('task_create');68  });69 70  it('creates a task with real file I/O', async () => {71    const invocation = tool.build({72      subject: 'Fix bug',73      description: 'Fix the login bug',74    });75    const result = await invocation.execute(new AbortController().signal);76    expect(result.error).toBeUndefined();77    expect(result.llmContent).toContain('Fix bug');78    expect(result.llmContent).toMatch(/#\d+/);79  });80 81  it('accepts optional metadata', async () => {82    const invocation = tool.build({83      subject: 'Deploy',84      description: 'Deploy to prod',85      activeForm: 'Deploying',86      metadata: { priority: 'high' },87    });88    const result = await invocation.execute(new AbortController().signal);89    expect(result.error).toBeUndefined();90  });91 92  it('returns error when no team is active', async () => {93    const noTeamTool = new TaskCreateTool(makeConfigNoTeam());94    const invocation = noTeamTool.build({95      subject: 'Test',96      description: 'Test desc',97    });98    const result = await invocation.execute(new AbortController().signal);99    expect(result.error).toBeDefined();100    expect(result.llmContent).toContain('No active team');101  });102 103  it('blocks plan-required teammates before leader approval', async () => {104    const planTool = new TaskCreateTool(makeConfig('test-team', PLAN_MODE));105    const invocation = planTool.build({106      subject: 'Bypass approval',107      description: 'Another teammate could execute this.',108    });109 110    const result = await runWithTeammateIdentity(111      {112        agentName: 'planner',113        teamName: 'test-team',114        agentId: 'planner@test-team',115        isTeamLead: false,116        planModeRequired: true,117      },118      () => invocation.execute(new AbortController().signal),119    );120 121    expect(result.error).toBeDefined();122    expect(result.llmContent).toContain('waiting for leader approval');123    await expect(listTasks('test-team')).resolves.toEqual([]);124  });125 126  it('validates required params', () => {127    expect(() => tool.build({} as never)).toThrow();128    expect(() => tool.build({ subject: 'x' } as never)).toThrow();129  });130 131  // ─── Permission surface ───────────────────────────────────132  // A regression back to 'allow' (or to the base '' classifier133  // sentinel) silently re-opens the task-injection path: the AUTO134  // classifier would rule on task_create({}) and always allow.135 136  it("defaults to 'ask' permission", async () => {137    const invocation = tool.build({138      subject: 'Injected',139      description: 'do something sneaky',140    });141    await expect(invocation.getDefaultPermission()).resolves.toBe('ask');142  });143 144  it('projects subject and description to the AUTO classifier', () => {145    const projected = tool.toAutoClassifierInput({146      subject: 'Fix bug',147      description: 'the instruction text',148    });149    expect(projected).toEqual({150      subject: 'Fix bug',151      description: 'the instruction text',152    });153  });154 155  it('shows the description in the confirmation prompt', async () => {156    const invocation = tool.build({157      subject: 'Fix bug',158      description: 'The full instruction text a teammate will execute.',159    });160    const details = await invocation.getConfirmationDetails(161      new AbortController().signal,162    );163    expect(details.type).toBe('info');164    expect((details as { prompt: string }).prompt).toContain(165      'The full instruction text a teammate will execute.',166    );167  });168});169 
basant307/AI_Governance_Project · CoolFace