@capekai/core 1.0.0
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/README.md +12 -0
- package/package.json +105 -0
- package/src/adapters/ai-sdk.ts +84 -0
- package/src/compaction/contracts.ts +82 -0
- package/src/compaction/executor.ts +161 -0
- package/src/compaction/policy.ts +318 -0
- package/src/compaction/recovery.ts +139 -0
- package/src/compaction/task.ts +540 -0
- package/src/configuration/contracts.ts +58 -0
- package/src/configuration/defaults.ts +27 -0
- package/src/configuration/runtime.ts +42 -0
- package/src/configuration/single-model.ts +75 -0
- package/src/context/assembler.ts +112 -0
- package/src/context/index.ts +2 -0
- package/src/context/sources.ts +119 -0
- package/src/context/workspace.ts +63 -0
- package/src/core/agent.ts +401 -0
- package/src/core/build-tools.ts +139 -0
- package/src/core/chat-handler.ts +858 -0
- package/src/core/error-handling.ts +18 -0
- package/src/core/fork.ts +103 -0
- package/src/core/interrupt.ts +192 -0
- package/src/core/message-utils.ts +261 -0
- package/src/core/model-utils.ts +149 -0
- package/src/core/part-utils.ts +88 -0
- package/src/core/provider-utils.ts +67 -0
- package/src/core/revert.ts +46 -0
- package/src/core/step-handlers.ts +157 -0
- package/src/core/stream/finalization.ts +65 -0
- package/src/core/stream/stream-config.ts +82 -0
- package/src/core/stream-handlers.ts +242 -0
- package/src/core/structured-output.ts +68 -0
- package/src/core/tool-builders/agent-tools.ts +71 -0
- package/src/core/tool-builders/external-tools.ts +179 -0
- package/src/core/tool-builders/types.ts +16 -0
- package/src/core/tool-builders/workspace-tools.ts +293 -0
- package/src/core/tool-capabilities.ts +65 -0
- package/src/goals/evaluator.ts +171 -0
- package/src/goals/index.ts +3 -0
- package/src/goals/loop.ts +167 -0
- package/src/goals/service.ts +39 -0
- package/src/index.ts +10 -0
- package/src/internal/ask-authority.ts +29 -0
- package/src/internal/composition.ts +44 -0
- package/src/internal/configuration.ts +22 -0
- package/src/internal/execution.ts +108 -0
- package/src/internal/hosts.ts +64 -0
- package/src/internal/plugins.ts +71 -0
- package/src/internal/providers.ts +32 -0
- package/src/internal/sandbox.ts +19 -0
- package/src/internal/tools.ts +48 -0
- package/src/internal/workspace.ts +25 -0
- package/src/kernel/diagnostics.ts +249 -0
- package/src/kernel/errors.ts +120 -0
- package/src/kernel/events.ts +82 -0
- package/src/kernel/index.ts +72 -0
- package/src/kernel/kernel.ts +62 -0
- package/src/kernel/lifecycle.ts +72 -0
- package/src/kernel/plugin.ts +218 -0
- package/src/kernel/registry.ts +493 -0
- package/src/kernel/scope.ts +776 -0
- package/src/kernel/service-key.ts +19 -0
- package/src/kernel/types.ts +317 -0
- package/src/memory/index.ts +2 -0
- package/src/memory/memory-tool.ts +75 -0
- package/src/memory/registry.ts +172 -0
- package/src/permission/ask-user-api.ts +70 -0
- package/src/permission/contracts.ts +135 -0
- package/src/permission/permission-request-manager.ts +58 -0
- package/src/permission/policy.ts +277 -0
- package/src/permission/runtime.ts +612 -0
- package/src/plugins/compaction-policy.ts +46 -0
- package/src/plugins/compose.ts +171 -0
- package/src/plugins/context-sections.ts +246 -0
- package/src/plugins/default-agent-driver.ts +14 -0
- package/src/plugins/facade-plugins.ts +129 -0
- package/src/plugins/goal-domain.ts +82 -0
- package/src/plugins/legacy-system-message.ts +152 -0
- package/src/plugins/loaded-tools.ts +23 -0
- package/src/plugins/memory-domain.ts +264 -0
- package/src/plugins/orchestrator-session.ts +29 -0
- package/src/plugins/permission-policy.ts +49 -0
- package/src/plugins/retry-policy.ts +28 -0
- package/src/plugins/scheduler-domain.ts +192 -0
- package/src/plugins/service-keys.ts +294 -0
- package/src/plugins/session-search-domain.ts +238 -0
- package/src/plugins/skills-domain.ts +272 -0
- package/src/plugins/subagent-domain.ts +287 -0
- package/src/plugins/tool-catalog.ts +78 -0
- package/src/plugins/tool-output-policy.ts +52 -0
- package/src/plugins/value-plugins.ts +150 -0
- package/src/plugins/workflow-domain.ts +198 -0
- package/src/plugins/workspace-policy.ts +37 -0
- package/src/providers/registry.ts +63 -0
- package/src/providers/types.ts +44 -0
- package/src/retry/policy.ts +282 -0
- package/src/retry/stream-chat.ts +312 -0
- package/src/runtime/agent-runtime.ts +83 -0
- package/src/runtime/default-agent-driver.ts +23 -0
- package/src/runtime/domain-tool-source.ts +156 -0
- package/src/runtime/events.ts +61 -0
- package/src/runtime/host-dependencies.ts +71 -0
- package/src/runtime/host-guidance.ts +22 -0
- package/src/runtime/host-layout.ts +23 -0
- package/src/runtime/host.ts +129 -0
- package/src/runtime/standalone-host.ts +118 -0
- package/src/sandbox/controller.ts +204 -0
- package/src/sandbox/model.ts +305 -0
- package/src/sandbox/provider.ts +53 -0
- package/src/sandbox/types.ts +110 -0
- package/src/scheduler/host.ts +22 -0
- package/src/scheduler/scheduler-tool.ts +172 -0
- package/src/session-search/host.ts +56 -0
- package/src/session-search/index.ts +23 -0
- package/src/session-search/session-search-tool.ts +151 -0
- package/src/skills/index.ts +3 -0
- package/src/skills/registry.ts +63 -0
- package/src/skills/skill-manage-tool.ts +205 -0
- package/src/skills/skill-tool.ts +42 -0
- package/src/storage/contracts.ts +159 -0
- package/src/storage/memory.ts +321 -0
- package/src/storage/options.ts +75 -0
- package/src/storage/runtime.ts +115 -0
- package/src/storage/sqlite-tool-output-artifacts.ts +106 -0
- package/src/storage/sqlite.ts +321 -0
- package/src/storage/tool-output-artifacts.ts +75 -0
- package/src/storage.ts +31 -0
- package/src/subagent/child-session.ts +282 -0
- package/src/subagent/guidance.ts +8 -0
- package/src/subagent/policy.ts +198 -0
- package/src/subagent/task-tool.ts +584 -0
- package/src/tool-output/contracts.ts +111 -0
- package/src/tool-output/policy.ts +410 -0
- package/src/tool.ts +1 -0
- package/src/tools/executor.ts +258 -0
- package/src/tools/install-manifest.ts +40 -0
- package/src/tools/llm-api.ts +77 -0
- package/src/tools/registry.ts +206 -0
- package/src/tools/tool-artifact.ts +182 -0
- package/src/tools/tool-source.ts +53 -0
- package/src/utils/errors.ts +334 -0
- package/src/utils/strip-visualization.ts +50 -0
- package/src/workflow/decomposer.ts +139 -0
- package/src/workflow/execution.ts +523 -0
- package/src/workflow/orchestrator-session.ts +161 -0
- package/src/workflow/synthesizer.ts +130 -0
- package/src/workspace/contracts.ts +135 -0
- package/src/workspace/policy.ts +327 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import type { Preconfig } from '@capekai/types';
|
|
2
|
+
import { loadMemoryInstructions } from '../memory';
|
|
3
|
+
import { selfDelegationGuidance } from '../subagent/guidance';
|
|
4
|
+
import {
|
|
5
|
+
buildWorkspaceSystemPrompt,
|
|
6
|
+
formatInstructions,
|
|
7
|
+
getAgentDirectory,
|
|
8
|
+
loadInstructions,
|
|
9
|
+
readAgentMemoryFile,
|
|
10
|
+
} from '../context';
|
|
11
|
+
import { getWorkspace } from '../storage/runtime';
|
|
12
|
+
import { getHostGuidance } from '../runtime/host-guidance';
|
|
13
|
+
import { getHostLayout } from '../runtime/host-layout';
|
|
14
|
+
import {
|
|
15
|
+
validateContextAssemblyData,
|
|
16
|
+
type ContextAssembler,
|
|
17
|
+
type ContextAssemblyData,
|
|
18
|
+
} from '../context/assembler';
|
|
19
|
+
import type { ContextSectionContribution } from '../kernel/types';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Fixed system-message builder, byte-frozen as the C3 legacy adapter.
|
|
23
|
+
*
|
|
24
|
+
* C3 replaced this builder with ordered context contributions, but the fixed
|
|
25
|
+
* implementation stays available through `internal/execution` for migration
|
|
26
|
+
* and serves as the reference against which ordered assembly is verified
|
|
27
|
+
* byte-for-byte. The section guidance constants below are shared with the
|
|
28
|
+
* ordered contributions so both paths emit identical bytes.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
export interface SystemMessageOptions {
|
|
32
|
+
preconfig: Preconfig;
|
|
33
|
+
workspacePath?: string;
|
|
34
|
+
workspaceId?: string;
|
|
35
|
+
additionalPaths?: string[];
|
|
36
|
+
selfDelegationAvailable?: boolean;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** The fixed builder behind the ContextAssembler contract. Installed as the
|
|
40
|
+
* default assembler so consumers that run outside a composed agent scope
|
|
41
|
+
* (the current Jean2 server path) keep the exact pre-C3 behavior until they
|
|
42
|
+
* adopt the ordered composition. */
|
|
43
|
+
export const fixedBuilderContextAssembler: ContextAssembler = {
|
|
44
|
+
id: 'fixed-legacy-adapter',
|
|
45
|
+
build: (data) => buildSystemMessage(data),
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/** The legacy session-search guidance contribution, kept for facade and
|
|
49
|
+
* legacy compositions that reproduce the fixed builder byte-for-byte. The
|
|
50
|
+
* C5 domain plugin owns this section in the current Jean2 composition;
|
|
51
|
+
* `createContextSectionsPlugin` includes it only when its
|
|
52
|
+
* `includeSessionSearchGuidance` option stays at the legacy default. */
|
|
53
|
+
export const legacySessionSearchGuidanceSection: ContextSectionContribution<ContextAssemblyData> = {
|
|
54
|
+
id: 'session-search-guidance',
|
|
55
|
+
phase: 'workspace',
|
|
56
|
+
order: 50,
|
|
57
|
+
provide: async (context) => {
|
|
58
|
+
const data = validateContextAssemblyData(context.data);
|
|
59
|
+
if (!data.workspaceId) return null;
|
|
60
|
+
return (await getWorkspace(data.workspaceId))?.settings?.sessionSearch?.enabled
|
|
61
|
+
? getHostGuidance().sessionSearch
|
|
62
|
+
: null;
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const AGENT_MEMORY_SKILLS_GUIDANCE = `You have personal memory and skills that travel with you across all workspaces.
|
|
67
|
+
|
|
68
|
+
MEMORY:
|
|
69
|
+
- Use "memory" (workspace) for facts about THIS project (repo conventions, build commands, project-specific patterns).
|
|
70
|
+
- Use "agent_memory" (personal) for cross-project knowledge: reusable patterns, techniques, pitfalls, and user preferences that apply everywhere.
|
|
71
|
+
- Save to agent_memory when: you complete a complex multi-step task, the user corrects your approach, you discover a pattern useful beyond this project, or you debug through errors.
|
|
72
|
+
|
|
73
|
+
SKILLS:
|
|
74
|
+
- Use "skill_manage" for procedures specific to THIS workspace.
|
|
75
|
+
- Use "agent_skill_manage" for personal workflows you've refined across projects.
|
|
76
|
+
|
|
77
|
+
Before saving, use list to check existing entries and avoid duplicates.`;
|
|
78
|
+
|
|
79
|
+
/** The legacy self-delegation guidance contribution, kept for facade and
|
|
80
|
+
* legacy compositions that reproduce the fixed builder byte-for-byte. The
|
|
81
|
+
* C5 subagent domain plugin owns this section in the current Jean2 and
|
|
82
|
+
* facade compositions; `createContextSectionsPlugin` includes it only when
|
|
83
|
+
* its `includeSelfDelegationGuidance` option stays at the legacy default. */
|
|
84
|
+
export const legacySelfDelegationGuidanceSection: ContextSectionContribution<ContextAssemblyData> = {
|
|
85
|
+
id: 'self-delegation',
|
|
86
|
+
phase: 'identity',
|
|
87
|
+
order: 50,
|
|
88
|
+
provide: (context) => {
|
|
89
|
+
const data = validateContextAssemblyData(context.data);
|
|
90
|
+
return data.selfDelegationAvailable ? selfDelegationGuidance(data.preconfig.id) : null;
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export async function buildSystemMessage(options: SystemMessageOptions): Promise<string> {
|
|
95
|
+
const { preconfig, workspacePath, workspaceId, additionalPaths } = options;
|
|
96
|
+
|
|
97
|
+
let systemMessage = preconfig.systemPrompt || '';
|
|
98
|
+
|
|
99
|
+
// Inject agent memory layers if this is an agent
|
|
100
|
+
const agentDir = await getAgentDirectory(preconfig.id);
|
|
101
|
+
if (agentDir) {
|
|
102
|
+
const agentUserMemory = await readAgentMemoryFile(preconfig.id, 'USER.md');
|
|
103
|
+
if (agentUserMemory) {
|
|
104
|
+
systemMessage = `<agent_user_preferences>\n${agentUserMemory}\n</agent_user_preferences>\n\n` + systemMessage;
|
|
105
|
+
}
|
|
106
|
+
const agentMemory = await readAgentMemoryFile(preconfig.id, 'MEMORY.md');
|
|
107
|
+
if (agentMemory) {
|
|
108
|
+
systemMessage = `<agent_memory>\n${agentMemory}\n</agent_memory>\n\n` + systemMessage;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
systemMessage = systemMessage + '\n\n' + getHostGuidance().agentMemorySkills;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (options.selfDelegationAvailable) {
|
|
115
|
+
systemMessage = systemMessage + '\n\n' + selfDelegationGuidance(preconfig.id);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Add instructions (global first, then project)
|
|
119
|
+
const instructions = await loadInstructions(workspacePath);
|
|
120
|
+
const instructionsSection = formatInstructions(instructions);
|
|
121
|
+
if (instructionsSection) {
|
|
122
|
+
systemMessage = systemMessage + '\n\n' + instructionsSection;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Add workspace context
|
|
126
|
+
if (workspacePath) {
|
|
127
|
+
const workspaceContext = buildWorkspaceSystemPrompt(workspacePath, additionalPaths);
|
|
128
|
+
systemMessage = systemMessage + '\n\n' + workspaceContext;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Add workspace-gated guidance sections
|
|
132
|
+
if (workspaceId) {
|
|
133
|
+
const workspace = await getWorkspace(workspaceId);
|
|
134
|
+
if (workspace?.settings?.memory?.enabled && workspacePath) {
|
|
135
|
+
const memorySection = await loadMemoryInstructions(getHostLayout().workspaceMemoryDir(workspacePath));
|
|
136
|
+
if (memorySection) {
|
|
137
|
+
systemMessage = systemMessage + '\n\n' + memorySection;
|
|
138
|
+
}
|
|
139
|
+
systemMessage = systemMessage + '\n\n' + getHostGuidance().memory;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (workspace?.settings?.skills?.managementEnabled) {
|
|
143
|
+
systemMessage = systemMessage + '\n\n' + getHostGuidance().skillManage;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (workspace?.settings?.sessionSearch?.enabled) {
|
|
147
|
+
systemMessage = systemMessage + '\n\n' + getHostGuidance().sessionSearch;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return systemMessage;
|
|
152
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { LoadedTool } from '@capekai/tool';
|
|
2
|
+
import type { CapekPlugin, ToolDefinition } from '../kernel/types';
|
|
3
|
+
|
|
4
|
+
/** One agent plugin contributing the given loaded tools as visible tool
|
|
5
|
+
* contributions carrying their execution payloads, in array order. This is
|
|
6
|
+
* the plugin behind the former `createAgent({ tools })` option; compose it
|
|
7
|
+
* directly into your agent scope's plugin list. */
|
|
8
|
+
export function loadedToolsPlugin(id: string, tools: readonly LoadedTool[]): CapekPlugin<unknown> {
|
|
9
|
+
return {
|
|
10
|
+
id,
|
|
11
|
+
scope: 'agent',
|
|
12
|
+
setup(context) {
|
|
13
|
+
tools.forEach((loaded, index) => {
|
|
14
|
+
context.contributeTool({
|
|
15
|
+
id: `${id}.${loaded.definition.name}`,
|
|
16
|
+
order: 1000 + index,
|
|
17
|
+
definition: loaded.definition as unknown as ToolDefinition,
|
|
18
|
+
payload: loaded,
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import type { PermissionRiskLevel } from '@capekai/tool';
|
|
2
|
+
import { serviceKey } from '../kernel/service-key';
|
|
3
|
+
import type {
|
|
4
|
+
CapekPlugin,
|
|
5
|
+
ContextSectionContribution,
|
|
6
|
+
PluginContext,
|
|
7
|
+
ToolDefinition as KernelToolDefinition,
|
|
8
|
+
} from '../kernel/types';
|
|
9
|
+
import {
|
|
10
|
+
DOMAIN_TOOL_PAYLOAD_FIELD,
|
|
11
|
+
registerDomainToolFallback,
|
|
12
|
+
type DomainToolPayload,
|
|
13
|
+
} from '../runtime/domain-tool-source';
|
|
14
|
+
import { validateContextAssemblyData, type ContextAssemblyData } from '../context/assembler';
|
|
15
|
+
import type { ContextSources } from '../context/sources';
|
|
16
|
+
import {
|
|
17
|
+
executeMemoryTool,
|
|
18
|
+
memoryToolDefinition,
|
|
19
|
+
loadMemoryInstructions,
|
|
20
|
+
} from '../memory';
|
|
21
|
+
import type { StorageBundle } from '../storage/contracts';
|
|
22
|
+
import { getHostGuidance } from '../runtime/host-guidance';
|
|
23
|
+
import { getHostLayout } from '../runtime/host-layout';
|
|
24
|
+
import { capekContextSourcesKey, capekStorageKey } from './service-keys';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* C5 memory domain plugin. Owns the agent-scoped memory service: the
|
|
28
|
+
* workspace `memory` tool payload, the agent `agent_memory` tool payload,
|
|
29
|
+
* and the memory context sections (agent-memory, agent-user-preferences,
|
|
30
|
+
* memory-skills-guidance, workspace-memory, memory-guidance). Tool building
|
|
31
|
+
* stays in the core tool builders over the generic contributed-domain-tool
|
|
32
|
+
* seam; the payloads read only the build context the builders capture
|
|
33
|
+
* (workspace path, permission risk, agent directory), never module globals.
|
|
34
|
+
* The unscoped fallback installs explicitly, never at module load.
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
export const CURRENT_MEMORY_DOMAIN_PLUGIN_ID = 'current.memory-domain';
|
|
38
|
+
export const MEMORY_TOOL_CONTRIBUTION_ID = 'memory.memory';
|
|
39
|
+
export const MEMORY_TOOL_CONTRIBUTION_ORDER = 665;
|
|
40
|
+
export const AGENT_MEMORY_TOOL_CONTRIBUTION_ID = 'memory.agent_memory';
|
|
41
|
+
export const AGENT_MEMORY_TOOL_CONTRIBUTION_ORDER = 800;
|
|
42
|
+
|
|
43
|
+
export interface MemoryDomainService {
|
|
44
|
+
readonly tools: readonly DomainToolPayload[];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const capekMemoryDomainKey = serviceKey<MemoryDomainService>(
|
|
48
|
+
'capek.memory-domain',
|
|
49
|
+
'agent',
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
export function createMemoryToolPayload(): DomainToolPayload {
|
|
53
|
+
return {
|
|
54
|
+
name: memoryToolDefinition.name,
|
|
55
|
+
description: memoryToolDefinition.description,
|
|
56
|
+
inputSchema: memoryToolDefinition.inputSchema,
|
|
57
|
+
display: { summary: '{action} {target}' },
|
|
58
|
+
visualize: (_input, result) => {
|
|
59
|
+
const r = result as { action?: string; target?: string; usage?: { chars?: number; limit?: number }; entries?: string[] };
|
|
60
|
+
if (r.action === 'list') {
|
|
61
|
+
const count = Array.isArray(r.entries) ? r.entries.length : 0;
|
|
62
|
+
const usage = r.usage ? `${r.usage.chars ?? 0}/${r.usage.limit ?? 0} chars` : '';
|
|
63
|
+
return {
|
|
64
|
+
type: 'none',
|
|
65
|
+
badge: [`${count} entr${count === 1 ? 'y' : 'ies'}`, usage].filter(Boolean).join(' · '),
|
|
66
|
+
message: `Memory (${r.target ?? 'memory'})`,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
return { type: 'none', message: String(result.title ?? 'Memory updated') };
|
|
70
|
+
},
|
|
71
|
+
execute: async (input, context) => {
|
|
72
|
+
const workspacePath = context.workspacePath as string;
|
|
73
|
+
const risk = (context.permissionRisk ?? 'none') as PermissionRiskLevel;
|
|
74
|
+
const result = await executeMemoryTool(
|
|
75
|
+
input,
|
|
76
|
+
getHostLayout().workspaceMemoryDir(workspacePath),
|
|
77
|
+
risk,
|
|
78
|
+
context.ask,
|
|
79
|
+
);
|
|
80
|
+
if (!result.success) {
|
|
81
|
+
return {
|
|
82
|
+
error: result.error ?? 'Memory operation failed',
|
|
83
|
+
...(result.entries ? { entries: result.entries } : {}),
|
|
84
|
+
...(result.usage ? { usage: result.usage } : {}),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
const r = result.result!;
|
|
88
|
+
return {
|
|
89
|
+
title: r.action === 'list' ? `Memory list (${r.target})` : 'Memory updated',
|
|
90
|
+
...r,
|
|
91
|
+
};
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function createAgentMemoryToolPayload(): DomainToolPayload {
|
|
97
|
+
return {
|
|
98
|
+
name: 'agent_memory',
|
|
99
|
+
description: `Persist YOUR personal knowledge that travels with you across all workspaces.
|
|
100
|
+
|
|
101
|
+
Use target="user" for cross-workspace user preferences (how this person likes to work).
|
|
102
|
+
Use target="memory" for accumulated work knowledge (lessons, patterns, techniques from any project).
|
|
103
|
+
|
|
104
|
+
This is YOUR personal memory. It is separate from the workspace memory tool.
|
|
105
|
+
- Use "memory" (workspace) for project-specific facts about the current codebase.
|
|
106
|
+
- Use "agent_memory" (this tool) for cross-project knowledge that applies everywhere.
|
|
107
|
+
|
|
108
|
+
Actions:
|
|
109
|
+
- list: Read current entries and char usage. Requires target only.
|
|
110
|
+
- add: Append a new bullet entry. Requires content.
|
|
111
|
+
- replace: Find an entry by oldText substring and replace it.
|
|
112
|
+
- remove: Find an entry by oldText substring and remove it.
|
|
113
|
+
|
|
114
|
+
Character limits: user=1500, memory=2500. Keep entries compact.`,
|
|
115
|
+
inputSchema: memoryToolDefinition.inputSchema,
|
|
116
|
+
display: { summary: '{action} {target}' },
|
|
117
|
+
visualize: (_input, result) => {
|
|
118
|
+
const r = result as { action?: string; target?: string; entries?: string[] };
|
|
119
|
+
if (r.action === 'list') {
|
|
120
|
+
const count = Array.isArray(r.entries) ? r.entries.length : 0;
|
|
121
|
+
return {
|
|
122
|
+
type: 'none',
|
|
123
|
+
badge: `${count} entr${count === 1 ? 'y' : 'ies'}`,
|
|
124
|
+
message: `Agent memory (${r.target ?? 'memory'})`,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
return { type: 'none', message: String(result.title ?? 'Agent memory updated') };
|
|
128
|
+
},
|
|
129
|
+
execute: async (input, context) => {
|
|
130
|
+
const result = await executeMemoryTool(input, context.agentDir as string, 'none');
|
|
131
|
+
if (!result.success) {
|
|
132
|
+
return { error: result.error ?? 'Agent memory operation failed' };
|
|
133
|
+
}
|
|
134
|
+
const r = result.result!;
|
|
135
|
+
return {
|
|
136
|
+
title: r.action === 'list' ? `Agent memory list (${r.target})` : 'Agent memory updated',
|
|
137
|
+
...r,
|
|
138
|
+
};
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Explicitly installs the unscoped legacy fallbacks. Called by the Jean2
|
|
144
|
+
* compatibility bindings installation (server bootstrap) and by focused
|
|
145
|
+
* tests; no module-load registration exists. */
|
|
146
|
+
export function installMemoryToolFallback(): void {
|
|
147
|
+
registerDomainToolFallback('memory', createMemoryToolPayload());
|
|
148
|
+
registerDomainToolFallback('agent_memory', createAgentMemoryToolPayload());
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
type MemorySectionContribution = ContextSectionContribution<ContextAssemblyData>;
|
|
152
|
+
|
|
153
|
+
function agentMemorySections(
|
|
154
|
+
sources: Partial<ContextSources>,
|
|
155
|
+
guidance: string,
|
|
156
|
+
): readonly MemorySectionContribution[] {
|
|
157
|
+
return [
|
|
158
|
+
{
|
|
159
|
+
id: 'agent-memory',
|
|
160
|
+
phase: 'identity',
|
|
161
|
+
order: 10,
|
|
162
|
+
provide: async (build) => {
|
|
163
|
+
const data = validateContextAssemblyData(build.data);
|
|
164
|
+
const agentDir = await sources.agents?.getDirectory(data.preconfig.id);
|
|
165
|
+
if (!agentDir) return null;
|
|
166
|
+
const memory = await sources.agents?.readMemoryFile(data.preconfig.id, 'MEMORY.md');
|
|
167
|
+
return memory ? `<agent_memory>\n${memory}\n</agent_memory>` : null;
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
id: 'agent-user-preferences',
|
|
172
|
+
phase: 'identity',
|
|
173
|
+
order: 20,
|
|
174
|
+
provide: async (build) => {
|
|
175
|
+
const data = validateContextAssemblyData(build.data);
|
|
176
|
+
const agentDir = await sources.agents?.getDirectory(data.preconfig.id);
|
|
177
|
+
if (!agentDir) return null;
|
|
178
|
+
const memory = await sources.agents?.readMemoryFile(data.preconfig.id, 'USER.md');
|
|
179
|
+
return memory ? `<agent_user_preferences>\n${memory}\n</agent_user_preferences>` : null;
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
id: 'memory-skills-guidance',
|
|
184
|
+
phase: 'identity',
|
|
185
|
+
order: 40,
|
|
186
|
+
provide: async (build) => {
|
|
187
|
+
const data = validateContextAssemblyData(build.data);
|
|
188
|
+
const agentDir = await sources.agents?.getDirectory(data.preconfig.id);
|
|
189
|
+
return agentDir ? guidance : null;
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
];
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function workspaceMemorySections(storage: StorageBundle): readonly MemorySectionContribution[] {
|
|
196
|
+
return [
|
|
197
|
+
{
|
|
198
|
+
id: 'workspace-memory',
|
|
199
|
+
phase: 'workspace',
|
|
200
|
+
order: 20,
|
|
201
|
+
provide: async (build) => {
|
|
202
|
+
const data = validateContextAssemblyData(build.data);
|
|
203
|
+
if (!data.workspaceId) return null;
|
|
204
|
+
const workspace = await storage.workspaces.get(data.workspaceId);
|
|
205
|
+
if (!workspace?.settings?.memory?.enabled || !data.workspacePath) return null;
|
|
206
|
+
return loadMemoryInstructions(getHostLayout().workspaceMemoryDir(data.workspacePath));
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
id: 'memory-guidance',
|
|
211
|
+
phase: 'workspace',
|
|
212
|
+
order: 30,
|
|
213
|
+
provide: async (build) => {
|
|
214
|
+
const data = validateContextAssemblyData(build.data);
|
|
215
|
+
if (!data.workspaceId) return null;
|
|
216
|
+
const workspace = await storage.workspaces.get(data.workspaceId);
|
|
217
|
+
return workspace?.settings?.memory?.enabled && data.workspacePath ? getHostGuidance().memory : null;
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
];
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export function memoryDomainPlugin(id: string): CapekPlugin<unknown> {
|
|
224
|
+
return {
|
|
225
|
+
id,
|
|
226
|
+
scope: 'agent',
|
|
227
|
+
provides: [capekMemoryDomainKey],
|
|
228
|
+
requires: [capekStorageKey, capekContextSourcesKey],
|
|
229
|
+
setup(context: PluginContext) {
|
|
230
|
+
const storage: StorageBundle = context.require(capekStorageKey);
|
|
231
|
+
const sources: Partial<ContextSources> = context.require(capekContextSourcesKey);
|
|
232
|
+
|
|
233
|
+
const service: MemoryDomainService = {
|
|
234
|
+
tools: [createMemoryToolPayload(), createAgentMemoryToolPayload()],
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
context.provide(capekMemoryDomainKey, service);
|
|
238
|
+
for (const payload of service.tools) {
|
|
239
|
+
context.contributeTool({
|
|
240
|
+
id: payload.name === 'memory'
|
|
241
|
+
? MEMORY_TOOL_CONTRIBUTION_ID
|
|
242
|
+
: AGENT_MEMORY_TOOL_CONTRIBUTION_ID,
|
|
243
|
+
order: payload.name === 'memory'
|
|
244
|
+
? MEMORY_TOOL_CONTRIBUTION_ORDER
|
|
245
|
+
: AGENT_MEMORY_TOOL_CONTRIBUTION_ORDER,
|
|
246
|
+
definition: {
|
|
247
|
+
name: payload.name,
|
|
248
|
+
description: payload.description,
|
|
249
|
+
inputSchema: payload.inputSchema,
|
|
250
|
+
timeout: 10000,
|
|
251
|
+
[DOMAIN_TOOL_PAYLOAD_FIELD]: payload,
|
|
252
|
+
} as KernelToolDefinition,
|
|
253
|
+
requiredCapabilities: [capekMemoryDomainKey],
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
for (const section of agentMemorySections(sources, getHostGuidance().agentMemorySkills)) {
|
|
257
|
+
context.contributeContext(section);
|
|
258
|
+
}
|
|
259
|
+
for (const section of workspaceMemorySections(storage)) {
|
|
260
|
+
context.contributeContext(section);
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
};
|
|
264
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { CapekPlugin, PluginContext } from '../kernel/types';
|
|
2
|
+
import { runOrchestratorSession } from '../workflow/orchestrator-session';
|
|
3
|
+
import {
|
|
4
|
+
capekOrchestratorSessionKey,
|
|
5
|
+
type OrchestratorSessionContract,
|
|
6
|
+
} from './service-keys';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* C5 provider for the shared workflow/goals orchestrator model-turn
|
|
10
|
+
* contract (`capek.orchestrator-session`). Wraps the current implementation
|
|
11
|
+
* at `workflow/orchestrator-session.ts` with its exact function identity, so
|
|
12
|
+
* the workflow domain plugin and, next slice, the goals domain plugin
|
|
13
|
+
* consume the same named service without owning workflow code. The provider
|
|
14
|
+
* is a composition bridge; its workflow-domain import is pinned by the
|
|
15
|
+
* `plugins-no-workflow-ownership` boundary rule.
|
|
16
|
+
*/
|
|
17
|
+
export function orchestratorSessionProviderPlugin(id: string): CapekPlugin<unknown> {
|
|
18
|
+
return {
|
|
19
|
+
id,
|
|
20
|
+
scope: 'agent',
|
|
21
|
+
provides: [capekOrchestratorSessionKey],
|
|
22
|
+
setup(context: PluginContext) {
|
|
23
|
+
const contract: OrchestratorSessionContract = {
|
|
24
|
+
run: runOrchestratorSession,
|
|
25
|
+
};
|
|
26
|
+
context.provide(capekOrchestratorSessionKey, contract);
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { CapekPlugin, PluginContext } from '../kernel/types';
|
|
2
|
+
import {
|
|
3
|
+
createAskPermissionService,
|
|
4
|
+
type AskPermissionServiceCreateOptions,
|
|
5
|
+
} from '../permission/policy';
|
|
6
|
+
import { createPermissionRuntimeService } from '../permission/runtime';
|
|
7
|
+
import {
|
|
8
|
+
capekPermissionPolicyKey,
|
|
9
|
+
capekPermissionRuntimeKey,
|
|
10
|
+
capekRuntimeHostKey,
|
|
11
|
+
} from './service-keys';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* C6 providers for the permission surface:
|
|
15
|
+
*
|
|
16
|
+
* - `capek.permission-policy` (REPLACEABLE advice/config): the permission
|
|
17
|
+
* timeout translates into provider options here, at composition. The
|
|
18
|
+
* generic ask timeout has no current configuration source and stays the
|
|
19
|
+
* fixed 5-minute constant.
|
|
20
|
+
* - `capek.permission-runtime` (NON-REPLACEABLE lifecycle): request-id
|
|
21
|
+
* routing, waiters, validation enforcement, raw-audit denial, and
|
|
22
|
+
* canonical grant construction/persistence. A replacement policy can
|
|
23
|
+
* change advice only; it can never approve malformed responses or create
|
|
24
|
+
* grants outside the canonical allowed scopes.
|
|
25
|
+
*/
|
|
26
|
+
export function permissionPolicyPlugin(id: string): CapekPlugin<unknown> {
|
|
27
|
+
return {
|
|
28
|
+
id,
|
|
29
|
+
scope: 'agent',
|
|
30
|
+
provides: [capekPermissionPolicyKey, capekPermissionRuntimeKey],
|
|
31
|
+
requires: [capekRuntimeHostKey],
|
|
32
|
+
setup(context: PluginContext) {
|
|
33
|
+
const host = context.require(capekRuntimeHostKey);
|
|
34
|
+
const createOptions: AskPermissionServiceCreateOptions = {
|
|
35
|
+
id,
|
|
36
|
+
options: {
|
|
37
|
+
askTimeoutMs: 5 * 60 * 1000,
|
|
38
|
+
permissionTimeoutMs: host.interaction.getPermissionTimeoutMs(),
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
const policy = createAskPermissionService(createOptions);
|
|
42
|
+
context.provide(capekPermissionPolicyKey, policy);
|
|
43
|
+
context.provide(
|
|
44
|
+
capekPermissionRuntimeKey,
|
|
45
|
+
createPermissionRuntimeService({ id: `${id}.runtime`, provider: policy }),
|
|
46
|
+
);
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { CapekPlugin, PluginContext } from '../kernel/types';
|
|
2
|
+
import {
|
|
3
|
+
createRetryPolicy,
|
|
4
|
+
type RetryPolicy,
|
|
5
|
+
} from '../retry/policy';
|
|
6
|
+
import { capekRetryPolicyKey } from './service-keys';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* C6 provider for the agent-scoped retry policy contract
|
|
10
|
+
* (`capek.retry-policy`). Wraps the exact current behavior through
|
|
11
|
+
* `createRetryPolicy()`: classification, exponential jittered backoff with
|
|
12
|
+
* Retry-After as a minimum, circuit state owned by this policy instance, and
|
|
13
|
+
* the no-retry-after-tool-activity side-effect barrier. Every composed agent
|
|
14
|
+
* scope gets its own policy instance, so circuit state is isolated per
|
|
15
|
+
* agent; the facade's pre-C6 per-agent `withRetryCircuitState` wrap is
|
|
16
|
+
* replaced by this scope-owned provider.
|
|
17
|
+
*/
|
|
18
|
+
export function retryPolicyPlugin(id: string): CapekPlugin<unknown> {
|
|
19
|
+
return {
|
|
20
|
+
id,
|
|
21
|
+
scope: 'agent',
|
|
22
|
+
provides: [capekRetryPolicyKey],
|
|
23
|
+
setup(context: PluginContext) {
|
|
24
|
+
const policy: RetryPolicy = createRetryPolicy({ id });
|
|
25
|
+
context.provide(capekRetryPolicyKey, policy);
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|