clementine-agent 1.18.48 → 1.18.50
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/agent/agent-definitions.js +49 -8
- package/dist/agent/assistant.d.ts +1 -110
- package/dist/agent/assistant.js +96 -3394
- package/dist/agent/route-classifier.js +2 -3
- package/dist/agent/run-agent-context.d.ts +17 -0
- package/dist/agent/run-agent-context.js +80 -0
- package/dist/agent/run-agent-cron.js +17 -15
- package/dist/agent/run-agent-heartbeat.js +15 -2
- package/dist/agent/run-agent-team-task.js +15 -1
- package/dist/agent/run-agent.d.ts +6 -0
- package/dist/agent/run-agent.js +41 -9
- package/dist/agent/wave-scheduler.d.ts +21 -0
- package/dist/agent/wave-scheduler.js +72 -0
- package/dist/agent/workflow-runner.d.ts +2 -2
- package/dist/agent/workflow-runner.js +3 -3
- package/dist/channels/discord-agent-bot.js +1 -80
- package/dist/channels/discord.js +4 -108
- package/dist/gateway/cron-scheduler.js +4 -129
- package/dist/gateway/failure-diagnostics.js +6 -1
- package/dist/gateway/heartbeat-scheduler.js +12 -2
- package/dist/gateway/outcome-grader.js +2 -3
- package/dist/gateway/router.d.ts +5 -23
- package/dist/gateway/router.js +173 -893
- package/dist/tools/admin-tools.js +10 -43
- package/dist/types.d.ts +24 -0
- package/package.json +1 -1
- package/dist/agent/complexity-classifier.d.ts +0 -37
- package/dist/agent/complexity-classifier.js +0 -209
- package/dist/agent/fanout-policy.d.ts +0 -92
- package/dist/agent/fanout-policy.js +0 -243
- package/dist/agent/orchestrator.d.ts +0 -88
- package/dist/agent/orchestrator.js +0 -862
- package/dist/events/bus.d.ts +0 -43
- package/dist/events/bus.js +0 -136
- package/dist/gateway/long-task-preflight.d.ts +0 -30
- package/dist/gateway/long-task-preflight.js +0 -290
|
@@ -62,18 +62,41 @@ const CRON_FIXER_PROMPT = [
|
|
|
62
62
|
'',
|
|
63
63
|
'Return: a one-paragraph summary of what you applied (or what is blocking apply), per job.',
|
|
64
64
|
].join('\n');
|
|
65
|
+
/** Build a routing-signal description for a hired agent.
|
|
66
|
+
* The SDK uses descriptions for auto-routing — they must be imperative
|
|
67
|
+
* ("Use for: ..."), not narrative prose. Otherwise the main agent
|
|
68
|
+
* has nothing to match user phrasings against. */
|
|
69
|
+
function buildHiredAgentDescription(p) {
|
|
70
|
+
const role = p.role ?? p.description ?? `${p.name}, a hired agent`;
|
|
71
|
+
const slug = p.slug;
|
|
72
|
+
const capabilities = (p.routingHints && p.routingHints.length > 0)
|
|
73
|
+
? p.routingHints.join(', ')
|
|
74
|
+
: (p.description ?? '').slice(0, 200);
|
|
75
|
+
return [
|
|
76
|
+
`Delegate to ${p.name} (${slug}).`,
|
|
77
|
+
capabilities ? `Use for: ${capabilities}.` : '',
|
|
78
|
+
`Role: ${role}.`,
|
|
79
|
+
'Spawn this subagent when the user names them, asks a question in their domain, or asks Clementine to "have <name> do X".',
|
|
80
|
+
].filter(Boolean).join(' ');
|
|
81
|
+
}
|
|
65
82
|
/** Map a hired-agent profile to an AgentDefinition.
|
|
66
83
|
* Used when Clementine wants to delegate to Ross/Sasha/Nora etc. */
|
|
67
84
|
function profileToAgentDefinition(p) {
|
|
85
|
+
// Always include `Agent` so the subagent can further fan out, plus
|
|
86
|
+
// core read tools as a baseline. profile.team.allowedTools narrows
|
|
87
|
+
// beyond this when set.
|
|
88
|
+
const baseline = ['Agent', 'Read', 'Grep', 'Glob', 'WebSearch', 'WebFetch', 'TodoWrite'];
|
|
89
|
+
const tools = p.team?.allowedTools?.length
|
|
90
|
+
? Array.from(new Set(['Agent', ...p.team.allowedTools]))
|
|
91
|
+
: baseline;
|
|
68
92
|
return {
|
|
69
|
-
description:
|
|
93
|
+
description: buildHiredAgentDescription(p),
|
|
70
94
|
prompt: p.systemPromptBody ?? `You are ${p.name}.`,
|
|
71
|
-
|
|
72
|
-
...(p.team?.allowedTools?.length ? { tools: p.team.allowedTools } : {}),
|
|
95
|
+
tools,
|
|
73
96
|
// Hired agents keep their configured model (Sonnet by default).
|
|
74
97
|
...(p.model ? { model: p.model } : { model: 'sonnet' }),
|
|
75
|
-
// Effort: hired agents do real work, default medium.
|
|
76
|
-
effort: 'medium',
|
|
98
|
+
// Effort: hired agents do real work, default medium. Profile may override.
|
|
99
|
+
...(p.effort ? { effort: p.effort } : { effort: 'medium' }),
|
|
77
100
|
};
|
|
78
101
|
}
|
|
79
102
|
/**
|
|
@@ -89,8 +112,19 @@ export function buildAgentMap(opts = {}) {
|
|
|
89
112
|
// ── System subagents ────────────────────────────────────────────
|
|
90
113
|
// Planner: opus, no tools, single turn. Used when the parent agent
|
|
91
114
|
// sees a multi-step request and wants a decomposition.
|
|
115
|
+
// Description is imperative + matches real user phrasings — the SDK
|
|
116
|
+
// matches against it for auto-routing, so prose doesn't trigger.
|
|
92
117
|
map['planner'] = {
|
|
93
|
-
description:
|
|
118
|
+
description: [
|
|
119
|
+
'Use this subagent BEFORE doing the work whenever the user request',
|
|
120
|
+
'involves 3 or more items, multiple distinct subtasks, or a phrase',
|
|
121
|
+
'like "research my top N", "for each X do Y", "look at all of",',
|
|
122
|
+
'"go through every", "do A, B, and C", or any task that would burn',
|
|
123
|
+
'context if processed serially. The planner returns a JSON plan',
|
|
124
|
+
'with parallel-safe steps; you then spawn researcher/cron-fixer/',
|
|
125
|
+
'hired-agent subagents per step. Always prefer this over doing',
|
|
126
|
+
'multi-item work yourself in the main conversation.',
|
|
127
|
+
].join(' '),
|
|
94
128
|
prompt: PLANNER_PROMPT,
|
|
95
129
|
model: 'opus',
|
|
96
130
|
tools: [], // pure reasoning, no tools
|
|
@@ -98,11 +132,18 @@ export function buildAgentMap(opts = {}) {
|
|
|
98
132
|
maxTurns: 1,
|
|
99
133
|
};
|
|
100
134
|
// Researcher: haiku, per-item investigation. Cheap fan-out target.
|
|
135
|
+
// No Bash — researcher is read-only fanout, must not mutate state.
|
|
101
136
|
map['researcher'] = {
|
|
102
|
-
description:
|
|
137
|
+
description: [
|
|
138
|
+
'Use this subagent to investigate ONE specific item — a single',
|
|
139
|
+
'lead, account, file, web page, or topic — and return a',
|
|
140
|
+
'one-paragraph summary. Spawn it in PARALLEL via the Agent tool',
|
|
141
|
+
'with one subagent per item when the planner returns multiple',
|
|
142
|
+
'research steps. Read-only: never mutates state. Cheap (Haiku).',
|
|
143
|
+
].join(' '),
|
|
103
144
|
prompt: RESEARCHER_PROMPT,
|
|
104
145
|
model: 'haiku',
|
|
105
|
-
tools: ['Read', 'Grep', 'Glob', '
|
|
146
|
+
tools: ['Read', 'Grep', 'Glob', 'WebSearch', 'WebFetch'],
|
|
106
147
|
effort: 'low',
|
|
107
148
|
maxTurns: 15,
|
|
108
149
|
};
|
|
@@ -9,9 +9,8 @@
|
|
|
9
9
|
* - Session expiry: sessions expire after 24 hours of inactivity
|
|
10
10
|
* - Env isolation: Claude subprocess doesn't see credential env vars
|
|
11
11
|
*/
|
|
12
|
-
import type { AgentProfile
|
|
12
|
+
import type { AgentProfile } from '../types.js';
|
|
13
13
|
import { AgentManager } from './agent-manager.js';
|
|
14
|
-
import { type ToolsetName } from './toolsets.js';
|
|
15
14
|
/**
|
|
16
15
|
* Estimate token count for Claude.
|
|
17
16
|
*
|
|
@@ -28,13 +27,10 @@ import { type ToolsetName } from './toolsets.js';
|
|
|
28
27
|
* SDK result; this function is for pre-flight planning only.
|
|
29
28
|
*/
|
|
30
29
|
export declare function estimateTokens(text: string): number;
|
|
31
|
-
export declare function looksLikeContextThrashText(value: unknown): boolean;
|
|
32
30
|
/** Format a millisecond duration as a human-friendly "X ago" string. */
|
|
33
31
|
export declare function formatTimeAgo(ms: number): string;
|
|
34
|
-
export declare function scrubInternalContextBlocks(text: string): string;
|
|
35
32
|
export declare function looksLikeOneMillionContextError(value: unknown): boolean;
|
|
36
33
|
export declare function oneMillionContextRecoveryMessage(): string;
|
|
37
|
-
export declare function looksLikeProviderApiErrorResponse(value: unknown): boolean;
|
|
38
34
|
export declare function looksLikeNoResponseRequested(value: unknown): boolean;
|
|
39
35
|
/** Autonomous jobs use this sentinel to mean "completed, but do not notify the owner." */
|
|
40
36
|
export declare function isAutonomousNothingOutput(response: string): boolean;
|
|
@@ -59,13 +55,6 @@ export interface ProactiveGoalInput {
|
|
|
59
55
|
nextActions?: string[];
|
|
60
56
|
};
|
|
61
57
|
}
|
|
62
|
-
/**
|
|
63
|
-
* Build the compact "active goals" block that gets injected when no goal
|
|
64
|
-
* keyword matches the user's prompt. Pure so it can be tested without the
|
|
65
|
-
* full Assistant/vault setup.
|
|
66
|
-
*/
|
|
67
|
-
export declare function buildActiveGoalsBlock(goals: ProactiveGoalInput[], agentSlug?: string | null, maxEntries?: number): string;
|
|
68
|
-
export declare function chunkReferencedInResponse(chunkContent: string, responseLower: string): boolean;
|
|
69
58
|
export declare class PersonalAssistant {
|
|
70
59
|
static readonly MAX_SESSION_EXCHANGES = 40;
|
|
71
60
|
private sessions;
|
|
@@ -80,9 +69,6 @@ export declare class PersonalAssistant {
|
|
|
80
69
|
private _lastDailyNotePath;
|
|
81
70
|
private memoryStore;
|
|
82
71
|
private _lastUserMessage?;
|
|
83
|
-
private onUnleashedComplete;
|
|
84
|
-
private onPhaseComplete;
|
|
85
|
-
private onPhaseProgress;
|
|
86
72
|
onSkillProposed: ((skill: import('../types.js').SkillDocument) => void) | null;
|
|
87
73
|
private _lastMcpStatus;
|
|
88
74
|
private _lastMcpStatusTime;
|
|
@@ -91,8 +77,6 @@ export declare class PersonalAssistant {
|
|
|
91
77
|
/** Per-session stall nudge — set after a query shows stall signals, consumed on the next query. */
|
|
92
78
|
private stallNudges;
|
|
93
79
|
/** Last contradiction finding per session, consumed by the session transcript writer to splice a correction note. */
|
|
94
|
-
private _lastContradictionFinding;
|
|
95
|
-
private _compactedSessions;
|
|
96
80
|
/** Last auto-matched project per session — exposed for CLI display. */
|
|
97
81
|
private _lastMatchedProject;
|
|
98
82
|
/**
|
|
@@ -100,7 +84,6 @@ export declare class PersonalAssistant {
|
|
|
100
84
|
* post-response outcome scorer can check which actually got referenced.
|
|
101
85
|
* Cleared after each scoring pass.
|
|
102
86
|
*/
|
|
103
|
-
private _lastRetrievedChunks;
|
|
104
87
|
/** Lazy-built SessionStore adapter that mirrors SDK transcripts to SQLite. */
|
|
105
88
|
private _sessionStore;
|
|
106
89
|
/** Hot correction buffer — explicit behavioral corrections applied before nightly SI. */
|
|
@@ -109,11 +92,6 @@ export declare class PersonalAssistant {
|
|
|
109
92
|
private initPromptWatchers;
|
|
110
93
|
/** Log SDK result metrics and store usage. Shared across all query methods. */
|
|
111
94
|
private logQueryResult;
|
|
112
|
-
/** Capture MCP server status from system init messages. */
|
|
113
|
-
private captureMcpStatus;
|
|
114
|
-
setUnleashedCompleteCallback(cb: (jobName: string, result: string) => void): void;
|
|
115
|
-
setPhaseCompleteCallback(cb: (jobName: string, phase: number, totalPhases: number, output: string) => void): void;
|
|
116
|
-
setPhaseProgressCallback(cb: (jobName: string, phase: number, summary: string) => void): void;
|
|
117
95
|
setSkillProposedCallback(cb: (skill: import('../types.js').SkillDocument) => void): void;
|
|
118
96
|
getMcpStatus(): {
|
|
119
97
|
servers: Array<{
|
|
@@ -153,45 +131,6 @@ export declare class PersonalAssistant {
|
|
|
153
131
|
getMemoryChunkCount(): number;
|
|
154
132
|
private buildSystemPrompt;
|
|
155
133
|
private buildOptions;
|
|
156
|
-
private retrieveContext;
|
|
157
|
-
/** Cached active goals — avoids N file reads per query. Refreshes every 30s. */
|
|
158
|
-
private _goalCache;
|
|
159
|
-
private static readonly GOAL_CACHE_TTL_MS;
|
|
160
|
-
private loadGoalsFromCache;
|
|
161
|
-
/**
|
|
162
|
-
* Match a user message against active goals by keyword overlap.
|
|
163
|
-
* Returns formatted goal status block for injection into system prompt,
|
|
164
|
-
* or empty string if no goals match.
|
|
165
|
-
*/
|
|
166
|
-
private matchGoals;
|
|
167
|
-
/**
|
|
168
|
-
* Compact always-on block of active goals. Used when no keyword match
|
|
169
|
-
* fires so the agent still sees what it's supposed to be working on.
|
|
170
|
-
* Scoped: for agent sessions, includes that agent's goals plus any
|
|
171
|
-
* clementine-owned goals it might contribute to.
|
|
172
|
-
*/
|
|
173
|
-
private formatActiveGoalsBlock;
|
|
174
|
-
chat(text: string, sessionKey?: string | null, options?: {
|
|
175
|
-
onText?: OnTextCallback;
|
|
176
|
-
onToolActivity?: OnToolActivityCallback;
|
|
177
|
-
model?: string;
|
|
178
|
-
maxTurns?: number;
|
|
179
|
-
profile?: AgentProfile;
|
|
180
|
-
securityAnnotation?: string;
|
|
181
|
-
projectOverride?: ProjectMeta;
|
|
182
|
-
verboseLevel?: VerboseLevel;
|
|
183
|
-
abortController?: AbortController;
|
|
184
|
-
toolset?: ToolsetName;
|
|
185
|
-
}): Promise<[string, string]>;
|
|
186
|
-
/**
|
|
187
|
-
* Compare retrieved chunks against the response text and record which
|
|
188
|
-
* were referenced. Uses a distinctive-token overlap heuristic — cheap,
|
|
189
|
-
* deterministic, no extra LLM calls. Called right after a turn completes.
|
|
190
|
-
*/
|
|
191
|
-
private scoreRetrievalOutcomes;
|
|
192
|
-
private static readonly RATE_LIMIT_MAX_RETRIES;
|
|
193
|
-
private static readonly RATE_LIMIT_BACKOFF;
|
|
194
|
-
private runQuery;
|
|
195
134
|
/**
|
|
196
135
|
* Compact a session's context when nearing the context window limit.
|
|
197
136
|
*
|
|
@@ -208,11 +147,6 @@ export declare class PersonalAssistant {
|
|
|
208
147
|
summary?: string;
|
|
209
148
|
reason: string;
|
|
210
149
|
};
|
|
211
|
-
/**
|
|
212
|
-
* Expire sessions inactive for more than 24 hours.
|
|
213
|
-
* Called periodically from chat() to prevent unbounded map growth.
|
|
214
|
-
*/
|
|
215
|
-
private expireOldSessions;
|
|
216
150
|
/**
|
|
217
151
|
* Build an instant local summary from in-memory exchange history.
|
|
218
152
|
* No LLM call — returns immediately. Used during session rotation
|
|
@@ -227,36 +161,10 @@ export declare class PersonalAssistant {
|
|
|
227
161
|
* (which represent in-flight messages with no reply yet).
|
|
228
162
|
*/
|
|
229
163
|
private pairTranscriptTurns;
|
|
230
|
-
/**
|
|
231
|
-
* Build a short summary of older turns (older than what's already cached
|
|
232
|
-
* in `lastExchanges`) for restart-restore prompt injection. Returns ''
|
|
233
|
-
* if there's nothing older or no memory store. Capped at 600 chars.
|
|
234
|
-
*/
|
|
235
|
-
private buildOlderTurnsContext;
|
|
236
|
-
/**
|
|
237
|
-
* Reconstruct context after the SDK reports the session is dead
|
|
238
|
-
* ("no conversation found"). Pulls last N turns from the transcripts
|
|
239
|
-
* table (hydrating `lastExchanges` if the cache is too thin) and
|
|
240
|
-
* builds a recovery prefix that gets prepended to the retry prompt.
|
|
241
|
-
* Mirrors the buildContextRecoveredPrompt pattern used by autocompact.
|
|
242
|
-
*/
|
|
243
|
-
private buildSessionDeathRecoveryPrompt;
|
|
244
|
-
/**
|
|
245
|
-
* Auto-save a lightweight handoff file when a session rotates.
|
|
246
|
-
* Uses in-memory exchange history — no LLM call.
|
|
247
|
-
*/
|
|
248
|
-
private saveAutoHandoff;
|
|
249
|
-
/**
|
|
250
|
-
* Load a handoff file for a session if one exists.
|
|
251
|
-
* Returns formatted context string or empty string.
|
|
252
|
-
*/
|
|
253
|
-
private loadHandoff;
|
|
254
164
|
/**
|
|
255
165
|
* Run an LLM summary in the background and save to memoryStore.
|
|
256
166
|
* Does not block the caller — for future retrieval context only.
|
|
257
167
|
*/
|
|
258
|
-
private summarizeSessionAsync;
|
|
259
|
-
private summarizeSession;
|
|
260
168
|
/**
|
|
261
169
|
* Parse a structured checkpoint from an unleashed phase's STATUS SUMMARY output.
|
|
262
170
|
* Returns null if no recognizable structure is found.
|
|
@@ -270,10 +178,6 @@ export declare class PersonalAssistant {
|
|
|
270
178
|
} | null;
|
|
271
179
|
/** Fire-and-forget: extract a reusable skill from a successful execution. */
|
|
272
180
|
private extractSkillFromExecution;
|
|
273
|
-
private preRotationFlush;
|
|
274
|
-
private lastExtractionTimes;
|
|
275
|
-
private memoryExtractionKey;
|
|
276
|
-
private assessMemoryExtraction;
|
|
277
181
|
private logMemoryExtractionSkip;
|
|
278
182
|
/**
|
|
279
183
|
* Public entry point for triggering auto-memory extraction after an
|
|
@@ -298,7 +202,6 @@ export declare class PersonalAssistant {
|
|
|
298
202
|
private spawnMemoryExtraction;
|
|
299
203
|
private static readonly MEMORY_TOOL_NAMES;
|
|
300
204
|
private extractMemory;
|
|
301
|
-
heartbeat(standingInstructions: string, changesSummary?: string, timeContext?: string, dedupContext?: string, profile?: AgentProfile | null): Promise<string>;
|
|
302
205
|
runPlanStep(stepId: string, prompt: string, opts?: {
|
|
303
206
|
tier?: number;
|
|
304
207
|
maxTurns?: number;
|
|
@@ -315,9 +218,6 @@ export declare class PersonalAssistant {
|
|
|
315
218
|
usageLabel?: string;
|
|
316
219
|
usageAgentSlug?: string;
|
|
317
220
|
}): Promise<string>;
|
|
318
|
-
runCronJob(jobName: string, jobPrompt: string, tier?: number, maxTurns?: number, model?: string, workDir?: string, timeoutMs?: number, successCriteria?: string[], agentSlug?: string, opts?: {
|
|
319
|
-
disableAllTools?: boolean;
|
|
320
|
-
}): Promise<string>;
|
|
321
221
|
/**
|
|
322
222
|
* Goal-backward verification pass using Haiku after cron job execution.
|
|
323
223
|
* Instead of vague quality ratings, verifies actual outcomes:
|
|
@@ -326,15 +226,6 @@ export declare class PersonalAssistant {
|
|
|
326
226
|
* 3. Does it connect to the goal / produce actionable results? (wired)
|
|
327
227
|
*/
|
|
328
228
|
private runCronReflection;
|
|
329
|
-
runUnleashedTask(jobName: string, jobPrompt: string, tier?: number, maxTurns?: number, model?: string, workDir?: string, maxHours?: number, agentSlug?: string): Promise<string>;
|
|
330
|
-
/**
|
|
331
|
-
* Run a team message as an unleashed-style autonomous task.
|
|
332
|
-
* Gives team agents the same multi-phase execution as cron jobs,
|
|
333
|
-
* instead of being killed by the 5-minute interactive chat timeout.
|
|
334
|
-
*
|
|
335
|
-
* @param onText Streaming callback for real-time progress updates
|
|
336
|
-
*/
|
|
337
|
-
runTeamTask(fromName: string, fromSlug: string, content: string, profile: AgentProfile, onText?: (token: string) => void, externalAbortController?: AbortController): Promise<string>;
|
|
338
229
|
/**
|
|
339
230
|
* Inject a user/assistant exchange into a session's context without running
|
|
340
231
|
* a query. Used to give the DM session visibility of cron/heartbeat outputs
|