copilotkit 4.16.0 → 4.18.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 (83) hide show
  1. package/README.md +195 -8
  2. package/cli-build-info.json +7 -7
  3. package/exporters/langgraph/README.md +118 -0
  4. package/exporters/langgraph/export_checkpointer.py +125 -0
  5. package/index.js +13890 -9434
  6. package/onboarding/index.json +1 -1
  7. package/onboarding/prompts/authenticate/start.md +24 -23
  8. package/onboarding/prompts/conversion/plan.md +3 -3
  9. package/onboarding/prompts/credentials/finalize-plan.md +56 -199
  10. package/onboarding/prompts/credentials/plan.md +24 -23
  11. package/onboarding/prompts/credentials/settle-credentials.md +40 -177
  12. package/onboarding/prompts/credentials/write-plan.md +47 -23
  13. package/onboarding/prompts/fallback/best-effort.md +25 -17
  14. package/onboarding/prompts/feature/a2ui/implement.md +40 -12
  15. package/onboarding/prompts/feature/a2ui/proof.md +29 -9
  16. package/onboarding/prompts/feature/a2ui/start.md +54 -12
  17. package/onboarding/prompts/feature/blocked-by-plan.md +4 -4
  18. package/onboarding/prompts/feature/channels/implement.md +41 -13
  19. package/onboarding/prompts/feature/channels/proof.md +30 -11
  20. package/onboarding/prompts/feature/channels/start.md +54 -9
  21. package/onboarding/prompts/feature/chat-suggestions/implement.md +40 -12
  22. package/onboarding/prompts/feature/chat-suggestions/proof.md +29 -9
  23. package/onboarding/prompts/feature/chat-suggestions/start.md +51 -10
  24. package/onboarding/prompts/feature/complete.md +2 -2
  25. package/onboarding/prompts/feature/learning/implement.md +66 -29
  26. package/onboarding/prompts/feature/learning/proof.md +30 -10
  27. package/onboarding/prompts/feature/learning/start.md +46 -20
  28. package/onboarding/prompts/feature/open-generative-ui/implement.md +41 -13
  29. package/onboarding/prompts/feature/open-generative-ui/proof.md +29 -9
  30. package/onboarding/prompts/feature/open-generative-ui/start.md +51 -10
  31. package/onboarding/prompts/feature/realtime-sync/implement.md +41 -13
  32. package/onboarding/prompts/feature/realtime-sync/proof.md +31 -10
  33. package/onboarding/prompts/feature/realtime-sync/start.md +51 -9
  34. package/onboarding/prompts/feature/rich-threads/implement.md +42 -14
  35. package/onboarding/prompts/feature/rich-threads/proof.md +31 -10
  36. package/onboarding/prompts/feature/rich-threads/start.md +51 -9
  37. package/onboarding/prompts/feature/stop.md +5 -5
  38. package/onboarding/prompts/feature/voice/implement.md +40 -12
  39. package/onboarding/prompts/feature/voice/proof.md +29 -9
  40. package/onboarding/prompts/feature/voice/start.md +51 -9
  41. package/onboarding/prompts/framework/ag2.md +2 -2
  42. package/onboarding/prompts/framework/agno.md +4 -4
  43. package/onboarding/prompts/framework/built-in.md +2 -2
  44. package/onboarding/prompts/framework/claude-sdk-python.md +8 -7
  45. package/onboarding/prompts/framework/claude-sdk-typescript.md +2 -2
  46. package/onboarding/prompts/framework/crewai-flows.md +15 -7
  47. package/onboarding/prompts/framework/deep-agents.md +4 -3
  48. package/onboarding/prompts/framework/google-adk.md +7 -7
  49. package/onboarding/prompts/framework/langgraph-fastapi.md +2 -2
  50. package/onboarding/prompts/framework/langgraph-python.md +2 -2
  51. package/onboarding/prompts/framework/langgraph-typescript.md +2 -2
  52. package/onboarding/prompts/framework/llamaindex.md +4 -4
  53. package/onboarding/prompts/framework/mastra.md +2 -2
  54. package/onboarding/prompts/framework/ms-agent-dotnet.md +2 -2
  55. package/onboarding/prompts/framework/ms-agent-harness-dotnet.md +2 -2
  56. package/onboarding/prompts/framework/ms-agent-python.md +6 -6
  57. package/onboarding/prompts/framework/pydantic-ai.md +2 -2
  58. package/onboarding/prompts/framework/strands-python.md +4 -4
  59. package/onboarding/prompts/framework/strands-typescript.md +4 -4
  60. package/onboarding/prompts/frontend/angular.md +3 -3
  61. package/onboarding/prompts/frontend/nextjs.md +16 -3
  62. package/onboarding/prompts/frontend/plan.md +9 -8
  63. package/onboarding/prompts/frontend/react-native.md +2 -2
  64. package/onboarding/prompts/frontend/react-spa.md +2 -2
  65. package/onboarding/prompts/frontend/vue.md +2 -2
  66. package/onboarding/prompts/implementation/build-and-validate.md +68 -30
  67. package/onboarding/prompts/proof/complete.md +24 -17
  68. package/onboarding/prompts/proof/oss-baseline.md +16 -12
  69. package/onboarding/prompts/proof/round-trip.md +39 -27
  70. package/onboarding/prompts/research/gather.md +8 -7
  71. package/onboarding/prompts/research/merge.md +3 -3
  72. package/onboarding/prompts/research/preflight.md +4 -4
  73. package/onboarding/prompts/research/route.md +6 -6
  74. package/onboarding/prompts/starter/clone.md +16 -12
  75. package/onboarding/prompts/stopped/run-failed.md +11 -11
  76. package/onboarding/prompts/subagent/create-plan.md +24 -10
  77. package/onboarding/prompts/subagent/implement-and-validate.md +25 -11
  78. package/onboarding/prompts/subagent/inspect-repository.md +21 -6
  79. package/onboarding/prompts/subagent/prove-oss-baseline.md +5 -4
  80. package/onboarding/prompts/subagent/prove-round-trip.md +77 -23
  81. package/onboarding/prompts/unsupported/no-validated-path.md +4 -4
  82. package/package.json +1 -5
  83. package/release/release-tool.js +189 -44
@@ -14811,7 +14811,7 @@ var FLAG_DEFINITIONS = defineFlags({
14811
14811
 
14812
14812
  // apps/cli/src/config.ts
14813
14813
  function getTemplateRef() {
14814
- return true ? "a933af0b132e61d2d04be7ce0a8f55743af21ccc" : "main";
14814
+ return true ? "70d1f3c0a832d6274e2fe710e24102f6429f14f4" : "main";
14815
14815
  }
14816
14816
 
14817
14817
  // apps/cli/src/services/agentcore-config.ts
@@ -14980,6 +14980,13 @@ async function writeShowcaseConfig(projectDir, showcase) {
14980
14980
  // apps/cli/src/services/telemetry/event-properties.ts
14981
14981
  var TELEMETRY_ERROR_CODES = {
14982
14982
  TEMPLATE_FETCH_FAILED: "TEMPLATE_FETCH_FAILED",
14983
+ /**
14984
+ * Copying the fetched starter into the project folder failed. Separate from
14985
+ * {@link TELEMETRY_ERROR_CODES.TEMPLATE_FETCH_FAILED}: a Windows antivirus
14986
+ * lock (`EBUSY`) used to be filed as a failed download (PE-358). Buckets as
14987
+ * `filesystem`, or `sandbox_denied` when a sandbox refused the write.
14988
+ */
14989
+ TEMPLATE_COPY_FAILED: "TEMPLATE_COPY_FAILED",
14983
14990
  GIT_FAILED: "GIT_FAILED",
14984
14991
  PREREQUISITE_MISSING: "PREREQUISITE_MISSING",
14985
14992
  INVALID_FRAMEWORK: "INVALID_FRAMEWORK",
@@ -15020,12 +15027,30 @@ var TELEMETRY_ERROR_CODES = {
15020
15027
  LEARNING_RESPONSE_INVALID: "LEARNING_RESPONSE_INVALID",
15021
15028
  LEARNING_SKILLS_BUNDLE_INVALID: "LEARNING_SKILLS_BUNDLE_INVALID",
15022
15029
  LEARNING_SKILLS_INTEGRITY_FAILED: "LEARNING_SKILLS_INTEGRITY_FAILED",
15023
- LEARNING_SKILLS_OUTPUT_EXISTS: "LEARNING_SKILLS_OUTPUT_EXISTS"
15030
+ LEARNING_SKILLS_OUTPUT_EXISTS: "LEARNING_SKILLS_OUTPUT_EXISTS",
15031
+ /** A device sign-in code ran out before anybody approved it. */
15032
+ DEVICE_LOGIN_EXPIRED: "DEVICE_LOGIN_EXPIRED",
15033
+ /** The person denied a device sign-in request. */
15034
+ DEVICE_LOGIN_DENIED: "DEVICE_LOGIN_DENIED",
15035
+ /** The server does not offer device sign-in. */
15036
+ DEVICE_LOGIN_UNAVAILABLE: "DEVICE_LOGIN_UNAVAILABLE",
15037
+ /** `login --json` refused a new code after repeated unapproved expiries. */
15038
+ LOGIN_REPEATED_EXPIRY: "LOGIN_REPEATED_EXPIRY",
15039
+ /**
15040
+ * An import source's environment is missing a required value or holds one
15041
+ * the importer rejects, such as an unset `MASTRA_IMPORT_AGENT_ID` (PE-397).
15042
+ */
15043
+ IMPORT_SOURCE_CONFIG_INVALID: "IMPORT_SOURCE_CONFIG_INVALID"
15024
15044
  };
15025
15045
  function tagError(err, code) {
15026
15046
  err.code = code;
15027
15047
  return err;
15028
15048
  }
15049
+ function annotateFailure(err, cause) {
15050
+ const annotated = err;
15051
+ annotated.failureCause = { ...cause, ...annotated.failureCause };
15052
+ return err;
15053
+ }
15029
15054
 
15030
15055
  // apps/cli/src/types.ts
15031
15056
  var AGENT_FRAMEWORKS = Object.keys(
@@ -15383,7 +15408,7 @@ var FRAMEWORK_TEMPLATES = {
15383
15408
  import * as fs4 from "node:fs";
15384
15409
  import * as path4 from "node:path";
15385
15410
  import * as os from "node:os";
15386
- import { execFileSync } from "node:child_process";
15411
+ import { execFileSync, spawn } from "node:child_process";
15387
15412
 
15388
15413
  // apps/cli/src/services/project-config.ts
15389
15414
  import * as fs3 from "node:fs";
@@ -15416,9 +15441,10 @@ var projectConfigSchema = external_exports.object({
15416
15441
  * container, a port that only ever appears on a command line — says so once
15417
15442
  * instead of passing `--runtime-url` on every invocation (OSS-1090).
15418
15443
  *
15419
- * A person writes it, and so does `project select --runtime-url`. An
15420
- * onboarding run settles a free port and then has nowhere to put it, so
15421
- * `verify` falls back to its assumed default and reports on whatever holds
15444
+ * A person writes it, and so do `project select --runtime-url` and
15445
+ * `onboard runtime-url`, which records the port a started server bound
15446
+ * (PE-368). An onboarding run settles a free port and then has nowhere to
15447
+ * put it, so `verify` falls back to its assumed default and reports on whatever holds
15422
15448
  * that port — in one run, an unrelated checkout (PE-58). The flag is still
15423
15449
  * a statement rather than a guess: the caller has to name the URL.
15424
15450
  */
@@ -15434,6 +15460,11 @@ function canonicalizeDir(dir) {
15434
15460
  }
15435
15461
 
15436
15462
  // apps/cli/src/services/project-scaffold.ts
15463
+ var DEFAULT_GIT_STALL_TIMEOUT_MS = 6e4;
15464
+ var NON_INTERACTIVE_GIT_ENV = {
15465
+ GIT_TERMINAL_PROMPT: "0",
15466
+ GCM_INTERACTIVE: "never"
15467
+ };
15437
15468
  var PROJECT_DIRECTORY_NAMES = /* @__PURE__ */ new Set([
15438
15469
  "agent",
15439
15470
  "api",
@@ -15451,12 +15482,17 @@ var PROJECT_MANIFEST_NAMES = /* @__PURE__ */ new Set([
15451
15482
  "Gemfile",
15452
15483
  "build.gradle",
15453
15484
  "composer.json",
15485
+ "global.json",
15454
15486
  "go.mod",
15455
15487
  "package.json",
15456
15488
  "pom.xml",
15457
15489
  "pyproject.toml",
15458
15490
  "requirements.txt"
15459
15491
  ]);
15492
+ var PROJECT_MANIFEST_EXTENSIONS = [".csproj", ".sln"];
15493
+ function isProjectManifest(entry) {
15494
+ return PROJECT_MANIFEST_NAMES.has(entry) || PROJECT_MANIFEST_EXTENSIONS.some((extension) => entry.endsWith(extension));
15495
+ }
15460
15496
  var ENV_TEMPLATE_SUFFIXES = [".example", ".sample", ".template"];
15461
15497
  function isCredentialEnvFile(entry) {
15462
15498
  if (!entry.startsWith(".env"))
@@ -15468,7 +15504,7 @@ function isCredentialEnvFile(entry) {
15468
15504
  function entryHoldsProject(entry) {
15469
15505
  if (isCredentialEnvFile(entry))
15470
15506
  return true;
15471
- return PROJECT_DIRECTORY_NAMES.has(entry) || PROJECT_MANIFEST_NAMES.has(entry);
15507
+ return PROJECT_DIRECTORY_NAMES.has(entry) || isProjectManifest(entry);
15472
15508
  }
15473
15509
  var SYSTEM_FOLDERS = [
15474
15510
  "/Applications",
@@ -15565,7 +15601,7 @@ function walkProjectsBelow(dir, top, limits) {
15565
15601
  if (exhausted)
15566
15602
  return;
15567
15603
  const names = childEntries.map((e) => e.name);
15568
- if (names.some((n) => n === ".git" || PROJECT_MANIFEST_NAMES.has(n))) {
15604
+ if (names.some((n) => n === ".git" || isProjectManifest(n))) {
15569
15605
  found.push(child);
15570
15606
  } else if (depth < PROJECTS_BELOW_DEPTH) {
15571
15607
  visit(child, childEntries, depth + 1);
@@ -15622,6 +15658,7 @@ function occupiedMessage(projectDir, contents) {
15622
15658
  }
15623
15659
  async function scaffoldProject(options) {
15624
15660
  const { projectDir, template } = options;
15661
+ const stallTimeoutMs = options.gitStallTimeoutMs ?? DEFAULT_GIT_STALL_TIMEOUT_MS;
15625
15662
  assertProjectDirAvailable(projectDir);
15626
15663
  const localTemplateDir = process.env["COPILOTKIT_TEMPLATE_DIR"];
15627
15664
  if (localTemplateDir !== void 0 && localTemplateDir !== "") {
@@ -15633,8 +15670,16 @@ async function scaffoldProject(options) {
15633
15670
  TELEMETRY_ERROR_CODES.TEMPLATE_FETCH_FAILED
15634
15671
  );
15635
15672
  }
15636
- fs4.mkdirSync(projectDir, { recursive: true });
15637
- await copyDirectory(localTemplateDir, projectDir, true);
15673
+ try {
15674
+ fs4.mkdirSync(projectDir, { recursive: true });
15675
+ await copyDirectory(localTemplateDir, projectDir, true);
15676
+ } catch (cause) {
15677
+ throw wrapStepError(
15678
+ cause,
15679
+ TELEMETRY_ERROR_CODES.TEMPLATE_COPY_FAILED,
15680
+ "copy"
15681
+ );
15682
+ }
15638
15683
  return;
15639
15684
  }
15640
15685
  const source = typeof template === "string" ? parseGitHubUrl(template) : {
@@ -15644,7 +15689,7 @@ async function scaffoldProject(options) {
15644
15689
  subdirectoryPath: template.path,
15645
15690
  mode: template.mode
15646
15691
  };
15647
- await cloneTemplate(source, projectDir);
15692
+ await cloneTemplate(source, projectDir, stallTimeoutMs);
15648
15693
  }
15649
15694
  function pathEntryExists(entryPath) {
15650
15695
  try {
@@ -15657,61 +15702,85 @@ function pathEntryExists(entryPath) {
15657
15702
  throw error48;
15658
15703
  }
15659
15704
  }
15660
- async function cloneTemplate(source, destinationPath) {
15705
+ async function cloneTemplate(source, destinationPath, stallTimeoutMs) {
15661
15706
  const { owner, repo, revision, subdirectoryPath, mode } = source;
15662
15707
  const tempDir = fs4.mkdtempSync(path4.join(os.tmpdir(), "copilotkit-clone-"));
15663
15708
  const isWholeRepo = mode === "whole-repository";
15664
15709
  const destinationExisted = pathEntryExists(destinationPath);
15665
15710
  try {
15666
- runGit(
15711
+ await runGit(
15667
15712
  ["init"],
15668
- { cwd: tempDir, stdio: "pipe" },
15669
- TELEMETRY_ERROR_CODES.GIT_FAILED
15713
+ { cwd: tempDir, stallTimeoutMs },
15714
+ TELEMETRY_ERROR_CODES.GIT_FAILED,
15715
+ "git_init"
15670
15716
  );
15671
- runGit(
15717
+ await runGit(
15672
15718
  ["remote", "add", "origin", `https://github.com/${owner}/${repo}.git`],
15673
- { cwd: tempDir, stdio: "pipe" },
15674
- TELEMETRY_ERROR_CODES.GIT_FAILED
15719
+ { cwd: tempDir, stallTimeoutMs },
15720
+ TELEMETRY_ERROR_CODES.GIT_FAILED,
15721
+ "remote_add"
15675
15722
  );
15676
15723
  if (!isWholeRepo) {
15677
- runGit(
15724
+ await runGit(
15678
15725
  ["config", "core.sparseCheckout", "true"],
15679
- { cwd: tempDir, stdio: "pipe" },
15680
- TELEMETRY_ERROR_CODES.GIT_FAILED
15681
- );
15682
- fs4.writeFileSync(
15683
- path4.join(tempDir, ".git/info/sparse-checkout"),
15684
- subdirectoryPath
15726
+ { cwd: tempDir, stallTimeoutMs },
15727
+ TELEMETRY_ERROR_CODES.GIT_FAILED,
15728
+ "sparse_config"
15685
15729
  );
15730
+ try {
15731
+ fs4.writeFileSync(
15732
+ path4.join(tempDir, ".git/info/sparse-checkout"),
15733
+ subdirectoryPath
15734
+ );
15735
+ } catch (cause) {
15736
+ throw wrapStepError(
15737
+ cause,
15738
+ TELEMETRY_ERROR_CODES.GIT_FAILED,
15739
+ "sparse_config"
15740
+ );
15741
+ }
15686
15742
  }
15687
- runGit(
15688
- ["fetch", "--depth=1", "origin", revision],
15689
- { cwd: tempDir, stdio: "pipe" },
15690
- TELEMETRY_ERROR_CODES.TEMPLATE_FETCH_FAILED
15743
+ await runGit(
15744
+ ["fetch", "--progress", "--depth=1", "origin", revision],
15745
+ { cwd: tempDir, stallTimeoutMs },
15746
+ TELEMETRY_ERROR_CODES.TEMPLATE_FETCH_FAILED,
15747
+ "fetch"
15691
15748
  );
15692
- runGit(
15693
- ["checkout", "--detach", "FETCH_HEAD"],
15694
- { cwd: tempDir, stdio: "pipe" },
15695
- TELEMETRY_ERROR_CODES.GIT_FAILED
15749
+ await runGit(
15750
+ ["checkout", "--progress", "--detach", "FETCH_HEAD"],
15751
+ { cwd: tempDir, stallTimeoutMs },
15752
+ TELEMETRY_ERROR_CODES.GIT_FAILED,
15753
+ "checkout"
15696
15754
  );
15697
15755
  const sourcePath = isWholeRepo ? tempDir : path4.join(tempDir, subdirectoryPath);
15698
15756
  if (!isWholeRepo && !fs4.existsSync(sourcePath)) {
15699
- throw tagError(
15700
- new Error(
15701
- `Template directory '${subdirectoryPath}' not found in the repository.`
15757
+ throw annotateFailure(
15758
+ tagError(
15759
+ new Error(
15760
+ `Template directory '${subdirectoryPath}' not found in the repository.`
15761
+ ),
15762
+ TELEMETRY_ERROR_CODES.TEMPLATE_FETCH_FAILED
15702
15763
  ),
15703
- TELEMETRY_ERROR_CODES.TEMPLATE_FETCH_FAILED
15764
+ { failedStep: "subdirectory_missing" }
15765
+ );
15766
+ }
15767
+ try {
15768
+ fs4.mkdirSync(destinationPath, { recursive: true });
15769
+ await copyDirectory(sourcePath, destinationPath, isWholeRepo);
15770
+ } catch (cause) {
15771
+ throw wrapStepError(
15772
+ cause,
15773
+ TELEMETRY_ERROR_CODES.TEMPLATE_COPY_FAILED,
15774
+ "copy"
15704
15775
  );
15705
15776
  }
15706
- fs4.mkdirSync(destinationPath, { recursive: true });
15707
- await copyDirectory(sourcePath, destinationPath, isWholeRepo);
15708
15777
  } catch (cause) {
15709
15778
  if (!destinationExisted) {
15710
15779
  fs4.rmSync(destinationPath, { recursive: true, force: true });
15711
15780
  }
15712
15781
  const error48 = cause instanceof Error ? cause : new Error("Starter template checkout failed");
15713
15782
  const code = error48.code;
15714
- if (code === TELEMETRY_ERROR_CODES.TEMPLATE_FETCH_FAILED || code === TELEMETRY_ERROR_CODES.GIT_FAILED) {
15783
+ if (code === TELEMETRY_ERROR_CODES.TEMPLATE_FETCH_FAILED || code === TELEMETRY_ERROR_CODES.TEMPLATE_COPY_FAILED || code === TELEMETRY_ERROR_CODES.GIT_FAILED) {
15715
15784
  throw error48;
15716
15785
  }
15717
15786
  throw tagError(error48, TELEMETRY_ERROR_CODES.TEMPLATE_FETCH_FAILED);
@@ -15740,12 +15809,88 @@ async function copyDirectory(source, destination, excludeGit = false) {
15740
15809
  }
15741
15810
  }
15742
15811
  }
15743
- function runGit(args, opts, code) {
15812
+ function wrapStepError(cause, code, failedStep) {
15813
+ const message = cause instanceof Error ? cause.message : `Starter step failed: ${failedStep}`;
15814
+ const status = cause?.status;
15815
+ return annotateFailure(tagError(new Error(message, { cause }), code), {
15816
+ failedStep,
15817
+ ...typeof status === "number" ? { gitExitCode: status } : {}
15818
+ });
15819
+ }
15820
+ var GIT_STDERR_TAIL_LINES = 20;
15821
+ var GIT_PROGRESS_LINE = /^(remote: )?(Counting|Compressing|Receiving|Resolving|Enumerating|Updating files|Total)\b/;
15822
+ function gitStderrTail(stderr) {
15823
+ return stderr.split(/\r|\n/).map((line) => line.trimEnd()).filter((line) => line !== "" && !GIT_PROGRESS_LINE.test(line)).slice(-GIT_STDERR_TAIL_LINES).join("\n");
15824
+ }
15825
+ var GIT_STDERR_MAX_CHARS = 64 * 1024;
15826
+ function stallError(command, failedStep, options) {
15827
+ const seconds = Math.round(options.stallTimeoutMs / 1e3);
15828
+ const advice = failedStep === "fetch" ? " Check your network connection to github.com. If you are behind a proxy, set HTTPS_PROXY to its address and run the command again." : "";
15829
+ return Object.assign(
15830
+ new Error(
15831
+ `\`${command}\` stopped: git printed nothing for ${seconds} seconds.${advice}`
15832
+ ),
15833
+ { code: "ETIMEDOUT" }
15834
+ );
15835
+ }
15836
+ async function runGit(args, options, code, failedStep) {
15837
+ const command = `git ${args.join(" ")}`;
15744
15838
  try {
15745
- execFileSync("git", args, opts);
15839
+ await new Promise((resolve5, reject) => {
15840
+ const child = spawn("git", args, {
15841
+ cwd: options.cwd,
15842
+ env: { ...process.env, ...NON_INTERACTIVE_GIT_ENV },
15843
+ stdio: ["ignore", "ignore", "pipe"],
15844
+ windowsHide: true
15845
+ });
15846
+ let stderr = "";
15847
+ let settled = false;
15848
+ let watchdog;
15849
+ const settle = (finish) => {
15850
+ if (settled)
15851
+ return;
15852
+ settled = true;
15853
+ clearTimeout(watchdog);
15854
+ finish();
15855
+ };
15856
+ const armWatchdog = () => {
15857
+ clearTimeout(watchdog);
15858
+ watchdog = setTimeout(() => {
15859
+ child.kill();
15860
+ child.stderr.destroy();
15861
+ child.unref();
15862
+ settle(() => reject(stallError(command, failedStep, options)));
15863
+ }, options.stallTimeoutMs);
15864
+ };
15865
+ armWatchdog();
15866
+ child.stderr.setEncoding("utf8");
15867
+ child.stderr.on("data", (chunk) => {
15868
+ stderr = (stderr + chunk).slice(-GIT_STDERR_MAX_CHARS);
15869
+ armWatchdog();
15870
+ });
15871
+ child.on("error", (error48) => settle(() => reject(error48)));
15872
+ child.on(
15873
+ "close",
15874
+ (status) => settle(() => {
15875
+ if (status === 0) {
15876
+ resolve5();
15877
+ return;
15878
+ }
15879
+ const tail = gitStderrTail(stderr);
15880
+ reject(
15881
+ Object.assign(
15882
+ new Error(
15883
+ `Command failed: ${command}${tail ? `
15884
+ ${tail}` : ""}`
15885
+ ),
15886
+ { status }
15887
+ )
15888
+ );
15889
+ })
15890
+ );
15891
+ });
15746
15892
  } catch (cause) {
15747
- const wrapped = cause instanceof Error ? cause : new Error(`git command failed: git ${args.join(" ")}`);
15748
- throw tagError(wrapped, code);
15893
+ throw wrapStepError(cause, code, failedStep);
15749
15894
  }
15750
15895
  }
15751
15896
  function parseGitHubUrl(githubUrl) {