copilotkit 4.9.60 → 4.10.1

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 (77) hide show
  1. package/README.md +10 -3
  2. package/cli-build-info.json +8 -8
  3. package/index.js +336 -172
  4. package/onboarding/index.json +106 -18
  5. package/onboarding/prompts/authenticate/start.md +41 -202
  6. package/onboarding/prompts/conversion/plan.md +3 -3
  7. package/onboarding/prompts/credentials/finalize-plan.md +15 -129
  8. package/onboarding/prompts/credentials/plan.md +20 -20
  9. package/onboarding/prompts/credentials/settle-credentials.md +153 -0
  10. package/onboarding/prompts/credentials/write-plan.md +93 -0
  11. package/onboarding/prompts/fallback/best-effort.md +12 -9
  12. package/onboarding/prompts/feature/a2ui/implement.md +35 -6
  13. package/onboarding/prompts/feature/a2ui/proof.md +30 -6
  14. package/onboarding/prompts/feature/a2ui/start.md +29 -6
  15. package/onboarding/prompts/feature/channels/implement.md +70 -0
  16. package/onboarding/prompts/feature/channels/proof.md +60 -0
  17. package/onboarding/prompts/feature/channels/start.md +87 -0
  18. package/onboarding/prompts/feature/chat-suggestions/implement.md +36 -6
  19. package/onboarding/prompts/feature/chat-suggestions/proof.md +30 -5
  20. package/onboarding/prompts/feature/chat-suggestions/start.md +29 -6
  21. package/onboarding/prompts/feature/complete.md +11 -0
  22. package/onboarding/prompts/feature/learning/implement.md +41 -12
  23. package/onboarding/prompts/feature/learning/proof.md +32 -6
  24. package/onboarding/prompts/feature/learning/start.md +28 -5
  25. package/onboarding/prompts/feature/open-generative-ui/implement.md +37 -6
  26. package/onboarding/prompts/feature/open-generative-ui/proof.md +30 -5
  27. package/onboarding/prompts/feature/open-generative-ui/start.md +29 -6
  28. package/onboarding/prompts/feature/realtime-sync/implement.md +36 -7
  29. package/onboarding/prompts/feature/realtime-sync/proof.md +29 -5
  30. package/onboarding/prompts/feature/realtime-sync/start.md +28 -5
  31. package/onboarding/prompts/feature/rich-threads/implement.md +37 -8
  32. package/onboarding/prompts/feature/rich-threads/proof.md +31 -5
  33. package/onboarding/prompts/feature/rich-threads/start.md +28 -5
  34. package/onboarding/prompts/feature/stop.md +17 -8
  35. package/onboarding/prompts/feature/voice/implement.md +35 -6
  36. package/onboarding/prompts/feature/voice/proof.md +30 -5
  37. package/onboarding/prompts/feature/voice/start.md +29 -6
  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 +2 -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 +2 -2
  45. package/onboarding/prompts/framework/google-adk.md +2 -2
  46. package/onboarding/prompts/framework/langgraph-fastapi.md +2 -2
  47. package/onboarding/prompts/framework/langgraph-python.md +2 -2
  48. package/onboarding/prompts/framework/langgraph-typescript.md +2 -2
  49. package/onboarding/prompts/framework/llamaindex.md +2 -2
  50. package/onboarding/prompts/framework/mastra.md +2 -2
  51. package/onboarding/prompts/framework/ms-agent-dotnet.md +2 -2
  52. package/onboarding/prompts/framework/ms-agent-harness-dotnet.md +2 -2
  53. package/onboarding/prompts/framework/ms-agent-python.md +2 -2
  54. package/onboarding/prompts/framework/pydantic-ai.md +2 -2
  55. package/onboarding/prompts/framework/strands-python.md +2 -2
  56. package/onboarding/prompts/framework/strands-typescript.md +2 -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 +6 -6
  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 +75 -15
  64. package/onboarding/prompts/proof/complete.md +21 -8
  65. package/onboarding/prompts/proof/oss-baseline.md +6 -5
  66. package/onboarding/prompts/proof/round-trip.md +27 -14
  67. package/onboarding/prompts/research/gather.md +121 -0
  68. package/onboarding/prompts/research/route.md +81 -0
  69. package/onboarding/prompts/starter/clone.md +18 -9
  70. package/onboarding/prompts/stopped/run-failed.md +44 -0
  71. package/onboarding/prompts/subagent/create-plan.md +32 -1
  72. package/onboarding/prompts/subagent/implement-and-validate.md +9 -1
  73. package/onboarding/prompts/subagent/prove-oss-baseline.md +1 -1
  74. package/onboarding/prompts/subagent/prove-round-trip.md +52 -8
  75. package/onboarding/prompts/unsupported/no-validated-path.md +9 -6
  76. package/package.json +1 -1
  77. package/release/release-tool.js +39 -3
package/index.js CHANGED
@@ -96,14 +96,14 @@ function getTelemetryEndpointUrl() {
96
96
  }
97
97
  function getBuildInfo() {
98
98
  return {
99
- version: true ? "4.9.60" : "dev",
100
- buildNumber: true ? "34616405214" : "dev",
101
- commitSha: true ? "5f0f9a7cf15492544f1341f562fa5cd55387099c" : "dev",
99
+ version: true ? "4.10.1" : "dev",
100
+ buildNumber: true ? "35080956003" : "dev",
101
+ commitSha: true ? "b5b41dba88259cb723cfd2560be82b234417efa7" : "dev",
102
102
  copilotKitCommit: getTemplateRef()
103
103
  };
104
104
  }
105
105
  function getTemplateRef() {
106
- return true ? "d1584b840f904674b470be5d2b16c4ccca99c4f4" : "main";
106
+ return true ? "7e6964fc11092b685bbea62bc331d5d177b738c1" : "main";
107
107
  }
108
108
  function getC15tBackendUrl() {
109
109
  return true ? "https://calm-hazelnut-joy-copilotkit.inth.app" : "";
@@ -1033,6 +1033,12 @@ function classifyError(err2, depth = 0) {
1033
1033
  if (err2.name === "AbortError") {
1034
1034
  return "timeout";
1035
1035
  }
1036
+ const apiErrorCode = err2.code;
1037
+ if (apiErrorCode === "LEARNING_NOT_ENABLED")
1038
+ return "learning_not_enabled";
1039
+ if (apiErrorCode === "LEARNING_CONTAINER_NOT_FOUND") {
1040
+ return "learning_container_absent";
1041
+ }
1036
1042
  const status = err2.status;
1037
1043
  if (err2.name === "ApiClientError" && typeof status === "number") {
1038
1044
  if (status === 401 || status === 403)
@@ -1070,7 +1076,7 @@ function classifyError(err2, depth = 0) {
1070
1076
  return "validation";
1071
1077
  if (code === "ONBOARDING_PROMPT_UNREADABLE")
1072
1078
  return "filesystem";
1073
- if (code === "CLI_PRODUCT_BINARY_TOO_LARGE" || code === "LEARNING_CANDIDATE_CONFLICT" || code === "LEARNING_CANDIDATE_SETTLED" || code === "LEARNING_CANDIDATE_ID_INVALID" || code === "LEARNING_CONTAINER_ID_INVALID" || code === "LEARNING_CONTAINER_INPUT_INVALID" || code === "LEARNING_CONTAINER_NOT_FOUND" || code === "LEARNING_CONTAINER_RESPONSE_INVALID" || code === "LEARNING_PROJECT_ID_INVALID" || code === "LEARNING_RESPONSE_INVALID" || code === "LEARNING_SKILLS_BUNDLE_INVALID" || code === "LEARNING_SKILLS_INTEGRITY_FAILED" || code === "LEARNING_SKILLS_OUTPUT_EXISTS") {
1079
+ if (code === "CLI_PRODUCT_BINARY_TOO_LARGE" || code === "LEARNING_CANDIDATE_CONFLICT" || code === "LEARNING_CANDIDATE_SETTLED" || code === "LEARNING_CANDIDATE_ID_INVALID" || code === "LEARNING_CONTAINER_ID_INVALID" || code === "LEARNING_CONTAINER_INPUT_INVALID" || code === "LEARNING_CONTAINER_RESPONSE_INVALID" || code === "LEARNING_PROJECT_ID_INVALID" || code === "LEARNING_RESPONSE_INVALID" || code === "LEARNING_SKILLS_BUNDLE_INVALID" || code === "LEARNING_SKILLS_INTEGRITY_FAILED" || code === "LEARNING_SKILLS_OUTPUT_EXISTS") {
1074
1080
  return "validation";
1075
1081
  }
1076
1082
  if (code === "KEY_PROVISION_FAILED")
@@ -28858,6 +28864,29 @@ function recordServedPrompt(dependencies, runId, promptName) {
28858
28864
  route: [...previous, promptName]
28859
28865
  });
28860
28866
  }
28867
+ function markRunEnded(dependencies, runId) {
28868
+ const key = stateKey("route", resolveAnchoredRoot(dependencies));
28869
+ const stored = readStoredRoute(dependencies.store, key);
28870
+ if (stored === void 0 || stored.runId !== runId)
28871
+ return;
28872
+ dependencies.store.set(key, { ...stored, ended: true });
28873
+ }
28874
+ function readAbandonedRun(dependencies, currentRunId) {
28875
+ const stored = readStoredRoute(
28876
+ dependencies.store,
28877
+ stateKey("route", resolveAnchoredRoot(dependencies))
28878
+ );
28879
+ if (stored === void 0)
28880
+ return void 0;
28881
+ if (stored.runId === currentRunId)
28882
+ return void 0;
28883
+ if (stored.ended === true)
28884
+ return void 0;
28885
+ const lastPrompt = stored.route[stored.route.length - 1];
28886
+ if (lastPrompt === void 0)
28887
+ return void 0;
28888
+ return { runId: stored.runId, lastPrompt, steps: stored.route.length };
28889
+ }
28861
28890
  function readOnboardingRoute(dependencies) {
28862
28891
  const root2 = resolveAnchoredRoot(dependencies);
28863
28892
  const stored = readStoredRoute(dependencies.store, stateKey("route", root2));
@@ -66808,7 +66837,7 @@ var require_websocket = __commonJS({
66808
66837
  var http4 = __require("http");
66809
66838
  var net = __require("net");
66810
66839
  var tls = __require("tls");
66811
- var { randomBytes: randomBytes3, createHash: createHash8 } = __require("crypto");
66840
+ var { randomBytes: randomBytes4, createHash: createHash8 } = __require("crypto");
66812
66841
  var { Duplex, Readable: Readable5 } = __require("stream");
66813
66842
  var { URL: URL7 } = __require("url");
66814
66843
  var PerMessageDeflate2 = require_permessage_deflate();
@@ -67355,7 +67384,7 @@ var require_websocket = __commonJS({
67355
67384
  }
67356
67385
  }
67357
67386
  const defaultPort = isSecure ? 443 : 80;
67358
- const key = randomBytes3(16).toString("base64");
67387
+ const key = randomBytes4(16).toString("base64");
67359
67388
  const request = isSecure ? https2.request : http4.request;
67360
67389
  const protocolSet = /* @__PURE__ */ new Set();
67361
67390
  let perMessageDeflate;
@@ -91701,7 +91730,7 @@ function formatTelemetryNotice(privacyPolicyUrl) {
91701
91730
  return [
91702
91731
  "The CopilotKit CLI collects usage data to help improve the product.",
91703
91732
  "While you are signed in, that data is linked to your CopilotKit account.",
91704
- "The onboarding feedback command may send up to 2,048 UTF-8 bytes of text.",
91733
+ "The onboarding friction command sends up to 2,048 UTF-8 bytes of text.",
91705
91734
  "",
91706
91735
  " Disable anytime: copilotkit telemetry disable (or set DO_NOT_TRACK=1)",
91707
91736
  ` Privacy policy: ${privacyPolicyUrl}`,
@@ -91748,6 +91777,15 @@ function createTelemetryService(deps) {
91748
91777
  return typeof deps.installationId === "function" ? deps.installationId() : deps.installationId;
91749
91778
  }
91750
91779
  async function sendOne(prepared) {
91780
+ if (prepared.installationId === "") {
91781
+ deps.logger.error({
91782
+ msg: "telemetry.dropped.no_identity",
91783
+ event: prepared.body.event,
91784
+ outcome: prepared.outcome,
91785
+ command: prepared.command
91786
+ });
91787
+ return { status: "no_identity" };
91788
+ }
91751
91789
  const controller = new AbortController();
91752
91790
  const timer = setTimeout(() => controller.abort(), perRequestTimeoutMs);
91753
91791
  timer.unref?.();
@@ -91763,33 +91801,38 @@ function createTelemetryService(deps) {
91763
91801
  signal: controller.signal
91764
91802
  });
91765
91803
  if (!res.ok) {
91804
+ const latencyMs = Date.now() - started;
91766
91805
  deps.logger.warn({
91767
91806
  msg: "telemetry.sink.failed",
91807
+ event: prepared.body.event,
91768
91808
  status: res.status,
91769
- latency_ms: Date.now() - started,
91809
+ latency_ms: latencyMs,
91770
91810
  outcome: prepared.outcome,
91771
91811
  command: prepared.command
91772
91812
  });
91773
- return false;
91813
+ return { status: "http_error", httpStatus: res.status, latencyMs };
91774
91814
  }
91775
91815
  deps.logger.debug({
91776
91816
  msg: "telemetry.sink.succeeded",
91817
+ event: prepared.body.event,
91777
91818
  status: res.status,
91778
91819
  latency_ms: Date.now() - started,
91779
91820
  outcome: prepared.outcome,
91780
91821
  command: prepared.command
91781
91822
  });
91782
- return true;
91823
+ return { status: "sent" };
91783
91824
  } catch (err2) {
91784
91825
  const isAbort = err2 instanceof Error && err2.name === "AbortError";
91826
+ const latencyMs = Date.now() - started;
91785
91827
  deps.logger.warn({
91786
91828
  msg: "telemetry.sink.failed",
91787
- latency_ms: Date.now() - started,
91829
+ event: prepared.body.event,
91830
+ latency_ms: latencyMs,
91788
91831
  outcome: prepared.outcome,
91789
91832
  command: prepared.command,
91790
91833
  error_code: isAbort ? "timeout" : "network"
91791
91834
  });
91792
- return false;
91835
+ return isAbort ? { status: "timeout", timeoutMs: perRequestTimeoutMs, latencyMs } : { status: "network", latencyMs };
91793
91836
  } finally {
91794
91837
  clearTimeout(timer);
91795
91838
  }
@@ -91816,6 +91859,7 @@ function createTelemetryService(deps) {
91816
91859
  if (inFlight.size >= maxInFlight) {
91817
91860
  deps.logger.error({
91818
91861
  msg: "telemetry.dropped.queue_full",
91862
+ event: event.event ?? CLI_TELEMETRY_EVENT_NAME,
91819
91863
  outcome: event.properties.outcome,
91820
91864
  command: event.properties.command
91821
91865
  });
@@ -91831,8 +91875,17 @@ function createTelemetryService(deps) {
91831
91875
  });
91832
91876
  }
91833
91877
  async function submitEvent(event) {
91834
- if (!deps.enabled || inFlight.size >= maxInFlight)
91835
- return false;
91878
+ if (!deps.enabled)
91879
+ return { status: "disabled" };
91880
+ if (inFlight.size >= maxInFlight) {
91881
+ deps.logger.error({
91882
+ msg: "telemetry.dropped.queue_full",
91883
+ event: event.event ?? CLI_TELEMETRY_EVENT_NAME,
91884
+ outcome: event.properties.outcome,
91885
+ command: event.properties.command
91886
+ });
91887
+ return { status: "queue_full", inFlight: inFlight.size };
91888
+ }
91836
91889
  const promise3 = (async () => {
91837
91890
  await new Promise((resolve9) => setImmediate(resolve9));
91838
91891
  return await sendOne(prepareEvent(event));
@@ -92017,14 +92070,47 @@ async function submitTelemetryEvent(event) {
92017
92070
  if (!gate.send)
92018
92071
  return { status: "declined" };
92019
92072
  try {
92020
- const accepted = await getTelemetry().submitEvent(
92073
+ const delivery = await getTelemetry().submitEvent(
92021
92074
  withProjectIdentity(event)
92022
92075
  );
92023
- return accepted ? { status: "sent" } : { status: "failed", detail: "the transport did not accept the event" };
92076
+ return describeDelivery(delivery);
92024
92077
  } catch (error98) {
92025
92078
  return { status: "failed", detail: describeSubmissionError(error98) };
92026
92079
  }
92027
92080
  }
92081
+ function describeDelivery(delivery) {
92082
+ switch (delivery.status) {
92083
+ case "sent":
92084
+ return { status: "sent" };
92085
+ case "disabled":
92086
+ return { status: "declined" };
92087
+ case "no_identity":
92088
+ return {
92089
+ status: "failed",
92090
+ detail: "this install has no telemetry id, so nothing was sent"
92091
+ };
92092
+ case "queue_full":
92093
+ return {
92094
+ status: "failed",
92095
+ detail: `the send queue was full at ${delivery.inFlight} requests, so nothing was sent`
92096
+ };
92097
+ case "http_error":
92098
+ return {
92099
+ status: "failed",
92100
+ detail: `the sink refused the event with HTTP ${delivery.httpStatus}`
92101
+ };
92102
+ case "timeout":
92103
+ return {
92104
+ status: "failed",
92105
+ detail: `the send timed out after ${delivery.timeoutMs}ms`
92106
+ };
92107
+ case "network":
92108
+ return {
92109
+ status: "failed",
92110
+ detail: "the network request failed before the sink answered"
92111
+ };
92112
+ }
92113
+ }
92028
92114
  function describeSubmissionError(error98) {
92029
92115
  if (error98 instanceof Error && error98.message !== "")
92030
92116
  return error98.message;
@@ -92227,7 +92313,8 @@ function recordChannelsStage(input) {
92227
92313
  // the builder writes every key explicitly from its input so customer
92228
92314
  // content cannot leak in by construction, and reading ambient process
92229
92315
  // state inside it would break that guarantee. Both values are booleans.
92230
- ...currentCliStateProperties(input.command ?? "channels")
92316
+ ...currentCliStateProperties(input.command ?? "channels"),
92317
+ ...currentOnboardingRunProperties()
92231
92318
  }
92232
92319
  });
92233
92320
  }
@@ -94899,13 +94986,25 @@ import * as fs18 from "node:fs";
94899
94986
  import * as path14 from "node:path";
94900
94987
  import * as os7 from "node:os";
94901
94988
  import { execFileSync as execFileSync3 } from "node:child_process";
94989
+ function isCredentialEnvFile(entry) {
94990
+ if (!entry.startsWith(".env"))
94991
+ return false;
94992
+ if (ENV_TEMPLATE_SUFFIXES.some((suffix) => entry.endsWith(suffix)))
94993
+ return false;
94994
+ return entry === ".env" || entry.startsWith(".env.");
94995
+ }
94996
+ function entryHoldsProject(entry) {
94997
+ if (isCredentialEnvFile(entry))
94998
+ return true;
94999
+ return PROJECT_DIRECTORY_NAMES.has(entry) || PROJECT_MANIFEST_NAMES.has(entry);
95000
+ }
94902
95001
  function isProjectDirOccupied(projectDir) {
94903
- return fs18.existsSync(projectDir) && fs18.readdirSync(projectDir).length > 0;
95002
+ return fs18.existsSync(projectDir) && fs18.readdirSync(projectDir).some(entryHoldsProject);
94904
95003
  }
94905
95004
  function assertProjectDirAvailable(projectDir) {
94906
95005
  if (isProjectDirOccupied(projectDir)) {
94907
95006
  throw tagError(
94908
- new Error(`${projectDir} already exists and is not empty`),
95007
+ new Error(`${projectDir} already holds a project`),
94909
95008
  TELEMETRY_ERROR_CODES.PREREQUISITE_MISSING
94910
95009
  );
94911
95010
  }
@@ -95155,12 +95254,36 @@ async function initializeProjectGit(projectDir) {
95155
95254
  }
95156
95255
  return { kind: "initialized" };
95157
95256
  }
95158
- var TEST_HARNESS_ARTIFACTS, LICENSE_TOKEN_LINE_RE;
95257
+ var PROJECT_DIRECTORY_NAMES, PROJECT_MANIFEST_NAMES, ENV_TEMPLATE_SUFFIXES, TEST_HARNESS_ARTIFACTS, LICENSE_TOKEN_LINE_RE;
95159
95258
  var init_project_scaffold = __esm({
95160
95259
  "apps/cli/src/services/project-scaffold.ts"() {
95161
95260
  "use strict";
95162
95261
  init_repository_root();
95163
95262
  init_event_properties();
95263
+ PROJECT_DIRECTORY_NAMES = /* @__PURE__ */ new Set([
95264
+ "agent",
95265
+ "api",
95266
+ "app",
95267
+ "components",
95268
+ "lib",
95269
+ "packages",
95270
+ "pages",
95271
+ "server",
95272
+ "src",
95273
+ "web"
95274
+ ]);
95275
+ PROJECT_MANIFEST_NAMES = /* @__PURE__ */ new Set([
95276
+ "Cargo.toml",
95277
+ "Gemfile",
95278
+ "build.gradle",
95279
+ "composer.json",
95280
+ "go.mod",
95281
+ "package.json",
95282
+ "pom.xml",
95283
+ "pyproject.toml",
95284
+ "requirements.txt"
95285
+ ]);
95286
+ ENV_TEMPLATE_SUFFIXES = [".example", ".sample", ".template"];
95164
95287
  TEST_HARNESS_ARTIFACTS = [
95165
95288
  "docker",
95166
95289
  ".dockerignore",
@@ -97734,13 +97857,15 @@ var init_clipboard = __esm({
97734
97857
  });
97735
97858
 
97736
97859
  // apps/cli/src/services/agent-prompt.ts
97860
+ import { randomBytes as randomBytes2 } from "node:crypto";
97737
97861
  function buildSkillsOnboardPrompt() {
97738
97862
  return SKILLS_ONBOARD_AGENT_PROMPT;
97739
97863
  }
97740
97864
  function buildChannelsSetupPrompt() {
97741
- return CHANNELS_SETUP_PROMPT;
97865
+ const runId = randomBytes2(9).toString("base64url");
97866
+ return `npx --yes copilotkit@latest onboard start --intent add-channels --run=${runId}`;
97742
97867
  }
97743
- var SKILLS_ONBOARD_AGENT_PROMPT, CHANNELS_SETUP_SKILL, CHANNELS_SETUP_PROMPT;
97868
+ var SKILLS_ONBOARD_AGENT_PROMPT, CHANNELS_SETUP_SKILL;
97744
97869
  var init_agent_prompt = __esm({
97745
97870
  "apps/cli/src/services/agent-prompt.ts"() {
97746
97871
  "use strict";
@@ -97754,7 +97879,6 @@ Use the copilotkit-setup skill to:
97754
97879
 
97755
97880
  Start by inspecting my repo, then walk me through the setup.`;
97756
97881
  CHANNELS_SETUP_SKILL = "channels-setup";
97757
- CHANNELS_SETUP_PROMPT = `Use the \`${CHANNELS_SETUP_SKILL}\` skill to set up a Channel for this project.`;
97758
97882
  }
97759
97883
  });
97760
97884
 
@@ -100013,6 +100137,70 @@ var init_learning = __esm({
100013
100137
  }
100014
100138
  });
100015
100139
 
100140
+ // libs/app-api-contracts/src/learning-schedule.ts
100141
+ var localTimeSchema, timeZoneSchema, learningScheduleInputSchema, learningScheduleSchema, learningScheduleResponseSchema, projectLearningScheduleSchema, projectLearningScheduleResponseSchema;
100142
+ var init_learning_schedule = __esm({
100143
+ "libs/app-api-contracts/src/learning-schedule.ts"() {
100144
+ "use strict";
100145
+ init_zod();
100146
+ localTimeSchema = external_exports.string().regex(/^(?:[01]\d|2[0-3]):[0-5]\d$/, {
100147
+ message: "Use a local time in HH:mm format."
100148
+ }).length(5);
100149
+ timeZoneSchema = external_exports.string().min(1).max(255).refine(
100150
+ (timeZone) => {
100151
+ if (/^[+-]/.test(timeZone) || timeZone.trim() !== timeZone)
100152
+ return false;
100153
+ try {
100154
+ new Intl.DateTimeFormat("en-US", { timeZone }).format(0);
100155
+ return true;
100156
+ } catch {
100157
+ return false;
100158
+ }
100159
+ },
100160
+ { message: "Use a valid IANA time zone." }
100161
+ );
100162
+ learningScheduleInputSchema = external_exports.object({
100163
+ localTime: localTimeSchema,
100164
+ timeZone: timeZoneSchema
100165
+ }).strict();
100166
+ learningScheduleSchema = learningScheduleInputSchema.extend({
100167
+ organizationId: external_exports.string(),
100168
+ nextRunAt: external_exports.string().datetime(),
100169
+ updatedAt: external_exports.string().datetime()
100170
+ });
100171
+ learningScheduleResponseSchema = external_exports.object({
100172
+ schedule: learningScheduleSchema
100173
+ }).strict();
100174
+ projectLearningScheduleSchema = learningScheduleSchema.extend({
100175
+ projectId: external_exports.number().int().positive(),
100176
+ source: external_exports.enum(["organization", "project"]),
100177
+ automationEnabled: external_exports.boolean().optional()
100178
+ });
100179
+ projectLearningScheduleResponseSchema = external_exports.object({ schedule: projectLearningScheduleSchema }).strict();
100180
+ }
100181
+ });
100182
+
100183
+ // libs/app-api-contracts/src/learning-automation.ts
100184
+ var learningAutomationReadinessSchema, learningAutomationReadinessResponseSchema;
100185
+ var init_learning_automation = __esm({
100186
+ "libs/app-api-contracts/src/learning-automation.ts"() {
100187
+ "use strict";
100188
+ init_zod();
100189
+ learningAutomationReadinessSchema = external_exports.object({
100190
+ containerId: external_exports.string().min(1).max(64),
100191
+ projectId: external_exports.number().int().positive(),
100192
+ enabled: external_exports.boolean(),
100193
+ eligibleThreadCount: external_exports.number().int().nonnegative(),
100194
+ requiredThreadCount: external_exports.number().int().positive(),
100195
+ blocked: external_exports.boolean(),
100196
+ activeRun: external_exports.boolean()
100197
+ });
100198
+ learningAutomationReadinessResponseSchema = external_exports.object({
100199
+ automation: learningAutomationReadinessSchema
100200
+ }).strict();
100201
+ }
100202
+ });
100203
+
100016
100204
  // libs/app-api-contracts/src/threads.ts
100017
100205
  var threadIdSchema, appUserAliasSchema, collapseAppUserAliases, refuseInternalAppUserForms, threadAppUserSchema, threadReadQuerySchema;
100018
100206
  var init_threads = __esm({
@@ -100124,6 +100312,8 @@ var init_src6 = __esm({
100124
100312
  init_inspector_metadata();
100125
100313
  init_inspector_learning();
100126
100314
  init_learning();
100315
+ init_learning_schedule();
100316
+ init_learning_automation();
100127
100317
  init_threads();
100128
100318
  init_usage();
100129
100319
  }
@@ -141432,7 +141622,7 @@ var require_websocket2 = __commonJS({
141432
141622
  var http4 = __require("http");
141433
141623
  var net = __require("net");
141434
141624
  var tls = __require("tls");
141435
- var { randomBytes: randomBytes3, createHash: createHash8 } = __require("crypto");
141625
+ var { randomBytes: randomBytes4, createHash: createHash8 } = __require("crypto");
141436
141626
  var { Duplex, Readable: Readable5 } = __require("stream");
141437
141627
  var { URL: URL7 } = __require("url");
141438
141628
  var PerMessageDeflate2 = require_permessage_deflate2();
@@ -141987,7 +142177,7 @@ var require_websocket2 = __commonJS({
141987
142177
  }
141988
142178
  }
141989
142179
  const defaultPort = isSecure ? 443 : 80;
141990
- const key = randomBytes3(16).toString("base64");
142180
+ const key = randomBytes4(16).toString("base64");
141991
142181
  const request = isSecure ? https2.request : http4.request;
141992
142182
  const protocolSet = /* @__PURE__ */ new Set();
141993
142183
  let perMessageDeflate;
@@ -383639,7 +383829,7 @@ function createHostedProjectApiClient(auth2) {
383639
383829
  productOrganizationId: auth2.clerkOrgId
383640
383830
  });
383641
383831
  }
383642
- function buildInitNextSteps(templateDefinition, projectName, result, unsatisfiedKeys, installAlreadyRan = false, mockProvider = void 0) {
383832
+ function buildInitNextSteps(templateDefinition, projectName, result, unsatisfiedKeys, installAlreadyRan = false, mockProvider = void 0, mockAvailable = false) {
383643
383833
  const missingPrerequisites = templateDefinition.prerequisites.filter(
383644
383834
  (prerequisite) => result.missingPrerequisites.includes(prerequisite.command)
383645
383835
  );
@@ -383700,6 +383890,13 @@ function buildInitNextSteps(templateDefinition, projectName, result, unsatisfied
383700
383890
  code: `${requirement.key}=${requirement.example}`
383701
383891
  });
383702
383892
  }
383893
+ if (unsatisfiedKeys.length > 0 && mockProvider === void 0 && mockAvailable) {
383894
+ steps.push({ text: " Or run without a key:" });
383895
+ steps.push({
383896
+ text: ` Start a local mock model${SEP2}`,
383897
+ code: "copilotkit mock"
383898
+ });
383899
+ }
383703
383900
  for (const note of templateDefinition.setupNotes ?? []) {
383704
383901
  steps.push(note.code !== void 0 ? { ...note } : { text: note.text });
383705
383902
  }
@@ -384492,7 +384689,12 @@ function ScaffoldProgress({
384492
384689
  result,
384493
384690
  unsatisfied,
384494
384691
  installAlreadyRan,
384495
- activeMockProvider
384692
+ activeMockProvider,
384693
+ // Gated on the flag as well as on the framework. `copilotkit mock` is
384694
+ // dark in released binaries (`cli.aimock-mock-mode`, prod: false), and a
384695
+ // run told to reach for a command its own CLI does not implement spends
384696
+ // real time discovering that -- which is itself a reported friction.
384697
+ scaffoldedMockProvider !== void 0 && isCliFlagEnabled("cli.aimock-mock-mode")
384496
384698
  )
384497
384699
  );
384498
384700
  setScaffoldWarnings((prev) => mergeScaffoldWarnings(prev, result.warnings));
@@ -385464,7 +385666,16 @@ function reviewFrictionReport(input) {
385464
385666
  `--category must be one of: ${FRICTION_CATEGORIES.join(", ")}.`
385465
385667
  );
385466
385668
  }
385467
- if (input.costSeconds === void 0 || !COST_SECONDS_PATTERN.test(input.costSeconds) || Number(input.costSeconds) > MAX_COST_SECONDS_ESTIMATED) {
385669
+ const phase = input.phase === void 0 ? DEFAULT_FRICTION_PHASE : FRICTION_PHASES.find((candidate) => candidate === input.phase);
385670
+ if (phase === void 0) {
385671
+ return refuse(
385672
+ "FRICTION_PHASE_INVALID",
385673
+ `--phase must be one of: ${FRICTION_PHASES.join(", ")}.`
385674
+ );
385675
+ }
385676
+ const costOmitted = input.costSeconds === void 0;
385677
+ const costMalformed = !costOmitted && (!COST_SECONDS_PATTERN.test(input.costSeconds) || Number(input.costSeconds) > MAX_COST_SECONDS_ESTIMATED);
385678
+ if (costMalformed || costOmitted && phase !== "stop") {
385468
385679
  return refuse(
385469
385680
  "FRICTION_COST_INVALID",
385470
385681
  `--cost-seconds must be a whole number of seconds from 0 to ${MAX_COST_SECONDS_ESTIMATED}.`
@@ -385516,7 +385727,10 @@ function reviewFrictionReport(input) {
385516
385727
  ok: true,
385517
385728
  report: {
385518
385729
  category,
385519
- costSecondsEstimated: Number(input.costSeconds),
385730
+ phase,
385731
+ // Spread so a stop report that named no cost leaves the key off rather
385732
+ // than reporting a zero it never estimated.
385733
+ ...costOmitted ? {} : { costSecondsEstimated: Number(input.costSeconds) },
385520
385734
  // Spread so an absent path leaves the key off entirely, matching how the
385521
385735
  // telemetry properties treat every optional dimension.
385522
385736
  ...docsPath === void 0 ? {} : { docsPath },
@@ -385524,7 +385738,7 @@ function reviewFrictionReport(input) {
385524
385738
  }
385525
385739
  };
385526
385740
  }
385527
- var FRICTION_CATEGORIES, MAX_FRICTION_TEXT_CHARS, MAX_FRICTION_TEXT_NEWLINES, MAX_COST_SECONDS_ESTIMATED, MAX_FRICTION_INPUT_BYTES, FRICTION_SIZE_LIMIT, MAX_FRICTION_DOCS_PATH_CHARS, DOCS_PATH_PATTERN, COST_SECONDS_PATTERN;
385741
+ var FRICTION_CATEGORIES, FRICTION_PHASES, DEFAULT_FRICTION_PHASE, MAX_FRICTION_TEXT_CHARS, MAX_FRICTION_TEXT_NEWLINES, MAX_COST_SECONDS_ESTIMATED, MAX_FRICTION_INPUT_BYTES, FRICTION_SIZE_LIMIT, MAX_FRICTION_DOCS_PATH_CHARS, DOCS_PATH_PATTERN, COST_SECONDS_PATTERN;
385528
385742
  var init_onboarding_friction = __esm({
385529
385743
  "apps/cli/src/services/onboarding-friction.ts"() {
385530
385744
  "use strict";
@@ -385541,6 +385755,8 @@ var init_onboarding_friction = __esm({
385541
385755
  "validation-loop",
385542
385756
  "other"
385543
385757
  ];
385758
+ FRICTION_PHASES = ["repair", "stop", "completion"];
385759
+ DEFAULT_FRICTION_PHASE = "completion";
385544
385760
  MAX_FRICTION_TEXT_CHARS = 2e3;
385545
385761
  MAX_FRICTION_TEXT_NEWLINES = 3;
385546
385762
  MAX_COST_SECONDS_ESTIMATED = 86400;
@@ -385555,76 +385771,6 @@ var init_onboarding_friction = __esm({
385555
385771
  }
385556
385772
  });
385557
385773
 
385558
- // apps/cli/src/services/onboarding-feedback.ts
385559
- function refuse2(code, message) {
385560
- return { ok: false, refusal: { code, message } };
385561
- }
385562
- async function readFeedbackInput(stdin) {
385563
- const read = await readBoundedReportText(stdin, MAX_FEEDBACK_INPUT_BYTES);
385564
- if (read.ok)
385565
- return { ok: true, text: read.text };
385566
- if (read.kind === "invalid-utf8") {
385567
- return refuse2(
385568
- "ONBOARDING_FEEDBACK_INVALID_UTF8",
385569
- "Nothing was sent: the report is not valid UTF-8. Send it again as plain UTF-8 text."
385570
- );
385571
- }
385572
- return refuse2(
385573
- "ONBOARDING_FEEDBACK_TOO_LARGE",
385574
- `Nothing was sent: the report is too large to read. Shorten it to at most ${MAX_FEEDBACK_TEXT_BYTES} UTF-8 bytes and send it again.`
385575
- );
385576
- }
385577
- function reviewFeedbackReport(text2) {
385578
- const violation = reviewReportText({
385579
- text: text2,
385580
- size: FEEDBACK_SIZE_LIMIT,
385581
- maxNewlines: MAX_FEEDBACK_TEXT_NEWLINES
385582
- });
385583
- if (violation === void 0)
385584
- return { ok: true, text: text2.trim() };
385585
- switch (violation.kind) {
385586
- case "empty":
385587
- return refuse2(
385588
- "ONBOARDING_FEEDBACK_EMPTY",
385589
- "Nothing was sent: the report was empty. Name the step that failed, in one or two sentences, on standard input."
385590
- );
385591
- case "possible-secret":
385592
- return refuse2(
385593
- "ONBOARDING_FEEDBACK_POSSIBLE_SECRET",
385594
- `Nothing was sent: the report looks like it contains ${violation.shape}. Describe the problem in words and send it again without the value.`
385595
- );
385596
- case "code-block":
385597
- return refuse2(
385598
- "ONBOARDING_FEEDBACK_CODE_BLOCK",
385599
- "Nothing was sent: the report contains a fenced code block. Describe the problem in words, without source code, logs, or command output."
385600
- );
385601
- case "too-many-lines":
385602
- return refuse2(
385603
- "ONBOARDING_FEEDBACK_TOO_MANY_LINES",
385604
- `Nothing was sent: the report has more than ${MAX_FEEDBACK_TEXT_NEWLINES + 1} lines, so it reads as pasted output. Send at most ${MAX_FEEDBACK_TEXT_NEWLINES + 1} lines of plain prose.`
385605
- );
385606
- case "too-long":
385607
- return refuse2(
385608
- "ONBOARDING_FEEDBACK_TOO_LARGE",
385609
- `Nothing was sent: the report is ${violation.measured} UTF-8 bytes. Shorten it to at most ${MAX_FEEDBACK_TEXT_BYTES} and send it again.`
385610
- );
385611
- }
385612
- }
385613
- var MAX_FEEDBACK_TEXT_BYTES, MAX_FEEDBACK_TEXT_NEWLINES, MAX_FEEDBACK_INPUT_BYTES, FEEDBACK_SIZE_LIMIT;
385614
- var init_onboarding_feedback = __esm({
385615
- "apps/cli/src/services/onboarding-feedback.ts"() {
385616
- "use strict";
385617
- init_onboarding_report_text();
385618
- MAX_FEEDBACK_TEXT_BYTES = 2048;
385619
- MAX_FEEDBACK_TEXT_NEWLINES = 3;
385620
- MAX_FEEDBACK_INPUT_BYTES = 2050;
385621
- FEEDBACK_SIZE_LIMIT = {
385622
- unit: "utf8-bytes",
385623
- max: MAX_FEEDBACK_TEXT_BYTES
385624
- };
385625
- }
385626
- });
385627
-
385628
385774
  // apps/cli/src/services/onboarding-checkpoint.ts
385629
385775
  function reviewCheckpoint(input) {
385630
385776
  const phase = CHECKPOINT_PHASES.find((known) => known === input.phase);
@@ -385858,6 +386004,9 @@ function probeGraphOwned(root2, cwd2) {
385858
386004
  }
385859
386005
  return found;
385860
386006
  }
386007
+ function toRequestedPath(root2, path45) {
386008
+ return isAbsolute(path45) ? path45 : resolve7(root2, path45);
386009
+ }
385861
386010
  function toRepositoryRelative(root2, absolute) {
385862
386011
  const relativePath = relative3(root2, absolute);
385863
386012
  if (relativePath === "" || relativePath.startsWith(".."))
@@ -385888,7 +386037,7 @@ function captureProtectedPaths(dependencies, input) {
385888
386037
  const existing = ownBaseline?.entries ?? [];
385889
386038
  const requested = [];
385890
386039
  for (const path45 of input.paths) {
385891
- const absolute = isAbsolute(path45) ? path45 : resolve7(dependencies.cwd, path45);
386040
+ const absolute = toRequestedPath(root2, path45);
385892
386041
  const relativePath = toRepositoryRelative(root2, absolute);
385893
386042
  if (relativePath === void 0) {
385894
386043
  return {
@@ -386025,7 +386174,7 @@ function rebaselineProtectedPaths(dependencies, input) {
386025
386174
  }
386026
386175
  const targets = [];
386027
386176
  for (const path45 of input.paths) {
386028
- const absolute = isAbsolute(path45) ? path45 : resolve7(dependencies.cwd, path45);
386177
+ const absolute = toRequestedPath(root2, path45);
386029
386178
  const relativePath = toRepositoryRelative(root2, absolute);
386030
386179
  if (relativePath === void 0) {
386031
386180
  return { status: "blocked", reason: "unknown-path", detail: path45 };
@@ -386115,7 +386264,7 @@ function acceptProtectedPathDrift(dependencies, input) {
386115
386264
  const drift = /* @__PURE__ */ new Map();
386116
386265
  const accepted = [];
386117
386266
  for (const path45 of input.paths) {
386118
- const absolute = isAbsolute(path45) ? path45 : resolve7(dependencies.cwd, path45);
386267
+ const absolute = toRequestedPath(root2, path45);
386119
386268
  const relativePath = toRepositoryRelative(root2, absolute);
386120
386269
  if (relativePath === void 0) {
386121
386270
  return { status: "blocked", reason: "unknown-path", detail: path45 };
@@ -386218,7 +386367,7 @@ function acceptCredentialPlacement(dependencies, input) {
386218
386367
  const placed = /* @__PURE__ */ new Map();
386219
386368
  const accepted = [];
386220
386369
  for (const path45 of input.paths) {
386221
- const absolute = isAbsolute(path45) ? path45 : resolve7(dependencies.cwd, path45);
386370
+ const absolute = toRequestedPath(root2, path45);
386222
386371
  const relativePath = toRepositoryRelative(root2, absolute);
386223
386372
  if (relativePath === void 0) {
386224
386373
  return { status: "blocked", reason: "unknown-path", detail: path45 };
@@ -386367,7 +386516,7 @@ function authorizeProtectedPathChange(dependencies, input) {
386367
386516
  const priorDrift = /* @__PURE__ */ new Map();
386368
386517
  const authorized = [];
386369
386518
  for (const path45 of input.paths) {
386370
- const absolute = isAbsolute(path45) ? path45 : resolve7(dependencies.cwd, path45);
386519
+ const absolute = toRequestedPath(root2, path45);
386371
386520
  const relativePath = toRepositoryRelative(root2, absolute);
386372
386521
  if (relativePath === void 0) {
386373
386522
  return { status: "blocked", reason: "unknown-path", detail: path45 };
@@ -386488,6 +386637,11 @@ var init_onboarding_protected_paths = __esm({
386488
386637
  });
386489
386638
 
386490
386639
  // apps/cli/src/services/onboarding-classification.ts
386640
+ function resolveAgentFrameworkAlias(value) {
386641
+ if (value === void 0)
386642
+ return void 0;
386643
+ return ONBOARDING_AGENT_FRAMEWORK_ALIASES[value] ?? value;
386644
+ }
386491
386645
  function unprovenBaselineRefusal(startingState, route, proof) {
386492
386646
  if (startingState !== "both-oss" && startingState !== "both-copilotkit-unproved") {
386493
386647
  return void 0;
@@ -386534,7 +386688,7 @@ function requireOnboardingChoice(flag, value, choices) {
386534
386688
  }
386535
386689
  return selected;
386536
386690
  }
386537
- var ONBOARDING_STARTING_STATES, ONBOARDING_AGENT_FRAMEWORKS, ONBOARDING_FRONTENDS, ONBOARDING_PROOF_STEPS, ONBOARDING_PROOF_OUTCOMES, ABSENCE_STATES, OSS_BASELINE_NODE, TERMINAL_NODES, REPOSITORY_RESEARCH_NODE;
386691
+ 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;
386538
386692
  var init_onboarding_classification = __esm({
386539
386693
  "apps/cli/src/services/onboarding-classification.ts"() {
386540
386694
  "use strict";
@@ -386567,6 +386721,9 @@ var init_onboarding_classification = __esm({
386567
386721
  "strands-python",
386568
386722
  "strands-typescript"
386569
386723
  ];
386724
+ ONBOARDING_AGENT_FRAMEWORK_ALIASES = {
386725
+ langgraph: "langgraph-python"
386726
+ };
386570
386727
  ONBOARDING_FRONTENDS = [
386571
386728
  "react-spa",
386572
386729
  "nextjs",
@@ -386595,6 +386752,12 @@ var init_onboarding_classification = __esm({
386595
386752
  // feature run must not enter, because a stop reported from inside a route the
386596
386753
  // run never took is a stop that never happened.
386597
386754
  "feature/stop": "feature-blocked",
386755
+ // A run that broke gets its own ending. 52 outside runs ended at
386756
+ // `unsupported/no-validated-path` in the three weeks to 2026-09-13, and 10 of
386757
+ // them had classified as `built-in` with `nextjs` -- a stack this graph serves.
386758
+ // While one terminal absorbs both, "we do not support this" and "this run
386759
+ // broke" are the same row, and neither can be counted.
386760
+ "stopped/run-failed": "run-failed",
386598
386761
  "unsupported/no-validated-path": "unsupported"
386599
386762
  };
386600
386763
  REPOSITORY_RESEARCH_NODE = "subagent/inspect-repository";
@@ -386725,7 +386888,7 @@ __export(onboard_exports, {
386725
386888
  ONBOARD_SUBCOMMANDS: () => ONBOARD_SUBCOMMANDS,
386726
386889
  runOnboard: () => runOnboard
386727
386890
  });
386728
- import { randomBytes as randomBytes2 } from "node:crypto";
386891
+ import { randomBytes as randomBytes3 } from "node:crypto";
386729
386892
  import { parseArgs as parseArgs2 } from "node:util";
386730
386893
  async function runOnboard(argv, dependencies) {
386731
386894
  const deps = dependencies ?? {
@@ -386735,7 +386898,7 @@ async function runOnboard(argv, dependencies) {
386735
386898
  stderr: process.stderr,
386736
386899
  store: configStore,
386737
386900
  cliVersion: getBuildInfo().version,
386738
- randomRunId: () => randomBytes2(9).toString("base64url"),
386901
+ randomRunId: () => randomBytes3(9).toString("base64url"),
386739
386902
  loadPrompt: loadOnboardingPrompt,
386740
386903
  loadGraphTree: loadOnboardingGraphTree,
386741
386904
  loadStartPrompt: loadOnboardingStartPrompt,
@@ -386787,6 +386950,7 @@ async function runOnboard(argv, dependencies) {
386787
386950
  parsed.values["coding-agent"]
386788
386951
  );
386789
386952
  }
386953
+ recordAbandonedRunWhenFound(deps, binding.runId);
386790
386954
  printRunId(deps, binding.runId);
386791
386955
  await printGraphTree(deps);
386792
386956
  writePrompt(deps, binding.runId, startPrompt);
@@ -386848,6 +387012,7 @@ async function runOnboard(argv, dependencies) {
386848
387012
  throw new Error(SURFACE_CHECK_USAGE);
386849
387013
  const accepted = readAcceptedDriftBestEffort(deps, runId);
386850
387014
  const authorized = readAuthorizationsBestEffort(deps, runId);
387015
+ markRunEndedBestEffort(deps, runId);
386851
387016
  recordBestEffort(deps, {
386852
387017
  event: "cli.onboarding.completed",
386853
387018
  properties: {
@@ -386905,7 +387070,7 @@ async function runOnboard(argv, dependencies) {
386905
387070
  { requested_agent_framework: reportableSlug(requestedFramework) },
386906
387071
  () => requireOnboardingChoice(
386907
387072
  "--agent-framework",
386908
- requestedFramework,
387073
+ resolveAgentFrameworkAlias(requestedFramework),
386909
387074
  ONBOARDING_AGENT_FRAMEWORKS
386910
387075
  )
386911
387076
  );
@@ -386953,13 +387118,6 @@ async function runOnboard(argv, dependencies) {
386953
387118
  deps.stdout.write("Onboarding path included in telemetry when enabled.\n");
386954
387119
  return;
386955
387120
  }
386956
- if (subcommand === "feedback") {
386957
- if (argv.length !== 1) {
386958
- throw new Error("Usage: copilotkit onboard feedback");
386959
- }
386960
- await reportFeedback(deps, runId);
386961
- return;
386962
- }
386963
387121
  if (subcommand === "friction") {
386964
387122
  await reportFriction(deps, runId, argv.slice(1));
386965
387123
  return;
@@ -387627,6 +387785,7 @@ function recordTerminalWhenReached(dependencies, runId, promptName) {
387627
387785
  const terminal = TERMINAL_NODES[promptName];
387628
387786
  if (terminal === void 0)
387629
387787
  return;
387788
+ markRunEndedBestEffort(dependencies, runId);
387630
387789
  recordBestEffort(dependencies, {
387631
387790
  event: "cli.onboarding.terminal_reached",
387632
387791
  properties: {
@@ -387638,6 +387797,40 @@ function recordTerminalWhenReached(dependencies, runId, promptName) {
387638
387797
  }
387639
387798
  });
387640
387799
  }
387800
+ function recordAbandonedRunWhenFound(dependencies, currentRunId) {
387801
+ let abandoned;
387802
+ try {
387803
+ abandoned = readAbandonedRun(
387804
+ { cwd: dependencies.cwd, store: dependencies.store },
387805
+ currentRunId
387806
+ );
387807
+ } catch {
387808
+ return;
387809
+ }
387810
+ if (abandoned === void 0)
387811
+ return;
387812
+ recordBestEffort(dependencies, {
387813
+ event: "cli.onboarding.run_abandoned",
387814
+ properties: {
387815
+ command: "onboard",
387816
+ ...onboardingIntentProperties(dependencies),
387817
+ // The run that is reporting, the way every other event binds. The run
387818
+ // being reported cannot emit anything: it is over, and reporting it is
387819
+ // the whole point. It rides as its own property instead.
387820
+ onboarding_run_id: currentRunId,
387821
+ cli_version: dependencies.cliVersion,
387822
+ abandoned_run_id: abandoned.runId,
387823
+ abandoned_at_prompt: abandoned.lastPrompt,
387824
+ abandoned_after_steps: abandoned.steps
387825
+ }
387826
+ });
387827
+ }
387828
+ function markRunEndedBestEffort(dependencies, runId) {
387829
+ try {
387830
+ markRunEnded({ cwd: dependencies.cwd, store: dependencies.store }, runId);
387831
+ } catch {
387832
+ }
387833
+ }
387641
387834
  function joinChanges(changes) {
387642
387835
  return [...new Set(changes)].sort().join(",");
387643
387836
  }
@@ -387765,53 +387958,16 @@ function completionReport(input) {
387765
387958
  }
387766
387959
  return input.blocker === void 0 ? "CopilotKit onboarding marked complete.\n" : blockedAfterProof(input.blocker);
387767
387960
  }
387768
- async function reportFeedback(dependencies, runId) {
387769
- const input = await readFeedbackInput(dependencies.stdin);
387770
- if (!input.ok)
387771
- return printFeedbackRefusal(dependencies, runId, input.refusal);
387772
- const reviewed = reviewFeedbackReport(input.text);
387773
- if (!reviewed.ok)
387774
- return printFeedbackRefusal(dependencies, runId, reviewed.refusal);
387775
- const feedbackText = reviewed.text;
387776
- let submission;
387777
- try {
387778
- submission = await dependencies.submitFeedbackEvent({
387779
- event: "cli.onboarding.feedback_submitted",
387780
- properties: {
387781
- command: "onboard",
387782
- ...onboardingIntentProperties(dependencies),
387783
- onboarding_run_id: runId,
387784
- cli_version: dependencies.cliVersion,
387785
- feedback_text: feedbackText
387786
- }
387787
- });
387788
- } catch (error98) {
387789
- submission = { status: "failed", detail: describeSubmissionError(error98) };
387790
- }
387791
- dependencies.stdout.write(
387792
- `${describeSubmission("Feedback", submission)}
387793
- report: ${feedbackText}
387794
- `
387795
- );
387796
- }
387797
387961
  function describeSubmission(subject, submission) {
387798
387962
  switch (submission.status) {
387799
387963
  case "sent":
387800
- return subject === "Feedback" ? "Feedback sent." : "Friction reported.";
387964
+ return "Friction reported.";
387801
387965
  case "declined":
387802
387966
  return `${subject} was not sent because telemetry is off.`;
387803
387967
  default:
387804
387968
  return `${subject} was not sent because the telemetry send failed: ${submission.detail}`;
387805
387969
  }
387806
387970
  }
387807
- function printFeedbackRefusal(dependencies, runId, refusal) {
387808
- recordReportRefused(dependencies, runId, "feedback", refusal.code);
387809
- dependencies.stdout.write(
387810
- `Feedback refused, and nothing was sent.
387811
- ${refusal.code}: ${refusal.message}
387812
- `
387813
- );
387814
- }
387815
387971
  async function reportFriction(dependencies, runId, args) {
387816
387972
  const parsed = parseFrictionArguments(args);
387817
387973
  if (!parsed.ok)
@@ -387823,6 +387979,7 @@ async function reportFriction(dependencies, runId, args) {
387823
387979
  category: parsed.category,
387824
387980
  costSeconds: parsed.costSeconds,
387825
387981
  docsPath: parsed.docsPath,
387982
+ phase: parsed.phase,
387826
387983
  text: input.text
387827
387984
  });
387828
387985
  if (!reviewed.ok)
@@ -387838,7 +387995,10 @@ async function reportFriction(dependencies, runId, args) {
387838
387995
  onboarding_run_id: runId,
387839
387996
  cli_version: dependencies.cliVersion,
387840
387997
  friction_category: report.category,
387841
- cost_seconds_estimated: report.costSecondsEstimated,
387998
+ friction_phase: report.phase,
387999
+ // Spread so a stop report that named no cost leaves the key off rather
388000
+ // than sending an undefined the sink stores as a value.
388001
+ ...report.costSecondsEstimated === void 0 ? {} : { cost_seconds_estimated: report.costSecondsEstimated },
387842
388002
  // Spread so a report about no particular page leaves the key off
387843
388003
  // rather than joining to an empty one.
387844
388004
  ...report.docsPath === void 0 ? {} : { friction_docs_path: report.docsPath },
@@ -387858,7 +388018,8 @@ function parseFrictionArguments(args) {
387858
388018
  options: {
387859
388019
  category: { type: "string" },
387860
388020
  "cost-seconds": { type: "string" },
387861
- "docs-path": { type: "string" }
388021
+ "docs-path": { type: "string" },
388022
+ phase: { type: "string" }
387862
388023
  },
387863
388024
  strict: true
387864
388025
  });
@@ -387866,14 +388027,15 @@ function parseFrictionArguments(args) {
387866
388027
  ok: true,
387867
388028
  category: parsed.values.category,
387868
388029
  costSeconds: parsed.values["cost-seconds"],
387869
- docsPath: parsed.values["docs-path"]
388030
+ docsPath: parsed.values["docs-path"],
388031
+ phase: parsed.values.phase
387870
388032
  };
387871
388033
  } catch {
387872
388034
  return {
387873
388035
  ok: false,
387874
388036
  refusal: {
387875
388037
  code: "FRICTION_ARGUMENTS_INVALID",
387876
- message: `Usage: copilotkit onboard friction --category <${FRICTION_CATEGORIES.join("|")}> --cost-seconds <seconds> [--docs-path <page path or URL>]`
388038
+ message: `Usage: copilotkit onboard friction --category <${FRICTION_CATEGORIES.join("|")}> --cost-seconds <seconds> [--phase <${FRICTION_PHASES.join("|")}>] [--docs-path <page path or URL>]`
387877
388039
  }
387878
388040
  };
387879
388041
  }
@@ -387890,8 +388052,9 @@ function printFrictionReport(dependencies, report, submission) {
387890
388052
  dependencies.stdout.write(
387891
388053
  `${describeSubmission("Friction", submission)}
387892
388054
  category: ${report.category}
387893
- cost_seconds_estimated: ${report.costSecondsEstimated}
387894
- ` + (report.docsPath === void 0 ? "" : `docs_path: ${report.docsPath}
388055
+ phase: ${report.phase}
388056
+ ` + (report.costSecondsEstimated === void 0 ? "" : `cost_seconds_estimated: ${report.costSecondsEstimated}
388057
+ `) + (report.docsPath === void 0 ? "" : `docs_path: ${report.docsPath}
387895
388058
  `) + `report: ${report.text}
387896
388059
  `
387897
388060
  );
@@ -388118,7 +388281,6 @@ var init_onboard = __esm({
388118
388281
  init_config_service();
388119
388282
  init_onboarding_graph();
388120
388283
  init_onboarding_friction();
388121
- init_onboarding_feedback();
388122
388284
  init_onboarding_checkpoint();
388123
388285
  init_onboarding_state();
388124
388286
  init_onboarding_protected_paths();
@@ -388140,7 +388302,6 @@ var init_onboard = __esm({
388140
388302
  "checkpoint",
388141
388303
  "proof",
388142
388304
  "complete",
388143
- "feedback",
388144
388305
  "friction"
388145
388306
  ];
388146
388307
  READ_RUN_NOT_BOUND = runNotBound(
@@ -391409,8 +391570,8 @@ General:
391409
391570
  --verbose Mirror CLI diagnostics to stderr
391410
391571
 
391411
391572
  Privacy:
391412
- CopilotKit collects CLI usage data to improve the product. Onboarding feedback
391413
- may send up to 2,048 UTF-8 bytes through this telemetry path. To opt out, set
391573
+ CopilotKit collects CLI usage data to improve the product. An onboarding
391574
+ friction report sends up to 2,048 UTF-8 bytes through this telemetry path. To opt out, set
391414
391575
  DO_NOT_TRACK=1 or COPILOTKIT_TELEMETRY_DISABLED=1 in your environment.
391415
391576
  `,
391416
391577
  login: `Usage: copilotkit login [--json]
@@ -391436,8 +391597,8 @@ Options:
391436
391597
  copilotkit onboard proof --step <oss-baseline|round-trip> --outcome <passed|failed|skipped>
391437
391598
  [--predicate <1-6>]
391438
391599
  copilotkit onboard complete
391439
- copilotkit onboard feedback
391440
- copilotkit onboard friction --category <slug> --cost-seconds <seconds>
391600
+ copilotkit onboard friction --category <slug> [--cost-seconds <seconds>]
391601
+ [--phase <repair|stop|completion>]
391441
391602
 
391442
391603
  Guide a coding agent through the Markdown graph bundled with this exact CLI.
391443
391604
 
@@ -391452,12 +391613,12 @@ Subcommands:
391452
391613
  checkpoint Report how far a long step has got
391453
391614
  proof Record what one proof gate returned
391454
391615
  complete Mark a proven onboarding run complete
391455
- feedback Read one non-empty message from standard input
391456
391616
  friction Report one papercut that slowed a run down
391457
391617
 
391458
- Feedback must be no larger than 2,048 UTF-8 bytes. Do not include secrets,
391459
- source code, logs, or command output. The global telemetry setting applies.
391460
- When telemetry is off, or the send fails, feedback exits zero and says which.
391618
+ A friction report must be no larger than 2,048 UTF-8 bytes. Do not include
391619
+ secrets, source code, logs, or command output. The global telemetry setting
391620
+ applies. When telemetry is off, or the send fails, the command exits zero and
391621
+ says which.
391461
391622
 
391462
391623
  Protect captures the paths this run must not change -- the developer's work in
391463
391624
  progress -- as path and digest, derived from the working tree rather than taken
@@ -391536,6 +391697,10 @@ report from standard input, at most 2,000 characters and four lines of prose.
391536
391697
  --category takes one of: docs-missing, docs-wrong, docs-sequential, cli-gap,
391537
391698
  sdk-gap, environment, port-collision, credential, validation-loop, other.
391538
391699
  --cost-seconds takes the reporting agent's own estimate of the seconds lost.
391700
+ --phase takes one of: repair, stop, completion, and defaults to completion. A
391701
+ repair report is filed once a repair cycle has resolved. A stop report is the
391702
+ one that can leave --cost-seconds off, because a run that stopped cannot
391703
+ separate one papercut's cost from the cost of the whole run.
391539
391704
 
391540
391705
  A report containing a secret shape, a fenced code block, or pasted output is
391541
391706
  refused before anything is sent, and the reason is printed. Both commands print
@@ -393796,7 +393961,6 @@ var ONBOARD_SUBCOMMANDS2 = [
393796
393961
  "checkpoint",
393797
393962
  "classify",
393798
393963
  "complete",
393799
- "feedback",
393800
393964
  "friction",
393801
393965
  "identify",
393802
393966
  "proof",