@imricci/zaker 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/dist/commands/app-server.d.ts +67 -0
  2. package/dist/commands/app-server.js +601 -0
  3. package/dist/commands/app-server.js.map +1 -0
  4. package/dist/commands/audit.js +2 -1
  5. package/dist/commands/audit.js.map +1 -1
  6. package/dist/commands/build.d.ts +3 -0
  7. package/dist/commands/build.js +22 -0
  8. package/dist/commands/build.js.map +1 -0
  9. package/dist/commands/confirm.d.ts +0 -2
  10. package/dist/commands/confirm.js +2 -16
  11. package/dist/commands/confirm.js.map +1 -1
  12. package/dist/commands/dialog-handlers/auth.d.ts +3 -0
  13. package/dist/commands/dialog-handlers/auth.js +174 -0
  14. package/dist/commands/dialog-handlers/auth.js.map +1 -0
  15. package/dist/commands/dialog-handlers/basic.d.ts +2 -2
  16. package/dist/commands/dialog-handlers/basic.js +8 -9
  17. package/dist/commands/dialog-handlers/basic.js.map +1 -1
  18. package/dist/commands/dialog-handlers/bootstrap.js +2 -2
  19. package/dist/commands/dialog-handlers/bootstrap.js.map +1 -1
  20. package/dist/commands/dialog-handlers/index.d.ts +1 -1
  21. package/dist/commands/dialog-handlers/message.js +94 -3
  22. package/dist/commands/dialog-handlers/message.js.map +1 -1
  23. package/dist/commands/dialog-handlers/model.d.ts +2 -0
  24. package/dist/commands/dialog-handlers/model.js +168 -0
  25. package/dist/commands/dialog-handlers/model.js.map +1 -0
  26. package/dist/commands/dialog-handlers/new.d.ts +2 -0
  27. package/dist/commands/dialog-handlers/new.js +53 -0
  28. package/dist/commands/dialog-handlers/new.js.map +1 -0
  29. package/dist/commands/dialog-handlers/router.js +39 -3
  30. package/dist/commands/dialog-handlers/router.js.map +1 -1
  31. package/dist/commands/dialog-handlers/run.js +44 -8
  32. package/dist/commands/dialog-handlers/run.js.map +1 -1
  33. package/dist/commands/dialog-handlers/types.d.ts +16 -17
  34. package/dist/commands/dialog.d.ts +92 -0
  35. package/dist/commands/dialog.js +1542 -422
  36. package/dist/commands/dialog.js.map +1 -1
  37. package/dist/commands/init.d.ts +3 -1
  38. package/dist/commands/init.js +6 -4
  39. package/dist/commands/init.js.map +1 -1
  40. package/dist/commands/plan.js +10 -6
  41. package/dist/commands/plan.js.map +1 -1
  42. package/dist/commands/run.js +8 -10
  43. package/dist/commands/run.js.map +1 -1
  44. package/dist/commands/status.js +6 -12
  45. package/dist/commands/status.js.map +1 -1
  46. package/dist/commands/tui-launcher.d.ts +1 -0
  47. package/dist/commands/tui-launcher.js +8 -0
  48. package/dist/commands/tui-launcher.js.map +1 -0
  49. package/dist/core/alignment-reply.d.ts +1 -0
  50. package/dist/core/alignment-reply.js +44 -0
  51. package/dist/core/alignment-reply.js.map +1 -0
  52. package/dist/core/checkpoint.js +3 -1
  53. package/dist/core/checkpoint.js.map +1 -1
  54. package/dist/core/planner.d.ts +16 -16
  55. package/dist/core/planner.js +3 -1
  56. package/dist/core/planner.js.map +1 -1
  57. package/dist/core/planning-prep.d.ts +12 -0
  58. package/dist/core/planning-prep.js +26 -0
  59. package/dist/core/planning-prep.js.map +1 -0
  60. package/dist/core/preflight.js +1 -2
  61. package/dist/core/preflight.js.map +1 -1
  62. package/dist/core/provider-onboarding.js +6 -11
  63. package/dist/core/provider-onboarding.js.map +1 -1
  64. package/dist/core/readonly-checkpoint.d.ts +2 -0
  65. package/dist/core/readonly-checkpoint.js +35 -0
  66. package/dist/core/readonly-checkpoint.js.map +1 -0
  67. package/dist/core/run-loop.js +3 -1
  68. package/dist/core/run-loop.js.map +1 -1
  69. package/dist/core/types.d.ts +20 -1
  70. package/dist/index.js +6 -5
  71. package/dist/index.js.map +1 -1
  72. package/dist/infra/artifact-schema.d.ts +25 -0
  73. package/dist/infra/artifact-schema.js +353 -0
  74. package/dist/infra/artifact-schema.js.map +1 -0
  75. package/dist/infra/config.d.ts +14 -1
  76. package/dist/infra/config.js +542 -22
  77. package/dist/infra/config.js.map +1 -1
  78. package/dist/infra/dependency-report.d.ts +5 -0
  79. package/dist/infra/dependency-report.js +22 -0
  80. package/dist/infra/dependency-report.js.map +1 -0
  81. package/dist/infra/dialog-session.d.ts +29 -0
  82. package/dist/infra/dialog-session.js +244 -0
  83. package/dist/infra/dialog-session.js.map +1 -0
  84. package/dist/infra/intent.d.ts +0 -1
  85. package/dist/infra/intent.js +62 -25
  86. package/dist/infra/intent.js.map +1 -1
  87. package/dist/infra/model-accounts.d.ts +22 -0
  88. package/dist/infra/model-accounts.js +172 -0
  89. package/dist/infra/model-accounts.js.map +1 -0
  90. package/dist/infra/model-catalog.d.ts +4 -1
  91. package/dist/infra/model-catalog.js +102 -27
  92. package/dist/infra/model-catalog.js.map +1 -1
  93. package/dist/infra/openai-codex-oauth.d.ts +18 -0
  94. package/dist/infra/openai-codex-oauth.js +267 -0
  95. package/dist/infra/openai-codex-oauth.js.map +1 -0
  96. package/dist/infra/provider-registry.d.ts +36 -0
  97. package/dist/infra/provider-registry.js +403 -0
  98. package/dist/infra/provider-registry.js.map +1 -0
  99. package/dist/infra/session-status.d.ts +6 -0
  100. package/dist/infra/session-status.js +34 -0
  101. package/dist/infra/session-status.js.map +1 -0
  102. package/dist/infra/tui-utils.d.ts +6 -0
  103. package/dist/infra/tui-utils.js +163 -0
  104. package/dist/infra/tui-utils.js.map +1 -0
  105. package/dist/infra/tui-view.d.ts +44 -0
  106. package/dist/infra/tui-view.js +314 -0
  107. package/dist/infra/tui-view.js.map +1 -0
  108. package/package.json +4 -1
@@ -0,0 +1,67 @@
1
+ import { Command } from "commander";
2
+ import { ConversationRuntime } from "../infra/dialog-session";
3
+ import { ModelProviderId } from "../infra/provider-registry";
4
+ import { loginOpenAICodexOAuth } from "../infra/openai-codex-oauth";
5
+ import { TaskBoardState } from "./dialog-handlers";
6
+ export declare const APP_SERVER_PROTOCOL_VERSION = "zaker.app/1";
7
+ export declare const APP_SERVER_METHODS: readonly ["initialize", "ping", "session.get", "command.execute", "menu.context", "oauth.start", "oauth.cancel", "shutdown"];
8
+ export declare const APP_SERVER_EVENTS: readonly ["session.update", "run.stage", "audit.result", "oauth.status"];
9
+ type JsonRpcId = string | number | null;
10
+ type AppServerEventName = (typeof APP_SERVER_EVENTS)[number];
11
+ interface JsonRpcRequest {
12
+ jsonrpc?: string;
13
+ id?: JsonRpcId;
14
+ method?: string;
15
+ params?: unknown;
16
+ }
17
+ interface JsonRpcResult {
18
+ jsonrpc: "2.0";
19
+ id: JsonRpcId;
20
+ result: unknown;
21
+ }
22
+ interface JsonRpcErrorResult {
23
+ jsonrpc: "2.0";
24
+ id: JsonRpcId;
25
+ error: {
26
+ code: number;
27
+ message: string;
28
+ data?: unknown;
29
+ };
30
+ }
31
+ export interface AppServerEvent {
32
+ event: AppServerEventName;
33
+ timestamp: string;
34
+ payload: Record<string, unknown>;
35
+ }
36
+ type OAuthLoginAdapter = typeof loginOpenAICodexOAuth;
37
+ interface PendingOAuthRequest {
38
+ request_id: string;
39
+ provider: ModelProviderId;
40
+ started_at: string;
41
+ controller: AbortController;
42
+ }
43
+ export interface AppServerState {
44
+ cwd: string;
45
+ defaultSopOut: string;
46
+ defaultCheckpointOut: string;
47
+ protocolInitialized: boolean;
48
+ terminated: boolean;
49
+ board: TaskBoardState;
50
+ conversations: ConversationRuntime;
51
+ oauthRequestSeq: number;
52
+ pendingOAuthRequests: Map<string, PendingOAuthRequest>;
53
+ oauthLogin: OAuthLoginAdapter;
54
+ }
55
+ export declare function createAppServerState(cwd?: string, options?: {
56
+ sopOut?: string;
57
+ checkpointOut?: string;
58
+ oauthLogin?: OAuthLoginAdapter;
59
+ }): Promise<AppServerState>;
60
+ export declare function handleAppServerRequest(state: AppServerState, request: JsonRpcRequest, emitEvent: (event: AppServerEvent) => Promise<void>): Promise<JsonRpcResult | JsonRpcErrorResult | undefined>;
61
+ export declare function runAppServer(cwd?: string, options?: {
62
+ sopOut?: string;
63
+ checkpointOut?: string;
64
+ oauthLogin?: OAuthLoginAdapter;
65
+ }): Promise<void>;
66
+ export declare function registerAppServerCommand(program: Command): void;
67
+ export {};
@@ -0,0 +1,601 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.APP_SERVER_EVENTS = exports.APP_SERVER_METHODS = exports.APP_SERVER_PROTOCOL_VERSION = void 0;
7
+ exports.createAppServerState = createAppServerState;
8
+ exports.handleAppServerRequest = handleAppServerRequest;
9
+ exports.runAppServer = runAppServer;
10
+ exports.registerAppServerCommand = registerAppServerCommand;
11
+ const node_fs_1 = require("node:fs");
12
+ const node_path_1 = require("node:path");
13
+ const node_readline_1 = __importDefault(require("node:readline"));
14
+ const dialog_session_1 = require("../infra/dialog-session");
15
+ const intent_1 = require("../infra/intent");
16
+ const model_accounts_1 = require("../infra/model-accounts");
17
+ const provider_registry_1 = require("../infra/provider-registry");
18
+ const session_status_1 = require("../infra/session-status");
19
+ const openai_codex_oauth_1 = require("../infra/openai-codex-oauth");
20
+ const config_1 = require("../infra/config");
21
+ const dialog_1 = require("./dialog");
22
+ exports.APP_SERVER_PROTOCOL_VERSION = "zaker.app/1";
23
+ exports.APP_SERVER_METHODS = [
24
+ "initialize",
25
+ "ping",
26
+ "session.get",
27
+ "command.execute",
28
+ "menu.context",
29
+ "oauth.start",
30
+ "oauth.cancel",
31
+ "shutdown"
32
+ ];
33
+ exports.APP_SERVER_EVENTS = [
34
+ "session.update",
35
+ "run.stage",
36
+ "audit.result",
37
+ "oauth.status"
38
+ ];
39
+ function now() {
40
+ return new Date().toISOString();
41
+ }
42
+ function resolveServerVersion() {
43
+ try {
44
+ const packagePath = (0, node_path_1.resolve)(__dirname, "..", "..", "package.json");
45
+ const raw = (0, node_fs_1.readFileSync)(packagePath, "utf8");
46
+ const parsed = JSON.parse(raw);
47
+ return typeof parsed.version === "string" && parsed.version.trim()
48
+ ? parsed.version.trim()
49
+ : "0.0.0";
50
+ }
51
+ catch {
52
+ return "0.0.0";
53
+ }
54
+ }
55
+ function isRecord(value) {
56
+ return typeof value === "object" && value !== null && !Array.isArray(value);
57
+ }
58
+ function cloneBoard(board) {
59
+ return { ...board };
60
+ }
61
+ async function buildSessionSnapshot(state) {
62
+ const session = await (0, intent_1.readSessionStore)(state.cwd);
63
+ const draft = await (0, intent_1.readIntentCard)(state.cwd);
64
+ const confirmed = await (0, intent_1.readConfirmedIntent)(state.cwd);
65
+ const statusLines = session
66
+ ? (0, session_status_1.formatSessionStatusLines)(session, draft, confirmed, {
67
+ includeDialog: true,
68
+ recentRoundLimit: 5
69
+ })
70
+ : ["session_state: UNINITIALIZED"];
71
+ const history = session?.dialog?.history
72
+ ? session.dialog.history.slice(-80).map((entry) => ({
73
+ turn: entry.turn,
74
+ timestamp: entry.timestamp,
75
+ role: entry.role,
76
+ kind: entry.kind,
77
+ content: entry.content
78
+ }))
79
+ : [];
80
+ return {
81
+ session_state: session?.state ?? "UNINITIALIZED",
82
+ active_conversation_id: state.conversations.index.active_id || null,
83
+ draft_intent_id: draft?.intent_id ?? null,
84
+ confirmed_intent_id: confirmed?.intent_id ?? null,
85
+ current_intent_id: session?.current_intent_id ?? null,
86
+ board: cloneBoard(state.board),
87
+ status_lines: statusLines,
88
+ history
89
+ };
90
+ }
91
+ async function buildMenuContext(state) {
92
+ const config = await (0, config_1.readConfig)(state.cwd);
93
+ const modelMenu = (0, model_accounts_1.buildModelMenuSnapshot)(config);
94
+ const sessionIds = await (0, dialog_session_1.listConversationIds)(state.conversations.index, state.cwd);
95
+ const providerIds = (0, provider_registry_1.getModelProviderIds)().filter((providerId) => providerId !== "mock");
96
+ return {
97
+ sessions: {
98
+ active_id: state.conversations.index.active_id || null,
99
+ ids: sessionIds
100
+ },
101
+ model_menu: modelMenu,
102
+ login: {
103
+ providers: providerIds.map((id) => ({
104
+ id,
105
+ supports_oauth: (0, provider_registry_1.providerSupportsOAuth)(id)
106
+ }))
107
+ },
108
+ logout: {
109
+ targets: [...providerIds, "ollama", "all"]
110
+ },
111
+ oauth: {
112
+ pending: [...state.pendingOAuthRequests.values()].map((request) => ({
113
+ request_id: request.request_id,
114
+ provider: request.provider,
115
+ started_at: request.started_at
116
+ }))
117
+ },
118
+ current_model: {
119
+ provider: config.model.provider,
120
+ planner_model: config.model.planner_model,
121
+ auditor_model: config.model.auditor_model,
122
+ execution_model: config.execution.model
123
+ }
124
+ };
125
+ }
126
+ function toError(id, code, message, data) {
127
+ return {
128
+ jsonrpc: "2.0",
129
+ id,
130
+ error: {
131
+ code,
132
+ message,
133
+ data
134
+ }
135
+ };
136
+ }
137
+ function toResult(id, result) {
138
+ return {
139
+ jsonrpc: "2.0",
140
+ id,
141
+ result
142
+ };
143
+ }
144
+ function parseExecuteParams(params, fallbackSopOut, fallbackCheckpointOut) {
145
+ if (!isRecord(params)) {
146
+ return null;
147
+ }
148
+ const input = typeof params.input === "string" ? params.input : "";
149
+ const sopOut = typeof params.sop_out === "string" && params.sop_out.trim()
150
+ ? params.sop_out.trim()
151
+ : fallbackSopOut;
152
+ const checkpointOut = typeof params.checkpoint_out === "string" && params.checkpoint_out.trim()
153
+ ? params.checkpoint_out.trim()
154
+ : fallbackCheckpointOut;
155
+ if (!input.trim()) {
156
+ return null;
157
+ }
158
+ return {
159
+ input,
160
+ sopOut,
161
+ checkpointOut
162
+ };
163
+ }
164
+ function parseOAuthStartParams(params) {
165
+ if (!isRecord(params)) {
166
+ return null;
167
+ }
168
+ const provider = typeof params.provider === "string" ? params.provider.trim() : "";
169
+ if (!provider) {
170
+ return null;
171
+ }
172
+ return { provider };
173
+ }
174
+ function parseOAuthCancelParams(params) {
175
+ if (!isRecord(params)) {
176
+ return {};
177
+ }
178
+ const requestId = typeof params.request_id === "string" ? params.request_id.trim() : "";
179
+ if (!requestId) {
180
+ return {};
181
+ }
182
+ return { requestId };
183
+ }
184
+ function parseOAuthCommandShortcut(input) {
185
+ const tokens = input.trim().split(/\s+/).filter(Boolean);
186
+ if (tokens.length === 3 && tokens[0] === "/login" && tokens[2].toLowerCase() === "oauth") {
187
+ return { provider: tokens[1] || "" };
188
+ }
189
+ return null;
190
+ }
191
+ async function emitSessionUpdate(state, emitEvent, snapshot) {
192
+ await emitEvent({
193
+ event: "session.update",
194
+ timestamp: now(),
195
+ payload: {
196
+ session_state: snapshot.session_state,
197
+ active_conversation_id: snapshot.active_conversation_id,
198
+ current_intent_id: snapshot.current_intent_id
199
+ }
200
+ });
201
+ }
202
+ async function emitOAuthStatus(emitEvent, payload) {
203
+ await emitEvent({
204
+ event: "oauth.status",
205
+ timestamp: now(),
206
+ payload
207
+ });
208
+ }
209
+ function nextOAuthRequestId(state) {
210
+ state.oauthRequestSeq += 1;
211
+ return `oauth_${Date.now()}_${state.oauthRequestSeq}`;
212
+ }
213
+ async function performOAuthStart(state, providerInput, emitEvent) {
214
+ let provider;
215
+ try {
216
+ provider = (0, provider_registry_1.toLoginProviderId)(providerInput);
217
+ }
218
+ catch {
219
+ throw new Error(`Unsupported provider: ${providerInput}`);
220
+ }
221
+ if (!(0, provider_registry_1.providerSupportsOAuth)(provider)) {
222
+ throw new Error(`Provider \"${provider}\" does not support oauth login.`);
223
+ }
224
+ if (provider !== "openai-codex") {
225
+ throw new Error(`UNSUPPORTED_OAUTH_PROVIDER: ${provider}`);
226
+ }
227
+ const requestId = nextOAuthRequestId(state);
228
+ const controller = new AbortController();
229
+ const requestState = {
230
+ request_id: requestId,
231
+ provider,
232
+ started_at: now(),
233
+ controller
234
+ };
235
+ state.pendingOAuthRequests.set(requestId, requestState);
236
+ await emitOAuthStatus(emitEvent, {
237
+ request_id: requestId,
238
+ provider,
239
+ phase: "started",
240
+ status: "OAuth started"
241
+ });
242
+ void (async () => {
243
+ try {
244
+ const config = await (0, config_1.readConfig)(state.cwd);
245
+ const endpoint = config.model.endpoint?.trim() || "";
246
+ const oauth = await state.oauthLogin({
247
+ onAuth: async ({ url, instructions }) => {
248
+ await emitOAuthStatus(emitEvent, {
249
+ request_id: requestId,
250
+ provider,
251
+ phase: "authorize",
252
+ status: instructions,
253
+ url
254
+ });
255
+ },
256
+ onProgress: async (message) => {
257
+ await emitOAuthStatus(emitEvent, {
258
+ request_id: requestId,
259
+ provider,
260
+ phase: "progress",
261
+ status: message
262
+ });
263
+ },
264
+ onPrompt: async () => "",
265
+ open_browser: true,
266
+ originator: "pi",
267
+ abort_signal: controller.signal
268
+ });
269
+ const loginLine = `/login ${provider} oauth ${oauth.access_token}${endpoint ? ` ${endpoint}` : ""}`;
270
+ await (0, dialog_1.handleDialogInput)(loginLine, state.cwd, {
271
+ sopOut: state.defaultSopOut,
272
+ checkpointOut: state.defaultCheckpointOut,
273
+ interactive: true,
274
+ quiet: true,
275
+ board: state.board,
276
+ conversations: state.conversations,
277
+ redraw: async (nextNotice) => {
278
+ await emitEvent({
279
+ event: "run.stage",
280
+ timestamp: now(),
281
+ payload: {
282
+ notice: nextNotice ?? "",
283
+ run_stage: state.board.run_stage,
284
+ run_status: state.board.run_status,
285
+ verification_status: state.board.verification_status,
286
+ verification_passed: state.board.verification_passed,
287
+ verification_total: state.board.verification_total,
288
+ risk_hit: state.board.risk_hit,
289
+ audit_verdict: state.board.audit_verdict,
290
+ budget_plan_calls: state.board.budget_plan_calls,
291
+ budget_audit_calls: state.board.budget_audit_calls,
292
+ budget_challenge_used: state.board.budget_challenge_used
293
+ }
294
+ });
295
+ }
296
+ });
297
+ const snapshot = await buildSessionSnapshot(state);
298
+ await emitSessionUpdate(state, emitEvent, snapshot);
299
+ await emitOAuthStatus(emitEvent, {
300
+ request_id: requestId,
301
+ provider,
302
+ phase: "success",
303
+ status: "OAuth login completed"
304
+ });
305
+ }
306
+ catch (error) {
307
+ const message = error instanceof Error ? error.message : String(error);
308
+ const phase = /cancel/i.test(message) || controller.signal.aborted ? "cancelled" : "failed";
309
+ await emitOAuthStatus(emitEvent, {
310
+ request_id: requestId,
311
+ provider,
312
+ phase,
313
+ status: message
314
+ });
315
+ }
316
+ finally {
317
+ state.pendingOAuthRequests.delete(requestId);
318
+ }
319
+ })();
320
+ return {
321
+ request_id: requestId,
322
+ status: "started"
323
+ };
324
+ }
325
+ async function performOAuthCancel(state, params, emitEvent) {
326
+ const parsed = parseOAuthCancelParams(params);
327
+ const requestId = parsed.requestId || [...state.pendingOAuthRequests.keys()].at(-1) || "";
328
+ if (!requestId) {
329
+ throw new Error("No pending OAuth request.");
330
+ }
331
+ const pending = state.pendingOAuthRequests.get(requestId);
332
+ if (!pending) {
333
+ const error = new Error("OAuth request not found.");
334
+ error.code = -32004;
335
+ throw error;
336
+ }
337
+ pending.controller.abort();
338
+ await emitOAuthStatus(emitEvent, {
339
+ request_id: requestId,
340
+ provider: pending.provider,
341
+ phase: "cancel_requested",
342
+ status: "OAuth cancellation requested"
343
+ });
344
+ return {
345
+ ok: true,
346
+ cancelled_request_id: requestId
347
+ };
348
+ }
349
+ async function executeDialogCommand(state, params, emitEvent) {
350
+ const parsed = parseExecuteParams(params, state.defaultSopOut, state.defaultCheckpointOut);
351
+ if (!parsed) {
352
+ throw new Error("Invalid params: input must be non-empty string.");
353
+ }
354
+ const trimmedInput = parsed.input.trim();
355
+ const oauthShortcut = parseOAuthCommandShortcut(trimmedInput);
356
+ if (oauthShortcut) {
357
+ const started = await performOAuthStart(state, oauthShortcut.provider, emitEvent);
358
+ const snapshot = await buildSessionSnapshot(state);
359
+ await emitSessionUpdate(state, emitEvent, snapshot);
360
+ return {
361
+ action: "continue",
362
+ notice: `oauth started: ${started.request_id}`,
363
+ snapshot
364
+ };
365
+ }
366
+ const result = await (0, dialog_1.handleDialogInput)(parsed.input, state.cwd, {
367
+ sopOut: parsed.sopOut,
368
+ checkpointOut: parsed.checkpointOut,
369
+ interactive: true,
370
+ quiet: true,
371
+ board: state.board,
372
+ conversations: state.conversations,
373
+ redraw: async (nextNotice) => {
374
+ await emitEvent({
375
+ event: "run.stage",
376
+ timestamp: now(),
377
+ payload: {
378
+ notice: nextNotice ?? "",
379
+ run_stage: state.board.run_stage,
380
+ run_status: state.board.run_status,
381
+ verification_status: state.board.verification_status,
382
+ verification_passed: state.board.verification_passed,
383
+ verification_total: state.board.verification_total,
384
+ risk_hit: state.board.risk_hit,
385
+ audit_verdict: state.board.audit_verdict,
386
+ budget_plan_calls: state.board.budget_plan_calls,
387
+ budget_audit_calls: state.board.budget_audit_calls,
388
+ budget_challenge_used: state.board.budget_challenge_used
389
+ }
390
+ });
391
+ if (/oauth/i.test(nextNotice ?? "")) {
392
+ await emitOAuthStatus(emitEvent, {
393
+ phase: "progress",
394
+ status: nextNotice ?? ""
395
+ });
396
+ }
397
+ }
398
+ });
399
+ if (result.action === "exit") {
400
+ state.terminated = true;
401
+ }
402
+ const snapshot = await buildSessionSnapshot(state);
403
+ await emitSessionUpdate(state, emitEvent, snapshot);
404
+ if (trimmedInput.startsWith("/run")) {
405
+ await emitEvent({
406
+ event: "audit.result",
407
+ timestamp: now(),
408
+ payload: {
409
+ verdict: state.board.audit_verdict,
410
+ reason: state.board.audit_reason,
411
+ conclusion: state.board.audit_conclusion,
412
+ retry_allowed: state.board.retry_allowed
413
+ }
414
+ });
415
+ }
416
+ return {
417
+ action: result.action,
418
+ notice: result.notice,
419
+ snapshot
420
+ };
421
+ }
422
+ async function createAppServerState(cwd = process.cwd(), options = {}) {
423
+ return {
424
+ cwd,
425
+ defaultSopOut: options.sopOut ?? "sop.json",
426
+ defaultCheckpointOut: options.checkpointOut ?? "checkpoint.json",
427
+ protocolInitialized: false,
428
+ terminated: false,
429
+ board: (0, dialog_1.createTaskBoardState)(),
430
+ conversations: {
431
+ index: await (0, dialog_session_1.readConversationIndex)(cwd)
432
+ },
433
+ oauthRequestSeq: 0,
434
+ pendingOAuthRequests: new Map(),
435
+ oauthLogin: options.oauthLogin ?? openai_codex_oauth_1.loginOpenAICodexOAuth
436
+ };
437
+ }
438
+ async function handleAppServerRequest(state, request, emitEvent) {
439
+ const id = request.id ?? null;
440
+ if (request.jsonrpc !== "2.0" || typeof request.method !== "string") {
441
+ if (request.id === undefined) {
442
+ return undefined;
443
+ }
444
+ return toError(id, -32600, "INVALID_REQUEST");
445
+ }
446
+ const method = request.method;
447
+ const needsInitialized = method === "session.get" ||
448
+ method === "command.execute" ||
449
+ method === "menu.context" ||
450
+ method === "oauth.start" ||
451
+ method === "oauth.cancel" ||
452
+ method === "shutdown";
453
+ if (needsInitialized && !state.protocolInitialized) {
454
+ return toError(id, -32002, "NOT_INITIALIZED");
455
+ }
456
+ try {
457
+ if (method === "initialize") {
458
+ const params = isRecord(request.params) ? request.params : {};
459
+ const protocolVersion = typeof params.protocol_version === "string"
460
+ ? params.protocol_version.trim()
461
+ : "";
462
+ if (protocolVersion && protocolVersion !== exports.APP_SERVER_PROTOCOL_VERSION) {
463
+ return toError(id, -32001, "PROTOCOL_VERSION_MISMATCH", {
464
+ expected: exports.APP_SERVER_PROTOCOL_VERSION,
465
+ received: protocolVersion
466
+ });
467
+ }
468
+ state.protocolInitialized = true;
469
+ return toResult(id, {
470
+ protocol_version: exports.APP_SERVER_PROTOCOL_VERSION,
471
+ server: {
472
+ name: "zaker-app-server",
473
+ version: resolveServerVersion()
474
+ },
475
+ capabilities: {
476
+ methods: [...exports.APP_SERVER_METHODS],
477
+ events: [...exports.APP_SERVER_EVENTS]
478
+ }
479
+ });
480
+ }
481
+ if (method === "ping") {
482
+ return toResult(id, {
483
+ ok: true,
484
+ timestamp: now()
485
+ });
486
+ }
487
+ if (method === "session.get") {
488
+ return toResult(id, await buildSessionSnapshot(state));
489
+ }
490
+ if (method === "menu.context") {
491
+ return toResult(id, await buildMenuContext(state));
492
+ }
493
+ if (method === "oauth.start") {
494
+ const parsed = parseOAuthStartParams(request.params);
495
+ if (!parsed) {
496
+ return toError(id, -32602, "INVALID_PARAMS", {
497
+ expected: { provider: "openai-codex" }
498
+ });
499
+ }
500
+ try {
501
+ return toResult(id, await performOAuthStart(state, parsed.provider, emitEvent));
502
+ }
503
+ catch (error) {
504
+ const message = error instanceof Error ? error.message : String(error);
505
+ return toError(id, -32003, "COMMAND_EXECUTION_FAILED", { message });
506
+ }
507
+ }
508
+ if (method === "oauth.cancel") {
509
+ try {
510
+ return toResult(id, await performOAuthCancel(state, request.params, emitEvent));
511
+ }
512
+ catch (error) {
513
+ const errorCode = typeof error === "object" && error !== null && "code" in error
514
+ ? Number(error.code)
515
+ : NaN;
516
+ const message = error instanceof Error ? error.message : String(error);
517
+ if (Number.isFinite(errorCode) && errorCode === -32004) {
518
+ return toError(id, -32004, "OAUTH_REQUEST_NOT_FOUND", { message });
519
+ }
520
+ return toError(id, -32003, "COMMAND_EXECUTION_FAILED", { message });
521
+ }
522
+ }
523
+ if (method === "command.execute") {
524
+ try {
525
+ const executed = await executeDialogCommand(state, request.params, emitEvent);
526
+ return toResult(id, executed);
527
+ }
528
+ catch (error) {
529
+ const message = error instanceof Error ? error.message : String(error);
530
+ return toError(id, -32003, "COMMAND_EXECUTION_FAILED", { message });
531
+ }
532
+ }
533
+ if (method === "shutdown") {
534
+ for (const pending of state.pendingOAuthRequests.values()) {
535
+ pending.controller.abort();
536
+ }
537
+ state.pendingOAuthRequests.clear();
538
+ state.terminated = true;
539
+ return toResult(id, { ok: true });
540
+ }
541
+ return toError(id, -32601, "METHOD_NOT_FOUND");
542
+ }
543
+ catch (error) {
544
+ const message = error instanceof Error ? error.message : String(error);
545
+ return toError(id, -32603, "INTERNAL_ERROR", { message });
546
+ }
547
+ }
548
+ function writeJsonLine(payload) {
549
+ process.stdout.write(`${JSON.stringify(payload)}\n`);
550
+ }
551
+ async function runAppServer(cwd = process.cwd(), options = {}) {
552
+ const state = await createAppServerState(cwd, options);
553
+ const input = node_readline_1.default.createInterface({
554
+ input: process.stdin,
555
+ crlfDelay: Infinity,
556
+ terminal: false
557
+ });
558
+ const emitEvent = async (event) => {
559
+ writeJsonLine({
560
+ jsonrpc: "2.0",
561
+ method: "event",
562
+ params: event
563
+ });
564
+ };
565
+ for await (const line of input) {
566
+ if (!line.trim()) {
567
+ continue;
568
+ }
569
+ let parsed;
570
+ try {
571
+ parsed = JSON.parse(line);
572
+ }
573
+ catch {
574
+ writeJsonLine(toError(null, -32700, "PARSE_ERROR"));
575
+ continue;
576
+ }
577
+ const response = await handleAppServerRequest(state, parsed, emitEvent);
578
+ if (response && parsed.id !== undefined) {
579
+ writeJsonLine(response);
580
+ }
581
+ if (state.terminated) {
582
+ break;
583
+ }
584
+ }
585
+ input.close();
586
+ }
587
+ function registerAppServerCommand(program) {
588
+ program
589
+ .command("app-server")
590
+ .description("start zaker JSON-RPC app server over stdio")
591
+ .option("--cwd <path>", "workspace directory", process.cwd())
592
+ .option("-o, --sop-out <path>", "default sop output path", "sop.json")
593
+ .option("-c, --checkpoint-out <path>", "default checkpoint output path", "checkpoint.json")
594
+ .action(async (options) => {
595
+ await runAppServer(options.cwd, {
596
+ sopOut: options.sopOut,
597
+ checkpointOut: options.checkpointOut
598
+ });
599
+ });
600
+ }
601
+ //# sourceMappingURL=app-server.js.map