@xfey/tutti 0.1.78 → 0.1.80

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 (85) hide show
  1. package/README.md +1 -1
  2. package/dist/chat-assistant/index.d.ts +11 -1
  3. package/dist/chat-assistant/index.js +61 -7
  4. package/dist/checks/index.d.ts +22 -0
  5. package/dist/checks/index.js +110 -4
  6. package/dist/control-plane/follow-up-start.d.ts +1 -0
  7. package/dist/control-plane/follow-up-start.js +3 -1
  8. package/dist/control-plane/index.d.ts +6 -1
  9. package/dist/control-plane/index.js +72 -11
  10. package/dist/control-plane/procedure-logging.js +24 -67
  11. package/dist/control-plane/project-context-bootstrap.js +7 -1
  12. package/dist/control-plane/reference-summary-refresh.js +1 -1
  13. package/dist/control-plane/run-result-recording.js +2 -1
  14. package/dist/control-plane/task-compile-start.d.ts +1 -0
  15. package/dist/control-plane/task-compile-start.js +11 -1
  16. package/dist/control-plane/workflows/openai.d.ts +6 -0
  17. package/dist/control-plane/workflows/openai.js +16 -3
  18. package/dist/procedure-engine/index.d.ts +1 -0
  19. package/dist/procedure-engine/index.js +7 -1
  20. package/dist/process-tree.d.ts +25 -0
  21. package/dist/process-tree.js +121 -0
  22. package/dist/providers/openai/app-server/invocation-coordinator.d.ts +28 -0
  23. package/dist/providers/openai/app-server/invocation-coordinator.js +104 -0
  24. package/dist/providers/openai/app-server/invocation-lifecycle.d.ts +45 -0
  25. package/dist/providers/openai/app-server/invocation-lifecycle.js +104 -0
  26. package/dist/providers/openai/app-server/json-rpc.d.ts +1 -1
  27. package/dist/providers/openai/app-server/json-rpc.js +9 -16
  28. package/dist/providers/openai/app-server/read-only-procedure.d.ts +8 -2
  29. package/dist/providers/openai/app-server/read-only-procedure.js +63 -11
  30. package/dist/providers/openai/app-server/smoke-types.d.ts +4 -2
  31. package/dist/providers/openai/app-server/smoke.js +41 -12
  32. package/dist/providers/openai/app-server/stale-temp-cleanup.d.ts +17 -0
  33. package/dist/providers/openai/app-server/stale-temp-cleanup.js +130 -0
  34. package/dist/providers/openai/app-server/workspace-write-run.d.ts +8 -2
  35. package/dist/providers/openai/app-server/workspace-write-run.js +63 -11
  36. package/dist/providers/openai/chat-assistant.d.ts +6 -0
  37. package/dist/providers/openai/chat-assistant.js +12 -0
  38. package/dist/providers/openai/index.d.ts +1 -0
  39. package/dist/providers/openai/index.js +1 -0
  40. package/dist/providers/openai/machine-local-files.d.ts +1 -1
  41. package/dist/providers/openai/machine-local-files.js +32 -9
  42. package/dist/providers/openai/provider-config.d.ts +5 -1
  43. package/dist/providers/openai/provider-config.js +25 -4
  44. package/dist/providers/openai/provider-models.d.ts +41 -0
  45. package/dist/providers/openai/provider-models.js +82 -0
  46. package/dist/providers/openai/provider-setup.js +5 -2
  47. package/dist/run-engine/index.js +2 -1
  48. package/dist/run-pipeline/artifact-applicability.js +2 -2
  49. package/dist/run-pipeline/openai.d.ts +9 -0
  50. package/dist/run-pipeline/openai.js +26 -26
  51. package/dist/run-pipeline/task-run-invocation.js +6 -0
  52. package/dist/runtime-failures.d.ts +3 -0
  53. package/dist/runtime-failures.js +22 -0
  54. package/dist/server-shell/cli/host-lifecycle.js +1 -1
  55. package/dist/server-shell/cli/host-project-runtime-lifecycle.d.ts +43 -0
  56. package/dist/server-shell/cli/host-project-runtime-lifecycle.js +54 -0
  57. package/dist/server-shell/cli/host-server-runtime.d.ts +1 -1
  58. package/dist/server-shell/cli/host-server-runtime.js +140 -15
  59. package/dist/server-shell/http/create-server.d.ts +3 -0
  60. package/dist/server-shell/http/create-server.js +10 -4
  61. package/dist/server-shell/http/routes/project-api/invalidations.d.ts +1 -0
  62. package/dist/server-shell/http/routes/project-api/invalidations.js +4 -5
  63. package/dist/server-shell/http/routes/project-api/openapi-workspace-routes.d.ts +38 -14
  64. package/dist/server-shell/http/routes/project-api/openapi-workspace-routes.js +26 -1
  65. package/dist/server-shell/http/routes/project-api/openapi.d.ts +38 -14
  66. package/dist/server-shell/http/routes/project-api/schemas.d.ts +8 -2
  67. package/dist/server-shell/http/routes/project-api/schemas.js +2 -0
  68. package/dist/server-shell/http/routes/project-api/session-requirements.d.ts +1 -0
  69. package/dist/server-shell/http/routes/project-api/session-requirements.js +7 -0
  70. package/dist/server-shell/http/routes/project-api/system-routes.js +96 -5
  71. package/dist/server-shell/http/routes/project-api/types.d.ts +10 -1
  72. package/dist/server-shell/http/routes/project-api/workspace-projections.js +4 -2
  73. package/dist/server-shell/http/routes/project-api.d.ts +1 -1
  74. package/node_modules/@tutti/shared/dist/schemas/api/index.d.ts +1 -1
  75. package/node_modules/@tutti/shared/dist/schemas/api/index.js +1 -1
  76. package/node_modules/@tutti/shared/dist/schemas/api/provider-config.d.ts +36 -0
  77. package/node_modules/@tutti/shared/dist/schemas/api/provider-config.js +58 -1
  78. package/node_modules/@tutti/shared/dist/schemas/api/types.d.ts +9 -1
  79. package/package.json +1 -1
  80. package/web/assets/{homepage-motion-scene-sNI8fBH3.js → homepage-motion-scene-DXzmjALa.js} +1 -1
  81. package/web/assets/index-9gApbtPC.js +69 -0
  82. package/web/assets/index-BKeSEhsn.css +1 -0
  83. package/web/index.html +2 -2
  84. package/web/assets/index-BUfAlA_H.css +0 -1
  85. package/web/assets/index-d-q9yZ09.js +0 -69
@@ -0,0 +1,54 @@
1
+ export class HostProjectRuntimeShutdownError extends Error {
2
+ code;
3
+ constructor(code, message) {
4
+ super(message);
5
+ this.code = code;
6
+ this.name = "HostProjectRuntimeShutdownError";
7
+ }
8
+ }
9
+ const DEFAULT_GRACEFUL_DRAIN_MS = 1_000;
10
+ const DEFAULT_FORCED_DRAIN_MS = 10_000;
11
+ function wait(delayMs) {
12
+ return new Promise((resolve) => setTimeout(resolve, delayMs));
13
+ }
14
+ async function settlesWithin(promise, timeoutMs) {
15
+ return await Promise.race([
16
+ promise.then(() => true),
17
+ wait(timeoutMs).then(() => false),
18
+ ]);
19
+ }
20
+ export class HostProjectRuntimeLifecycle {
21
+ options;
22
+ closePromise;
23
+ constructor(options) {
24
+ this.options = options;
25
+ }
26
+ close() {
27
+ this.closePromise ??= this.closeOnce();
28
+ return this.closePromise;
29
+ }
30
+ async closeOnce() {
31
+ this.options.controlPlane.beginShutdown();
32
+ this.options.chatAssistant.stopAccepting();
33
+ this.options.invocationCoordinator.stopAccepting();
34
+ this.options.checkProcessCoordinator.stopAccepting();
35
+ this.options.approvalManager.clearPending();
36
+ const waitForOwners = () => Promise.all([
37
+ this.options.chatAssistant.waitForIdle(),
38
+ this.options.controlPlane.waitForIdle(),
39
+ this.options.invocationCoordinator.waitForIdle(),
40
+ this.options.checkProcessCoordinator.waitForIdle(),
41
+ ]).then(() => undefined);
42
+ if (!(await settlesWithin(waitForOwners(), this.options.gracefulDrainMs ?? DEFAULT_GRACEFUL_DRAIN_MS))) {
43
+ await Promise.all([
44
+ this.options.invocationCoordinator.closeActive(),
45
+ this.options.checkProcessCoordinator.terminateActive(),
46
+ ]);
47
+ if (!(await settlesWithin(waitForOwners(), this.options.forcedDrainMs ?? DEFAULT_FORCED_DRAIN_MS))) {
48
+ throw new HostProjectRuntimeShutdownError("drain_timeout", "Host project runtime did not settle within the bounded shutdown window.");
49
+ }
50
+ }
51
+ this.options.approvalManager.dispose();
52
+ }
53
+ }
54
+ //# sourceMappingURL=host-project-runtime-lifecycle.js.map
@@ -1,5 +1,5 @@
1
1
  import type { FastifyInstance } from "fastify";
2
- import type { ExecutionStatusProjection } from "@tutti/shared/schemas/api";
2
+ import { type ExecutionStatusProjection } from "@tutti/shared/schemas/api";
3
3
  import { type HostProjectStore } from "../../store/index.js";
4
4
  import type { createHostServer } from "../http/create-server.js";
5
5
  import type { HostLocalLaunchStatus } from "../http/routes/local-control.js";
@@ -1,14 +1,18 @@
1
1
  import { basename, join } from "node:path";
2
+ import { MAX_PROVIDER_MODEL_NAME_LENGTH, } from "@tutti/shared/schemas/api";
2
3
  import { serializeRuntimeLogLine } from "@tutti/shared/utils";
3
4
  import { completeRelayUpload, resolveRelayUpload } from "@tutti/relay-client";
4
5
  import { ApprovalRequestManager } from "../../approvals/index.js";
5
6
  import { ArtifactPreviewManager } from "../../artifacts/index.js";
6
7
  import { ReadOnlyChatAssistant } from "../../chat-assistant/index.js";
8
+ import { CheckProcessCoordinator } from "../../checks/index.js";
7
9
  import { ensureInitialProjectWelcomeMessage } from "../../collaboration-state/index.js";
8
10
  import { Phase5ControlPlane } from "../../control-plane/index.js";
9
11
  import { resolveProjectOpenAiProcedureWorkflowRunner } from "../../control-plane/workflows/index.js";
12
+ import { cleanupStaleCodexAppServerTempRoots } from "../../providers/openai/app-server/stale-temp-cleanup.js";
13
+ import { CodexAppServerInvocationCoordinator } from "../../providers/openai/app-server/invocation-coordinator.js";
10
14
  import { resolveProjectOpenAiReadOnlyChatAssistantModel } from "../../providers/openai/chat-assistant.js";
11
- import { configureProjectOpenAiProvider, readOpenAiProviderConfigProjection, } from "../../providers/openai/index.js";
15
+ import { configureProjectOpenAiProvider, discoverProjectOpenAiModels, readOpenAiProviderConfigProjection, updateProjectOpenAiDefaultModel, } from "../../providers/openai/index.js";
12
16
  import { readProviderUsageProjection, recordProviderUsageEvent, } from "../../provider-usage/index.js";
13
17
  import { resolveProjectOpenAiRunPipelineRunner } from "../../run-pipeline/openai.js";
14
18
  import { openHostProjectStore } from "../../store/index.js";
@@ -18,6 +22,7 @@ import { readHostRepoProjection } from "../http/routes/project-api.js";
18
22
  import { WorkspaceEventBus } from "../http/workspace-events.js";
19
23
  import { createTrustedRelaySessionMetadataStore, } from "../session/relay-session-context.js";
20
24
  import { LaunchError } from "./errors.js";
25
+ import { HostProjectRuntimeLifecycle } from "./host-project-runtime-lifecycle.js";
21
26
  import { readCliVersion } from "./version.js";
22
27
  import { relayStateFromLaunchStatus } from "./host-relay-status.js";
23
28
  import { appendHostLogLine, readHostRegistrationSecret, createMachineRuntimeEndpointToken, deleteMachineRuntimeEndpoint, ensureHostLogFile, getHostLogFilePath, updateMachineProjectDisplayNameSnapshot, writeMachineRuntimeEndpoint, } from "./machine-local.js";
@@ -32,6 +37,62 @@ export function packageUpdateReadinessFromExecutionStatus(execution) {
32
37
  ? "busy"
33
38
  : "ready";
34
39
  }
40
+ function createHostProviderModelService(options) {
41
+ return {
42
+ discover: async () => {
43
+ const result = await discoverProjectOpenAiModels(options);
44
+ if (result.kind !== "ok") {
45
+ return { status: "unavailable", reason: result.reason };
46
+ }
47
+ const models = result.models.filter((model) => model.length <= MAX_PROVIDER_MODEL_NAME_LENGTH && /^\S(?:.*\S)?$/.test(model));
48
+ return models.length > 0
49
+ ? { status: "available", models }
50
+ : { status: "unavailable", reason: "model_list_empty" };
51
+ },
52
+ update: async (payload) => {
53
+ const result = await updateProjectOpenAiDefaultModel({
54
+ ...options,
55
+ defaultModel: payload.default_model,
56
+ expectedDefaultModel: payload.expected_default_model,
57
+ });
58
+ if (result.kind === "updated") {
59
+ return {
60
+ disposition: { kind: "updated" },
61
+ provider_config: result.projection,
62
+ };
63
+ }
64
+ if (result.kind === "unchanged") {
65
+ return {
66
+ disposition: { kind: "unchanged" },
67
+ provider_config: result.projection,
68
+ };
69
+ }
70
+ if (result.kind === "stale_default_model") {
71
+ return {
72
+ disposition: {
73
+ kind: result.kind,
74
+ current_default_model: result.current_default_model,
75
+ },
76
+ };
77
+ }
78
+ if (result.kind === "validation_failed") {
79
+ return {
80
+ disposition: {
81
+ kind: result.kind,
82
+ reason: result.reason,
83
+ retryable: result.retryable,
84
+ },
85
+ };
86
+ }
87
+ return {
88
+ disposition: {
89
+ kind: result.kind,
90
+ reason: result.reason,
91
+ },
92
+ };
93
+ },
94
+ };
95
+ }
35
96
  function createHostRuntimeLogger(options) {
36
97
  return {
37
98
  info(fields, message) {
@@ -47,6 +108,15 @@ function createHostRuntimeLogger(options) {
47
108
  },
48
109
  };
49
110
  }
111
+ function createLifecycleIncidentReporter(logger, consumer) {
112
+ return (incident) => {
113
+ logger.info({
114
+ consumer,
115
+ incident_code: incident.code,
116
+ error_code: incident.error_code,
117
+ }, "Codex app-server lifecycle incident");
118
+ };
119
+ }
50
120
  function createAgentContextRuntime(options) {
51
121
  return {
52
122
  baseUrl: new URL(AGENT_CONTEXT_BASE_PATH, options.baseUrl).toString(),
@@ -214,10 +284,25 @@ export async function startForegroundHostServer(options) {
214
284
  logFilePath,
215
285
  now,
216
286
  });
287
+ const procedureLifecycleIncident = createLifecycleIncidentReporter(controlPlaneLogger, "procedure");
288
+ const runLifecycleIncident = createLifecycleIncidentReporter(runPipelineLogger, "run");
289
+ const chatLifecycleIncident = createLifecycleIncidentReporter(controlPlaneLogger, "chat_assistant");
290
+ const staleTempCleanup = await cleanupStaleCodexAppServerTempRoots({
291
+ onIncident: (incident) => {
292
+ controlPlaneLogger.info({
293
+ consumer: "maintenance",
294
+ incident_code: incident.code,
295
+ error_code: incident.error_code,
296
+ }, "Codex app-server lifecycle incident");
297
+ },
298
+ });
299
+ controlPlaneLogger.info(staleTempCleanup, "Codex app-server stale temp cleanup completed");
217
300
  const approvalManager = new ApprovalRequestManager({
218
301
  events: workspaceEvents,
219
302
  now,
220
303
  });
304
+ const codexInvocationCoordinator = new CodexAppServerInvocationCoordinator();
305
+ const checkProcessCoordinator = new CheckProcessCoordinator();
221
306
  const artifactPreviewManager = new ArtifactPreviewManager({
222
307
  onStatusChange: () => {
223
308
  workspaceEvents.publish({
@@ -254,6 +339,9 @@ export async function startForegroundHostServer(options) {
254
339
  approvalManager,
255
340
  logger: runPipelineLogger,
256
341
  recordUsage,
342
+ invocationCoordinator: codexInvocationCoordinator,
343
+ checkProcessCoordinator,
344
+ onLifecycleIncident: runLifecycleIncident,
257
345
  }),
258
346
  resolveWorkflowRunner: () => resolveProjectOpenAiProcedureWorkflowRunner({
259
347
  tuttiHome: options.preparation.tutti_home,
@@ -261,6 +349,8 @@ export async function startForegroundHostServer(options) {
261
349
  workspaceRoot: options.preparation.workspace_root,
262
350
  agentContext: agentContextRuntime,
263
351
  recordUsage,
352
+ invocationCoordinator: codexInvocationCoordinator,
353
+ onLifecycleIncident: procedureLifecycleIncident,
264
354
  }),
265
355
  });
266
356
  const chatAssistant = new ReadOnlyChatAssistant({
@@ -276,6 +366,8 @@ export async function startForegroundHostServer(options) {
276
366
  workspaceRoot: options.preparation.workspace_root,
277
367
  agentContext: agentContextRuntime,
278
368
  recordUsage,
369
+ invocationCoordinator: codexInvocationCoordinator,
370
+ onLifecycleIncident: chatLifecycleIncident,
279
371
  });
280
372
  if (resolution.kind !== "ready") {
281
373
  throw new Error("Provider is not configured.");
@@ -283,9 +375,17 @@ export async function startForegroundHostServer(options) {
283
375
  return await resolution.model.answer(input);
284
376
  },
285
377
  },
378
+ waitForInspectionAvailability: () => controlPlane.waitForRepoInspectionIdle(),
286
379
  onScratchpadSourceChanged: (message) => controlPlane.notifyScratchpadSourceChanged(message),
287
380
  now,
288
381
  });
382
+ const projectRuntimeLifecycle = new HostProjectRuntimeLifecycle({
383
+ controlPlane,
384
+ chatAssistant,
385
+ invocationCoordinator: codexInvocationCoordinator,
386
+ checkProcessCoordinator,
387
+ approvalManager,
388
+ });
289
389
  let close = async () => { };
290
390
  let relayConnectionManager;
291
391
  const packageUpdateReadiness = () => packageUpdateReadinessFromExecutionStatus(controlPlane.getExecutionStatus());
@@ -372,6 +472,9 @@ export async function startForegroundHostServer(options) {
372
472
  },
373
473
  },
374
474
  logger: { file: logFilePath },
475
+ lifecycle: {
476
+ close: () => projectRuntimeLifecycle.close(),
477
+ },
375
478
  localControl,
376
479
  now,
377
480
  projectApi: {
@@ -396,6 +499,11 @@ export async function startForegroundHostServer(options) {
396
499
  chatAssistant,
397
500
  tuttiHome: options.preparation.tutti_home,
398
501
  getProviderConfig,
502
+ providerModel: createHostProviderModelService({
503
+ tuttiHome: options.preparation.tutti_home,
504
+ projectId: options.preparation.project_id,
505
+ now,
506
+ }),
399
507
  getProviderUsage: () => readProviderUsageProjection(store.db),
400
508
  updateProjectDisplayName: (displayName) => {
401
509
  updateRuntimeProjectDisplayName(displayName);
@@ -456,30 +564,47 @@ export async function startForegroundHostServer(options) {
456
564
  recoverInProgressCommands: true,
457
565
  });
458
566
  let resolveClosed;
459
- const closed = new Promise((resolve) => {
567
+ let rejectClosed;
568
+ const closed = new Promise((resolve, reject) => {
460
569
  resolveClosed = resolve;
570
+ rejectClosed = reject;
461
571
  });
462
572
  let closePromise;
463
573
  close = () => {
464
574
  closePromise ??= (async () => {
575
+ let closeError;
576
+ let appClosed = false;
465
577
  try {
466
- await relayConnectionManager?.stop();
467
- await app.close();
468
- }
469
- finally {
470
578
  try {
471
- approvalManager.dispose();
472
- store.close();
579
+ await relayConnectionManager?.stop();
473
580
  }
474
- finally {
475
- deleteMachineRuntimeEndpoint({
476
- tuttiHome: options.preparation.tutti_home,
477
- projectId: options.preparation.project_id,
478
- expectedToken: token,
479
- });
480
- resolveClosed();
581
+ catch (error) {
582
+ closeError = error;
583
+ }
584
+ try {
585
+ await app.close();
586
+ appClosed = true;
481
587
  }
588
+ catch (error) {
589
+ closeError ??= error;
590
+ }
591
+ if (appClosed) {
592
+ store.close();
593
+ }
594
+ }
595
+ finally {
596
+ deleteMachineRuntimeEndpoint({
597
+ tuttiHome: options.preparation.tutti_home,
598
+ projectId: options.preparation.project_id,
599
+ expectedToken: token,
600
+ });
601
+ }
602
+ if (closeError !== undefined) {
603
+ const normalizedCloseError = closeError instanceof Error ? closeError : new Error("Host server close failed.");
604
+ rejectClosed(normalizedCloseError);
605
+ throw normalizedCloseError;
482
606
  }
607
+ resolveClosed();
483
608
  })();
484
609
  return closePromise;
485
610
  };
@@ -16,6 +16,9 @@ export type HostServerOptions = {
16
16
  logger?: false | {
17
17
  file?: string;
18
18
  };
19
+ lifecycle?: {
20
+ close: () => void | Promise<void>;
21
+ };
19
22
  localControl?: HostLocalControlOptions;
20
23
  now?: () => Date;
21
24
  projectApi?: false | HostProjectApiRouteOptions;
@@ -24,10 +24,11 @@ export function createHostServer(options = {}) {
24
24
  if (options.projectApi !== undefined && options.projectApi !== false) {
25
25
  const projectApiOptions = options.projectApi;
26
26
  registerHostProjectApiRoutes(app, projectApiOptions);
27
- app.addHook("onClose", (_instance, done) => {
28
- projectApiOptions.controlPlane?.dispose();
29
- done();
30
- });
27
+ if (options.lifecycle === undefined) {
28
+ app.addHook("onClose", async () => {
29
+ await projectApiOptions.controlPlane?.dispose();
30
+ });
31
+ }
31
32
  if (options.agentContext !== false) {
32
33
  registerAgentContextRoutes(app, {
33
34
  project: projectApiOptions.project,
@@ -46,6 +47,11 @@ export function createHostServer(options = {}) {
46
47
  });
47
48
  }
48
49
  }
50
+ if (options.lifecycle !== undefined) {
51
+ app.addHook("onClose", async () => {
52
+ await options.lifecycle?.close();
53
+ });
54
+ }
49
55
  if (options.webStatic !== undefined && options.webStatic !== false) {
50
56
  registerHostWebStaticRoutes(app, options.webStatic);
51
57
  }
@@ -7,5 +7,6 @@ export declare function clarificationRoundInvalidates(roundId: ClarificationRoun
7
7
  export declare function approvalInvalidates(): QueryInvalidationHint[];
8
8
  export declare function readStateInvalidates(): QueryInvalidationHint[];
9
9
  export declare function projectMetadataInvalidates(): QueryInvalidationHint[];
10
+ export declare function providerConfigInvalidates(): QueryInvalidationHint[];
10
11
  export declare function projectDisplayNameInvalidates(): QueryInvalidationHint[];
11
12
  //# sourceMappingURL=invalidations.d.ts.map
@@ -1,9 +1,5 @@
1
1
  export function mainChatMessageInvalidates() {
2
- return [
3
- { kind: "messages", scope: "main_chat" },
4
- { kind: "read_state" },
5
- { kind: "bootstrap" },
6
- ];
2
+ return [{ kind: "messages", scope: "main_chat" }, { kind: "read_state" }, { kind: "bootstrap" }];
7
3
  }
8
4
  export function worklistSubmitInvalidates() {
9
5
  return [
@@ -54,6 +50,9 @@ export function readStateInvalidates() {
54
50
  export function projectMetadataInvalidates() {
55
51
  return [{ kind: "workspace" }, { kind: "bootstrap" }];
56
52
  }
53
+ export function providerConfigInvalidates() {
54
+ return [{ kind: "provider_config" }, { kind: "workspace" }, { kind: "bootstrap" }];
55
+ }
57
56
  export function projectDisplayNameInvalidates() {
58
57
  return projectMetadataInvalidates();
59
58
  }
@@ -76,6 +76,36 @@ export declare const HOST_PROJECT_WORKSPACE_OPENAPI_ROUTES: ({
76
76
  };
77
77
  };
78
78
  requestBody?: never;
79
+ } | {
80
+ method: "get";
81
+ path: string;
82
+ summary: string;
83
+ tags: string[];
84
+ responses: {
85
+ 200: {
86
+ description: string;
87
+ schema: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
88
+ status: import("@sinclair/typebox").TLiteral<"available">;
89
+ models: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>;
90
+ }>, import("@sinclair/typebox").TObject<{
91
+ status: import("@sinclair/typebox").TLiteral<"unavailable">;
92
+ reason: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"model_list_unavailable">, import("@sinclair/typebox").TLiteral<"model_list_empty">, import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"provider_not_configured">, import("@sinclair/typebox").TLiteral<"provider_config_invalid">, import("@sinclair/typebox").TLiteral<"provider_credential_missing">]>]>;
93
+ }>]>;
94
+ };
95
+ };
96
+ requestBody?: never;
97
+ } | {
98
+ method: "post";
99
+ path: string;
100
+ summary: string;
101
+ tags: string[];
102
+ requestBody: import("@sinclair/typebox").TSchema;
103
+ responses: {
104
+ 200: {
105
+ description: string;
106
+ schema: import("@sinclair/typebox").TSchema;
107
+ };
108
+ };
79
109
  } | {
80
110
  method: "get";
81
111
  path: string;
@@ -555,7 +585,7 @@ export declare const HOST_PROJECT_WORKSPACE_OPENAPI_ROUTES: ({
555
585
  };
556
586
  readonly capabilities: {
557
587
  readonly type: "object";
558
- readonly required: readonly ["sse", "relay_join", "repo_viewer", "provider_config_query", "browser_secret_write", "task_auto_scheduler", "task_run_now_scheduler", "clarification"];
588
+ readonly required: readonly ["sse", "relay_join", "repo_viewer", "provider_config_query", "provider_model_update", "browser_secret_write", "task_auto_scheduler", "task_run_now_scheduler", "clarification"];
559
589
  readonly additionalProperties: false;
560
590
  readonly properties: {
561
591
  readonly sse: {
@@ -570,6 +600,9 @@ export declare const HOST_PROJECT_WORKSPACE_OPENAPI_ROUTES: ({
570
600
  readonly provider_config_query: {
571
601
  readonly type: "boolean";
572
602
  };
603
+ readonly provider_model_update: {
604
+ readonly type: "boolean";
605
+ };
573
606
  readonly browser_secret_write: {
574
607
  readonly type: "boolean";
575
608
  readonly enum: readonly [false];
@@ -590,18 +623,6 @@ export declare const HOST_PROJECT_WORKSPACE_OPENAPI_ROUTES: ({
590
623
  };
591
624
  };
592
625
  requestBody?: never;
593
- } | {
594
- method: "post";
595
- path: string;
596
- summary: string;
597
- tags: string[];
598
- requestBody: import("@sinclair/typebox").TSchema;
599
- responses: {
600
- 200: {
601
- description: string;
602
- schema: import("@sinclair/typebox").TSchema;
603
- };
604
- };
605
626
  } | {
606
627
  method: "get";
607
628
  path: string;
@@ -755,7 +776,7 @@ export declare const HOST_PROJECT_WORKSPACE_OPENAPI_ROUTES: ({
755
776
  };
756
777
  readonly capabilities: {
757
778
  readonly type: "object";
758
- readonly required: readonly ["sse", "relay_join", "repo_viewer", "provider_config_query", "browser_secret_write", "task_auto_scheduler", "task_run_now_scheduler", "clarification"];
779
+ readonly required: readonly ["sse", "relay_join", "repo_viewer", "provider_config_query", "provider_model_update", "browser_secret_write", "task_auto_scheduler", "task_run_now_scheduler", "clarification"];
759
780
  readonly additionalProperties: false;
760
781
  readonly properties: {
761
782
  readonly sse: {
@@ -770,6 +791,9 @@ export declare const HOST_PROJECT_WORKSPACE_OPENAPI_ROUTES: ({
770
791
  readonly provider_config_query: {
771
792
  readonly type: "boolean";
772
793
  };
794
+ readonly provider_model_update: {
795
+ readonly type: "boolean";
796
+ };
773
797
  readonly browser_secret_write: {
774
798
  readonly type: "boolean";
775
799
  readonly enum: readonly [false];
@@ -1,4 +1,4 @@
1
- import { MarkReadBodySchema, MarkReadResponseSchema, ReadStateSummaryProjectionSchema, UpdateProjectDescriptionBodySchema, UpdateProjectDescriptionResponseSchema, UpdateProjectDisplayNameBodySchema, UpdateProjectDisplayNameResponseSchema, } from "@tutti/shared/schemas/api";
1
+ import { MarkReadBodySchema, MarkReadResponseSchema, ReadStateSummaryProjectionSchema, UpdateProjectDescriptionBodySchema, UpdateProjectDescriptionResponseSchema, UpdateProjectDisplayNameBodySchema, UpdateProjectDisplayNameResponseSchema, GetProviderModelsResponseSchema, UpdateProviderDefaultModelBodySchema, UpdateProviderDefaultModelResponseSchema, } from "@tutti/shared/schemas/api";
2
2
  import { HOST_PROJECT_API_BASE_PATH } from "./constants.js";
3
3
  import { BootstrapResponseSchema, ProviderConfigProjectionSchema, ProviderUsageProjectionSchema, SessionResponseSchema, WorkspaceResponseSchema, } from "./schemas.js";
4
4
  export const HOST_PROJECT_WORKSPACE_OPENAPI_ROUTES = [
@@ -14,6 +14,31 @@ export const HOST_PROJECT_WORKSPACE_OPENAPI_ROUTES = [
14
14
  },
15
15
  },
16
16
  },
17
+ {
18
+ method: "get",
19
+ path: `${HOST_PROJECT_API_BASE_PATH}/provider/models`,
20
+ summary: "Discover model names with the configured provider credential (owner only).",
21
+ tags: ["provider"],
22
+ responses: {
23
+ 200: {
24
+ description: "Bounded provider model discovery result.",
25
+ schema: GetProviderModelsResponseSchema,
26
+ },
27
+ },
28
+ },
29
+ {
30
+ method: "post",
31
+ path: `${HOST_PROJECT_API_BASE_PATH}/provider/default-model`,
32
+ summary: "Validate and update the default provider model (owner only).",
33
+ tags: ["provider"],
34
+ requestBody: UpdateProviderDefaultModelBodySchema,
35
+ responses: {
36
+ 200: {
37
+ description: "Default-model update command response.",
38
+ schema: UpdateProviderDefaultModelResponseSchema,
39
+ },
40
+ },
41
+ },
17
42
  {
18
43
  method: "get",
19
44
  path: `${HOST_PROJECT_API_BASE_PATH}/provider/usage`,
@@ -1350,6 +1350,36 @@ export declare const HOST_PROJECT_OPENAPI_ROUTES: ({
1350
1350
  };
1351
1351
  };
1352
1352
  requestBody?: never;
1353
+ } | {
1354
+ method: "get";
1355
+ path: string;
1356
+ summary: string;
1357
+ tags: string[];
1358
+ responses: {
1359
+ 200: {
1360
+ description: string;
1361
+ schema: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
1362
+ status: import("@sinclair/typebox").TLiteral<"available">;
1363
+ models: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>;
1364
+ }>, import("@sinclair/typebox").TObject<{
1365
+ status: import("@sinclair/typebox").TLiteral<"unavailable">;
1366
+ reason: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"model_list_unavailable">, import("@sinclair/typebox").TLiteral<"model_list_empty">, import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"provider_not_configured">, import("@sinclair/typebox").TLiteral<"provider_config_invalid">, import("@sinclair/typebox").TLiteral<"provider_credential_missing">]>]>;
1367
+ }>]>;
1368
+ };
1369
+ };
1370
+ requestBody?: never;
1371
+ } | {
1372
+ method: "post";
1373
+ path: string;
1374
+ summary: string;
1375
+ tags: string[];
1376
+ requestBody: import("@sinclair/typebox").TSchema;
1377
+ responses: {
1378
+ 200: {
1379
+ description: string;
1380
+ schema: import("@sinclair/typebox").TSchema;
1381
+ };
1382
+ };
1353
1383
  } | {
1354
1384
  method: "get";
1355
1385
  path: string;
@@ -1829,7 +1859,7 @@ export declare const HOST_PROJECT_OPENAPI_ROUTES: ({
1829
1859
  };
1830
1860
  readonly capabilities: {
1831
1861
  readonly type: "object";
1832
- readonly required: readonly ["sse", "relay_join", "repo_viewer", "provider_config_query", "browser_secret_write", "task_auto_scheduler", "task_run_now_scheduler", "clarification"];
1862
+ readonly required: readonly ["sse", "relay_join", "repo_viewer", "provider_config_query", "provider_model_update", "browser_secret_write", "task_auto_scheduler", "task_run_now_scheduler", "clarification"];
1833
1863
  readonly additionalProperties: false;
1834
1864
  readonly properties: {
1835
1865
  readonly sse: {
@@ -1844,6 +1874,9 @@ export declare const HOST_PROJECT_OPENAPI_ROUTES: ({
1844
1874
  readonly provider_config_query: {
1845
1875
  readonly type: "boolean";
1846
1876
  };
1877
+ readonly provider_model_update: {
1878
+ readonly type: "boolean";
1879
+ };
1847
1880
  readonly browser_secret_write: {
1848
1881
  readonly type: "boolean";
1849
1882
  readonly enum: readonly [false];
@@ -1864,18 +1897,6 @@ export declare const HOST_PROJECT_OPENAPI_ROUTES: ({
1864
1897
  };
1865
1898
  };
1866
1899
  requestBody?: never;
1867
- } | {
1868
- method: "post";
1869
- path: string;
1870
- summary: string;
1871
- tags: string[];
1872
- requestBody: import("@sinclair/typebox").TSchema;
1873
- responses: {
1874
- 200: {
1875
- description: string;
1876
- schema: import("@sinclair/typebox").TSchema;
1877
- };
1878
- };
1879
1900
  } | {
1880
1901
  method: "get";
1881
1902
  path: string;
@@ -2029,7 +2050,7 @@ export declare const HOST_PROJECT_OPENAPI_ROUTES: ({
2029
2050
  };
2030
2051
  readonly capabilities: {
2031
2052
  readonly type: "object";
2032
- readonly required: readonly ["sse", "relay_join", "repo_viewer", "provider_config_query", "browser_secret_write", "task_auto_scheduler", "task_run_now_scheduler", "clarification"];
2053
+ readonly required: readonly ["sse", "relay_join", "repo_viewer", "provider_config_query", "provider_model_update", "browser_secret_write", "task_auto_scheduler", "task_run_now_scheduler", "clarification"];
2033
2054
  readonly additionalProperties: false;
2034
2055
  readonly properties: {
2035
2056
  readonly sse: {
@@ -2044,6 +2065,9 @@ export declare const HOST_PROJECT_OPENAPI_ROUTES: ({
2044
2065
  readonly provider_config_query: {
2045
2066
  readonly type: "boolean";
2046
2067
  };
2068
+ readonly provider_model_update: {
2069
+ readonly type: "boolean";
2070
+ };
2047
2071
  readonly browser_secret_write: {
2048
2072
  readonly type: "boolean";
2049
2073
  readonly enum: readonly [false];
@@ -560,7 +560,7 @@ export declare const WorkspaceResponseSchema: {
560
560
  };
561
561
  readonly capabilities: {
562
562
  readonly type: "object";
563
- readonly required: readonly ["sse", "relay_join", "repo_viewer", "provider_config_query", "browser_secret_write", "task_auto_scheduler", "task_run_now_scheduler", "clarification"];
563
+ readonly required: readonly ["sse", "relay_join", "repo_viewer", "provider_config_query", "provider_model_update", "browser_secret_write", "task_auto_scheduler", "task_run_now_scheduler", "clarification"];
564
564
  readonly additionalProperties: false;
565
565
  readonly properties: {
566
566
  readonly sse: {
@@ -575,6 +575,9 @@ export declare const WorkspaceResponseSchema: {
575
575
  readonly provider_config_query: {
576
576
  readonly type: "boolean";
577
577
  };
578
+ readonly provider_model_update: {
579
+ readonly type: "boolean";
580
+ };
578
581
  readonly browser_secret_write: {
579
582
  readonly type: "boolean";
580
583
  readonly enum: readonly [false];
@@ -737,7 +740,7 @@ export declare const BootstrapResponseSchema: {
737
740
  };
738
741
  readonly capabilities: {
739
742
  readonly type: "object";
740
- readonly required: readonly ["sse", "relay_join", "repo_viewer", "provider_config_query", "browser_secret_write", "task_auto_scheduler", "task_run_now_scheduler", "clarification"];
743
+ readonly required: readonly ["sse", "relay_join", "repo_viewer", "provider_config_query", "provider_model_update", "browser_secret_write", "task_auto_scheduler", "task_run_now_scheduler", "clarification"];
741
744
  readonly additionalProperties: false;
742
745
  readonly properties: {
743
746
  readonly sse: {
@@ -752,6 +755,9 @@ export declare const BootstrapResponseSchema: {
752
755
  readonly provider_config_query: {
753
756
  readonly type: "boolean";
754
757
  };
758
+ readonly provider_model_update: {
759
+ readonly type: "boolean";
760
+ };
755
761
  readonly browser_secret_write: {
756
762
  readonly type: "boolean";
757
763
  readonly enum: readonly [false];