@compilr-dev/sdk 0.20.0 → 0.20.2
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 +1 -1
- package/dist/index.js +1 -1
- package/dist/team/index.d.ts +1 -1
- package/dist/team/index.js +1 -1
- package/dist/team/team-agent.d.ts +30 -4
- package/dist/team/team-agent.js +77 -22
- package/dist/team/team.js +9 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -35,7 +35,7 @@
|
|
|
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, createDelegateTool, createDelegateBackgroundTool, buildHandoffTaskMessage, validateHandoffIntent, HandoffStash, createConsultTool, buildConsultQuestionMessage, ROLE_NAME_ALIASES, normalizeRoleName, isNarrowing, } from './team/index.js';
|
|
38
|
+
export { AgentTeam, TeamAgent, SharedContextManager, ArtifactStore, DelegationTracker, ContextResolver, createDelegationStatusTool, createHandoffTool, createDelegateTool, createDelegateBackgroundTool, buildHandoffTaskMessage, validateHandoffIntent, HandoffStash, createConsultTool, buildConsultQuestionMessage, ROLE_NAME_ALIASES, normalizeRoleName, isNarrowing, lostWriteAccess, } from './team/index.js';
|
|
39
39
|
export type { AgentTeamConfig, TeamAgentConfig, TeamAgentUpdate, AgentUpdateResult, 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, HandoffResult, HandoffToolConfig, HandoffIntent, HandoffValidationResult, DelegateResult, DelegateToolConfig, DelegateBackgroundResult, DelegateBackgroundToolConfig, ConsultInput, ConsultResult, ConsultToolConfig, NormalizedRole, 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';
|
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, createDelegateTool, createDelegateBackgroundTool, buildHandoffTaskMessage, validateHandoffIntent, HandoffStash, createConsultTool, buildConsultQuestionMessage, ROLE_NAME_ALIASES, normalizeRoleName, isNarrowing, } from './team/index.js';
|
|
44
|
+
export { AgentTeam, TeamAgent, SharedContextManager, ArtifactStore, DelegationTracker, ContextResolver, createDelegationStatusTool, createHandoffTool, createDelegateTool, createDelegateBackgroundTool, buildHandoffTaskMessage, validateHandoffIntent, HandoffStash, createConsultTool, buildConsultQuestionMessage, ROLE_NAME_ALIASES, normalizeRoleName, isNarrowing, lostWriteAccess, } 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
|
package/dist/team/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export { AgentTeam } from './team.js';
|
|
8
8
|
export type { AgentTeamConfig } from './team.js';
|
|
9
|
-
export { TeamAgent, isNarrowing } from './team-agent.js';
|
|
9
|
+
export { TeamAgent, isNarrowing, lostWriteAccess } from './team-agent.js';
|
|
10
10
|
export type { TeamAgentUpdate, AgentUpdateResult } from './team-agent.js';
|
|
11
11
|
export { SharedContextManager } from './shared-context.js';
|
|
12
12
|
export type { SharedContext, SharedProjectInfo, SharedTeamInfo, TeamRosterEntry, TeamActivity, TeamActivityType, SharedDecision, TokenBudget, SerializedSharedContext, } from './shared-context.js';
|
package/dist/team/index.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
// Core classes
|
|
8
8
|
export { AgentTeam } from './team.js';
|
|
9
|
-
export { TeamAgent, isNarrowing } from './team-agent.js';
|
|
9
|
+
export { TeamAgent, isNarrowing, lostWriteAccess } from './team-agent.js';
|
|
10
10
|
export { SharedContextManager } from './shared-context.js';
|
|
11
11
|
export { ArtifactStore } from './artifacts.js';
|
|
12
12
|
export { ROLE_METADATA, ROLE_EXPERTISE, ROLE_GROUPS, PREDEFINED_ROLE_IDS } from './types.js';
|
|
@@ -22,6 +22,12 @@ import type { CustomAgentDefinition } from './custom-agents.js';
|
|
|
22
22
|
*/
|
|
23
23
|
export interface TeamAgentUpdate {
|
|
24
24
|
displayName?: string;
|
|
25
|
+
/**
|
|
26
|
+
* ⚠️ HANDLED BY `setModelTier`, NOT BY THE FIELD ASSIGNMENT BELOW. The tier owns its own
|
|
27
|
+
* rebuild (it has to strip thinking blocks, whose signatures do not transfer across a
|
|
28
|
+
* model change), so `applyUpdate` delegates rather than reimplementing it.
|
|
29
|
+
*/
|
|
30
|
+
modelTier?: ModelTier;
|
|
25
31
|
mascot?: MascotExpression;
|
|
26
32
|
description?: string;
|
|
27
33
|
systemPromptAddition?: string;
|
|
@@ -47,13 +53,33 @@ export interface AgentUpdateResult {
|
|
|
47
53
|
newProfile?: TeamAgentConfig['toolProfile'];
|
|
48
54
|
}
|
|
49
55
|
/**
|
|
50
|
-
* Did the
|
|
56
|
+
* Did the agent's reach get strictly smaller?
|
|
57
|
+
*
|
|
58
|
+
* ⚠️ TWO TESTS, NOT ONE, and the first version had only half of the first.
|
|
59
|
+
*
|
|
60
|
+
* Losing the ability to WRITE is the narrowing that matters most, so a move into a read-only
|
|
61
|
+
* profile counts however the tool counts land. But it is not the only one: `full` → `custom`
|
|
62
|
+
* with no groups is total tool removal — the largest narrowing there is — and neither profile
|
|
63
|
+
* is read-only, so a read-only test alone called it no change at all.
|
|
51
64
|
*
|
|
52
|
-
* ⚠️
|
|
53
|
-
*
|
|
54
|
-
*
|
|
65
|
+
* ⚠️ `undefined` IS NOT "UNKNOWN". `initialize` passes `toolFilter` straight to the factory,
|
|
66
|
+
* and an absent filter means NO filter — every tool. So `undefined` → `read-only` is the
|
|
67
|
+
* maximal narrowing, and the original returned false for it. My own test asserted exactly
|
|
68
|
+
* that under the name "says nothing when either side is unknown", which is how it survived:
|
|
69
|
+
* the suite encoded the defect as intended behaviour.
|
|
55
70
|
*/
|
|
56
71
|
export declare function isNarrowing(before: TeamAgentConfig['toolProfile'], after: TeamAgentConfig['toolProfile']): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Did the agent specifically lose the ability to change files?
|
|
74
|
+
*
|
|
75
|
+
* ⚠️ A NARROWER QUESTION THAN `isNarrowing`, and the host needs both. "Fewer tools" and
|
|
76
|
+
* "cannot write any more" are different facts, and a notice that says "it can no longer
|
|
77
|
+
* change files" when the agent merely dropped six tools is a false statement in the
|
|
78
|
+
* transcript — exactly the class of error this whole review found.
|
|
79
|
+
*/
|
|
80
|
+
export declare function lostWriteAccess(before: TeamAgentConfig['toolProfile'], after: TeamAgentConfig['toolProfile']): boolean;
|
|
81
|
+
/** Is this a profile the registry actually knows? Used to refuse bad IPC data. */
|
|
82
|
+
export declare function isKnownProfile(p: unknown): p is NonNullable<TeamAgentConfig['toolProfile']>;
|
|
57
83
|
/**
|
|
58
84
|
* TeamAgent wraps an Agent instance with team-specific metadata
|
|
59
85
|
*/
|
package/dist/team/team-agent.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import { ROLE_METADATA } from './types.js';
|
|
11
11
|
import { getModelForTier, getModelContextWindow } from '../models/index.js';
|
|
12
12
|
import { generateCustomAgentSystemPrompt, getCustomAgentToolFilter } from './custom-agents.js';
|
|
13
|
-
import { getToolsForProfile, generateToolAwarenessPrompt, generateCoordinatorGuidance, generateSpecialistGuidance, } from './tool-config.js';
|
|
13
|
+
import { getToolsForProfile, PROFILE_INFO, generateToolAwarenessPrompt, generateCoordinatorGuidance, generateSpecialistGuidance, } from './tool-config.js';
|
|
14
14
|
/**
|
|
15
15
|
* Estimate token count from text (approximate: ~4 chars per token)
|
|
16
16
|
*/
|
|
@@ -18,34 +18,64 @@ function estimateTokens(text) {
|
|
|
18
18
|
return Math.ceil(text.length / 4);
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
|
-
* Did the
|
|
21
|
+
* Did the agent's reach get strictly smaller?
|
|
22
22
|
*
|
|
23
|
-
* ⚠️
|
|
24
|
-
*
|
|
25
|
-
*
|
|
23
|
+
* ⚠️ TWO TESTS, NOT ONE, and the first version had only half of the first.
|
|
24
|
+
*
|
|
25
|
+
* Losing the ability to WRITE is the narrowing that matters most, so a move into a read-only
|
|
26
|
+
* profile counts however the tool counts land. But it is not the only one: `full` → `custom`
|
|
27
|
+
* with no groups is total tool removal — the largest narrowing there is — and neither profile
|
|
28
|
+
* is read-only, so a read-only test alone called it no change at all.
|
|
29
|
+
*
|
|
30
|
+
* ⚠️ `undefined` IS NOT "UNKNOWN". `initialize` passes `toolFilter` straight to the factory,
|
|
31
|
+
* and an absent filter means NO filter — every tool. So `undefined` → `read-only` is the
|
|
32
|
+
* maximal narrowing, and the original returned false for it. My own test asserted exactly
|
|
33
|
+
* that under the name "says nothing when either side is unknown", which is how it survived:
|
|
34
|
+
* the suite encoded the defect as intended behaviour.
|
|
26
35
|
*/
|
|
27
36
|
export function isNarrowing(before, after) {
|
|
28
37
|
if (before === after)
|
|
29
38
|
return false;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
39
|
+
const couldWrite = before === undefined || !isReadOnlyProfile(before);
|
|
40
|
+
const canWrite = after === undefined || !isReadOnlyProfile(after);
|
|
41
|
+
if (couldWrite && !canWrite)
|
|
42
|
+
return true;
|
|
43
|
+
// Otherwise compare what it may actually reach — `undefined` is every tool.
|
|
44
|
+
return toolReach(after) < toolReach(before);
|
|
33
45
|
}
|
|
34
46
|
/**
|
|
35
|
-
*
|
|
47
|
+
* Did the agent specifically lose the ability to change files?
|
|
36
48
|
*
|
|
37
|
-
* ⚠️
|
|
38
|
-
* cannot
|
|
49
|
+
* ⚠️ A NARROWER QUESTION THAN `isNarrowing`, and the host needs both. "Fewer tools" and
|
|
50
|
+
* "cannot write any more" are different facts, and a notice that says "it can no longer
|
|
51
|
+
* change files" when the agent merely dropped six tools is a false statement in the
|
|
52
|
+
* transcript — exactly the class of error this whole review found.
|
|
39
53
|
*/
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
54
|
+
export function lostWriteAccess(before, after) {
|
|
55
|
+
if (before === after)
|
|
56
|
+
return false;
|
|
57
|
+
const couldWrite = before === undefined || !isReadOnlyProfile(before);
|
|
58
|
+
const canWrite = after === undefined || !isReadOnlyProfile(after);
|
|
59
|
+
return couldWrite && !canWrite;
|
|
60
|
+
}
|
|
61
|
+
/*
|
|
62
|
+
⚠️ NO DEFENSIVE LOOKUP HERE — the profile is validated at the boundary instead.
|
|
63
|
+
`PROFILE_INFO` is a total Record over `ToolProfile`, so a guard here is dead code by the
|
|
64
|
+
type system's reckoning and ESLint says so. The real risk is a bogus string arriving over
|
|
65
|
+
IPC, and the honest place to refuse that is once, on the way in, rather than to absorb it
|
|
66
|
+
silently at every reader. See `isKnownProfile` and its use in `updateAgent`.
|
|
67
|
+
*/
|
|
68
|
+
const isReadOnlyProfile = (p) => PROFILE_INFO[p].isReadOnly;
|
|
69
|
+
/** Is this a profile the registry actually knows? Used to refuse bad IPC data. */
|
|
70
|
+
export function isKnownProfile(p) {
|
|
71
|
+
return typeof p === 'string' && Object.prototype.hasOwnProperty.call(PROFILE_INFO, p);
|
|
72
|
+
}
|
|
73
|
+
/** How many tools a profile grants. `undefined` means no filter, i.e. all of them. */
|
|
74
|
+
function toolReach(p) {
|
|
75
|
+
if (p === undefined)
|
|
76
|
+
return Number.POSITIVE_INFINITY;
|
|
77
|
+
return getToolsForProfile(p).length;
|
|
78
|
+
}
|
|
49
79
|
/** Order-insensitive comparison — a reordered skill list is not a change. */
|
|
50
80
|
function sameStrings(a, b) {
|
|
51
81
|
if (a === undefined || b === undefined)
|
|
@@ -254,6 +284,13 @@ export class TeamAgent {
|
|
|
254
284
|
(patch.toolProfile !== undefined && patch.toolProfile !== this.toolProfile) ||
|
|
255
285
|
(patch.toolFilter !== undefined && !sameStrings(patch.toolFilter, this.toolFilter)) ||
|
|
256
286
|
(patch.enabledSkills !== undefined && !sameStrings(patch.enabledSkills, this.enabledSkills));
|
|
287
|
+
/*
|
|
288
|
+
Delegated: `setModelTier` no-ops when the tier is unchanged and stashes for rebuild
|
|
289
|
+
when it is not. Its `rebuilt` contribution is folded in below.
|
|
290
|
+
*/
|
|
291
|
+
const tierChanged = patch.modelTier !== undefined && patch.modelTier !== this._modelTier;
|
|
292
|
+
if (patch.modelTier !== undefined)
|
|
293
|
+
this.setModelTier(patch.modelTier);
|
|
257
294
|
if (patch.displayName !== undefined)
|
|
258
295
|
this.displayName = patch.displayName;
|
|
259
296
|
if (patch.mascot !== undefined)
|
|
@@ -262,15 +299,33 @@ export class TeamAgent {
|
|
|
262
299
|
this.description = patch.description;
|
|
263
300
|
if (patch.systemPromptAddition !== undefined)
|
|
264
301
|
this.systemPromptAddition = patch.systemPromptAddition;
|
|
265
|
-
|
|
302
|
+
/*
|
|
303
|
+
⚠️ THE PROFILE IS A LABEL; `toolFilter` IS THE ENFORCEMENT. `initialize()` passes
|
|
304
|
+
`toolFilter` to the factory and never looks at `toolProfile`, so setting the profile
|
|
305
|
+
alone changed the word on screen and nothing else: an agent switched to `read-only`
|
|
306
|
+
kept `write_file` and 168 other tools, while `toolsNarrowed` truthfully reported that
|
|
307
|
+
its reach had shrunk. A security control that confirms and does not engage.
|
|
308
|
+
|
|
309
|
+
All four CONSTRUCTION sites already derive it — `fromSerialized`, `fromRole`,
|
|
310
|
+
`fromSpecialist`, `fromCustomDefinition` — which is why a restart applied the
|
|
311
|
+
restriction the running session had ignored, and why creating a read-only agent was
|
|
312
|
+
correct all along. Update was the only path that did not.
|
|
313
|
+
|
|
314
|
+
An explicit `toolFilter` still wins: `custom` profiles carry their own list.
|
|
315
|
+
*/
|
|
316
|
+
if (patch.toolProfile !== undefined) {
|
|
266
317
|
this.toolProfile = patch.toolProfile;
|
|
318
|
+
if (patch.toolFilter === undefined) {
|
|
319
|
+
this.toolFilter = getToolsForProfile(patch.toolProfile);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
267
322
|
if (patch.toolFilter !== undefined)
|
|
268
323
|
this.toolFilter = patch.toolFilter;
|
|
269
324
|
if (patch.enabledSkills !== undefined)
|
|
270
325
|
this.enabledSkills = patch.enabledSkills;
|
|
271
326
|
if (needsRebuild)
|
|
272
327
|
this.stashForRebuild();
|
|
273
|
-
return { rebuilt: needsRebuild };
|
|
328
|
+
return { rebuilt: needsRebuild || tierChanged };
|
|
274
329
|
}
|
|
275
330
|
/**
|
|
276
331
|
* Initialize the agent with the given factory
|
package/dist/team/team.js
CHANGED
|
@@ -11,7 +11,7 @@ import { TeamAgent } from './team-agent.js';
|
|
|
11
11
|
import { ROLE_EXPERTISE } from './types.js';
|
|
12
12
|
import { SharedContextManager } from './shared-context.js';
|
|
13
13
|
import { ArtifactStore } from './artifacts.js';
|
|
14
|
-
import { isNarrowing } from './team-agent.js';
|
|
14
|
+
import { isNarrowing, isKnownProfile } from './team-agent.js';
|
|
15
15
|
import { resolveAgentIdCollision } from './collision-utils.js';
|
|
16
16
|
/**
|
|
17
17
|
* AgentTeam orchestrates multiple persistent agents
|
|
@@ -339,6 +339,14 @@ export class AgentTeam {
|
|
|
339
339
|
throw new Error(`Agent id is immutable — '${id}' cannot be renamed. Duplicate the agent instead: ` +
|
|
340
340
|
'mention handles are written into stored message text and cannot be migrated.');
|
|
341
341
|
}
|
|
342
|
+
/*
|
|
343
|
+
⚠️ An unknown profile would otherwise be absorbed silently: `getToolsForProfile` returns
|
|
344
|
+
nothing for it, so the agent would end up with an empty filter — every tool removed —
|
|
345
|
+
while the UI showed whatever string was sent. Refuse it here, once.
|
|
346
|
+
*/
|
|
347
|
+
if (patch.toolProfile !== undefined && !isKnownProfile(patch.toolProfile)) {
|
|
348
|
+
throw new Error(`Unknown tool profile '${String(patch.toolProfile)}'`);
|
|
349
|
+
}
|
|
342
350
|
const previousProfile = agent.toolProfile;
|
|
343
351
|
const { rebuilt } = agent.applyUpdate(patch);
|
|
344
352
|
if (rebuilt) {
|