@agent-native/core 0.209.1 → 0.209.2-nightly-20261016005836

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 (97) hide show
  1. package/dist/agent/actions/list-model-providers.js +15 -2
  2. package/dist/agent/app-model-defaults.d.ts +9 -13
  3. package/dist/agent/app-model-defaults.js +23 -5
  4. package/dist/agent/default-agent-engine.d.ts +5 -3
  5. package/dist/agent/default-agent-engine.js +38 -8
  6. package/dist/agent/durable-background.d.ts +2 -0
  7. package/dist/agent/durable-background.js +2 -0
  8. package/dist/agent/engine/registry.js +6 -0
  9. package/dist/agent/production-agent.js +58 -5
  10. package/dist/app-config/clips.d.ts +43 -0
  11. package/dist/app-config/clips.js +91 -0
  12. package/dist/app-config/index.d.ts +1 -0
  13. package/dist/app-config/index.js +1 -0
  14. package/dist/app-config/schema.d.ts +17 -0
  15. package/dist/app-config/schema.js +2 -0
  16. package/dist/automations/service.d.ts +2 -0
  17. package/dist/automations/service.js +4 -1
  18. package/dist/client/analytics.js +48 -1
  19. package/dist/client/application-state.js +7 -2
  20. package/dist/client/chat/agentkit-protocol.js +12 -3
  21. package/dist/client/client-bootstrap.js +2 -0
  22. package/dist/client/problem-report.d.ts +11 -0
  23. package/dist/client/problem-report.js +19 -0
  24. package/dist/client/recorder.d.ts +88 -0
  25. package/dist/client/recorder.js +585 -0
  26. package/dist/client/route-chunk-recovery.js +4 -1
  27. package/dist/client/sign-out.js +2 -0
  28. package/dist/client/use-action.js +3 -0
  29. package/dist/deploy/workspace-deploy.js +77 -3
  30. package/dist/file-upload/actions/upload-image.d.ts +2 -2
  31. package/dist/integrations/google-docs-poller.js +12 -5
  32. package/dist/integrations/plugin.js +86 -19
  33. package/dist/integrations/request-scope.d.ts +16 -0
  34. package/dist/integrations/request-scope.js +27 -0
  35. package/dist/integrations/webhook-handler.d.ts +2 -0
  36. package/dist/integrations/webhook-handler.js +38 -18
  37. package/dist/jobs/background-automation-runner.d.ts +2 -0
  38. package/dist/jobs/background-automation-runner.js +25 -2
  39. package/dist/jobs/scheduler.js +36 -22
  40. package/dist/mcp/screen-memory-stdio.d.ts +7 -7
  41. package/dist/notifications/routes.d.ts +2 -2
  42. package/dist/observability/routes.d.ts +1 -1
  43. package/dist/org/context.d.ts +12 -0
  44. package/dist/org/context.js +26 -11
  45. package/dist/org/index.d.ts +1 -1
  46. package/dist/problem-report/actions/read-problem-report.d.ts +27 -0
  47. package/dist/problem-report/actions/read-problem-report.js +103 -0
  48. package/dist/problem-report/actions/save-problem-report.d.ts +35 -0
  49. package/dist/problem-report/actions/save-problem-report.js +36 -0
  50. package/dist/problem-report/format.d.ts +7 -0
  51. package/dist/problem-report/format.js +110 -0
  52. package/dist/problem-report/schema.d.ts +41 -0
  53. package/dist/problem-report/schema.js +34 -0
  54. package/dist/provider-api/actions/custom-provider-registration.d.ts +8 -8
  55. package/dist/provider-api/actions/provider-api.d.ts +14 -14
  56. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  57. package/dist/scripts/agent-engines/manage-agent-engine.js +9 -4
  58. package/dist/scripts/agent-engines/set-agent-engine.js +7 -1
  59. package/dist/server/action-discovery.js +11 -0
  60. package/dist/server/action-routes.js +2 -0
  61. package/dist/server/agent-chat-ai-setup.d.ts +2 -3
  62. package/dist/server/agent-chat-ai-setup.js +18 -4
  63. package/dist/server/agent-chat-plugin.js +97 -22
  64. package/dist/server/agent-chat-stream.d.ts +17 -5
  65. package/dist/server/agent-chat-stream.js +15 -0
  66. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  67. package/dist/server/agent-engine-default-model-route.d.ts +2 -2
  68. package/dist/server/agent-engine-default-model-route.js +39 -6
  69. package/dist/server/agent-engine-status-cache.d.ts +4 -0
  70. package/dist/server/agent-engine-status-cache.js +2 -0
  71. package/dist/server/agent-run-context.d.ts +9 -0
  72. package/dist/server/agent-run-context.js +82 -17
  73. package/dist/server/auth.js +6 -1
  74. package/dist/server/builder-browser.js +18 -3
  75. package/dist/server/chatgpt-subscription-oauth.js +12 -17
  76. package/dist/server/core-routes-plugin.d.ts +1 -0
  77. package/dist/server/core-routes-plugin.js +46 -9
  78. package/dist/server/index.d.ts +1 -1
  79. package/dist/server/index.js +1 -1
  80. package/dist/server/loopback.d.ts +1 -0
  81. package/dist/server/loopback.js +30 -0
  82. package/dist/server/origin-allowlist.d.ts +2 -0
  83. package/dist/server/origin-allowlist.js +13 -1
  84. package/dist/server/realtime-token.d.ts +1 -1
  85. package/dist/server/request-context.d.ts +4 -0
  86. package/dist/templates/chat/app/components/layout/Sidebar.tsx +11 -1
  87. package/dist/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +2 -2
  88. package/dist/templates/factory/.agents/skills/review-latest-feedback/references/channel-inventory.md +31 -0
  89. package/dist/triggers/dispatcher.js +117 -31
  90. package/docs/content/recorder.mdx +259 -0
  91. package/docs/content/template-clips-developers.mdx +9 -8
  92. package/docs/content/template-clips-features.mdx +8 -7
  93. package/package.json +7 -4
  94. package/src/templates/chat/app/components/layout/Sidebar.tsx +11 -1
  95. package/src/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +2 -2
  96. package/src/templates/factory/.agents/skills/review-latest-feedback/references/channel-inventory.md +31 -0
  97. package/third-party-licenses/TABLER-ICONS.txt +21 -0
@@ -0,0 +1,41 @@
1
+ import { z } from "zod";
2
+ export declare const RECORDER_EVENT_TYPES: readonly ["action", "state", "nav", "error", "toast", "log"];
3
+ export declare const recorderReportSchema: z.ZodObject<{
4
+ app: z.ZodString;
5
+ build: z.ZodString;
6
+ url: z.ZodString;
7
+ at: z.ZodString;
8
+ reason: z.ZodEnum<{
9
+ error: "error";
10
+ manual: "manual";
11
+ test: "test";
12
+ user: "user";
13
+ }>;
14
+ windowSeconds: z.ZodNumber;
15
+ events: z.ZodArray<z.ZodObject<{
16
+ t: z.ZodNumber;
17
+ at: z.ZodNumber;
18
+ type: z.ZodEnum<{
19
+ action: "action";
20
+ error: "error";
21
+ log: "log";
22
+ nav: "nav";
23
+ state: "state";
24
+ toast: "toast";
25
+ }>;
26
+ name: z.ZodOptional<z.ZodString>;
27
+ ok: z.ZodOptional<z.ZodBoolean>;
28
+ status: z.ZodOptional<z.ZodNumber>;
29
+ errorCode: z.ZodOptional<z.ZodString>;
30
+ ms: z.ZodOptional<z.ZodNumber>;
31
+ requestId: z.ZodOptional<z.ZodString>;
32
+ data: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
33
+ }, z.core.$loose>>;
34
+ watched: z.ZodRecord<z.ZodString, z.ZodUnknown>;
35
+ pending: z.ZodArray<z.ZodObject<{
36
+ type: z.ZodString;
37
+ name: z.ZodString;
38
+ ageMs: z.ZodNumber;
39
+ }, z.core.$loose>>;
40
+ dropped: z.ZodNumber;
41
+ }, z.core.$loose>;
@@ -0,0 +1,34 @@
1
+ import { z } from "zod";
2
+ export const RECORDER_EVENT_TYPES = [
3
+ "action",
4
+ "state",
5
+ "nav",
6
+ "error",
7
+ "toast",
8
+ "log",
9
+ ];
10
+ // Loose objects: a field the recorder adds later is stored, not stripped.
11
+ const recorderEventSchema = z.looseObject({
12
+ t: z.number(),
13
+ at: z.number(),
14
+ type: z.enum(RECORDER_EVENT_TYPES),
15
+ name: z.string().optional(),
16
+ ok: z.boolean().optional(),
17
+ status: z.number().optional(),
18
+ errorCode: z.string().optional(),
19
+ ms: z.number().optional(),
20
+ requestId: z.string().optional(),
21
+ data: z.record(z.string(), z.unknown()).optional(),
22
+ });
23
+ export const recorderReportSchema = z.looseObject({
24
+ app: z.string().max(200),
25
+ build: z.string(),
26
+ url: z.string(),
27
+ at: z.string(),
28
+ reason: z.enum(["user", "error", "test", "manual"]),
29
+ windowSeconds: z.number(),
30
+ events: z.array(recorderEventSchema),
31
+ watched: z.record(z.string(), z.unknown()),
32
+ pending: z.array(z.looseObject({ type: z.string(), name: z.string(), ageMs: z.number() })),
33
+ dropped: z.number(),
34
+ });
@@ -76,7 +76,6 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
76
76
  }>>;
77
77
  }, z.core.$strip>>, {
78
78
  id?: undefined;
79
- provider?: undefined;
80
79
  deleted?: undefined;
81
80
  message?: undefined;
82
81
  providers: {
@@ -89,44 +88,45 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
89
88
  updatedAt: number;
90
89
  }[];
91
90
  count: number;
91
+ provider?: undefined;
92
92
  found?: undefined;
93
93
  registered?: undefined;
94
94
  label?: undefined;
95
95
  } | {
96
96
  id?: undefined;
97
97
  deleted?: undefined;
98
+ count?: undefined;
98
99
  message?: undefined;
99
100
  providers?: undefined;
100
- count?: undefined;
101
101
  found: boolean;
102
102
  provider: import("../custom-registry.js").CustomProviderConfig;
103
103
  registered?: undefined;
104
104
  label?: undefined;
105
105
  } | {
106
- provider?: undefined;
107
106
  deleted?: undefined;
107
+ count?: undefined;
108
108
  message?: undefined;
109
109
  providers?: undefined;
110
- count?: undefined;
110
+ provider?: undefined;
111
111
  found: boolean;
112
112
  id: string;
113
113
  registered?: undefined;
114
114
  label?: undefined;
115
115
  } | {
116
- provider?: undefined;
116
+ count?: undefined;
117
117
  message?: undefined;
118
118
  providers?: undefined;
119
- count?: undefined;
119
+ provider?: undefined;
120
120
  found?: undefined;
121
121
  deleted: boolean;
122
122
  id: string;
123
123
  registered?: undefined;
124
124
  label?: undefined;
125
125
  } | {
126
- provider?: undefined;
127
126
  deleted?: undefined;
128
- providers?: undefined;
129
127
  count?: undefined;
128
+ providers?: undefined;
129
+ provider?: undefined;
130
130
  found?: undefined;
131
131
  registered: boolean;
132
132
  id: string;
@@ -317,9 +317,6 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
317
317
  scope?: "org" | "user" | undefined;
318
318
  }, {
319
319
  message?: undefined;
320
- id?: undefined;
321
- deleted?: undefined;
322
- provider?: undefined;
323
320
  providers: {
324
321
  id: string;
325
322
  label: string;
@@ -330,45 +327,48 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
330
327
  updatedAt: number;
331
328
  }[];
332
329
  count: number;
330
+ provider?: undefined;
333
331
  found?: undefined;
332
+ deleted?: undefined;
334
333
  registered?: undefined;
334
+ id?: undefined;
335
335
  label?: undefined;
336
336
  } | {
337
+ count?: undefined;
337
338
  message?: undefined;
338
- id?: undefined;
339
- deleted?: undefined;
340
339
  providers?: undefined;
341
- count?: undefined;
342
340
  found: boolean;
343
341
  provider: import("../custom-registry.js").CustomProviderConfig;
342
+ deleted?: undefined;
344
343
  registered?: undefined;
344
+ id?: undefined;
345
345
  label?: undefined;
346
346
  } | {
347
+ count?: undefined;
347
348
  message?: undefined;
348
- deleted?: undefined;
349
- provider?: undefined;
350
349
  providers?: undefined;
351
- count?: undefined;
350
+ provider?: undefined;
352
351
  found: boolean;
353
352
  id: string;
353
+ deleted?: undefined;
354
354
  registered?: undefined;
355
355
  label?: undefined;
356
356
  } | {
357
+ count?: undefined;
357
358
  message?: undefined;
358
- provider?: undefined;
359
359
  providers?: undefined;
360
- count?: undefined;
360
+ provider?: undefined;
361
361
  found?: undefined;
362
362
  deleted: boolean;
363
363
  id: string;
364
364
  registered?: undefined;
365
365
  label?: undefined;
366
366
  } | {
367
- deleted?: undefined;
368
- provider?: undefined;
369
- providers?: undefined;
370
367
  count?: undefined;
368
+ providers?: undefined;
369
+ provider?: undefined;
371
370
  found?: undefined;
371
+ deleted?: undefined;
372
372
  registered: boolean;
373
373
  id: string;
374
374
  label: string;
@@ -73,6 +73,7 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
73
73
  offset?: unknown;
74
74
  limit?: unknown;
75
75
  }, {
76
+ deleted?: undefined;
76
77
  jobs: {
77
78
  id: string;
78
79
  name: string;
@@ -83,7 +84,6 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
83
84
  updatedAt: string;
84
85
  }[];
85
86
  total: number;
86
- deleted?: undefined;
87
87
  jobId?: undefined;
88
88
  } | {
89
89
  jobs?: undefined;
@@ -91,9 +91,9 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
91
91
  deleted: boolean;
92
92
  jobId: string;
93
93
  } | {
94
+ deleted?: undefined;
94
95
  jobs?: undefined;
95
96
  total?: undefined;
96
- deleted?: undefined;
97
97
  jobId?: undefined;
98
98
  hits: Record<string, unknown>[];
99
99
  offset: number;
@@ -3,7 +3,7 @@ import { CHATGPT_SUBSCRIPTION_ENGINE_NAME } from "../../agent/chatgpt-subscripti
3
3
  import { listChatGPTSubscriptionModels } from "../../agent/engine/chatgpt-subscription-engine.js";
4
4
  import { getAgentEngineEntry, isAgentEnginePackageInstalled, normalizeModelForEngine, resolveEngineAcceptsCustomModels, resolveEnginePreservesCustomModels, registerBuiltinEngines, } from "../../agent/engine/index.js";
5
5
  import { defaultModelMessagesForUser } from "../../localization/default-model-messages.js";
6
- import { getRequestOrgId, getRequestUserEmail, } from "../../server/request-context.js";
6
+ import { getRequestContext, getRequestOrgId, getRequestUserEmail, } from "../../server/request-context.js";
7
7
  import { run as runList } from "./list-agent-engines.js";
8
8
  import { run as runSet, resolveDefaultModelEffective, effectiveConfigurationMessage, } from "./set-agent-engine.js";
9
9
  import { run as runTest } from "./test-agent-engine.js";
@@ -46,9 +46,11 @@ export const tool = {
46
46
  };
47
47
  function currentContext() {
48
48
  try {
49
+ const context = getRequestContext();
49
50
  return {
50
51
  userEmail: getRequestUserEmail(),
51
52
  orgId: getRequestOrgId(),
53
+ ...(context?.orgScope === "personal" ? { orgScope: "personal" } : {}),
52
54
  };
53
55
  }
54
56
  catch {
@@ -64,7 +66,7 @@ async function runGetAppDefault(args) {
64
66
  return "Error: appId is required";
65
67
  const ctx = currentContext();
66
68
  const settings = await readAgentAppModelDefaultSettings(ctx, appId);
67
- const canUpdate = await canUpdateAgentAppModelDefaultSettings(ctx.userEmail, ctx.orgId);
69
+ const canUpdate = await canUpdateAgentAppModelDefaultSettings(ctx.userEmail, ctx.orgId, ctx.orgScope);
68
70
  return JSON.stringify({ ok: true, ...settings, canUpdate }, null, 2);
69
71
  }
70
72
  async function runSetAppDefault(args) {
@@ -79,6 +81,9 @@ async function runSetAppDefault(args) {
79
81
  if (!model)
80
82
  return "Error: model is required";
81
83
  const ctx = currentContext();
84
+ if (!ctx.orgId && ctx.orgScope !== "personal") {
85
+ return "Error: Organization scope could not be resolved.";
86
+ }
82
87
  if (engine === CHATGPT_SUBSCRIPTION_ENGINE_NAME) {
83
88
  if (ctx.orgId) {
84
89
  return "Error: ChatGPT plan access is personal and cannot be selected as an organization default.";
@@ -108,7 +113,7 @@ async function runSetAppDefault(args) {
108
113
  acceptsCustomModels,
109
114
  preserveCustomModels,
110
115
  });
111
- const canUpdate = await canUpdateAgentAppModelDefaultSettings(ctx.userEmail, ctx.orgId);
116
+ const canUpdate = await canUpdateAgentAppModelDefaultSettings(ctx.userEmail, ctx.orgId, ctx.orgScope);
112
117
  if (!canUpdate) {
113
118
  return ctx.orgId
114
119
  ? "Error: Only organization owners and admins can change app model defaults."
@@ -141,7 +146,7 @@ async function runResetAppDefault(args) {
141
146
  if (!appId)
142
147
  return "Error: appId is required";
143
148
  const ctx = currentContext();
144
- const canUpdate = await canUpdateAgentAppModelDefaultSettings(ctx.userEmail, ctx.orgId);
149
+ const canUpdate = await canUpdateAgentAppModelDefaultSettings(ctx.userEmail, ctx.orgId, ctx.orgScope);
145
150
  if (!canUpdate) {
146
151
  return ctx.orgId
147
152
  ? "Error: Only organization owners and admins can reset app model defaults."
@@ -13,7 +13,7 @@ import { getAppConfig } from "../../app-config/index.js";
13
13
  import { CHATGPT_SUBSCRIPTION_LAB } from "../../labs/core-labs.js";
14
14
  import { getUserLabEnabled } from "../../labs/store.js";
15
15
  import { defaultModelMessagesForUser } from "../../localization/default-model-messages.js";
16
- import { getRequestOrgId, getRequestUserEmail, } from "../../server/request-context.js";
16
+ import { getRequestContext, getRequestOrgId, getRequestUserEmail, } from "../../server/request-context.js";
17
17
  export const tool = {
18
18
  description: 'Set only the organization\'s default AI engine and model (or a no-organization user\'s personal default). Preserve every app override and explicit chat/automation model. For an app default, use manage-agent-engine with action="set-app-default"; inheritance requires action="reset-app-default". If the user\'s requested scope is ambiguous, clarify organization/personal versus app before changing anything. The result separates the saved default from the current app\'s effective model. Only organization owners and admins can change it. Use manage-agent-engine with action="list" first to see options and canUpdateDefault.',
19
19
  parameters: {
@@ -33,6 +33,9 @@ export const tool = {
33
33
  };
34
34
  export const DEFAULT_MODEL_ADMIN_REQUIRED_ERROR_CODE = "default_model_admin_required";
35
35
  export async function resolveDefaultModelEffective(ctx, appId, planned = {}) {
36
+ if (!ctx.orgId && ctx.orgScope !== "personal") {
37
+ throw new Error("Organization scope could not be resolved.");
38
+ }
36
39
  const credentialIdentity = ctx.userEmail
37
40
  ? { userEmail: ctx.userEmail, orgId: ctx.orgId }
38
41
  : undefined;
@@ -92,6 +95,9 @@ export function effectiveConfigurationMessage(effective, messages) {
92
95
  export async function selectDefaultAgentEngine(input, meta, ctx = {
93
96
  userEmail: getRequestUserEmail(),
94
97
  orgId: getRequestOrgId(),
98
+ ...(getRequestContext()?.orgScope === "personal"
99
+ ? { orgScope: "personal" }
100
+ : {}),
95
101
  }) {
96
102
  registerBuiltinEngines();
97
103
  const engineName = input.engine?.trim();
@@ -386,6 +386,9 @@ export const ALWAYS_ON_CORE_ACTIONS = new Set([
386
386
  "set-tool-approval-policy",
387
387
  // The client's same-tick GET batching depends on it, so it cannot be gated.
388
388
  "get-actions-batch",
389
+ // The shared Report a problem entry calls these in every app.
390
+ "save-problem-report",
391
+ "read-problem-report",
389
392
  ]);
390
393
  export async function mergeCoreSharingActions(registry) {
391
394
  const entries = [
@@ -469,6 +472,14 @@ export async function mergeCoreSharingActions(registry) {
469
472
  () => import("../agent/actions/get-agentkit-capabilities.js"),
470
473
  ],
471
474
  ["upload-image", () => import("../file-upload/actions/upload-image.js")],
475
+ [
476
+ "save-problem-report",
477
+ () => import("../problem-report/actions/save-problem-report.js"),
478
+ ],
479
+ [
480
+ "read-problem-report",
481
+ () => import("../problem-report/actions/read-problem-report.js"),
482
+ ],
472
483
  [
473
484
  "get-file-storage",
474
485
  () => import("../file-upload/actions/get-file-storage.js"),
@@ -48,6 +48,7 @@ function currentBuildId() {
48
48
  }
49
49
  import { isLoopbackRequest, registerAuthPublicPaths } from "./auth.js";
50
50
  import { getH3App } from "./framework-request-handler.js";
51
+ import { isDirectLoopbackRequest } from "./loopback.js";
51
52
  import { getVerifiedServiceIdentityFromEvent, getRequestIdentityAuthenticatedAtMs, getRequestIdentitySessionToken, hasExplicitPersonalOrgScope, markExplicitPersonalOrgScope, runWithRequestContext, } from "./request-context.js";
52
53
  const ROUTE_PREFIX = ACTION_ROUTE_PREFIX;
53
54
  const WEBMCP_ACTION_ROUTE_PREFIX = "/_agent-native/webmcp/actions";
@@ -815,6 +816,7 @@ function mountActionRoutesInternal(nitroApp, actions, options) {
815
816
  requestOrigin: getForwardedRequestOrigin(event),
816
817
  federationMembershipValidated: isFederationMembershipValidatedForEvent(event, userEmail, orgId),
817
818
  isLoopbackRequest: isLoopbackRequest(event),
819
+ isDirectLoopbackRequest: isDirectLoopbackRequest(event),
818
820
  }, async () => {
819
821
  if (typeof entry.maxBodyBytes === "number" && method !== "GET") {
820
822
  const clRaw = getHeader(event, "content-length");
@@ -9,9 +9,8 @@ export declare function isBuilderChatSetupReady(input: {
9
9
  }): boolean;
10
10
  /**
11
11
  * Chat accepts the Builder gateway/OAuth lane, a usable BYOK API key, or a
12
- * configured OpenAI-compatible/Ollama endpoint. Engine selection by itself is
13
- * not readiness: ChatGPT subscription auth and untyped engine names do not
14
- * qualify.
12
+ * configured OpenAI-compatible/Ollama endpoint, or a usable personal ChatGPT
13
+ * subscription account. Engine selection by itself is not readiness.
15
14
  */
16
15
  export declare function isAgentChatAiSetupReady(input?: {
17
16
  status?: AgentEngineStatusResult;
@@ -3,8 +3,9 @@ import { CHATGPT_SUBSCRIPTION_ENGINE_NAME } from "../agent/chatgpt-subscription-
3
3
  import { OLLAMA_BASE_URL_ENV_VAR, OPENAI_BASE_URL_ENV_VAR, PROVIDER_ENV_VARS, } from "../agent/engine/provider-env-vars.js";
4
4
  import { getAgentEngineEntry } from "../agent/engine/registry.js";
5
5
  import { hasUsableBuilderOAuthSessionForReadiness } from "./builder-oauth.js";
6
+ import { hasChatGPTSubscriptionCredential } from "./chatgpt-subscription-oauth.js";
6
7
  import { assertCredentialStoreReadable, getProviderCredentialAuthFailure, prefetchSecrets, resolveBuilderGatewayCredentialsDetailed, resolveBuilderPrivateKey, resolveSecretDetailed, } from "./credential-provider.js";
7
- import { getRequestOrgId, getRequestUserEmail } from "./request-context.js";
8
+ import { getRequestContext, getRequestOrgId, getRequestUserEmail, } from "./request-context.js";
8
9
  export const AGENT_CHAT_AI_SETUP_REQUIRED_CODE = "AGENT_CHAT_AI_SETUP_REQUIRED";
9
10
  export function isBuilderChatSetupReady(input) {
10
11
  return Boolean(input.oauthSessionUsable ||
@@ -13,9 +14,8 @@ export function isBuilderChatSetupReady(input) {
13
14
  }
14
15
  /**
15
16
  * Chat accepts the Builder gateway/OAuth lane, a usable BYOK API key, or a
16
- * configured OpenAI-compatible/Ollama endpoint. Engine selection by itself is
17
- * not readiness: ChatGPT subscription auth and untyped engine names do not
18
- * qualify.
17
+ * configured OpenAI-compatible/Ollama endpoint, or a usable personal ChatGPT
18
+ * subscription account. Engine selection by itself is not readiness.
19
19
  */
20
20
  export async function isAgentChatAiSetupReady(input) {
21
21
  if (input?.status && input.detectFromUserSecrets) {
@@ -42,6 +42,10 @@ export async function isAgentChatAiSetupReady(input) {
42
42
  return true;
43
43
  unreadable ||= readiness.unreadable;
44
44
  }
45
+ const ownerEmail = getRequestUserEmail();
46
+ if (ownerEmail && (await hasEligibleChatGPTSubscription(ownerEmail))) {
47
+ return true;
48
+ }
45
49
  if (unreadable)
46
50
  throwAgentChatSetupReadUnavailable();
47
51
  return false;
@@ -103,8 +107,18 @@ export async function isAgentChatAiSetupReady(input) {
103
107
  assertCredentialStoreReadable(unreadable);
104
108
  throwAgentChatSetupReadUnavailable();
105
109
  }
110
+ if (ownerEmail && (await hasEligibleChatGPTSubscription(ownerEmail))) {
111
+ return true;
112
+ }
106
113
  return false;
107
114
  }
115
+ async function hasEligibleChatGPTSubscription(ownerEmail) {
116
+ const requestContext = getRequestContext();
117
+ if (getRequestOrgId() || requestContext?.orgScope !== "personal") {
118
+ return false;
119
+ }
120
+ return hasChatGPTSubscriptionCredential(ownerEmail);
121
+ }
108
122
  async function checkProviderEntryReadiness(entry) {
109
123
  if (!entry || !isChatSetupProviderEntry(entry)) {
110
124
  return { usable: false, unreadable: false };