feat(FN-3155): add createAiSession plugin context API with DI wiring

This merge brings FN-3155's plugin `createAiSession` API (types, DI hooks, engine adapter, context wiring, docs, and tests), FN-3056's task title sanitization, and FN-3129's tokenized footer and mobile initialization for MissionManager. It also adds CentralCore Docker node management, a new AddNodeM

Fusion-Task-Id: FN-3155
This commit is contained in:
Fusion
2026-05-02 13:20:12 -07:00
committed by gsxdsm
parent 2769e4a57b
commit 5ebccc43cc
17 changed files with 540 additions and 122 deletions

View File

@@ -717,6 +717,7 @@ interface PluginContext {
settings: Record<string, unknown>;
logger: PluginLogger;
emitEvent: (event: string, data: unknown) => void;
createAiSession?: CreateAiSessionFactory;
}
```
@@ -729,6 +730,7 @@ interface PluginContext {
| `settings` | `Record<string, unknown>` | User configuration (merged with defaults) |
| `logger` | `PluginLogger` | Structured logging |
| `emitEvent` | `(event, data) => void` | Emit custom events |
| `createAiSession` | `CreateAiSessionFactory \| undefined` | Engine-injected AI session factory (undefined when engine isn't loaded) |
### Logger Methods
@@ -741,6 +743,55 @@ interface PluginLogger {
}
```
### `createAiSession` API
```typescript
interface CreateAiSessionOptions {
cwd: string;
systemPrompt: string;
tools?: "coding" | "readonly";
defaultProvider?: string;
defaultModelId?: string;
}
interface AiSessionResult {
session: {
prompt(text: string): Promise<void>;
state: { messages: Array<{ role: string; content?: unknown }> };
};
sessionFile?: string;
}
type CreateAiSessionFactory = (
options: CreateAiSessionOptions,
) => Promise<AiSessionResult>;
```
The factory is dependency-injected by the engine at runtime. In test-only or core-only environments where the engine module is not loaded, `ctx.createAiSession` is `undefined`, so guard before calling it.
### Example: Using `ctx.createAiSession()`
```typescript
hooks: {
onLoad: async (ctx) => {
if (!ctx.createAiSession) {
ctx.logger.warn("AI session factory unavailable; engine not loaded");
return;
}
const { session } = await ctx.createAiSession({
cwd: process.cwd(),
systemPrompt: "You are a release assistant for this plugin.",
tools: "readonly",
});
await session.prompt("Summarize what this plugin contributes.");
const latest = session.state.messages.at(-1);
ctx.logger.info("AI summary generated", latest);
},
},
```
### Example: Using the Context
```typescript