Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
7 changes: 7 additions & 0 deletions scripts/t3layer-mcp-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ export const T3LAYER_APP_REQUIRED_TOOL_NAMES = [
"stop",
"respondToApproval",
"respondToUserInput",
"archive",
"unarchive",
"settle",
"unsettle",
"snooze",
"unsnooze",
"updateMeta",
] as const satisfies readonly StockT3McpToolName[];

const LOCAL_TOOL_NAMES = new Set<string>(T3LAYER_LOCAL_TOOL_NAMES);
Expand Down
24 changes: 24 additions & 0 deletions src/facade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type {
SpawnResult,
StockSpawnInput,
T3NativeRuntime,
ThreadMetaFields,
TurnReceipt,
UserInputResponse,
} from "./nativeRuntime";
Expand Down Expand Up @@ -46,6 +47,7 @@ export type {
RetryState,
RuntimeModelSelection,
RuntimeOperationOptions,
ThreadMetaFields,
SanitizedRetryError,
SpawnResult,
StockRuntimeErrorCode,
Expand Down Expand Up @@ -236,6 +238,11 @@ export function createStockT3Facade(
}
try {
const result = await action();
if (result.kind === "pending") {
endLifecycleMutation(mutationKey);
if (wasTerminal) recordWorkerTerminalState(overlay, ref, true);
return result;
Comment thread
macroscopeapp[bot] marked this conversation as resolved.
Resolved
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
}
lifecycleSequenceByRef.set(mutationKey, result.snapshot.snapshotSequence);
const terminal = isTerminalSnapshot(result.snapshot);
recordWorkerTerminalState(overlay, ref, terminal);
Expand Down Expand Up @@ -405,6 +412,23 @@ export function createStockT3Facade(
ref,
() => runtime.respondToUserInput(ref, response, options),
),
archive: async (ref: AgentRef, options?: RuntimeOperationOptions) =>
runControlLifecycleMutation(ref, () => runtime.archive(ref, options)),
unarchive: async (ref: AgentRef, options?: RuntimeOperationOptions) =>
runControlLifecycleMutation(ref, () => runtime.unarchive(ref, options)),
settle: async (ref: AgentRef, options?: RuntimeOperationOptions) =>
runControlLifecycleMutation(ref, () => runtime.settle(ref, options)),
unsettle: async (ref: AgentRef, options?: RuntimeOperationOptions) =>
runControlLifecycleMutation(ref, () => runtime.unsettle(ref, options)),
snooze: async (ref: AgentRef, until: string, options?: RuntimeOperationOptions) =>
runControlLifecycleMutation(ref, () => runtime.snooze(ref, until, options)),
unsnooze: async (ref: AgentRef, options?: RuntimeOperationOptions) =>
runControlLifecycleMutation(ref, () => runtime.unsnooze(ref, options)),
updateMeta: async (
ref: AgentRef,
fields: ThreadMetaFields,
options?: RuntimeOperationOptions,
) => runControlLifecycleMutation(ref, () => runtime.updateMeta(ref, fields, options)),
async observe(ref: AgentRef, options?: RuntimeOperationOptions) {
const snapshot = await runtime.observe(ref, options);
if (snapshot !== undefined) {
Expand Down
70 changes: 70 additions & 0 deletions src/mcp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {
ApprovalResponse,
RuntimeOperationOptions,
StockSpawnInput,
ThreadMetaFields,
TurnReceipt,
UserInputResponse,
} from "./nativeRuntime";
Expand All @@ -22,6 +23,13 @@ export const MCP_TOOL_NAMES = [
"stop",
"respondToApproval",
"respondToUserInput",
"archive",
"unarchive",
"settle",
"unsettle",
"snooze",
"unsnooze",
"updateMeta",
] as const;

export type StockT3McpToolName = (typeof MCP_TOOL_NAMES)[number];
Expand Down Expand Up @@ -174,6 +182,16 @@ const receiptSchema = Object.freeze({
]),
additionalProperties: false,
});
const threadMetaFieldsSchema = Object.freeze({
type: "object",
properties: Object.freeze({
title: stringSchema,
modelSelection: modelSelectionSchema,
branch: nullableStringSchema,
worktreePath: nullableStringSchema,
}),
additionalProperties: false,
});

function tool(
name: StockT3McpToolName,
Expand Down Expand Up @@ -256,6 +274,36 @@ const TOOLS = Object.freeze([
}),
operation: operationSchema,
}, ["ref", "response"]),
tool("archive", "Archive a stock thread and confirm the disposition through snapshots.", {
ref: agentRefSchema,
operation: operationSchema,
}, ["ref"]),
tool("unarchive", "Restore an archived stock thread and confirm through snapshots.", {
ref: agentRefSchema,
operation: operationSchema,
}, ["ref"]),
tool("settle", "Settle a stock thread and confirm the disposition through snapshots.", {
ref: agentRefSchema,
operation: operationSchema,
}, ["ref"]),
tool("unsettle", "Reopen a settled stock thread as an explicit user action.", {
ref: agentRefSchema,
operation: operationSchema,
}, ["ref"]),
tool("snooze", "Snooze a stock thread until an ISO timestamp and confirm through snapshots.", {
ref: agentRefSchema,
until: stringSchema,
operation: operationSchema,
}, ["ref", "until"]),
tool("unsnooze", "Wake a snoozed stock thread as an explicit user action.", {
ref: agentRefSchema,
operation: operationSchema,
}, ["ref"]),
tool("updateMeta", "Update canonical stock thread metadata and confirm through snapshots.", {
ref: agentRefSchema,
fields: threadMetaFieldsSchema,
operation: operationSchema,
}, ["ref", "fields"]),
]);

function resultContent(payload: unknown) {
Expand Down Expand Up @@ -480,6 +528,28 @@ export function createStockT3McpFacade(facade: StockT3Facade) {
args.response as unknown as UserInputResponse,
operation,
));
case "archive":
return success(await facade.archive(args.ref as AgentRef, operation));
case "unarchive":
return success(await facade.unarchive(args.ref as AgentRef, operation));
case "settle":
return success(await facade.settle(args.ref as AgentRef, operation));
case "unsettle":
return success(await facade.unsettle(args.ref as AgentRef, operation));
case "snooze":
return success(await facade.snooze(
args.ref as AgentRef,
args.until as string,
operation,
));
case "unsnooze":
return success(await facade.unsnooze(args.ref as AgentRef, operation));
case "updateMeta":
return success(await facade.updateMeta(
args.ref as AgentRef,
args.fields as ThreadMetaFields,
operation,
));
default:
return protocolMismatch("tool.name");
}
Expand Down
Loading