@clawos-dev/clawd 0.2.647 → 0.2.649

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.
@@ -31292,6 +31292,8 @@ var EnvConnectorSchema = external_exports.object({
31292
31292
  id: external_exports.string().min(1),
31293
31293
  credentialSource: external_exports.enum(CREDENTIAL_SOURCES).optional(),
31294
31294
  auth: external_exports.enum(CONNECTOR_AUTHS).optional(),
31295
+ // Stamped by deploy:release from the authenticated owner, never chosen by the UI.
31296
+ publisherUnionId: external_exports.string().regex(/^on_[A-Za-z0-9_-]+$/).optional(),
31295
31297
  fields: external_exports.array(ConnectorFieldSchema).default([]),
31296
31298
  http: external_exports.object({ url: external_exports.string().min(1), headers: external_exports.record(external_exports.string(), external_exports.string()) }).optional()
31297
31299
  });
@@ -31523,6 +31525,11 @@ var DeployStateSchema = external_exports.object({
31523
31525
  personaId: external_exports.string().min(1),
31524
31526
  /** 本机 GitHub 身份(机器级,githubAuth:* 的同一份;上云页顶上那张卡用)。老 daemon 不给(可选只为兼容),UI 缺席时按未知处理 */
31525
31527
  github: GithubAuthStatusSchema.optional(),
31528
+ /** Current publisher's Feishu tool grant, including authorization links before first release. */
31529
+ publisherFeishuAuth: external_exports.object({
31530
+ integration: external_exports.object({ connected: external_exports.boolean(), authUrl: external_exports.string().optional(), error: external_exports.string().optional() }).strict(),
31531
+ production: external_exports.object({ connected: external_exports.boolean(), authUrl: external_exports.string().optional(), error: external_exports.string().optional() }).strict()
31532
+ }).strict().optional(),
31526
31533
  repo: DeployRepoSchema.optional(),
31527
31534
  scans: external_exports.array(DeployScanSchema).default([]),
31528
31535
  releases: external_exports.array(DeployReleasedSchema).default([]),
package/dist/cli.cjs CHANGED
@@ -6022,9 +6022,14 @@ var init_github_auth_schemas = __esm({
6022
6022
  function isFeishuBotConnector(c2) {
6023
6023
  return c2.name === "feishu" && c2.runner === "cli" && c2.kind === "env" && c2.credentialSource === "shared";
6024
6024
  }
6025
+ function isFeishuPublisherConnector(c2) {
6026
+ return c2.name === "feishu" && c2.id === "feishu" && c2.runner === "cli" && c2.kind === "proxy" && c2.protocol === "lark-sidecar" && c2.credentialSource === "shared" && c2.auth === "oauth" && c2.fields.length === 0;
6027
+ }
6025
6028
  function connectorBlockers(c2) {
6026
6029
  if (!c2.credentialSource) return [`\u8FDE\u63A5\u5668 ${c2.name} \u8FD8\u6CA1\u9009\u7528\u8C01\u7684\u8D26\u53F7`];
6027
6030
  const out = [];
6031
+ if (isFeishuPublisherConnector(c2)) return out;
6032
+ if (c2.protocol === "lark-sidecar" && c2.credentialSource === "shared") return ["\u8FDE\u63A5\u5668 feishu \u7684\u53D1\u5E03\u8005 OAuth \u914D\u7F6E\u4E0D\u5B8C\u6574\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9\u8D26\u53F7\u8EAB\u4EFD"];
6028
6033
  if (isFeishuBotConnector(c2)) {
6029
6034
  return FEISHU_BOT_FIELDS.filter((f2) => !c2.fields.includes(f2)).map((f2) => `\u8FDE\u63A5\u5668 feishu \u7684 Lark App Bot \u7F3A\u5C11 ${f2 === "LARKSUITE_CLI_APP_ID" ? "App ID" : "App Secret"}`);
6030
6035
  }
@@ -6138,6 +6143,8 @@ var init_environment_schemas = __esm({
6138
6143
  id: external_exports.string().min(1),
6139
6144
  credentialSource: external_exports.enum(CREDENTIAL_SOURCES).optional(),
6140
6145
  auth: external_exports.enum(CONNECTOR_AUTHS).optional(),
6146
+ // Stamped by deploy:release from the authenticated owner, never chosen by the UI.
6147
+ publisherUnionId: external_exports.string().regex(/^on_[A-Za-z0-9_-]+$/).optional(),
6141
6148
  fields: external_exports.array(ConnectorFieldSchema).default([]),
6142
6149
  http: external_exports.object({ url: external_exports.string().min(1), headers: external_exports.record(external_exports.string(), external_exports.string()) }).optional()
6143
6150
  });
@@ -6434,6 +6441,11 @@ var init_deploy_schemas = __esm({
6434
6441
  personaId: external_exports.string().min(1),
6435
6442
  /** 本机 GitHub 身份(机器级,githubAuth:* 的同一份;上云页顶上那张卡用)。老 daemon 不给(可选只为兼容),UI 缺席时按未知处理 */
6436
6443
  github: GithubAuthStatusSchema.optional(),
6444
+ /** Current publisher's Feishu tool grant, including authorization links before first release. */
6445
+ publisherFeishuAuth: external_exports.object({
6446
+ integration: external_exports.object({ connected: external_exports.boolean(), authUrl: external_exports.string().optional(), error: external_exports.string().optional() }).strict(),
6447
+ production: external_exports.object({ connected: external_exports.boolean(), authUrl: external_exports.string().optional(), error: external_exports.string().optional() }).strict()
6448
+ }).strict().optional(),
6437
6449
  repo: DeployRepoSchema.optional(),
6438
6450
  scans: external_exports.array(DeployScanSchema).default([]),
6439
6451
  releases: external_exports.array(DeployReleasedSchema).default([]),
@@ -57576,7 +57588,7 @@ function cliConnectorFromFinding(item) {
57576
57588
  }
57577
57589
  function mergeConnector(existing, incoming) {
57578
57590
  if (!existing) return incoming;
57579
- if (isFeishuBotConnector(existing) && incoming.name === existing.name && incoming.runner === "cli") return existing;
57591
+ if ((isFeishuBotConnector(existing) || isFeishuPublisherConnector(existing)) && incoming.name === existing.name && incoming.runner === "cli") return existing;
57580
57592
  const reviewed = existing.credentialSource !== void 0;
57581
57593
  return {
57582
57594
  ...incoming,
@@ -61477,6 +61489,7 @@ async function storeGithubAuth(args) {
61477
61489
  init_zod();
61478
61490
  var SLUG = "ottin4ttc/clawos";
61479
61491
  var WORKFLOW = ".github/workflows/base-image-acr.yml";
61492
+ var DOCKERFILE = "cloud-host/Dockerfile.base";
61480
61493
  var SHA = external_exports.string().regex(/^[a-f0-9]{40}$/);
61481
61494
  var SourceSchema = external_exports.object({ cloudHost: SHA, workflow: SHA });
61482
61495
  var BaseSchema = external_exports.object({
@@ -61502,6 +61515,25 @@ async function currentSource(api) {
61502
61515
  if (!source.success) throw new Error("\u5E95\u5EA7\u6E90\u7801\u7248\u672C\u8BB0\u5F55\u4E0D\u5B8C\u6574\uFF0C\u8BF7\u5237\u65B0\u540E\u518D\u53D1\u5E03");
61503
61516
  return { commit, source: source.data };
61504
61517
  }
61518
+ function dockerfileInputs(text) {
61519
+ if (!/^\s*FROM\s+/im.test(text)) throw new Error("\u8BFB\u4E0D\u5230\u53EF\u4FE1\u7684\u5E95\u5EA7\u6784\u5EFA\u914D\u65B9");
61520
+ const logical = text.replace(/\\\r?\n/g, " ");
61521
+ if (/^\s*RUN\b.*--mount=/im.test(logical)) throw new Error("\u5E95\u5EA7\u6302\u8F7D\u8F93\u5165\u65E0\u6CD5\u5B8C\u6574\u6BD4\u8F83\uFF0C\u8BF7\u91CD\u65B0\u6784\u5EFA");
61522
+ const inputs = /* @__PURE__ */ new Set([DOCKERFILE, "cloud-host/.dockerignore", "cloud-host/Dockerfile.base.dockerignore"]);
61523
+ for (const line of logical.split("\n")) {
61524
+ const instruction = /^\s*(?:COPY|ADD)\s+(.+)$/i.exec(line)?.[1];
61525
+ if (!instruction || /^--from=\S+\s/.test(instruction)) continue;
61526
+ const tokens = instruction.startsWith("[") ? JSON.parse(instruction) : instruction.trim().split(/\s+/);
61527
+ if (!Array.isArray(tokens) || tokens.length < 2) throw new Error("\u5E95\u5EA7 COPY \u8F93\u5165\u4E0D\u5B8C\u6574\uFF0C\u8BF7\u91CD\u65B0\u6784\u5EFA");
61528
+ for (const source of tokens.slice(0, -1)) {
61529
+ if (typeof source !== "string" || !/^[A-Za-z0-9_-][A-Za-z0-9_./-]*$/.test(source) || source.split("/").some((segment) => !segment || segment === "." || segment === "..")) {
61530
+ throw new Error("\u5E95\u5EA7 COPY \u8F93\u5165\u65E0\u6CD5\u5B8C\u6574\u6BD4\u8F83\uFF0C\u8BF7\u91CD\u65B0\u6784\u5EFA");
61531
+ }
61532
+ inputs.add("cloud-host/" + source.replace(/\/$/, ""));
61533
+ }
61534
+ }
61535
+ return inputs;
61536
+ }
61505
61537
  async function readCurrentBase(api) {
61506
61538
  const current = await currentSource(api);
61507
61539
  const listed = await api.getJsonStrict(`/repos/${SLUG}/actions/workflows/base-image-acr.yml/runs?branch=release&per_page=1`);
@@ -61523,10 +61555,23 @@ async function readCurrentBase(api) {
61523
61555
  const parsed = BaseSchema.safeParse(await readReleaseArchive(await api.downloadArtifact(SLUG, artifact.id)));
61524
61556
  if (!parsed.success) throw new Error("\u5E95\u5EA7\u5236\u54C1\u7248\u672C\u8BB0\u5F55\u65E0\u6548\uFF0C\u8BF7\u91CD\u65B0\u8FD0\u884C\u5E95\u5EA7\u6784\u5EFA");
61525
61557
  const release2 = parsed.data;
61526
- const matches = (source) => release2.source.cloudHost === source.cloudHost && release2.source.workflow === source.workflow;
61527
- if (release2.workflowCommit !== run.head_sha || !matches(current.source)) throw new Error("\u5E95\u5EA7\u5C1A\u672A\u6784\u5EFA\u5F53\u524D release \u6E90\u7801\uFF0C\u8BF7\u7B49\u5F85\u6216\u91CD\u65B0\u8FD0\u884C\u5E95\u5EA7\u6D41\u6C34\u7EBF");
61558
+ const matches = async (candidate) => {
61559
+ if (release2.source.workflow !== candidate.source.workflow) return false;
61560
+ if (release2.source.cloudHost === candidate.source.cloudHost) return true;
61561
+ if (release2.commit === candidate.commit) return false;
61562
+ const comparison = await api.getJsonStrict(`/repos/${SLUG}/compare/${release2.commit}...${candidate.commit}`);
61563
+ if (comparison.status !== "ahead" || !Array.isArray(comparison.files) || comparison.files.length >= 300 || comparison.files.some((file) => typeof file.filename !== "string" || !file.filename)) {
61564
+ throw new Error("\u65E0\u6CD5\u5B8C\u6574\u6BD4\u8F83\u5E95\u5EA7\u8F93\u5165\uFF0C\u8BF7\u91CD\u65B0\u8FD0\u884C\u5E95\u5EA7\u6D41\u6C34\u7EBF");
61565
+ }
61566
+ if (comparison.files.some((file) => file.filename === DOCKERFILE || file.previous_filename === DOCKERFILE)) return false;
61567
+ const recipe = await api.getJsonStrict(`/repos/${SLUG}/contents/${DOCKERFILE}?ref=${candidate.commit}`);
61568
+ if (recipe.type !== "file" || recipe.encoding !== "base64" || typeof recipe.content !== "string") throw new Error("\u8BFB\u4E0D\u5230\u5E95\u5EA7\u6784\u5EFA\u914D\u65B9");
61569
+ const inputs = dockerfileInputs(Buffer.from(recipe.content, "base64").toString("utf8"));
61570
+ return comparison.files.every((file) => ![file.filename, file.previous_filename].some((filename) => filename && [...inputs].some((input) => filename === input || filename.startsWith(input + "/"))));
61571
+ };
61572
+ if (release2.commit !== run.head_sha || release2.workflowCommit !== run.head_sha || !await matches(current)) throw new Error("\u5E95\u5EA7\u5C1A\u672A\u6784\u5EFA\u5F53\u524D release \u6E90\u7801\uFF0C\u8BF7\u7B49\u5F85\u6216\u91CD\u65B0\u8FD0\u884C\u5E95\u5EA7\u6D41\u6C34\u7EBF");
61528
61573
  const after = await currentSource(api);
61529
- if (!matches(after.source)) throw new Error("\u5E95\u5EA7\u6E90\u7801\u5728\u53D1\u5E03\u51C6\u5907\u671F\u95F4\u53D8\u5316\uFF0C\u8BF7\u7B49\u65B0\u6784\u5EFA\u6210\u529F\u540E\u518D\u53D1\u5E03");
61574
+ if ((after.source.cloudHost !== current.source.cloudHost || after.source.workflow !== current.source.workflow) && !await matches(after)) throw new Error("\u5E95\u5EA7\u6E90\u7801\u5728\u53D1\u5E03\u51C6\u5907\u671F\u95F4\u53D8\u5316\uFF0C\u8BF7\u7B49\u65B0\u6784\u5EFA\u6210\u529F\u540E\u518D\u53D1\u5E03");
61530
61575
  return release2;
61531
61576
  }
61532
61577
 
@@ -62939,9 +62984,22 @@ function buildDeployHandlers(deps) {
62939
62984
  run = historical ? selected?.environment === "integration" ? intRun : prodRun ?? run : prodTarget.run;
62940
62985
  }
62941
62986
  if (!historical && latestProductionRelease(file.releases) && (!api || github.status !== "authorized")) online = (await cachedCloud(personaId2, "production", run, unpublish, repo2 ? cloudPersonaIdOf(repo2.url) : personaId2)).online;
62987
+ let publisherFeishuAuth;
62988
+ if (scans.at(-1)?.manifest.connectors.some(isFeishuPublisherConnector)) {
62989
+ const query2 = async (environment2) => {
62990
+ try {
62991
+ return await deps.publisherFeishuAuth(repo2 ? cloudPersonaIdOf(repo2.url) : personaId2, environment2);
62992
+ } catch (e) {
62993
+ return { connected: false, error: e instanceof Error ? e.message : "\u98DE\u4E66\u6388\u6743\u72B6\u6001\u67E5\u8BE2\u5931\u8D25" };
62994
+ }
62995
+ };
62996
+ const [integration, production] = await Promise.all([query2("integration"), query2("production")]);
62997
+ publisherFeishuAuth = { integration, production };
62998
+ }
62942
62999
  return {
62943
63000
  personaId: personaId2,
62944
63001
  github,
63002
+ ...publisherFeishuAuth ? { publisherFeishuAuth } : {},
62945
63003
  targets,
62946
63004
  promotions: file.promotions,
62947
63005
  ...repo2 ? { repo: repo2 } : {},
@@ -63161,7 +63219,7 @@ function buildDeployHandlers(deps) {
63161
63219
  }
63162
63220
  if (args.kind === "connector") {
63163
63221
  const incoming = cliConnectorFromFinding(item);
63164
- const previous = scan.manifest.connectors.some((c2) => c2.name === incoming.name) ? void 0 : [...file.scans].reverse().find((s2) => s2.status === "done")?.manifest.connectors.find((c2) => c2.name === incoming.name && isFeishuBotConnector(c2));
63222
+ const previous = scan.manifest.connectors.some((c2) => c2.name === incoming.name) ? void 0 : [...file.scans].reverse().find((s2) => s2.status === "done")?.manifest.connectors.find((c2) => c2.name === incoming.name && (isFeishuBotConnector(c2) || isFeishuPublisherConnector(c2)));
63165
63223
  item = mergeConnector(previous, incoming);
63166
63224
  }
63167
63225
  if (args.kind === "package") item = await settlePackage(item);
@@ -63291,11 +63349,23 @@ function buildDeployHandlers(deps) {
63291
63349
  blockers.push(cloudEngine.tool === "claude" ? "\u8FD8\u6CA1\u9009\u4E91\u4E0A\u6A21\u578B\uFF08Claude \u7684\u4E91\u4E0A\u6A21\u578B\u4E0E\u672C\u673A\u5206\u5F00\u5B58\uFF09\u2014\u2014\u5728\u4E0A\u4E91\u9875\u300C\u5F15\u64CE\u4E0E\u6A21\u578B\u300D\u91CC\u9009\u4E00\u4E2A" : "\u8FD8\u6CA1\u9009\u6A21\u578B\uFF08\u5207\u5F15\u64CE\u65F6\u4F1A\u6E05\u7A7A\uFF09\u2014\u2014\u5728\u4E0A\u4E91\u9875\u300C\u5F15\u64CE\u4E0E\u6A21\u578B\u300D\u91CC\u9009\u4E00\u4E2A");
63292
63350
  }
63293
63351
  if (blockers.length > 0) throw invalid(`\u8FD8\u5DEE\uFF1A${blockers.join("\uFF1B")}`);
63352
+ const publisherUnionId = ctx?.principal.feishuUnionId;
63353
+ if (entry.manifest.connectors.some(isFeishuPublisherConnector) && !/^on_[A-Za-z0-9_-]+$/.test(publisherUnionId ?? "")) {
63354
+ throw invalid("\u4F7F\u7528\u53D1\u5E03\u8005\u8D26\u53F7\u524D\uFF0C\u8BF7\u5148\u767B\u5F55\u98DE\u4E66");
63355
+ }
63356
+ if (entry.manifest.connectors.some(isFeishuPublisherConnector)) {
63357
+ const status = await deps.publisherFeishuAuth?.(cloudPersonaIdOf(repo2.url), "integration");
63358
+ if (!status?.connected) throw invalid("\u8BF7\u5148\u5728\u8FDE\u63A5\u5668\u533A\u5173\u8054\u53D1\u5E03\u8005\u7684\u6D4B\u8BD5\u73AF\u5883\u98DE\u4E66\u8D26\u53F7\uFF0C\u518D\u53D1\u5E03");
63359
+ }
63360
+ const manifest = { ...entry.manifest, connectors: entry.manifest.connectors.map((c2) => {
63361
+ const { publisherUnionId: _untrusted, ...connector } = c2;
63362
+ return isFeishuPublisherConnector(c2) ? { ...connector, publisherUnionId } : connector;
63363
+ }) };
63294
63364
  await configureTestIdentity(api, repoSlug(repo2.url));
63295
63365
  if (await deps.claimPublisher(cloudPersonaIdOf(repo2.url), "integration") === "taken") throw invalid("\u6D4B\u8BD5\u73AF\u5883\u91CC\u7684\u8FD9\u4E2A\u540D\u5B57\u5DF2\u7531\u522B\u4EBA\u53D1\u5E03");
63296
63366
  const releaseId = (0, import_node_crypto14.randomUUID)();
63297
63367
  try {
63298
- const result = await release(deps.exec, api, { dir, now: deps.now, auth, manifest: entry.manifest, onPrepared: async (head) => {
63368
+ const result = await release(deps.exec, api, { dir, now: deps.now, auth, manifest, onPrepared: async (head) => {
63299
63369
  const latest2 = await readHistory(dir);
63300
63370
  await writeScanFile(dir, { ...latest2, releases: [...latest2.releases, { id: releaseId, environment: "integration", head, contentHead: entry.head, scanId: entry.id, at: deps.now(), pushed: false }] });
63301
63371
  } });
@@ -63440,6 +63510,7 @@ function buildDeployHandlers(deps) {
63440
63510
  const scan = file.scans.find((s2) => s2.id === record4.scanId);
63441
63511
  if (!scan || scan.status !== "done") throw invalid("\u627E\u4E0D\u5230\u672C\u6B21\u6D4B\u8BD5\u7684\u5B8C\u6574\u626B\u63CF\uFF0C\u8BF7\u91CD\u65B0\u626B\u63CF");
63442
63512
  const missing = requiredEnvNames(scan.manifest).filter((name) => !names.find((s2) => s2.env === name)?.setAt);
63513
+ if (scan.manifest.connectors.some(isFeishuPublisherConnector) && !(await deps.publisherFeishuAuth?.(cloudPersonaIdOf(repo2.url), "production"))?.connected) throw invalid("\u8BF7\u5148\u5728\u8FDE\u63A5\u5668\u533A\u5173\u8054\u53D1\u5E03\u8005\u7684\u7EBF\u4E0A\u73AF\u5883\u98DE\u4E66\u8D26\u53F7\uFF0C\u518D\u4E0A\u7EBF");
63443
63514
  if (missing.length || engineAuthState(names) === "partial") throw invalid("\u7EBF\u4E0A\u73AF\u5883\u51ED\u636E\u5C1A\u672A\u586B\u9F50\uFF1A" + (missing.join(" / ") || ENGINE_AUTH_PARTIAL_BLOCKER));
63444
63515
  const reuse = old && old.phase !== "failed" && (recovering || !old.verified || old.verified.verification.fingerprint === record4.verified.verification.fingerprint);
63445
63516
  if (old && !reuse && old.phase === "prepared") {
@@ -73942,17 +74013,17 @@ function buildCloudConnectorsHandlers(deps) {
73942
74013
  if (!loginPass) throw new ClawdError(ERROR_CODES.FEISHU_LOGIN_REQUIRED, "FEISHU_LOGIN_REQUIRED: \u8FD8\u6CA1\u767B\u5F55\u98DE\u4E66\uFF0C\u4E91\u4E0A persona \u7684\u8FDE\u63A5\u5668\u7528\u4E0D\u4E86");
73943
74014
  return { loginPass };
73944
74015
  }
73945
- async function personalConnectors(personaId2) {
74016
+ async function personalConnectors(personaId2, publisherUnionId) {
73946
74017
  const persona = deps.getPersona(personaId2);
73947
74018
  if (!persona) throw new ClawdError(ERROR_CODES.PERSONA_NOT_FOUND, `PERSONA_NOT_FOUND: \u6CA1\u6709\u8FD9\u4E2A persona\uFF08${personaId2}\uFF09`);
73948
74019
  if (!persona.cloud) throw invalid2(`${personaId2} \u4E0D\u662F\u4E91\u4E0A persona\uFF0C\u6CA1\u6709\u8FDE\u63A5\u5668\u533A`);
73949
74020
  const all = await deps.gatewayConnectors(persona.cloud.personaId, persona.cloud.gatewayUrl);
73950
- return { environment: persona.cloud.environment ?? "production", gatewayPersonaId: persona.cloud.personaId, connectors: all.filter((c2) => c2.credentialSource === "personal") };
74021
+ return { environment: persona.cloud.environment ?? "production", gatewayPersonaId: persona.cloud.personaId, connectors: all.flatMap((c2) => c2.credentialSource === "personal" ? [c2] : isFeishuPublisherConnector(c2) && publisherUnionId && c2.publisherUnionId === publisherUnionId ? [{ ...c2, credentialSource: "personal" }] : []) };
73951
74022
  }
73952
74023
  const list = async (frame, _client, ctx) => {
73953
74024
  ensureOwner6(ctx);
73954
74025
  const { personaId: personaId2 } = parseArgs2(CloudConnectorsListArgsSchema, frame, "cloud:connectors:list");
73955
- const { gatewayPersonaId, connectors, environment } = await personalConnectors(personaId2);
74026
+ const { gatewayPersonaId, connectors, environment } = await personalConnectors(personaId2, ctx?.principal.feishuUnionId);
73956
74027
  if (connectors.length === 0) return { response: { type: "cloud:connectors:list:ok", connectors: [] } };
73957
74028
  const login = requireLogin(environment);
73958
74029
  const r2 = await (deps.centralForEnvironment?.(environment) ?? deps.central).mine({ ...login, personaId: gatewayPersonaId, connectors });
@@ -74297,7 +74368,7 @@ function computeMethodAccess(args) {
74297
74368
  }
74298
74369
 
74299
74370
  // src/version.ts
74300
- var version = "0.2.647".length > 0 ? "0.2.647" : "dev";
74371
+ var version = "0.2.649".length > 0 ? "0.2.649" : "dev";
74301
74372
 
74302
74373
  // src/cli-probe/probe.ts
74303
74374
  var fs85 = __toESM(require("fs"), 1);
@@ -76836,6 +76907,7 @@ async function startDaemon(config) {
76836
76907
  contactStore.load();
76837
76908
  const serverKeyStore = new ServerKeyStore(config.dataDir);
76838
76909
  const buildConnectAuthDeps = () => ({
76910
+ ownerFeishuUnionId,
76839
76911
  isOwnerToken: (x2) => resolvedAuthToken != null && constantTimeEqual(x2, resolvedAuthToken),
76840
76912
  ownerPrincipalId,
76841
76913
  ownerDisplayName,
@@ -77957,6 +78029,18 @@ async function startDaemon(config) {
77957
78029
  const persona = list.find((p3) => p3.personaId === personaId2);
77958
78030
  return { online: persona !== void 0, ...persona?.image ? { image: persona.image } : {} };
77959
78031
  },
78032
+ publisherFeishuAuth: async (personaId2, environment) => {
78033
+ const loginPass = requireEnvironmentIdentity(environmentStores, environment).loginPass;
78034
+ const result = await centralConnectorsMine({
78035
+ api: targetApi(environment),
78036
+ loginPass,
78037
+ personaId: personaId2,
78038
+ connectors: [{ name: "feishu", id: "feishu", kind: "proxy", runner: "cli", protocol: "lark-sidecar", credentialSource: "personal", auth: "oauth", fields: [] }]
78039
+ });
78040
+ const status = result.connectors.find((c2) => !!c2 && typeof c2 === "object" && "name" in c2 && c2.name === "feishu");
78041
+ if (!status) throw new Error("\u4E2D\u5FC3\u672A\u8FD4\u56DE\u53D1\u5E03\u8005\u98DE\u4E66\u6388\u6743\u72B6\u6001");
78042
+ return { connected: status.status === "connected", ...status.authUrl ? { authUrl: status.authUrl } : {} };
78043
+ },
77960
78044
  testLoginPass: async () => {
77961
78045
  const loginPass = requireEnvironmentIdentity(environmentStores, "integration").loginPass;
77962
78046
  const credentials = await centralGetApiKey({ api: targetApi("integration"), loginPass });