@compilr-dev/sdk 0.9.13 → 0.9.15

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.
@@ -43,7 +43,8 @@ export function createCompressorHook(config) {
43
43
  if (compressed !== null && compressed.length < stdout.length) {
44
44
  const saved = stdout.length - compressed.length;
45
45
  const pct = Math.round((saved / stdout.length) * 100);
46
- console.log(`[compressor] bash "${command.slice(0, 40)}" ${String(stdout.length)} → ${String(compressed.length)} chars (${String(pct)}% saved)`); // eslint-disable-line no-console
46
+ // eslint-disable-next-line no-console
47
+ console.log(`[compressor] bash "${command.slice(0, 40)}" ${String(stdout.length)} → ${String(compressed.length)} chars (${String(pct)}% saved)`);
47
48
  return {
48
49
  result: {
49
50
  ...ctx.result,
package/dist/index.d.ts CHANGED
@@ -36,9 +36,9 @@
36
36
  export { createCompilrAgent } from './agent.js';
37
37
  export type { CompilrAgentConfig, CompilrAgent, RunOptions, RunResult, ToolCallRecord, ToolConfig, UsageInfo, ProviderType, PermissionCallback, GuardrailConfig, ContextConfig, CapabilitiesConfig, } from './config.js';
38
38
  export { AgentTeam, TeamAgent, SharedContextManager, ArtifactStore, DelegationTracker, ContextResolver, } from './team/index.js';
39
- export type { AgentTeamConfig, TeamAgentConfig, ITeamPersistence, IArtifactStorage, ISessionRegistry, CustomAgentDefinition, AgentTemplate, AgentWorkshopData, WorkshopRoleDef, WorkshopToolProfile, WorkshopModelTier, WorkshopSkillDef, ToolConfig as TeamToolConfig, ToolTier, ToolGroup, ProfileInfo, } from './team/index.js';
39
+ export type { AgentTeamConfig, TeamAgentConfig, ITeamPersistence, IArtifactStorage, ISessionRegistry, CustomAgentDefinition, AgentTemplate, AgentWorkshopData, WorkshopRoleDef, WorkshopToolProfile, WorkshopModelTier, WorkshopSkillDef, PlanSubmitInfo, PlanSubmitResult, PlanModeExitInfo, PlanModeCallbacks, ToolConfig as TeamToolConfig, ToolTier, ToolGroup, ProfileInfo, } from './team/index.js';
40
40
  export type { AgentRole, RoleMetadata, ToolProfile, MascotExpression, BackgroundSessionInfo, SerializedTeam, SerializedTeamAgent, TeamMetadata, TeamEvent, TeamEventType, TeamEventHandler, Artifact, ArtifactType as TeamArtifactType, ArtifactSummary as TeamArtifactSummary, CreateArtifactOptions, UpdateArtifactOptions, SerializedArtifact, SharedContext, SharedProjectInfo, SharedTeamInfo, TeamRosterEntry, TeamActivity, TeamActivityType, SharedDecision, TokenBudget, SerializedSharedContext, ParsedMention, ParsedInput, ResolvedMention, ResolveOptions, ResolutionSource, Delegation, DelegationStatus, DelegationResult, CompletionEvent, CreateDelegationOptions, DelegationStats, DelegationTrackerEvents, SkillToolRequirement, } from './team/index.js';
41
- export { ROLE_METADATA, ROLE_EXPERTISE, ROLE_GROUPS, PREDEFINED_ROLE_IDS, TOOL_GROUPS, TOOL_PROFILES, PROFILE_INFO, SKILL_REQUIREMENTS, CUSTOM_MASCOTS, buildAgentWorkshopData, buildSuggestedRolesMap, } from './team/index.js';
41
+ export { ROLE_METADATA, ROLE_EXPERTISE, ROLE_GROUPS, PREDEFINED_ROLE_IDS, TOOL_GROUPS, TOOL_PROFILES, PROFILE_INFO, SKILL_REQUIREMENTS, CUSTOM_MASCOTS, buildAgentWorkshopData, buildSuggestedRolesMap, PLAN_MODE_BLOCKED_TOOLS, PLAN_MODE_DENIAL_MESSAGE, PLAN_MODE_PROMPT, isToolAllowedInPlanMode, getPlanModePrompt, } from './team/index.js';
42
42
  export { getToolsForProfile, detectProfileFromTools, isProfileReadOnly, generateToolAwarenessPrompt, generateCoordinatorGuidance, generateSpecialistGuidance, createDefaultToolConfig, validateToolConfig, getAllGroupIds, getGroupInfo, getGroupsByTier, getGroupsForProfile, assignMascot, generateCustomAgentSystemPrompt, getCustomAgentToolFilter, getCustomAgentProfileLabel, validateAgentId, isAgentIdTaken, createCustomAgentDefinition, listTemplates, getTemplate, saveTemplate, updateTemplate, deleteTemplate, createAgentFromTemplate, parseInputForMentions, getReferencedAgents, hasReferences, buildMessageWithContext, buildContextMap, findAgentForRole, findAgentById, getAvailableSpecialists, getSpecialistsSummary, hasSpecialists, suggestOwner, suggestOwners, matchesAgentExpertise, wouldCreateLoop, recordAssignment, getAssignmentHistory, clearAssignmentHistory, clearAllAssignmentHistory, canReassign, resolveAgentIdCollision, setActiveSharedContext, getActiveSharedContext, recordTeamActivity, getDefinedSkillNames, getSkillRequirements, checkSkillCompatibility, getCompatibleSkills, getAllRequiredTools, getSkillsByCategory, } from './team/index.js';
43
43
  export { codingPreset, readOnlyPreset, resolvePreset } from './presets/index.js';
44
44
  export type { Preset } from './presets/index.js';
package/dist/index.js CHANGED
@@ -43,7 +43,9 @@ export { createCompilrAgent } from './agent.js';
43
43
  // Core classes
44
44
  export { AgentTeam, TeamAgent, SharedContextManager, ArtifactStore, DelegationTracker, ContextResolver, } from './team/index.js';
45
45
  // Constants
46
- export { ROLE_METADATA, ROLE_EXPERTISE, ROLE_GROUPS, PREDEFINED_ROLE_IDS, TOOL_GROUPS, TOOL_PROFILES, PROFILE_INFO, SKILL_REQUIREMENTS, CUSTOM_MASCOTS, buildAgentWorkshopData, buildSuggestedRolesMap, } from './team/index.js';
46
+ export { ROLE_METADATA, ROLE_EXPERTISE, ROLE_GROUPS, PREDEFINED_ROLE_IDS, TOOL_GROUPS, TOOL_PROFILES, PROFILE_INFO, SKILL_REQUIREMENTS, CUSTOM_MASCOTS, buildAgentWorkshopData, buildSuggestedRolesMap,
47
+ // Plan mode
48
+ PLAN_MODE_BLOCKED_TOOLS, PLAN_MODE_DENIAL_MESSAGE, PLAN_MODE_PROMPT, isToolAllowedInPlanMode, getPlanModePrompt, } from './team/index.js';
47
49
  // Utility functions
48
50
  export {
49
51
  // Tool config
@@ -11,12 +11,18 @@
11
11
  import type { Tool } from '@compilr-dev/agents';
12
12
  import type { PlatformToolsConfig } from '../context.js';
13
13
  import type { ImageToolsConfig } from './image-tools.js';
14
+ import type { PlanModeCallbacks } from '../../team/plan-mode.js';
15
+ export interface PlatformToolsOptions {
16
+ imageConfig?: ImageToolsConfig;
17
+ planModeCallbacks?: PlanModeCallbacks;
18
+ }
14
19
  /**
15
20
  * Create all platform tools operating against the given context.
16
- * Returns 25 DB tools + 1 image tool unconditionally, plus up to 8 service-based
21
+ * Returns 25+ DB tools + 1 image tool unconditionally, plus up to 8 service-based
17
22
  * tools if the optional anchors/artifacts/episodes services are provided.
23
+ * If planModeCallbacks are provided, plan_submit and plan_mode_exit tools are included.
18
24
  */
19
- export declare function createPlatformTools(config: PlatformToolsConfig, imageConfig?: ImageToolsConfig): Tool<never>[];
25
+ export declare function createPlatformTools(config: PlatformToolsConfig, options?: ImageToolsConfig | PlatformToolsOptions): Tool<never>[];
20
26
  export { createProjectTools } from './project-tools.js';
21
27
  export { createWorkItemTools } from './workitem-tools.js';
22
28
  export { createDocumentTools } from './document-tools.js';
@@ -19,18 +19,29 @@ import { createEpisodeTools } from './episode-tools.js';
19
19
  import { createImageTools } from './image-tools.js';
20
20
  /**
21
21
  * Create all platform tools operating against the given context.
22
- * Returns 25 DB tools + 1 image tool unconditionally, plus up to 8 service-based
22
+ * Returns 25+ DB tools + 1 image tool unconditionally, plus up to 8 service-based
23
23
  * tools if the optional anchors/artifacts/episodes services are provided.
24
+ * If planModeCallbacks are provided, plan_submit and plan_mode_exit tools are included.
24
25
  */
25
26
  // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
26
- export function createPlatformTools(config, imageConfig) {
27
+ export function createPlatformTools(config, options) {
28
+ // Backwards compat: options can be ImageToolsConfig (old) or PlatformToolsOptions (new)
29
+ let imageConfig;
30
+ let planCallbacks;
31
+ if (options && 'planModeCallbacks' in options) {
32
+ imageConfig = options.imageConfig;
33
+ planCallbacks = options.planModeCallbacks;
34
+ }
35
+ else if (options) {
36
+ imageConfig = options;
37
+ }
27
38
  // Use Tool<never>[] to accept any Tool<T> — the generic parameter is only
28
39
  // relevant to execute() callers, not to the registry that stores them.
29
40
  const tools = [
30
41
  ...createProjectTools(config),
31
42
  ...createWorkItemTools(config),
32
43
  ...createDocumentTools(config),
33
- ...createPlanTools(config),
44
+ ...createPlanTools(config, planCallbacks),
34
45
  ...createBacklogTools(config),
35
46
  ...createImageTools({ cwd: config.cwd, ...imageConfig }),
36
47
  ];
@@ -5,26 +5,12 @@
5
5
  *
6
6
  * Ported from CLI's src/tools/plan-tools.ts.
7
7
  */
8
+ import { type Tool } from '@compilr-dev/agents';
8
9
  import type { PlatformToolsConfig } from '../context.js';
9
- export declare function createPlanTools(config: PlatformToolsConfig): (import("@compilr-dev/agents").Tool<{
10
- name: string;
11
- content: string;
12
- work_item_id?: number;
13
- project_id?: number;
14
- }> | import("@compilr-dev/agents").Tool<{
15
- plan_id: number;
16
- content?: string;
17
- status?: string;
18
- work_item_id?: number | null;
19
- }> | import("@compilr-dev/agents").Tool<{
20
- plan_id?: number;
21
- name?: string;
22
- summary_only?: boolean;
23
- project_id?: number;
24
- }> | import("@compilr-dev/agents").Tool<{
25
- project_id?: number;
26
- status?: string;
27
- work_item_id?: number;
28
- limit?: number;
29
- order_by?: string;
30
- }>)[];
10
+ import type { PlanModeCallbacks } from '../../team/plan-mode.js';
11
+ export interface PlanToolsConfig {
12
+ platform: PlatformToolsConfig;
13
+ /** Optional plan mode callbacks (for plan_submit and plan_mode_exit) */
14
+ planModeCallbacks?: PlanModeCallbacks;
15
+ }
16
+ export declare function createPlanTools(config: PlatformToolsConfig, planModeCallbacks?: PlanModeCallbacks): Tool<never>[];
@@ -8,7 +8,7 @@
8
8
  import { defineTool, createSuccessResult, createErrorResult } from '@compilr-dev/agents';
9
9
  import { truncateContent } from './truncate.js';
10
10
  // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
11
- export function createPlanTools(config) {
11
+ export function createPlanTools(config, planModeCallbacks) {
12
12
  const { context: ctx } = config;
13
13
  // ---------------------------------------------------------------------------
14
14
  // plan_create
@@ -105,6 +105,12 @@ export function createPlanTools(config) {
105
105
  },
106
106
  execute: async (input) => {
107
107
  try {
108
+ // Guard: prevent agent from self-approving plans during plan mode
109
+ if (input.status === 'approved' &&
110
+ planModeCallbacks?.isPlanModeActive?.()) {
111
+ return createErrorResult('Cannot set status to "approved" directly during plan mode. ' +
112
+ 'Use plan_submit to submit your plan for user approval instead.');
113
+ }
108
114
  const updateInput = {};
109
115
  if (input.content !== undefined) {
110
116
  updateInput.content = input.content;
@@ -360,5 +366,96 @@ export function createPlanTools(config) {
360
366
  }
361
367
  },
362
368
  });
363
- return [planCreateTool, planUpdateTool, planGetTool, planListTool, planDeleteTool];
369
+ // ---------------------------------------------------------------------------
370
+ // plan_submit (requires callback from host app)
371
+ // ---------------------------------------------------------------------------
372
+ const onPlanSubmitFn = planModeCallbacks?.onPlanSubmit;
373
+ const planSubmitTool = onPlanSubmitFn
374
+ ? defineTool({
375
+ name: 'plan_submit',
376
+ description: 'Submit a plan for user approval. Call this when your plan is ready for review. ' +
377
+ 'The user will see the plan and choose to approve, revise, or reject it. ' +
378
+ 'On approval, write tools are unlocked and you can implement the plan.',
379
+ inputSchema: {
380
+ type: 'object',
381
+ properties: {
382
+ plan_id: {
383
+ type: 'number',
384
+ description: 'ID of the plan to submit for approval',
385
+ },
386
+ summary: {
387
+ type: 'string',
388
+ description: 'One-line summary of what the plan does',
389
+ },
390
+ },
391
+ required: ['plan_id'],
392
+ },
393
+ execute: async (input) => {
394
+ // Verify plan exists
395
+ const plan = await ctx.plans.getById(input.plan_id);
396
+ if (!plan) {
397
+ return createErrorResult(`Plan ${String(input.plan_id)} not found`);
398
+ }
399
+ // Call host app's approval UI
400
+ const result = await onPlanSubmitFn({
401
+ planId: input.plan_id,
402
+ summary: input.summary,
403
+ });
404
+ // Update plan status based on user decision
405
+ if (result.action === 'approve-auto' || result.action === 'approve') {
406
+ await ctx.plans.update(input.plan_id, { status: 'approved' });
407
+ }
408
+ else if (result.action === 'reject') {
409
+ await ctx.plans.update(input.plan_id, { status: 'abandoned' });
410
+ }
411
+ const messages = {
412
+ 'approve-auto': 'Plan approved. Auto-accept mode enabled. Proceed with implementation.',
413
+ approve: 'Plan approved. Proceed with implementation (tools will require approval).',
414
+ revise: `Plan needs revision. Feedback: ${result.feedback ?? 'No specific feedback'}`,
415
+ reject: 'Plan rejected. Create a new plan or exit plan mode.',
416
+ };
417
+ return createSuccessResult({ action: result.action, message: messages[result.action] });
418
+ },
419
+ })
420
+ : null;
421
+ // ---------------------------------------------------------------------------
422
+ // plan_mode_exit (requires callback from host app)
423
+ // ---------------------------------------------------------------------------
424
+ const onPlanModeExitFn = planModeCallbacks?.onPlanModeExit;
425
+ const planModeExitTool = onPlanModeExitFn
426
+ ? defineTool({
427
+ name: 'plan_mode_exit',
428
+ description: 'Exit plan mode without submitting a plan. Use this when the task is simple enough ' +
429
+ 'to implement directly without a formal plan.',
430
+ inputSchema: {
431
+ type: 'object',
432
+ properties: {
433
+ reason: {
434
+ type: 'string',
435
+ description: 'Brief reason for exiting plan mode (e.g., "Simple one-line fix")',
436
+ },
437
+ },
438
+ required: ['reason'],
439
+ },
440
+ execute: async (input) => {
441
+ await onPlanModeExitFn({ reason: input.reason });
442
+ return createSuccessResult({
443
+ message: `Exited plan mode: ${input.reason}. Full tools now available.`,
444
+ });
445
+ },
446
+ })
447
+ : null;
448
+ // Build tools array — include plan_submit and plan_mode_exit only if callbacks provided
449
+ const tools = [
450
+ planCreateTool,
451
+ planUpdateTool,
452
+ planGetTool,
453
+ planListTool,
454
+ planDeleteTool,
455
+ ];
456
+ if (planSubmitTool)
457
+ tools.push(planSubmitTool);
458
+ if (planModeExitTool)
459
+ tools.push(planModeExitTool);
460
+ return tools;
364
461
  }
@@ -112,10 +112,10 @@ Suggest delegation when a task would benefit from focused expertise.`,
112
112
  // =============================================================================
113
113
  export const generalConfig = {
114
114
  id: 'general',
115
- label: 'General',
116
- description: 'Blank project — define your own workflow',
115
+ label: 'General Purpose',
116
+ description: 'Any project — define your own workflow',
117
117
  icon: 'FolderOpen',
118
- category: 'software',
118
+ category: 'general',
119
119
  phases: [],
120
120
  suggestedAgents: [],
121
121
  documentTemplates: [
@@ -76,7 +76,7 @@ export interface ProjectTypeConfig {
76
76
  /** Lucide icon name */
77
77
  icon: string;
78
78
  /** Category for grouping in type selector */
79
- category: 'software' | 'writing' | 'business' | 'education';
79
+ category: 'general' | 'software' | 'writing' | 'business' | 'education';
80
80
  /** Workflow phases (shown in project panel lifecycle) */
81
81
  phases: ProjectPhase[];
82
82
  /** Suggested agent roles (shown first in "Add Agent" dialog) */
@@ -20,6 +20,8 @@ export type { CustomAgentDefinition } from './custom-agents.js';
20
20
  export { CUSTOM_MASCOTS, assignMascot, generateCustomAgentSystemPrompt, getCustomAgentToolFilter, getCustomAgentProfileLabel, validateAgentId, isAgentIdTaken, createCustomAgentDefinition, } from './custom-agents.js';
21
21
  export type { AgentTemplate } from './agent-templates.js';
22
22
  export { listTemplates, getTemplate, saveTemplate, updateTemplate, deleteTemplate, createAgentFromTemplate, } from './agent-templates.js';
23
+ export type { PlanSubmitInfo, PlanSubmitResult, PlanModeExitInfo, PlanModeCallbacks, } from './plan-mode.js';
24
+ export { PLAN_MODE_BLOCKED_TOOLS, PLAN_MODE_DENIAL_MESSAGE, PLAN_MODE_PROMPT, isToolAllowedInPlanMode, getPlanModePrompt, } from './plan-mode.js';
23
25
  export type { AgentWorkshopData, WorkshopRoleDef, WorkshopToolProfile, WorkshopModelTier, WorkshopSkillDef, } from './workshop-data.js';
24
26
  export { buildAgentWorkshopData, buildSuggestedRolesMap } from './workshop-data.js';
25
27
  export type { ITeamPersistence, IArtifactStorage, ISessionRegistry } from './interfaces.js';
@@ -15,6 +15,7 @@ export { TOOL_GROUPS, TOOL_PROFILES, PROFILE_INFO, getToolsForProfile, detectPro
15
15
  export { createDefaultToolConfig, validateToolConfig, getAllGroupIds, getGroupInfo, getGroupsByTier, getGroupsForProfile, } from './tool-config.js';
16
16
  export { CUSTOM_MASCOTS, assignMascot, generateCustomAgentSystemPrompt, getCustomAgentToolFilter, getCustomAgentProfileLabel, validateAgentId, isAgentIdTaken, createCustomAgentDefinition, } from './custom-agents.js';
17
17
  export { listTemplates, getTemplate, saveTemplate, updateTemplate, deleteTemplate, createAgentFromTemplate, } from './agent-templates.js';
18
+ export { PLAN_MODE_BLOCKED_TOOLS, PLAN_MODE_DENIAL_MESSAGE, PLAN_MODE_PROMPT, isToolAllowedInPlanMode, getPlanModePrompt, } from './plan-mode.js';
18
19
  export { buildAgentWorkshopData, buildSuggestedRolesMap } from './workshop-data.js';
19
20
  export { parseInputForMentions, getReferencedAgents, hasReferences, buildMessageWithContext, } from './mention-parser.js';
20
21
  export { ContextResolver, buildContextMap } from './context-resolver.js';
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Plan Mode — Tool blocking and callbacks for plan-before-act workflow.
3
+ *
4
+ * During plan mode, write/execute tools are blocked at the permission layer.
5
+ * The agent can only read, search, and create plans. When ready, it calls
6
+ * plan_submit to trigger the host app's approval UI.
7
+ */
8
+ /**
9
+ * Tools that are blocked during plan mode.
10
+ * The agent still "sees" these tools in its schema but any call
11
+ * is denied with a message explaining plan mode restrictions.
12
+ */
13
+ export declare const PLAN_MODE_BLOCKED_TOOLS: Set<string>;
14
+ /**
15
+ * Check if a tool is allowed during plan mode.
16
+ */
17
+ export declare function isToolAllowedInPlanMode(toolName: string): boolean;
18
+ /**
19
+ * Message returned to the agent when a blocked tool is called in plan mode.
20
+ */
21
+ export declare const PLAN_MODE_DENIAL_MESSAGE: string;
22
+ export interface PlanSubmitInfo {
23
+ planId: number;
24
+ summary?: string;
25
+ }
26
+ export interface PlanSubmitResult {
27
+ /** User's decision */
28
+ action: 'approve-auto' | 'approve' | 'revise' | 'reject';
29
+ /** User's feedback (for revise/reject) */
30
+ feedback?: string;
31
+ }
32
+ export interface PlanModeExitInfo {
33
+ reason: string;
34
+ }
35
+ /**
36
+ * Callbacks that the host app (CLI/Desktop) must provide for plan mode tools.
37
+ * Same pattern as ask_user — SDK defines the tool, host provides the UI.
38
+ */
39
+ export interface PlanModeCallbacks {
40
+ /** Called when agent submits a plan for approval (shows approval UI) */
41
+ onPlanSubmit?: (info: PlanSubmitInfo) => Promise<PlanSubmitResult>;
42
+ /** Called when agent wants to exit plan mode without a plan */
43
+ onPlanModeExit?: (info: PlanModeExitInfo) => Promise<void>;
44
+ /** Check if plan mode is currently active (used to guard plan_update from self-approval) */
45
+ isPlanModeActive?: () => boolean;
46
+ }
47
+ /**
48
+ * System prompt section injected when plan mode is active.
49
+ * Appended to the agent's system prompt by the host app.
50
+ */
51
+ export declare const PLAN_MODE_PROMPT = "## Plan Mode (Active)\n\nYou are in plan mode. Your write and execute tools are temporarily blocked.\n\n**What you CAN do:**\n- Read files, search code, analyze the codebase\n- Create and update plans with plan_create and plan_update\n- Ask the user clarifying questions\n- Submit your plan for approval with plan_submit\n\n**What you CANNOT do (until plan is approved):**\n- Edit, create, or delete files\n- Run shell commands\n- Execute tests or builds\n- Make git commits\n\n**Your workflow:**\n1. Understand the request \u2014 read relevant files, check the backlog, review existing code\n2. Create a plan \u2014 use plan_create with a clear name and structured content\n3. Submit for approval \u2014 call plan_submit when your plan is ready\n4. Wait for user decision \u2014 they may approve, ask for revisions, or reject\n\n**Plan format:**\n- Context: What problem are we solving? What exists today?\n- Approach: High-level strategy\n- Steps: Numbered list of specific changes (file, what to change, why)\n- Verification: How to confirm the changes work\n\nIf the task is too simple for a plan, call plan_mode_exit with a reason.";
52
+ /**
53
+ * Get the plan mode prompt, optionally with active plan context.
54
+ */
55
+ export declare function getPlanModePrompt(activePlan?: {
56
+ id: number;
57
+ name: string;
58
+ }): string;
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Plan Mode — Tool blocking and callbacks for plan-before-act workflow.
3
+ *
4
+ * During plan mode, write/execute tools are blocked at the permission layer.
5
+ * The agent can only read, search, and create plans. When ready, it calls
6
+ * plan_submit to trigger the host app's approval UI.
7
+ */
8
+ // =============================================================================
9
+ // Blocked Tools
10
+ // =============================================================================
11
+ /**
12
+ * Tools that are blocked during plan mode.
13
+ * The agent still "sees" these tools in its schema but any call
14
+ * is denied with a message explaining plan mode restrictions.
15
+ */
16
+ export const PLAN_MODE_BLOCKED_TOOLS = new Set([
17
+ // Shell / execution
18
+ 'bash',
19
+ 'bash_output',
20
+ 'kill_shell',
21
+ // File writes
22
+ 'edit',
23
+ 'write_file',
24
+ 'create_file',
25
+ 'delete_file',
26
+ 'rename_file',
27
+ 'move_file',
28
+ // Git writes
29
+ 'git_commit',
30
+ 'git_branch',
31
+ 'git_checkout',
32
+ 'git_push',
33
+ // Runners (execute code)
34
+ 'run_tests',
35
+ 'run_lint',
36
+ 'run_build',
37
+ ]);
38
+ /**
39
+ * Check if a tool is allowed during plan mode.
40
+ */
41
+ export function isToolAllowedInPlanMode(toolName) {
42
+ return !PLAN_MODE_BLOCKED_TOOLS.has(toolName);
43
+ }
44
+ /**
45
+ * Message returned to the agent when a blocked tool is called in plan mode.
46
+ */
47
+ export const PLAN_MODE_DENIAL_MESSAGE = 'Plan mode: write/execute tools are blocked during planning. ' +
48
+ 'Read and analyze first, create your plan with plan_create, ' +
49
+ 'then call plan_submit to request approval.';
50
+ // =============================================================================
51
+ // System Prompt
52
+ // =============================================================================
53
+ /**
54
+ * System prompt section injected when plan mode is active.
55
+ * Appended to the agent's system prompt by the host app.
56
+ */
57
+ export const PLAN_MODE_PROMPT = `## Plan Mode (Active)
58
+
59
+ You are in plan mode. Your write and execute tools are temporarily blocked.
60
+
61
+ **What you CAN do:**
62
+ - Read files, search code, analyze the codebase
63
+ - Create and update plans with plan_create and plan_update
64
+ - Ask the user clarifying questions
65
+ - Submit your plan for approval with plan_submit
66
+
67
+ **What you CANNOT do (until plan is approved):**
68
+ - Edit, create, or delete files
69
+ - Run shell commands
70
+ - Execute tests or builds
71
+ - Make git commits
72
+
73
+ **Your workflow:**
74
+ 1. Understand the request — read relevant files, check the backlog, review existing code
75
+ 2. Create a plan — use plan_create with a clear name and structured content
76
+ 3. Submit for approval — call plan_submit when your plan is ready
77
+ 4. Wait for user decision — they may approve, ask for revisions, or reject
78
+
79
+ **Plan format:**
80
+ - Context: What problem are we solving? What exists today?
81
+ - Approach: High-level strategy
82
+ - Steps: Numbered list of specific changes (file, what to change, why)
83
+ - Verification: How to confirm the changes work
84
+
85
+ If the task is too simple for a plan, call plan_mode_exit with a reason.`;
86
+ /**
87
+ * Get the plan mode prompt, optionally with active plan context.
88
+ */
89
+ export function getPlanModePrompt(activePlan) {
90
+ let prompt = PLAN_MODE_PROMPT;
91
+ if (activePlan) {
92
+ prompt +=
93
+ `\n\n**Active Plan:** "${activePlan.name}" (ID: ${String(activePlan.id)}). ` +
94
+ 'Use plan_get to review it, plan_update to modify it, or plan_submit to submit for approval.';
95
+ }
96
+ return prompt;
97
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@compilr-dev/sdk",
3
- "version": "0.9.13",
3
+ "version": "0.9.15",
4
4
  "description": "Universal agent runtime for building AI-powered applications",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -62,6 +62,9 @@
62
62
  "better-sqlite3": "^11.0.0 || ^12.0.0"
63
63
  },
64
64
  "peerDependenciesMeta": {
65
+ "@compilr-dev/agents-coding": {
66
+ "optional": true
67
+ },
65
68
  "better-sqlite3": {
66
69
  "optional": true
67
70
  }