@autohq/cli 0.1.89 → 0.1.90

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
@@ -257,10 +257,10 @@ function mergeDefs(...defs) {
257
257
  function cloneDef(schema) {
258
258
  return mergeDefs(schema._zod.def);
259
259
  }
260
- function getElementAtPath(obj, path) {
261
- if (!path)
260
+ function getElementAtPath(obj, path2) {
261
+ if (!path2)
262
262
  return obj;
263
- return path.reduce((acc, key) => acc?.[key], obj);
263
+ return path2.reduce((acc, key) => acc?.[key], obj);
264
264
  }
265
265
  function promiseAllObject(promisesObj) {
266
266
  const keys = Object.keys(promisesObj);
@@ -588,11 +588,11 @@ function explicitlyAborted(x, startIndex = 0) {
588
588
  }
589
589
  return false;
590
590
  }
591
- function prefixIssues(path, issues) {
591
+ function prefixIssues(path2, issues) {
592
592
  return issues.map((iss) => {
593
593
  var _a3;
594
594
  (_a3 = iss).path ?? (_a3.path = []);
595
- iss.path.unshift(path);
595
+ iss.path.unshift(path2);
596
596
  return iss;
597
597
  });
598
598
  }
@@ -810,16 +810,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
810
810
  }
811
811
  function formatError(error51, mapper = (issue2) => issue2.message) {
812
812
  const fieldErrors = { _errors: [] };
813
- const processError = (error52, path = []) => {
813
+ const processError = (error52, path2 = []) => {
814
814
  for (const issue2 of error52.issues) {
815
815
  if (issue2.code === "invalid_union" && issue2.errors.length) {
816
- issue2.errors.map((issues) => processError({ issues }, [...path, ...issue2.path]));
816
+ issue2.errors.map((issues) => processError({ issues }, [...path2, ...issue2.path]));
817
817
  } else if (issue2.code === "invalid_key") {
818
- processError({ issues: issue2.issues }, [...path, ...issue2.path]);
818
+ processError({ issues: issue2.issues }, [...path2, ...issue2.path]);
819
819
  } else if (issue2.code === "invalid_element") {
820
- processError({ issues: issue2.issues }, [...path, ...issue2.path]);
820
+ processError({ issues: issue2.issues }, [...path2, ...issue2.path]);
821
821
  } else {
822
- const fullpath = [...path, ...issue2.path];
822
+ const fullpath = [...path2, ...issue2.path];
823
823
  if (fullpath.length === 0) {
824
824
  fieldErrors._errors.push(mapper(issue2));
825
825
  } else {
@@ -846,17 +846,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
846
846
  }
847
847
  function treeifyError(error51, mapper = (issue2) => issue2.message) {
848
848
  const result = { errors: [] };
849
- const processError = (error52, path = []) => {
849
+ const processError = (error52, path2 = []) => {
850
850
  var _a3, _b;
851
851
  for (const issue2 of error52.issues) {
852
852
  if (issue2.code === "invalid_union" && issue2.errors.length) {
853
- issue2.errors.map((issues) => processError({ issues }, [...path, ...issue2.path]));
853
+ issue2.errors.map((issues) => processError({ issues }, [...path2, ...issue2.path]));
854
854
  } else if (issue2.code === "invalid_key") {
855
- processError({ issues: issue2.issues }, [...path, ...issue2.path]);
855
+ processError({ issues: issue2.issues }, [...path2, ...issue2.path]);
856
856
  } else if (issue2.code === "invalid_element") {
857
- processError({ issues: issue2.issues }, [...path, ...issue2.path]);
857
+ processError({ issues: issue2.issues }, [...path2, ...issue2.path]);
858
858
  } else {
859
- const fullpath = [...path, ...issue2.path];
859
+ const fullpath = [...path2, ...issue2.path];
860
860
  if (fullpath.length === 0) {
861
861
  result.errors.push(mapper(issue2));
862
862
  continue;
@@ -888,8 +888,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
888
888
  }
889
889
  function toDotPath(_path) {
890
890
  const segs = [];
891
- const path = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
892
- for (const seg of path) {
891
+ const path2 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
892
+ for (const seg of path2) {
893
893
  if (typeof seg === "number")
894
894
  segs.push(`[${seg}]`);
895
895
  else if (typeof seg === "symbol")
@@ -14392,13 +14392,13 @@ function resolveRef(ref, ctx) {
14392
14392
  if (!ref.startsWith("#")) {
14393
14393
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
14394
14394
  }
14395
- const path = ref.slice(1).split("/").filter(Boolean);
14396
- if (path.length === 0) {
14395
+ const path2 = ref.slice(1).split("/").filter(Boolean);
14396
+ if (path2.length === 0) {
14397
14397
  return ctx.rootSchema;
14398
14398
  }
14399
14399
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
14400
- if (path[0] === defsKey) {
14401
- const key = path[1];
14400
+ if (path2[0] === defsKey) {
14401
+ const key = path2[1];
14402
14402
  if (!key || !ctx.defs[key]) {
14403
14403
  throw new Error(`Reference not found: ${ref}`);
14404
14404
  }
@@ -15223,6 +15223,8 @@ var init_auth = __esm({
15223
15223
  "secrets:read",
15224
15224
  "secrets:write",
15225
15225
  "secrets:use",
15226
+ "github:mcp",
15227
+ "github:credentials",
15226
15228
  "projects:admin",
15227
15229
  "org:admin"
15228
15230
  ]);
@@ -16413,6 +16415,100 @@ var init_connections = __esm({
16413
16415
  }
16414
16416
  });
16415
16417
 
16418
+ // ../../packages/schemas/src/github-credentials.ts
16419
+ var CreateRunGithubCredentialRequestSchema, RunGithubCredentialResponseSchema;
16420
+ var init_github_credentials = __esm({
16421
+ "../../packages/schemas/src/github-credentials.ts"() {
16422
+ "use strict";
16423
+ init_zod();
16424
+ CreateRunGithubCredentialRequestSchema = external_exports.object({
16425
+ host: external_exports.literal("github.com"),
16426
+ path: external_exports.string().trim().min(1).optional()
16427
+ });
16428
+ RunGithubCredentialResponseSchema = external_exports.object({
16429
+ username: external_exports.literal("x-access-token"),
16430
+ password: external_exports.string().min(1),
16431
+ expiresAt: external_exports.string().datetime()
16432
+ });
16433
+ }
16434
+ });
16435
+
16436
+ // ../../packages/schemas/src/github-mcp-catalog.ts
16437
+ var GITHUB_MCP_TOOL_NAMES, GITHUB_MCP_WRITE_TOOLS, githubMcpToolNameSet, githubMcpWriteToolSet;
16438
+ var init_github_mcp_catalog = __esm({
16439
+ "../../packages/schemas/src/github-mcp-catalog.ts"() {
16440
+ "use strict";
16441
+ GITHUB_MCP_TOOL_NAMES = [
16442
+ "actions_get",
16443
+ "actions_list",
16444
+ "actions_run_trigger",
16445
+ "add_comment_to_pending_review",
16446
+ "add_issue_comment",
16447
+ "add_reply_to_pull_request_comment",
16448
+ "create_branch",
16449
+ "create_or_update_file",
16450
+ "create_pull_request",
16451
+ "create_repository",
16452
+ "delete_file",
16453
+ "fork_repository",
16454
+ "get_commit",
16455
+ "get_file_contents",
16456
+ "get_job_logs",
16457
+ "get_label",
16458
+ "get_latest_release",
16459
+ "get_release_by_tag",
16460
+ "get_tag",
16461
+ "issue_read",
16462
+ "issue_write",
16463
+ "list_branches",
16464
+ "list_commits",
16465
+ "list_issue_types",
16466
+ "list_issues",
16467
+ "list_pull_requests",
16468
+ "list_releases",
16469
+ "list_repository_collaborators",
16470
+ "list_tags",
16471
+ "merge_pull_request",
16472
+ "pull_request_read",
16473
+ "pull_request_review_write",
16474
+ "push_files",
16475
+ "search_code",
16476
+ "search_commits",
16477
+ "search_issues",
16478
+ "search_pull_requests",
16479
+ "search_repositories",
16480
+ "sub_issue_write",
16481
+ "update_pull_request",
16482
+ "update_pull_request_branch"
16483
+ ];
16484
+ GITHUB_MCP_WRITE_TOOLS = [
16485
+ "actions_run_trigger",
16486
+ "add_comment_to_pending_review",
16487
+ "add_issue_comment",
16488
+ "add_reply_to_pull_request_comment",
16489
+ "create_branch",
16490
+ "create_or_update_file",
16491
+ "create_pull_request",
16492
+ "create_repository",
16493
+ "delete_file",
16494
+ "fork_repository",
16495
+ "issue_write",
16496
+ "merge_pull_request",
16497
+ "pull_request_review_write",
16498
+ "push_files",
16499
+ "sub_issue_write",
16500
+ "update_pull_request",
16501
+ "update_pull_request_branch"
16502
+ ];
16503
+ githubMcpToolNameSet = new Set(
16504
+ GITHUB_MCP_TOOL_NAMES
16505
+ );
16506
+ githubMcpWriteToolSet = new Set(
16507
+ GITHUB_MCP_WRITE_TOOLS
16508
+ );
16509
+ }
16510
+ });
16511
+
16416
16512
  // ../../packages/schemas/src/secrets.ts
16417
16513
  var SECRET_ENCRYPTION_ALGORITHM, SecretEnvNameSchema, SecretCiphertextFieldSchema, SecretAesGcmIvSchema, SecretAesGcmAuthTagSchema, SecretEnvValueSchema, SecretEnvSchema, EncryptedSecretValueSchema, SecretSetRequestSchema, SecretMetadataSchema, SecretSetResponseSchema, SecretListResponseSchema, SecretDeleteResponseSchema;
16418
16514
  var init_secrets = __esm({
@@ -16600,7 +16696,7 @@ var init_mcp = __esm({
16600
16696
  });
16601
16697
 
16602
16698
  // ../../packages/schemas/src/mounts.ts
16603
- var AbsoluteMountPathSchema, GITHUB_MOUNT_CAPABILITY_LEVELS, GithubMountCapabilityLevelSchema, GitMountAuthSchema, GitMountSchema, SessionMountSchema;
16699
+ var AbsoluteMountPathSchema, GITHUB_MOUNT_CAPABILITY_LEVELS, GithubMountCapabilityLevelSchema, DEFAULT_GITHUB_MOUNT_CAPABILITIES, GitMountAuthSchema, GitMountSchema, SessionMountSchema;
16604
16700
  var init_mounts = __esm({
16605
16701
  "../../packages/schemas/src/mounts.ts"() {
16606
16702
  "use strict";
@@ -16616,6 +16712,14 @@ var init_mounts = __esm({
16616
16712
  GithubMountCapabilityLevelSchema = external_exports.enum(
16617
16713
  GITHUB_MOUNT_CAPABILITY_LEVELS
16618
16714
  );
16715
+ DEFAULT_GITHUB_MOUNT_CAPABILITIES = {
16716
+ contents: "write",
16717
+ pullRequests: "write",
16718
+ issues: "write",
16719
+ checks: "read",
16720
+ actions: "read",
16721
+ workflows: "none"
16722
+ };
16619
16723
  GitMountAuthSchema = external_exports.discriminatedUnion("kind", [
16620
16724
  external_exports.object({
16621
16725
  kind: external_exports.literal("none")
@@ -16636,14 +16740,7 @@ var init_mounts = __esm({
16636
16740
  checks: GithubMountCapabilityLevelSchema.default("read"),
16637
16741
  actions: GithubMountCapabilityLevelSchema.default("read"),
16638
16742
  workflows: GithubMountCapabilityLevelSchema.default("none")
16639
- }).default({
16640
- contents: "write",
16641
- pullRequests: "write",
16642
- issues: "write",
16643
- checks: "read",
16644
- actions: "read",
16645
- workflows: "none"
16646
- })
16743
+ }).default({ ...DEFAULT_GITHUB_MOUNT_CAPABILITIES })
16647
16744
  })
16648
16745
  ]);
16649
16746
  GitMountSchema = external_exports.object({
@@ -16759,12 +16856,13 @@ function remoteMcpToolSchema(input) {
16759
16856
  ]).default({ kind: "none" })
16760
16857
  });
16761
16858
  }
16762
- var RESOURCE_KIND_TOOL, REMOTE_MCP_TRANSPORTS, LOCAL_TOOL_IMPLEMENTATIONS, SecretReferenceSchema, NoToolAuthSchema, McpOAuthToolAuthSchema, ConnectionToolAuthSchema, ConnectionsToolAuthSchema, ToolAliasSchema, RemoteMcpToolSchema, LocalAutoToolSchema, LocalPingToolSchema, LocalChatToolSchema, LocalToolSchema, ToolSpecSchema, ToolResourceSchema, ToolApplyRequestSchema, ToolConnectRequestSchema, ToolConnectResponseSchema, ToolConnectCompleteResponseSchema, ReferencedSessionToolRefSchema, ReferencedSessionToolRefsSchema, InlineSessionToolSchema, SessionToolRefSchema, SessionToolsSchema;
16859
+ var RESOURCE_KIND_TOOL, REMOTE_MCP_TRANSPORTS, LOCAL_TOOL_IMPLEMENTATIONS, SecretReferenceSchema, NoToolAuthSchema, McpOAuthToolAuthSchema, ConnectionToolAuthSchema, ConnectionsToolAuthSchema, ToolAliasSchema, RemoteMcpToolSchema, LocalAutoToolSchema, LocalPingToolSchema, LocalChatToolSchema, LocalToolSchema, GithubToolSchema, ToolSpecSchema, ToolResourceSchema, ToolApplyRequestSchema, ToolConnectRequestSchema, ToolConnectResponseSchema, ToolConnectCompleteResponseSchema, ReferencedSessionToolRefSchema, ReferencedSessionToolRefsSchema, InlineSessionToolSchema, SessionToolRefSchema, SessionToolsSchema;
16763
16860
  var init_tools = __esm({
16764
16861
  "../../packages/schemas/src/tools.ts"() {
16765
16862
  "use strict";
16766
16863
  init_zod();
16767
16864
  init_connections();
16865
+ init_github_mcp_catalog();
16768
16866
  init_ids();
16769
16867
  init_resources();
16770
16868
  RESOURCE_KIND_TOOL = "tool";
@@ -16822,6 +16920,11 @@ var init_tools = __esm({
16822
16920
  error: `Unsupported local tool implementation. Supported implementations: ${LOCAL_TOOL_IMPLEMENTATIONS.join(", ")}`
16823
16921
  }
16824
16922
  );
16923
+ GithubToolSchema = external_exports.object({
16924
+ kind: external_exports.literal("github"),
16925
+ description: external_exports.string().trim().min(1).optional(),
16926
+ tools: external_exports.array(external_exports.enum(GITHUB_MCP_TOOL_NAMES)).min(1).optional()
16927
+ });
16825
16928
  ToolSpecSchema = external_exports.discriminatedUnion("kind", [
16826
16929
  RemoteMcpToolSchema,
16827
16930
  LocalToolSchema
@@ -16871,6 +16974,10 @@ var init_tools = __esm({
16871
16974
  disabled: external_exports.boolean().optional()
16872
16975
  })
16873
16976
  )
16977
+ ).or(
16978
+ GithubToolSchema.extend({
16979
+ disabled: external_exports.boolean().optional()
16980
+ })
16874
16981
  );
16875
16982
  SessionToolRefSchema = InlineSessionToolSchema.or(
16876
16983
  ReferencedSessionToolRefSchema
@@ -17133,8 +17240,8 @@ function hasAutoAttributionsExists(trigger, expected) {
17133
17240
  function isChatMessageEvent(trigger) {
17134
17241
  return trigger.event.startsWith("chat.message.");
17135
17242
  }
17136
- function hasFilterValue(trigger, path, expected) {
17137
- return trigger.where?.[path] === expected;
17243
+ function hasFilterValue(trigger, path2, expected) {
17244
+ return trigger.where?.[path2] === expected;
17138
17245
  }
17139
17246
  var RESOURCE_KIND_SESSION, TriggerFilterScalarSchema, TriggerFilterPathSchema, TriggerFilterClauseSchema, TriggerFilterSchema, SessionTriggerCheckTimeoutSchema, TriggerEventSchema, TriggerEventsSchema, SessionTriggerSharedFields, SessionTriggerEventSourceFields, SessionTriggerBaseSchema, SessionTriggerDefinitionBaseSchema, SessionTriggerSchema, SessionApplyTriggerSchema, SessionHeartbeatTriggerBaseSchema, SessionHeartbeatTriggerSchema, SessionApplyHeartbeatTriggerSchema, SessionTriggerDefinitionSchema, SessionApplyTriggerDefinitionSchema, SessionTriggersSchema, SessionApplyTriggersSchema, AVATAR_ASSET_EXTENSIONS, MAX_AVATAR_ASSET_BYTES, SESSION_IDENTITY_DESCRIPTION_MAX_LENGTH, SHA256_HEX_PATTERN, SessionIdentitySchema, SessionSpecSchema, SessionApplySpecSchema, SessionStatusSchema, SessionResourceSchema, SessionApplyRequestSchema, SessionApplyTriggerReceiptSchema, SessionApplyResponseSchema, SESSION_TELEGRAM_IDENTITY_STATUSES, SessionTelegramIdentityStatusSchema, SessionPresenceIdentitySchema, SessionPresenceResponseSchema, SessionPresenceConnectRequestSchema, SessionPresenceConnectPendingSchema, SessionPresenceConnectResponseSchema, SessionPresenceIconRequestSchema, SessionPresenceIconResponseSchema, SessionPresenceCompleteResponseSchema;
17140
17247
  var init_sessions = __esm({
@@ -17156,17 +17263,17 @@ var init_sessions = __esm({
17156
17263
  external_exports.boolean()
17157
17264
  ]);
17158
17265
  TriggerFilterPathSchema = external_exports.string().refine(
17159
- (path) => {
17160
- if (path.length === 0 || path.trim() !== path) {
17266
+ (path2) => {
17267
+ if (path2.length === 0 || path2.trim() !== path2) {
17161
17268
  return false;
17162
17269
  }
17163
- if (path.startsWith("$.")) {
17164
- const segments = path.slice(2).split(".");
17270
+ if (path2.startsWith("$.")) {
17271
+ const segments = path2.slice(2).split(".");
17165
17272
  return segments.length > 0 && segments.every(
17166
17273
  (segment) => segment.length > 0 && segment.trim() === segment
17167
17274
  );
17168
17275
  }
17169
- return !path.includes(".");
17276
+ return !path2.includes(".");
17170
17277
  },
17171
17278
  {
17172
17279
  message: "Trigger filter paths must be a single bare key or use $.path.segments"
@@ -17722,7 +17829,7 @@ var init_session_runs = __esm({
17722
17829
  external_exports.object({
17723
17830
  source: external_exports.literal("inline"),
17724
17831
  alias: ToolAliasSchema,
17725
- spec: RemoteMcpToolSchema.or(LocalToolSchema)
17832
+ spec: RemoteMcpToolSchema.or(LocalToolSchema).or(GithubToolSchema)
17726
17833
  }),
17727
17834
  external_exports.object({
17728
17835
  source: external_exports.literal("resource"),
@@ -18294,6 +18401,8 @@ var init_src = __esm({
18294
18401
  init_conversation();
18295
18402
  init_conversation_reducer();
18296
18403
  init_connections();
18404
+ init_github_credentials();
18405
+ init_github_mcp_catalog();
18297
18406
  init_ids();
18298
18407
  init_environments();
18299
18408
  init_mcp();
@@ -18369,10 +18478,10 @@ var init_active_project = __esm({
18369
18478
 
18370
18479
  // src/lib/config/path.ts
18371
18480
  import { createHash } from "crypto";
18372
- import { homedir } from "os";
18481
+ import { homedir as homedir2 } from "os";
18373
18482
  import { join, normalize } from "path";
18374
18483
  function defaultConfigPath() {
18375
- return process.env.AUTO_CLI_CONFIG ?? join(homedir(), ".auto", "config.yaml");
18484
+ return process.env.AUTO_CLI_CONFIG ?? join(homedir2(), ".auto", "config.yaml");
18376
18485
  }
18377
18486
  function profilesDir(configPath = defaultConfigPath()) {
18378
18487
  return normalize(join(configPath, "..", PROFILES_DIR_NAME));
@@ -18404,9 +18513,9 @@ var init_path = __esm({
18404
18513
  // src/lib/config/file.ts
18405
18514
  import { chmodSync, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
18406
18515
  import { basename, dirname as dirname2, join as join2 } from "path";
18407
- function readConfig(path = defaultConfigPath()) {
18516
+ function readConfig(path2 = defaultConfigPath()) {
18408
18517
  try {
18409
- const text = readFileSync2(path, "utf8");
18518
+ const text = readFileSync2(path2, "utf8");
18410
18519
  const config2 = {};
18411
18520
  for (const line of text.split(/\r?\n/)) {
18412
18521
  const match = /^([A-Za-z0-9_]+):\s*(.*)$/.exec(line.trim());
@@ -18420,13 +18529,13 @@ function readConfig(path = defaultConfigPath()) {
18420
18529
  throw err;
18421
18530
  }
18422
18531
  }
18423
- function writeConfig(config2, path = defaultConfigPath()) {
18424
- writeConfigFile(config2, path);
18425
- if (config2.userEmail && config2.serverUrl && basename(dirname2(path)) !== PROFILES_DIR_NAME) {
18532
+ function writeConfig(config2, path2 = defaultConfigPath()) {
18533
+ writeConfigFile(config2, path2);
18534
+ if (config2.userEmail && config2.serverUrl && basename(dirname2(path2)) !== PROFILES_DIR_NAME) {
18426
18535
  writeConfigFile(
18427
18536
  config2,
18428
18537
  join2(
18429
- dirname2(path),
18538
+ dirname2(path2),
18430
18539
  PROFILES_DIR_NAME,
18431
18540
  profileFileName({
18432
18541
  userEmail: config2.userEmail,
@@ -18436,17 +18545,17 @@ function writeConfig(config2, path = defaultConfigPath()) {
18436
18545
  );
18437
18546
  }
18438
18547
  }
18439
- function writeConfigFile(config2, path) {
18440
- mkdirSync2(dirname2(path), { recursive: true });
18548
+ function writeConfigFile(config2, path2) {
18549
+ mkdirSync2(dirname2(path2), { recursive: true });
18441
18550
  const lines = CONFIG_KEYS.filter((key) => config2[key]).map(
18442
18551
  (key) => `${key}: ${config2[key]}`
18443
18552
  );
18444
- writeFileSync2(path, `${lines.join("\n")}
18553
+ writeFileSync2(path2, `${lines.join("\n")}
18445
18554
  `, {
18446
18555
  encoding: "utf8",
18447
18556
  mode: 384
18448
18557
  });
18449
- chmodSync(path, 384);
18558
+ chmodSync(path2, 384);
18450
18559
  }
18451
18560
  var CONFIG_KEYS;
18452
18561
  var init_file = __esm({
@@ -18604,38 +18713,38 @@ var init_http = __esm({
18604
18713
  });
18605
18714
 
18606
18715
  // src/lib/api/paths.ts
18607
- function apiPath(path = "") {
18608
- return `${API_PREFIX}${cleanSubpath(path)}`;
18716
+ function apiPath(path2 = "") {
18717
+ return `${API_PREFIX}${cleanSubpath(path2)}`;
18609
18718
  }
18610
- function orgApiPath(organizationId, path = "") {
18611
- return apiPath(orgSubpath(organizationId, path));
18719
+ function orgApiPath(organizationId, path2 = "") {
18720
+ return apiPath(orgSubpath(organizationId, path2));
18612
18721
  }
18613
- function projectApiPath(project, path = "") {
18722
+ function projectApiPath(project, path2 = "") {
18614
18723
  return apiPath(
18615
18724
  orgSubpath(
18616
18725
  project.organizationId,
18617
- `/projects/${encodeURIComponent(project.projectId)}${cleanSubpath(path)}`
18726
+ `/projects/${encodeURIComponent(project.projectId)}${cleanSubpath(path2)}`
18618
18727
  )
18619
18728
  );
18620
18729
  }
18621
- function sessionApiPath(project, sessionName, path = "") {
18730
+ function sessionApiPath(project, sessionName, path2 = "") {
18622
18731
  return projectApiPath(
18623
18732
  project,
18624
- `/sessions/${encodeURIComponent(sessionName)}${cleanSubpath(path)}`
18733
+ `/sessions/${encodeURIComponent(sessionName)}${cleanSubpath(path2)}`
18625
18734
  );
18626
18735
  }
18627
- function runApiPath(runId, path = "") {
18628
- return apiPath(`/runs/${encodeURIComponent(runId)}${cleanSubpath(path)}`);
18736
+ function runApiPath(runId, path2 = "") {
18737
+ return apiPath(`/runs/${encodeURIComponent(runId)}${cleanSubpath(path2)}`);
18629
18738
  }
18630
- function cleanSubpath(path) {
18631
- const trimmed = path.trim();
18739
+ function cleanSubpath(path2) {
18740
+ const trimmed = path2.trim();
18632
18741
  if (!trimmed) {
18633
18742
  return "";
18634
18743
  }
18635
18744
  return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
18636
18745
  }
18637
- function orgSubpath(organizationId, path = "") {
18638
- return `/orgs/${encodeURIComponent(organizationId)}${cleanSubpath(path)}`;
18746
+ function orgSubpath(organizationId, path2 = "") {
18747
+ return `/orgs/${encodeURIComponent(organizationId)}${cleanSubpath(path2)}`;
18639
18748
  }
18640
18749
  var API_PREFIX;
18641
18750
  var init_paths = __esm({
@@ -18927,9 +19036,9 @@ async function deleteProjectResource(context, request, options) {
18927
19036
  };
18928
19037
  }
18929
19038
  async function applyProjectResources(context, request, options) {
18930
- const path = projectApplyPath(context);
19039
+ const path2 = projectApplyPath(context);
18931
19040
  const response = await context.authenticatedFetch(
18932
- context.apiUrl(path, options.apiBaseUrl),
19041
+ context.apiUrl(path2, options.apiBaseUrl),
18933
19042
  {
18934
19043
  method: "POST",
18935
19044
  headers: {
@@ -19026,8 +19135,8 @@ function createApiClient(input) {
19026
19135
  explicit
19027
19136
  });
19028
19137
  }
19029
- function apiUrl(path, explicit) {
19030
- return `${apiBaseUrl(explicit)}${path}`;
19138
+ function apiUrl(path2, explicit) {
19139
+ return `${apiBaseUrl(explicit)}${path2}`;
19031
19140
  }
19032
19141
  function activeProject() {
19033
19142
  const config2 = readConfig(input.configPath);
@@ -19196,8 +19305,8 @@ function createApiClient(input) {
19196
19305
  headers: bootstrapAuthHeaders(init.headers)
19197
19306
  });
19198
19307
  }
19199
- async function requestJson(path, options = {}) {
19200
- const url2 = new URL(apiUrl(path, options.apiBaseUrl));
19308
+ async function requestJson(path2, options = {}) {
19309
+ const url2 = new URL(apiUrl(path2, options.apiBaseUrl));
19201
19310
  const searchParamEntries = Array.isArray(options.searchParams) ? options.searchParams : Object.entries(options.searchParams ?? {});
19202
19311
  for (const [name, value] of searchParamEntries) {
19203
19312
  url2.searchParams.append(name, value);
@@ -19581,7 +19690,7 @@ function createApiClient(input) {
19581
19690
  }),
19582
19691
  async setSecret(name, request, options = {}) {
19583
19692
  const organization = activeOrganization();
19584
- const path = options.projectId ? projectApiPath(
19693
+ const path2 = options.projectId ? projectApiPath(
19585
19694
  {
19586
19695
  organizationId: organization.organizationId,
19587
19696
  projectId: options.projectId
@@ -19592,7 +19701,7 @@ function createApiClient(input) {
19592
19701
  `/secrets/${encodeURIComponent(name)}`
19593
19702
  );
19594
19703
  const response = await authenticatedFetch(
19595
- apiUrl(path, options.apiBaseUrl),
19704
+ apiUrl(path2, options.apiBaseUrl),
19596
19705
  {
19597
19706
  method: "PUT",
19598
19707
  headers: {
@@ -19609,7 +19718,7 @@ function createApiClient(input) {
19609
19718
  },
19610
19719
  async listSecrets(options = {}) {
19611
19720
  const organization = activeOrganization();
19612
- const path = options.projectId ? projectApiPath(
19721
+ const path2 = options.projectId ? projectApiPath(
19613
19722
  {
19614
19723
  organizationId: organization.organizationId,
19615
19724
  projectId: options.projectId
@@ -19617,7 +19726,7 @@ function createApiClient(input) {
19617
19726
  "/secrets"
19618
19727
  ) : orgApiPath(organization.organizationId, "/secrets");
19619
19728
  const response = await authenticatedFetch(
19620
- apiUrl(path, options.apiBaseUrl),
19729
+ apiUrl(path2, options.apiBaseUrl),
19621
19730
  {},
19622
19731
  options.apiBaseUrl
19623
19732
  );
@@ -19628,7 +19737,7 @@ function createApiClient(input) {
19628
19737
  },
19629
19738
  async removeSecret(name, options = {}) {
19630
19739
  const organization = activeOrganization();
19631
- const path = options.projectId ? projectApiPath(
19740
+ const path2 = options.projectId ? projectApiPath(
19632
19741
  {
19633
19742
  organizationId: organization.organizationId,
19634
19743
  projectId: options.projectId
@@ -19639,7 +19748,7 @@ function createApiClient(input) {
19639
19748
  `/secrets/${encodeURIComponent(name)}`
19640
19749
  );
19641
19750
  const response = await authenticatedFetch(
19642
- apiUrl(path, options.apiBaseUrl),
19751
+ apiUrl(path2, options.apiBaseUrl),
19643
19752
  {
19644
19753
  method: "DELETE"
19645
19754
  },
@@ -20138,9 +20247,9 @@ var init_browser = __esm({
20138
20247
  });
20139
20248
 
20140
20249
  // src/lib/oauth/loopback.ts
20141
- import { createServer } from "http";
20250
+ import { createServer as createServer2 } from "http";
20142
20251
  async function createOAuthLoopbackCallback(input) {
20143
- const path = input?.path ?? "/callback";
20252
+ const path2 = input?.path ?? "/callback";
20144
20253
  const successHtml = input?.successHtml ?? renderOAuthLoopbackPage({
20145
20254
  status: "success",
20146
20255
  eyebrow: "Auto",
@@ -20159,9 +20268,9 @@ async function createOAuthLoopbackCallback(input) {
20159
20268
  resolveResult = resolve2;
20160
20269
  rejectResult = reject;
20161
20270
  });
20162
- const server = createServer((request, response) => {
20271
+ const server = createServer2((request, response) => {
20163
20272
  const url2 = new URL(request.url ?? "/", "http://127.0.0.1");
20164
- if (url2.pathname !== path) {
20273
+ if (url2.pathname !== path2) {
20165
20274
  response.writeHead(404).end("Not found");
20166
20275
  return;
20167
20276
  }
@@ -20203,7 +20312,7 @@ async function createOAuthLoopbackCallback(input) {
20203
20312
  const address = server.address();
20204
20313
  return {
20205
20314
  close: () => server.close(),
20206
- redirectUri: `http://127.0.0.1:${address.port}${path}`,
20315
+ redirectUri: `http://127.0.0.1:${address.port}${path2}`,
20207
20316
  result
20208
20317
  };
20209
20318
  }
@@ -20585,12 +20694,12 @@ function readProjectApplyRequest(options) {
20585
20694
  throw new Error(`No resource files found in ${directory}`);
20586
20695
  }
20587
20696
  const resources = [];
20588
- for (const { kind, path } of files) {
20589
- const request = readApplyDocumentFile(path);
20697
+ for (const { kind, path: path2 } of files) {
20698
+ const request = readApplyDocumentFile(path2);
20590
20699
  for (const resource of request.resources) {
20591
20700
  if (resource.kind !== kind) {
20592
20701
  throw new Error(
20593
- `Resource kind "${resource.kind}" in ${path} does not match .auto/${APPLY_DIRECTORIES[kind]}`
20702
+ `Resource kind "${resource.kind}" in ${path2} does not match .auto/${APPLY_DIRECTORIES[kind]}`
20594
20703
  );
20595
20704
  }
20596
20705
  resources.push(resource);
@@ -20642,15 +20751,15 @@ function applyFiles(root) {
20642
20751
  const files = [];
20643
20752
  for (const kind of APPLY_RESOURCE_ORDER) {
20644
20753
  const directory = APPLY_DIRECTORIES[kind];
20645
- const path = join3(root, directory);
20754
+ const path2 = join3(root, directory);
20646
20755
  let entries;
20647
20756
  try {
20648
- entries = readdirSync(path, { withFileTypes: true });
20757
+ entries = readdirSync(path2, { withFileTypes: true });
20649
20758
  } catch {
20650
20759
  continue;
20651
20760
  }
20652
20761
  files.push(
20653
- ...resourceApplyFiles(path, entries).map((file2) => ({
20762
+ ...resourceApplyFiles(path2, entries).map((file2) => ({
20654
20763
  kind,
20655
20764
  path: file2
20656
20765
  }))
@@ -20658,8 +20767,8 @@ function applyFiles(root) {
20658
20767
  }
20659
20768
  return files;
20660
20769
  }
20661
- function readApplyDocumentFile(path) {
20662
- const source = readFileSync3(path, "utf8");
20770
+ function readApplyDocumentFile(path2) {
20771
+ const source = readFileSync3(path2, "utf8");
20663
20772
  let documents;
20664
20773
  try {
20665
20774
  documents = parseYamlDocuments(source).filter((document) => document.contents !== null).map((document) => document.toJSON());
@@ -20669,7 +20778,7 @@ function readApplyDocumentFile(path) {
20669
20778
  );
20670
20779
  }
20671
20780
  if (documents.length === 0) {
20672
- throw new Error(`Invalid apply file: ${path} is empty`);
20781
+ throw new Error(`Invalid apply file: ${path2} is empty`);
20673
20782
  }
20674
20783
  if (documents.length === 1) {
20675
20784
  const system = ProjectApplySystemConfigSchema.safeParse(documents[0]);
@@ -20795,8 +20904,8 @@ function applyFileProjectRoot(file2) {
20795
20904
  dir = parent;
20796
20905
  }
20797
20906
  }
20798
- function isInside(path, parent) {
20799
- return path.startsWith(`${parent}/`);
20907
+ function isInside(path2, parent) {
20908
+ return path2.startsWith(`${parent}/`);
20800
20909
  }
20801
20910
  function applyCandidate(document) {
20802
20911
  if (!isRecord(document) || !("kind" in document)) {
@@ -20822,15 +20931,15 @@ function isRecord(value) {
20822
20931
  function resourceApplyFiles(directory, entries) {
20823
20932
  const files = [];
20824
20933
  for (const entry of entries) {
20825
- const path = join3(directory, entry.name);
20934
+ const path2 = join3(directory, entry.name);
20826
20935
  if (entry.isDirectory()) {
20827
20936
  files.push(
20828
- ...resourceApplyFiles(path, readdirSync(path, { withFileTypes: true }))
20937
+ ...resourceApplyFiles(path2, readdirSync(path2, { withFileTypes: true }))
20829
20938
  );
20830
20939
  continue;
20831
20940
  }
20832
20941
  if (entry.isFile() && /\.(json|ya?ml)$/i.test(entry.name)) {
20833
- files.push(path);
20942
+ files.push(path2);
20834
20943
  }
20835
20944
  }
20836
20945
  return files.sort((left, right) => left.localeCompare(right));
@@ -20984,8 +21093,8 @@ function listProfiles(configPath = defaultConfigPath()) {
20984
21093
  throw err;
20985
21094
  }
20986
21095
  return entries.filter((entry) => entry.endsWith(".yaml")).sort().map((entry) => {
20987
- const path = join4(dir, entry);
20988
- return { path, config: readConfig(path) };
21096
+ const path2 = join4(dir, entry);
21097
+ return { path: path2, config: readConfig(path2) };
20989
21098
  }).filter((profile) => profile.config.userEmail);
20990
21099
  }
20991
21100
  function findAccountProfile(input) {
@@ -21490,7 +21599,7 @@ var init_package = __esm({
21490
21599
  "package.json"() {
21491
21600
  package_default = {
21492
21601
  name: "@autohq/cli",
21493
- version: "0.1.89",
21602
+ version: "0.1.90",
21494
21603
  license: "SEE LICENSE IN README.md",
21495
21604
  publishConfig: {
21496
21605
  access: "public"
@@ -26616,6 +26725,156 @@ var init_launcher = __esm({
26616
26725
  // src/cli/program.ts
26617
26726
  import { Command, Option as Option3 } from "commander";
26618
26727
 
26728
+ // src/commands/agent-bridge/git-credentials.ts
26729
+ import { once } from "events";
26730
+ import { chmod, mkdir, readFile, writeFile } from "fs/promises";
26731
+ import { createServer } from "http";
26732
+ import { homedir } from "os";
26733
+ import path from "path";
26734
+ var RELAY_PATH = "/git-credential";
26735
+ function defaultGitCredentialPortFilePath() {
26736
+ return path.join(homedir(), ".auto", "agent-bridge", "git-credential.json");
26737
+ }
26738
+ async function startGitCredentialRelay(input) {
26739
+ const fetchImpl = input.fetchImpl ?? fetch;
26740
+ let target = { url: input.url, accessToken: input.accessToken };
26741
+ const server = createServer((request, response) => {
26742
+ if (request.method !== "POST" || request.url !== RELAY_PATH) {
26743
+ response.writeHead(404).end();
26744
+ return;
26745
+ }
26746
+ const chunks = [];
26747
+ request.on("data", (chunk) => chunks.push(chunk));
26748
+ request.on("end", () => {
26749
+ void (async () => {
26750
+ try {
26751
+ const upstream = await fetchImpl(target.url, {
26752
+ method: "POST",
26753
+ headers: {
26754
+ authorization: `Bearer ${target.accessToken}`,
26755
+ "content-type": "application/json"
26756
+ },
26757
+ body: Buffer.concat(chunks).toString("utf8") || "{}"
26758
+ });
26759
+ const body = await upstream.text();
26760
+ response.writeHead(upstream.status, {
26761
+ "content-type": upstream.headers.get("content-type") ?? "application/json"
26762
+ }).end(body);
26763
+ } catch (error51) {
26764
+ response.writeHead(502, { "content-type": "application/json" }).end(
26765
+ JSON.stringify({
26766
+ error: error51 instanceof Error ? error51.message : String(error51)
26767
+ })
26768
+ );
26769
+ }
26770
+ })();
26771
+ });
26772
+ });
26773
+ server.listen(0, "127.0.0.1");
26774
+ await once(server, "listening");
26775
+ server.unref();
26776
+ const address = server.address();
26777
+ if (!address || typeof address !== "object") {
26778
+ server.close();
26779
+ throw new Error("git credential relay failed to bind a loopback port");
26780
+ }
26781
+ const portFilePath = input.portFilePath ?? defaultGitCredentialPortFilePath();
26782
+ await mkdir(path.dirname(portFilePath), { recursive: true });
26783
+ await writeFile(portFilePath, JSON.stringify({ port: address.port }), {
26784
+ mode: 384
26785
+ });
26786
+ await chmod(portFilePath, 384);
26787
+ return {
26788
+ port: address.port,
26789
+ update: (next) => {
26790
+ target = { url: next.url, accessToken: next.accessToken };
26791
+ },
26792
+ close: () => new Promise((resolve2) => {
26793
+ server.close(() => resolve2());
26794
+ })
26795
+ };
26796
+ }
26797
+ async function runGitCredentialHelper(input) {
26798
+ if (input.args.includes("--check")) {
26799
+ return 0;
26800
+ }
26801
+ const operation = input.args.find((arg) => !arg.startsWith("-"));
26802
+ if (operation === "store" || operation === "erase") {
26803
+ return 0;
26804
+ }
26805
+ if (operation !== "get") {
26806
+ input.writeError(`unsupported git credential operation: ${operation}`);
26807
+ return 1;
26808
+ }
26809
+ try {
26810
+ const attributes = parseGitCredentialAttributes(
26811
+ await readStream(input.stdin)
26812
+ );
26813
+ if (attributes.protocol !== "https" || attributes.host !== "github.com") {
26814
+ return 1;
26815
+ }
26816
+ const portFilePath = input.portFilePath ?? defaultGitCredentialPortFilePath();
26817
+ const portFile = JSON.parse(await readFile(portFilePath, "utf8"));
26818
+ if (typeof portFile.port !== "number") {
26819
+ input.writeError("git credential relay port file is malformed");
26820
+ return 1;
26821
+ }
26822
+ const response = await (input.fetchImpl ?? fetch)(
26823
+ `http://127.0.0.1:${portFile.port}${RELAY_PATH}`,
26824
+ {
26825
+ method: "POST",
26826
+ headers: { "content-type": "application/json" },
26827
+ body: JSON.stringify({
26828
+ host: attributes.host,
26829
+ ...attributes.path ? { path: attributes.path } : {}
26830
+ })
26831
+ }
26832
+ );
26833
+ if (!response.ok) {
26834
+ input.writeError(
26835
+ `git credential broker rejected the request: ${response.status}`
26836
+ );
26837
+ return 1;
26838
+ }
26839
+ const credential = await response.json();
26840
+ if (!credential.username || !credential.password) {
26841
+ input.writeError("git credential broker returned no credential");
26842
+ return 1;
26843
+ }
26844
+ input.writeOutput(`username=${credential.username}`);
26845
+ input.writeOutput(`password=${credential.password}`);
26846
+ const expiryUtc = credential.expiresAt ? Math.floor(new Date(credential.expiresAt).getTime() / 1e3) : void 0;
26847
+ if (expiryUtc && Number.isFinite(expiryUtc)) {
26848
+ input.writeOutput(`password_expiry_utc=${expiryUtc}`);
26849
+ }
26850
+ return 0;
26851
+ } catch (error51) {
26852
+ input.writeError(error51 instanceof Error ? error51.message : String(error51));
26853
+ return 1;
26854
+ }
26855
+ }
26856
+ function parseGitCredentialAttributes(raw) {
26857
+ const attributes = {};
26858
+ for (const line of raw.split("\n")) {
26859
+ if (!line.trim()) {
26860
+ continue;
26861
+ }
26862
+ const separator = line.indexOf("=");
26863
+ if (separator <= 0) {
26864
+ continue;
26865
+ }
26866
+ attributes[line.slice(0, separator)] = line.slice(separator + 1);
26867
+ }
26868
+ return attributes;
26869
+ }
26870
+ async function readStream(stream) {
26871
+ const chunks = [];
26872
+ for await (const chunk of stream) {
26873
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
26874
+ }
26875
+ return Buffer.concat(chunks).toString("utf8");
26876
+ }
26877
+
26619
26878
  // ../../packages/protocol/src/index.ts
26620
26879
  init_zod();
26621
26880
  var OpaqueIdSchema = external_exports.string().trim().min(1);
@@ -26724,7 +26983,14 @@ var AgentBridgeClaudeConfigSchema = external_exports.object({
26724
26983
  var RuntimeBridgeBootstrapPlaintextSchema = external_exports.object({
26725
26984
  version: external_exports.literal(1),
26726
26985
  outputSeqStart: external_exports.number().int().nonnegative(),
26727
- claude: AgentBridgeClaudeConfigSchema
26986
+ claude: AgentBridgeClaudeConfigSchema,
26987
+ // Endpoint + run token for the git credential broker. Present only when
26988
+ // the run has GitHub App git mounts; rides the encrypted bootstrap so the
26989
+ // token lives in agent-bridge memory, never on disk.
26990
+ gitCredentials: external_exports.object({
26991
+ url: external_exports.string().trim().min(1),
26992
+ accessToken: external_exports.string().trim().min(1)
26993
+ }).strict().optional()
26728
26994
  }).strict();
26729
26995
  var RuntimeBridgeEncryptedBootstrapSchema = external_exports.object({
26730
26996
  version: external_exports.literal(1),
@@ -26951,6 +27217,7 @@ async function runAgentBridgeSocket(options) {
26951
27217
  RUNTIME_BRIDGE_BOOTSTRAP_EVENT,
26952
27218
  createRuntimeBridgeBootstrapListener({
26953
27219
  token: options.token,
27220
+ onBootstrap: options.onBootstrap,
26954
27221
  createHandler: (bootstrap) => options.createHandler({
26955
27222
  emitOutput: (output) => emitOutputWithAck(socket, output),
26956
27223
  claude: bootstrap.claude,
@@ -27049,6 +27316,7 @@ function createRuntimeBridgeBootstrapListener(input) {
27049
27316
  input.writeOutput?.(
27050
27317
  `agent_bridge_bootstrap_decrypted duration_ms=${Date.now() - decryptStartedAt}`
27051
27318
  );
27319
+ await input.onBootstrap?.(bootstrap);
27052
27320
  let handler = input.getHandler();
27053
27321
  if (!handler) {
27054
27322
  handler = input.createHandler(bootstrap);
@@ -27885,21 +28153,21 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
27885
28153
  import { dirname } from "path";
27886
28154
  var AGENT_BRIDGE_RUNTIME_DIR = "/tmp/auto-bridge-runtime";
27887
28155
  var CLAUDE_SESSION_RESUME_PATH = `${AGENT_BRIDGE_RUNTIME_DIR}/claude-session-id`;
27888
- function fileClaudeSessionResumeStore(path = CLAUDE_SESSION_RESUME_PATH) {
28156
+ function fileClaudeSessionResumeStore(path2 = CLAUDE_SESSION_RESUME_PATH) {
27889
28157
  return {
27890
28158
  read(runId) {
27891
- if (!existsSync(path)) {
28159
+ if (!existsSync(path2)) {
27892
28160
  return null;
27893
28161
  }
27894
- const record2 = parseResumeRecord(readFileSync(path, "utf8"));
28162
+ const record2 = parseResumeRecord(readFileSync(path2, "utf8"));
27895
28163
  if (!record2 || record2.runId !== runId) {
27896
28164
  return null;
27897
28165
  }
27898
28166
  return record2.sessionId;
27899
28167
  },
27900
28168
  write(record2) {
27901
- mkdirSync(dirname(path), { recursive: true });
27902
- writeFileSync(path, `${JSON.stringify(record2)}
28169
+ mkdirSync(dirname(path2), { recursive: true });
28170
+ writeFileSync(path2, `${JSON.stringify(record2)}
27903
28171
  `, "utf8");
27904
28172
  }
27905
28173
  };
@@ -28268,7 +28536,10 @@ function deliveryMessage(delivery) {
28268
28536
  // src/commands/agent-bridge/entrypoint.ts
28269
28537
  async function runAgentBridgeProcess(input) {
28270
28538
  const runAgentBridge = input.runAgentBridge ?? runAgentBridgeClaudeCode;
28271
- await runAgentBridge(agentBridgeOptionsFromEnv(input));
28539
+ await runAgentBridge({
28540
+ ...agentBridgeOptionsFromEnv(input),
28541
+ onBootstrap: createGitCredentialRelayStarter(input.writeOutput)
28542
+ });
28272
28543
  }
28273
28544
  function agentBridgeOptionsFromEnv(input) {
28274
28545
  return {
@@ -28277,6 +28548,37 @@ function agentBridgeOptionsFromEnv(input) {
28277
28548
  writeOutput: input.writeOutput
28278
28549
  };
28279
28550
  }
28551
+ function createGitCredentialRelayStarter(writeOutput) {
28552
+ let relay;
28553
+ let startup;
28554
+ return async (bootstrap) => {
28555
+ const gitCredentials = bootstrap.gitCredentials;
28556
+ if (!gitCredentials) {
28557
+ return;
28558
+ }
28559
+ if (relay) {
28560
+ relay.update(gitCredentials);
28561
+ return;
28562
+ }
28563
+ if (startup) {
28564
+ const started = await startup;
28565
+ started?.update(gitCredentials);
28566
+ return;
28567
+ }
28568
+ startup = startGitCredentialRelay(gitCredentials).then((started) => {
28569
+ relay = started;
28570
+ writeOutput?.(`agent_bridge_git_credential_relay port=${started.port}`);
28571
+ return started;
28572
+ }).catch((error51) => {
28573
+ startup = void 0;
28574
+ writeOutput?.(
28575
+ `agent_bridge_git_credential_relay_failed error=${error51 instanceof Error ? error51.message : String(error51)}`
28576
+ );
28577
+ return void 0;
28578
+ });
28579
+ await startup;
28580
+ };
28581
+ }
28280
28582
  function requiredEnv(env, key) {
28281
28583
  const value = env[key]?.trim();
28282
28584
  if (!value) {
@@ -28287,12 +28589,25 @@ function requiredEnv(env, key) {
28287
28589
 
28288
28590
  // src/commands/agent-bridge/commands.ts
28289
28591
  function registerAgentBridgeCommands(program, context) {
28290
- program.command("agent-bridge", { hidden: true }).description("Run the internal runtime bridge wrapper.").action(async () => {
28592
+ const agentBridge = program.command("agent-bridge", { hidden: true }).description("Run the internal runtime bridge wrapper.").action(async () => {
28291
28593
  await runAgentBridgeProcess({
28292
28594
  env: context.env,
28293
28595
  writeOutput: context.writeOutput
28294
28596
  });
28295
28597
  });
28598
+ agentBridge.command("git-credential [operation]").description("git credential helper backed by the run's broker endpoint.").option("--check", "Exit 0 when the helper is available.").allowUnknownOption(true).action(async (operation, options) => {
28599
+ const exitCode = await runGitCredentialHelper({
28600
+ args: [
28601
+ ...options.check ? ["--check"] : [],
28602
+ ...operation ? [operation] : []
28603
+ ],
28604
+ stdin: process.stdin,
28605
+ writeOutput: context.writeOutput,
28606
+ writeError: (line) => process.stderr.write(`${line}
28607
+ `)
28608
+ });
28609
+ process.exitCode = exitCode;
28610
+ });
28296
28611
  }
28297
28612
 
28298
28613
  // src/cli/options.ts
@@ -31214,7 +31529,7 @@ async function secretValue(input) {
31214
31529
  }
31215
31530
  value = envValue;
31216
31531
  } else if (input.options.stdin) {
31217
- value = await readStream(input.stdin, Boolean(input.options.raw));
31532
+ value = await readStream2(input.stdin, Boolean(input.options.raw));
31218
31533
  } else {
31219
31534
  throw new Error(
31220
31535
  "Provide the secret value with --stdin, --value, or --from-env."
@@ -31227,7 +31542,7 @@ async function secretValue(input) {
31227
31542
  }
31228
31543
  return value;
31229
31544
  }
31230
- async function readStream(stream, raw) {
31545
+ async function readStream2(stream, raw) {
31231
31546
  const chunks = [];
31232
31547
  for await (const chunk of stream) {
31233
31548
  chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));
@@ -31457,7 +31772,7 @@ function withApiBaseUrl2(context, commandOptions) {
31457
31772
  init_resources2();
31458
31773
  init_browser();
31459
31774
  import { existsSync as existsSync2, mkdtempSync as mkdtempSync2, writeFileSync as writeFileSync4 } from "fs";
31460
- import { homedir as homedir2, tmpdir as tmpdir2 } from "os";
31775
+ import { homedir as homedir3, tmpdir as tmpdir2 } from "os";
31461
31776
  import { join as join6 } from "path";
31462
31777
  var POLL_INTERVAL_MS = 2e3;
31463
31778
  var POLL_TIMEOUT_MS = 5 * 6e4;
@@ -31619,7 +31934,7 @@ async function promptForIconUploads(input, options) {
31619
31934
  }
31620
31935
  }
31621
31936
  function stagedLocationLabel(stagedPath) {
31622
- return stagedPath.startsWith(`${join6(homedir2(), "Downloads")}/`) ? "Downloads" : "the printed path";
31937
+ return stagedPath.startsWith(`${join6(homedir3(), "Downloads")}/`) ? "Downloads" : "the printed path";
31623
31938
  }
31624
31939
  async function stageAvatarImage(input) {
31625
31940
  try {
@@ -31631,11 +31946,11 @@ async function stageAvatarImage(input) {
31631
31946
  }
31632
31947
  const contentType = response.headers.get("content-type") ?? "";
31633
31948
  const extension = contentType.includes("jpeg") ? ".jpg" : ".png";
31634
- const downloads = join6(homedir2(), "Downloads");
31949
+ const downloads = join6(homedir3(), "Downloads");
31635
31950
  const directory = existsSync2(downloads) ? downloads : mkdtempSync2(join6(tmpdir2(), "auto-avatar-"));
31636
- const path = join6(directory, `${input.session}-avatar${extension}`);
31637
- writeFileSync4(path, Buffer.from(await response.arrayBuffer()));
31638
- return path;
31951
+ const path2 = join6(directory, `${input.session}-avatar${extension}`);
31952
+ writeFileSync4(path2, Buffer.from(await response.arrayBuffer()));
31953
+ return path2;
31639
31954
  } catch {
31640
31955
  return void 0;
31641
31956
  }