Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/framework.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2023,7 +2023,7 @@
const namespace = `subagent/${config.name}`;

const contextManager = await ContextManager.open({
store: this.store,

Check failure on line 2026 in src/framework.ts

View workflow job for this annotation

GitHub Actions / Build & Test (macos-latest)

Type 'JsStore' is missing the following properties from type 'JsStore': getStateUpdateJson, updateStateStrategy

Check failure on line 2026 in src/framework.ts

View workflow job for this annotation

GitHub Actions / Build & Test (ubuntu-latest)

Type 'JsStore' is missing the following properties from type 'JsStore': getStateUpdateJson, updateStateStrategy
namespace,
isolate: true,
strategy: config.strategy ?? new PassthroughStrategy(),
Expand Down Expand Up @@ -3587,7 +3587,7 @@
private async createAgent(config: AgentConfig): Promise<Agent> {
// Create context manager for this agent
const contextManager = await ContextManager.open({
store: this.store,

Check failure on line 3590 in src/framework.ts

View workflow job for this annotation

GitHub Actions / Build & Test (macos-latest)

Type 'JsStore' is missing the following properties from type 'JsStore': getStateUpdateJson, updateStateStrategy

Check failure on line 3590 in src/framework.ts

View workflow job for this annotation

GitHub Actions / Build & Test (ubuntu-latest)

Type 'JsStore' is missing the following properties from type 'JsStore': getStateUpdateJson, updateStateStrategy
namespace: `agents/${config.name}`,
strategy: config.strategy ?? new PassthroughStrategy(),
membrane: this.membrane,
Expand Down Expand Up @@ -4296,7 +4296,7 @@
}

const contextManager = await ContextManager.open({
store: this.store,

Check failure on line 4299 in src/framework.ts

View workflow job for this annotation

GitHub Actions / Build & Test (macos-latest)

Type 'JsStore' is missing the following properties from type 'JsStore': getStateUpdateJson, updateStateStrategy

Check failure on line 4299 in src/framework.ts

View workflow job for this annotation

GitHub Actions / Build & Test (ubuntu-latest)

Type 'JsStore' is missing the following properties from type 'JsStore': getStateUpdateJson, updateStateStrategy
namespace: `conversations/${name}`,
isolate: true,
// Strategy instances are stateful — never share the template's.
Expand Down Expand Up @@ -5552,7 +5552,7 @@
}
break;

case 'retrying': {

Check failure on line 5555 in src/framework.ts

View workflow job for this annotation

GitHub Actions / Build & Test (macos-latest)

Type '"retrying"' is not comparable to type '"aborted" | "error" | "usage" | "tokens" | "block" | "tool-calls" | "complete"'.

Check failure on line 5555 in src/framework.ts

View workflow job for this annotation

GitHub Actions / Build & Test (ubuntu-latest)

Type '"retrying"' is not comparable to type '"aborted" | "error" | "usage" | "tokens" | "block" | "tool-calls" | "complete"'.
// Membrane is re-issuing after a content-policy refusal. Per the
// RetryingEvent contract we must DISCARD everything this call has
// emitted: the tokens above were already streamed to the surface
Expand All @@ -5566,8 +5566,8 @@
// destination bookkeeping starts clean for the new attempt.
console.error(
`[refusal-retry] agent=${agent.name} membrane retry ` +
`${event.attempt}/${event.maxAttempts}` +

Check failure on line 5569 in src/framework.ts

View workflow job for this annotation

GitHub Actions / Build & Test (macos-latest)

Property 'maxAttempts' does not exist on type 'never'.

Check failure on line 5569 in src/framework.ts

View workflow job for this annotation

GitHub Actions / Build & Test (macos-latest)

Property 'attempt' does not exist on type 'never'.

Check failure on line 5569 in src/framework.ts

View workflow job for this annotation

GitHub Actions / Build & Test (ubuntu-latest)

Property 'maxAttempts' does not exist on type 'never'.

Check failure on line 5569 in src/framework.ts

View workflow job for this annotation

GitHub Actions / Build & Test (ubuntu-latest)

Property 'attempt' does not exist on type 'never'.
(event.category ? ` category=${event.category}` : '') +

Check failure on line 5570 in src/framework.ts

View workflow job for this annotation

GitHub Actions / Build & Test (macos-latest)

Property 'category' does not exist on type 'never'.

Check failure on line 5570 in src/framework.ts

View workflow job for this annotation

GitHub Actions / Build & Test (macos-latest)

Property 'category' does not exist on type 'never'.

Check failure on line 5570 in src/framework.ts

View workflow job for this annotation

GitHub Actions / Build & Test (ubuntu-latest)

Property 'category' does not exist on type 'never'.

Check failure on line 5570 in src/framework.ts

View workflow job for this annotation

GitHub Actions / Build & Test (ubuntu-latest)

Property 'category' does not exist on type 'never'.
' — discarding the refused attempt',
);
outgoingInferenceId = newOutgoingInferenceId();
Expand Down Expand Up @@ -8926,6 +8926,16 @@
deniedCapabilities: string[];
/** Host-owned authority; deliberately separate from the portable grant. */
allowHostCommands: boolean;
/**
* Per-transport §17 facts about the last manifest this host fetched and
* acted on. The revision is server-authored and equality-only; these are
* not the server's manifestChanged announcements.
*/
manifestState: {
lastValidatedRevision: string | null;
lastFetchedAt: number | null;
lastNegotiatedAt: number | null;
};
command?: string;
url?: string;
}> {
Expand All @@ -8934,6 +8944,11 @@
toolPrefix: string; toolCount: number; policyEstablished: boolean;
effectiveGrant: string[]; maskedCapabilities: string[];
deniedCapabilities: string[]; allowHostCommands: boolean;
manifestState: {
lastValidatedRevision: string | null;
lastFetchedAt: number | null;
lastNegotiatedAt: number | null;
};
command?: string; url?: string;
}> = [];
for (const [id, config] of this.mcplServerConfigs) {
Expand All @@ -8951,6 +8966,9 @@
maskedCapabilities: [...(connection?.droppedCapabilities ?? [])].sort(),
deniedCapabilities: [...(connection?.grant.deniedPaths ?? [])].sort(),
allowHostCommands: config.allowHostCommands === true,
manifestState: connection
? { ...connection.manifestState }
: { lastValidatedRevision: null, lastFetchedAt: null, lastNegotiatedAt: null },
command: config.command,
url: config.url,
});
Expand Down
29 changes: 26 additions & 3 deletions test/mcpl-list-status.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,22 @@ test('listMcplServers exposes the live grant layers and host-owned authority', (
new Set(['channels.incoming', 'channels.publish']),
['contextHooks.beforeInference.inject.system'],
);
const framework = frameworkWithConnection({
const connection = {
isConnected: true,
willReconnect: true,
policyEstablished: true,
grant,
droppedCapabilities: new Set(['channels.streaming']),
});
manifestState: {
lastValidatedRevision: 'sha256:validated',
lastFetchedAt: 1_786_000_000_000,
lastNegotiatedAt: 1_786_000_000_100,
},
};
const framework = frameworkWithConnection(connection);

assert.deepEqual(framework.listMcplServers(), [{
const listed = framework.listMcplServers();
assert.deepEqual(listed, [{
id: 'discord',
connected: true,
retrying: false,
Expand All @@ -41,9 +48,15 @@ test('listMcplServers exposes the live grant layers and host-owned authority', (
maskedCapabilities: ['channels.streaming'],
deniedCapabilities: ['contextHooks.beforeInference.inject.system'],
allowHostCommands: true,
manifestState: {
lastValidatedRevision: 'sha256:validated',
lastFetchedAt: 1_786_000_000_000,
lastNegotiatedAt: 1_786_000_000_100,
},
command: 'node',
url: undefined,
}]);
assert.notStrictEqual(listed[0]!.manifestState, connection.manifestState);
});

test('listMcplServers distinguishes a disconnected retrying stub from connected', () => {
Expand All @@ -53,11 +66,21 @@ test('listMcplServers distinguishes a disconnected retrying stub from connected'
policyEstablished: false,
grant: CapabilityGrant.empty(),
droppedCapabilities: new Set<string>(),
manifestState: {
lastValidatedRevision: null,
lastFetchedAt: null,
lastNegotiatedAt: null,
},
});

const [status] = framework.listMcplServers();
assert.equal(status.connected, false);
assert.equal(status.retrying, true);
assert.equal(status.policyEstablished, false);
assert.deepEqual(status.effectiveGrant, []);
assert.deepEqual(status.manifestState, {
lastValidatedRevision: null,
lastFetchedAt: null,
lastNegotiatedAt: null,
});
});
Loading