copilotkit 4.12.0 → 4.13.0

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 (80) hide show
  1. package/README.md +10 -0
  2. package/cli-build-info.json +8 -8
  3. package/index.js +1015 -123
  4. package/onboarding/index.json +20 -2
  5. package/onboarding/prompts/authenticate/start.md +38 -33
  6. package/onboarding/prompts/conversion/plan.md +3 -3
  7. package/onboarding/prompts/credentials/finalize-plan.md +7 -7
  8. package/onboarding/prompts/credentials/plan.md +26 -20
  9. package/onboarding/prompts/credentials/settle-credentials.md +8 -8
  10. package/onboarding/prompts/credentials/write-plan.md +19 -6
  11. package/onboarding/prompts/fallback/best-effort.md +6 -6
  12. package/onboarding/prompts/feature/a2ui/implement.md +6 -6
  13. package/onboarding/prompts/feature/a2ui/proof.md +6 -6
  14. package/onboarding/prompts/feature/a2ui/start.md +7 -7
  15. package/onboarding/prompts/feature/channels/implement.md +67 -12
  16. package/onboarding/prompts/feature/channels/proof.md +13 -6
  17. package/onboarding/prompts/feature/channels/start.md +27 -10
  18. package/onboarding/prompts/feature/chat-suggestions/implement.md +6 -6
  19. package/onboarding/prompts/feature/chat-suggestions/proof.md +6 -6
  20. package/onboarding/prompts/feature/chat-suggestions/start.md +7 -7
  21. package/onboarding/prompts/feature/complete.md +1 -1
  22. package/onboarding/prompts/feature/learning/implement.md +15 -15
  23. package/onboarding/prompts/feature/learning/proof.md +7 -7
  24. package/onboarding/prompts/feature/learning/start.md +8 -8
  25. package/onboarding/prompts/feature/open-generative-ui/implement.md +6 -6
  26. package/onboarding/prompts/feature/open-generative-ui/proof.md +6 -6
  27. package/onboarding/prompts/feature/open-generative-ui/start.md +7 -7
  28. package/onboarding/prompts/feature/realtime-sync/implement.md +7 -7
  29. package/onboarding/prompts/feature/realtime-sync/proof.md +6 -6
  30. package/onboarding/prompts/feature/realtime-sync/start.md +6 -6
  31. package/onboarding/prompts/feature/rich-threads/implement.md +8 -8
  32. package/onboarding/prompts/feature/rich-threads/proof.md +6 -6
  33. package/onboarding/prompts/feature/rich-threads/start.md +6 -6
  34. package/onboarding/prompts/feature/stop.md +2 -2
  35. package/onboarding/prompts/feature/voice/implement.md +6 -6
  36. package/onboarding/prompts/feature/voice/proof.md +6 -6
  37. package/onboarding/prompts/feature/voice/start.md +7 -7
  38. package/onboarding/prompts/framework/ag2.md +2 -2
  39. package/onboarding/prompts/framework/agno.md +2 -2
  40. package/onboarding/prompts/framework/built-in.md +4 -2
  41. package/onboarding/prompts/framework/claude-sdk-python.md +2 -2
  42. package/onboarding/prompts/framework/claude-sdk-typescript.md +2 -2
  43. package/onboarding/prompts/framework/crewai-flows.md +2 -2
  44. package/onboarding/prompts/framework/deep-agents.md +5 -2
  45. package/onboarding/prompts/framework/google-adk.md +4 -2
  46. package/onboarding/prompts/framework/langgraph-fastapi.md +4 -3
  47. package/onboarding/prompts/framework/langgraph-python.md +6 -2
  48. package/onboarding/prompts/framework/langgraph-typescript.md +6 -2
  49. package/onboarding/prompts/framework/llamaindex.md +2 -2
  50. package/onboarding/prompts/framework/mastra.md +4 -2
  51. package/onboarding/prompts/framework/ms-agent-dotnet.md +4 -2
  52. package/onboarding/prompts/framework/ms-agent-harness-dotnet.md +2 -2
  53. package/onboarding/prompts/framework/ms-agent-python.md +4 -2
  54. package/onboarding/prompts/framework/pydantic-ai.md +2 -2
  55. package/onboarding/prompts/framework/strands-python.md +4 -2
  56. package/onboarding/prompts/framework/strands-typescript.md +4 -2
  57. package/onboarding/prompts/frontend/angular.md +3 -3
  58. package/onboarding/prompts/frontend/nextjs.md +3 -3
  59. package/onboarding/prompts/frontend/plan.md +21 -10
  60. package/onboarding/prompts/frontend/react-native.md +2 -2
  61. package/onboarding/prompts/frontend/react-spa.md +2 -2
  62. package/onboarding/prompts/frontend/vue.md +2 -2
  63. package/onboarding/prompts/implementation/build-and-validate.md +33 -15
  64. package/onboarding/prompts/proof/complete.md +35 -16
  65. package/onboarding/prompts/proof/oss-baseline.md +5 -5
  66. package/onboarding/prompts/proof/round-trip.md +23 -12
  67. package/onboarding/prompts/research/gather.md +12 -102
  68. package/onboarding/prompts/research/merge.md +60 -0
  69. package/onboarding/prompts/research/preflight.md +75 -0
  70. package/onboarding/prompts/research/route.md +28 -4
  71. package/onboarding/prompts/starter/clone.md +5 -5
  72. package/onboarding/prompts/stopped/run-failed.md +2 -2
  73. package/onboarding/prompts/subagent/create-plan.md +18 -1
  74. package/onboarding/prompts/subagent/implement-and-validate.md +30 -0
  75. package/onboarding/prompts/subagent/inspect-repository.md +1 -1
  76. package/onboarding/prompts/subagent/prove-oss-baseline.md +1 -1
  77. package/onboarding/prompts/subagent/prove-round-trip.md +17 -7
  78. package/onboarding/prompts/unsupported/no-validated-path.md +2 -2
  79. package/package.json +4 -1
  80. package/release/release-tool.js +1 -1
package/index.js CHANGED
@@ -109,14 +109,14 @@ function getTelemetryEndpointUrl() {
109
109
  }
110
110
  function getBuildInfo() {
111
111
  return {
112
- version: true ? "4.12.0" : "dev",
113
- buildNumber: true ? "35617651318" : "dev",
114
- commitSha: true ? "894cde3a9735b1605afef07a1250bef02a123ca4" : "dev",
112
+ version: true ? "4.13.0" : "dev",
113
+ buildNumber: true ? "35742767211" : "dev",
114
+ commitSha: true ? "addb7285609bab57a4a8ef12d73351fdf5dfaf3f" : "dev",
115
115
  copilotKitCommit: getTemplateRef()
116
116
  };
117
117
  }
118
118
  function getTemplateRef() {
119
- return true ? "0048ba241fdf14a9036cdad11a4f31aa021a9c8d" : "main";
119
+ return true ? "1e13b4945b44c6afa2e398a0c9935415d4aa7577" : "main";
120
120
  }
121
121
  function getC15tBackendUrl() {
122
122
  return true ? "https://calm-hazelnut-joy-copilotkit.inth.app" : "";
@@ -26858,6 +26858,66 @@ var init_zod = __esm({
26858
26858
  }
26859
26859
  });
26860
26860
 
26861
+ // libs/ops-contracts/src/billing.ts
26862
+ var billingProviderSchema, billingContextResponseSchema, paidSelfServicePlanCodeSchema, createCheckoutSessionRequestSchema, createCheckoutSessionResponseSchema, expireCheckoutSessionResponseSchema, checkoutReturnResponseSchema, createPortalSessionRequestSchema, createPortalSessionResponseSchema;
26863
+ var init_billing = __esm({
26864
+ "libs/ops-contracts/src/billing.ts"() {
26865
+ "use strict";
26866
+ init_zod();
26867
+ billingProviderSchema = external_exports.enum(["clerk", "stripe"]);
26868
+ billingContextResponseSchema = external_exports.object({
26869
+ billingProvider: billingProviderSchema
26870
+ }).strict();
26871
+ paidSelfServicePlanCodeSchema = external_exports.enum([
26872
+ "pro",
26873
+ "team",
26874
+ "team_self_hosted"
26875
+ ]);
26876
+ createCheckoutSessionRequestSchema = external_exports.object({
26877
+ planCode: paidSelfServicePlanCodeSchema,
26878
+ // Omission preserves the prebuilt checkout for older deployed frontends.
26879
+ uiMode: external_exports.literal("elements").optional(),
26880
+ // An old request must never expire a checkout it has not observed.
26881
+ replacesCheckoutSessionId: external_exports.string().min(1).max(255).startsWith("cs_").optional()
26882
+ }).strict();
26883
+ createCheckoutSessionResponseSchema = external_exports.union([
26884
+ external_exports.object({
26885
+ clientSecret: external_exports.string().min(1),
26886
+ sessionId: external_exports.string().min(1).max(255).startsWith("cs_").optional(),
26887
+ // Present only when resuming an Elements checkout from an earlier attempt.
26888
+ checkoutAttemptId: external_exports.string().uuid().optional()
26889
+ }).strict(),
26890
+ external_exports.object({
26891
+ state: external_exports.literal("confirmation_required"),
26892
+ sessionId: external_exports.string().min(1),
26893
+ checkoutAttemptId: external_exports.string().uuid().optional()
26894
+ }).strict(),
26895
+ external_exports.object({
26896
+ state: external_exports.literal("recovery_required"),
26897
+ sessionId: external_exports.string().min(1).max(255).startsWith("cs_"),
26898
+ planCode: paidSelfServicePlanCodeSchema
26899
+ }).strict()
26900
+ ]);
26901
+ expireCheckoutSessionResponseSchema = external_exports.object({ state: external_exports.literal("expired") }).strict();
26902
+ checkoutReturnResponseSchema = external_exports.discriminatedUnion("state", [
26903
+ external_exports.object({
26904
+ state: external_exports.literal("paid"),
26905
+ planCode: paidSelfServicePlanCodeSchema,
26906
+ quantity: external_exports.number().int().positive()
26907
+ }).strict(),
26908
+ external_exports.object({ state: external_exports.literal("processing") }).strict(),
26909
+ external_exports.object({ state: external_exports.literal("expired") }).strict()
26910
+ ]);
26911
+ createPortalSessionRequestSchema = external_exports.object({}).strict();
26912
+ createPortalSessionResponseSchema = external_exports.object({
26913
+ portalUrl: external_exports.string().url().refine((value) => {
26914
+ const url4 = new URL(value);
26915
+ return url4.origin === "https://billing.stripe.com" && !url4.username && !url4.password;
26916
+ }, "Expected a Stripe Customer Portal URL.")
26917
+ }).strict();
26918
+ }
26919
+ });
26920
+
26861
26921
  // libs/license-catalog/src/index.ts
26862
26922
  function isFeatureId(feature) {
26863
26923
  return FEATURE_IDS.includes(feature);
@@ -27349,7 +27409,10 @@ __export(src_exports, {
27349
27409
  adminEnterpriseSubscriptionListResponseSchema: () => adminEnterpriseSubscriptionListResponseSchema,
27350
27410
  adminEnterpriseSubscriptionResponseSchema: () => adminEnterpriseSubscriptionResponseSchema,
27351
27411
  adminEnterpriseSubscriptionSchema: () => adminEnterpriseSubscriptionSchema,
27412
+ billingContextResponseSchema: () => billingContextResponseSchema,
27413
+ billingProviderSchema: () => billingProviderSchema,
27352
27414
  catalogFeatureMapSchema: () => catalogFeatureMapSchema,
27415
+ checkoutReturnResponseSchema: () => checkoutReturnResponseSchema,
27353
27416
  cliProductCredentialActorSchema: () => cliProductCredentialActorSchema,
27354
27417
  cliProductCredentialCapabilitySchema: () => cliProductCredentialCapabilitySchema,
27355
27418
  cliProductCredentialExchangeResponseSchema: () => cliProductCredentialExchangeResponseSchema,
@@ -27360,8 +27423,12 @@ __export(src_exports, {
27360
27423
  cliTelemetryIdentityResponseSchema: () => cliTelemetryIdentityResponseSchema,
27361
27424
  cliTelemetryProjectIdSchema: () => cliTelemetryProjectIdSchema,
27362
27425
  createAdminEnterpriseSubscriptionRequestSchema: () => createAdminEnterpriseSubscriptionRequestSchema,
27426
+ createCheckoutSessionRequestSchema: () => createCheckoutSessionRequestSchema,
27427
+ createCheckoutSessionResponseSchema: () => createCheckoutSessionResponseSchema,
27363
27428
  createHostedApiKeyRequestSchema: () => createHostedApiKeyRequestSchema,
27364
27429
  createHostedProjectRequestSchema: () => createHostedProjectRequestSchema,
27430
+ createPortalSessionRequestSchema: () => createPortalSessionRequestSchema,
27431
+ createPortalSessionResponseSchema: () => createPortalSessionResponseSchema,
27365
27432
  currentEntitlementResponseSchema: () => currentEntitlementResponseSchema,
27366
27433
  currentWaitlistResponseSchema: () => currentWaitlistResponseSchema,
27367
27434
  customerEffectiveEntitlementSchema: () => customerEffectiveEntitlementSchema,
@@ -27373,6 +27440,7 @@ __export(src_exports, {
27373
27440
  entitlementGrantedEventSchema: () => entitlementGrantedEventSchema,
27374
27441
  entitlementSourceSchema: () => entitlementSourceSchema,
27375
27442
  entitlementStateSchema: () => entitlementStateSchema,
27443
+ expireCheckoutSessionResponseSchema: () => expireCheckoutSessionResponseSchema,
27376
27444
  featureValueSchema: () => featureValueSchema,
27377
27445
  hostedProjectApiKeyDeleteResponseSchema: () => hostedProjectApiKeyDeleteResponseSchema,
27378
27446
  hostedProjectApiKeyListItemSchema: () => hostedProjectApiKeyListItemSchema,
@@ -27413,6 +27481,7 @@ __export(src_exports, {
27413
27481
  organizationPlanSelectionGateSchema: () => organizationPlanSelectionGateSchema,
27414
27482
  organizationPlanSelectionRequestSchema: () => organizationPlanSelectionRequestSchema,
27415
27483
  organizationPlanSelectionResponseSchema: () => organizationPlanSelectionResponseSchema,
27484
+ paidSelfServicePlanCodeSchema: () => paidSelfServicePlanCodeSchema,
27416
27485
  parseAdminEnterpriseSubscriptionDetailResponse: () => parseAdminEnterpriseSubscriptionDetailResponse,
27417
27486
  parseAdminEnterpriseSubscriptionListResponse: () => parseAdminEnterpriseSubscriptionListResponse,
27418
27487
  parseAdminEnterpriseSubscriptionResponse: () => parseAdminEnterpriseSubscriptionResponse,
@@ -27519,6 +27588,7 @@ var init_src2 = __esm({
27519
27588
  "libs/ops-contracts/src/index.ts"() {
27520
27589
  "use strict";
27521
27590
  init_zod();
27591
+ init_billing();
27522
27592
  init_src();
27523
27593
  init_hosted_project();
27524
27594
  init_managed_navigation();
@@ -27778,7 +27848,8 @@ var init_src2 = __esm({
27778
27848
  token: true
27779
27849
  });
27780
27850
  cliProductCredentialTokenPayloadSchema = cliProductCredentialPayloadSchema.extend({
27781
- organizationName: external_exports.string().trim().min(1).optional()
27851
+ organizationName: external_exports.string().trim().min(1).optional(),
27852
+ organizationSlug: external_exports.string().trim().min(1).optional()
27782
27853
  }).strict();
27783
27854
  cliProductCredentialExchangeResponseSchema = external_exports.object({
27784
27855
  productCredential: cliProductCredentialSchema
@@ -28217,6 +28288,9 @@ function normalizeCodingAgent(_value) {
28217
28288
  const normalized = _value?.trim().toLowerCase() ?? "";
28218
28289
  return CODING_AGENT_PATTERN.test(normalized) ? normalized : "unknown";
28219
28290
  }
28291
+ function codingAgentProperty(value) {
28292
+ return value === void 0 || value.trim() === "" ? {} : { coding_agent: normalizeCodingAgent(value) };
28293
+ }
28220
28294
  function resolveOnboardingRepositoryRoot(cwd2) {
28221
28295
  const canonicalCwd = canonicalizeDir(cwd2);
28222
28296
  return findRepositoryRoot(canonicalCwd) ?? canonicalCwd;
@@ -28242,15 +28316,24 @@ function readBoundRun(store, root2) {
28242
28316
  ...intent === void 0 ? {} : { intent }
28243
28317
  };
28244
28318
  }
28245
- function resolveAnchoredRoot(dependencies) {
28319
+ function continuesAnchoredRun(store, root2, bound, lookup) {
28320
+ if (lookup.runId !== void 0 && lookup.runId !== bound.runId)
28321
+ return false;
28322
+ const stored = readStoredRoute(store, stateKey("route", root2));
28323
+ return !(stored?.runId === bound.runId && stored.ended === true);
28324
+ }
28325
+ function resolveAnchoredRoot(dependencies, lookup = {}) {
28246
28326
  const start = resolveOnboardingRepositoryRoot(dependencies.cwd);
28247
28327
  const home = canonicalizeDir(homedir3());
28248
28328
  const filesystemRoot = parse5(start).root;
28249
28329
  let candidate = start;
28250
28330
  while (true) {
28251
28331
  const bound = readBoundRun(dependencies.store, candidate);
28252
- if (bound.state === "live" && bound.anchored)
28253
- return candidate;
28332
+ if (bound.state === "live" && bound.anchored) {
28333
+ if (candidate === start)
28334
+ return candidate;
28335
+ return continuesAnchoredRun(dependencies.store, candidate, bound, lookup) ? candidate : start;
28336
+ }
28254
28337
  const parent = dirname3(candidate);
28255
28338
  if (candidate === filesystemRoot || parent === candidate || parent === home || parent === filesystemRoot) {
28256
28339
  return start;
@@ -28402,9 +28485,15 @@ function startOnboardingRun(dependencies, requestedRunId, requestedIntent) {
28402
28485
  if (requestedIntent !== void 0 && !ONBOARDING_INTENT_PATTERN.test(requestedIntent)) {
28403
28486
  throw new Error("Requested onboarding intent is invalid");
28404
28487
  }
28405
- const root2 = resolveAnchoredRoot(dependencies);
28406
- const bound = readBoundRun(dependencies.store, root2);
28407
28488
  const validRequestedRun = requestedRunId !== void 0 && RUN_ID_PATTERN.test(requestedRunId) ? requestedRunId : void 0;
28489
+ const project = resolveOnboardingRepositoryRoot(dependencies.cwd);
28490
+ const anchored = resolveAnchoredRoot(dependencies, {
28491
+ ...validRequestedRun === void 0 ? {} : { runId: validRequestedRun }
28492
+ });
28493
+ const anchoredBinding = readBoundRun(dependencies.store, anchored);
28494
+ const continuesAnchor = anchoredBinding.state === "live" && (validRequestedRun === void 0 ? anchoredBinding.intent === requestedIntent : validRequestedRun === anchoredBinding.runId);
28495
+ const root2 = anchored === project || continuesAnchor ? anchored : project;
28496
+ const bound = root2 === anchored ? anchoredBinding : readBoundRun(dependencies.store, root2);
28408
28497
  const continuesBoundRun = bound.state === "live" && bound.intent === requestedIntent;
28409
28498
  const runId = validRequestedRun ?? (continuesBoundRun ? bound.runId : mintRunId(dependencies));
28410
28499
  dependencies.store.set(stateKey("run", root2), {
@@ -66269,7 +66358,7 @@ var require_websocket = __commonJS({
66269
66358
  var http4 = __require("http");
66270
66359
  var net = __require("net");
66271
66360
  var tls = __require("tls");
66272
- var { randomBytes: randomBytes4, createHash: createHash8 } = __require("crypto");
66361
+ var { randomBytes: randomBytes4, createHash: createHash9 } = __require("crypto");
66273
66362
  var { Duplex, Readable: Readable5 } = __require("stream");
66274
66363
  var { URL: URL7 } = __require("url");
66275
66364
  var PerMessageDeflate2 = require_permessage_deflate();
@@ -66949,7 +67038,7 @@ var require_websocket = __commonJS({
66949
67038
  abortHandshake(websocket, socket, "Invalid Upgrade header");
66950
67039
  return;
66951
67040
  }
66952
- const digest = createHash8("sha1").update(key + GUID).digest("base64");
67041
+ const digest = createHash9("sha1").update(key + GUID).digest("base64");
66953
67042
  if (res.headers["sec-websocket-accept"] !== digest) {
66954
67043
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
66955
67044
  return;
@@ -67336,7 +67425,7 @@ var require_websocket_server = __commonJS({
67336
67425
  var EventEmitter4 = __require("events");
67337
67426
  var http4 = __require("http");
67338
67427
  var { Duplex } = __require("stream");
67339
- var { createHash: createHash8 } = __require("crypto");
67428
+ var { createHash: createHash9 } = __require("crypto");
67340
67429
  var extension2 = require_extension();
67341
67430
  var PerMessageDeflate2 = require_permessage_deflate();
67342
67431
  var subprotocol2 = require_subprotocol();
@@ -67645,7 +67734,7 @@ var require_websocket_server = __commonJS({
67645
67734
  }
67646
67735
  if (this._state > RUNNING)
67647
67736
  return abortHandshake(socket, 503);
67648
- const digest = createHash8("sha1").update(key + GUID).digest("base64");
67737
+ const digest = createHash9("sha1").update(key + GUID).digest("base64");
67649
67738
  const headers = [
67650
67739
  "HTTP/1.1 101 Switching Protocols",
67651
67740
  "Upgrade: websocket",
@@ -91204,6 +91293,7 @@ __export(telemetry_exports, {
91204
91293
  getTelemetry: () => getTelemetry,
91205
91294
  hasStandaloneTelemetryIdentityConsent: () => hasStandaloneTelemetryIdentityConsent,
91206
91295
  linkConsentSubjectToUser: () => linkConsentSubjectToUser,
91296
+ recordAbandonedInvocation: () => recordAbandonedInvocation,
91207
91297
  recordTelemetryEvent: () => recordTelemetryEvent,
91208
91298
  resolveReturnedOutcome: () => resolveReturnedOutcome,
91209
91299
  submitTelemetryEvent: () => submitTelemetryEvent,
@@ -91321,7 +91411,52 @@ function recordTelemetryEvent(event) {
91321
91411
  });
91322
91412
  if (!gate.send)
91323
91413
  return;
91324
- getTelemetry().recordEvent(withProjectIdentity(event));
91414
+ for (const paired of pairCommandBookends(event)) {
91415
+ getTelemetry().recordEvent(withProjectIdentity(paired));
91416
+ }
91417
+ }
91418
+ function isCommandLifecycle(event) {
91419
+ return (event.event === void 0 || event.event === CLI_TELEMETRY_EVENT_NAME) && event.properties.outcome !== void 0;
91420
+ }
91421
+ function pairCommandBookends(event) {
91422
+ if (!isCommandLifecycle(event))
91423
+ return [event];
91424
+ if (event.properties.outcome === "started") {
91425
+ if (openInvocation !== null || invocationSettled)
91426
+ return [];
91427
+ openInvocation = { properties: event.properties, startedAt: Date.now() };
91428
+ return [event];
91429
+ }
91430
+ if (invocationSettled)
91431
+ return [];
91432
+ invocationSettled = true;
91433
+ if (openInvocation !== null) {
91434
+ openInvocation = null;
91435
+ return [event];
91436
+ }
91437
+ const opening = { ...event.properties };
91438
+ delete opening.outcome;
91439
+ delete opening.error_code;
91440
+ delete opening.duration_ms;
91441
+ return [
91442
+ { ...event, properties: { ...opening, outcome: "started" } },
91443
+ event
91444
+ ];
91445
+ }
91446
+ function settleOpenInvocation(outcome) {
91447
+ if (openInvocation === null || invocationSettled)
91448
+ return;
91449
+ const { properties, startedAt } = openInvocation;
91450
+ recordTelemetryEvent({
91451
+ properties: {
91452
+ ...properties,
91453
+ outcome,
91454
+ duration_ms: Date.now() - startedAt
91455
+ }
91456
+ });
91457
+ }
91458
+ function recordAbandonedInvocation() {
91459
+ settleOpenInvocation("abandoned");
91325
91460
  }
91326
91461
  async function submitTelemetryEvent(event) {
91327
91462
  const buildInfo = getBuildInfo();
@@ -91389,6 +91524,7 @@ async function flushTelemetry(timeoutMs = DEFAULT_FLUSH_TIMEOUT_MS) {
91389
91524
  await instance.flush(timeoutMs);
91390
91525
  }
91391
91526
  async function exitWithFlush(code) {
91527
+ settleOpenInvocation(code === 0 ? "succeeded" : "failed");
91392
91528
  await flushTelemetry();
91393
91529
  process.exit(code);
91394
91530
  }
@@ -91519,11 +91655,13 @@ function __resetTelemetryForTests() {
91519
91655
  instance = null;
91520
91656
  consentProviderInstance = null;
91521
91657
  recordedTelemetryIdCache = void 0;
91658
+ openInvocation = null;
91659
+ invocationSettled = false;
91522
91660
  }
91523
91661
  function __setConsentProviderForTests(provider) {
91524
91662
  consentProviderInstance = provider;
91525
91663
  }
91526
- var instance, consentProviderInstance, cliLogTelemetryLogger, recordedTelemetryIdCache;
91664
+ var instance, consentProviderInstance, cliLogTelemetryLogger, recordedTelemetryIdCache, openInvocation, invocationSettled;
91527
91665
  var init_telemetry = __esm({
91528
91666
  async "apps/cli/src/services/telemetry/index.ts"() {
91529
91667
  "use strict";
@@ -91552,6 +91690,8 @@ var init_telemetry = __esm({
91552
91690
  warn: (payload) => writeCliLog("info", payload),
91553
91691
  error: (payload) => writeCliLog("error", payload)
91554
91692
  };
91693
+ openInvocation = null;
91694
+ invocationSettled = false;
91555
91695
  }
91556
91696
  });
91557
91697
 
@@ -91921,6 +92061,30 @@ function createApiClient(baseUrl, token, options = {}) {
91921
92061
  }
91922
92062
  return res.json();
91923
92063
  },
92064
+ /**
92065
+ * Redeems a short sign-in code for a CLI session.
92066
+ *
92067
+ * @param code - The code the browser displayed or the callback delivered.
92068
+ * @param codeVerifier - The PKCE verifier this process generated.
92069
+ * @param telemetryInstallationId - Anonymous installation id to bind, or
92070
+ * omitted when telemetry is disabled or the CLI is running in CI.
92071
+ * @returns The parsed {@link AuthPayload} containing the CLI session token.
92072
+ */
92073
+ async exchangeAuthorizationCode(code, codeVerifier, telemetryInstallationId) {
92074
+ const res = await fetchWithTimeout(`${baseUrl}/api/cli/auth/session`, {
92075
+ method: "POST",
92076
+ headers: { "Content-Type": "application/json" },
92077
+ body: JSON.stringify({
92078
+ code,
92079
+ codeVerifier,
92080
+ ...telemetryInstallationId === void 0 ? {} : { telemetryInstallationId }
92081
+ })
92082
+ });
92083
+ if (!res.ok) {
92084
+ throw await readApiError(res);
92085
+ }
92086
+ return res.json();
92087
+ },
91924
92088
  async verifySession(telemetryInstallationId) {
91925
92089
  const query = telemetryInstallationId === void 0 ? "" : `?telemetryInstallationId=${encodeURIComponent(telemetryInstallationId)}`;
91926
92090
  const res = await retryTransient(async () => {
@@ -93017,17 +93181,29 @@ var init_open = __esm({
93017
93181
  // apps/cli/src/services/auth.service.ts
93018
93182
  var auth_service_exports = {};
93019
93183
  __export(auth_service_exports, {
93184
+ MANUAL_LOGIN_ONLY_ENV_VAR: () => MANUAL_LOGIN_ONLY_ENV_VAR,
93020
93185
  TERMINAL_SESSION_INVALID_MESSAGE: () => TERMINAL_SESSION_INVALID_MESSAGE,
93021
93186
  clearAuthOnTerminalSessionInvalidation: () => clearAuthOnTerminalSessionInvalidation,
93187
+ createPkcePair: () => createPkcePair,
93188
+ isManualLoginOnlyEnabled: () => isManualLoginOnlyEnabled,
93022
93189
  isTerminalSessionInvalidationError: () => isTerminalSessionInvalidationError,
93023
93190
  login: () => login,
93024
93191
  logout: () => logout,
93025
- raceForClerkToken: () => raceForClerkToken,
93192
+ raceForAuthCode: () => raceForAuthCode,
93026
93193
  startCallbackServer: () => startCallbackServer,
93027
93194
  verifyAndRefresh: () => verifyAndRefresh
93028
93195
  });
93029
93196
  import * as crypto3 from "crypto";
93030
93197
  import * as http from "http";
93198
+ function createPkcePair() {
93199
+ const codeVerifier = crypto3.randomBytes(32).toString("base64url");
93200
+ const codeChallenge = crypto3.createHash("sha256").update(codeVerifier).digest("base64url");
93201
+ return { codeVerifier, codeChallenge };
93202
+ }
93203
+ function isManualLoginOnlyEnabled() {
93204
+ const value = process.env[MANUAL_LOGIN_ONLY_ENV_VAR]?.trim().toLowerCase();
93205
+ return value === "1" || value === "true";
93206
+ }
93031
93207
  function startCallbackServer(expectedState, waitForLoginCompletion = false) {
93032
93208
  const diagnostics = createCliAuthDiagnostics(expectedState);
93033
93209
  diagnostics.logPhase("callback-server.starting", {
@@ -93051,6 +93227,26 @@ function startCallbackServer(expectedState, waitForLoginCompletion = false) {
93051
93227
  <html><head><meta charset="utf-8"><title>Sign-in failed</title>
93052
93228
  <style>body{font-family:-apple-system,system-ui,sans-serif;display:flex;align-items:center;justify-content:center;min-height:100vh;margin:0;color:#111}main{text-align:center;max-width:420px;padding:2rem}h1{font-size:1.25rem;margin:0 0 .5rem;color:#c0392b}p{color:#555;font-size:.95rem;line-height:1.5;margin:0}</style>
93053
93229
  </head><body><main><h1>Sign-in failed</h1><p>${msg}</p></main></body></html>`;
93230
+ const MANUAL_ONLY_HTML = (code) => `<!doctype html>
93231
+ <html><head><meta charset="utf-8"><title>Automatic sign-in blocked</title>
93232
+ <style>body{font-family:-apple-system,system-ui,sans-serif;display:flex;align-items:center;justify-content:center;min-height:100vh;margin:0;color:#111}main{text-align:center;max-width:640px;padding:2rem}h1{font-size:1.25rem;margin:0 0 .5rem}p{color:#555;font-size:.95rem;line-height:1.5;margin:0 0 1rem}code{display:block;word-break:break-all;text-align:left;background:#f4f4f5;border:1px solid #e4e4e7;border-radius:6px;padding:.75rem;font-size:.8rem}button{margin-top:.75rem;font-size:.9rem;padding:.5rem 1rem;border-radius:6px;border:1px solid #d4d4d8;background:#fff;cursor:pointer}#age{margin-top:.75rem;color:#777;font-size:.85rem}</style>
93233
+ </head><body><main><h1>Automatic sign-in blocked</h1>
93234
+ <p>This CLI runs with <code style="display:inline;padding:.1rem .3rem">${MANUAL_LOGIN_ONLY_ENV_VAR}</code> set, so it ignored this redirect. Copy the code below and paste it into the CLI prompt.</p>
93235
+ <code id="t">${code}</code>
93236
+ <button id="c">Copy code</button>
93237
+ <p id="age"></p>
93238
+ <script>
93239
+ const minted = Date.now();
93240
+ document.getElementById("c").addEventListener("click", async () => {
93241
+ await navigator.clipboard.writeText(document.getElementById("t").textContent);
93242
+ document.getElementById("c").textContent = "Copied";
93243
+ });
93244
+ setInterval(() => {
93245
+ document.getElementById("age").textContent =
93246
+ "On this page for " + Math.round((Date.now() - minted) / 1000) + "s.";
93247
+ }, 1000);
93248
+ </script>
93249
+ </main></body></html>`;
93054
93250
  const sendCompletion = (res, success3) => new Promise((resolve9) => {
93055
93251
  if (res.destroyed) {
93056
93252
  resolve9();
@@ -93113,12 +93309,14 @@ function startCallbackServer(expectedState, waitForLoginCompletion = false) {
93113
93309
  rejectResult(reason);
93114
93310
  };
93115
93311
  const state = url4.searchParams.get("state");
93312
+ const code = url4.searchParams.get("code");
93116
93313
  const clerkToken = url4.searchParams.get("clerkToken");
93117
93314
  const hostedSnapshot = parseHostedCliAuthDiagnosticSnapshot(
93118
93315
  url4.searchParams.get("cliAuthDiag")
93119
93316
  );
93120
93317
  diagnostics.logPhase("callback-server.callback-received", {
93121
93318
  callback: summarizeCallbackUrl(`http://127.0.0.1${url4.pathname}`),
93319
+ hasCode: Boolean(code),
93122
93320
  hasClerkToken: Boolean(clerkToken),
93123
93321
  receivedState: summarizeState(state)
93124
93322
  });
@@ -93142,10 +93340,10 @@ function startCallbackServer(expectedState, waitForLoginCompletion = false) {
93142
93340
  rejectOnce(new Error("State mismatch in callback"));
93143
93341
  return;
93144
93342
  }
93145
- if (!clerkToken) {
93343
+ if (!code && !clerkToken) {
93146
93344
  diagnostics.logError(
93147
- "callback-server.missing-clerk-token",
93148
- new Error("Missing clerkToken in callback"),
93345
+ "callback-server.missing-code",
93346
+ new Error("Missing code in callback"),
93149
93347
  {
93150
93348
  receivedState: summarizeState(state)
93151
93349
  }
@@ -93154,8 +93352,20 @@ function startCallbackServer(expectedState, waitForLoginCompletion = false) {
93154
93352
  "Content-Type": "text/html; charset=utf-8",
93155
93353
  Connection: "close"
93156
93354
  });
93157
- res.end(ERROR_HTML("Missing Clerk token. Please retry from the CLI."));
93158
- rejectOnce(new Error("Missing clerkToken in callback"));
93355
+ res.end(ERROR_HTML("Missing sign-in code. Please retry from the CLI."));
93356
+ rejectOnce(new Error("Missing code in callback"));
93357
+ return;
93358
+ }
93359
+ if (isManualLoginOnlyEnabled() && code) {
93360
+ res.writeHead(200, {
93361
+ "Content-Type": "text/html; charset=utf-8",
93362
+ Connection: "close"
93363
+ });
93364
+ res.end(MANUAL_ONLY_HTML(code));
93365
+ diagnostics.logPhase("callback-server.callback-ignored", {
93366
+ reason: "manual-login-only",
93367
+ receivedState: summarizeState(state)
93368
+ });
93159
93369
  return;
93160
93370
  }
93161
93371
  if (waitForLoginCompletion) {
@@ -93179,9 +93389,10 @@ function startCallbackServer(expectedState, waitForLoginCompletion = false) {
93179
93389
  res.end(SUCCESS_HTML);
93180
93390
  }
93181
93391
  diagnostics.logPhase("callback-server.callback-accepted", {
93182
- receivedState: summarizeState(state)
93392
+ receivedState: summarizeState(state),
93393
+ via: code ? "code" : "clerkToken"
93183
93394
  });
93184
- resolveOnce({ clerkToken });
93395
+ resolveOnce(code ? { code } : { clerkToken });
93185
93396
  });
93186
93397
  server.on("error", (error98) => {
93187
93398
  diagnostics.logError("callback-server.error", error98);
@@ -93204,16 +93415,16 @@ function startCallbackServer(expectedState, waitForLoginCompletion = false) {
93204
93415
  });
93205
93416
  });
93206
93417
  }
93207
- async function raceForClerkToken(resultPromise, manualClerkToken) {
93418
+ async function raceForAuthCode(resultPromise, manualClerkToken) {
93208
93419
  const callbackBranch = resultPromise.then((result) => ({
93209
- clerkToken: result.clerkToken,
93420
+ ...result,
93210
93421
  source: "callback"
93211
93422
  }));
93212
93423
  if (!manualClerkToken) {
93213
93424
  return await callbackBranch;
93214
93425
  }
93215
- const manualBranch = manualClerkToken.then((clerkToken) => ({
93216
- clerkToken,
93426
+ const manualBranch = manualClerkToken.then((code) => ({
93427
+ code,
93217
93428
  source: "manual"
93218
93429
  }));
93219
93430
  const swallow = (promise3) => {
@@ -93223,8 +93434,21 @@ async function raceForClerkToken(resultPromise, manualClerkToken) {
93223
93434
  swallow(manualBranch);
93224
93435
  return await Promise.race([callbackBranch, manualBranch]);
93225
93436
  }
93437
+ function reportAuthCodeShape(code, source, diagnostics) {
93438
+ diagnostics.logPhase("login.code-shape", {
93439
+ length: code.length,
93440
+ source
93441
+ });
93442
+ if (!isManualLoginOnlyEnabled()) {
93443
+ return;
93444
+ }
93445
+ process.stderr.write(`
93446
+ [manual-login-only] Code length ${code.length}.
93447
+ `);
93448
+ }
93226
93449
  async function login(options = {}) {
93227
93450
  const state = crypto3.randomBytes(16).toString("hex");
93451
+ const { codeVerifier, codeChallenge } = createPkcePair();
93228
93452
  const diagnostics = createCliAuthDiagnostics(state);
93229
93453
  diagnostics.logPhase("login.start", {
93230
93454
  opsApiUrl: getOpsApiUrl(),
@@ -93242,6 +93466,8 @@ async function login(options = {}) {
93242
93466
  const loginParams = new URLSearchParams({
93243
93467
  callback: callbackUrl,
93244
93468
  state,
93469
+ code_challenge: codeChallenge,
93470
+ code_challenge_method: "S256",
93245
93471
  ...isCliAuthDiagnosticsVerboseEnabled() ? { verbose: "1" } : {},
93246
93472
  ...posthogDistinctId !== null ? { posthog_distinct_id: posthogDistinctId } : {}
93247
93473
  });
@@ -93273,13 +93499,14 @@ async function login(options = {}) {
93273
93499
  }
93274
93500
  }
93275
93501
  diagnostics.logPhase("login.waiting-for-callback");
93276
- const { clerkToken, source } = await raceForClerkToken(
93502
+ const credential = await raceForAuthCode(
93277
93503
  resultPromise,
93278
93504
  options.manualClerkToken
93279
93505
  );
93506
+ const { source } = credential;
93280
93507
  tokenSource = source;
93281
93508
  diagnostics.logPhase("login.callback-complete", {
93282
- clerkTokenReceived: true,
93509
+ codeReceived: "code" in credential,
93283
93510
  tokenSource: source
93284
93511
  });
93285
93512
  const apiClient = createApiClient(getOpsApiUrl());
@@ -93288,10 +93515,20 @@ async function login(options = {}) {
93288
93515
  let authPayload;
93289
93516
  try {
93290
93517
  diagnostics.logPhase("login.exchange-start");
93291
- authPayload = await apiClient.exchangeClerkToken(
93292
- clerkToken,
93293
- bindDuringExchange
93294
- );
93518
+ if ("code" in credential) {
93519
+ reportAuthCodeShape(credential.code, source, diagnostics);
93520
+ authPayload = await apiClient.exchangeAuthorizationCode(
93521
+ credential.code,
93522
+ codeVerifier,
93523
+ bindDuringExchange
93524
+ );
93525
+ } else {
93526
+ diagnostics.logPhase("login.exchange-clerk-token-fallback");
93527
+ authPayload = await apiClient.exchangeClerkToken(
93528
+ credential.clerkToken,
93529
+ bindDuringExchange
93530
+ );
93531
+ }
93295
93532
  diagnostics.logPhase("login.exchange-complete", {
93296
93533
  organizationId: authPayload.organization.clerkOrgId,
93297
93534
  userId: authPayload.user.id
@@ -93422,7 +93659,7 @@ async function logout() {
93422
93659
  authStore.clear();
93423
93660
  rotateInstallationId({ configStore });
93424
93661
  }
93425
- var MANUAL_PASTE_SERVER_LINGER_MS, TERMINAL_SESSION_INVALID_MESSAGE;
93662
+ var MANUAL_LOGIN_ONLY_ENV_VAR, MANUAL_PASTE_SERVER_LINGER_MS, TERMINAL_SESSION_INVALID_MESSAGE;
93426
93663
  var init_auth_service = __esm({
93427
93664
  async "apps/cli/src/services/auth.service.ts"() {
93428
93665
  "use strict";
@@ -93433,6 +93670,7 @@ var init_auth_service = __esm({
93433
93670
  await init_telemetry();
93434
93671
  init_cli_auth_diagnostics();
93435
93672
  init_config();
93673
+ MANUAL_LOGIN_ONLY_ENV_VAR = "COPILOTKIT_CLI_MANUAL_LOGIN_ONLY";
93436
93674
  MANUAL_PASTE_SERVER_LINGER_MS = 6e3;
93437
93675
  TERMINAL_SESSION_INVALID_MESSAGE = "Existing CLI sessions are invalid after the Clerk cutover. Please log in again.";
93438
93676
  }
@@ -93536,6 +93774,37 @@ var init_build4 = __esm({
93536
93774
  }
93537
93775
  });
93538
93776
 
93777
+ // apps/cli/src/services/auth-code-shape.ts
93778
+ function normalizeAuthCode(raw2) {
93779
+ return raw2.trim().toUpperCase().replaceAll("-", "").replaceAll(/\s/gu, "").replaceAll(/[IL]/gu, "1").replaceAll("O", "0");
93780
+ }
93781
+ function inspectAuthCode(value) {
93782
+ const normalized = normalizeAuthCode(value);
93783
+ if (normalized.length === 0) {
93784
+ return { ok: false, reason: "The code is empty." };
93785
+ }
93786
+ if (normalized.includes(".")) {
93787
+ return {
93788
+ ok: false,
93789
+ reason: "That looks like a session token, not a sign-in code. Copy the short code shown on the page."
93790
+ };
93791
+ }
93792
+ if (!CODE_PATTERN.test(normalized)) {
93793
+ return {
93794
+ ok: false,
93795
+ reason: "A sign-in code is eight characters, like WDJB-MJHT. Check the code on the page and enter it again."
93796
+ };
93797
+ }
93798
+ return { ok: true };
93799
+ }
93800
+ var CODE_PATTERN;
93801
+ var init_auth_code_shape = __esm({
93802
+ "apps/cli/src/services/auth-code-shape.ts"() {
93803
+ "use strict";
93804
+ CODE_PATTERN = /^[0-9ABCDEFGHJKMNPQRSTVWXYZ]{8}$/u;
93805
+ }
93806
+ });
93807
+
93539
93808
  // apps/cli/src/services/cli-tips.ts
93540
93809
  function rankCliTips(tips = CLI_TIPS) {
93541
93810
  return [...tips].sort((firstTip, secondTip) => {
@@ -94063,7 +94332,16 @@ function BrowserLoginProvider({
94063
94332
  if (trimmed.length === 0) {
94064
94333
  return void 0;
94065
94334
  }
94335
+ const inspection = inspectAuthCode(trimmed);
94336
+ if (!inspection.ok) {
94337
+ setState((previous) => ({
94338
+ ...previous,
94339
+ manualTokenError: inspection.reason
94340
+ }));
94341
+ return void 0;
94342
+ }
94066
94343
  pendingManualTokenRef.current = null;
94344
+ setState((previous) => ({ ...previous, manualTokenError: "" }));
94067
94345
  pendingManualToken.resolve(trimmed);
94068
94346
  return void 0;
94069
94347
  }, []);
@@ -94115,7 +94393,8 @@ function BrowserLoginProvider({
94115
94393
  phase: "finalizing",
94116
94394
  identity,
94117
94395
  errorMessage: "",
94118
- loginUrl: ""
94396
+ loginUrl: "",
94397
+ manualTokenError: ""
94119
94398
  });
94120
94399
  await new Promise((resolve9) => {
94121
94400
  setTimeout(() => {
@@ -94127,7 +94406,8 @@ function BrowserLoginProvider({
94127
94406
  phase: "success",
94128
94407
  identity,
94129
94408
  errorMessage: "",
94130
- loginUrl: ""
94409
+ loginUrl: "",
94410
+ manualTokenError: ""
94131
94411
  });
94132
94412
  return result;
94133
94413
  } catch (error98) {
@@ -94140,7 +94420,8 @@ function BrowserLoginProvider({
94140
94420
  phase: "error",
94141
94421
  identity: null,
94142
94422
  errorMessage: concreteError.message,
94143
- loginUrl: ""
94423
+ loginUrl: "",
94424
+ manualTokenError: ""
94144
94425
  });
94145
94426
  throw concreteError;
94146
94427
  }
@@ -94233,6 +94514,7 @@ function BrowserLoginConfirmation({
94233
94514
  )
94234
94515
  ] })
94235
94516
  ] }) : null,
94517
+ state.manualTokenError !== "" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "red", children: state.manualTokenError }) }) : null,
94236
94518
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CliTip, {})
94237
94519
  ] });
94238
94520
  }
@@ -94278,6 +94560,7 @@ var init_browser_login = __esm({
94278
94560
  await init_build4();
94279
94561
  await init_auth_service();
94280
94562
  init_cli_auth_diagnostics();
94563
+ init_auth_code_shape();
94281
94564
  await init_cli_tip();
94282
94565
  await init_spinner();
94283
94566
  await init_success_text();
@@ -94289,10 +94572,11 @@ var init_browser_login = __esm({
94289
94572
  phase: "idle",
94290
94573
  identity: null,
94291
94574
  errorMessage: "",
94292
- loginUrl: ""
94575
+ loginUrl: "",
94576
+ manualTokenError: ""
94293
94577
  };
94294
94578
  BrowserLoginContext = (0, import_react35.createContext)(null);
94295
- BROWSER_LOGIN_MANUAL_PASTE_LABEL = "If your browser finished sign-in but the CLI didn't notice, paste the code shown in the browser:";
94579
+ BROWSER_LOGIN_MANUAL_PASTE_LABEL = "If your browser finished sign-in but the CLI didn't notice, paste the short code shown there:";
94296
94580
  BROWSER_LOGIN_MANUAL_URL_LABEL = "If the browser didn't open, sign in at:";
94297
94581
  }
94298
94582
  });
@@ -96721,7 +97005,7 @@ var init_learning_skills_api = __esm({
96721
97005
  });
96722
97006
 
96723
97007
  // apps/cli/src/services/learning-skills-download.ts
96724
- import { createHash as createHash2 } from "node:crypto";
97008
+ import { createHash as createHash3 } from "node:crypto";
96725
97009
  import {
96726
97010
  existsSync as existsSync10,
96727
97011
  mkdirSync as mkdirSync5,
@@ -96932,7 +97216,7 @@ function verifyEtag(bytes, etag) {
96932
97216
  if (etag === void 0) {
96933
97217
  return;
96934
97218
  }
96935
- const expected = `"${createHash2("sha256").update(bytes).digest("hex")}"`;
97219
+ const expected = `"${createHash3("sha256").update(bytes).digest("hex")}"`;
96936
97220
  if (etag !== expected) {
96937
97221
  throw learningSkillsError(
96938
97222
  TELEMETRY_ERROR_CODES.LEARNING_SKILLS_INTEGRITY_FAILED,
@@ -97053,6 +97337,68 @@ var init_skills_download = __esm({
97053
97337
  }
97054
97338
  });
97055
97339
 
97340
+ // apps/cli/src/services/child-timeout.ts
97341
+ function signalChildTree(child, signal, ownsProcessGroup) {
97342
+ const { pid } = child;
97343
+ if (ownsProcessGroup && pid !== void 0) {
97344
+ try {
97345
+ process.kill(-pid, signal);
97346
+ return;
97347
+ } catch {
97348
+ }
97349
+ }
97350
+ try {
97351
+ child.kill(signal);
97352
+ } catch {
97353
+ }
97354
+ }
97355
+ function armChildTimeout(child, timeoutMs, onTimeout, options = {}) {
97356
+ if (timeoutMs <= 0)
97357
+ return { cancel: () => void 0 };
97358
+ const ownsProcessGroup = options.ownsProcessGroup === true;
97359
+ let closed = false;
97360
+ let graceTimer;
97361
+ const timer = setTimeout(() => {
97362
+ signalChildTree(child, "SIGTERM", ownsProcessGroup);
97363
+ onTimeout();
97364
+ graceTimer = setTimeout(() => {
97365
+ if (!closed)
97366
+ signalChildTree(child, "SIGKILL", ownsProcessGroup);
97367
+ }, TERMINATION_GRACE_MS);
97368
+ }, timeoutMs);
97369
+ const forwarders = (ownsProcessGroup ? FORWARDED_SIGNALS : []).flatMap((signal) => {
97370
+ if (process.listenerCount(signal) === 0)
97371
+ return [];
97372
+ const forward = () => {
97373
+ signalChildTree(child, signal, ownsProcessGroup);
97374
+ };
97375
+ process.once(signal, forward);
97376
+ return [{ signal, forward }];
97377
+ });
97378
+ const cancel = () => {
97379
+ clearTimeout(timer);
97380
+ if (graceTimer !== void 0)
97381
+ clearTimeout(graceTimer);
97382
+ for (const { signal, forward } of forwarders) {
97383
+ process.off(signal, forward);
97384
+ }
97385
+ };
97386
+ child.once("close", () => {
97387
+ closed = true;
97388
+ cancel();
97389
+ });
97390
+ return { cancel };
97391
+ }
97392
+ var TERMINATION_GRACE_MS, OWN_PROCESS_GROUP, FORWARDED_SIGNALS;
97393
+ var init_child_timeout = __esm({
97394
+ "apps/cli/src/services/child-timeout.ts"() {
97395
+ "use strict";
97396
+ TERMINATION_GRACE_MS = 5e3;
97397
+ OWN_PROCESS_GROUP = { detached: true };
97398
+ FORWARDED_SIGNALS = ["SIGINT", "SIGTERM"];
97399
+ }
97400
+ });
97401
+
97056
97402
  // apps/cli/src/services/skills-install.ts
97057
97403
  import { spawn } from "node:child_process";
97058
97404
  import {
@@ -97158,6 +97504,65 @@ function removePartialFailureMonitor(monitor) {
97158
97504
  } catch {
97159
97505
  }
97160
97506
  }
97507
+ function createSkillsInstallRunner(timeoutMs = SKILLS_INSTALL_TIMEOUT_MS) {
97508
+ return (command2, args, outputMode) => new Promise((resolve9, reject) => {
97509
+ let capture = {
97510
+ output: "",
97511
+ reportedPartialFailure: false
97512
+ };
97513
+ const monitor = outputMode === "monitor" ? createPartialFailureMonitor() : null;
97514
+ const ownsProcessGroup = outputMode === "capture";
97515
+ const child = spawn(command2, [...args], {
97516
+ stdio: outputMode === "capture" ? ["ignore", "pipe", "pipe"] : "inherit",
97517
+ ...ownsProcessGroup ? OWN_PROCESS_GROUP : {},
97518
+ env: monitor === null ? void 0 : {
97519
+ ...process.env,
97520
+ NODE_OPTIONS: monitor.nodeOptions,
97521
+ [PARTIAL_FAILURE_FILE_ENV]: monitor.markerPath
97522
+ },
97523
+ // `npx` is a `.cmd` shim on Windows and is only resolvable through a shell
97524
+ // there; POSIX can exec it directly. Selection tokens are validated against
97525
+ // SELECTION_TOKEN before reaching here, so there is no injection surface.
97526
+ shell: process.platform === "win32"
97527
+ });
97528
+ if (outputMode === "capture") {
97529
+ child.stdout?.on("data", (chunk) => {
97530
+ capture = appendSkillsInstallOutput(capture, chunk);
97531
+ });
97532
+ child.stderr?.on("data", (chunk) => {
97533
+ capture = appendSkillsInstallOutput(capture, chunk);
97534
+ });
97535
+ }
97536
+ let timedOut = false;
97537
+ const timeout = armChildTimeout(
97538
+ child,
97539
+ timeoutMs,
97540
+ () => {
97541
+ timedOut = true;
97542
+ },
97543
+ { ownsProcessGroup }
97544
+ );
97545
+ child.on("error", (error98) => {
97546
+ timeout.cancel();
97547
+ removePartialFailureMonitor(monitor);
97548
+ reject(error98);
97549
+ });
97550
+ child.on("close", (code) => {
97551
+ timeout.cancel();
97552
+ const reportedPartialFailure = capture.reportedPartialFailure || monitor !== null && existsSync11(monitor.markerPath);
97553
+ removePartialFailureMonitor(monitor);
97554
+ if (timedOut) {
97555
+ reject(
97556
+ new Error(
97557
+ `The skills installer stopped responding after ${timeoutMs} ms and was stopped. Check the network and the npm registry configuration, then run \`${command2} ${args.join(" ")}\` by hand.`
97558
+ )
97559
+ );
97560
+ return;
97561
+ }
97562
+ resolve9({ exitCode: code ?? 1, ...capture, reportedPartialFailure });
97563
+ });
97564
+ });
97565
+ }
97161
97566
  async function installCopilotKitSkills(options = {}, deps = {}) {
97162
97567
  const run = deps.run ?? defaultRunner;
97163
97568
  const args = buildSkillsInstallArgs(options);
@@ -97183,10 +97588,11 @@ Retry with \`${SKILLS_INSTALL_COMMAND} ${retryArgs}\`.`
97183
97588
  );
97184
97589
  }
97185
97590
  }
97186
- var SKILLS_INSTALL_COMMAND, SKILLS_INSTALL_PACKAGE, SKILLS_SOURCE, ALL_SELECTION, DEFAULT_ONBOARD_AGENTS, SELECTION_TOKEN, MAX_CAPTURED_OUTPUT_CHARACTERS, PARTIAL_FAILURE_PATTERN, PARTIAL_FAILURE_FILE_ENV, PARTIAL_FAILURE_MONITOR_SOURCE, defaultRunner;
97591
+ var SKILLS_INSTALL_COMMAND, SKILLS_INSTALL_PACKAGE, SKILLS_SOURCE, ALL_SELECTION, DEFAULT_ONBOARD_AGENTS, SELECTION_TOKEN, MAX_CAPTURED_OUTPUT_CHARACTERS, SKILLS_INSTALL_TIMEOUT_MS, PARTIAL_FAILURE_PATTERN, PARTIAL_FAILURE_FILE_ENV, PARTIAL_FAILURE_MONITOR_SOURCE, defaultRunner;
97187
97592
  var init_skills_install = __esm({
97188
97593
  "apps/cli/src/services/skills-install.ts"() {
97189
97594
  "use strict";
97595
+ init_child_timeout();
97190
97596
  init_event_properties();
97191
97597
  SKILLS_INSTALL_COMMAND = "npx";
97192
97598
  SKILLS_INSTALL_PACKAGE = "skills@1.5.18";
@@ -97195,6 +97601,7 @@ var init_skills_install = __esm({
97195
97601
  DEFAULT_ONBOARD_AGENTS = ["universal", "claude-code"];
97196
97602
  SELECTION_TOKEN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
97197
97603
  MAX_CAPTURED_OUTPUT_CHARACTERS = 16384;
97604
+ SKILLS_INSTALL_TIMEOUT_MS = 5 * 6e4;
97198
97605
  PARTIAL_FAILURE_PATTERN = /\bFailed to install [1-9]\d*\b/;
97199
97606
  PARTIAL_FAILURE_FILE_ENV = "CPKI_SKILLS_PARTIAL_FAILURE_FILE";
97200
97607
  PARTIAL_FAILURE_MONITOR_SOURCE = String.raw`"use strict";
@@ -97228,42 +97635,7 @@ function monitor(stream) {
97228
97635
  monitor(process.stdout);
97229
97636
  monitor(process.stderr);
97230
97637
  `;
97231
- defaultRunner = (command2, args, outputMode) => new Promise((resolve9, reject) => {
97232
- let capture = {
97233
- output: "",
97234
- reportedPartialFailure: false
97235
- };
97236
- const monitor = outputMode === "monitor" ? createPartialFailureMonitor() : null;
97237
- const child = spawn(command2, [...args], {
97238
- stdio: outputMode === "capture" ? ["ignore", "pipe", "pipe"] : "inherit",
97239
- env: monitor === null ? void 0 : {
97240
- ...process.env,
97241
- NODE_OPTIONS: monitor.nodeOptions,
97242
- [PARTIAL_FAILURE_FILE_ENV]: monitor.markerPath
97243
- },
97244
- // `npx` is a `.cmd` shim on Windows and is only resolvable through a shell
97245
- // there; POSIX can exec it directly. Selection tokens are validated against
97246
- // SELECTION_TOKEN before reaching here, so there is no injection surface.
97247
- shell: process.platform === "win32"
97248
- });
97249
- if (outputMode === "capture") {
97250
- child.stdout?.on("data", (chunk) => {
97251
- capture = appendSkillsInstallOutput(capture, chunk);
97252
- });
97253
- child.stderr?.on("data", (chunk) => {
97254
- capture = appendSkillsInstallOutput(capture, chunk);
97255
- });
97256
- }
97257
- child.on("error", (error98) => {
97258
- removePartialFailureMonitor(monitor);
97259
- reject(error98);
97260
- });
97261
- child.on("close", (code) => {
97262
- const reportedPartialFailure = capture.reportedPartialFailure || monitor !== null && existsSync11(monitor.markerPath);
97263
- removePartialFailureMonitor(monitor);
97264
- resolve9({ exitCode: code ?? 1, ...capture, reportedPartialFailure });
97265
- });
97266
- });
97638
+ defaultRunner = createSkillsInstallRunner();
97267
97639
  }
97268
97640
  });
97269
97641
 
@@ -98791,7 +99163,7 @@ var init_inspector_metadata = __esm({
98791
99163
  });
98792
99164
 
98793
99165
  // libs/app-api-contracts/src/inspector-learning.ts
98794
- var text, idSchema, boundedTextSchema, urlSchema, originSchema, candidateReviewUrlSchema, inspectorLearningRequestV1Schema, inspectorLearningUpstreamRequestV1Schema, evidenceSchema, inspectorLearningInsightSchema, configurationSchema, runSchema, pageSchema, skillSchema, inspectorLearningSnapshotV1Schema;
99166
+ var text, idSchema, boundedTextSchema, urlSchema, originSchema, candidateReviewUrlSchema, analysisResultsUrlSchema, inspectorLearningRequestV1Schema, inspectorLearningUpstreamRequestV1Schema, evidenceSchema, inspectorLearningInsightSchema, configurationSchema, runSchema, pageSchema, skillSchema, inspectorLearningSnapshotV1Schema;
98795
99167
  var init_inspector_learning = __esm({
98796
99168
  "libs/app-api-contracts/src/inspector-learning.ts"() {
98797
99169
  "use strict";
@@ -98818,6 +99190,12 @@ var init_inspector_learning = __esm({
98818
99190
  const url4 = new URL(value);
98819
99191
  return /^\/o\/[^/]+\/[^/]+\/learning\/[^/]+\/skills$/u.test(url4.pathname) && url4.search === "" && url4.hash === "";
98820
99192
  }, "Expected a project-scoped Learning Skill-review URL.");
99193
+ analysisResultsUrlSchema = urlSchema.refine((value) => {
99194
+ const url4 = new URL(value);
99195
+ return /^\/o\/[^/]+\/[^/]+\/learning\/[^/]+\/analysis-results$/u.test(
99196
+ url4.pathname
99197
+ ) && url4.search === "" && url4.hash === "";
99198
+ }, "Expected a project-scoped Learning analysis-results URL.");
98821
99199
  inspectorLearningRequestV1Schema = external_exports.object({
98822
99200
  agentId: idSchema.optional(),
98823
99201
  skillsPage: external_exports.number().int().min(1).optional(),
@@ -98914,7 +99292,7 @@ var init_inspector_learning = __esm({
98914
99292
  links: external_exports.object({
98915
99293
  learning: urlSchema,
98916
99294
  candidates: candidateReviewUrlSchema.nullable(),
98917
- runs: urlSchema.nullable()
99295
+ runs: analysisResultsUrlSchema.nullable()
98918
99296
  }).strict()
98919
99297
  }).strict().superRefine((snapshot, context3) => {
98920
99298
  const origin = new URL(snapshot.webAppOrigin).origin;
@@ -100778,7 +101156,7 @@ var init_import_metadata = __esm({
100778
101156
  });
100779
101157
 
100780
101158
  // libs/import-contracts/src/schemas.ts
100781
- var TextContentBlockSchema, ReasoningContentBlockSchema, InlineMediaContentBlockSchema, UnresolvedMediaContentBlockSchema, MediaContentBlockSchema, ToolCallContentBlockSchema, NormalizedContentBlockSchema, NormalizedMessageRoleSchema, NormalizedRunStatusSchema, NormalizedSourceBackendSchema, EndUserPolicySchema, NormalizedMessageSchema, NormalizedRunUsageSchema, NormalizedRunSchema, NormalizedConversationSchema, ImportRequestSchema;
101159
+ var TextContentBlockSchema, ReasoningContentBlockSchema, InlineMediaContentBlockSchema, UnresolvedMediaContentBlockSchema, MediaContentBlockSchema, ToolCallContentBlockSchema, NormalizedContentBlockSchema, NormalizedMessageRoleSchema, NormalizedRunStatusSchema, NormalizedSourceBackendSchema, EndUserPolicySchema, NormalizedMessageSchema, NormalizedRunUsageSchema, NormalizedRunSchema, NormalizedPendingInterruptSchema, NormalizedConversationSchema, ImportRequestSchema;
100782
101160
  var init_schemas3 = __esm({
100783
101161
  "libs/import-contracts/src/schemas.ts"() {
100784
101162
  "use strict";
@@ -100840,6 +101218,7 @@ var init_schemas3 = __esm({
100840
101218
  role: NormalizedMessageRoleSchema,
100841
101219
  timestamp: external_exports.string(),
100842
101220
  toolCallId: external_exports.string().optional(),
101221
+ error: external_exports.string().optional(),
100843
101222
  content: external_exports.array(NormalizedContentBlockSchema)
100844
101223
  });
100845
101224
  NormalizedRunUsageSchema = external_exports.object({
@@ -100854,9 +101233,14 @@ var init_schemas3 = __esm({
100854
101233
  finishedAt: external_exports.string().optional(),
100855
101234
  usage: NormalizedRunUsageSchema.optional(),
100856
101235
  finishReason: external_exports.string().optional(),
101236
+ errorMessage: external_exports.string().optional(),
100857
101237
  interruptValue: external_exports.unknown().optional(),
100858
101238
  messages: external_exports.array(NormalizedMessageSchema)
100859
101239
  });
101240
+ NormalizedPendingInterruptSchema = external_exports.object({
101241
+ id: external_exports.string().min(1).optional(),
101242
+ value: external_exports.json()
101243
+ }).loose();
100860
101244
  NormalizedConversationSchema = external_exports.object({
100861
101245
  // Non-empty: `sourceThreadId` is half of the conversation-level dedup key
100862
101246
  // (project_id, import_metadata->>'source', ->>'source_thread_id'); a blank
@@ -100866,6 +101250,8 @@ var init_schemas3 = __esm({
100866
101250
  sourceBackend: NormalizedSourceBackendSchema.optional(),
100867
101251
  endUserId: external_exports.string().nullable(),
100868
101252
  lastActivityAt: external_exports.string().optional(),
101253
+ stateSnapshot: external_exports.json().optional(),
101254
+ pendingInterrupts: external_exports.array(NormalizedPendingInterruptSchema).optional(),
100869
101255
  runs: external_exports.array(NormalizedRunSchema)
100870
101256
  });
100871
101257
  ImportRequestSchema = external_exports.object({
@@ -140643,7 +141029,7 @@ var require_websocket2 = __commonJS({
140643
141029
  var http4 = __require("http");
140644
141030
  var net = __require("net");
140645
141031
  var tls = __require("tls");
140646
- var { randomBytes: randomBytes4, createHash: createHash8 } = __require("crypto");
141032
+ var { randomBytes: randomBytes4, createHash: createHash9 } = __require("crypto");
140647
141033
  var { Duplex, Readable: Readable5 } = __require("stream");
140648
141034
  var { URL: URL7 } = __require("url");
140649
141035
  var PerMessageDeflate2 = require_permessage_deflate2();
@@ -141331,7 +141717,7 @@ var require_websocket2 = __commonJS({
141331
141717
  abortHandshake(websocket, socket, "Invalid Upgrade header");
141332
141718
  return;
141333
141719
  }
141334
- const digest = createHash8("sha1").update(key + GUID).digest("base64");
141720
+ const digest = createHash9("sha1").update(key + GUID).digest("base64");
141335
141721
  if (res.headers["sec-websocket-accept"] !== digest) {
141336
141722
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
141337
141723
  return;
@@ -141720,7 +142106,7 @@ var require_websocket_server2 = __commonJS({
141720
142106
  var EventEmitter4 = __require("events");
141721
142107
  var http4 = __require("http");
141722
142108
  var { Duplex } = __require("stream");
141723
- var { createHash: createHash8 } = __require("crypto");
142109
+ var { createHash: createHash9 } = __require("crypto");
141724
142110
  var extension2 = require_extension2();
141725
142111
  var PerMessageDeflate2 = require_permessage_deflate2();
141726
142112
  var subprotocol2 = require_subprotocol2();
@@ -142035,7 +142421,7 @@ var require_websocket_server2 = __commonJS({
142035
142421
  }
142036
142422
  if (this._state > RUNNING)
142037
142423
  return abortHandshake(socket, 503);
142038
- const digest = createHash8("sha1").update(key + GUID).digest("base64");
142424
+ const digest = createHash9("sha1").update(key + GUID).digest("base64");
142039
142425
  const headers = [
142040
142426
  "HTTP/1.1 101 Switching Protocols",
142041
142427
  "Upgrade: websocket",
@@ -233269,7 +233655,7 @@ var init_crc32c = __esm({
233269
233655
  });
233270
233656
 
233271
233657
  // node_modules/.pnpm/@google-cloud+storage@7.21.0_encoding@0.1.13/node_modules/@google-cloud/storage/build/esm/src/hash-stream-validator.js
233272
- import { createHash as createHash3 } from "crypto";
233658
+ import { createHash as createHash4 } from "crypto";
233273
233659
  import { Transform as Transform3 } from "stream";
233274
233660
  var __classPrivateFieldSet2, __classPrivateFieldGet2, _HashStreamValidator_crc32cHash, _HashStreamValidator_md5Hash, _HashStreamValidator_md5Digest, HashStreamValidator;
233275
233661
  var init_hash_stream_validator = __esm({
@@ -233314,7 +233700,7 @@ var init_hash_stream_validator = __esm({
233314
233700
  }
233315
233701
  }
233316
233702
  if (this.md5Enabled) {
233317
- __classPrivateFieldSet2(this, _HashStreamValidator_md5Hash, createHash3("md5"), "f");
233703
+ __classPrivateFieldSet2(this, _HashStreamValidator_md5Hash, createHash4("md5"), "f");
233318
233704
  }
233319
233705
  }
233320
233706
  /**
@@ -233382,7 +233768,7 @@ var init_hash_stream_validator = __esm({
233382
233768
  });
233383
233769
 
233384
233770
  // node_modules/.pnpm/@google-cloud+storage@7.21.0_encoding@0.1.13/node_modules/@google-cloud/storage/build/esm/src/resumable-upload.js
233385
- import { createHash as createHash4 } from "crypto";
233771
+ import { createHash as createHash5 } from "crypto";
233386
233772
  import { Readable as Readable2, Writable } from "stream";
233387
233773
  import * as crypto10 from "crypto";
233388
233774
  function upload(cfg) {
@@ -233514,13 +233900,13 @@ var init_resumable_upload = __esm({
233514
233900
  const base64Key = Buffer.from(cfg.key).toString("base64");
233515
233901
  this.encryption = {
233516
233902
  key: base64Key,
233517
- hash: createHash4("sha256").update(cfg.key).digest("base64")
233903
+ hash: createHash5("sha256").update(cfg.key).digest("base64")
233518
233904
  };
233519
233905
  } else {
233520
233906
  const base64Key = cfg.key.toString("base64");
233521
233907
  this.encryption = {
233522
233908
  key: base64Key,
233523
- hash: createHash4("sha256").update(cfg.key).digest("base64")
233909
+ hash: createHash5("sha256").update(cfg.key).digest("base64")
233524
233910
  };
233525
233911
  }
233526
233912
  }
@@ -376392,7 +376778,9 @@ var init_messages6 = __esm({
376392
376778
  content.push(reasoning);
376393
376779
  }
376394
376780
  }
376395
- content.push(...contentBlocksFrom(message.content));
376781
+ content.push(
376782
+ ...contentBlocksFrom(message.content)
376783
+ );
376396
376784
  if (type2 === "ai") {
376397
376785
  content.push(...toolCallBlocksFrom(message));
376398
376786
  }
@@ -376405,6 +376793,8 @@ var init_messages6 = __esm({
376405
376793
  content
376406
376794
  };
376407
376795
  if (type2 === "tool") {
376796
+ if ("status" in message && message.status === "error")
376797
+ normalized.error = "error";
376408
376798
  const toolCallId = message.tool_call_id;
376409
376799
  if (typeof toolCallId === "string" && toolCallId !== "") {
376410
376800
  return { ...normalized, toolCallId };
@@ -376541,6 +376931,135 @@ var init_state2 = __esm({
376541
376931
  }
376542
376932
  });
376543
376933
 
376934
+ // libs/import-langgraph/src/state-snapshot.ts
376935
+ var defaultWarn2, assistantSchema, createAssistantSchemaCache, hasRecoverableState, readAssistantSchemas, readStateSnapshot;
376936
+ var init_state_snapshot = __esm({
376937
+ "libs/import-langgraph/src/state-snapshot.ts"() {
376938
+ "use strict";
376939
+ init_zod();
376940
+ defaultWarn2 = (warning) => {
376941
+ console.warn("[import-langgraph] schema lookup fallback", warning);
376942
+ };
376943
+ assistantSchema = external_exports.object({
376944
+ output_schema: external_exports.object({
376945
+ properties: external_exports.record(external_exports.string(), external_exports.unknown()).optional()
376946
+ }).loose().nullish()
376947
+ }).loose();
376948
+ createAssistantSchemaCache = () => /* @__PURE__ */ new Map();
376949
+ hasRecoverableState = (values) => {
376950
+ if (values === void 0 || values === null)
376951
+ return false;
376952
+ if (typeof values !== "object")
376953
+ return true;
376954
+ return Object.keys(values).length > 0;
376955
+ };
376956
+ readAssistantSchemas = async (assistants, assistantId, cache3, onLookupFailure) => {
376957
+ if (cache3.has(assistantId))
376958
+ return cache3.get(assistantId);
376959
+ try {
376960
+ const schemas = await assistants.getSchemas(assistantId);
376961
+ cache3.set(assistantId, schemas);
376962
+ return schemas;
376963
+ } catch {
376964
+ onLookupFailure();
376965
+ return { output_schema: { properties: { messages: {}, tools: {} } } };
376966
+ }
376967
+ };
376968
+ readStateSnapshot = async (client2, thread, checkpoints, assistantId, cache3, onWarn = defaultWarn2) => {
376969
+ const values = checkpoints[0]?.values !== void 0 ? checkpoints[0].values : thread.values;
376970
+ if (!hasRecoverableState(values))
376971
+ return void 0;
376972
+ const assistants = client2.assistants;
376973
+ if (assistants === void 0)
376974
+ return values;
376975
+ const schemas = await readAssistantSchemas(
376976
+ assistants,
376977
+ assistantId,
376978
+ cache3,
376979
+ () => onWarn({
376980
+ reason: "schema_lookup_fallback",
376981
+ sourceThreadId: thread.thread_id,
376982
+ assistantId,
376983
+ detail: "State limited to messages and tools. After fixing schema access, re-import with --replace to recover graph-defined state."
376984
+ })
376985
+ );
376986
+ if (schemas === void 0)
376987
+ return values;
376988
+ const schema2 = assistantSchema.safeParse(schemas);
376989
+ const properties = schema2.success ? schema2.data.output_schema?.properties : void 0;
376990
+ if (properties === void 0 || Object.keys(properties).length === 0 || typeof values !== "object" || values === null || Array.isArray(values)) {
376991
+ return values;
376992
+ }
376993
+ const keys2 = /* @__PURE__ */ new Set(["messages", "tools", ...Object.keys(properties)]);
376994
+ const projected = Object.fromEntries(
376995
+ Object.entries(values).filter(([key]) => keys2.has(key))
376996
+ );
376997
+ return hasRecoverableState(projected) ? projected : void 0;
376998
+ };
376999
+ }
377000
+ });
377001
+
377002
+ // libs/import-langgraph/src/interrupts.ts
377003
+ var headInterruptsSchema, readHeadInterrupts, readPendingInterrupts;
377004
+ var init_interrupts2 = __esm({
377005
+ "libs/import-langgraph/src/interrupts.ts"() {
377006
+ "use strict";
377007
+ init_src6();
377008
+ init_zod();
377009
+ headInterruptsSchema = external_exports.object({ interrupts: external_exports.array(external_exports.unknown()).optional() }).loose();
377010
+ readHeadInterrupts = (head) => {
377011
+ const parsed = headInterruptsSchema.safeParse(head);
377012
+ return parsed.success ? parsed.data.interrupts ?? [] : [];
377013
+ };
377014
+ readPendingInterrupts = (head, thread) => {
377015
+ const fromTasks = (head?.tasks ?? []).flatMap(
377016
+ (task) => task.interrupts ?? []
377017
+ );
377018
+ const fromHead = head === void 0 ? [] : readHeadInterrupts(head);
377019
+ const fromThread = external_exports.record(external_exports.string(), external_exports.array(external_exports.unknown())).safeParse(thread?.interrupts);
377020
+ const raw2 = fromTasks.length > 0 ? fromTasks : fromHead.length > 0 ? fromHead : fromThread.success ? Object.values(fromThread.data).flat() : [];
377021
+ const seen = /* @__PURE__ */ new Set();
377022
+ const result = [];
377023
+ for (const candidate of raw2) {
377024
+ const parsed = NormalizedPendingInterruptSchema.safeParse(candidate);
377025
+ if (!parsed.success)
377026
+ continue;
377027
+ const interrupt = parsed.data;
377028
+ if (interrupt.id !== void 0) {
377029
+ if (seen.has(interrupt.id))
377030
+ continue;
377031
+ seen.add(interrupt.id);
377032
+ }
377033
+ result.push(interrupt);
377034
+ }
377035
+ return result;
377036
+ };
377037
+ }
377038
+ });
377039
+
377040
+ // libs/import-langgraph/src/errors.ts
377041
+ var readTaskError, readRunErrors;
377042
+ var init_errors10 = __esm({
377043
+ "libs/import-langgraph/src/errors.ts"() {
377044
+ "use strict";
377045
+ readTaskError = (checkpoint) => {
377046
+ const errors = (checkpoint?.tasks ?? []).flatMap(
377047
+ (task) => typeof task.error === "string" && task.error.trim() !== "" ? [task.error] : []
377048
+ );
377049
+ return errors.length > 0 ? [...new Set(errors)].join("\n") : void 0;
377050
+ };
377051
+ readRunErrors = (checkpoints) => {
377052
+ const errors = /* @__PURE__ */ new Map();
377053
+ for (const checkpoint of checkpoints) {
377054
+ const runId = checkpoint.metadata?.["run_id"];
377055
+ if (typeof runId === "string" && !errors.has(runId))
377056
+ errors.set(runId, readTaskError(checkpoint));
377057
+ }
377058
+ return errors;
377059
+ };
377060
+ }
377061
+ });
377062
+
376544
377063
  // libs/import-langgraph/src/user-source.ts
376545
377064
  var LANGGRAPH_AUTH_USER_ID_KEY, parseUserSource, readStringField, readValuesStringField, resolveEndUserId;
376546
377065
  var init_user_source = __esm({
@@ -376635,9 +377154,16 @@ async function* streamLangGraph(config3) {
376635
377154
  const client2 = await resolveClient(config3);
376636
377155
  const userSource = parseUserSource(config3.userSource);
376637
377156
  const pageSize = config3.pageSize ?? DEFAULT_THREAD_PAGE_SIZE;
377157
+ const schemaCache = createAssistantSchemaCache();
376638
377158
  for await (const thread of enumerateThreads(client2, pageSize)) {
376639
377159
  try {
376640
- yield await extractThread(client2, thread, userSource);
377160
+ yield await extractThread(
377161
+ client2,
377162
+ thread,
377163
+ userSource,
377164
+ schemaCache,
377165
+ config3.onWarn
377166
+ );
376641
377167
  } catch (error98) {
376642
377168
  yield {
376643
377169
  kind: "failed",
@@ -376659,11 +377185,14 @@ var init_extract2 = __esm({
376659
377185
  init_graph_id();
376660
377186
  init_runs2();
376661
377187
  init_state2();
377188
+ init_state_snapshot();
377189
+ init_interrupts2();
377190
+ init_errors10();
376662
377191
  init_user_source();
376663
377192
  DEFAULT_THREAD_PAGE_SIZE = 50;
376664
377193
  FULL_HISTORY_LIMIT = 1e3;
376665
- synthesizeSingleRun = (threadId, messages, activityAt) => {
376666
- if (messages.length === 0) {
377194
+ synthesizeSingleRun = (threadId, messages, activityAt, hasState = false) => {
377195
+ if (messages.length === 0 && !hasState) {
376667
377196
  return null;
376668
377197
  }
376669
377198
  return {
@@ -376695,7 +377224,7 @@ var init_extract2 = __esm({
376695
377224
  const head = await client2.threads.getState(threadId);
376696
377225
  return [head];
376697
377226
  };
376698
- extractThread = async (client2, thread, userSource) => {
377227
+ extractThread = async (client2, thread, userSource, schemaCache, onWarn) => {
376699
377228
  const threadId = thread.thread_id;
376700
377229
  const checkpoints = await readCheckpoints(client2, threadId);
376701
377230
  const graphResolution = resolveGraphId(thread, checkpoints);
@@ -376713,9 +377242,27 @@ var init_extract2 = __esm({
376713
377242
  }
376714
377243
  const messages = readMessages(thread, checkpoints);
376715
377244
  const lastActivityAt = readLastActivityAt(thread, checkpoints);
376716
- const rawRuns = await client2.runs.list(threadId, { limit: FULL_HISTORY_LIMIT });
377245
+ const rawRuns = await client2.runs.list(threadId, {
377246
+ limit: FULL_HISTORY_LIMIT
377247
+ });
376717
377248
  const sortedRuns = sortRunsChronologically(rawRuns);
376718
- const synthetic = synthesizeSingleRun(threadId, messages, lastActivityAt);
377249
+ const runErrors = readRunErrors(checkpoints);
377250
+ const headError = readTaskError(checkpoints[0]);
377251
+ const pendingInterrupts = readPendingInterrupts(checkpoints[0], thread);
377252
+ const stateSnapshot = await readStateSnapshot(
377253
+ client2,
377254
+ thread,
377255
+ checkpoints,
377256
+ sortedRuns.at(-1)?.assistant_id ?? graphResolution.graphId,
377257
+ schemaCache,
377258
+ onWarn
377259
+ );
377260
+ const synthetic = synthesizeSingleRun(
377261
+ threadId,
377262
+ messages,
377263
+ lastActivityAt,
377264
+ stateSnapshot !== void 0 || pendingInterrupts.length > 0 || headError !== void 0
377265
+ );
376719
377266
  const runs = sortedRuns.length === 0 && synthetic !== null ? [synthetic] : sortedRuns;
376720
377267
  const spans = partitionMessagesByRun(messages, runs);
376721
377268
  const normalizedRuns = [];
@@ -376723,7 +377270,13 @@ var init_extract2 = __esm({
376723
377270
  for (const span of spans) {
376724
377271
  const slice = messages.slice(cursor, cursor + span.messageCount);
376725
377272
  cursor += span.messageCount;
376726
- normalizedRuns.push(normalizeRun(span, slice));
377273
+ const normalized = normalizeRun(span, slice);
377274
+ const recordedError = sortedRuns.length === 0 ? headError : runErrors.get(normalized.sourceRunId);
377275
+ if (sortedRuns.length === 0 && recordedError !== void 0)
377276
+ normalized.status = "error";
377277
+ if (normalized.status === "error" && recordedError !== void 0)
377278
+ normalized.errorMessage = recordedError;
377279
+ normalizedRuns.push(normalized);
376727
377280
  }
376728
377281
  const endUserId = resolveEndUserId(userSource, thread, checkpoints);
376729
377282
  const conversation = {
@@ -376732,6 +377285,8 @@ var init_extract2 = __esm({
376732
377285
  sourceBackend: "server",
376733
377286
  endUserId,
376734
377287
  ...lastActivityAt !== void 0 ? { lastActivityAt } : {},
377288
+ ...stateSnapshot !== void 0 ? { stateSnapshot } : {},
377289
+ ...pendingInterrupts.length > 0 ? { pendingInterrupts } : {},
376735
377290
  runs: normalizedRuns
376736
377291
  };
376737
377292
  return {
@@ -379045,7 +379600,7 @@ function createSlackIngressUrl(input) {
379045
379600
  return new URL(input.path, ingressBaseUrl).toString();
379046
379601
  }
379047
379602
  function createSlackAppDisplayName(channelDisplayName) {
379048
- return [...channelDisplayName].slice(0, 35).join("");
379603
+ return [...channelDisplayName].slice(0, SLACK_APP_NAME_MAX_LENGTH).join("");
379049
379604
  }
379050
379605
  function normalizeSlackIdentity(value) {
379051
379606
  return value.normalize("NFKD").toLowerCase().replace(/[^a-z0-9]+/gu, "-").replace(/^-+|-+$/gu, "").slice(0, 80).replace(/-+$/gu, "");
@@ -379058,6 +379613,48 @@ function createSlackBotDisplayName(channelDisplayName, fallbackName = DEFAULT_SL
379058
379613
  const safeFallback = normalizeSlackIdentity(fallbackName);
379059
379614
  return safeFallback && !RESERVED_SLACK_IDENTITIES.has(safeFallback) ? safeFallback : DEFAULT_SLACK_IDENTITY;
379060
379615
  }
379616
+ function reservedWordIn(candidate) {
379617
+ const folded = candidate.normalize("NFKD").toLowerCase();
379618
+ return SLACK_RESERVED_NAME_WORDS.find(
379619
+ (word) => folded.includes(word.toLowerCase())
379620
+ );
379621
+ }
379622
+ function suggestSlackDisplayName(channelName) {
379623
+ const words = channelName.normalize("NFKD").toLowerCase().split(/[^a-z0-9]+/u).filter((word) => word.length > 0 && reservedWordIn(word) === void 0).map((word) => `${word.slice(0, 1).toUpperCase()}${word.slice(1)}`);
379624
+ const suggestion = [...words.join(" ")].slice(0, SLACK_APP_NAME_MAX_LENGTH).join("").trim();
379625
+ return suggestion.length > 0 ? suggestion : DEFAULT_SLACK_APP_NAME;
379626
+ }
379627
+ function validateSlackDisplayName(input) {
379628
+ const appName = input.channelDisplayName.trim();
379629
+ const suggestion = suggestSlackDisplayName(input.channelName);
379630
+ if (appName.length === 0) {
379631
+ return {
379632
+ message: `A Slack app needs a name: Slack rejects a manifest whose display_information.name is empty. Pass --display-name, for example "${suggestion}".`,
379633
+ status: "invalid",
379634
+ suggestion,
379635
+ violation: "empty"
379636
+ };
379637
+ }
379638
+ const length = [...appName].length;
379639
+ if (length > SLACK_APP_NAME_MAX_LENGTH) {
379640
+ return {
379641
+ message: `A Slack app name may be at most ${SLACK_APP_NAME_MAX_LENGTH} characters, and "${appName}" is ${length}. Pass a shorter --display-name, for example "${suggestion}".`,
379642
+ status: "invalid",
379643
+ suggestion,
379644
+ violation: "too_long"
379645
+ };
379646
+ }
379647
+ const reserved = reservedWordIn(appName) ?? reservedWordIn(createSlackBotDisplayName(appName, input.channelName));
379648
+ if (reserved !== void 0) {
379649
+ return {
379650
+ message: `A Slack app name and bot display name may not contain "${reserved}"; Slack refuses to create the app. Pass a different --display-name, for example "${suggestion}".`,
379651
+ status: "invalid",
379652
+ suggestion,
379653
+ violation: "reserved_word"
379654
+ };
379655
+ }
379656
+ return { status: "ok" };
379657
+ }
379061
379658
  function createSlackInviteCommand(channelDisplayName, fallbackName) {
379062
379659
  return `/invite @${createSlackBotDisplayName(
379063
379660
  channelDisplayName,
@@ -379116,12 +379713,13 @@ function createSlackManifestInstallUrl(manifest) {
379116
379713
  url4.searchParams.set("manifest_yaml", manifest);
379117
379714
  return url4.toString();
379118
379715
  }
379119
- var SLACK_EVENTS_INGRESS_PATH, SLACK_INTERACTIVITY_INGRESS_PATH, DEFAULT_SLACK_IDENTITY, RESERVED_SLACK_IDENTITIES, REQUIRED_SLACK_BOT_SCOPES, REQUIRED_SLACK_BOT_SCOPE_COUNT, SLACK_PREINSTALL_GRANTED_SCOPES, SLACK_PREINSTALL_SCOPE_COUNT;
379716
+ var SLACK_EVENTS_INGRESS_PATH, SLACK_INTERACTIVITY_INGRESS_PATH, SLACK_APP_NAME_MAX_LENGTH, DEFAULT_SLACK_IDENTITY, RESERVED_SLACK_IDENTITIES, SLACK_RESERVED_NAME_WORDS, DEFAULT_SLACK_APP_NAME, REQUIRED_SLACK_BOT_SCOPES, REQUIRED_SLACK_BOT_SCOPE_COUNT, SLACK_PREINSTALL_GRANTED_SCOPES, SLACK_PREINSTALL_SCOPE_COUNT;
379120
379717
  var init_slack = __esm({
379121
379718
  "libs/channels-setup/src/slack.ts"() {
379122
379719
  "use strict";
379123
379720
  SLACK_EVENTS_INGRESS_PATH = "/api/channels/adapters/slack/events";
379124
379721
  SLACK_INTERACTIVITY_INGRESS_PATH = "/api/channels/adapters/slack/interactivity";
379722
+ SLACK_APP_NAME_MAX_LENGTH = 35;
379125
379723
  DEFAULT_SLACK_IDENTITY = "intelligence-agent";
379126
379724
  RESERVED_SLACK_IDENTITIES = /* @__PURE__ */ new Set([
379127
379725
  "channel",
@@ -379129,6 +379727,8 @@ var init_slack = __esm({
379129
379727
  "here",
379130
379728
  "slackbot"
379131
379729
  ]);
379730
+ SLACK_RESERVED_NAME_WORDS = Object.freeze(["Slack"]);
379731
+ DEFAULT_SLACK_APP_NAME = "Intelligence Agent";
379132
379732
  REQUIRED_SLACK_BOT_SCOPES = Object.freeze([
379133
379733
  "app_mentions:read",
379134
379734
  "assistant:write",
@@ -380897,9 +381497,26 @@ function delay2(ms) {
380897
381497
  setTimeout(resolve9, ms);
380898
381498
  });
380899
381499
  }
380900
- function runInstallOnce(cwd2, command2) {
381500
+ function formatTimeoutTail(command2, timeoutMs) {
381501
+ return `\`${command2}\` stopped responding after ${timeoutMs} ms and was stopped. Check the network and the npm registry configuration, then run it by hand.`;
381502
+ }
381503
+ function runInstallOnce(cwd2, command2, timeoutMs) {
380901
381504
  return new Promise((resolve9) => {
380902
- const child = spawn4(command2, { cwd: cwd2, shell: true, stdio: ["ignore", "pipe", "pipe"] });
381505
+ const child = spawn4(command2, {
381506
+ cwd: cwd2,
381507
+ shell: true,
381508
+ stdio: ["ignore", "pipe", "pipe"],
381509
+ ...OWN_PROCESS_GROUP
381510
+ });
381511
+ let timedOut = false;
381512
+ const timeout = armChildTimeout(
381513
+ child,
381514
+ timeoutMs,
381515
+ () => {
381516
+ timedOut = true;
381517
+ },
381518
+ { ownsProcessGroup: true }
381519
+ );
380903
381520
  const stdoutDecoder = new StringDecoder("utf8");
380904
381521
  const stderrDecoder = new StringDecoder("utf8");
380905
381522
  let stdout = "";
@@ -380917,22 +381534,26 @@ function runInstallOnce(cwd2, command2) {
380917
381534
  }
380918
381535
  });
380919
381536
  child.once("error", (error98) => {
381537
+ timeout.cancel();
380920
381538
  resolve9({
380921
381539
  ok: false,
380922
381540
  code: null,
380923
381541
  stdoutTail: "",
380924
381542
  stderrTail: "",
380925
- spawnError: error98.message
381543
+ spawnError: error98.message,
381544
+ timedOut
380926
381545
  });
380927
381546
  });
380928
381547
  child.once("close", (code) => {
381548
+ timeout.cancel();
380929
381549
  stdout += stdoutDecoder.end();
380930
381550
  stderr += stderrDecoder.end();
380931
381551
  resolve9({
380932
381552
  ok: code === 0,
380933
381553
  code,
380934
381554
  stdoutTail: stdout.slice(-STDOUT_TAIL_LIMIT).trim(),
380935
- stderrTail: stderr.slice(-STDERR_TAIL_LIMIT).trim()
381555
+ stderrTail: stderr.slice(-STDERR_TAIL_LIMIT).trim(),
381556
+ timedOut
380936
381557
  });
380937
381558
  });
380938
381559
  });
@@ -380941,14 +381562,15 @@ async function installDependencies({
380941
381562
  cwd: cwd2,
380942
381563
  command: command2,
380943
381564
  log,
380944
- retryDelayMs = DEFAULT_RETRY_DELAY_MS
381565
+ retryDelayMs = DEFAULT_RETRY_DELAY_MS,
381566
+ timeoutMs = DEFAULT_INSTALL_TIMEOUT_MS
380945
381567
  }) {
380946
381568
  let lastAttempt;
380947
381569
  for (let attempt = 1; attempt <= INSTALL_MAX_ATTEMPTS; attempt += 1) {
380948
381570
  if (attempt > 1 && retryDelayMs > 0) {
380949
381571
  await delay2(retryDelayMs);
380950
381572
  }
380951
- lastAttempt = await runInstallOnce(cwd2, command2);
381573
+ lastAttempt = await runInstallOnce(cwd2, command2, timeoutMs);
380952
381574
  if (lastAttempt.ok) {
380953
381575
  if (attempt > 1) {
380954
381576
  log?.("info", {
@@ -380960,6 +381582,18 @@ async function installDependencies({
380960
381582
  }
380961
381583
  return { ok: true };
380962
381584
  }
381585
+ if (lastAttempt.timedOut) {
381586
+ log?.("error", {
381587
+ event: "install_timed_out",
381588
+ command: command2,
381589
+ cwd: cwd2,
381590
+ attempt,
381591
+ timeoutMs,
381592
+ stdoutTail: lastAttempt.stdoutTail,
381593
+ stderrTail: lastAttempt.stderrTail
381594
+ });
381595
+ return { ok: false, stderrTail: formatTimeoutTail(command2, timeoutMs) };
381596
+ }
380963
381597
  log?.("error", {
380964
381598
  event: "install_failed",
380965
381599
  command: command2,
@@ -380977,14 +381611,16 @@ async function installDependencies({
380977
381611
  stderrTail: lastAttempt?.spawnError ?? lastAttempt?.stderrTail ?? "install failed"
380978
381612
  };
380979
381613
  }
380980
- var STDERR_TAIL_LIMIT, STDOUT_TAIL_LIMIT, INSTALL_MAX_ATTEMPTS, DEFAULT_RETRY_DELAY_MS;
381614
+ var STDERR_TAIL_LIMIT, STDOUT_TAIL_LIMIT, INSTALL_MAX_ATTEMPTS, DEFAULT_RETRY_DELAY_MS, DEFAULT_INSTALL_TIMEOUT_MS;
380981
381615
  var init_install_dependencies = __esm({
380982
381616
  "apps/cli/src/services/install-dependencies.ts"() {
380983
381617
  "use strict";
381618
+ init_child_timeout();
380984
381619
  STDERR_TAIL_LIMIT = 2e3;
380985
381620
  STDOUT_TAIL_LIMIT = 4e3;
380986
381621
  INSTALL_MAX_ATTEMPTS = 2;
380987
381622
  DEFAULT_RETRY_DELAY_MS = 1e3;
381623
+ DEFAULT_INSTALL_TIMEOUT_MS = 10 * 6e4;
380988
381624
  }
380989
381625
  });
380990
381626
 
@@ -382182,7 +382818,35 @@ var init_channels_state = __esm({
382182
382818
  });
382183
382819
 
382184
382820
  // apps/cli/src/services/channels-flow.ts
382821
+ function slackDisplayNameRefusal(adapter2, channelName, displayName) {
382822
+ if (adapter2 !== "slack") {
382823
+ return void 0;
382824
+ }
382825
+ const validated = validateSlackDisplayName({
382826
+ channelDisplayName: displayName,
382827
+ channelName
382828
+ });
382829
+ if (validated.status === "ok") {
382830
+ return void 0;
382831
+ }
382832
+ return {
382833
+ code: CHANNELS_FLOW_CODES.slackDisplayNameInvalid,
382834
+ message: validated.message,
382835
+ status: "failed"
382836
+ };
382837
+ }
382185
382838
  function resolveIdentity(input) {
382839
+ const resolved = resolveChannelIdentity(input);
382840
+ if (resolved.status === "failed") {
382841
+ return resolved;
382842
+ }
382843
+ return slackDisplayNameRefusal(
382844
+ input.adapter,
382845
+ resolved.name,
382846
+ resolved.displayName
382847
+ ) ?? resolved;
382848
+ }
382849
+ function resolveChannelIdentity(input) {
382186
382850
  if (input.channelName !== void 0) {
382187
382851
  const validated = validateChannelName(input.channelName);
382188
382852
  if (validated.status === "invalid") {
@@ -382263,6 +382927,22 @@ async function runChannelsAdd(input, deps) {
382263
382927
  );
382264
382928
  const wasDeclared = alreadyDeclared?.providers[adapter2] !== void 0;
382265
382929
  const effectiveDisplayName = input.displayName ?? alreadyDeclared?.displayName ?? displayName;
382930
+ const declaredRefusal = slackDisplayNameRefusal(
382931
+ adapter2,
382932
+ name,
382933
+ effectiveDisplayName
382934
+ );
382935
+ if (declaredRefusal !== void 0) {
382936
+ return failedEnvelope({
382937
+ channels: [],
382938
+ command: command2,
382939
+ diagnostics,
382940
+ error: {
382941
+ code: declaredRefusal.code,
382942
+ message: declaredRefusal.message
382943
+ }
382944
+ });
382945
+ }
382266
382946
  let config3 = configRead.config;
382267
382947
  if (!wasDeclared) {
382268
382948
  config3 = declareChannel(config3, {
@@ -382549,6 +383229,7 @@ var init_channels_flow = __esm({
382549
383229
  nameMissing: "CLI_CHANNELS_NAME_MISSING",
382550
383230
  nameUndecidable: "CLI_CHANNELS_NAME_UNDECIDABLE",
382551
383231
  notDeclared: "CLI_CHANNELS_NOT_DECLARED",
383232
+ slackDisplayNameInvalid: "CLI_CHANNELS_SLACK_DISPLAY_NAME_INVALID",
382552
383233
  stalled: "CLI_CHANNELS_RECONCILE_STALLED"
382553
383234
  });
382554
383235
  MAX_RECONCILE_STEPS = 8;
@@ -385081,6 +385762,8 @@ var init_onboarding_checkpoint = __esm({
385081
385762
  "apps/cli/src/services/onboarding-checkpoint.ts"() {
385082
385763
  "use strict";
385083
385764
  CHECKPOINT_PHASES = [
385765
+ "research-dispatched",
385766
+ "surface-probed",
385084
385767
  "research-returned",
385085
385768
  "starter-cloned",
385086
385769
  "plan-written",
@@ -385104,6 +385787,17 @@ function resolveAgentFrameworkAlias(value) {
385104
385787
  return void 0;
385105
385788
  return ONBOARDING_AGENT_FRAMEWORK_ALIASES[value] ?? value;
385106
385789
  }
385790
+ function terminalReasonForRoute(route) {
385791
+ for (let index2 = route.length - 1; index2 >= 0; index2 -= 1) {
385792
+ const node = route[index2];
385793
+ if (node === void 0)
385794
+ continue;
385795
+ if (Object.prototype.hasOwnProperty.call(TERMINAL_NODES, node))
385796
+ continue;
385797
+ return STAGE_BY_NODE[node] ?? STAGE_BY_DIRECTORY[node.split("/")[0] ?? ""] ?? "other";
385798
+ }
385799
+ return void 0;
385800
+ }
385107
385801
  function unprovenBaselineRefusal(startingState, route, proof) {
385108
385802
  if (startingState !== "both-oss" && startingState !== "both-copilotkit-unproved") {
385109
385803
  return void 0;
@@ -385150,7 +385844,7 @@ function requireOnboardingChoice(flag, value, choices) {
385150
385844
  }
385151
385845
  return selected;
385152
385846
  }
385153
- var ONBOARDING_STARTING_STATES, ONBOARDING_AGENT_FRAMEWORKS, ONBOARDING_AGENT_FRAMEWORK_ALIASES, ONBOARDING_FRONTENDS, ONBOARDING_PROOF_STEPS, ONBOARDING_PROOF_OUTCOMES, ABSENCE_STATES, OSS_BASELINE_NODE, TERMINAL_NODES, REPOSITORY_RESEARCH_NODE;
385847
+ var ONBOARDING_STARTING_STATES, ONBOARDING_AGENT_FRAMEWORKS, ONBOARDING_AGENT_FRAMEWORK_ALIASES, ONBOARDING_FRONTENDS, ONBOARDING_PROOF_STEPS, ONBOARDING_PROOF_OUTCOMES, ABSENCE_STATES, OSS_BASELINE_NODE, TERMINAL_NODES, STAGE_BY_DIRECTORY, STAGE_BY_NODE, REPOSITORY_RESEARCH_NODE;
385154
385848
  var init_onboarding_classification = __esm({
385155
385849
  "apps/cli/src/services/onboarding-classification.ts"() {
385156
385850
  "use strict";
@@ -385227,6 +385921,25 @@ var init_onboarding_classification = __esm({
385227
385921
  "stopped/run-failed": "run-failed",
385228
385922
  "unsupported/no-validated-path": "unsupported"
385229
385923
  };
385924
+ STAGE_BY_DIRECTORY = {
385925
+ authenticate: "authentication",
385926
+ conversion: "plan",
385927
+ credentials: "credentials",
385928
+ feature: "feature",
385929
+ framework: "journey",
385930
+ frontend: "journey",
385931
+ implementation: "implementation",
385932
+ proof: "validation",
385933
+ research: "research",
385934
+ starter: "journey"
385935
+ };
385936
+ STAGE_BY_NODE = {
385937
+ "subagent/create-plan": "plan",
385938
+ "subagent/implement-and-validate": "implementation",
385939
+ "subagent/inspect-repository": "research",
385940
+ "subagent/prove-oss-baseline": "validation",
385941
+ "subagent/prove-round-trip": "validation"
385942
+ };
385230
385943
  REPOSITORY_RESEARCH_NODE = "subagent/inspect-repository";
385231
385944
  }
385232
385945
  });
@@ -385334,7 +386047,7 @@ var init_onboarding_resume = __esm({
385334
386047
 
385335
386048
  // apps/cli/src/services/onboarding-protected-paths.ts
385336
386049
  import { execFileSync as execFileSync5 } from "node:child_process";
385337
- import { createHash as createHash7 } from "node:crypto";
386050
+ import { createHash as createHash8 } from "node:crypto";
385338
386051
  import { existsSync as existsSync21, readFileSync as readFileSync22, readdirSync as readdirSync5, statSync as statSync4 } from "node:fs";
385339
386052
  import { isAbsolute, join as join28, relative as relative3, resolve as resolve7, sep as sep3 } from "node:path";
385340
386053
  function deriveProjectFiles(root2) {
@@ -385465,7 +386178,7 @@ function digestOf(root2, relativePath) {
385465
386178
  if (!existsSync21(absolute))
385466
386179
  return {};
385467
386180
  return {
385468
- digest: createHash7("sha256").update(readFileSync22(absolute)).digest("hex")
386181
+ digest: createHash8("sha256").update(readFileSync22(absolute)).digest("hex")
385469
386182
  };
385470
386183
  } catch {
385471
386184
  return "unreadable";
@@ -385548,6 +386261,12 @@ function captureEntry(root2, relativePath, derived) {
385548
386261
  }
385549
386262
  function captureProtectedPaths(dependencies, input) {
385550
386263
  const root2 = resolveAnchoredRoot(dependencies);
386264
+ const enclosingRepository = findRepositoryRoot(
386265
+ resolveOnboardingRepositoryRoot(dependencies.cwd)
386266
+ );
386267
+ if (enclosingRepository !== void 0 && enclosingRepository !== root2) {
386268
+ return { status: "blocked", reason: "root-outside-project", detail: root2 };
386269
+ }
385551
386270
  const stored = readManifest(dependencies);
385552
386271
  const ownBaseline = stored !== void 0 && stored !== "malformed" && stored.runId === input.runId ? stored : void 0;
385553
386272
  const derive = ownBaseline === void 0;
@@ -386134,6 +386853,80 @@ function authorizeProtectedPathChange(dependencies, input) {
386134
386853
  authorized: byPath(authorized)
386135
386854
  };
386136
386855
  }
386856
+ function commitsAfterCapture(root2, capturedAt) {
386857
+ const since = capturedAt.replace(/\.\d+Z$/, "Z");
386858
+ let output;
386859
+ try {
386860
+ output = execFileSync5(
386861
+ "git",
386862
+ ["log", `--since=${since}`, "--name-only", "--format=%H"],
386863
+ { cwd: root2, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }
386864
+ );
386865
+ } catch {
386866
+ return "failed";
386867
+ }
386868
+ const lines = output.split("\n").filter((line) => line.length > 0);
386869
+ if (lines.length === 0)
386870
+ return "none";
386871
+ return lines.filter((line) => !/^[0-9a-f]{40}$/.test(line));
386872
+ }
386873
+ function readProjectChanges(dependencies, input) {
386874
+ const root2 = resolveAnchoredRoot(dependencies);
386875
+ const stored = readManifest(dependencies);
386876
+ if (stored === void 0) {
386877
+ return { status: "blocked", reason: "no-baseline", detail: input.runId };
386878
+ }
386879
+ if (stored === "malformed") {
386880
+ return {
386881
+ status: "blocked",
386882
+ reason: "unreadable-baseline",
386883
+ detail: input.runId
386884
+ };
386885
+ }
386886
+ if (stored.runId !== input.runId) {
386887
+ return { status: "blocked", reason: "run-mismatch", detail: stored.runId };
386888
+ }
386889
+ const derived = deriveChangedPaths(root2);
386890
+ if (derived === "failed") {
386891
+ return { status: "blocked", reason: "git-failed", detail: root2 };
386892
+ }
386893
+ const current = derived === "no-repository" ? deriveProjectFiles(root2) : derived;
386894
+ const baseline = new Map(
386895
+ stored.entries.map((entry) => [entry.path, entry.digest])
386896
+ );
386897
+ const changed = [];
386898
+ for (const relativePath of new Set(current)) {
386899
+ if (isGraphOwned(relativePath))
386900
+ continue;
386901
+ const read = digestOf(root2, relativePath);
386902
+ if (read === "unreadable") {
386903
+ changed.push(relativePath);
386904
+ continue;
386905
+ }
386906
+ const held = baseline.has(relativePath);
386907
+ if (!held || baseline.get(relativePath) !== read.digest) {
386908
+ changed.push(relativePath);
386909
+ }
386910
+ }
386911
+ const ordered = [...changed].sort(
386912
+ (left, right) => left < right ? -1 : left > right ? 1 : 0
386913
+ );
386914
+ if (ordered.length > 0 || derived === "no-repository") {
386915
+ return { status: "passed", runId: input.runId, changed: ordered };
386916
+ }
386917
+ const committed = commitsAfterCapture(root2, stored.capturedAt);
386918
+ if (committed === "failed" || committed === "none") {
386919
+ return { status: "passed", runId: input.runId, changed: ordered };
386920
+ }
386921
+ return {
386922
+ status: "passed",
386923
+ runId: input.runId,
386924
+ changed: [...new Set(committed)].sort(
386925
+ (left, right) => left < right ? -1 : left > right ? 1 : 0
386926
+ ),
386927
+ committedAfterCapture: true
386928
+ };
386929
+ }
386137
386930
  var SKIPPED_DIRECTORIES3, GRAPH_OWNED_SUFFIXES;
386138
386931
  var init_onboarding_protected_paths = __esm({
386139
386932
  "apps/cli/src/services/onboarding-protected-paths.ts"() {
@@ -387068,7 +387861,7 @@ async function runOnboard(argv, dependencies) {
387068
387861
  ...onboardingIntentProperties(deps),
387069
387862
  onboarding_run_id: runId2,
387070
387863
  cli_version: deps.cliVersion,
387071
- coding_agent: normalizeCodingAgent(parsed.codingAgent)
387864
+ ...codingAgentProperty(parsed.codingAgent)
387072
387865
  }
387073
387866
  });
387074
387867
  deps.stdout.write(`Coding agent recorded for run ${runId2}.
@@ -387143,6 +387936,11 @@ async function runOnboard(argv, dependencies) {
387143
387936
  const check4 = parseSurfaceCheck(blocked2.rest);
387144
387937
  if (check4 === void 0)
387145
387938
  throw new Error(SURFACE_CHECK_USAGE);
387939
+ const unchanged = unchangedProjectRefusal(deps, runId);
387940
+ if (unchanged !== void 0) {
387941
+ deps.stdout.write(unchanged);
387942
+ return;
387943
+ }
387146
387944
  const accepted = readAcceptedDriftBestEffort(deps, runId);
387147
387945
  const authorized = readAuthorizationsBestEffort(deps, runId);
387148
387946
  const removed = readRemovedPathsBestEffort(deps, runId);
@@ -387476,6 +388274,12 @@ Onboarding protects the developer\u2019s own tree and captures nothing beyond it
387476
388274
  "git-failed": `\`git status\` failed in ${result.detail}, so the protected set could not be
387477
388275
  derived. Nothing was captured: an empty baseline would read as "nothing here
387478
388276
  needs protecting", which is the opposite of what just happened.
388277
+ `,
388278
+ "root-outside-project": `This run is anchored at ${result.detail}, above the repository this command
388279
+ ran in. Nothing was captured: a baseline derived up there reads every file
388280
+ below it, including repositories this run has no business in.
388281
+ Run \`copilotkit onboard start --run <id>\` here to give this project a run of
388282
+ its own, or run this step from the directory the run started in.
387479
388283
  `
387480
388284
  }[result.reason];
387481
388285
  return `Status: blocked
@@ -388075,10 +388879,11 @@ function reportingRefusal(dependencies, runId, code, extra, read) {
388075
388879
  throw error98;
388076
388880
  }
388077
388881
  }
388078
- function recordTerminalWhenReached(dependencies, runId, promptName) {
388882
+ function recordTerminalWhenReached(dependencies, runId, promptName, routeBefore) {
388079
388883
  const terminal = TERMINAL_NODES[promptName];
388080
388884
  if (terminal === void 0)
388081
388885
  return;
388886
+ const reason = terminalReasonForRoute(routeBefore);
388082
388887
  markRunEndedBestEffort(dependencies, runId);
388083
388888
  recordBestEffort(dependencies, {
388084
388889
  event: "cli.onboarding.terminal_reached",
@@ -388088,6 +388893,10 @@ function recordTerminalWhenReached(dependencies, runId, promptName) {
388088
388893
  onboarding_run_id: runId,
388089
388894
  cli_version: dependencies.cliVersion,
388090
388895
  terminal,
388896
+ // Omitted rather than sent as `other` when the route names no earlier
388897
+ // step: a route that could not be read has not said the reason is
388898
+ // unknown, it has said nothing at all.
388899
+ ...reason === void 0 ? {} : { terminal_reason: reason },
388091
388900
  ...detectionProperties(dependencies)
388092
388901
  }
388093
388902
  });
@@ -388506,6 +389315,42 @@ function readAuthorizationsBestEffort(dependencies, runId) {
388506
389315
  return [];
388507
389316
  }
388508
389317
  }
389318
+ function unchangedProjectRefusal(dependencies, runId) {
389319
+ let changes;
389320
+ try {
389321
+ changes = readProjectChanges(
389322
+ { cwd: dependencies.cwd, store: dependencies.store },
389323
+ { runId }
389324
+ );
389325
+ } catch {
389326
+ return void 0;
389327
+ }
389328
+ if (changes.status === "blocked")
389329
+ return void 0;
389330
+ if (changes.committedAfterCapture === true)
389331
+ return void 0;
389332
+ if (changes.changed.length > 0)
389333
+ return void 0;
389334
+ return [
389335
+ "Status: blocked",
389336
+ "no-changes-in-project",
389337
+ "This project holds no change since its protected baseline was captured: no",
389338
+ "tracked file was modified, and nothing new was added beyond the files this",
389339
+ "graph writes itself, `.env` and `.copilotkit/project.json`. Ignored files do",
389340
+ "not count as work.",
389341
+ "",
389342
+ "A run that built something and left this tree untouched built it somewhere",
389343
+ "else. The usual cause is an implementation subagent that worked in its own",
389344
+ "git worktree, a branch checkout, or a copy of the project, and reported back",
389345
+ "without bringing the changes here. This is not a preservation failure: no",
389346
+ "protected path was changed, and none had to be.",
389347
+ "",
389348
+ "Bring those changes into this project, then run `onboard audit` and this",
389349
+ "command again. Onboarding is not complete until they are here: the developer",
389350
+ "is left with the project in front of them, not the one the work was done in.",
389351
+ ""
389352
+ ].join("\n");
389353
+ }
388509
389354
  function readAcceptedDriftBestEffort(dependencies, runId) {
388510
389355
  try {
388511
389356
  return readAcceptedDrift(
@@ -388528,7 +389373,7 @@ function recordStarted(dependencies, runId, origin, idOrigin, codingAgent) {
388528
389373
  ...onboardingIntentProperties(dependencies),
388529
389374
  onboarding_run_id: runId,
388530
389375
  cli_version: dependencies.cliVersion,
388531
- coding_agent: normalizeCodingAgent(codingAgent),
389376
+ ...codingAgentProperty(codingAgent),
388532
389377
  started_by: origin,
388533
389378
  run_id_origin: idOrigin
388534
389379
  }
@@ -388568,7 +389413,7 @@ function writePrompt(dependencies, runId, prompt) {
388568
389413
  `);
388569
389414
  }
388570
389415
  recordRouteBestEffort(dependencies, runId, prompt.name);
388571
- recordTerminalWhenReached(dependencies, runId, prompt.name);
389416
+ recordTerminalWhenReached(dependencies, runId, prompt.name, routeBefore);
388572
389417
  const routeAfter = readRouteBestEffort(dependencies);
388573
389418
  recordBestEffort(dependencies, {
388574
389419
  event: "cli.onboarding.prompt_served",
@@ -391737,6 +392582,42 @@ var init_kite = __esm({
391737
392582
  }
391738
392583
  });
391739
392584
 
392585
+ // apps/cli/src/node-version.ts
392586
+ var MINIMUM_NODE_VERSION = "20.9.0";
392587
+ function readVersionParts(version6) {
392588
+ const match2 = /^v?(\d+)\.(\d+)\.(\d+)/.exec(version6.trim());
392589
+ if (match2 === null)
392590
+ return void 0;
392591
+ return [Number(match2[1]), Number(match2[2]), Number(match2[3])];
392592
+ }
392593
+ function meetsMinimumNodeVersion(running, minimum = MINIMUM_NODE_VERSION) {
392594
+ const current = readVersionParts(running);
392595
+ const floor = readVersionParts(minimum);
392596
+ if (current === void 0 || floor === void 0)
392597
+ return true;
392598
+ for (let index2 = 0; index2 < current.length; index2 += 1) {
392599
+ if (current[index2] !== floor[index2])
392600
+ return current[index2] > floor[index2];
392601
+ }
392602
+ return true;
392603
+ }
392604
+ function formatUnsupportedNodeMessage(running, minimum = MINIMUM_NODE_VERSION) {
392605
+ return `copilotkit needs Node.js ${minimum} or later.
392606
+ This machine is running Node.js ${running}.
392607
+
392608
+ Upgrade Node.js, then run the command again. A version manager installs a
392609
+ newer one beside the current one:
392610
+
392611
+ nvm install 22
392612
+ `;
392613
+ }
392614
+
392615
+ // apps/cli/src/node-version-gate.ts
392616
+ if (!meetsMinimumNodeVersion(process.versions.node)) {
392617
+ process.stderr.write(formatUnsupportedNodeMessage(process.versions.node));
392618
+ process.exit(1);
392619
+ }
392620
+
391740
392621
  // apps/cli/src/index.ts
391741
392622
  init_event_properties();
391742
392623
  init_types();
@@ -392098,11 +392979,18 @@ records their answer with --unplanned, which marks the consent as taken outside
392098
392979
  the plan wherever it is printed. The flag is refused before the plan is
392099
392980
  reported, so it can never stand in for the plan's own approval.
392100
392981
 
392982
+ Complete refuses a run whose project holds no change since that baseline was
392983
+ captured, and prints Status: blocked with no-changes-in-project. The files
392984
+ onboarding writes itself do not count, and neither do ignored files. Work done
392985
+ in another worktree, a branch checkout, or a copy of the project leaves the
392986
+ developer nothing, so bring the changes into this project, then run audit and
392987
+ complete again.
392988
+
392101
392989
  Checkpoint reports progress from inside a step, where the graph would
392102
392990
  otherwise say nothing between one prompt and the next. --phase takes one of:
392103
- research-returned, starter-cloned, plan-written, container-surveyed,
392104
- container-settled, build-validated, journey-attempted, repair-attempted,
392105
- delegation-unavailable. Pass --attempt <1-9>
392991
+ research-dispatched, surface-probed, research-returned, starter-cloned,
392992
+ plan-written, container-surveyed, container-settled, build-validated,
392993
+ journey-attempted, repair-attempted, delegation-unavailable. Pass --attempt <1-9>
392106
392994
  where the step loops, so a repair cycle can be counted.
392107
392995
  A refused checkpoint exits zero and prints the closed set. It is called from
392108
392996
  the middle of the longest step of a run, and a non-zero exit there reads as a
@@ -394588,14 +395476,17 @@ async function main(rawArgv = process.argv.slice(2)) {
394588
395476
  const helpText = helpTopic === null ? null : helpTextForTopic(helpTopic);
394589
395477
  const command2 = argv[0];
394590
395478
  if (helpText !== null) {
395479
+ const helpBase = {
395480
+ command: "help",
395481
+ subcommand: helpTopic ?? "unknown"
395482
+ };
394591
395483
  recordTelemetryEvent({
394592
- properties: {
394593
- command: "help",
394594
- outcome: "started",
394595
- subcommand: helpTopic ?? "unknown"
394596
- }
395484
+ properties: { ...helpBase, outcome: "started" }
394597
395485
  });
394598
395486
  process.stdout.write(helpText);
395487
+ recordTelemetryEvent({
395488
+ properties: { ...helpBase, outcome: "succeeded" }
395489
+ });
394599
395490
  return;
394600
395491
  }
394601
395492
  await applyGlobalArgs(globalArgs);
@@ -394651,6 +395542,7 @@ function installSignalHandlers() {
394651
395542
  shuttingDown = true;
394652
395543
  const safety = setTimeout(() => process.exit(130), 2e3);
394653
395544
  safety.unref();
395545
+ recordAbandonedInvocation();
394654
395546
  const reraise = () => {
394655
395547
  process.kill(process.pid, signal);
394656
395548
  };