vidpipe 1.3.12 → 1.3.13

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.
package/dist/index.js CHANGED
@@ -93,7 +93,6 @@ var init_types = __esm({
93
93
  PipelineStage2["MediumClipPosts"] = "medium-clip-posts";
94
94
  PipelineStage2["Blog"] = "blog";
95
95
  PipelineStage2["QueueBuild"] = "queue-build";
96
- PipelineStage2["GitPush"] = "git-push";
97
96
  return PipelineStage2;
98
97
  })(PipelineStage || {});
99
98
  PIPELINE_STAGES = [
@@ -111,8 +110,7 @@ var init_types = __esm({
111
110
  { stage: "short-posts" /* ShortPosts */, name: "Short Posts", stageNumber: 12 },
112
111
  { stage: "medium-clip-posts" /* MediumClipPosts */, name: "Medium Clip Posts", stageNumber: 13 },
113
112
  { stage: "queue-build" /* QueueBuild */, name: "Queue Build", stageNumber: 14 },
114
- { stage: "blog" /* Blog */, name: "Blog", stageNumber: 15 },
115
- { stage: "git-push" /* GitPush */, name: "Git Push", stageNumber: 16 }
113
+ { stage: "blog" /* Blog */, name: "Blog", stageNumber: 15 }
116
114
  ];
117
115
  TOTAL_STAGES = PIPELINE_STAGES.length;
118
116
  PLATFORM_CHAR_LIMITS = {
@@ -143,7 +141,7 @@ function findRoot(startDir) {
143
141
  }
144
142
  }
145
143
  function projectRoot() {
146
- if (!_cachedRoot) _cachedRoot = findRoot(__dirname);
144
+ if (!_cachedRoot) _cachedRoot = findRoot(__dirname2);
147
145
  return _cachedRoot;
148
146
  }
149
147
  function assetsDir(...segments) {
@@ -157,11 +155,11 @@ function modelsDir() {
157
155
  const bundled = resolve2(projectRoot(), "dist", "models");
158
156
  return existsSync(bundled) ? bundled : assetsDir("models");
159
157
  }
160
- var __dirname, _cachedRoot;
158
+ var __dirname2, _cachedRoot;
161
159
  var init_paths = __esm({
162
160
  "src/L1-infra/paths/paths.ts"() {
163
161
  "use strict";
164
- __dirname = dirname2(fileURLToPath2(import.meta.url));
162
+ __dirname2 = dirname2(fileURLToPath2(import.meta.url));
165
163
  }
166
164
  });
167
165
 
@@ -471,8 +469,9 @@ var init_globalConfig = __esm({
471
469
 
472
470
  // src/L1-infra/config/configResolver.ts
473
471
  import { join as join4 } from "path";
474
- function resolveString(...sources) {
475
- for (const source of sources) {
472
+ function resolveString(cliValue, ...fallbacks) {
473
+ if (cliValue !== void 0) return cliValue;
474
+ for (const source of fallbacks) {
476
475
  if (source !== void 0 && source !== "") {
477
476
  return source;
478
477
  }
@@ -490,7 +489,11 @@ function resolveBoolean(cliValue, envValue, defaultValue) {
490
489
  }
491
490
  function resolveConfig(cliOptions = {}) {
492
491
  const globalConfig = loadGlobalConfig();
493
- const repoRoot = process.env.REPO_ROOT || process.cwd();
492
+ const repoRoot = resolveString(
493
+ cliOptions.repoRoot,
494
+ process.env.REPO_ROOT,
495
+ process.cwd()
496
+ );
494
497
  return {
495
498
  OPENAI_API_KEY: resolveString(
496
499
  cliOptions.openaiKey,
@@ -504,14 +507,22 @@ function resolveConfig(cliOptions = {}) {
504
507
  join4(repoRoot, "watch")
505
508
  ),
506
509
  REPO_ROOT: repoRoot,
507
- FFMPEG_PATH: resolveString(process.env.FFMPEG_PATH, "ffmpeg"),
508
- FFPROBE_PATH: resolveString(process.env.FFPROBE_PATH, "ffprobe"),
510
+ FFMPEG_PATH: resolveString(
511
+ cliOptions.ffmpegPath,
512
+ process.env.FFMPEG_PATH,
513
+ "ffmpeg"
514
+ ),
515
+ FFPROBE_PATH: resolveString(
516
+ cliOptions.ffprobePath,
517
+ process.env.FFPROBE_PATH,
518
+ "ffprobe"
519
+ ),
509
520
  EXA_API_KEY: resolveString(
510
521
  cliOptions.exaKey,
511
522
  process.env.EXA_API_KEY,
512
523
  globalConfig.credentials.exaApiKey
513
524
  ),
514
- EXA_MCP_URL: resolveString(process.env.EXA_MCP_URL, "https://mcp.exa.ai/mcp"),
525
+ EXA_MCP_URL: resolveString(void 0, process.env.EXA_MCP_URL, "https://mcp.exa.ai/mcp"),
515
526
  YOUTUBE_API_KEY: resolveString(
516
527
  cliOptions.youtubeKey,
517
528
  process.env.YOUTUBE_API_KEY,
@@ -523,12 +534,18 @@ function resolveConfig(cliOptions = {}) {
523
534
  globalConfig.credentials.perplexityApiKey
524
535
  ),
525
536
  LLM_PROVIDER: resolveString(
537
+ cliOptions.llmProvider,
526
538
  process.env.LLM_PROVIDER,
527
539
  globalConfig.defaults.llmProvider,
528
540
  "copilot"
529
541
  ),
530
- LLM_MODEL: resolveString(process.env.LLM_MODEL, globalConfig.defaults.llmModel),
542
+ LLM_MODEL: resolveString(
543
+ cliOptions.llmModel,
544
+ process.env.LLM_MODEL,
545
+ globalConfig.defaults.llmModel
546
+ ),
531
547
  ANTHROPIC_API_KEY: resolveString(
548
+ cliOptions.anthropicKey,
532
549
  process.env.ANTHROPIC_API_KEY,
533
550
  globalConfig.credentials.anthropicApiKey
534
551
  ),
@@ -545,7 +562,6 @@ function resolveConfig(cliOptions = {}) {
545
562
  join4(repoRoot, "brand.json")
546
563
  ),
547
564
  VERBOSE: cliOptions.verbose ?? false,
548
- SKIP_GIT: resolveBoolean(cliOptions.git === void 0 ? void 0 : !cliOptions.git, process.env.SKIP_GIT, false),
549
565
  SKIP_SILENCE_REMOVAL: resolveBoolean(
550
566
  cliOptions.silenceRemoval === void 0 ? void 0 : !cliOptions.silenceRemoval,
551
567
  process.env.SKIP_SILENCE_REMOVAL,
@@ -592,10 +608,12 @@ function resolveConfig(cliOptions = {}) {
592
608
  false
593
609
  ),
594
610
  GEMINI_API_KEY: resolveString(
611
+ cliOptions.geminiKey,
595
612
  process.env.GEMINI_API_KEY,
596
613
  globalConfig.credentials.geminiApiKey
597
614
  ),
598
615
  GEMINI_MODEL: resolveString(
616
+ cliOptions.geminiModel,
599
617
  process.env.GEMINI_MODEL,
600
618
  globalConfig.defaults.geminiModel,
601
619
  "gemini-2.5-pro"
@@ -610,9 +628,19 @@ function resolveConfig(cliOptions = {}) {
610
628
  cliOptions.githubToken,
611
629
  process.env.GITHUB_TOKEN,
612
630
  globalConfig.credentials.githubToken
613
- )
631
+ ),
632
+ MODEL_OVERRIDES: resolveModelOverrides()
614
633
  };
615
634
  }
635
+ function resolveModelOverrides() {
636
+ const overrides = {};
637
+ for (const [key, value] of Object.entries(process.env)) {
638
+ if (key.startsWith("MODEL_") && value) {
639
+ overrides[key] = value;
640
+ }
641
+ }
642
+ return overrides;
643
+ }
616
644
  var init_configResolver = __esm({
617
645
  "src/L1-infra/config/configResolver.ts"() {
618
646
  "use strict";
@@ -628,7 +656,7 @@ __export(environment_exports, {
628
656
  validateRequiredKeys: () => validateRequiredKeys
629
657
  });
630
658
  function validateRequiredKeys() {
631
- if (!config?.OPENAI_API_KEY && !process.env.OPENAI_API_KEY) {
659
+ if (!config?.OPENAI_API_KEY) {
632
660
  throw new Error("Missing required: OPENAI_API_KEY (set via --openai-key, env var, or vidpipe configure)");
633
661
  }
634
662
  }
@@ -1439,7 +1467,7 @@ var require_messages = __commonJS({
1439
1467
  ErrorCodes2.jsonrpcReservedErrorRangeEnd = -32e3;
1440
1468
  ErrorCodes2.serverErrorEnd = -32e3;
1441
1469
  })(ErrorCodes || (exports.ErrorCodes = ErrorCodes = {}));
1442
- var ResponseError = class _ResponseError extends Error {
1470
+ var ResponseError2 = class _ResponseError extends Error {
1443
1471
  constructor(code, message, data) {
1444
1472
  super(message);
1445
1473
  this.code = is.number(code) ? code : ErrorCodes.UnknownErrorCode;
@@ -1457,7 +1485,7 @@ var require_messages = __commonJS({
1457
1485
  return result;
1458
1486
  }
1459
1487
  };
1460
- exports.ResponseError = ResponseError;
1488
+ exports.ResponseError = ResponseError2;
1461
1489
  var ParameterStructures = class _ParameterStructures {
1462
1490
  constructor(kind) {
1463
1491
  this.kind = kind;
@@ -3010,14 +3038,14 @@ var require_connection = __commonJS({
3010
3038
  ConnectionErrors2[ConnectionErrors2["Disposed"] = 2] = "Disposed";
3011
3039
  ConnectionErrors2[ConnectionErrors2["AlreadyListening"] = 3] = "AlreadyListening";
3012
3040
  })(ConnectionErrors || (exports.ConnectionErrors = ConnectionErrors = {}));
3013
- var ConnectionError = class _ConnectionError extends Error {
3041
+ var ConnectionError2 = class _ConnectionError extends Error {
3014
3042
  constructor(code, message) {
3015
3043
  super(message);
3016
3044
  this.code = code;
3017
3045
  Object.setPrototypeOf(this, _ConnectionError.prototype);
3018
3046
  }
3019
3047
  };
3020
- exports.ConnectionError = ConnectionError;
3048
+ exports.ConnectionError = ConnectionError2;
3021
3049
  var ConnectionStrategy;
3022
3050
  (function(ConnectionStrategy2) {
3023
3051
  function is(value) {
@@ -3640,15 +3668,15 @@ ${JSON.stringify(message, null, 4)}`);
3640
3668
  }
3641
3669
  function throwIfClosedOrDisposed() {
3642
3670
  if (isClosed()) {
3643
- throw new ConnectionError(ConnectionErrors.Closed, "Connection is closed.");
3671
+ throw new ConnectionError2(ConnectionErrors.Closed, "Connection is closed.");
3644
3672
  }
3645
3673
  if (isDisposed()) {
3646
- throw new ConnectionError(ConnectionErrors.Disposed, "Connection is disposed.");
3674
+ throw new ConnectionError2(ConnectionErrors.Disposed, "Connection is disposed.");
3647
3675
  }
3648
3676
  }
3649
3677
  function throwIfListening() {
3650
3678
  if (isListening()) {
3651
- throw new ConnectionError(ConnectionErrors.AlreadyListening, "Connection is already listening");
3679
+ throw new ConnectionError2(ConnectionErrors.AlreadyListening, "Connection is already listening");
3652
3680
  }
3653
3681
  }
3654
3682
  function throwIfNotListening() {
@@ -4640,6 +4668,47 @@ init_globalConfig();
4640
4668
  init_fileSystem();
4641
4669
  init_paths();
4642
4670
 
4671
+ // src/L1-infra/progress/progressEmitter.ts
4672
+ var ProgressEmitter = class {
4673
+ enabled = false;
4674
+ listeners = /* @__PURE__ */ new Set();
4675
+ /** Turn on progress event output to stderr. */
4676
+ enable() {
4677
+ this.enabled = true;
4678
+ }
4679
+ /** Turn off progress event output. */
4680
+ disable() {
4681
+ this.enabled = false;
4682
+ }
4683
+ /** Whether the emitter is currently active (stderr or listeners). */
4684
+ isEnabled() {
4685
+ return this.enabled || this.listeners.size > 0;
4686
+ }
4687
+ /** Register a programmatic listener for progress events. */
4688
+ addListener(fn) {
4689
+ this.listeners.add(fn);
4690
+ }
4691
+ /** Remove a previously registered listener. */
4692
+ removeListener(fn) {
4693
+ this.listeners.delete(fn);
4694
+ }
4695
+ /**
4696
+ * Write a progress event as a single JSON line to stderr (if enabled)
4697
+ * and dispatch to all registered listeners.
4698
+ * No-op when neither stderr output nor listeners are active.
4699
+ */
4700
+ emit(event) {
4701
+ if (!this.enabled && this.listeners.size === 0) return;
4702
+ if (this.enabled) {
4703
+ process.stderr.write(JSON.stringify(event) + "\n");
4704
+ }
4705
+ for (const listener of this.listeners) {
4706
+ listener(event);
4707
+ }
4708
+ }
4709
+ };
4710
+ var progressEmitter = new ProgressEmitter();
4711
+
4643
4712
  // src/L1-infra/process/process.ts
4644
4713
  import { execFile as nodeExecFile, execSync as nodeExecSync, spawnSync as nodeSpawnSync } from "child_process";
4645
4714
  import { createRequire } from "module";
@@ -4648,9 +4717,6 @@ function execFileRaw(cmd, args, opts, callback) {
4648
4717
  callback(error, String(stdout ?? ""), String(stderr ?? ""));
4649
4718
  });
4650
4719
  }
4651
- function execCommandSync(cmd, opts) {
4652
- return nodeExecSync(cmd, { encoding: "utf-8", ...opts }).toString().trim();
4653
- }
4654
4720
  function spawnCommand(cmd, args, opts) {
4655
4721
  return nodeSpawnSync(cmd, args, { encoding: "utf-8", ...opts });
4656
4722
  }
@@ -4744,12 +4810,13 @@ var AGENT_MODEL_MAP = {
4744
4810
  ProducerAgent: PREMIUM_MODEL
4745
4811
  };
4746
4812
  function getModelForAgent(agentName) {
4813
+ const config2 = getConfig();
4747
4814
  const envKey = `MODEL_${agentName.replace(/([a-z])([A-Z])/g, "$1_$2").toUpperCase()}`;
4748
- const envOverride = process.env[envKey];
4815
+ const envOverride = config2.MODEL_OVERRIDES[envKey];
4749
4816
  if (envOverride) return envOverride;
4750
4817
  const mapped = AGENT_MODEL_MAP[agentName];
4751
4818
  if (mapped) return mapped;
4752
- const global = getConfig().LLM_MODEL;
4819
+ const global = config2.LLM_MODEL;
4753
4820
  if (global) return global;
4754
4821
  return void 0;
4755
4822
  }
@@ -4765,20 +4832,77 @@ import { default as default4 } from "openai";
4765
4832
  import { default as default5 } from "@anthropic-ai/sdk";
4766
4833
 
4767
4834
  // node_modules/@github/copilot-sdk/dist/client.js
4768
- var import_node = __toESM(require_node(), 1);
4835
+ var import_node2 = __toESM(require_node(), 1);
4769
4836
  import { spawn } from "child_process";
4770
4837
  import { existsSync as existsSync4 } from "fs";
4771
4838
  import { Socket } from "net";
4772
4839
  import { dirname as dirname3, join as join5 } from "path";
4773
4840
  import { fileURLToPath as fileURLToPath3 } from "url";
4774
4841
 
4842
+ // node_modules/@github/copilot-sdk/dist/generated/rpc.js
4843
+ function createServerRpc(connection) {
4844
+ return {
4845
+ ping: async (params) => connection.sendRequest("ping", params),
4846
+ models: {
4847
+ list: async () => connection.sendRequest("models.list", {})
4848
+ },
4849
+ tools: {
4850
+ list: async (params) => connection.sendRequest("tools.list", params)
4851
+ },
4852
+ account: {
4853
+ getQuota: async () => connection.sendRequest("account.getQuota", {})
4854
+ }
4855
+ };
4856
+ }
4857
+ function createSessionRpc(connection, sessionId) {
4858
+ return {
4859
+ model: {
4860
+ getCurrent: async () => connection.sendRequest("session.model.getCurrent", { sessionId }),
4861
+ switchTo: async (params) => connection.sendRequest("session.model.switchTo", { sessionId, ...params })
4862
+ },
4863
+ mode: {
4864
+ get: async () => connection.sendRequest("session.mode.get", { sessionId }),
4865
+ set: async (params) => connection.sendRequest("session.mode.set", { sessionId, ...params })
4866
+ },
4867
+ plan: {
4868
+ read: async () => connection.sendRequest("session.plan.read", { sessionId }),
4869
+ update: async (params) => connection.sendRequest("session.plan.update", { sessionId, ...params }),
4870
+ delete: async () => connection.sendRequest("session.plan.delete", { sessionId })
4871
+ },
4872
+ workspace: {
4873
+ listFiles: async () => connection.sendRequest("session.workspace.listFiles", { sessionId }),
4874
+ readFile: async (params) => connection.sendRequest("session.workspace.readFile", { sessionId, ...params }),
4875
+ createFile: async (params) => connection.sendRequest("session.workspace.createFile", { sessionId, ...params })
4876
+ },
4877
+ fleet: {
4878
+ start: async (params) => connection.sendRequest("session.fleet.start", { sessionId, ...params })
4879
+ },
4880
+ agent: {
4881
+ list: async () => connection.sendRequest("session.agent.list", { sessionId }),
4882
+ getCurrent: async () => connection.sendRequest("session.agent.getCurrent", { sessionId }),
4883
+ select: async (params) => connection.sendRequest("session.agent.select", { sessionId, ...params }),
4884
+ deselect: async () => connection.sendRequest("session.agent.deselect", { sessionId })
4885
+ },
4886
+ compaction: {
4887
+ compact: async () => connection.sendRequest("session.compaction.compact", { sessionId })
4888
+ },
4889
+ tools: {
4890
+ handlePendingToolCall: async (params) => connection.sendRequest("session.tools.handlePendingToolCall", { sessionId, ...params })
4891
+ },
4892
+ permissions: {
4893
+ handlePendingPermissionRequest: async (params) => connection.sendRequest("session.permissions.handlePendingPermissionRequest", { sessionId, ...params })
4894
+ }
4895
+ };
4896
+ }
4897
+
4775
4898
  // node_modules/@github/copilot-sdk/dist/sdkProtocolVersion.js
4776
- var SDK_PROTOCOL_VERSION = 2;
4899
+ var SDK_PROTOCOL_VERSION = 3;
4777
4900
  function getSdkProtocolVersion() {
4778
4901
  return SDK_PROTOCOL_VERSION;
4779
4902
  }
4780
4903
 
4781
4904
  // node_modules/@github/copilot-sdk/dist/session.js
4905
+ var import_node = __toESM(require_node(), 1);
4782
4906
  var CopilotSession = class {
4783
4907
  /**
4784
4908
  * Creates a new CopilotSession instance.
@@ -4799,6 +4923,16 @@ var CopilotSession = class {
4799
4923
  permissionHandler;
4800
4924
  userInputHandler;
4801
4925
  hooks;
4926
+ _rpc = null;
4927
+ /**
4928
+ * Typed session-scoped RPC methods.
4929
+ */
4930
+ get rpc() {
4931
+ if (!this._rpc) {
4932
+ this._rpc = createSessionRpc(this.connection, this.sessionId);
4933
+ }
4934
+ return this._rpc;
4935
+ }
4802
4936
  /**
4803
4937
  * Path to the session workspace directory when infinite sessions are enabled.
4804
4938
  * Contains checkpoints/, plan.md, and files/ subdirectories.
@@ -4815,7 +4949,7 @@ var CopilotSession = class {
4815
4949
  *
4816
4950
  * @param options - The message options including the prompt and optional attachments
4817
4951
  * @returns A promise that resolves with the message ID of the response
4818
- * @throws Error if the session has been destroyed or the connection fails
4952
+ * @throws Error if the session has been disconnected or the connection fails
4819
4953
  *
4820
4954
  * @example
4821
4955
  * ```typescript
@@ -4848,7 +4982,7 @@ var CopilotSession = class {
4848
4982
  * @returns A promise that resolves with the final assistant message when the session becomes idle,
4849
4983
  * or undefined if no assistant message was received
4850
4984
  * @throws Error if the timeout is reached before the session becomes idle
4851
- * @throws Error if the session has been destroyed or the connection fails
4985
+ * @throws Error if the session has been disconnected or the connection fails
4852
4986
  *
4853
4987
  * @example
4854
4988
  * ```typescript
@@ -4922,11 +5056,13 @@ var CopilotSession = class {
4922
5056
  }
4923
5057
  /**
4924
5058
  * Dispatches an event to all registered handlers.
5059
+ * Also handles broadcast request events internally (external tool calls, permissions).
4925
5060
  *
4926
5061
  * @param event - The session event to dispatch
4927
5062
  * @internal This method is for internal use by the SDK.
4928
5063
  */
4929
5064
  _dispatchEvent(event) {
5065
+ this._handleBroadcastEvent(event);
4930
5066
  const typedHandlers = this.typedEventHandlers.get(event.type);
4931
5067
  if (typedHandlers) {
4932
5068
  for (const handler of typedHandlers) {
@@ -4943,6 +5079,85 @@ var CopilotSession = class {
4943
5079
  }
4944
5080
  }
4945
5081
  }
5082
+ /**
5083
+ * Handles broadcast request events by executing local handlers and responding via RPC.
5084
+ * Handlers are dispatched as fire-and-forget — rejections propagate as unhandled promise
5085
+ * rejections, consistent with standard EventEmitter / event handler semantics.
5086
+ * @internal
5087
+ */
5088
+ _handleBroadcastEvent(event) {
5089
+ if (event.type === "external_tool.requested") {
5090
+ const { requestId, toolName } = event.data;
5091
+ const args = event.data.arguments;
5092
+ const toolCallId = event.data.toolCallId;
5093
+ const handler = this.toolHandlers.get(toolName);
5094
+ if (handler) {
5095
+ void this._executeToolAndRespond(requestId, toolName, toolCallId, args, handler);
5096
+ }
5097
+ } else if (event.type === "permission.requested") {
5098
+ const { requestId, permissionRequest } = event.data;
5099
+ if (this.permissionHandler) {
5100
+ void this._executePermissionAndRespond(requestId, permissionRequest);
5101
+ }
5102
+ }
5103
+ }
5104
+ /**
5105
+ * Executes a tool handler and sends the result back via RPC.
5106
+ * @internal
5107
+ */
5108
+ async _executeToolAndRespond(requestId, toolName, toolCallId, args, handler) {
5109
+ try {
5110
+ const rawResult = await handler(args, {
5111
+ sessionId: this.sessionId,
5112
+ toolCallId,
5113
+ toolName,
5114
+ arguments: args
5115
+ });
5116
+ let result;
5117
+ if (rawResult == null) {
5118
+ result = "";
5119
+ } else if (typeof rawResult === "string") {
5120
+ result = rawResult;
5121
+ } else {
5122
+ result = JSON.stringify(rawResult);
5123
+ }
5124
+ await this.rpc.tools.handlePendingToolCall({ requestId, result });
5125
+ } catch (error) {
5126
+ const message = error instanceof Error ? error.message : String(error);
5127
+ try {
5128
+ await this.rpc.tools.handlePendingToolCall({ requestId, error: message });
5129
+ } catch (rpcError) {
5130
+ if (!(rpcError instanceof import_node.ConnectionError || rpcError instanceof import_node.ResponseError)) {
5131
+ throw rpcError;
5132
+ }
5133
+ }
5134
+ }
5135
+ }
5136
+ /**
5137
+ * Executes a permission handler and sends the result back via RPC.
5138
+ * @internal
5139
+ */
5140
+ async _executePermissionAndRespond(requestId, permissionRequest) {
5141
+ try {
5142
+ const result = await this.permissionHandler(permissionRequest, {
5143
+ sessionId: this.sessionId
5144
+ });
5145
+ await this.rpc.permissions.handlePendingPermissionRequest({ requestId, result });
5146
+ } catch (_error) {
5147
+ try {
5148
+ await this.rpc.permissions.handlePendingPermissionRequest({
5149
+ requestId,
5150
+ result: {
5151
+ kind: "denied-no-approval-rule-and-could-not-request-from-user"
5152
+ }
5153
+ });
5154
+ } catch (rpcError) {
5155
+ if (!(rpcError instanceof import_node.ConnectionError || rpcError instanceof import_node.ResponseError)) {
5156
+ throw rpcError;
5157
+ }
5158
+ }
5159
+ }
5160
+ }
4946
5161
  /**
4947
5162
  * Registers custom tool handlers for this session.
4948
5163
  *
@@ -5008,13 +5223,14 @@ var CopilotSession = class {
5008
5223
  this.hooks = hooks;
5009
5224
  }
5010
5225
  /**
5011
- * Handles a permission request from the Copilot CLI.
5226
+ * Handles a permission request in the v2 protocol format (synchronous RPC).
5227
+ * Used as a back-compat adapter when connected to a v2 server.
5012
5228
  *
5013
5229
  * @param request - The permission request data from the CLI
5014
5230
  * @returns A promise that resolves with the permission decision
5015
5231
  * @internal This method is for internal use by the SDK.
5016
5232
  */
5017
- async _handlePermissionRequest(request) {
5233
+ async _handlePermissionRequestV2(request) {
5018
5234
  if (!this.permissionHandler) {
5019
5235
  return { kind: "denied-no-approval-rule-and-could-not-request-from-user" };
5020
5236
  }
@@ -5085,7 +5301,7 @@ var CopilotSession = class {
5085
5301
  * assistant responses, tool executions, and other session events.
5086
5302
  *
5087
5303
  * @returns A promise that resolves with an array of all session events
5088
- * @throws Error if the session has been destroyed or the connection fails
5304
+ * @throws Error if the session has been disconnected or the connection fails
5089
5305
  *
5090
5306
  * @example
5091
5307
  * ```typescript
@@ -5104,22 +5320,27 @@ var CopilotSession = class {
5104
5320
  return response.events;
5105
5321
  }
5106
5322
  /**
5107
- * Destroys this session and releases all associated resources.
5323
+ * Disconnects this session and releases all in-memory resources (event handlers,
5324
+ * tool handlers, permission handlers).
5108
5325
  *
5109
- * After calling this method, the session can no longer be used. All event
5110
- * handlers and tool handlers are cleared. To continue the conversation,
5111
- * use {@link CopilotClient.resumeSession} with the session ID.
5326
+ * Session state on disk (conversation history, planning state, artifacts) is
5327
+ * preserved, so the conversation can be resumed later by calling
5328
+ * {@link CopilotClient.resumeSession} with the session ID. To permanently
5329
+ * remove all session data including files on disk, use
5330
+ * {@link CopilotClient.deleteSession} instead.
5112
5331
  *
5113
- * @returns A promise that resolves when the session is destroyed
5332
+ * After calling this method, the session object can no longer be used.
5333
+ *
5334
+ * @returns A promise that resolves when the session is disconnected
5114
5335
  * @throws Error if the connection fails
5115
5336
  *
5116
5337
  * @example
5117
5338
  * ```typescript
5118
- * // Clean up when done
5119
- * await session.destroy();
5339
+ * // Clean up when done — session can still be resumed later
5340
+ * await session.disconnect();
5120
5341
  * ```
5121
5342
  */
5122
- async destroy() {
5343
+ async disconnect() {
5123
5344
  await this.connection.sendRequest("session.destroy", {
5124
5345
  sessionId: this.sessionId
5125
5346
  });
@@ -5128,6 +5349,22 @@ var CopilotSession = class {
5128
5349
  this.toolHandlers.clear();
5129
5350
  this.permissionHandler = void 0;
5130
5351
  }
5352
+ /**
5353
+ * @deprecated Use {@link disconnect} instead. This method will be removed in a future release.
5354
+ *
5355
+ * Disconnects this session and releases all in-memory resources.
5356
+ * Session data on disk is preserved for later resumption.
5357
+ *
5358
+ * @returns A promise that resolves when the session is disconnected
5359
+ * @throws Error if the connection fails
5360
+ */
5361
+ async destroy() {
5362
+ return this.disconnect();
5363
+ }
5364
+ /** Enables `await using session = ...` syntax for automatic cleanup. */
5365
+ async [Symbol.asyncDispose]() {
5366
+ return this.disconnect();
5367
+ }
5131
5368
  /**
5132
5369
  * Aborts the currently processing message in this session.
5133
5370
  *
@@ -5135,7 +5372,7 @@ var CopilotSession = class {
5135
5372
  * and can continue to be used for new messages.
5136
5373
  *
5137
5374
  * @returns A promise that resolves when the abort request is acknowledged
5138
- * @throws Error if the session has been destroyed or the connection fails
5375
+ * @throws Error if the session has been disconnected or the connection fails
5139
5376
  *
5140
5377
  * @example
5141
5378
  * ```typescript
@@ -5153,9 +5390,24 @@ var CopilotSession = class {
5153
5390
  sessionId: this.sessionId
5154
5391
  });
5155
5392
  }
5393
+ /**
5394
+ * Change the model for this session.
5395
+ * The new model takes effect for the next message. Conversation history is preserved.
5396
+ *
5397
+ * @param model - Model ID to switch to
5398
+ *
5399
+ * @example
5400
+ * ```typescript
5401
+ * await session.setModel("gpt-4.1");
5402
+ * ```
5403
+ */
5404
+ async setModel(model) {
5405
+ await this.rpc.model.switchTo({ modelId: model });
5406
+ }
5156
5407
  };
5157
5408
 
5158
5409
  // node_modules/@github/copilot-sdk/dist/client.js
5410
+ var MIN_PROTOCOL_VERSION = 2;
5159
5411
  function isZodSchema(value) {
5160
5412
  return value != null && typeof value === "object" && "toJSONSchema" in value && typeof value.toJSONSchema === "function";
5161
5413
  }
@@ -5166,6 +5418,12 @@ function toJsonSchema(parameters) {
5166
5418
  }
5167
5419
  return parameters;
5168
5420
  }
5421
+ function getNodeExecPath() {
5422
+ if (process.versions.bun) {
5423
+ return "node";
5424
+ }
5425
+ return process.execPath;
5426
+ }
5169
5427
  function getBundledCliPath() {
5170
5428
  const sdkUrl = import.meta.resolve("@github/copilot/sdk");
5171
5429
  const sdkPath = fileURLToPath3(sdkUrl);
@@ -5179,6 +5437,8 @@ var CopilotClient = class {
5179
5437
  actualHost = "localhost";
5180
5438
  state = "disconnected";
5181
5439
  sessions = /* @__PURE__ */ new Map();
5440
+ stderrBuffer = "";
5441
+ // Captures CLI stderr for error messages
5182
5442
  options;
5183
5443
  isExternalServer = false;
5184
5444
  forceStopping = false;
@@ -5186,6 +5446,23 @@ var CopilotClient = class {
5186
5446
  modelsCacheLock = Promise.resolve();
5187
5447
  sessionLifecycleHandlers = /* @__PURE__ */ new Set();
5188
5448
  typedLifecycleHandlers = /* @__PURE__ */ new Map();
5449
+ _rpc = null;
5450
+ processExitPromise = null;
5451
+ // Rejects when CLI process exits
5452
+ negotiatedProtocolVersion = null;
5453
+ /**
5454
+ * Typed server-scoped RPC methods.
5455
+ * @throws Error if the client is not connected
5456
+ */
5457
+ get rpc() {
5458
+ if (!this.connection) {
5459
+ throw new Error("Client is not connected. Call start() first.");
5460
+ }
5461
+ if (!this._rpc) {
5462
+ this._rpc = createServerRpc(this.connection);
5463
+ }
5464
+ return this._rpc;
5465
+ }
5189
5466
  /**
5190
5467
  * Creates a new CopilotClient instance.
5191
5468
  *
@@ -5211,6 +5488,11 @@ var CopilotClient = class {
5211
5488
  if (options.cliUrl && (options.useStdio === true || options.cliPath)) {
5212
5489
  throw new Error("cliUrl is mutually exclusive with useStdio and cliPath");
5213
5490
  }
5491
+ if (options.isChildProcess && (options.cliUrl || options.useStdio === false)) {
5492
+ throw new Error(
5493
+ "isChildProcess must be used in conjunction with useStdio and not with cliUrl"
5494
+ );
5495
+ }
5214
5496
  if (options.cliUrl && (options.githubToken || options.useLoggedInUser !== void 0)) {
5215
5497
  throw new Error(
5216
5498
  "githubToken and useLoggedInUser cannot be used with cliUrl (external server manages its own auth)"
@@ -5222,6 +5504,9 @@ var CopilotClient = class {
5222
5504
  this.actualPort = port;
5223
5505
  this.isExternalServer = true;
5224
5506
  }
5507
+ if (options.isChildProcess) {
5508
+ this.isExternalServer = true;
5509
+ }
5225
5510
  this.options = {
5226
5511
  cliPath: options.cliPath || getBundledCliPath(),
5227
5512
  cliArgs: options.cliArgs ?? [],
@@ -5229,6 +5514,7 @@ var CopilotClient = class {
5229
5514
  port: options.port || 0,
5230
5515
  useStdio: options.cliUrl ? false : options.useStdio ?? true,
5231
5516
  // Default to stdio unless cliUrl is provided
5517
+ isChildProcess: options.isChildProcess ?? false,
5232
5518
  cliUrl: options.cliUrl,
5233
5519
  logLevel: options.logLevel || "debug",
5234
5520
  autoStart: options.autoStart ?? true,
@@ -5300,10 +5586,14 @@ var CopilotClient = class {
5300
5586
  * Stops the CLI server and closes all active sessions.
5301
5587
  *
5302
5588
  * This method performs graceful cleanup:
5303
- * 1. Destroys all active sessions with retry logic
5589
+ * 1. Closes all active sessions (releases in-memory resources)
5304
5590
  * 2. Closes the JSON-RPC connection
5305
5591
  * 3. Terminates the CLI server process (if spawned by this client)
5306
5592
  *
5593
+ * Note: session data on disk is preserved, so sessions can be resumed later.
5594
+ * To permanently remove session data before stopping, call
5595
+ * {@link deleteSession} for each session first.
5596
+ *
5307
5597
  * @returns A promise that resolves with an array of errors encountered during cleanup.
5308
5598
  * An empty array indicates all cleanup succeeded.
5309
5599
  *
@@ -5322,7 +5612,7 @@ var CopilotClient = class {
5322
5612
  let lastError = null;
5323
5613
  for (let attempt = 1; attempt <= 3; attempt++) {
5324
5614
  try {
5325
- await session.destroy();
5615
+ await session.disconnect();
5326
5616
  lastError = null;
5327
5617
  break;
5328
5618
  } catch (error) {
@@ -5336,7 +5626,7 @@ var CopilotClient = class {
5336
5626
  if (lastError) {
5337
5627
  errors.push(
5338
5628
  new Error(
5339
- `Failed to destroy session ${sessionId} after 3 attempts: ${lastError.message}`
5629
+ `Failed to disconnect session ${sessionId} after 3 attempts: ${lastError.message}`
5340
5630
  )
5341
5631
  );
5342
5632
  }
@@ -5353,6 +5643,7 @@ var CopilotClient = class {
5353
5643
  );
5354
5644
  }
5355
5645
  this.connection = null;
5646
+ this._rpc = null;
5356
5647
  }
5357
5648
  this.modelsCache = null;
5358
5649
  if (this.socket) {
@@ -5381,6 +5672,8 @@ var CopilotClient = class {
5381
5672
  }
5382
5673
  this.state = "disconnected";
5383
5674
  this.actualPort = null;
5675
+ this.stderrBuffer = "";
5676
+ this.processExitPromise = null;
5384
5677
  return errors;
5385
5678
  }
5386
5679
  /**
@@ -5417,6 +5710,7 @@ var CopilotClient = class {
5417
5710
  } catch {
5418
5711
  }
5419
5712
  this.connection = null;
5713
+ this._rpc = null;
5420
5714
  }
5421
5715
  this.modelsCache = null;
5422
5716
  if (this.socket) {
@@ -5435,6 +5729,8 @@ var CopilotClient = class {
5435
5729
  }
5436
5730
  this.state = "disconnected";
5437
5731
  this.actualPort = null;
5732
+ this.stderrBuffer = "";
5733
+ this.processExitPromise = null;
5438
5734
  }
5439
5735
  /**
5440
5736
  * Creates a new conversation session with the Copilot CLI.
@@ -5450,10 +5746,11 @@ var CopilotClient = class {
5450
5746
  * @example
5451
5747
  * ```typescript
5452
5748
  * // Basic session
5453
- * const session = await client.createSession();
5749
+ * const session = await client.createSession({ onPermissionRequest: approveAll });
5454
5750
  *
5455
5751
  * // Session with model and tools
5456
5752
  * const session = await client.createSession({
5753
+ * onPermissionRequest: approveAll,
5457
5754
  * model: "gpt-4",
5458
5755
  * tools: [{
5459
5756
  * name: "get_weather",
@@ -5464,7 +5761,12 @@ var CopilotClient = class {
5464
5761
  * });
5465
5762
  * ```
5466
5763
  */
5467
- async createSession(config2 = {}) {
5764
+ async createSession(config2) {
5765
+ if (!config2?.onPermissionRequest) {
5766
+ throw new Error(
5767
+ "An onPermissionRequest handler is required when creating a session. For example, to allow all permissions, use { onPermissionRequest: approveAll }."
5768
+ );
5769
+ }
5468
5770
  if (!this.connection) {
5469
5771
  if (this.options.autoStart) {
5470
5772
  await this.start();
@@ -5475,22 +5777,25 @@ var CopilotClient = class {
5475
5777
  const response = await this.connection.sendRequest("session.create", {
5476
5778
  model: config2.model,
5477
5779
  sessionId: config2.sessionId,
5780
+ clientName: config2.clientName,
5478
5781
  reasoningEffort: config2.reasoningEffort,
5479
5782
  tools: config2.tools?.map((tool) => ({
5480
5783
  name: tool.name,
5481
5784
  description: tool.description,
5482
- parameters: toJsonSchema(tool.parameters)
5785
+ parameters: toJsonSchema(tool.parameters),
5786
+ overridesBuiltInTool: tool.overridesBuiltInTool
5483
5787
  })),
5484
5788
  systemMessage: config2.systemMessage,
5485
5789
  availableTools: config2.availableTools,
5486
5790
  excludedTools: config2.excludedTools,
5487
5791
  provider: config2.provider,
5488
- requestPermission: !!config2.onPermissionRequest,
5792
+ requestPermission: true,
5489
5793
  requestUserInput: !!config2.onUserInputRequest,
5490
5794
  hooks: !!(config2.hooks && Object.values(config2.hooks).some(Boolean)),
5491
5795
  workingDirectory: config2.workingDirectory,
5492
5796
  streaming: config2.streaming,
5493
5797
  mcpServers: config2.mcpServers,
5798
+ envValueMode: "direct",
5494
5799
  customAgents: config2.customAgents,
5495
5800
  configDir: config2.configDir,
5496
5801
  skillDirectories: config2.skillDirectories,
@@ -5500,9 +5805,7 @@ var CopilotClient = class {
5500
5805
  const { sessionId, workspacePath } = response;
5501
5806
  const session = new CopilotSession(sessionId, this.connection, workspacePath);
5502
5807
  session.registerTools(config2.tools);
5503
- if (config2.onPermissionRequest) {
5504
- session.registerPermissionHandler(config2.onPermissionRequest);
5505
- }
5808
+ session.registerPermissionHandler(config2.onPermissionRequest);
5506
5809
  if (config2.onUserInputRequest) {
5507
5810
  session.registerUserInputHandler(config2.onUserInputRequest);
5508
5811
  }
@@ -5527,15 +5830,21 @@ var CopilotClient = class {
5527
5830
  * @example
5528
5831
  * ```typescript
5529
5832
  * // Resume a previous session
5530
- * const session = await client.resumeSession("session-123");
5833
+ * const session = await client.resumeSession("session-123", { onPermissionRequest: approveAll });
5531
5834
  *
5532
5835
  * // Resume with new tools
5533
5836
  * const session = await client.resumeSession("session-123", {
5837
+ * onPermissionRequest: approveAll,
5534
5838
  * tools: [myNewTool]
5535
5839
  * });
5536
5840
  * ```
5537
5841
  */
5538
- async resumeSession(sessionId, config2 = {}) {
5842
+ async resumeSession(sessionId, config2) {
5843
+ if (!config2?.onPermissionRequest) {
5844
+ throw new Error(
5845
+ "An onPermissionRequest handler is required when resuming a session. For example, to allow all permissions, use { onPermissionRequest: approveAll }."
5846
+ );
5847
+ }
5539
5848
  if (!this.connection) {
5540
5849
  if (this.options.autoStart) {
5541
5850
  await this.start();
@@ -5545,6 +5854,7 @@ var CopilotClient = class {
5545
5854
  }
5546
5855
  const response = await this.connection.sendRequest("session.resume", {
5547
5856
  sessionId,
5857
+ clientName: config2.clientName,
5548
5858
  model: config2.model,
5549
5859
  reasoningEffort: config2.reasoningEffort,
5550
5860
  systemMessage: config2.systemMessage,
@@ -5553,16 +5863,18 @@ var CopilotClient = class {
5553
5863
  tools: config2.tools?.map((tool) => ({
5554
5864
  name: tool.name,
5555
5865
  description: tool.description,
5556
- parameters: toJsonSchema(tool.parameters)
5866
+ parameters: toJsonSchema(tool.parameters),
5867
+ overridesBuiltInTool: tool.overridesBuiltInTool
5557
5868
  })),
5558
5869
  provider: config2.provider,
5559
- requestPermission: !!config2.onPermissionRequest,
5870
+ requestPermission: true,
5560
5871
  requestUserInput: !!config2.onUserInputRequest,
5561
5872
  hooks: !!(config2.hooks && Object.values(config2.hooks).some(Boolean)),
5562
5873
  workingDirectory: config2.workingDirectory,
5563
5874
  configDir: config2.configDir,
5564
5875
  streaming: config2.streaming,
5565
5876
  mcpServers: config2.mcpServers,
5877
+ envValueMode: "direct",
5566
5878
  customAgents: config2.customAgents,
5567
5879
  skillDirectories: config2.skillDirectories,
5568
5880
  disabledSkills: config2.disabledSkills,
@@ -5572,9 +5884,7 @@ var CopilotClient = class {
5572
5884
  const { sessionId: resumedSessionId, workspacePath } = response;
5573
5885
  const session = new CopilotSession(resumedSessionId, this.connection, workspacePath);
5574
5886
  session.registerTools(config2.tools);
5575
- if (config2.onPermissionRequest) {
5576
- session.registerPermissionHandler(config2.onPermissionRequest);
5577
- }
5887
+ session.registerPermissionHandler(config2.onPermissionRequest);
5578
5888
  if (config2.onUserInputRequest) {
5579
5889
  session.registerUserInputHandler(config2.onUserInputRequest);
5580
5890
  }
@@ -5592,7 +5902,7 @@ var CopilotClient = class {
5592
5902
  * @example
5593
5903
  * ```typescript
5594
5904
  * if (client.getState() === "connected") {
5595
- * const session = await client.createSession();
5905
+ * const session = await client.createSession({ onPermissionRequest: approveAll });
5596
5906
  * }
5597
5907
  * ```
5598
5908
  */
@@ -5670,22 +5980,29 @@ var CopilotClient = class {
5670
5980
  }
5671
5981
  }
5672
5982
  /**
5673
- * Verify that the server's protocol version matches the SDK's expected version
5983
+ * Verify that the server's protocol version is within the supported range
5984
+ * and store the negotiated version.
5674
5985
  */
5675
5986
  async verifyProtocolVersion() {
5676
- const expectedVersion = getSdkProtocolVersion();
5677
- const pingResult = await this.ping();
5987
+ const maxVersion = getSdkProtocolVersion();
5988
+ let pingResult;
5989
+ if (this.processExitPromise) {
5990
+ pingResult = await Promise.race([this.ping(), this.processExitPromise]);
5991
+ } else {
5992
+ pingResult = await this.ping();
5993
+ }
5678
5994
  const serverVersion = pingResult.protocolVersion;
5679
5995
  if (serverVersion === void 0) {
5680
5996
  throw new Error(
5681
- `SDK protocol version mismatch: SDK expects version ${expectedVersion}, but server does not report a protocol version. Please update your server to ensure compatibility.`
5997
+ `SDK protocol version mismatch: SDK supports versions ${MIN_PROTOCOL_VERSION}-${maxVersion}, but server does not report a protocol version. Please update your server to ensure compatibility.`
5682
5998
  );
5683
5999
  }
5684
- if (serverVersion !== expectedVersion) {
6000
+ if (serverVersion < MIN_PROTOCOL_VERSION || serverVersion > maxVersion) {
5685
6001
  throw new Error(
5686
- `SDK protocol version mismatch: SDK expects version ${expectedVersion}, but server reports version ${serverVersion}. Please update your SDK or server to ensure compatibility.`
6002
+ `SDK protocol version mismatch: SDK supports versions ${MIN_PROTOCOL_VERSION}-${maxVersion}, but server reports version ${serverVersion}. Please update your SDK or server to ensure compatibility.`
5687
6003
  );
5688
6004
  }
6005
+ this.negotiatedProtocolVersion = serverVersion;
5689
6006
  }
5690
6007
  /**
5691
6008
  * Gets the ID of the most recently updated session.
@@ -5700,7 +6017,7 @@ var CopilotClient = class {
5700
6017
  * ```typescript
5701
6018
  * const lastId = await client.getLastSessionId();
5702
6019
  * if (lastId) {
5703
- * const session = await client.resumeSession(lastId);
6020
+ * const session = await client.resumeSession(lastId, { onPermissionRequest: approveAll });
5704
6021
  * }
5705
6022
  * ```
5706
6023
  */
@@ -5712,10 +6029,12 @@ var CopilotClient = class {
5712
6029
  return response.sessionId;
5713
6030
  }
5714
6031
  /**
5715
- * Deletes a session and its data from disk.
6032
+ * Permanently deletes a session and all its data from disk, including
6033
+ * conversation history, planning state, and artifacts.
5716
6034
  *
5717
- * This permanently removes the session and all its conversation history.
5718
- * The session cannot be resumed after deletion.
6035
+ * Unlike {@link CopilotSession.disconnect}, which only releases in-memory
6036
+ * resources and preserves session data for later resumption, this method
6037
+ * is irreversible. The session cannot be resumed after deletion.
5719
6038
  *
5720
6039
  * @param sessionId - The ID of the session to delete
5721
6040
  * @returns A promise that resolves when the session is deleted
@@ -5740,33 +6059,31 @@ var CopilotClient = class {
5740
6059
  this.sessions.delete(sessionId);
5741
6060
  }
5742
6061
  /**
5743
- * Lists all available sessions known to the server.
6062
+ * List all available sessions.
5744
6063
  *
5745
- * Returns metadata about each session including ID, timestamps, and summary.
5746
- *
5747
- * @returns A promise that resolves with an array of session metadata
5748
- * @throws Error if the client is not connected
6064
+ * @param filter - Optional filter to limit returned sessions by context fields
5749
6065
  *
5750
6066
  * @example
5751
- * ```typescript
6067
+ * // List all sessions
5752
6068
  * const sessions = await client.listSessions();
5753
- * for (const session of sessions) {
5754
- * console.log(`${session.sessionId}: ${session.summary}`);
5755
- * }
5756
- * ```
6069
+ *
6070
+ * @example
6071
+ * // List sessions for a specific repository
6072
+ * const sessions = await client.listSessions({ repository: "owner/repo" });
5757
6073
  */
5758
- async listSessions() {
6074
+ async listSessions(filter) {
5759
6075
  if (!this.connection) {
5760
6076
  throw new Error("Client not connected");
5761
6077
  }
5762
- const response = await this.connection.sendRequest("session.list", {});
6078
+ const response = await this.connection.sendRequest("session.list", { filter });
5763
6079
  const { sessions } = response;
5764
6080
  return sessions.map((s) => ({
5765
6081
  sessionId: s.sessionId,
5766
6082
  startTime: new Date(s.startTime),
5767
6083
  modifiedTime: new Date(s.modifiedTime),
5768
6084
  summary: s.summary,
5769
- isRemote: s.isRemote
6085
+ isRemote: s.isRemote,
6086
+ context: s.context
5770
6087
  }));
5771
6088
  }
5772
6089
  /**
@@ -5845,6 +6162,7 @@ var CopilotClient = class {
5845
6162
  */
5846
6163
  async startCLIServer() {
5847
6164
  return new Promise((resolve3, reject) => {
6165
+ this.stderrBuffer = "";
5848
6166
  const args = [
5849
6167
  ...this.options.cliArgs,
5850
6168
  "--headless",
@@ -5876,16 +6194,18 @@ var CopilotClient = class {
5876
6194
  const stdioConfig = this.options.useStdio ? ["pipe", "pipe", "pipe"] : ["ignore", "pipe", "pipe"];
5877
6195
  const isJsFile = this.options.cliPath.endsWith(".js");
5878
6196
  if (isJsFile) {
5879
- this.cliProcess = spawn(process.execPath, [this.options.cliPath, ...args], {
6197
+ this.cliProcess = spawn(getNodeExecPath(), [this.options.cliPath, ...args], {
5880
6198
  stdio: stdioConfig,
5881
6199
  cwd: this.options.cwd,
5882
- env: envWithoutNodeDebug
6200
+ env: envWithoutNodeDebug,
6201
+ windowsHide: true
5883
6202
  });
5884
6203
  } else {
5885
6204
  this.cliProcess = spawn(this.options.cliPath, args, {
5886
6205
  stdio: stdioConfig,
5887
6206
  cwd: this.options.cwd,
5888
- env: envWithoutNodeDebug
6207
+ env: envWithoutNodeDebug,
6208
+ windowsHide: true
5889
6209
  });
5890
6210
  }
5891
6211
  let stdout = "";
@@ -5905,6 +6225,7 @@ var CopilotClient = class {
5905
6225
  });
5906
6226
  }
5907
6227
  this.cliProcess.stderr?.on("data", (data) => {
6228
+ this.stderrBuffer += data.toString();
5908
6229
  const lines = data.toString().split("\n");
5909
6230
  for (const line of lines) {
5910
6231
  if (line.trim()) {
@@ -5916,13 +6237,54 @@ var CopilotClient = class {
5916
6237
  this.cliProcess.on("error", (error) => {
5917
6238
  if (!resolved) {
5918
6239
  resolved = true;
5919
- reject(new Error(`Failed to start CLI server: ${error.message}`));
6240
+ const stderrOutput = this.stderrBuffer.trim();
6241
+ if (stderrOutput) {
6242
+ reject(
6243
+ new Error(
6244
+ `Failed to start CLI server: ${error.message}
6245
+ stderr: ${stderrOutput}`
6246
+ )
6247
+ );
6248
+ } else {
6249
+ reject(new Error(`Failed to start CLI server: ${error.message}`));
6250
+ }
5920
6251
  }
5921
6252
  });
6253
+ this.processExitPromise = new Promise((_, rejectProcessExit) => {
6254
+ this.cliProcess.on("exit", (code) => {
6255
+ setTimeout(() => {
6256
+ const stderrOutput = this.stderrBuffer.trim();
6257
+ if (stderrOutput) {
6258
+ rejectProcessExit(
6259
+ new Error(
6260
+ `CLI server exited with code ${code}
6261
+ stderr: ${stderrOutput}`
6262
+ )
6263
+ );
6264
+ } else {
6265
+ rejectProcessExit(
6266
+ new Error(`CLI server exited unexpectedly with code ${code}`)
6267
+ );
6268
+ }
6269
+ }, 50);
6270
+ });
6271
+ });
6272
+ this.processExitPromise.catch(() => {
6273
+ });
5922
6274
  this.cliProcess.on("exit", (code) => {
5923
6275
  if (!resolved) {
5924
6276
  resolved = true;
5925
- reject(new Error(`CLI server exited with code ${code}`));
6277
+ const stderrOutput = this.stderrBuffer.trim();
6278
+ if (stderrOutput) {
6279
+ reject(
6280
+ new Error(
6281
+ `CLI server exited with code ${code}
6282
+ stderr: ${stderrOutput}`
6283
+ )
6284
+ );
6285
+ } else {
6286
+ reject(new Error(`CLI server exited with code ${code}`));
6287
+ }
5926
6288
  } else if (this.options.autoRestart && this.state === "connected") {
5927
6289
  void this.reconnect();
5928
6290
  }
@@ -5939,16 +6301,18 @@ var CopilotClient = class {
5939
6301
  * Connect to the CLI server (via socket or stdio)
5940
6302
  */
5941
6303
  async connectToServer() {
5942
- if (this.options.useStdio) {
5943
- return this.connectViaStdio();
6304
+ if (this.options.isChildProcess) {
6305
+ return this.connectToParentProcessViaStdio();
6306
+ } else if (this.options.useStdio) {
6307
+ return this.connectToChildProcessViaStdio();
5944
6308
  } else {
5945
6309
  return this.connectViaTcp();
5946
6310
  }
5947
6311
  }
5948
6312
  /**
5949
- * Connect via stdio pipes
6313
+ * Connect to child via stdio pipes
5950
6314
  */
5951
- async connectViaStdio() {
6315
+ async connectToChildProcessViaStdio() {
5952
6316
  if (!this.cliProcess) {
5953
6317
  throw new Error("CLI process not started");
5954
6318
  }
@@ -5957,9 +6321,23 @@ var CopilotClient = class {
5957
6321
  throw err;
5958
6322
  }
5959
6323
  });
5960
- this.connection = (0, import_node.createMessageConnection)(
5961
- new import_node.StreamMessageReader(this.cliProcess.stdout),
5962
- new import_node.StreamMessageWriter(this.cliProcess.stdin)
6324
+ this.connection = (0, import_node2.createMessageConnection)(
6325
+ new import_node2.StreamMessageReader(this.cliProcess.stdout),
6326
+ new import_node2.StreamMessageWriter(this.cliProcess.stdin)
6327
+ );
6328
+ this.attachConnectionHandlers();
6329
+ this.connection.listen();
6330
+ }
6331
+ /**
6332
+ * Connect to parent via stdio pipes
6333
+ */
6334
+ async connectToParentProcessViaStdio() {
6335
+ if (this.cliProcess) {
6336
+ throw new Error("CLI child process was unexpectedly started in parent process mode");
6337
+ }
6338
+ this.connection = (0, import_node2.createMessageConnection)(
6339
+ new import_node2.StreamMessageReader(process.stdin),
6340
+ new import_node2.StreamMessageWriter(process.stdout)
5963
6341
  );
5964
6342
  this.attachConnectionHandlers();
5965
6343
  this.connection.listen();
@@ -5974,9 +6352,9 @@ var CopilotClient = class {
5974
6352
  return new Promise((resolve3, reject) => {
5975
6353
  this.socket = new Socket();
5976
6354
  this.socket.connect(this.actualPort, this.actualHost, () => {
5977
- this.connection = (0, import_node.createMessageConnection)(
5978
- new import_node.StreamMessageReader(this.socket),
5979
- new import_node.StreamMessageWriter(this.socket)
6355
+ this.connection = (0, import_node2.createMessageConnection)(
6356
+ new import_node2.StreamMessageReader(this.socket),
6357
+ new import_node2.StreamMessageWriter(this.socket)
5980
6358
  );
5981
6359
  this.attachConnectionHandlers();
5982
6360
  this.connection.listen();
@@ -5999,11 +6377,11 @@ var CopilotClient = class {
5999
6377
  });
6000
6378
  this.connection.onRequest(
6001
6379
  "tool.call",
6002
- async (params) => await this.handleToolCallRequest(params)
6380
+ async (params) => await this.handleToolCallRequestV2(params)
6003
6381
  );
6004
6382
  this.connection.onRequest(
6005
6383
  "permission.request",
6006
- async (params) => await this.handlePermissionRequest(params)
6384
+ async (params) => await this.handlePermissionRequestV2(params)
6007
6385
  );
6008
6386
  this.connection.onRequest(
6009
6387
  "userInput.request",
@@ -6051,7 +6429,41 @@ var CopilotClient = class {
6051
6429
  }
6052
6430
  }
6053
6431
  }
6054
- async handleToolCallRequest(params) {
6432
+ async handleUserInputRequest(params) {
6433
+ if (!params || typeof params.sessionId !== "string" || typeof params.question !== "string") {
6434
+ throw new Error("Invalid user input request payload");
6435
+ }
6436
+ const session = this.sessions.get(params.sessionId);
6437
+ if (!session) {
6438
+ throw new Error(`Session not found: ${params.sessionId}`);
6439
+ }
6440
+ const result = await session._handleUserInputRequest({
6441
+ question: params.question,
6442
+ choices: params.choices,
6443
+ allowFreeform: params.allowFreeform
6444
+ });
6445
+ return result;
6446
+ }
6447
+ async handleHooksInvoke(params) {
6448
+ if (!params || typeof params.sessionId !== "string" || typeof params.hookType !== "string") {
6449
+ throw new Error("Invalid hooks invoke payload");
6450
+ }
6451
+ const session = this.sessions.get(params.sessionId);
6452
+ if (!session) {
6453
+ throw new Error(`Session not found: ${params.sessionId}`);
6454
+ }
6455
+ const output = await session._handleHooksInvoke(params.hookType, params.input);
6456
+ return { output };
6457
+ }
6458
+ // ========================================================================
6459
+ // Protocol v2 backward-compatibility adapters
6460
+ // ========================================================================
6461
+ /**
6462
+ * Handles a v2-style tool.call RPC request from the server.
6463
+ * Looks up the session and tool handler, executes it, and returns the result
6464
+ * in the v2 response format.
6465
+ */
6466
+ async handleToolCallRequestV2(params) {
6055
6467
  if (!params || typeof params.sessionId !== "string" || typeof params.toolCallId !== "string" || typeof params.toolName !== "string") {
6056
6468
  throw new Error("Invalid tool call payload");
6057
6469
  }
@@ -6061,25 +6473,28 @@ var CopilotClient = class {
6061
6473
  }
6062
6474
  const handler = session.getToolHandler(params.toolName);
6063
6475
  if (!handler) {
6064
- return { result: this.buildUnsupportedToolResult(params.toolName) };
6476
+ return {
6477
+ result: {
6478
+ textResultForLlm: `Tool '${params.toolName}' is not supported by this client instance.`,
6479
+ resultType: "failure",
6480
+ error: `tool '${params.toolName}' not supported`,
6481
+ toolTelemetry: {}
6482
+ }
6483
+ };
6065
6484
  }
6066
- return await this.executeToolCall(handler, params);
6067
- }
6068
- async executeToolCall(handler, request) {
6069
6485
  try {
6070
6486
  const invocation = {
6071
- sessionId: request.sessionId,
6072
- toolCallId: request.toolCallId,
6073
- toolName: request.toolName,
6074
- arguments: request.arguments
6487
+ sessionId: params.sessionId,
6488
+ toolCallId: params.toolCallId,
6489
+ toolName: params.toolName,
6490
+ arguments: params.arguments
6075
6491
  };
6076
- const result = await handler(request.arguments, invocation);
6077
- return { result: this.normalizeToolResult(result) };
6492
+ const result = await handler(params.arguments, invocation);
6493
+ return { result: this.normalizeToolResultV2(result) };
6078
6494
  } catch (error) {
6079
6495
  const message = error instanceof Error ? error.message : String(error);
6080
6496
  return {
6081
6497
  result: {
6082
- // Don't expose detailed error information to the LLM for security reasons
6083
6498
  textResultForLlm: "Invoking this tool produced an error. Detailed information is not available.",
6084
6499
  resultType: "failure",
6085
6500
  error: message,
@@ -6088,7 +6503,10 @@ var CopilotClient = class {
6088
6503
  };
6089
6504
  }
6090
6505
  }
6091
- async handlePermissionRequest(params) {
6506
+ /**
6507
+ * Handles a v2-style permission.request RPC request from the server.
6508
+ */
6509
+ async handlePermissionRequestV2(params) {
6092
6510
  if (!params || typeof params.sessionId !== "string" || !params.permissionRequest) {
6093
6511
  throw new Error("Invalid permission request payload");
6094
6512
  }
@@ -6097,7 +6515,7 @@ var CopilotClient = class {
6097
6515
  throw new Error(`Session not found: ${params.sessionId}`);
6098
6516
  }
6099
6517
  try {
6100
- const result = await session._handlePermissionRequest(params.permissionRequest);
6518
+ const result = await session._handlePermissionRequestV2(params.permissionRequest);
6101
6519
  return { result };
6102
6520
  } catch (_error) {
6103
6521
  return {
@@ -6107,33 +6525,7 @@ var CopilotClient = class {
6107
6525
  };
6108
6526
  }
6109
6527
  }
6110
- async handleUserInputRequest(params) {
6111
- if (!params || typeof params.sessionId !== "string" || typeof params.question !== "string") {
6112
- throw new Error("Invalid user input request payload");
6113
- }
6114
- const session = this.sessions.get(params.sessionId);
6115
- if (!session) {
6116
- throw new Error(`Session not found: ${params.sessionId}`);
6117
- }
6118
- const result = await session._handleUserInputRequest({
6119
- question: params.question,
6120
- choices: params.choices,
6121
- allowFreeform: params.allowFreeform
6122
- });
6123
- return result;
6124
- }
6125
- async handleHooksInvoke(params) {
6126
- if (!params || typeof params.sessionId !== "string" || typeof params.hookType !== "string") {
6127
- throw new Error("Invalid hooks invoke payload");
6128
- }
6129
- const session = this.sessions.get(params.sessionId);
6130
- if (!session) {
6131
- throw new Error(`Session not found: ${params.sessionId}`);
6132
- }
6133
- const output = await session._handleHooksInvoke(params.hookType, params.input);
6134
- return { output };
6135
- }
6136
- normalizeToolResult(result) {
6528
+ normalizeToolResultV2(result) {
6137
6529
  if (result === void 0 || result === null) {
6138
6530
  return {
6139
6531
  textResultForLlm: "Tool returned no result",
@@ -6155,14 +6547,6 @@ var CopilotClient = class {
6155
6547
  isToolResultObject(value) {
6156
6548
  return typeof value === "object" && value !== null && "textResultForLlm" in value && typeof value.textResultForLlm === "string" && "resultType" in value;
6157
6549
  }
6158
- buildUnsupportedToolResult(toolName) {
6159
- return {
6160
- textResultForLlm: `Tool '${toolName}' is not supported by this client instance.`,
6161
- resultType: "failure",
6162
- error: `tool '${toolName}' not supported`,
6163
- toolTelemetry: {}
6164
- };
6165
- }
6166
6550
  /**
6167
6551
  * Attempt to reconnect to the server
6168
6552
  */
@@ -6176,6 +6560,38 @@ var CopilotClient = class {
6176
6560
  }
6177
6561
  };
6178
6562
 
6563
+ // node_modules/@github/copilot-sdk/dist/types.js
6564
+ var approveAll = () => ({ kind: "approved" });
6565
+
6566
+ // src/L1-infra/ai/copilot.ts
6567
+ import { existsSync as existsSync5 } from "fs";
6568
+ import { join as join6, dirname as dirname4 } from "path";
6569
+ import { createRequire as createRequire2 } from "module";
6570
+ function resolveCopilotCliPath() {
6571
+ const platform = process.platform;
6572
+ const arch = process.arch;
6573
+ const binaryName = platform === "win32" ? "copilot.exe" : "copilot";
6574
+ const platformPkg = `@github/copilot-${platform}-${arch}`;
6575
+ try {
6576
+ const require_ = createRequire2(import.meta.url);
6577
+ const searchPaths = require_.resolve.paths(platformPkg) ?? [];
6578
+ for (const base of searchPaths) {
6579
+ const candidate = join6(base, platformPkg, binaryName);
6580
+ if (existsSync5(candidate)) return candidate;
6581
+ }
6582
+ } catch {
6583
+ }
6584
+ let dir = dirname4(import.meta.dirname ?? __dirname);
6585
+ for (let i = 0; i < 10; i++) {
6586
+ const candidate = join6(dir, "node_modules", platformPkg, binaryName);
6587
+ if (existsSync5(candidate)) return candidate;
6588
+ const parent = dirname4(dir);
6589
+ if (parent === dir) break;
6590
+ dir = parent;
6591
+ }
6592
+ return void 0;
6593
+ }
6594
+
6179
6595
  // src/L2-clients/llm/ai.ts
6180
6596
  function createOpenAI(...args) {
6181
6597
  return new default4(...args);
@@ -6191,6 +6607,7 @@ function createCopilotClient(...args) {
6191
6607
  init_configLogger();
6192
6608
  var DEFAULT_MODEL = "claude-opus-4.5";
6193
6609
  var DEFAULT_TIMEOUT_MS = 3e5;
6610
+ var SESSION_CREATE_TIMEOUT_MS = 3e4;
6194
6611
  var CopilotProvider = class {
6195
6612
  name = "copilot";
6196
6613
  client = null;
@@ -6202,21 +6619,57 @@ var CopilotProvider = class {
6202
6619
  }
6203
6620
  async createSession(config2) {
6204
6621
  if (!this.client) {
6205
- this.client = createCopilotClient({ autoStart: true, logLevel: "error" });
6622
+ const cliPath = resolveCopilotCliPath();
6623
+ if (cliPath) {
6624
+ logger_default.info(`[CopilotProvider] Using native CLI binary: ${cliPath}`);
6625
+ }
6626
+ this.client = createCopilotClient({
6627
+ autoStart: true,
6628
+ autoRestart: true,
6629
+ logLevel: "error",
6630
+ env: buildChildEnv(),
6631
+ ...cliPath ? { cliPath } : {}
6632
+ });
6206
6633
  }
6207
- const copilotSession = await this.client.createSession({
6208
- model: config2.model,
6209
- mcpServers: config2.mcpServers,
6210
- systemMessage: { mode: "replace", content: config2.systemPrompt },
6211
- tools: config2.tools.map((t) => ({
6212
- name: t.name,
6213
- description: t.description,
6214
- parameters: t.parameters,
6215
- handler: t.handler
6216
- })),
6217
- streaming: config2.streaming ?? true,
6218
- onUserInputRequest: config2.onUserInputRequest ? (request) => config2.onUserInputRequest(request) : void 0
6219
- });
6634
+ logger_default.info("[CopilotProvider] Creating session\u2026");
6635
+ let copilotSession;
6636
+ try {
6637
+ copilotSession = await new Promise((resolve3, reject) => {
6638
+ const timeoutId = setTimeout(
6639
+ () => reject(new Error(
6640
+ `[CopilotProvider] createSession timed out after ${SESSION_CREATE_TIMEOUT_MS / 1e3}s \u2014 the Copilot SDK language server may not be reachable. Check GitHub authentication and network connectivity.`
6641
+ )),
6642
+ SESSION_CREATE_TIMEOUT_MS
6643
+ );
6644
+ this.client.createSession({
6645
+ model: config2.model,
6646
+ mcpServers: config2.mcpServers,
6647
+ systemMessage: { mode: "replace", content: config2.systemPrompt },
6648
+ tools: config2.tools.map((t) => ({
6649
+ name: t.name,
6650
+ description: t.description,
6651
+ parameters: t.parameters,
6652
+ handler: t.handler
6653
+ })),
6654
+ streaming: config2.streaming ?? true,
6655
+ onPermissionRequest: approveAll,
6656
+ onUserInputRequest: config2.onUserInputRequest ? (request) => config2.onUserInputRequest(request) : void 0
6657
+ }).then(
6658
+ (session) => {
6659
+ clearTimeout(timeoutId);
6660
+ resolve3(session);
6661
+ },
6662
+ (err) => {
6663
+ clearTimeout(timeoutId);
6664
+ reject(err);
6665
+ }
6666
+ );
6667
+ });
6668
+ } catch (err) {
6669
+ this.client = null;
6670
+ throw err;
6671
+ }
6672
+ logger_default.info("[CopilotProvider] Session created successfully");
6220
6673
  return new CopilotSessionWrapper(
6221
6674
  copilotSession,
6222
6675
  config2.timeoutMs ?? DEFAULT_TIMEOUT_MS
@@ -6361,6 +6814,15 @@ var CopilotSessionWrapper = class {
6361
6814
  }
6362
6815
  }
6363
6816
  };
6817
+ function buildChildEnv() {
6818
+ const env = { ...process.env };
6819
+ const flag = "--disable-warning=ExperimentalWarning";
6820
+ const current = env.NODE_OPTIONS ?? "";
6821
+ if (!current.includes(flag)) {
6822
+ env.NODE_OPTIONS = current ? `${current} ${flag}` : flag;
6823
+ }
6824
+ return env;
6825
+ }
6364
6826
 
6365
6827
  // src/L0-pure/pricing/pricing.ts
6366
6828
  var COPILOT_PRU_OVERAGE_RATE = 0.04;
@@ -6611,7 +7073,8 @@ var OpenAIProvider = class {
6611
7073
  return "gpt-4o";
6612
7074
  }
6613
7075
  async createSession(config2) {
6614
- const client = createOpenAI();
7076
+ const appConfig = getConfig();
7077
+ const client = createOpenAI({ apiKey: appConfig.OPENAI_API_KEY });
6615
7078
  const model = config2.model ?? this.getDefaultModel();
6616
7079
  logger_default.info(`OpenAI session created (model=${model}, tools=${config2.tools.length})`);
6617
7080
  return new OpenAISession(client, config2, model);
@@ -9271,6 +9734,8 @@ function transcodeToMp4(inputPath, outputPath) {
9271
9734
  createFFmpeg(inputPath).outputOptions([
9272
9735
  "-c:v",
9273
9736
  "libx264",
9737
+ "-pix_fmt",
9738
+ "yuv420p",
9274
9739
  "-preset",
9275
9740
  "ultrafast",
9276
9741
  "-crf",
@@ -9574,32 +10039,6 @@ async function markFailed(slug, error) {
9574
10039
  logger_default.info(`[ProcessingState] Marked failed: ${slug} \u2014 ${error}`);
9575
10040
  }
9576
10041
 
9577
- // src/L3-services/gitOperations/gitOperations.ts
9578
- init_environment();
9579
- init_configLogger();
9580
- async function commitAndPush(videoSlug, message) {
9581
- const { REPO_ROOT } = getConfig();
9582
- const commitMessage = message || `Auto-processed video: ${videoSlug}`;
9583
- try {
9584
- logger_default.info(`Staging all changes in ${REPO_ROOT}`);
9585
- execCommandSync("git add -A", { cwd: REPO_ROOT, stdio: "pipe" });
9586
- logger_default.info(`Committing: ${commitMessage}`);
9587
- execCommandSync(`git commit -m "${commitMessage}"`, { cwd: REPO_ROOT, stdio: "pipe" });
9588
- const branch = execCommandSync("git rev-parse --abbrev-ref HEAD", { cwd: REPO_ROOT, stdio: "pipe" });
9589
- logger_default.info(`Pushing to origin ${branch}`);
9590
- execCommandSync(`git push origin ${branch}`, { cwd: REPO_ROOT, stdio: "pipe" });
9591
- logger_default.info("Git commit and push completed successfully");
9592
- } catch (error) {
9593
- const msg = error instanceof Error ? error.message : String(error);
9594
- if (msg.includes("nothing to commit")) {
9595
- logger_default.info("Nothing to commit, working tree clean");
9596
- return;
9597
- }
9598
- logger_default.error(`Git operation failed: ${msg}`);
9599
- throw error;
9600
- }
9601
- }
9602
-
9603
10042
  // src/L3-services/queueBuilder/queueBuilder.ts
9604
10043
  init_fileSystem();
9605
10044
  init_paths();
@@ -9904,9 +10343,6 @@ function markCompleted2(...args) {
9904
10343
  function markFailed2(...args) {
9905
10344
  return markFailed(...args);
9906
10345
  }
9907
- function commitAndPush2(...args) {
9908
- return commitAndPush(...args);
9909
- }
9910
10346
  function buildPublishQueue2(...args) {
9911
10347
  return buildPublishQueue(...args);
9912
10348
  }
@@ -9960,6 +10396,7 @@ var BaseAgent = class _BaseAgent {
9960
10396
  for (let attempt = 1; attempt <= _BaseAgent.MAX_RETRIES; attempt++) {
9961
10397
  try {
9962
10398
  if (!this.session) {
10399
+ logger_default.info(`[${this.agentName}] Creating LLM session (provider=${this.provider.name})\u2026`);
9963
10400
  this.session = await this.provider.createSession({
9964
10401
  systemPrompt: this.systemPrompt,
9965
10402
  tools: this.getTools(),
@@ -9970,6 +10407,7 @@ var BaseAgent = class _BaseAgent {
9970
10407
  onUserInputRequest: this.getUserInputHandler()
9971
10408
  });
9972
10409
  this.setupEventHandlers(this.session);
10410
+ logger_default.info(`[${this.agentName}] LLM session ready`);
9973
10411
  }
9974
10412
  logger_default.info(`[${this.agentName}] Sending message (attempt ${attempt}/${_BaseAgent.MAX_RETRIES}): ${userMessage.substring(0, 80)}\u2026`);
9975
10413
  costTracker.setAgent(this.agentName);
@@ -10007,11 +10445,12 @@ var BaseAgent = class _BaseAgent {
10007
10445
  }
10008
10446
  /** Check if an error message indicates a transient/retryable failure. */
10009
10447
  static isRetryableError(message) {
10010
- const retryablePatterns = [
10448
+ const lower = message.toLowerCase();
10449
+ return [
10011
10450
  "missing finish_reason",
10012
- "ECONNRESET",
10013
- "ETIMEDOUT",
10014
- "ECONNREFUSED",
10451
+ "econnreset",
10452
+ "etimedout",
10453
+ "econnrefused",
10015
10454
  "socket hang up",
10016
10455
  "network error",
10017
10456
  "rate limit",
@@ -10021,10 +10460,9 @@ var BaseAgent = class _BaseAgent {
10021
10460
  "503",
10022
10461
  "504",
10023
10462
  "stream ended",
10024
- "aborted"
10025
- ];
10026
- const lower = message.toLowerCase();
10027
- return retryablePatterns.some((p) => lower.includes(p.toLowerCase()));
10463
+ "aborted",
10464
+ "cli server exited"
10465
+ ].some((p) => lower.includes(p));
10028
10466
  }
10029
10467
  /** Wire up session event listeners for logging. Override for custom display. */
10030
10468
  setupEventHandlers(session) {
@@ -10923,32 +11361,6 @@ init_fileSystem();
10923
11361
  init_configLogger();
10924
11362
  init_environment();
10925
11363
 
10926
- // src/L1-infra/progress/progressEmitter.ts
10927
- var ProgressEmitter = class {
10928
- enabled = false;
10929
- /** Turn on progress event output to stderr. */
10930
- enable() {
10931
- this.enabled = true;
10932
- }
10933
- /** Turn off progress event output. */
10934
- disable() {
10935
- this.enabled = false;
10936
- }
10937
- /** Whether the emitter is currently active. */
10938
- isEnabled() {
10939
- return this.enabled;
10940
- }
10941
- /**
10942
- * Write a progress event as a single JSON line to stderr.
10943
- * No-op when the emitter is disabled.
10944
- */
10945
- emit(event) {
10946
- if (!this.enabled) return;
10947
- process.stderr.write(JSON.stringify(event) + "\n");
10948
- }
10949
- };
10950
- var progressEmitter = new ProgressEmitter();
10951
-
10952
11364
  // src/L5-assets/Asset.ts
10953
11365
  init_fileSystem();
10954
11366
  var Asset = class {
@@ -15860,12 +16272,6 @@ var MainVideoAsset = class _MainVideoAsset extends VideoAsset {
15860
16272
  async buildQueue(shorts, mediumClips, socialPosts, captionedVideoPath) {
15861
16273
  await this.buildPublishQueueData(shorts, mediumClips, socialPosts, captionedVideoPath);
15862
16274
  }
15863
- /**
15864
- * Commit and push all generated assets via git.
15865
- */
15866
- async commitAndPushChanges(message) {
15867
- return commitAndPush2(this.slug, message);
15868
- }
15869
16275
  };
15870
16276
 
15871
16277
  // src/L6-pipeline/pipeline.ts
@@ -16071,11 +16477,6 @@ async function processVideo(videoPath, ideas) {
16071
16477
  skipStage("queue-build" /* QueueBuild */, "NO_SOCIAL_POSTS");
16072
16478
  }
16073
16479
  const blogPost = await trackStage("blog" /* Blog */, () => asset.getBlog());
16074
- if (!cfg.SKIP_GIT) {
16075
- await trackStage("git-push" /* GitPush */, () => asset.commitAndPushChanges());
16076
- } else {
16077
- skipStage("git-push" /* GitPush */, "SKIP_GIT");
16078
- }
16079
16480
  const totalDuration = Date.now() - pipelineStart;
16080
16481
  const report = costTracker3.getReport();
16081
16482
  if (report.records.length > 0) {
@@ -16252,20 +16653,11 @@ var platformVariantMap = {
16252
16653
  youtube: "youtube",
16253
16654
  "youtube-shorts": "youtube-shorts"
16254
16655
  };
16255
- function applySdkEnvironment(sdkConfig) {
16256
- if (!sdkConfig) {
16257
- return;
16258
- }
16259
- if (sdkConfig.anthropicApiKey) process.env.ANTHROPIC_API_KEY = sdkConfig.anthropicApiKey;
16260
- if (sdkConfig.geminiApiKey) process.env.GEMINI_API_KEY = sdkConfig.geminiApiKey;
16261
- if (sdkConfig.llmProvider) process.env.LLM_PROVIDER = sdkConfig.llmProvider;
16262
- if (sdkConfig.llmModel) process.env.LLM_MODEL = sdkConfig.llmModel;
16263
- if (sdkConfig.geminiModel) process.env.GEMINI_MODEL = sdkConfig.geminiModel;
16264
- if (sdkConfig.repoRoot) process.env.REPO_ROOT = sdkConfig.repoRoot;
16265
- }
16266
16656
  function mapSdkConfigToCliOptions(sdkConfig) {
16267
16657
  return {
16268
16658
  openaiKey: sdkConfig?.openaiApiKey,
16659
+ anthropicKey: sdkConfig?.anthropicApiKey,
16660
+ geminiKey: sdkConfig?.geminiApiKey,
16269
16661
  exaKey: sdkConfig?.exaApiKey,
16270
16662
  youtubeKey: sdkConfig?.youtubeApiKey,
16271
16663
  perplexityKey: sdkConfig?.perplexityApiKey,
@@ -16276,12 +16668,15 @@ function mapSdkConfigToCliOptions(sdkConfig) {
16276
16668
  lateApiKey: sdkConfig?.lateApiKey,
16277
16669
  lateProfileId: sdkConfig?.lateProfileId,
16278
16670
  ideasRepo: sdkConfig?.ideasRepo,
16279
- githubToken: sdkConfig?.githubToken
16671
+ githubToken: sdkConfig?.githubToken,
16672
+ llmProvider: sdkConfig?.llmProvider,
16673
+ llmModel: sdkConfig?.llmModel,
16674
+ geminiModel: sdkConfig?.geminiModel,
16675
+ repoRoot: sdkConfig?.repoRoot
16280
16676
  };
16281
16677
  }
16282
16678
  function mapProcessOptionsToCliOverrides(options) {
16283
16679
  const overrides = {};
16284
- if (options?.skipGit !== void 0) overrides.git = !options.skipGit;
16285
16680
  if (options?.skipSilenceRemoval !== void 0) overrides.silenceRemoval = !options.skipSilenceRemoval;
16286
16681
  if (options?.skipShorts !== void 0) overrides.shorts = !options.skipShorts;
16287
16682
  if (options?.skipMediumClips !== void 0) overrides.mediumClips = !options.skipMediumClips;
@@ -16346,10 +16741,10 @@ function applyPersistedConfigToRuntime(target, value, currentCliOptions) {
16346
16741
  currentCliOptions.githubToken = value;
16347
16742
  break;
16348
16743
  case "credentials.anthropicApiKey":
16349
- process.env.ANTHROPIC_API_KEY = value;
16744
+ currentCliOptions.anthropicKey = value;
16350
16745
  break;
16351
16746
  case "credentials.geminiApiKey":
16352
- process.env.GEMINI_API_KEY = value;
16747
+ currentCliOptions.geminiKey = value;
16353
16748
  break;
16354
16749
  case "defaults.outputDir":
16355
16750
  currentCliOptions.outputDir = value;
@@ -16367,13 +16762,13 @@ function applyPersistedConfigToRuntime(target, value, currentCliOptions) {
16367
16762
  currentCliOptions.lateProfileId = value;
16368
16763
  break;
16369
16764
  case "defaults.llmProvider":
16370
- process.env.LLM_PROVIDER = value;
16765
+ currentCliOptions.llmProvider = value;
16371
16766
  break;
16372
16767
  case "defaults.llmModel":
16373
- process.env.LLM_MODEL = value;
16768
+ currentCliOptions.llmModel = value;
16374
16769
  break;
16375
16770
  case "defaults.geminiModel":
16376
- process.env.GEMINI_MODEL = value;
16771
+ currentCliOptions.geminiModel = value;
16377
16772
  break;
16378
16773
  default:
16379
16774
  break;
@@ -16386,10 +16781,6 @@ function applyRuntimeOnlyOverride(rawKey, value, currentCliOptions) {
16386
16781
  case "VERBOSE":
16387
16782
  currentCliOptions.verbose = Boolean(value);
16388
16783
  return true;
16389
- case "skipGit":
16390
- case "SKIP_GIT":
16391
- currentCliOptions.git = !Boolean(value);
16392
- return true;
16393
16784
  case "skipSilenceRemoval":
16394
16785
  case "SKIP_SILENCE_REMOVAL":
16395
16786
  currentCliOptions.silenceRemoval = !Boolean(value);
@@ -16420,15 +16811,15 @@ function applyRuntimeOnlyOverride(rawKey, value, currentCliOptions) {
16420
16811
  return true;
16421
16812
  case "repoRoot":
16422
16813
  case "REPO_ROOT":
16423
- process.env.REPO_ROOT = String(value);
16814
+ currentCliOptions.repoRoot = String(value);
16424
16815
  return true;
16425
16816
  case "ffmpegPath":
16426
16817
  case "FFMPEG_PATH":
16427
- process.env.FFMPEG_PATH = String(value);
16818
+ currentCliOptions.ffmpegPath = String(value);
16428
16819
  return true;
16429
16820
  case "ffprobePath":
16430
16821
  case "FFPROBE_PATH":
16431
- process.env.FFPROBE_PATH = String(value);
16822
+ currentCliOptions.ffprobePath = String(value);
16432
16823
  return true;
16433
16824
  default:
16434
16825
  return false;
@@ -16587,7 +16978,6 @@ async function buildSocialPosts(context, platforms) {
16587
16978
  }));
16588
16979
  }
16589
16980
  function createVidPipe(sdkConfig) {
16590
- applySdkEnvironment(sdkConfig);
16591
16981
  let currentCliOptions = mapSdkConfigToCliOptions(sdkConfig);
16592
16982
  initConfig(currentCliOptions);
16593
16983
  function refreshConfig() {
@@ -16658,22 +17048,6 @@ function createVidPipe(sdkConfig) {
16658
17048
  status: buildDiagnosticStatus(false, Boolean(config2.EXA_API_KEY)),
16659
17049
  message: config2.EXA_API_KEY ? "EXA_API_KEY is configured" : "EXA_API_KEY is not configured (optional)"
16660
17050
  });
16661
- try {
16662
- const gitResult = spawnCommand("git", ["--version"], { timeout: 1e4 });
16663
- const passed = gitResult.status === 0 && typeof gitResult.stdout === "string" && gitResult.stdout.length > 0;
16664
- checks.push({
16665
- name: "git",
16666
- status: buildDiagnosticStatus(false, passed),
16667
- message: passed ? `Git ${parseVersionFromOutput(gitResult.stdout)} detected` : "Git is not available (optional for git-push stage)"
16668
- });
16669
- } catch (error) {
16670
- checks.push({
16671
- name: "git",
16672
- status: "warn",
16673
- message: "Git is not available (optional for git-push stage)",
16674
- details: error instanceof Error ? error.message : String(error)
16675
- });
16676
- }
16677
17051
  const watchFolder = config2.WATCH_FOLDER || join(process.cwd(), "watch");
16678
17052
  checks.push({
16679
17053
  name: "watch-folder",
@@ -16758,13 +17132,19 @@ function createVidPipe(sdkConfig) {
16758
17132
  const cliOverrides = mapProcessOptionsToCliOverrides(options);
16759
17133
  const ideaIds = options?.ideas?.map((ideaId) => String(ideaId));
16760
17134
  const ideas = ideaIds && ideaIds.length > 0 ? await getIdeasByIds(ideaIds) : void 0;
16761
- return await withTemporaryCliOverrides(cliOverrides, async () => {
16762
- const result = await processVideoSafe(videoPath, ideas);
16763
- if (!result) {
16764
- throw new Error(`VidPipe pipeline failed for "${videoPath}" with an uncaught error`);
16765
- }
16766
- return result;
16767
- });
17135
+ const listener = options?.onProgress;
17136
+ if (listener) progressEmitter.addListener(listener);
17137
+ try {
17138
+ return await withTemporaryCliOverrides(cliOverrides, async () => {
17139
+ const result = await processVideoSafe(videoPath, ideas);
17140
+ if (!result) {
17141
+ throw new Error(`VidPipe pipeline failed for "${videoPath}" with an uncaught error`);
17142
+ }
17143
+ return result;
17144
+ });
17145
+ } finally {
17146
+ if (listener) progressEmitter.removeListener(listener);
17147
+ }
16768
17148
  },
16769
17149
  async ideate(options) {
16770
17150
  return await generateIdeas3({