mirror of
https://github.com/wu736139669/hapi.git
synced 2026-11-09 01:51:39 +00:00
feat(codex): share sessions across terminal and web
Use one native app-server for terminal, Web and phone clients while retaining the existing CLI and Runner lifecycle. Synchronize native queues, permissions, question history and steering state; preserve explicit permission precedence and per-turn usage models. Resume inactive clear commands through Runner and reject independent child cold resumes. Add shared-runtime regression tests, generated protocol fixtures and lifecycle documentation.
This commit is contained in:
@@ -22,6 +22,7 @@ type ElicitationSchemaProperty = {
|
||||
};
|
||||
|
||||
type UserInputAnswer = Record<string, string[]> | Record<string, { answers: string[] }>;
|
||||
export const IGNORE_SHARED_REQUEST = Symbol('ignore-shared-request');
|
||||
|
||||
function asRecord(value: unknown): Record<string, unknown> | null {
|
||||
if (!value || typeof value !== 'object') {
|
||||
@@ -376,8 +377,9 @@ function isHapiBridgeElicitation(params: unknown): boolean {
|
||||
}
|
||||
|
||||
export function registerAppServerPermissionHandlers(args: {
|
||||
client: CodexAppServerClient;
|
||||
permissionHandler: CodexPermissionHandler;
|
||||
client: Pick<CodexAppServerClient, 'registerRequestHandler'>;
|
||||
permissionHandler: Pick<CodexPermissionHandler, 'handleToolCall'>;
|
||||
shared?: boolean;
|
||||
getPermissionMode?: () => CodexPermissionMode | undefined;
|
||||
onUserInputRequest?: (request: { id: string; input: unknown }) => Promise<
|
||||
| { decision: 'accept'; answers: UserInputAnswer }
|
||||
@@ -504,6 +506,7 @@ export function registerAppServerPermissionHandlers(args: {
|
||||
|
||||
const input = buildElicitationUserInput(params);
|
||||
if (!onUserInputRequest || !input) {
|
||||
if (args.shared) return IGNORE_SHARED_REQUEST;
|
||||
logger.debug('[CodexAppServer] Cancelling unsupported MCP elicitation request', {
|
||||
serverName: record.serverName,
|
||||
mode: request.mode,
|
||||
|
||||
@@ -45,6 +45,7 @@ export interface HapiMcpBridge {
|
||||
}
|
||||
|
||||
export interface HapiMcpBridgeOptions {
|
||||
exportSessionEnv?: boolean;
|
||||
emitTitleSummary?: boolean;
|
||||
enableChangeTitle?: boolean;
|
||||
skillLookup?: {
|
||||
@@ -76,7 +77,7 @@ export async function buildHapiMcpBridge(
|
||||
}
|
||||
}
|
||||
// Belt-and-suspenders: onMaterialized already exports; keep env set for non-lazy too.
|
||||
exportHapiSessionEnv(client.sessionId);
|
||||
if (options.exportSessionEnv !== false) exportHapiSessionEnv(client.sessionId);
|
||||
|
||||
const happyServer = await startHappyServer(client, {
|
||||
emitTitleSummary: options.emitTitleSummary,
|
||||
|
||||
Reference in New Issue
Block a user