@compilr-dev/sdk 0.10.16 → 0.10.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -35,9 +35,9 @@
35
35
  */
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
- export { AgentTeam, TeamAgent, SharedContextManager, ArtifactStore, DelegationTracker, ContextResolver, createDelegationStatusTool, createHandoffTool, } from './team/index.js';
38
+ export { AgentTeam, TeamAgent, SharedContextManager, ArtifactStore, DelegationTracker, ContextResolver, createDelegationStatusTool, createHandoffTool, buildHandoffTaskMessage, validateHandoffIntent, HandoffStash, } from './team/index.js';
39
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
- 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, HandoffResult, HandoffToolConfig, SkillToolRequirement, } from './team/index.js';
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, HandoffResult, HandoffToolConfig, HandoffIntent, HandoffValidationResult, SkillToolRequirement, } from './team/index.js';
41
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';
package/dist/index.js CHANGED
@@ -41,7 +41,7 @@ export { createCompilrAgent } from './agent.js';
41
41
  // Multi-Agent Team Orchestration
42
42
  // =============================================================================
43
43
  // Core classes
44
- export { AgentTeam, TeamAgent, SharedContextManager, ArtifactStore, DelegationTracker, ContextResolver, createDelegationStatusTool, createHandoffTool, } from './team/index.js';
44
+ export { AgentTeam, TeamAgent, SharedContextManager, ArtifactStore, DelegationTracker, ContextResolver, createDelegationStatusTool, createHandoffTool, buildHandoffTaskMessage, validateHandoffIntent, HandoffStash, } from './team/index.js';
45
45
  // Constants
46
46
  export { ROLE_METADATA, ROLE_EXPERTISE, ROLE_GROUPS, PREDEFINED_ROLE_IDS, TOOL_GROUPS, TOOL_PROFILES, PROFILE_INFO, SKILL_REQUIREMENTS, CUSTOM_MASCOTS, buildAgentWorkshopData, buildSuggestedRolesMap,
47
47
  // Plan mode
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Handoff orchestration helpers.
3
+ *
4
+ * The `createHandoffTool` factory (delegation-tools.ts) covers the
5
+ * tool-side of handoffs: validation, one-hop enforcement, `team.recordHandoff`.
6
+ * What it does NOT cover is the post-turn orchestration pattern shared by
7
+ * all hosts that surface this tool — stashing the dispatched intent during
8
+ * the source agent's turn, picking it back up once the turn ends, and
9
+ * dispatching the task to the target agent.
10
+ *
11
+ * Hosts (CLI, Desktop) used to implement that pattern independently,
12
+ * which is exactly the kind of drift that produced the desktop's
13
+ * silent-stub bug. This module centralises:
14
+ *
15
+ * - **HandoffIntent** — the shape both hosts pass between "tool fired"
16
+ * and "source turn ended."
17
+ * - **buildHandoffTaskMessage** — canonical `[Handoff from $arch]\n\nTask:`
18
+ * format so the synthesised message the target receives is identical
19
+ * across hosts.
20
+ * - **validateHandoffIntent** — re-checks team state at dispatch time
21
+ * (target could have been removed between stash and pickup).
22
+ * - **HandoffStash** — optional convenience for hosts that have multiple
23
+ * independent conversations (Desktop). CLI's single-REPL pattern is
24
+ * simpler than this class warrants; it can use the type + helpers
25
+ * directly without the stash.
26
+ *
27
+ * Storage location is intentionally platform-shaped (CLI: one global,
28
+ * Desktop: per-conversation map) — only the *what* gets standardised,
29
+ * not the *where*.
30
+ */
31
+ import type { AgentTeam } from './team.js';
32
+ /**
33
+ * The intent recorded when a specialist agent calls `handoff(...)`.
34
+ * Stashed during the source agent's turn, consumed when the turn ends so
35
+ * the target agent can be invoked with the task.
36
+ *
37
+ * `conversationId` is opaque to the SDK — hosts use it to scope stashed
38
+ * intents (Desktop's per-conversation map; CLI can use a constant like
39
+ * `'default'` because there's only one REPL session).
40
+ */
41
+ export interface HandoffIntent {
42
+ /** Host-defined conversation key. Opaque to the SDK. */
43
+ conversationId: string;
44
+ /** Agent that called `handoff`. */
45
+ sourceAgentId: string;
46
+ /** Agent receiving the handoff. */
47
+ targetAgentId: string;
48
+ /** Task description passed verbatim to the target. */
49
+ task: string;
50
+ /** Optional reason text the source provided. */
51
+ reason?: string;
52
+ }
53
+ /**
54
+ * Build the synthesised user-style message handed to the target agent
55
+ * after a successful handoff. Wrapping the body with a `[Handoff from $X]`
56
+ * marker keeps the target oriented and gives future tooling a way to
57
+ * distinguish handoff-injected messages from direct user input.
58
+ *
59
+ * Format:
60
+ *
61
+ * [Handoff from $arch]
62
+ *
63
+ * Task: <verbatim task>
64
+ *
65
+ * Reason: <verbatim reason — omitted when absent>
66
+ */
67
+ export declare function buildHandoffTaskMessage(intent: HandoffIntent): string;
68
+ /**
69
+ * Result of `validateHandoffIntent`. A discriminated union so call sites
70
+ * can `if (!result.valid) ... result.reason`.
71
+ */
72
+ export type HandoffValidationResult = {
73
+ valid: true;
74
+ } | {
75
+ valid: false;
76
+ reason: string;
77
+ };
78
+ /**
79
+ * Re-validate a stashed `HandoffIntent` against the current team state.
80
+ *
81
+ * The intent was validated by `createHandoffTool` at the moment the tool
82
+ * fired, but team state can change between stash and dispatch — an agent
83
+ * may have been removed, the team may have been swapped out, etc. Hosts
84
+ * should call this before invoking the target agent.
85
+ *
86
+ * Returns `{ valid: false, reason }` with a user-readable message when
87
+ * the intent is no longer dispatchable.
88
+ */
89
+ export declare function validateHandoffIntent(team: AgentTeam, intent: HandoffIntent): HandoffValidationResult;
90
+ /**
91
+ * Per-conversation stash for `HandoffIntent`s. Hosts that manage multiple
92
+ * independent conversations (the Desktop app) can use this directly; the
93
+ * CLI's single-REPL pattern is simpler than this class warrants and can
94
+ * use plain fields on its shared-state object.
95
+ *
96
+ * Usage:
97
+ *
98
+ * // Inside the handoff tool's `onHandoff` adapter callback:
99
+ * stash.set({ conversationId, sourceAgentId, targetAgentId, task, reason });
100
+ *
101
+ * // After the source agent's turn ends:
102
+ * const intent = stash.consume(conversationId);
103
+ * if (intent) {
104
+ * const check = validateHandoffIntent(team, intent);
105
+ * if (check.valid) {
106
+ * await runTargetAgent(intent.targetAgentId, buildHandoffTaskMessage(intent));
107
+ * }
108
+ * }
109
+ */
110
+ export declare class HandoffStash {
111
+ private readonly intents;
112
+ /** Stash an intent. Replaces any prior intent for the same conversation
113
+ * — only one handoff can be in flight per conversation at a time. */
114
+ set(intent: HandoffIntent): void;
115
+ /** Read without removing. Useful for "is there a handoff pending?" UI checks. */
116
+ peek(conversationId: string): HandoffIntent | undefined;
117
+ /** Read and remove. The normal post-turn pickup pattern. */
118
+ consume(conversationId: string): HandoffIntent | undefined;
119
+ /** Explicitly clear without consuming — used by error paths so a failed
120
+ * source turn doesn't leave a phantom intent for the next turn. */
121
+ clear(conversationId: string): void;
122
+ /** Whether a stashed intent exists for this conversation. */
123
+ has(conversationId: string): boolean;
124
+ }
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Handoff orchestration helpers.
3
+ *
4
+ * The `createHandoffTool` factory (delegation-tools.ts) covers the
5
+ * tool-side of handoffs: validation, one-hop enforcement, `team.recordHandoff`.
6
+ * What it does NOT cover is the post-turn orchestration pattern shared by
7
+ * all hosts that surface this tool — stashing the dispatched intent during
8
+ * the source agent's turn, picking it back up once the turn ends, and
9
+ * dispatching the task to the target agent.
10
+ *
11
+ * Hosts (CLI, Desktop) used to implement that pattern independently,
12
+ * which is exactly the kind of drift that produced the desktop's
13
+ * silent-stub bug. This module centralises:
14
+ *
15
+ * - **HandoffIntent** — the shape both hosts pass between "tool fired"
16
+ * and "source turn ended."
17
+ * - **buildHandoffTaskMessage** — canonical `[Handoff from $arch]\n\nTask:`
18
+ * format so the synthesised message the target receives is identical
19
+ * across hosts.
20
+ * - **validateHandoffIntent** — re-checks team state at dispatch time
21
+ * (target could have been removed between stash and pickup).
22
+ * - **HandoffStash** — optional convenience for hosts that have multiple
23
+ * independent conversations (Desktop). CLI's single-REPL pattern is
24
+ * simpler than this class warrants; it can use the type + helpers
25
+ * directly without the stash.
26
+ *
27
+ * Storage location is intentionally platform-shaped (CLI: one global,
28
+ * Desktop: per-conversation map) — only the *what* gets standardised,
29
+ * not the *where*.
30
+ */
31
+ // =============================================================================
32
+ // Canonical task-message format
33
+ // =============================================================================
34
+ /**
35
+ * Build the synthesised user-style message handed to the target agent
36
+ * after a successful handoff. Wrapping the body with a `[Handoff from $X]`
37
+ * marker keeps the target oriented and gives future tooling a way to
38
+ * distinguish handoff-injected messages from direct user input.
39
+ *
40
+ * Format:
41
+ *
42
+ * [Handoff from $arch]
43
+ *
44
+ * Task: <verbatim task>
45
+ *
46
+ * Reason: <verbatim reason — omitted when absent>
47
+ */
48
+ export function buildHandoffTaskMessage(intent) {
49
+ return intent.reason
50
+ ? `[Handoff from $${intent.sourceAgentId}]\n\nTask: ${intent.task}\n\nReason: ${intent.reason}`
51
+ : `[Handoff from $${intent.sourceAgentId}]\n\nTask: ${intent.task}`;
52
+ }
53
+ /**
54
+ * Re-validate a stashed `HandoffIntent` against the current team state.
55
+ *
56
+ * The intent was validated by `createHandoffTool` at the moment the tool
57
+ * fired, but team state can change between stash and dispatch — an agent
58
+ * may have been removed, the team may have been swapped out, etc. Hosts
59
+ * should call this before invoking the target agent.
60
+ *
61
+ * Returns `{ valid: false, reason }` with a user-readable message when
62
+ * the intent is no longer dispatchable.
63
+ */
64
+ export function validateHandoffIntent(team, intent) {
65
+ if (!team.has(intent.targetAgentId)) {
66
+ return {
67
+ valid: false,
68
+ reason: `Agent '${intent.targetAgentId}' no longer exists in team.`,
69
+ };
70
+ }
71
+ if (!team.has(intent.sourceAgentId)) {
72
+ return {
73
+ valid: false,
74
+ reason: `Source agent '${intent.sourceAgentId}' no longer exists in team.`,
75
+ };
76
+ }
77
+ return { valid: true };
78
+ }
79
+ // =============================================================================
80
+ // Optional stash for multi-conversation hosts (Desktop)
81
+ // =============================================================================
82
+ /**
83
+ * Per-conversation stash for `HandoffIntent`s. Hosts that manage multiple
84
+ * independent conversations (the Desktop app) can use this directly; the
85
+ * CLI's single-REPL pattern is simpler than this class warrants and can
86
+ * use plain fields on its shared-state object.
87
+ *
88
+ * Usage:
89
+ *
90
+ * // Inside the handoff tool's `onHandoff` adapter callback:
91
+ * stash.set({ conversationId, sourceAgentId, targetAgentId, task, reason });
92
+ *
93
+ * // After the source agent's turn ends:
94
+ * const intent = stash.consume(conversationId);
95
+ * if (intent) {
96
+ * const check = validateHandoffIntent(team, intent);
97
+ * if (check.valid) {
98
+ * await runTargetAgent(intent.targetAgentId, buildHandoffTaskMessage(intent));
99
+ * }
100
+ * }
101
+ */
102
+ export class HandoffStash {
103
+ intents = new Map();
104
+ /** Stash an intent. Replaces any prior intent for the same conversation
105
+ * — only one handoff can be in flight per conversation at a time. */
106
+ set(intent) {
107
+ this.intents.set(intent.conversationId, intent);
108
+ }
109
+ /** Read without removing. Useful for "is there a handoff pending?" UI checks. */
110
+ peek(conversationId) {
111
+ return this.intents.get(conversationId);
112
+ }
113
+ /** Read and remove. The normal post-turn pickup pattern. */
114
+ consume(conversationId) {
115
+ const intent = this.intents.get(conversationId);
116
+ this.intents.delete(conversationId);
117
+ return intent;
118
+ }
119
+ /** Explicitly clear without consuming — used by error paths so a failed
120
+ * source turn doesn't leave a phantom intent for the next turn. */
121
+ clear(conversationId) {
122
+ this.intents.delete(conversationId);
123
+ }
124
+ /** Whether a stashed intent exists for this conversation. */
125
+ has(conversationId) {
126
+ return this.intents.has(conversationId);
127
+ }
128
+ }
@@ -40,3 +40,5 @@ export { SKILL_REQUIREMENTS, getDefinedSkillNames, getSkillRequirements, checkSk
40
40
  export { resolveAgentIdCollision } from './collision-utils.js';
41
41
  export { createDelegationStatusTool, createHandoffTool } from './delegation-tools.js';
42
42
  export type { HandoffResult, HandoffToolConfig } from './delegation-tools.js';
43
+ export { buildHandoffTaskMessage, validateHandoffIntent, HandoffStash, } from './handoff-orchestration.js';
44
+ export type { HandoffIntent, HandoffValidationResult } from './handoff-orchestration.js';
@@ -33,3 +33,6 @@ export { SKILL_REQUIREMENTS, getDefinedSkillNames, getSkillRequirements, checkSk
33
33
  export { resolveAgentIdCollision } from './collision-utils.js';
34
34
  // Delegation & Handoff tools (factory functions)
35
35
  export { createDelegationStatusTool, createHandoffTool } from './delegation-tools.js';
36
+ // Handoff orchestration helpers — shared between CLI and Desktop for the
37
+ // post-turn stash/dispatch pattern. See handoff-orchestration.ts header.
38
+ export { buildHandoffTaskMessage, validateHandoffIntent, HandoffStash, } from './handoff-orchestration.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@compilr-dev/sdk",
3
- "version": "0.10.16",
3
+ "version": "0.10.18",
4
4
  "description": "Universal agent runtime for building AI-powered applications",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -56,7 +56,7 @@
56
56
  "node": ">=20.0.0"
57
57
  },
58
58
  "dependencies": {
59
- "@compilr-dev/agents": "^0.5.8",
59
+ "@compilr-dev/agents": "^0.5.9",
60
60
  "@compilr-dev/logger": "^0.1.0",
61
61
  "@compilr-dev/sdk": "^0.10.2",
62
62
  "ajv": "^6.14.0",