feat: let agents read supervisor story graphs
Expose saved decisions, timelines and source evidence through read-only Story Graph tools across Model, Harness and local/remote OpenCode and Continue. Supervisor enablement and runtime assignments govern discovery and calls; reads do not invoke models or modify stored evidence. Remote use requires matching Desktop and Agent changes. Make Continue discussion show the complete editable message with a separated destination and shared action layout. Sending uses the visible draft without reattaching removed context. Validation: existing focused MCP, runtime, controlled Linux Host, discussion component and Electron layout checks plus typechecks; staged diff check passed. Cross-scope fact reuse, historical reconstruction and full package acceptance remain deferred. Release note: Agents can consult saved supervisor decisions and their sources when continuing work. Continue discussion now lets you review and edit the complete message before sending.
This commit is contained in:
@@ -165,6 +165,7 @@ describe('CapabilityService', () => {
|
||||
const stored = JSON.parse(await readFile(filePath, 'utf8'))
|
||||
delete stored.obsidian
|
||||
delete stored.builtinMcpServers.obsidian
|
||||
delete stored.builtinMcpServers['story-graph']
|
||||
stored.version = version
|
||||
if (version === 5) delete stored.builtinMcpServers['builtin-browser']
|
||||
if (version === 1) {
|
||||
@@ -322,6 +323,7 @@ describe('CapabilityService', () => {
|
||||
|
||||
await expect(service.getSnapshot()).resolves.toMatchObject({
|
||||
builtinMcpServers: [
|
||||
{ id: 'story-graph', enabled: true, assignments: ['model', 'opencode', 'continue', 'deepseek-harness'] },
|
||||
{
|
||||
id: 'knowledge-base',
|
||||
enabled: true,
|
||||
@@ -366,19 +368,23 @@ describe('CapabilityService', () => {
|
||||
|
||||
await expect(
|
||||
service.getEnabledBuiltinMcpServerIds('model')
|
||||
).resolves.toEqual(['knowledge-base', 'goodbuddy-config'])
|
||||
).resolves.toEqual(['story-graph', 'knowledge-base', 'goodbuddy-config'])
|
||||
await expect(
|
||||
service.getEnabledBuiltinMcpServerIds('opencode')
|
||||
).resolves.toEqual(['goodbuddy-config'])
|
||||
).resolves.toEqual(['story-graph', 'goodbuddy-config'])
|
||||
await expect(
|
||||
service.getEnabledBuiltinMcpServerIds('continue')
|
||||
).resolves.toEqual([
|
||||
'story-graph',
|
||||
'goodbuddy-config',
|
||||
'builtin-browser'
|
||||
])
|
||||
await expect(
|
||||
service.getEnabledBuiltinMcpServerIds('deepseek-harness')
|
||||
).resolves.toEqual([])
|
||||
).resolves.toEqual(['story-graph'])
|
||||
|
||||
await service.setBuiltinMcpServerAssignments('story-graph', ['deepseek-harness'])
|
||||
await expect(service.getEnabledBuiltinMcpServerIds('model')).resolves.not.toContain('story-graph')
|
||||
|
||||
const reloaded = new CapabilityService(
|
||||
filePath,
|
||||
@@ -388,6 +394,7 @@ describe('CapabilityService', () => {
|
||||
)
|
||||
await expect(reloaded.getSnapshot()).resolves.toMatchObject({
|
||||
builtinMcpServers: expect.arrayContaining([
|
||||
expect.objectContaining({ id: 'story-graph', assignments: ['deepseek-harness'] }),
|
||||
expect.objectContaining({
|
||||
id: 'knowledge-base',
|
||||
assignments: ['model']
|
||||
|
||||
@@ -134,6 +134,7 @@ const legacyBuiltinMcpServerStatesSchema = z
|
||||
|
||||
const builtinMcpServerStatesSchema =
|
||||
legacyBuiltinMcpServerStatesSchema.extend({
|
||||
'story-graph': builtinMcpServerStateSchema.extend({ assignments: capabilityAssignmentsSchema }).default({ enabled: true, assignments: ['model', 'opencode', 'continue', 'deepseek-harness'] }),
|
||||
'builtin-browser': builtinMcpServerStateSchema,
|
||||
obsidian: builtinMcpServerStateSchema.default({
|
||||
enabled: false,
|
||||
@@ -317,6 +318,7 @@ function defaultBuiltinMcpServerStates(
|
||||
})
|
||||
return {
|
||||
'knowledge-base': defaultState(),
|
||||
'story-graph': { enabled: true, assignments: ['model', 'opencode', 'continue', 'deepseek-harness'] },
|
||||
'magic-notes': defaultState(),
|
||||
'goodbuddy-config': defaultState(),
|
||||
obsidian: { ...defaultState(), enabled: false },
|
||||
@@ -880,6 +882,7 @@ export class CapabilityService {
|
||||
version: 6,
|
||||
obsidian: { vaultPath: '' },
|
||||
builtinMcpServers: {
|
||||
'story-graph': defaultBuiltinMcpServerStates()['story-graph'],
|
||||
obsidian: defaultBuiltinMcpServerStates().obsidian,
|
||||
...legacy.builtinMcpServers,
|
||||
'builtin-browser': {
|
||||
@@ -1750,7 +1753,7 @@ export class CapabilityService {
|
||||
assignments: CapabilityAssignments
|
||||
): Promise<CapabilitySnapshot> {
|
||||
return this.updateBuiltinMcpServerState(serverId, {
|
||||
assignments: builtinMcpAssignmentsSchema.parse(assignments)
|
||||
assignments: (serverId === 'story-graph' ? capabilityAssignmentsSchema : builtinMcpAssignmentsSchema).parse(assignments)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2053,11 +2056,9 @@ export class CapabilityService {
|
||||
target: RuntimeTarget
|
||||
): Promise<BuiltinMcpServerId[]> {
|
||||
const runtime = runtimeTargetSchema.parse(target)
|
||||
if (runtime === 'deepseek-harness') {
|
||||
return []
|
||||
}
|
||||
const state = await this.load()
|
||||
return builtinMcpServerIdSchema.options.filter((id) => {
|
||||
if (runtime === 'deepseek-harness' && id !== 'story-graph') return false
|
||||
const server = state.builtinMcpServers[id]
|
||||
if (!server.enabled || !server.assignments.includes(runtime)) {
|
||||
return false
|
||||
|
||||
Reference in New Issue
Block a user