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/README.md +1 -4
- package/dist/cli.js +634 -227
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +66 -6
- package/dist/index.js +669 -289
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -56,7 +56,7 @@ function findRoot(startDir) {
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
function projectRoot() {
|
|
59
|
-
if (!_cachedRoot) _cachedRoot = findRoot(
|
|
59
|
+
if (!_cachedRoot) _cachedRoot = findRoot(__dirname2);
|
|
60
60
|
return _cachedRoot;
|
|
61
61
|
}
|
|
62
62
|
function assetsDir(...segments) {
|
|
@@ -70,11 +70,11 @@ function modelsDir() {
|
|
|
70
70
|
const bundled = resolve2(projectRoot(), "dist", "models");
|
|
71
71
|
return existsSync(bundled) ? bundled : assetsDir("models");
|
|
72
72
|
}
|
|
73
|
-
var
|
|
73
|
+
var __dirname2, _cachedRoot;
|
|
74
74
|
var init_paths = __esm({
|
|
75
75
|
"src/L1-infra/paths/paths.ts"() {
|
|
76
76
|
"use strict";
|
|
77
|
-
|
|
77
|
+
__dirname2 = dirname2(fileURLToPath2(import.meta.url));
|
|
78
78
|
}
|
|
79
79
|
});
|
|
80
80
|
|
|
@@ -415,8 +415,9 @@ var init_globalConfig = __esm({
|
|
|
415
415
|
|
|
416
416
|
// src/L1-infra/config/configResolver.ts
|
|
417
417
|
import { join as join4 } from "path";
|
|
418
|
-
function resolveString(...
|
|
419
|
-
|
|
418
|
+
function resolveString(cliValue, ...fallbacks) {
|
|
419
|
+
if (cliValue !== void 0) return cliValue;
|
|
420
|
+
for (const source of fallbacks) {
|
|
420
421
|
if (source !== void 0 && source !== "") {
|
|
421
422
|
return source;
|
|
422
423
|
}
|
|
@@ -434,7 +435,11 @@ function resolveBoolean(cliValue, envValue, defaultValue) {
|
|
|
434
435
|
}
|
|
435
436
|
function resolveConfig(cliOptions = {}) {
|
|
436
437
|
const globalConfig = loadGlobalConfig();
|
|
437
|
-
const repoRoot =
|
|
438
|
+
const repoRoot = resolveString(
|
|
439
|
+
cliOptions.repoRoot,
|
|
440
|
+
process.env.REPO_ROOT,
|
|
441
|
+
process.cwd()
|
|
442
|
+
);
|
|
438
443
|
return {
|
|
439
444
|
OPENAI_API_KEY: resolveString(
|
|
440
445
|
cliOptions.openaiKey,
|
|
@@ -448,14 +453,22 @@ function resolveConfig(cliOptions = {}) {
|
|
|
448
453
|
join4(repoRoot, "watch")
|
|
449
454
|
),
|
|
450
455
|
REPO_ROOT: repoRoot,
|
|
451
|
-
FFMPEG_PATH: resolveString(
|
|
452
|
-
|
|
456
|
+
FFMPEG_PATH: resolveString(
|
|
457
|
+
cliOptions.ffmpegPath,
|
|
458
|
+
process.env.FFMPEG_PATH,
|
|
459
|
+
"ffmpeg"
|
|
460
|
+
),
|
|
461
|
+
FFPROBE_PATH: resolveString(
|
|
462
|
+
cliOptions.ffprobePath,
|
|
463
|
+
process.env.FFPROBE_PATH,
|
|
464
|
+
"ffprobe"
|
|
465
|
+
),
|
|
453
466
|
EXA_API_KEY: resolveString(
|
|
454
467
|
cliOptions.exaKey,
|
|
455
468
|
process.env.EXA_API_KEY,
|
|
456
469
|
globalConfig.credentials.exaApiKey
|
|
457
470
|
),
|
|
458
|
-
EXA_MCP_URL: resolveString(process.env.EXA_MCP_URL, "https://mcp.exa.ai/mcp"),
|
|
471
|
+
EXA_MCP_URL: resolveString(void 0, process.env.EXA_MCP_URL, "https://mcp.exa.ai/mcp"),
|
|
459
472
|
YOUTUBE_API_KEY: resolveString(
|
|
460
473
|
cliOptions.youtubeKey,
|
|
461
474
|
process.env.YOUTUBE_API_KEY,
|
|
@@ -467,12 +480,18 @@ function resolveConfig(cliOptions = {}) {
|
|
|
467
480
|
globalConfig.credentials.perplexityApiKey
|
|
468
481
|
),
|
|
469
482
|
LLM_PROVIDER: resolveString(
|
|
483
|
+
cliOptions.llmProvider,
|
|
470
484
|
process.env.LLM_PROVIDER,
|
|
471
485
|
globalConfig.defaults.llmProvider,
|
|
472
486
|
"copilot"
|
|
473
487
|
),
|
|
474
|
-
LLM_MODEL: resolveString(
|
|
488
|
+
LLM_MODEL: resolveString(
|
|
489
|
+
cliOptions.llmModel,
|
|
490
|
+
process.env.LLM_MODEL,
|
|
491
|
+
globalConfig.defaults.llmModel
|
|
492
|
+
),
|
|
475
493
|
ANTHROPIC_API_KEY: resolveString(
|
|
494
|
+
cliOptions.anthropicKey,
|
|
476
495
|
process.env.ANTHROPIC_API_KEY,
|
|
477
496
|
globalConfig.credentials.anthropicApiKey
|
|
478
497
|
),
|
|
@@ -489,7 +508,6 @@ function resolveConfig(cliOptions = {}) {
|
|
|
489
508
|
join4(repoRoot, "brand.json")
|
|
490
509
|
),
|
|
491
510
|
VERBOSE: cliOptions.verbose ?? false,
|
|
492
|
-
SKIP_GIT: resolveBoolean(cliOptions.git === void 0 ? void 0 : !cliOptions.git, process.env.SKIP_GIT, false),
|
|
493
511
|
SKIP_SILENCE_REMOVAL: resolveBoolean(
|
|
494
512
|
cliOptions.silenceRemoval === void 0 ? void 0 : !cliOptions.silenceRemoval,
|
|
495
513
|
process.env.SKIP_SILENCE_REMOVAL,
|
|
@@ -536,10 +554,12 @@ function resolveConfig(cliOptions = {}) {
|
|
|
536
554
|
false
|
|
537
555
|
),
|
|
538
556
|
GEMINI_API_KEY: resolveString(
|
|
557
|
+
cliOptions.geminiKey,
|
|
539
558
|
process.env.GEMINI_API_KEY,
|
|
540
559
|
globalConfig.credentials.geminiApiKey
|
|
541
560
|
),
|
|
542
561
|
GEMINI_MODEL: resolveString(
|
|
562
|
+
cliOptions.geminiModel,
|
|
543
563
|
process.env.GEMINI_MODEL,
|
|
544
564
|
globalConfig.defaults.geminiModel,
|
|
545
565
|
"gemini-2.5-pro"
|
|
@@ -554,9 +574,19 @@ function resolveConfig(cliOptions = {}) {
|
|
|
554
574
|
cliOptions.githubToken,
|
|
555
575
|
process.env.GITHUB_TOKEN,
|
|
556
576
|
globalConfig.credentials.githubToken
|
|
557
|
-
)
|
|
577
|
+
),
|
|
578
|
+
MODEL_OVERRIDES: resolveModelOverrides()
|
|
558
579
|
};
|
|
559
580
|
}
|
|
581
|
+
function resolveModelOverrides() {
|
|
582
|
+
const overrides = {};
|
|
583
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
584
|
+
if (key.startsWith("MODEL_") && value) {
|
|
585
|
+
overrides[key] = value;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
return overrides;
|
|
589
|
+
}
|
|
560
590
|
var init_configResolver = __esm({
|
|
561
591
|
"src/L1-infra/config/configResolver.ts"() {
|
|
562
592
|
"use strict";
|
|
@@ -572,7 +602,7 @@ __export(environment_exports, {
|
|
|
572
602
|
validateRequiredKeys: () => validateRequiredKeys
|
|
573
603
|
});
|
|
574
604
|
function validateRequiredKeys() {
|
|
575
|
-
if (!config?.OPENAI_API_KEY
|
|
605
|
+
if (!config?.OPENAI_API_KEY) {
|
|
576
606
|
throw new Error("Missing required: OPENAI_API_KEY (set via --openai-key, env var, or vidpipe configure)");
|
|
577
607
|
}
|
|
578
608
|
}
|
|
@@ -720,8 +750,7 @@ var init_types = __esm({
|
|
|
720
750
|
{ stage: "short-posts" /* ShortPosts */, name: "Short Posts", stageNumber: 12 },
|
|
721
751
|
{ stage: "medium-clip-posts" /* MediumClipPosts */, name: "Medium Clip Posts", stageNumber: 13 },
|
|
722
752
|
{ stage: "queue-build" /* QueueBuild */, name: "Queue Build", stageNumber: 14 },
|
|
723
|
-
{ stage: "blog" /* Blog */, name: "Blog", stageNumber: 15 }
|
|
724
|
-
{ stage: "git-push" /* GitPush */, name: "Git Push", stageNumber: 16 }
|
|
753
|
+
{ stage: "blog" /* Blog */, name: "Blog", stageNumber: 15 }
|
|
725
754
|
];
|
|
726
755
|
TOTAL_STAGES = PIPELINE_STAGES.length;
|
|
727
756
|
PLATFORM_CHAR_LIMITS = {
|
|
@@ -870,7 +899,7 @@ var require_messages = __commonJS({
|
|
|
870
899
|
ErrorCodes2.jsonrpcReservedErrorRangeEnd = -32e3;
|
|
871
900
|
ErrorCodes2.serverErrorEnd = -32e3;
|
|
872
901
|
})(ErrorCodes || (exports.ErrorCodes = ErrorCodes = {}));
|
|
873
|
-
var
|
|
902
|
+
var ResponseError2 = class _ResponseError extends Error {
|
|
874
903
|
constructor(code, message, data) {
|
|
875
904
|
super(message);
|
|
876
905
|
this.code = is.number(code) ? code : ErrorCodes.UnknownErrorCode;
|
|
@@ -888,7 +917,7 @@ var require_messages = __commonJS({
|
|
|
888
917
|
return result;
|
|
889
918
|
}
|
|
890
919
|
};
|
|
891
|
-
exports.ResponseError =
|
|
920
|
+
exports.ResponseError = ResponseError2;
|
|
892
921
|
var ParameterStructures = class _ParameterStructures {
|
|
893
922
|
constructor(kind) {
|
|
894
923
|
this.kind = kind;
|
|
@@ -2441,14 +2470,14 @@ var require_connection = __commonJS({
|
|
|
2441
2470
|
ConnectionErrors2[ConnectionErrors2["Disposed"] = 2] = "Disposed";
|
|
2442
2471
|
ConnectionErrors2[ConnectionErrors2["AlreadyListening"] = 3] = "AlreadyListening";
|
|
2443
2472
|
})(ConnectionErrors || (exports.ConnectionErrors = ConnectionErrors = {}));
|
|
2444
|
-
var
|
|
2473
|
+
var ConnectionError2 = class _ConnectionError extends Error {
|
|
2445
2474
|
constructor(code, message) {
|
|
2446
2475
|
super(message);
|
|
2447
2476
|
this.code = code;
|
|
2448
2477
|
Object.setPrototypeOf(this, _ConnectionError.prototype);
|
|
2449
2478
|
}
|
|
2450
2479
|
};
|
|
2451
|
-
exports.ConnectionError =
|
|
2480
|
+
exports.ConnectionError = ConnectionError2;
|
|
2452
2481
|
var ConnectionStrategy;
|
|
2453
2482
|
(function(ConnectionStrategy2) {
|
|
2454
2483
|
function is(value) {
|
|
@@ -3071,15 +3100,15 @@ ${JSON.stringify(message, null, 4)}`);
|
|
|
3071
3100
|
}
|
|
3072
3101
|
function throwIfClosedOrDisposed() {
|
|
3073
3102
|
if (isClosed()) {
|
|
3074
|
-
throw new
|
|
3103
|
+
throw new ConnectionError2(ConnectionErrors.Closed, "Connection is closed.");
|
|
3075
3104
|
}
|
|
3076
3105
|
if (isDisposed()) {
|
|
3077
|
-
throw new
|
|
3106
|
+
throw new ConnectionError2(ConnectionErrors.Disposed, "Connection is disposed.");
|
|
3078
3107
|
}
|
|
3079
3108
|
}
|
|
3080
3109
|
function throwIfListening() {
|
|
3081
3110
|
if (isListening()) {
|
|
3082
|
-
throw new
|
|
3111
|
+
throw new ConnectionError2(ConnectionErrors.AlreadyListening, "Connection is already listening");
|
|
3083
3112
|
}
|
|
3084
3113
|
}
|
|
3085
3114
|
function throwIfNotListening() {
|
|
@@ -4064,6 +4093,67 @@ var require_node = __commonJS({
|
|
|
4064
4093
|
}
|
|
4065
4094
|
});
|
|
4066
4095
|
|
|
4096
|
+
// node_modules/@github/copilot-sdk/dist/generated/rpc.js
|
|
4097
|
+
function createServerRpc(connection) {
|
|
4098
|
+
return {
|
|
4099
|
+
ping: async (params) => connection.sendRequest("ping", params),
|
|
4100
|
+
models: {
|
|
4101
|
+
list: async () => connection.sendRequest("models.list", {})
|
|
4102
|
+
},
|
|
4103
|
+
tools: {
|
|
4104
|
+
list: async (params) => connection.sendRequest("tools.list", params)
|
|
4105
|
+
},
|
|
4106
|
+
account: {
|
|
4107
|
+
getQuota: async () => connection.sendRequest("account.getQuota", {})
|
|
4108
|
+
}
|
|
4109
|
+
};
|
|
4110
|
+
}
|
|
4111
|
+
function createSessionRpc(connection, sessionId) {
|
|
4112
|
+
return {
|
|
4113
|
+
model: {
|
|
4114
|
+
getCurrent: async () => connection.sendRequest("session.model.getCurrent", { sessionId }),
|
|
4115
|
+
switchTo: async (params) => connection.sendRequest("session.model.switchTo", { sessionId, ...params })
|
|
4116
|
+
},
|
|
4117
|
+
mode: {
|
|
4118
|
+
get: async () => connection.sendRequest("session.mode.get", { sessionId }),
|
|
4119
|
+
set: async (params) => connection.sendRequest("session.mode.set", { sessionId, ...params })
|
|
4120
|
+
},
|
|
4121
|
+
plan: {
|
|
4122
|
+
read: async () => connection.sendRequest("session.plan.read", { sessionId }),
|
|
4123
|
+
update: async (params) => connection.sendRequest("session.plan.update", { sessionId, ...params }),
|
|
4124
|
+
delete: async () => connection.sendRequest("session.plan.delete", { sessionId })
|
|
4125
|
+
},
|
|
4126
|
+
workspace: {
|
|
4127
|
+
listFiles: async () => connection.sendRequest("session.workspace.listFiles", { sessionId }),
|
|
4128
|
+
readFile: async (params) => connection.sendRequest("session.workspace.readFile", { sessionId, ...params }),
|
|
4129
|
+
createFile: async (params) => connection.sendRequest("session.workspace.createFile", { sessionId, ...params })
|
|
4130
|
+
},
|
|
4131
|
+
fleet: {
|
|
4132
|
+
start: async (params) => connection.sendRequest("session.fleet.start", { sessionId, ...params })
|
|
4133
|
+
},
|
|
4134
|
+
agent: {
|
|
4135
|
+
list: async () => connection.sendRequest("session.agent.list", { sessionId }),
|
|
4136
|
+
getCurrent: async () => connection.sendRequest("session.agent.getCurrent", { sessionId }),
|
|
4137
|
+
select: async (params) => connection.sendRequest("session.agent.select", { sessionId, ...params }),
|
|
4138
|
+
deselect: async () => connection.sendRequest("session.agent.deselect", { sessionId })
|
|
4139
|
+
},
|
|
4140
|
+
compaction: {
|
|
4141
|
+
compact: async () => connection.sendRequest("session.compaction.compact", { sessionId })
|
|
4142
|
+
},
|
|
4143
|
+
tools: {
|
|
4144
|
+
handlePendingToolCall: async (params) => connection.sendRequest("session.tools.handlePendingToolCall", { sessionId, ...params })
|
|
4145
|
+
},
|
|
4146
|
+
permissions: {
|
|
4147
|
+
handlePendingPermissionRequest: async (params) => connection.sendRequest("session.permissions.handlePendingPermissionRequest", { sessionId, ...params })
|
|
4148
|
+
}
|
|
4149
|
+
};
|
|
4150
|
+
}
|
|
4151
|
+
var init_rpc = __esm({
|
|
4152
|
+
"node_modules/@github/copilot-sdk/dist/generated/rpc.js"() {
|
|
4153
|
+
"use strict";
|
|
4154
|
+
}
|
|
4155
|
+
});
|
|
4156
|
+
|
|
4067
4157
|
// node_modules/@github/copilot-sdk/dist/sdkProtocolVersion.js
|
|
4068
4158
|
function getSdkProtocolVersion() {
|
|
4069
4159
|
return SDK_PROTOCOL_VERSION;
|
|
@@ -4072,15 +4162,17 @@ var SDK_PROTOCOL_VERSION;
|
|
|
4072
4162
|
var init_sdkProtocolVersion = __esm({
|
|
4073
4163
|
"node_modules/@github/copilot-sdk/dist/sdkProtocolVersion.js"() {
|
|
4074
4164
|
"use strict";
|
|
4075
|
-
SDK_PROTOCOL_VERSION =
|
|
4165
|
+
SDK_PROTOCOL_VERSION = 3;
|
|
4076
4166
|
}
|
|
4077
4167
|
});
|
|
4078
4168
|
|
|
4079
4169
|
// node_modules/@github/copilot-sdk/dist/session.js
|
|
4080
|
-
var CopilotSession;
|
|
4170
|
+
var import_node, CopilotSession;
|
|
4081
4171
|
var init_session = __esm({
|
|
4082
4172
|
"node_modules/@github/copilot-sdk/dist/session.js"() {
|
|
4083
4173
|
"use strict";
|
|
4174
|
+
import_node = __toESM(require_node(), 1);
|
|
4175
|
+
init_rpc();
|
|
4084
4176
|
CopilotSession = class {
|
|
4085
4177
|
/**
|
|
4086
4178
|
* Creates a new CopilotSession instance.
|
|
@@ -4101,6 +4193,16 @@ var init_session = __esm({
|
|
|
4101
4193
|
permissionHandler;
|
|
4102
4194
|
userInputHandler;
|
|
4103
4195
|
hooks;
|
|
4196
|
+
_rpc = null;
|
|
4197
|
+
/**
|
|
4198
|
+
* Typed session-scoped RPC methods.
|
|
4199
|
+
*/
|
|
4200
|
+
get rpc() {
|
|
4201
|
+
if (!this._rpc) {
|
|
4202
|
+
this._rpc = createSessionRpc(this.connection, this.sessionId);
|
|
4203
|
+
}
|
|
4204
|
+
return this._rpc;
|
|
4205
|
+
}
|
|
4104
4206
|
/**
|
|
4105
4207
|
* Path to the session workspace directory when infinite sessions are enabled.
|
|
4106
4208
|
* Contains checkpoints/, plan.md, and files/ subdirectories.
|
|
@@ -4117,7 +4219,7 @@ var init_session = __esm({
|
|
|
4117
4219
|
*
|
|
4118
4220
|
* @param options - The message options including the prompt and optional attachments
|
|
4119
4221
|
* @returns A promise that resolves with the message ID of the response
|
|
4120
|
-
* @throws Error if the session has been
|
|
4222
|
+
* @throws Error if the session has been disconnected or the connection fails
|
|
4121
4223
|
*
|
|
4122
4224
|
* @example
|
|
4123
4225
|
* ```typescript
|
|
@@ -4150,7 +4252,7 @@ var init_session = __esm({
|
|
|
4150
4252
|
* @returns A promise that resolves with the final assistant message when the session becomes idle,
|
|
4151
4253
|
* or undefined if no assistant message was received
|
|
4152
4254
|
* @throws Error if the timeout is reached before the session becomes idle
|
|
4153
|
-
* @throws Error if the session has been
|
|
4255
|
+
* @throws Error if the session has been disconnected or the connection fails
|
|
4154
4256
|
*
|
|
4155
4257
|
* @example
|
|
4156
4258
|
* ```typescript
|
|
@@ -4224,11 +4326,13 @@ var init_session = __esm({
|
|
|
4224
4326
|
}
|
|
4225
4327
|
/**
|
|
4226
4328
|
* Dispatches an event to all registered handlers.
|
|
4329
|
+
* Also handles broadcast request events internally (external tool calls, permissions).
|
|
4227
4330
|
*
|
|
4228
4331
|
* @param event - The session event to dispatch
|
|
4229
4332
|
* @internal This method is for internal use by the SDK.
|
|
4230
4333
|
*/
|
|
4231
4334
|
_dispatchEvent(event) {
|
|
4335
|
+
this._handleBroadcastEvent(event);
|
|
4232
4336
|
const typedHandlers = this.typedEventHandlers.get(event.type);
|
|
4233
4337
|
if (typedHandlers) {
|
|
4234
4338
|
for (const handler of typedHandlers) {
|
|
@@ -4245,6 +4349,85 @@ var init_session = __esm({
|
|
|
4245
4349
|
}
|
|
4246
4350
|
}
|
|
4247
4351
|
}
|
|
4352
|
+
/**
|
|
4353
|
+
* Handles broadcast request events by executing local handlers and responding via RPC.
|
|
4354
|
+
* Handlers are dispatched as fire-and-forget — rejections propagate as unhandled promise
|
|
4355
|
+
* rejections, consistent with standard EventEmitter / event handler semantics.
|
|
4356
|
+
* @internal
|
|
4357
|
+
*/
|
|
4358
|
+
_handleBroadcastEvent(event) {
|
|
4359
|
+
if (event.type === "external_tool.requested") {
|
|
4360
|
+
const { requestId, toolName } = event.data;
|
|
4361
|
+
const args = event.data.arguments;
|
|
4362
|
+
const toolCallId = event.data.toolCallId;
|
|
4363
|
+
const handler = this.toolHandlers.get(toolName);
|
|
4364
|
+
if (handler) {
|
|
4365
|
+
void this._executeToolAndRespond(requestId, toolName, toolCallId, args, handler);
|
|
4366
|
+
}
|
|
4367
|
+
} else if (event.type === "permission.requested") {
|
|
4368
|
+
const { requestId, permissionRequest } = event.data;
|
|
4369
|
+
if (this.permissionHandler) {
|
|
4370
|
+
void this._executePermissionAndRespond(requestId, permissionRequest);
|
|
4371
|
+
}
|
|
4372
|
+
}
|
|
4373
|
+
}
|
|
4374
|
+
/**
|
|
4375
|
+
* Executes a tool handler and sends the result back via RPC.
|
|
4376
|
+
* @internal
|
|
4377
|
+
*/
|
|
4378
|
+
async _executeToolAndRespond(requestId, toolName, toolCallId, args, handler) {
|
|
4379
|
+
try {
|
|
4380
|
+
const rawResult = await handler(args, {
|
|
4381
|
+
sessionId: this.sessionId,
|
|
4382
|
+
toolCallId,
|
|
4383
|
+
toolName,
|
|
4384
|
+
arguments: args
|
|
4385
|
+
});
|
|
4386
|
+
let result;
|
|
4387
|
+
if (rawResult == null) {
|
|
4388
|
+
result = "";
|
|
4389
|
+
} else if (typeof rawResult === "string") {
|
|
4390
|
+
result = rawResult;
|
|
4391
|
+
} else {
|
|
4392
|
+
result = JSON.stringify(rawResult);
|
|
4393
|
+
}
|
|
4394
|
+
await this.rpc.tools.handlePendingToolCall({ requestId, result });
|
|
4395
|
+
} catch (error) {
|
|
4396
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4397
|
+
try {
|
|
4398
|
+
await this.rpc.tools.handlePendingToolCall({ requestId, error: message });
|
|
4399
|
+
} catch (rpcError) {
|
|
4400
|
+
if (!(rpcError instanceof import_node.ConnectionError || rpcError instanceof import_node.ResponseError)) {
|
|
4401
|
+
throw rpcError;
|
|
4402
|
+
}
|
|
4403
|
+
}
|
|
4404
|
+
}
|
|
4405
|
+
}
|
|
4406
|
+
/**
|
|
4407
|
+
* Executes a permission handler and sends the result back via RPC.
|
|
4408
|
+
* @internal
|
|
4409
|
+
*/
|
|
4410
|
+
async _executePermissionAndRespond(requestId, permissionRequest) {
|
|
4411
|
+
try {
|
|
4412
|
+
const result = await this.permissionHandler(permissionRequest, {
|
|
4413
|
+
sessionId: this.sessionId
|
|
4414
|
+
});
|
|
4415
|
+
await this.rpc.permissions.handlePendingPermissionRequest({ requestId, result });
|
|
4416
|
+
} catch (_error) {
|
|
4417
|
+
try {
|
|
4418
|
+
await this.rpc.permissions.handlePendingPermissionRequest({
|
|
4419
|
+
requestId,
|
|
4420
|
+
result: {
|
|
4421
|
+
kind: "denied-no-approval-rule-and-could-not-request-from-user"
|
|
4422
|
+
}
|
|
4423
|
+
});
|
|
4424
|
+
} catch (rpcError) {
|
|
4425
|
+
if (!(rpcError instanceof import_node.ConnectionError || rpcError instanceof import_node.ResponseError)) {
|
|
4426
|
+
throw rpcError;
|
|
4427
|
+
}
|
|
4428
|
+
}
|
|
4429
|
+
}
|
|
4430
|
+
}
|
|
4248
4431
|
/**
|
|
4249
4432
|
* Registers custom tool handlers for this session.
|
|
4250
4433
|
*
|
|
@@ -4310,13 +4493,14 @@ var init_session = __esm({
|
|
|
4310
4493
|
this.hooks = hooks;
|
|
4311
4494
|
}
|
|
4312
4495
|
/**
|
|
4313
|
-
* Handles a permission request
|
|
4496
|
+
* Handles a permission request in the v2 protocol format (synchronous RPC).
|
|
4497
|
+
* Used as a back-compat adapter when connected to a v2 server.
|
|
4314
4498
|
*
|
|
4315
4499
|
* @param request - The permission request data from the CLI
|
|
4316
4500
|
* @returns A promise that resolves with the permission decision
|
|
4317
4501
|
* @internal This method is for internal use by the SDK.
|
|
4318
4502
|
*/
|
|
4319
|
-
async
|
|
4503
|
+
async _handlePermissionRequestV2(request) {
|
|
4320
4504
|
if (!this.permissionHandler) {
|
|
4321
4505
|
return { kind: "denied-no-approval-rule-and-could-not-request-from-user" };
|
|
4322
4506
|
}
|
|
@@ -4387,7 +4571,7 @@ var init_session = __esm({
|
|
|
4387
4571
|
* assistant responses, tool executions, and other session events.
|
|
4388
4572
|
*
|
|
4389
4573
|
* @returns A promise that resolves with an array of all session events
|
|
4390
|
-
* @throws Error if the session has been
|
|
4574
|
+
* @throws Error if the session has been disconnected or the connection fails
|
|
4391
4575
|
*
|
|
4392
4576
|
* @example
|
|
4393
4577
|
* ```typescript
|
|
@@ -4406,22 +4590,27 @@ var init_session = __esm({
|
|
|
4406
4590
|
return response.events;
|
|
4407
4591
|
}
|
|
4408
4592
|
/**
|
|
4409
|
-
*
|
|
4593
|
+
* Disconnects this session and releases all in-memory resources (event handlers,
|
|
4594
|
+
* tool handlers, permission handlers).
|
|
4410
4595
|
*
|
|
4411
|
-
*
|
|
4412
|
-
*
|
|
4413
|
-
*
|
|
4596
|
+
* Session state on disk (conversation history, planning state, artifacts) is
|
|
4597
|
+
* preserved, so the conversation can be resumed later by calling
|
|
4598
|
+
* {@link CopilotClient.resumeSession} with the session ID. To permanently
|
|
4599
|
+
* remove all session data including files on disk, use
|
|
4600
|
+
* {@link CopilotClient.deleteSession} instead.
|
|
4414
4601
|
*
|
|
4415
|
-
*
|
|
4602
|
+
* After calling this method, the session object can no longer be used.
|
|
4603
|
+
*
|
|
4604
|
+
* @returns A promise that resolves when the session is disconnected
|
|
4416
4605
|
* @throws Error if the connection fails
|
|
4417
4606
|
*
|
|
4418
4607
|
* @example
|
|
4419
4608
|
* ```typescript
|
|
4420
|
-
* // Clean up when done
|
|
4421
|
-
* await session.
|
|
4609
|
+
* // Clean up when done — session can still be resumed later
|
|
4610
|
+
* await session.disconnect();
|
|
4422
4611
|
* ```
|
|
4423
4612
|
*/
|
|
4424
|
-
async
|
|
4613
|
+
async disconnect() {
|
|
4425
4614
|
await this.connection.sendRequest("session.destroy", {
|
|
4426
4615
|
sessionId: this.sessionId
|
|
4427
4616
|
});
|
|
@@ -4430,6 +4619,22 @@ var init_session = __esm({
|
|
|
4430
4619
|
this.toolHandlers.clear();
|
|
4431
4620
|
this.permissionHandler = void 0;
|
|
4432
4621
|
}
|
|
4622
|
+
/**
|
|
4623
|
+
* @deprecated Use {@link disconnect} instead. This method will be removed in a future release.
|
|
4624
|
+
*
|
|
4625
|
+
* Disconnects this session and releases all in-memory resources.
|
|
4626
|
+
* Session data on disk is preserved for later resumption.
|
|
4627
|
+
*
|
|
4628
|
+
* @returns A promise that resolves when the session is disconnected
|
|
4629
|
+
* @throws Error if the connection fails
|
|
4630
|
+
*/
|
|
4631
|
+
async destroy() {
|
|
4632
|
+
return this.disconnect();
|
|
4633
|
+
}
|
|
4634
|
+
/** Enables `await using session = ...` syntax for automatic cleanup. */
|
|
4635
|
+
async [Symbol.asyncDispose]() {
|
|
4636
|
+
return this.disconnect();
|
|
4637
|
+
}
|
|
4433
4638
|
/**
|
|
4434
4639
|
* Aborts the currently processing message in this session.
|
|
4435
4640
|
*
|
|
@@ -4437,7 +4642,7 @@ var init_session = __esm({
|
|
|
4437
4642
|
* and can continue to be used for new messages.
|
|
4438
4643
|
*
|
|
4439
4644
|
* @returns A promise that resolves when the abort request is acknowledged
|
|
4440
|
-
* @throws Error if the session has been
|
|
4645
|
+
* @throws Error if the session has been disconnected or the connection fails
|
|
4441
4646
|
*
|
|
4442
4647
|
* @example
|
|
4443
4648
|
* ```typescript
|
|
@@ -4455,6 +4660,20 @@ var init_session = __esm({
|
|
|
4455
4660
|
sessionId: this.sessionId
|
|
4456
4661
|
});
|
|
4457
4662
|
}
|
|
4663
|
+
/**
|
|
4664
|
+
* Change the model for this session.
|
|
4665
|
+
* The new model takes effect for the next message. Conversation history is preserved.
|
|
4666
|
+
*
|
|
4667
|
+
* @param model - Model ID to switch to
|
|
4668
|
+
*
|
|
4669
|
+
* @example
|
|
4670
|
+
* ```typescript
|
|
4671
|
+
* await session.setModel("gpt-4.1");
|
|
4672
|
+
* ```
|
|
4673
|
+
*/
|
|
4674
|
+
async setModel(model) {
|
|
4675
|
+
await this.rpc.model.switchTo({ modelId: model });
|
|
4676
|
+
}
|
|
4458
4677
|
};
|
|
4459
4678
|
}
|
|
4460
4679
|
});
|
|
@@ -4475,18 +4694,26 @@ function toJsonSchema(parameters) {
|
|
|
4475
4694
|
}
|
|
4476
4695
|
return parameters;
|
|
4477
4696
|
}
|
|
4697
|
+
function getNodeExecPath() {
|
|
4698
|
+
if (process.versions.bun) {
|
|
4699
|
+
return "node";
|
|
4700
|
+
}
|
|
4701
|
+
return process.execPath;
|
|
4702
|
+
}
|
|
4478
4703
|
function getBundledCliPath() {
|
|
4479
4704
|
const sdkUrl = import.meta.resolve("@github/copilot/sdk");
|
|
4480
4705
|
const sdkPath = fileURLToPath3(sdkUrl);
|
|
4481
4706
|
return join5(dirname3(dirname3(sdkPath)), "index.js");
|
|
4482
4707
|
}
|
|
4483
|
-
var
|
|
4708
|
+
var import_node2, MIN_PROTOCOL_VERSION, CopilotClient;
|
|
4484
4709
|
var init_client = __esm({
|
|
4485
4710
|
"node_modules/@github/copilot-sdk/dist/client.js"() {
|
|
4486
4711
|
"use strict";
|
|
4487
|
-
|
|
4712
|
+
import_node2 = __toESM(require_node(), 1);
|
|
4713
|
+
init_rpc();
|
|
4488
4714
|
init_sdkProtocolVersion();
|
|
4489
4715
|
init_session();
|
|
4716
|
+
MIN_PROTOCOL_VERSION = 2;
|
|
4490
4717
|
CopilotClient = class {
|
|
4491
4718
|
cliProcess = null;
|
|
4492
4719
|
connection = null;
|
|
@@ -4495,6 +4722,8 @@ var init_client = __esm({
|
|
|
4495
4722
|
actualHost = "localhost";
|
|
4496
4723
|
state = "disconnected";
|
|
4497
4724
|
sessions = /* @__PURE__ */ new Map();
|
|
4725
|
+
stderrBuffer = "";
|
|
4726
|
+
// Captures CLI stderr for error messages
|
|
4498
4727
|
options;
|
|
4499
4728
|
isExternalServer = false;
|
|
4500
4729
|
forceStopping = false;
|
|
@@ -4502,6 +4731,23 @@ var init_client = __esm({
|
|
|
4502
4731
|
modelsCacheLock = Promise.resolve();
|
|
4503
4732
|
sessionLifecycleHandlers = /* @__PURE__ */ new Set();
|
|
4504
4733
|
typedLifecycleHandlers = /* @__PURE__ */ new Map();
|
|
4734
|
+
_rpc = null;
|
|
4735
|
+
processExitPromise = null;
|
|
4736
|
+
// Rejects when CLI process exits
|
|
4737
|
+
negotiatedProtocolVersion = null;
|
|
4738
|
+
/**
|
|
4739
|
+
* Typed server-scoped RPC methods.
|
|
4740
|
+
* @throws Error if the client is not connected
|
|
4741
|
+
*/
|
|
4742
|
+
get rpc() {
|
|
4743
|
+
if (!this.connection) {
|
|
4744
|
+
throw new Error("Client is not connected. Call start() first.");
|
|
4745
|
+
}
|
|
4746
|
+
if (!this._rpc) {
|
|
4747
|
+
this._rpc = createServerRpc(this.connection);
|
|
4748
|
+
}
|
|
4749
|
+
return this._rpc;
|
|
4750
|
+
}
|
|
4505
4751
|
/**
|
|
4506
4752
|
* Creates a new CopilotClient instance.
|
|
4507
4753
|
*
|
|
@@ -4527,6 +4773,11 @@ var init_client = __esm({
|
|
|
4527
4773
|
if (options.cliUrl && (options.useStdio === true || options.cliPath)) {
|
|
4528
4774
|
throw new Error("cliUrl is mutually exclusive with useStdio and cliPath");
|
|
4529
4775
|
}
|
|
4776
|
+
if (options.isChildProcess && (options.cliUrl || options.useStdio === false)) {
|
|
4777
|
+
throw new Error(
|
|
4778
|
+
"isChildProcess must be used in conjunction with useStdio and not with cliUrl"
|
|
4779
|
+
);
|
|
4780
|
+
}
|
|
4530
4781
|
if (options.cliUrl && (options.githubToken || options.useLoggedInUser !== void 0)) {
|
|
4531
4782
|
throw new Error(
|
|
4532
4783
|
"githubToken and useLoggedInUser cannot be used with cliUrl (external server manages its own auth)"
|
|
@@ -4538,6 +4789,9 @@ var init_client = __esm({
|
|
|
4538
4789
|
this.actualPort = port;
|
|
4539
4790
|
this.isExternalServer = true;
|
|
4540
4791
|
}
|
|
4792
|
+
if (options.isChildProcess) {
|
|
4793
|
+
this.isExternalServer = true;
|
|
4794
|
+
}
|
|
4541
4795
|
this.options = {
|
|
4542
4796
|
cliPath: options.cliPath || getBundledCliPath(),
|
|
4543
4797
|
cliArgs: options.cliArgs ?? [],
|
|
@@ -4545,6 +4799,7 @@ var init_client = __esm({
|
|
|
4545
4799
|
port: options.port || 0,
|
|
4546
4800
|
useStdio: options.cliUrl ? false : options.useStdio ?? true,
|
|
4547
4801
|
// Default to stdio unless cliUrl is provided
|
|
4802
|
+
isChildProcess: options.isChildProcess ?? false,
|
|
4548
4803
|
cliUrl: options.cliUrl,
|
|
4549
4804
|
logLevel: options.logLevel || "debug",
|
|
4550
4805
|
autoStart: options.autoStart ?? true,
|
|
@@ -4616,10 +4871,14 @@ var init_client = __esm({
|
|
|
4616
4871
|
* Stops the CLI server and closes all active sessions.
|
|
4617
4872
|
*
|
|
4618
4873
|
* This method performs graceful cleanup:
|
|
4619
|
-
* 1.
|
|
4874
|
+
* 1. Closes all active sessions (releases in-memory resources)
|
|
4620
4875
|
* 2. Closes the JSON-RPC connection
|
|
4621
4876
|
* 3. Terminates the CLI server process (if spawned by this client)
|
|
4622
4877
|
*
|
|
4878
|
+
* Note: session data on disk is preserved, so sessions can be resumed later.
|
|
4879
|
+
* To permanently remove session data before stopping, call
|
|
4880
|
+
* {@link deleteSession} for each session first.
|
|
4881
|
+
*
|
|
4623
4882
|
* @returns A promise that resolves with an array of errors encountered during cleanup.
|
|
4624
4883
|
* An empty array indicates all cleanup succeeded.
|
|
4625
4884
|
*
|
|
@@ -4638,7 +4897,7 @@ var init_client = __esm({
|
|
|
4638
4897
|
let lastError = null;
|
|
4639
4898
|
for (let attempt = 1; attempt <= 3; attempt++) {
|
|
4640
4899
|
try {
|
|
4641
|
-
await session.
|
|
4900
|
+
await session.disconnect();
|
|
4642
4901
|
lastError = null;
|
|
4643
4902
|
break;
|
|
4644
4903
|
} catch (error) {
|
|
@@ -4652,7 +4911,7 @@ var init_client = __esm({
|
|
|
4652
4911
|
if (lastError) {
|
|
4653
4912
|
errors.push(
|
|
4654
4913
|
new Error(
|
|
4655
|
-
`Failed to
|
|
4914
|
+
`Failed to disconnect session ${sessionId} after 3 attempts: ${lastError.message}`
|
|
4656
4915
|
)
|
|
4657
4916
|
);
|
|
4658
4917
|
}
|
|
@@ -4669,6 +4928,7 @@ var init_client = __esm({
|
|
|
4669
4928
|
);
|
|
4670
4929
|
}
|
|
4671
4930
|
this.connection = null;
|
|
4931
|
+
this._rpc = null;
|
|
4672
4932
|
}
|
|
4673
4933
|
this.modelsCache = null;
|
|
4674
4934
|
if (this.socket) {
|
|
@@ -4697,6 +4957,8 @@ var init_client = __esm({
|
|
|
4697
4957
|
}
|
|
4698
4958
|
this.state = "disconnected";
|
|
4699
4959
|
this.actualPort = null;
|
|
4960
|
+
this.stderrBuffer = "";
|
|
4961
|
+
this.processExitPromise = null;
|
|
4700
4962
|
return errors;
|
|
4701
4963
|
}
|
|
4702
4964
|
/**
|
|
@@ -4733,6 +4995,7 @@ var init_client = __esm({
|
|
|
4733
4995
|
} catch {
|
|
4734
4996
|
}
|
|
4735
4997
|
this.connection = null;
|
|
4998
|
+
this._rpc = null;
|
|
4736
4999
|
}
|
|
4737
5000
|
this.modelsCache = null;
|
|
4738
5001
|
if (this.socket) {
|
|
@@ -4751,6 +5014,8 @@ var init_client = __esm({
|
|
|
4751
5014
|
}
|
|
4752
5015
|
this.state = "disconnected";
|
|
4753
5016
|
this.actualPort = null;
|
|
5017
|
+
this.stderrBuffer = "";
|
|
5018
|
+
this.processExitPromise = null;
|
|
4754
5019
|
}
|
|
4755
5020
|
/**
|
|
4756
5021
|
* Creates a new conversation session with the Copilot CLI.
|
|
@@ -4766,10 +5031,11 @@ var init_client = __esm({
|
|
|
4766
5031
|
* @example
|
|
4767
5032
|
* ```typescript
|
|
4768
5033
|
* // Basic session
|
|
4769
|
-
* const session = await client.createSession();
|
|
5034
|
+
* const session = await client.createSession({ onPermissionRequest: approveAll });
|
|
4770
5035
|
*
|
|
4771
5036
|
* // Session with model and tools
|
|
4772
5037
|
* const session = await client.createSession({
|
|
5038
|
+
* onPermissionRequest: approveAll,
|
|
4773
5039
|
* model: "gpt-4",
|
|
4774
5040
|
* tools: [{
|
|
4775
5041
|
* name: "get_weather",
|
|
@@ -4780,7 +5046,12 @@ var init_client = __esm({
|
|
|
4780
5046
|
* });
|
|
4781
5047
|
* ```
|
|
4782
5048
|
*/
|
|
4783
|
-
async createSession(config2
|
|
5049
|
+
async createSession(config2) {
|
|
5050
|
+
if (!config2?.onPermissionRequest) {
|
|
5051
|
+
throw new Error(
|
|
5052
|
+
"An onPermissionRequest handler is required when creating a session. For example, to allow all permissions, use { onPermissionRequest: approveAll }."
|
|
5053
|
+
);
|
|
5054
|
+
}
|
|
4784
5055
|
if (!this.connection) {
|
|
4785
5056
|
if (this.options.autoStart) {
|
|
4786
5057
|
await this.start();
|
|
@@ -4791,22 +5062,25 @@ var init_client = __esm({
|
|
|
4791
5062
|
const response = await this.connection.sendRequest("session.create", {
|
|
4792
5063
|
model: config2.model,
|
|
4793
5064
|
sessionId: config2.sessionId,
|
|
5065
|
+
clientName: config2.clientName,
|
|
4794
5066
|
reasoningEffort: config2.reasoningEffort,
|
|
4795
5067
|
tools: config2.tools?.map((tool) => ({
|
|
4796
5068
|
name: tool.name,
|
|
4797
5069
|
description: tool.description,
|
|
4798
|
-
parameters: toJsonSchema(tool.parameters)
|
|
5070
|
+
parameters: toJsonSchema(tool.parameters),
|
|
5071
|
+
overridesBuiltInTool: tool.overridesBuiltInTool
|
|
4799
5072
|
})),
|
|
4800
5073
|
systemMessage: config2.systemMessage,
|
|
4801
5074
|
availableTools: config2.availableTools,
|
|
4802
5075
|
excludedTools: config2.excludedTools,
|
|
4803
5076
|
provider: config2.provider,
|
|
4804
|
-
requestPermission:
|
|
5077
|
+
requestPermission: true,
|
|
4805
5078
|
requestUserInput: !!config2.onUserInputRequest,
|
|
4806
5079
|
hooks: !!(config2.hooks && Object.values(config2.hooks).some(Boolean)),
|
|
4807
5080
|
workingDirectory: config2.workingDirectory,
|
|
4808
5081
|
streaming: config2.streaming,
|
|
4809
5082
|
mcpServers: config2.mcpServers,
|
|
5083
|
+
envValueMode: "direct",
|
|
4810
5084
|
customAgents: config2.customAgents,
|
|
4811
5085
|
configDir: config2.configDir,
|
|
4812
5086
|
skillDirectories: config2.skillDirectories,
|
|
@@ -4816,9 +5090,7 @@ var init_client = __esm({
|
|
|
4816
5090
|
const { sessionId, workspacePath } = response;
|
|
4817
5091
|
const session = new CopilotSession(sessionId, this.connection, workspacePath);
|
|
4818
5092
|
session.registerTools(config2.tools);
|
|
4819
|
-
|
|
4820
|
-
session.registerPermissionHandler(config2.onPermissionRequest);
|
|
4821
|
-
}
|
|
5093
|
+
session.registerPermissionHandler(config2.onPermissionRequest);
|
|
4822
5094
|
if (config2.onUserInputRequest) {
|
|
4823
5095
|
session.registerUserInputHandler(config2.onUserInputRequest);
|
|
4824
5096
|
}
|
|
@@ -4843,15 +5115,21 @@ var init_client = __esm({
|
|
|
4843
5115
|
* @example
|
|
4844
5116
|
* ```typescript
|
|
4845
5117
|
* // Resume a previous session
|
|
4846
|
-
* const session = await client.resumeSession("session-123");
|
|
5118
|
+
* const session = await client.resumeSession("session-123", { onPermissionRequest: approveAll });
|
|
4847
5119
|
*
|
|
4848
5120
|
* // Resume with new tools
|
|
4849
5121
|
* const session = await client.resumeSession("session-123", {
|
|
5122
|
+
* onPermissionRequest: approveAll,
|
|
4850
5123
|
* tools: [myNewTool]
|
|
4851
5124
|
* });
|
|
4852
5125
|
* ```
|
|
4853
5126
|
*/
|
|
4854
|
-
async resumeSession(sessionId, config2
|
|
5127
|
+
async resumeSession(sessionId, config2) {
|
|
5128
|
+
if (!config2?.onPermissionRequest) {
|
|
5129
|
+
throw new Error(
|
|
5130
|
+
"An onPermissionRequest handler is required when resuming a session. For example, to allow all permissions, use { onPermissionRequest: approveAll }."
|
|
5131
|
+
);
|
|
5132
|
+
}
|
|
4855
5133
|
if (!this.connection) {
|
|
4856
5134
|
if (this.options.autoStart) {
|
|
4857
5135
|
await this.start();
|
|
@@ -4861,6 +5139,7 @@ var init_client = __esm({
|
|
|
4861
5139
|
}
|
|
4862
5140
|
const response = await this.connection.sendRequest("session.resume", {
|
|
4863
5141
|
sessionId,
|
|
5142
|
+
clientName: config2.clientName,
|
|
4864
5143
|
model: config2.model,
|
|
4865
5144
|
reasoningEffort: config2.reasoningEffort,
|
|
4866
5145
|
systemMessage: config2.systemMessage,
|
|
@@ -4869,16 +5148,18 @@ var init_client = __esm({
|
|
|
4869
5148
|
tools: config2.tools?.map((tool) => ({
|
|
4870
5149
|
name: tool.name,
|
|
4871
5150
|
description: tool.description,
|
|
4872
|
-
parameters: toJsonSchema(tool.parameters)
|
|
5151
|
+
parameters: toJsonSchema(tool.parameters),
|
|
5152
|
+
overridesBuiltInTool: tool.overridesBuiltInTool
|
|
4873
5153
|
})),
|
|
4874
5154
|
provider: config2.provider,
|
|
4875
|
-
requestPermission:
|
|
5155
|
+
requestPermission: true,
|
|
4876
5156
|
requestUserInput: !!config2.onUserInputRequest,
|
|
4877
5157
|
hooks: !!(config2.hooks && Object.values(config2.hooks).some(Boolean)),
|
|
4878
5158
|
workingDirectory: config2.workingDirectory,
|
|
4879
5159
|
configDir: config2.configDir,
|
|
4880
5160
|
streaming: config2.streaming,
|
|
4881
5161
|
mcpServers: config2.mcpServers,
|
|
5162
|
+
envValueMode: "direct",
|
|
4882
5163
|
customAgents: config2.customAgents,
|
|
4883
5164
|
skillDirectories: config2.skillDirectories,
|
|
4884
5165
|
disabledSkills: config2.disabledSkills,
|
|
@@ -4888,9 +5169,7 @@ var init_client = __esm({
|
|
|
4888
5169
|
const { sessionId: resumedSessionId, workspacePath } = response;
|
|
4889
5170
|
const session = new CopilotSession(resumedSessionId, this.connection, workspacePath);
|
|
4890
5171
|
session.registerTools(config2.tools);
|
|
4891
|
-
|
|
4892
|
-
session.registerPermissionHandler(config2.onPermissionRequest);
|
|
4893
|
-
}
|
|
5172
|
+
session.registerPermissionHandler(config2.onPermissionRequest);
|
|
4894
5173
|
if (config2.onUserInputRequest) {
|
|
4895
5174
|
session.registerUserInputHandler(config2.onUserInputRequest);
|
|
4896
5175
|
}
|
|
@@ -4908,7 +5187,7 @@ var init_client = __esm({
|
|
|
4908
5187
|
* @example
|
|
4909
5188
|
* ```typescript
|
|
4910
5189
|
* if (client.getState() === "connected") {
|
|
4911
|
-
* const session = await client.createSession();
|
|
5190
|
+
* const session = await client.createSession({ onPermissionRequest: approveAll });
|
|
4912
5191
|
* }
|
|
4913
5192
|
* ```
|
|
4914
5193
|
*/
|
|
@@ -4986,22 +5265,29 @@ var init_client = __esm({
|
|
|
4986
5265
|
}
|
|
4987
5266
|
}
|
|
4988
5267
|
/**
|
|
4989
|
-
* Verify that the server's protocol version
|
|
5268
|
+
* Verify that the server's protocol version is within the supported range
|
|
5269
|
+
* and store the negotiated version.
|
|
4990
5270
|
*/
|
|
4991
5271
|
async verifyProtocolVersion() {
|
|
4992
|
-
const
|
|
4993
|
-
|
|
5272
|
+
const maxVersion = getSdkProtocolVersion();
|
|
5273
|
+
let pingResult;
|
|
5274
|
+
if (this.processExitPromise) {
|
|
5275
|
+
pingResult = await Promise.race([this.ping(), this.processExitPromise]);
|
|
5276
|
+
} else {
|
|
5277
|
+
pingResult = await this.ping();
|
|
5278
|
+
}
|
|
4994
5279
|
const serverVersion = pingResult.protocolVersion;
|
|
4995
5280
|
if (serverVersion === void 0) {
|
|
4996
5281
|
throw new Error(
|
|
4997
|
-
`SDK protocol version mismatch: SDK
|
|
5282
|
+
`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.`
|
|
4998
5283
|
);
|
|
4999
5284
|
}
|
|
5000
|
-
if (serverVersion
|
|
5285
|
+
if (serverVersion < MIN_PROTOCOL_VERSION || serverVersion > maxVersion) {
|
|
5001
5286
|
throw new Error(
|
|
5002
|
-
`SDK protocol version mismatch: SDK
|
|
5287
|
+
`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.`
|
|
5003
5288
|
);
|
|
5004
5289
|
}
|
|
5290
|
+
this.negotiatedProtocolVersion = serverVersion;
|
|
5005
5291
|
}
|
|
5006
5292
|
/**
|
|
5007
5293
|
* Gets the ID of the most recently updated session.
|
|
@@ -5016,7 +5302,7 @@ var init_client = __esm({
|
|
|
5016
5302
|
* ```typescript
|
|
5017
5303
|
* const lastId = await client.getLastSessionId();
|
|
5018
5304
|
* if (lastId) {
|
|
5019
|
-
* const session = await client.resumeSession(lastId);
|
|
5305
|
+
* const session = await client.resumeSession(lastId, { onPermissionRequest: approveAll });
|
|
5020
5306
|
* }
|
|
5021
5307
|
* ```
|
|
5022
5308
|
*/
|
|
@@ -5028,10 +5314,12 @@ var init_client = __esm({
|
|
|
5028
5314
|
return response.sessionId;
|
|
5029
5315
|
}
|
|
5030
5316
|
/**
|
|
5031
|
-
*
|
|
5317
|
+
* Permanently deletes a session and all its data from disk, including
|
|
5318
|
+
* conversation history, planning state, and artifacts.
|
|
5032
5319
|
*
|
|
5033
|
-
*
|
|
5034
|
-
*
|
|
5320
|
+
* Unlike {@link CopilotSession.disconnect}, which only releases in-memory
|
|
5321
|
+
* resources and preserves session data for later resumption, this method
|
|
5322
|
+
* is irreversible. The session cannot be resumed after deletion.
|
|
5035
5323
|
*
|
|
5036
5324
|
* @param sessionId - The ID of the session to delete
|
|
5037
5325
|
* @returns A promise that resolves when the session is deleted
|
|
@@ -5056,33 +5344,31 @@ var init_client = __esm({
|
|
|
5056
5344
|
this.sessions.delete(sessionId);
|
|
5057
5345
|
}
|
|
5058
5346
|
/**
|
|
5059
|
-
*
|
|
5060
|
-
*
|
|
5061
|
-
* Returns metadata about each session including ID, timestamps, and summary.
|
|
5347
|
+
* List all available sessions.
|
|
5062
5348
|
*
|
|
5063
|
-
* @
|
|
5064
|
-
* @throws Error if the client is not connected
|
|
5349
|
+
* @param filter - Optional filter to limit returned sessions by context fields
|
|
5065
5350
|
*
|
|
5066
5351
|
* @example
|
|
5067
|
-
*
|
|
5352
|
+
* // List all sessions
|
|
5068
5353
|
* const sessions = await client.listSessions();
|
|
5069
|
-
*
|
|
5070
|
-
*
|
|
5071
|
-
*
|
|
5072
|
-
*
|
|
5354
|
+
*
|
|
5355
|
+
* @example
|
|
5356
|
+
* // List sessions for a specific repository
|
|
5357
|
+
* const sessions = await client.listSessions({ repository: "owner/repo" });
|
|
5073
5358
|
*/
|
|
5074
|
-
async listSessions() {
|
|
5359
|
+
async listSessions(filter) {
|
|
5075
5360
|
if (!this.connection) {
|
|
5076
5361
|
throw new Error("Client not connected");
|
|
5077
5362
|
}
|
|
5078
|
-
const response = await this.connection.sendRequest("session.list", {});
|
|
5363
|
+
const response = await this.connection.sendRequest("session.list", { filter });
|
|
5079
5364
|
const { sessions } = response;
|
|
5080
5365
|
return sessions.map((s) => ({
|
|
5081
5366
|
sessionId: s.sessionId,
|
|
5082
5367
|
startTime: new Date(s.startTime),
|
|
5083
5368
|
modifiedTime: new Date(s.modifiedTime),
|
|
5084
5369
|
summary: s.summary,
|
|
5085
|
-
isRemote: s.isRemote
|
|
5370
|
+
isRemote: s.isRemote,
|
|
5371
|
+
context: s.context
|
|
5086
5372
|
}));
|
|
5087
5373
|
}
|
|
5088
5374
|
/**
|
|
@@ -5161,6 +5447,7 @@ var init_client = __esm({
|
|
|
5161
5447
|
*/
|
|
5162
5448
|
async startCLIServer() {
|
|
5163
5449
|
return new Promise((resolve3, reject) => {
|
|
5450
|
+
this.stderrBuffer = "";
|
|
5164
5451
|
const args = [
|
|
5165
5452
|
...this.options.cliArgs,
|
|
5166
5453
|
"--headless",
|
|
@@ -5192,16 +5479,18 @@ var init_client = __esm({
|
|
|
5192
5479
|
const stdioConfig = this.options.useStdio ? ["pipe", "pipe", "pipe"] : ["ignore", "pipe", "pipe"];
|
|
5193
5480
|
const isJsFile = this.options.cliPath.endsWith(".js");
|
|
5194
5481
|
if (isJsFile) {
|
|
5195
|
-
this.cliProcess = spawn(
|
|
5482
|
+
this.cliProcess = spawn(getNodeExecPath(), [this.options.cliPath, ...args], {
|
|
5196
5483
|
stdio: stdioConfig,
|
|
5197
5484
|
cwd: this.options.cwd,
|
|
5198
|
-
env: envWithoutNodeDebug
|
|
5485
|
+
env: envWithoutNodeDebug,
|
|
5486
|
+
windowsHide: true
|
|
5199
5487
|
});
|
|
5200
5488
|
} else {
|
|
5201
5489
|
this.cliProcess = spawn(this.options.cliPath, args, {
|
|
5202
5490
|
stdio: stdioConfig,
|
|
5203
5491
|
cwd: this.options.cwd,
|
|
5204
|
-
env: envWithoutNodeDebug
|
|
5492
|
+
env: envWithoutNodeDebug,
|
|
5493
|
+
windowsHide: true
|
|
5205
5494
|
});
|
|
5206
5495
|
}
|
|
5207
5496
|
let stdout = "";
|
|
@@ -5221,6 +5510,7 @@ var init_client = __esm({
|
|
|
5221
5510
|
});
|
|
5222
5511
|
}
|
|
5223
5512
|
this.cliProcess.stderr?.on("data", (data) => {
|
|
5513
|
+
this.stderrBuffer += data.toString();
|
|
5224
5514
|
const lines = data.toString().split("\n");
|
|
5225
5515
|
for (const line of lines) {
|
|
5226
5516
|
if (line.trim()) {
|
|
@@ -5232,13 +5522,54 @@ var init_client = __esm({
|
|
|
5232
5522
|
this.cliProcess.on("error", (error) => {
|
|
5233
5523
|
if (!resolved) {
|
|
5234
5524
|
resolved = true;
|
|
5235
|
-
|
|
5525
|
+
const stderrOutput = this.stderrBuffer.trim();
|
|
5526
|
+
if (stderrOutput) {
|
|
5527
|
+
reject(
|
|
5528
|
+
new Error(
|
|
5529
|
+
`Failed to start CLI server: ${error.message}
|
|
5530
|
+
stderr: ${stderrOutput}`
|
|
5531
|
+
)
|
|
5532
|
+
);
|
|
5533
|
+
} else {
|
|
5534
|
+
reject(new Error(`Failed to start CLI server: ${error.message}`));
|
|
5535
|
+
}
|
|
5236
5536
|
}
|
|
5237
5537
|
});
|
|
5538
|
+
this.processExitPromise = new Promise((_, rejectProcessExit) => {
|
|
5539
|
+
this.cliProcess.on("exit", (code) => {
|
|
5540
|
+
setTimeout(() => {
|
|
5541
|
+
const stderrOutput = this.stderrBuffer.trim();
|
|
5542
|
+
if (stderrOutput) {
|
|
5543
|
+
rejectProcessExit(
|
|
5544
|
+
new Error(
|
|
5545
|
+
`CLI server exited with code ${code}
|
|
5546
|
+
stderr: ${stderrOutput}`
|
|
5547
|
+
)
|
|
5548
|
+
);
|
|
5549
|
+
} else {
|
|
5550
|
+
rejectProcessExit(
|
|
5551
|
+
new Error(`CLI server exited unexpectedly with code ${code}`)
|
|
5552
|
+
);
|
|
5553
|
+
}
|
|
5554
|
+
}, 50);
|
|
5555
|
+
});
|
|
5556
|
+
});
|
|
5557
|
+
this.processExitPromise.catch(() => {
|
|
5558
|
+
});
|
|
5238
5559
|
this.cliProcess.on("exit", (code) => {
|
|
5239
5560
|
if (!resolved) {
|
|
5240
5561
|
resolved = true;
|
|
5241
|
-
|
|
5562
|
+
const stderrOutput = this.stderrBuffer.trim();
|
|
5563
|
+
if (stderrOutput) {
|
|
5564
|
+
reject(
|
|
5565
|
+
new Error(
|
|
5566
|
+
`CLI server exited with code ${code}
|
|
5567
|
+
stderr: ${stderrOutput}`
|
|
5568
|
+
)
|
|
5569
|
+
);
|
|
5570
|
+
} else {
|
|
5571
|
+
reject(new Error(`CLI server exited with code ${code}`));
|
|
5572
|
+
}
|
|
5242
5573
|
} else if (this.options.autoRestart && this.state === "connected") {
|
|
5243
5574
|
void this.reconnect();
|
|
5244
5575
|
}
|
|
@@ -5255,16 +5586,18 @@ var init_client = __esm({
|
|
|
5255
5586
|
* Connect to the CLI server (via socket or stdio)
|
|
5256
5587
|
*/
|
|
5257
5588
|
async connectToServer() {
|
|
5258
|
-
if (this.options.
|
|
5259
|
-
return this.
|
|
5589
|
+
if (this.options.isChildProcess) {
|
|
5590
|
+
return this.connectToParentProcessViaStdio();
|
|
5591
|
+
} else if (this.options.useStdio) {
|
|
5592
|
+
return this.connectToChildProcessViaStdio();
|
|
5260
5593
|
} else {
|
|
5261
5594
|
return this.connectViaTcp();
|
|
5262
5595
|
}
|
|
5263
5596
|
}
|
|
5264
5597
|
/**
|
|
5265
|
-
* Connect via stdio pipes
|
|
5598
|
+
* Connect to child via stdio pipes
|
|
5266
5599
|
*/
|
|
5267
|
-
async
|
|
5600
|
+
async connectToChildProcessViaStdio() {
|
|
5268
5601
|
if (!this.cliProcess) {
|
|
5269
5602
|
throw new Error("CLI process not started");
|
|
5270
5603
|
}
|
|
@@ -5273,9 +5606,23 @@ var init_client = __esm({
|
|
|
5273
5606
|
throw err;
|
|
5274
5607
|
}
|
|
5275
5608
|
});
|
|
5276
|
-
this.connection = (0,
|
|
5277
|
-
new
|
|
5278
|
-
new
|
|
5609
|
+
this.connection = (0, import_node2.createMessageConnection)(
|
|
5610
|
+
new import_node2.StreamMessageReader(this.cliProcess.stdout),
|
|
5611
|
+
new import_node2.StreamMessageWriter(this.cliProcess.stdin)
|
|
5612
|
+
);
|
|
5613
|
+
this.attachConnectionHandlers();
|
|
5614
|
+
this.connection.listen();
|
|
5615
|
+
}
|
|
5616
|
+
/**
|
|
5617
|
+
* Connect to parent via stdio pipes
|
|
5618
|
+
*/
|
|
5619
|
+
async connectToParentProcessViaStdio() {
|
|
5620
|
+
if (this.cliProcess) {
|
|
5621
|
+
throw new Error("CLI child process was unexpectedly started in parent process mode");
|
|
5622
|
+
}
|
|
5623
|
+
this.connection = (0, import_node2.createMessageConnection)(
|
|
5624
|
+
new import_node2.StreamMessageReader(process.stdin),
|
|
5625
|
+
new import_node2.StreamMessageWriter(process.stdout)
|
|
5279
5626
|
);
|
|
5280
5627
|
this.attachConnectionHandlers();
|
|
5281
5628
|
this.connection.listen();
|
|
@@ -5290,9 +5637,9 @@ var init_client = __esm({
|
|
|
5290
5637
|
return new Promise((resolve3, reject) => {
|
|
5291
5638
|
this.socket = new Socket();
|
|
5292
5639
|
this.socket.connect(this.actualPort, this.actualHost, () => {
|
|
5293
|
-
this.connection = (0,
|
|
5294
|
-
new
|
|
5295
|
-
new
|
|
5640
|
+
this.connection = (0, import_node2.createMessageConnection)(
|
|
5641
|
+
new import_node2.StreamMessageReader(this.socket),
|
|
5642
|
+
new import_node2.StreamMessageWriter(this.socket)
|
|
5296
5643
|
);
|
|
5297
5644
|
this.attachConnectionHandlers();
|
|
5298
5645
|
this.connection.listen();
|
|
@@ -5315,11 +5662,11 @@ var init_client = __esm({
|
|
|
5315
5662
|
});
|
|
5316
5663
|
this.connection.onRequest(
|
|
5317
5664
|
"tool.call",
|
|
5318
|
-
async (params) => await this.
|
|
5665
|
+
async (params) => await this.handleToolCallRequestV2(params)
|
|
5319
5666
|
);
|
|
5320
5667
|
this.connection.onRequest(
|
|
5321
5668
|
"permission.request",
|
|
5322
|
-
async (params) => await this.
|
|
5669
|
+
async (params) => await this.handlePermissionRequestV2(params)
|
|
5323
5670
|
);
|
|
5324
5671
|
this.connection.onRequest(
|
|
5325
5672
|
"userInput.request",
|
|
@@ -5367,7 +5714,41 @@ var init_client = __esm({
|
|
|
5367
5714
|
}
|
|
5368
5715
|
}
|
|
5369
5716
|
}
|
|
5370
|
-
async
|
|
5717
|
+
async handleUserInputRequest(params) {
|
|
5718
|
+
if (!params || typeof params.sessionId !== "string" || typeof params.question !== "string") {
|
|
5719
|
+
throw new Error("Invalid user input request payload");
|
|
5720
|
+
}
|
|
5721
|
+
const session = this.sessions.get(params.sessionId);
|
|
5722
|
+
if (!session) {
|
|
5723
|
+
throw new Error(`Session not found: ${params.sessionId}`);
|
|
5724
|
+
}
|
|
5725
|
+
const result = await session._handleUserInputRequest({
|
|
5726
|
+
question: params.question,
|
|
5727
|
+
choices: params.choices,
|
|
5728
|
+
allowFreeform: params.allowFreeform
|
|
5729
|
+
});
|
|
5730
|
+
return result;
|
|
5731
|
+
}
|
|
5732
|
+
async handleHooksInvoke(params) {
|
|
5733
|
+
if (!params || typeof params.sessionId !== "string" || typeof params.hookType !== "string") {
|
|
5734
|
+
throw new Error("Invalid hooks invoke payload");
|
|
5735
|
+
}
|
|
5736
|
+
const session = this.sessions.get(params.sessionId);
|
|
5737
|
+
if (!session) {
|
|
5738
|
+
throw new Error(`Session not found: ${params.sessionId}`);
|
|
5739
|
+
}
|
|
5740
|
+
const output = await session._handleHooksInvoke(params.hookType, params.input);
|
|
5741
|
+
return { output };
|
|
5742
|
+
}
|
|
5743
|
+
// ========================================================================
|
|
5744
|
+
// Protocol v2 backward-compatibility adapters
|
|
5745
|
+
// ========================================================================
|
|
5746
|
+
/**
|
|
5747
|
+
* Handles a v2-style tool.call RPC request from the server.
|
|
5748
|
+
* Looks up the session and tool handler, executes it, and returns the result
|
|
5749
|
+
* in the v2 response format.
|
|
5750
|
+
*/
|
|
5751
|
+
async handleToolCallRequestV2(params) {
|
|
5371
5752
|
if (!params || typeof params.sessionId !== "string" || typeof params.toolCallId !== "string" || typeof params.toolName !== "string") {
|
|
5372
5753
|
throw new Error("Invalid tool call payload");
|
|
5373
5754
|
}
|
|
@@ -5377,25 +5758,28 @@ var init_client = __esm({
|
|
|
5377
5758
|
}
|
|
5378
5759
|
const handler = session.getToolHandler(params.toolName);
|
|
5379
5760
|
if (!handler) {
|
|
5380
|
-
return {
|
|
5761
|
+
return {
|
|
5762
|
+
result: {
|
|
5763
|
+
textResultForLlm: `Tool '${params.toolName}' is not supported by this client instance.`,
|
|
5764
|
+
resultType: "failure",
|
|
5765
|
+
error: `tool '${params.toolName}' not supported`,
|
|
5766
|
+
toolTelemetry: {}
|
|
5767
|
+
}
|
|
5768
|
+
};
|
|
5381
5769
|
}
|
|
5382
|
-
return await this.executeToolCall(handler, params);
|
|
5383
|
-
}
|
|
5384
|
-
async executeToolCall(handler, request) {
|
|
5385
5770
|
try {
|
|
5386
5771
|
const invocation = {
|
|
5387
|
-
sessionId:
|
|
5388
|
-
toolCallId:
|
|
5389
|
-
toolName:
|
|
5390
|
-
arguments:
|
|
5772
|
+
sessionId: params.sessionId,
|
|
5773
|
+
toolCallId: params.toolCallId,
|
|
5774
|
+
toolName: params.toolName,
|
|
5775
|
+
arguments: params.arguments
|
|
5391
5776
|
};
|
|
5392
|
-
const result = await handler(
|
|
5393
|
-
return { result: this.
|
|
5777
|
+
const result = await handler(params.arguments, invocation);
|
|
5778
|
+
return { result: this.normalizeToolResultV2(result) };
|
|
5394
5779
|
} catch (error) {
|
|
5395
5780
|
const message = error instanceof Error ? error.message : String(error);
|
|
5396
5781
|
return {
|
|
5397
5782
|
result: {
|
|
5398
|
-
// Don't expose detailed error information to the LLM for security reasons
|
|
5399
5783
|
textResultForLlm: "Invoking this tool produced an error. Detailed information is not available.",
|
|
5400
5784
|
resultType: "failure",
|
|
5401
5785
|
error: message,
|
|
@@ -5404,7 +5788,10 @@ var init_client = __esm({
|
|
|
5404
5788
|
};
|
|
5405
5789
|
}
|
|
5406
5790
|
}
|
|
5407
|
-
|
|
5791
|
+
/**
|
|
5792
|
+
* Handles a v2-style permission.request RPC request from the server.
|
|
5793
|
+
*/
|
|
5794
|
+
async handlePermissionRequestV2(params) {
|
|
5408
5795
|
if (!params || typeof params.sessionId !== "string" || !params.permissionRequest) {
|
|
5409
5796
|
throw new Error("Invalid permission request payload");
|
|
5410
5797
|
}
|
|
@@ -5413,7 +5800,7 @@ var init_client = __esm({
|
|
|
5413
5800
|
throw new Error(`Session not found: ${params.sessionId}`);
|
|
5414
5801
|
}
|
|
5415
5802
|
try {
|
|
5416
|
-
const result = await session.
|
|
5803
|
+
const result = await session._handlePermissionRequestV2(params.permissionRequest);
|
|
5417
5804
|
return { result };
|
|
5418
5805
|
} catch (_error) {
|
|
5419
5806
|
return {
|
|
@@ -5423,33 +5810,7 @@ var init_client = __esm({
|
|
|
5423
5810
|
};
|
|
5424
5811
|
}
|
|
5425
5812
|
}
|
|
5426
|
-
|
|
5427
|
-
if (!params || typeof params.sessionId !== "string" || typeof params.question !== "string") {
|
|
5428
|
-
throw new Error("Invalid user input request payload");
|
|
5429
|
-
}
|
|
5430
|
-
const session = this.sessions.get(params.sessionId);
|
|
5431
|
-
if (!session) {
|
|
5432
|
-
throw new Error(`Session not found: ${params.sessionId}`);
|
|
5433
|
-
}
|
|
5434
|
-
const result = await session._handleUserInputRequest({
|
|
5435
|
-
question: params.question,
|
|
5436
|
-
choices: params.choices,
|
|
5437
|
-
allowFreeform: params.allowFreeform
|
|
5438
|
-
});
|
|
5439
|
-
return result;
|
|
5440
|
-
}
|
|
5441
|
-
async handleHooksInvoke(params) {
|
|
5442
|
-
if (!params || typeof params.sessionId !== "string" || typeof params.hookType !== "string") {
|
|
5443
|
-
throw new Error("Invalid hooks invoke payload");
|
|
5444
|
-
}
|
|
5445
|
-
const session = this.sessions.get(params.sessionId);
|
|
5446
|
-
if (!session) {
|
|
5447
|
-
throw new Error(`Session not found: ${params.sessionId}`);
|
|
5448
|
-
}
|
|
5449
|
-
const output = await session._handleHooksInvoke(params.hookType, params.input);
|
|
5450
|
-
return { output };
|
|
5451
|
-
}
|
|
5452
|
-
normalizeToolResult(result) {
|
|
5813
|
+
normalizeToolResultV2(result) {
|
|
5453
5814
|
if (result === void 0 || result === null) {
|
|
5454
5815
|
return {
|
|
5455
5816
|
textResultForLlm: "Tool returned no result",
|
|
@@ -5471,14 +5832,6 @@ var init_client = __esm({
|
|
|
5471
5832
|
isToolResultObject(value) {
|
|
5472
5833
|
return typeof value === "object" && value !== null && "textResultForLlm" in value && typeof value.textResultForLlm === "string" && "resultType" in value;
|
|
5473
5834
|
}
|
|
5474
|
-
buildUnsupportedToolResult(toolName) {
|
|
5475
|
-
return {
|
|
5476
|
-
textResultForLlm: `Tool '${toolName}' is not supported by this client instance.`,
|
|
5477
|
-
resultType: "failure",
|
|
5478
|
-
error: `tool '${toolName}' not supported`,
|
|
5479
|
-
toolTelemetry: {}
|
|
5480
|
-
};
|
|
5481
|
-
}
|
|
5482
5835
|
/**
|
|
5483
5836
|
* Attempt to reconnect to the server
|
|
5484
5837
|
*/
|
|
@@ -5495,9 +5848,11 @@ var init_client = __esm({
|
|
|
5495
5848
|
});
|
|
5496
5849
|
|
|
5497
5850
|
// node_modules/@github/copilot-sdk/dist/types.js
|
|
5851
|
+
var approveAll;
|
|
5498
5852
|
var init_types2 = __esm({
|
|
5499
5853
|
"node_modules/@github/copilot-sdk/dist/types.js"() {
|
|
5500
5854
|
"use strict";
|
|
5855
|
+
approveAll = () => ({ kind: "approved" });
|
|
5501
5856
|
}
|
|
5502
5857
|
});
|
|
5503
5858
|
|
|
@@ -5512,6 +5867,33 @@ var init_dist = __esm({
|
|
|
5512
5867
|
});
|
|
5513
5868
|
|
|
5514
5869
|
// src/L1-infra/ai/copilot.ts
|
|
5870
|
+
import { existsSync as existsSync5 } from "fs";
|
|
5871
|
+
import { join as join6, dirname as dirname4 } from "path";
|
|
5872
|
+
import { createRequire as createRequire2 } from "module";
|
|
5873
|
+
function resolveCopilotCliPath() {
|
|
5874
|
+
const platform = process.platform;
|
|
5875
|
+
const arch = process.arch;
|
|
5876
|
+
const binaryName = platform === "win32" ? "copilot.exe" : "copilot";
|
|
5877
|
+
const platformPkg = `@github/copilot-${platform}-${arch}`;
|
|
5878
|
+
try {
|
|
5879
|
+
const require_ = createRequire2(import.meta.url);
|
|
5880
|
+
const searchPaths = require_.resolve.paths(platformPkg) ?? [];
|
|
5881
|
+
for (const base of searchPaths) {
|
|
5882
|
+
const candidate = join6(base, platformPkg, binaryName);
|
|
5883
|
+
if (existsSync5(candidate)) return candidate;
|
|
5884
|
+
}
|
|
5885
|
+
} catch {
|
|
5886
|
+
}
|
|
5887
|
+
let dir = dirname4(import.meta.dirname ?? __dirname);
|
|
5888
|
+
for (let i = 0; i < 10; i++) {
|
|
5889
|
+
const candidate = join6(dir, "node_modules", platformPkg, binaryName);
|
|
5890
|
+
if (existsSync5(candidate)) return candidate;
|
|
5891
|
+
const parent = dirname4(dir);
|
|
5892
|
+
if (parent === dir) break;
|
|
5893
|
+
dir = parent;
|
|
5894
|
+
}
|
|
5895
|
+
return void 0;
|
|
5896
|
+
}
|
|
5515
5897
|
var init_copilot = __esm({
|
|
5516
5898
|
"src/L1-infra/ai/copilot.ts"() {
|
|
5517
5899
|
"use strict";
|
|
@@ -5539,14 +5921,25 @@ var init_ai = __esm({
|
|
|
5539
5921
|
});
|
|
5540
5922
|
|
|
5541
5923
|
// src/L2-clients/llm/CopilotProvider.ts
|
|
5542
|
-
|
|
5924
|
+
function buildChildEnv() {
|
|
5925
|
+
const env = { ...process.env };
|
|
5926
|
+
const flag = "--disable-warning=ExperimentalWarning";
|
|
5927
|
+
const current = env.NODE_OPTIONS ?? "";
|
|
5928
|
+
if (!current.includes(flag)) {
|
|
5929
|
+
env.NODE_OPTIONS = current ? `${current} ${flag}` : flag;
|
|
5930
|
+
}
|
|
5931
|
+
return env;
|
|
5932
|
+
}
|
|
5933
|
+
var DEFAULT_MODEL, DEFAULT_TIMEOUT_MS, SESSION_CREATE_TIMEOUT_MS, CopilotProvider, CopilotSessionWrapper;
|
|
5543
5934
|
var init_CopilotProvider = __esm({
|
|
5544
5935
|
"src/L2-clients/llm/CopilotProvider.ts"() {
|
|
5545
5936
|
"use strict";
|
|
5546
5937
|
init_ai();
|
|
5938
|
+
init_copilot();
|
|
5547
5939
|
init_configLogger();
|
|
5548
5940
|
DEFAULT_MODEL = "claude-opus-4.5";
|
|
5549
5941
|
DEFAULT_TIMEOUT_MS = 3e5;
|
|
5942
|
+
SESSION_CREATE_TIMEOUT_MS = 3e4;
|
|
5550
5943
|
CopilotProvider = class {
|
|
5551
5944
|
name = "copilot";
|
|
5552
5945
|
client = null;
|
|
@@ -5558,21 +5951,57 @@ var init_CopilotProvider = __esm({
|
|
|
5558
5951
|
}
|
|
5559
5952
|
async createSession(config2) {
|
|
5560
5953
|
if (!this.client) {
|
|
5561
|
-
|
|
5954
|
+
const cliPath = resolveCopilotCliPath();
|
|
5955
|
+
if (cliPath) {
|
|
5956
|
+
logger_default.info(`[CopilotProvider] Using native CLI binary: ${cliPath}`);
|
|
5957
|
+
}
|
|
5958
|
+
this.client = createCopilotClient({
|
|
5959
|
+
autoStart: true,
|
|
5960
|
+
autoRestart: true,
|
|
5961
|
+
logLevel: "error",
|
|
5962
|
+
env: buildChildEnv(),
|
|
5963
|
+
...cliPath ? { cliPath } : {}
|
|
5964
|
+
});
|
|
5562
5965
|
}
|
|
5563
|
-
|
|
5564
|
-
|
|
5565
|
-
|
|
5566
|
-
|
|
5567
|
-
|
|
5568
|
-
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
5572
|
-
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
|
|
5966
|
+
logger_default.info("[CopilotProvider] Creating session\u2026");
|
|
5967
|
+
let copilotSession;
|
|
5968
|
+
try {
|
|
5969
|
+
copilotSession = await new Promise((resolve3, reject) => {
|
|
5970
|
+
const timeoutId = setTimeout(
|
|
5971
|
+
() => reject(new Error(
|
|
5972
|
+
`[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.`
|
|
5973
|
+
)),
|
|
5974
|
+
SESSION_CREATE_TIMEOUT_MS
|
|
5975
|
+
);
|
|
5976
|
+
this.client.createSession({
|
|
5977
|
+
model: config2.model,
|
|
5978
|
+
mcpServers: config2.mcpServers,
|
|
5979
|
+
systemMessage: { mode: "replace", content: config2.systemPrompt },
|
|
5980
|
+
tools: config2.tools.map((t) => ({
|
|
5981
|
+
name: t.name,
|
|
5982
|
+
description: t.description,
|
|
5983
|
+
parameters: t.parameters,
|
|
5984
|
+
handler: t.handler
|
|
5985
|
+
})),
|
|
5986
|
+
streaming: config2.streaming ?? true,
|
|
5987
|
+
onPermissionRequest: approveAll,
|
|
5988
|
+
onUserInputRequest: config2.onUserInputRequest ? (request) => config2.onUserInputRequest(request) : void 0
|
|
5989
|
+
}).then(
|
|
5990
|
+
(session) => {
|
|
5991
|
+
clearTimeout(timeoutId);
|
|
5992
|
+
resolve3(session);
|
|
5993
|
+
},
|
|
5994
|
+
(err) => {
|
|
5995
|
+
clearTimeout(timeoutId);
|
|
5996
|
+
reject(err);
|
|
5997
|
+
}
|
|
5998
|
+
);
|
|
5999
|
+
});
|
|
6000
|
+
} catch (err) {
|
|
6001
|
+
this.client = null;
|
|
6002
|
+
throw err;
|
|
6003
|
+
}
|
|
6004
|
+
logger_default.info("[CopilotProvider] Session created successfully");
|
|
5576
6005
|
return new CopilotSessionWrapper(
|
|
5577
6006
|
copilotSession,
|
|
5578
6007
|
config2.timeoutMs ?? DEFAULT_TIMEOUT_MS
|
|
@@ -5928,7 +6357,8 @@ var init_OpenAIProvider = __esm({
|
|
|
5928
6357
|
return "gpt-4o";
|
|
5929
6358
|
}
|
|
5930
6359
|
async createSession(config2) {
|
|
5931
|
-
const
|
|
6360
|
+
const appConfig = getConfig();
|
|
6361
|
+
const client = createOpenAI({ apiKey: appConfig.OPENAI_API_KEY });
|
|
5932
6362
|
const model = config2.model ?? this.getDefaultModel();
|
|
5933
6363
|
logger_default.info(`OpenAI session created (model=${model}, tools=${config2.tools.length})`);
|
|
5934
6364
|
return new OpenAISession(client, config2, model);
|
|
@@ -6192,12 +6622,13 @@ var init_providerFactory = __esm({
|
|
|
6192
6622
|
|
|
6193
6623
|
// src/L1-infra/config/modelConfig.ts
|
|
6194
6624
|
function getModelForAgent(agentName) {
|
|
6625
|
+
const config2 = getConfig();
|
|
6195
6626
|
const envKey = `MODEL_${agentName.replace(/([a-z])([A-Z])/g, "$1_$2").toUpperCase()}`;
|
|
6196
|
-
const envOverride =
|
|
6627
|
+
const envOverride = config2.MODEL_OVERRIDES[envKey];
|
|
6197
6628
|
if (envOverride) return envOverride;
|
|
6198
6629
|
const mapped = AGENT_MODEL_MAP[agentName];
|
|
6199
6630
|
if (mapped) return mapped;
|
|
6200
|
-
const global =
|
|
6631
|
+
const global = config2.LLM_MODEL;
|
|
6201
6632
|
if (global) return global;
|
|
6202
6633
|
return void 0;
|
|
6203
6634
|
}
|
|
@@ -7330,6 +7761,7 @@ init_environment();
|
|
|
7330
7761
|
// src/L1-infra/progress/progressEmitter.ts
|
|
7331
7762
|
var ProgressEmitter = class {
|
|
7332
7763
|
enabled = false;
|
|
7764
|
+
listeners = /* @__PURE__ */ new Set();
|
|
7333
7765
|
/** Turn on progress event output to stderr. */
|
|
7334
7766
|
enable() {
|
|
7335
7767
|
this.enabled = true;
|
|
@@ -7338,17 +7770,31 @@ var ProgressEmitter = class {
|
|
|
7338
7770
|
disable() {
|
|
7339
7771
|
this.enabled = false;
|
|
7340
7772
|
}
|
|
7341
|
-
/** Whether the emitter is currently active. */
|
|
7773
|
+
/** Whether the emitter is currently active (stderr or listeners). */
|
|
7342
7774
|
isEnabled() {
|
|
7343
|
-
return this.enabled;
|
|
7775
|
+
return this.enabled || this.listeners.size > 0;
|
|
7776
|
+
}
|
|
7777
|
+
/** Register a programmatic listener for progress events. */
|
|
7778
|
+
addListener(fn) {
|
|
7779
|
+
this.listeners.add(fn);
|
|
7780
|
+
}
|
|
7781
|
+
/** Remove a previously registered listener. */
|
|
7782
|
+
removeListener(fn) {
|
|
7783
|
+
this.listeners.delete(fn);
|
|
7344
7784
|
}
|
|
7345
7785
|
/**
|
|
7346
|
-
* Write a progress event as a single JSON line to stderr
|
|
7347
|
-
*
|
|
7786
|
+
* Write a progress event as a single JSON line to stderr (if enabled)
|
|
7787
|
+
* and dispatch to all registered listeners.
|
|
7788
|
+
* No-op when neither stderr output nor listeners are active.
|
|
7348
7789
|
*/
|
|
7349
7790
|
emit(event) {
|
|
7350
|
-
if (!this.enabled) return;
|
|
7351
|
-
|
|
7791
|
+
if (!this.enabled && this.listeners.size === 0) return;
|
|
7792
|
+
if (this.enabled) {
|
|
7793
|
+
process.stderr.write(JSON.stringify(event) + "\n");
|
|
7794
|
+
}
|
|
7795
|
+
for (const listener of this.listeners) {
|
|
7796
|
+
listener(event);
|
|
7797
|
+
}
|
|
7352
7798
|
}
|
|
7353
7799
|
};
|
|
7354
7800
|
var progressEmitter = new ProgressEmitter();
|
|
@@ -7446,9 +7892,6 @@ function execFileRaw(cmd, args, opts, callback) {
|
|
|
7446
7892
|
callback(error, String(stdout ?? ""), String(stderr ?? ""));
|
|
7447
7893
|
});
|
|
7448
7894
|
}
|
|
7449
|
-
function execCommandSync(cmd, opts) {
|
|
7450
|
-
return nodeExecSync(cmd, { encoding: "utf-8", ...opts }).toString().trim();
|
|
7451
|
-
}
|
|
7452
7895
|
function spawnCommand(cmd, args, opts) {
|
|
7453
7896
|
return nodeSpawnSync(cmd, args, { encoding: "utf-8", ...opts });
|
|
7454
7897
|
}
|
|
@@ -8672,6 +9115,8 @@ function transcodeToMp4(inputPath, outputPath) {
|
|
|
8672
9115
|
createFFmpeg(inputPath).outputOptions([
|
|
8673
9116
|
"-c:v",
|
|
8674
9117
|
"libx264",
|
|
9118
|
+
"-pix_fmt",
|
|
9119
|
+
"yuv420p",
|
|
8675
9120
|
"-preset",
|
|
8676
9121
|
"ultrafast",
|
|
8677
9122
|
"-crf",
|
|
@@ -10468,6 +10913,7 @@ var BaseAgent = class _BaseAgent {
|
|
|
10468
10913
|
for (let attempt = 1; attempt <= _BaseAgent.MAX_RETRIES; attempt++) {
|
|
10469
10914
|
try {
|
|
10470
10915
|
if (!this.session) {
|
|
10916
|
+
logger_default.info(`[${this.agentName}] Creating LLM session (provider=${this.provider.name})\u2026`);
|
|
10471
10917
|
this.session = await this.provider.createSession({
|
|
10472
10918
|
systemPrompt: this.systemPrompt,
|
|
10473
10919
|
tools: this.getTools(),
|
|
@@ -10478,6 +10924,7 @@ var BaseAgent = class _BaseAgent {
|
|
|
10478
10924
|
onUserInputRequest: this.getUserInputHandler()
|
|
10479
10925
|
});
|
|
10480
10926
|
this.setupEventHandlers(this.session);
|
|
10927
|
+
logger_default.info(`[${this.agentName}] LLM session ready`);
|
|
10481
10928
|
}
|
|
10482
10929
|
logger_default.info(`[${this.agentName}] Sending message (attempt ${attempt}/${_BaseAgent.MAX_RETRIES}): ${userMessage.substring(0, 80)}\u2026`);
|
|
10483
10930
|
costTracker.setAgent(this.agentName);
|
|
@@ -10515,11 +10962,12 @@ var BaseAgent = class _BaseAgent {
|
|
|
10515
10962
|
}
|
|
10516
10963
|
/** Check if an error message indicates a transient/retryable failure. */
|
|
10517
10964
|
static isRetryableError(message) {
|
|
10518
|
-
const
|
|
10965
|
+
const lower = message.toLowerCase();
|
|
10966
|
+
return [
|
|
10519
10967
|
"missing finish_reason",
|
|
10520
|
-
"
|
|
10521
|
-
"
|
|
10522
|
-
"
|
|
10968
|
+
"econnreset",
|
|
10969
|
+
"etimedout",
|
|
10970
|
+
"econnrefused",
|
|
10523
10971
|
"socket hang up",
|
|
10524
10972
|
"network error",
|
|
10525
10973
|
"rate limit",
|
|
@@ -10529,10 +10977,9 @@ var BaseAgent = class _BaseAgent {
|
|
|
10529
10977
|
"503",
|
|
10530
10978
|
"504",
|
|
10531
10979
|
"stream ended",
|
|
10532
|
-
"aborted"
|
|
10533
|
-
|
|
10534
|
-
|
|
10535
|
-
return retryablePatterns.some((p) => lower.includes(p.toLowerCase()));
|
|
10980
|
+
"aborted",
|
|
10981
|
+
"cli server exited"
|
|
10982
|
+
].some((p) => lower.includes(p));
|
|
10536
10983
|
}
|
|
10537
10984
|
/** Wire up session event listeners for logging. Override for custom display. */
|
|
10538
10985
|
setupEventHandlers(session) {
|
|
@@ -13000,32 +13447,6 @@ async function markFailed(slug, error) {
|
|
|
13000
13447
|
logger_default.info(`[ProcessingState] Marked failed: ${slug} \u2014 ${error}`);
|
|
13001
13448
|
}
|
|
13002
13449
|
|
|
13003
|
-
// src/L3-services/gitOperations/gitOperations.ts
|
|
13004
|
-
init_environment();
|
|
13005
|
-
init_configLogger();
|
|
13006
|
-
async function commitAndPush(videoSlug, message) {
|
|
13007
|
-
const { REPO_ROOT } = getConfig();
|
|
13008
|
-
const commitMessage = message || `Auto-processed video: ${videoSlug}`;
|
|
13009
|
-
try {
|
|
13010
|
-
logger_default.info(`Staging all changes in ${REPO_ROOT}`);
|
|
13011
|
-
execCommandSync("git add -A", { cwd: REPO_ROOT, stdio: "pipe" });
|
|
13012
|
-
logger_default.info(`Committing: ${commitMessage}`);
|
|
13013
|
-
execCommandSync(`git commit -m "${commitMessage}"`, { cwd: REPO_ROOT, stdio: "pipe" });
|
|
13014
|
-
const branch = execCommandSync("git rev-parse --abbrev-ref HEAD", { cwd: REPO_ROOT, stdio: "pipe" });
|
|
13015
|
-
logger_default.info(`Pushing to origin ${branch}`);
|
|
13016
|
-
execCommandSync(`git push origin ${branch}`, { cwd: REPO_ROOT, stdio: "pipe" });
|
|
13017
|
-
logger_default.info("Git commit and push completed successfully");
|
|
13018
|
-
} catch (error) {
|
|
13019
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
13020
|
-
if (msg.includes("nothing to commit")) {
|
|
13021
|
-
logger_default.info("Nothing to commit, working tree clean");
|
|
13022
|
-
return;
|
|
13023
|
-
}
|
|
13024
|
-
logger_default.error(`Git operation failed: ${msg}`);
|
|
13025
|
-
throw error;
|
|
13026
|
-
}
|
|
13027
|
-
}
|
|
13028
|
-
|
|
13029
13450
|
// src/L3-services/queueBuilder/queueBuilder.ts
|
|
13030
13451
|
init_fileSystem();
|
|
13031
13452
|
init_paths();
|
|
@@ -13643,9 +14064,6 @@ function markCompleted2(...args) {
|
|
|
13643
14064
|
function markFailed2(...args) {
|
|
13644
14065
|
return markFailed(...args);
|
|
13645
14066
|
}
|
|
13646
|
-
function commitAndPush2(...args) {
|
|
13647
|
-
return commitAndPush(...args);
|
|
13648
|
-
}
|
|
13649
14067
|
function buildPublishQueue2(...args) {
|
|
13650
14068
|
return buildPublishQueue(...args);
|
|
13651
14069
|
}
|
|
@@ -14793,12 +15211,6 @@ var MainVideoAsset = class _MainVideoAsset extends VideoAsset {
|
|
|
14793
15211
|
async buildQueue(shorts, mediumClips, socialPosts, captionedVideoPath) {
|
|
14794
15212
|
await this.buildPublishQueueData(shorts, mediumClips, socialPosts, captionedVideoPath);
|
|
14795
15213
|
}
|
|
14796
|
-
/**
|
|
14797
|
-
* Commit and push all generated assets via git.
|
|
14798
|
-
*/
|
|
14799
|
-
async commitAndPushChanges(message) {
|
|
14800
|
-
return commitAndPush2(this.slug, message);
|
|
14801
|
-
}
|
|
14802
15214
|
};
|
|
14803
15215
|
|
|
14804
15216
|
// src/L2-clients/late/lateApi.ts
|
|
@@ -17480,11 +17892,6 @@ async function processVideo(videoPath, ideas) {
|
|
|
17480
17892
|
skipStage("queue-build" /* QueueBuild */, "NO_SOCIAL_POSTS");
|
|
17481
17893
|
}
|
|
17482
17894
|
const blogPost = await trackStage("blog" /* Blog */, () => asset.getBlog());
|
|
17483
|
-
if (!cfg.SKIP_GIT) {
|
|
17484
|
-
await trackStage("git-push" /* GitPush */, () => asset.commitAndPushChanges());
|
|
17485
|
-
} else {
|
|
17486
|
-
skipStage("git-push" /* GitPush */, "SKIP_GIT");
|
|
17487
|
-
}
|
|
17488
17895
|
const totalDuration = Date.now() - pipelineStart;
|
|
17489
17896
|
const report = costTracker3.getReport();
|
|
17490
17897
|
if (report.records.length > 0) {
|
|
@@ -17866,6 +18273,7 @@ async function checkScheduleConfig() {
|
|
|
17866
18273
|
// src/L7-app/commands/init.ts
|
|
17867
18274
|
init_fileSystem();
|
|
17868
18275
|
init_paths();
|
|
18276
|
+
init_environment();
|
|
17869
18277
|
|
|
17870
18278
|
// src/L3-services/diagnostics/diagnostics.ts
|
|
17871
18279
|
function getFFmpegPath3(...args) {
|
|
@@ -17915,7 +18323,7 @@ async function runInit() {
|
|
|
17915
18323
|
console.log(" \u274C FFprobe not found");
|
|
17916
18324
|
}
|
|
17917
18325
|
console.log("\nStep 2/5: OpenAI (Required for transcription)");
|
|
17918
|
-
const currentOpenAI = existingVars.OPENAI_API_KEY ||
|
|
18326
|
+
const currentOpenAI = existingVars.OPENAI_API_KEY || getConfig().OPENAI_API_KEY;
|
|
17919
18327
|
const hint = currentOpenAI ? ` (current: ${currentOpenAI.slice(0, 8)}...)` : "";
|
|
17920
18328
|
const openaiKey = await ask(` ? OpenAI API key${hint}: `);
|
|
17921
18329
|
if (openaiKey.trim()) {
|
|
@@ -19281,7 +19689,7 @@ function createRouter() {
|
|
|
19281
19689
|
// src/L7-app/review/server.ts
|
|
19282
19690
|
init_environment();
|
|
19283
19691
|
init_configLogger();
|
|
19284
|
-
var
|
|
19692
|
+
var __dirname3 = dirname(fileURLToPath(import.meta.url));
|
|
19285
19693
|
async function startReviewServer(options = {}) {
|
|
19286
19694
|
const app = default8();
|
|
19287
19695
|
const port = options.port || 3847;
|
|
@@ -19292,7 +19700,7 @@ async function startReviewServer(options = {}) {
|
|
|
19292
19700
|
const publishedDir = join(cfg.OUTPUT_DIR, "published");
|
|
19293
19701
|
app.use("/media/queue", default8.static(queueDir));
|
|
19294
19702
|
app.use("/media/published", default8.static(publishedDir));
|
|
19295
|
-
const publicDir = join(
|
|
19703
|
+
const publicDir = join(__dirname3, "public");
|
|
19296
19704
|
app.use(default8.static(publicDir));
|
|
19297
19705
|
app.get("/{*splat}", (req, res) => {
|
|
19298
19706
|
if (!req.path.startsWith("/api/") && !req.path.startsWith("/media/")) {
|
|
@@ -19412,7 +19820,7 @@ program.command("configure [subcommand]").description("Manage global configurati
|
|
|
19412
19820
|
await runConfigure(subcommand, args);
|
|
19413
19821
|
process.exit(process.exitCode ?? 0);
|
|
19414
19822
|
});
|
|
19415
|
-
var defaultCmd = program.command("process", { isDefault: true }).argument("[video-path]", "Path to a video file to process (implies --once)").option("--watch-dir <path>", "Folder to watch for new recordings (default: env WATCH_FOLDER)").option("--output-dir <path>", "Output directory for processed videos (default: ./recordings)").option("--openai-key <key>", "OpenAI API key (default: env OPENAI_API_KEY)").option("--exa-key <key>", "Exa AI API key for web search (default: env EXA_API_KEY)").option("--youtube-key <key>", "YouTube API key (default: env YOUTUBE_API_KEY)").option("--perplexity-key <key>", "Perplexity API key (default: env PERPLEXITY_API_KEY)").option("--once", "Process a single video and exit (no watching)").option("--brand <path>", "Path to brand.json config (default: ./brand.json)").option("--no-
|
|
19823
|
+
var defaultCmd = program.command("process", { isDefault: true }).argument("[video-path]", "Path to a video file to process (implies --once)").option("--watch-dir <path>", "Folder to watch for new recordings (default: env WATCH_FOLDER)").option("--output-dir <path>", "Output directory for processed videos (default: ./recordings)").option("--openai-key <key>", "OpenAI API key (default: env OPENAI_API_KEY)").option("--exa-key <key>", "Exa AI API key for web search (default: env EXA_API_KEY)").option("--youtube-key <key>", "YouTube API key (default: env YOUTUBE_API_KEY)").option("--perplexity-key <key>", "Perplexity API key (default: env PERPLEXITY_API_KEY)").option("--once", "Process a single video and exit (no watching)").option("--brand <path>", "Path to brand.json config (default: ./brand.json)").option("--no-silence-removal", "Skip silence removal stage").option("--no-shorts", "Skip shorts generation").option("--no-medium-clips", "Skip medium clip generation").option("--no-social", "Skip social media post generation").option("--no-captions", "Skip caption generation/burning").option("--no-visual-enhancement", "Skip visual enhancement (AI image overlays)").option("--no-social-publish", "Skip social media publishing/queue-build stage").option("--late-api-key <key>", "Late API key (default: env LATE_API_KEY)").option("--late-profile-id <id>", "Late profile ID (default: env LATE_PROFILE_ID)").option("--ideas <ids>", "Comma-separated idea IDs to link to this video").option("-v, --verbose", "Verbose logging").option("--progress", "Emit structured JSON progress events to stderr").option("--doctor", "Check all prerequisites and exit").action(async (videoPath) => {
|
|
19416
19824
|
const opts = defaultCmd.opts();
|
|
19417
19825
|
if (opts.doctor) {
|
|
19418
19826
|
await runDoctor();
|
|
@@ -19428,7 +19836,6 @@ var defaultCmd = program.command("process", { isDefault: true }).argument("[vide
|
|
|
19428
19836
|
perplexityKey: opts.perplexityKey,
|
|
19429
19837
|
brand: opts.brand,
|
|
19430
19838
|
verbose: opts.verbose,
|
|
19431
|
-
git: opts.git,
|
|
19432
19839
|
silenceRemoval: opts.silenceRemoval,
|
|
19433
19840
|
shorts: opts.shorts,
|
|
19434
19841
|
mediumClips: opts.mediumClips,
|