@team-ai/teamai-cli 0.30.4 → 0.30.5

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/cli.js CHANGED
@@ -61601,6 +61601,7 @@ __export(local_agent_exports, {
61601
61601
  import fs35 from "fs";
61602
61602
  import os9 from "os";
61603
61603
  import path76 from "path";
61604
+ import { createHash as createHash10 } from "crypto";
61604
61605
  import { execFile as execFile4 } from "child_process";
61605
61606
  import { promisify as promisify3 } from "util";
61606
61607
  function modelAgentKind(tool) {
@@ -61640,6 +61641,65 @@ async function acquireLocalAgentLock(waitMs = 0) {
61640
61641
  function getConfigPath() {
61641
61642
  return path76.join(getLocalAgentHome(), CONFIG_FILE);
61642
61643
  }
61644
+ function credentialKey(context) {
61645
+ const agentType = normalizeAgentType(context.tool ?? "workbuddy");
61646
+ return `${agentType}:${resolveLocalAgentId(context)}`;
61647
+ }
61648
+ function credentialEndpointDir(endpoint) {
61649
+ const endpointDigest = createHash10("sha256").update(normalizeEndpoint(endpoint)).digest("hex").slice(0, 16);
61650
+ return path76.join("credentials", endpointDigest);
61651
+ }
61652
+ function credentialRelativePath(endpoint, key) {
61653
+ const digest = createHash10("sha256").update(key).digest("hex");
61654
+ return path76.join(credentialEndpointDir(endpoint), `${digest}.token`);
61655
+ }
61656
+ async function readAgentCredential(config, context) {
61657
+ const entry = context ? config.agentCredentials?.[credentialKey(context)] : void 0;
61658
+ const candidate = entry ?? (!context ? Object.values(config.agentCredentials ?? {})[0] : void 0);
61659
+ if (candidate) {
61660
+ const credentialRoot = path76.join(getLocalAgentHome(), "credentials");
61661
+ const credentialPath = path76.resolve(getLocalAgentHome(), candidate.file);
61662
+ if (!credentialPath.startsWith(credentialRoot + path76.sep)) {
61663
+ throw new Error("HTTP local agent credential path is outside its credential directory.");
61664
+ }
61665
+ const value = (await readFileSafe(credentialPath))?.trim();
61666
+ if (value) return value;
61667
+ throw new Error(`HTTP local agent credential is missing for ${candidate.agentType}. Re-run HTTP setup for that agent.`);
61668
+ }
61669
+ const legacy = config.token?.trim();
61670
+ if (legacy) return legacy;
61671
+ if (context && Object.keys(config.agentCredentials ?? {}).length > 0) {
61672
+ throw new Error(
61673
+ `No HTTP credential is configured for ${normalizeAgentType(context.tool ?? "workbuddy")}. Re-run HTTP setup with this agent and its token.`
61674
+ );
61675
+ }
61676
+ return void 0;
61677
+ }
61678
+ async function writeAgentCredential(config, context, token) {
61679
+ const key = credentialKey(context);
61680
+ const tool = context.tool ?? "workbuddy";
61681
+ const agentType = normalizeAgentType(tool);
61682
+ const localAgentId = resolveLocalAgentId(context);
61683
+ const file = credentialRelativePath(config.endpoint, key);
61684
+ await ensureDir(path76.join(getLocalAgentHome(), path76.dirname(file)));
61685
+ await writeTokenFile(path76.join(getLocalAgentHome(), file), token);
61686
+ config.agentCredentials = {
61687
+ ...config.agentCredentials,
61688
+ [key]: {
61689
+ tool,
61690
+ agentType,
61691
+ localAgentId,
61692
+ file,
61693
+ createdAt: config.agentCredentials?.[key]?.createdAt ?? (/* @__PURE__ */ new Date()).toISOString()
61694
+ }
61695
+ };
61696
+ return key;
61697
+ }
61698
+ async function promoteLegacyCredential(config, context) {
61699
+ if (!config.token || config.agentCredentials?.[credentialKey(context)]) return;
61700
+ await writeAgentCredential(config, context, config.token);
61701
+ await saveLocalAgentConfig(config);
61702
+ }
61643
61703
  function getManifestPath() {
61644
61704
  return path76.join(getLocalAgentHome(), MANIFEST_FILE);
61645
61705
  }
@@ -61821,6 +61881,8 @@ function mergeWorkspaceBindings(existing2, incoming, canonicalKey) {
61821
61881
  }
61822
61882
  const base = existingRank >= incomingRank ? { ...existing2 } : { ...incoming };
61823
61883
  base.enrolledAt ??= existing2.enrolledAt ?? incoming.enrolledAt;
61884
+ const agentKeys = [.../* @__PURE__ */ new Set([...existing2.agentKeys ?? [], ...incoming.agentKeys ?? []])];
61885
+ if (agentKeys.length > 0) base.agentKeys = agentKeys;
61824
61886
  if (!base.ideType) base.ideType = existing2.ideType ?? incoming.ideType;
61825
61887
  return base;
61826
61888
  }
@@ -62085,12 +62147,13 @@ async function workspaceCacheGitignore(workspacePath, repoPath) {
62085
62147
  const file = path76.join(teamaiDir, ".gitignore");
62086
62148
  return await readFileSafe(file) === WORKSPACE_CACHE_GITIGNORE ? file : null;
62087
62149
  }
62088
- function authHeaders5(config, json = true) {
62150
+ async function authHeaders5(config, json = true, context) {
62089
62151
  const headers = {};
62090
62152
  if (json) headers["Content-Type"] = "application/json";
62091
- if (config.token) {
62092
- headers.Authorization = `Bearer ${config.token}`;
62093
- headers["X-API-Token"] = config.token;
62153
+ const token = await readAgentCredential(config, context);
62154
+ if (token) {
62155
+ headers.Authorization = `Bearer ${token}`;
62156
+ headers["X-API-Token"] = token;
62094
62157
  }
62095
62158
  return headers;
62096
62159
  }
@@ -62098,7 +62161,7 @@ async function localAgentFetch(config, tag, route, init3, opts) {
62098
62161
  const method = init3?.method ?? "GET";
62099
62162
  const url = `${config.endpoint}${resolveRoute(config, route)}`;
62100
62163
  const headers = {
62101
- ...authHeaders5(config, init3?.body !== void 0),
62164
+ ...await authHeaders5(config, init3?.body !== void 0, opts?.context),
62102
62165
  ...init3?.headers
62103
62166
  };
62104
62167
  logHttpRequest(tag, method, url, headers, init3?.body);
@@ -62134,12 +62197,13 @@ async function appendErrorLog(entry) {
62134
62197
  } catch {
62135
62198
  }
62136
62199
  }
62137
- async function fetchUserProjects(config) {
62200
+ async function fetchUserProjects(config, context) {
62138
62201
  const response = await localAgentFetch(
62139
62202
  config,
62140
62203
  localAgentTag({}),
62141
62204
  "projects",
62142
- { method: "GET" }
62205
+ { method: "GET" },
62206
+ { context }
62143
62207
  );
62144
62208
  return response.projects ?? [];
62145
62209
  }
@@ -62181,8 +62245,14 @@ async function execPluginCommand(cmd, timeoutMs) {
62181
62245
  );
62182
62246
  });
62183
62247
  }
62184
- async function fetchPluginConfig(config, tag) {
62185
- return localAgentFetch(config, tag, "getConfig", { method: "GET" }, { redactResponseLog: true });
62248
+ async function fetchPluginConfig(config, tag, context) {
62249
+ return localAgentFetch(
62250
+ config,
62251
+ tag,
62252
+ "getConfig",
62253
+ { method: "GET" },
62254
+ { redactResponseLog: true, context }
62255
+ );
62186
62256
  }
62187
62257
  function getPluginPullStatePath() {
62188
62258
  return path76.join(getLocalAgentHome(), "plugin-pull.json");
@@ -62220,7 +62290,16 @@ async function maybeReconcilePlugins(context) {
62220
62290
  const child = spawn13(
62221
62291
  process.execPath,
62222
62292
  [process.argv[1], "source", "reconcile-plugins"],
62223
- { detached: true, windowsHide: true, stdio: "ignore", env: { ...process.env, TEAMAI_PLUGIN_LOCAL_AGENT_ID: localAgentId } }
62293
+ {
62294
+ detached: true,
62295
+ windowsHide: true,
62296
+ stdio: "ignore",
62297
+ env: {
62298
+ ...process.env,
62299
+ TEAMAI_PLUGIN_LOCAL_AGENT_ID: localAgentId,
62300
+ TEAMAI_PLUGIN_TOOL: tool
62301
+ }
62302
+ }
62224
62303
  );
62225
62304
  child.unref();
62226
62305
  } catch (e) {
@@ -62236,7 +62315,8 @@ async function runPluginReconcileWorker() {
62236
62315
  const tag = "[local-agent] [plugin-reconcile]";
62237
62316
  const statePath = getPluginPullStatePath();
62238
62317
  try {
62239
- const resp = await fetchPluginConfig(config, tag);
62318
+ const context = { tool: process.env.TEAMAI_PLUGIN_TOOL ?? "workbuddy" };
62319
+ const resp = await fetchPluginConfig(config, tag, context);
62240
62320
  const { vars, plugins } = parseGetConfig(resp);
62241
62321
  const declaredSlugs = plugins.length ? ` [${plugins.map((p2) => p2.slug).join(", ")}]` : "";
62242
62322
  log.debug(`${tag} get-config: ${plugins.length} plugin(s) declared${declaredSlugs}`);
@@ -62317,10 +62397,20 @@ async function persistWorkspaceBinding(config, cwd, resolvedPath, projectId, pro
62317
62397
  }
62318
62398
  await saveLocalAgentConfig(config);
62319
62399
  }
62320
- async function enrollWorkspace(config, resolvedPath) {
62400
+ async function enrollWorkspace(config, resolvedPath, agentKeys = []) {
62321
62401
  const enrolledAt = (/* @__PURE__ */ new Date()).toISOString();
62322
62402
  const binding = config.workspaceBindings[resolvedPath];
62323
- config.workspaceBindings[resolvedPath] = binding ? { ...binding, enrolledAt: binding.enrolledAt ?? enrolledAt } : { projectId: 0, boundAt: enrolledAt, enrolledAt };
62403
+ const mergedAgentKeys = [.../* @__PURE__ */ new Set([...binding?.agentKeys ?? [], ...agentKeys])];
62404
+ config.workspaceBindings[resolvedPath] = binding ? {
62405
+ ...binding,
62406
+ enrolledAt: binding.enrolledAt ?? enrolledAt,
62407
+ ...mergedAgentKeys.length > 0 ? { agentKeys: mergedAgentKeys } : {}
62408
+ } : {
62409
+ projectId: 0,
62410
+ boundAt: enrolledAt,
62411
+ enrolledAt,
62412
+ ...mergedAgentKeys.length > 0 ? { agentKeys: mergedAgentKeys } : {}
62413
+ };
62324
62414
  }
62325
62415
  async function inheritWorktreeBinding(config, cwd, resolvedPath) {
62326
62416
  const anchors = await resolveAnchors(cwd);
@@ -62358,7 +62448,7 @@ async function bindWorkspaceToProject(workspacePath, projectId) {
62358
62448
  log.success(`\u5DF2\u5C06\u5DE5\u4F5C\u533A\u7ED1\u5B9A\u5230\u9879\u76EE\uFF1A${project.name} [id=${project.id}]`);
62359
62449
  return binding;
62360
62450
  }
62361
- async function ensureWorkspaceBinding(config, workspacePath, sessionId, cwd) {
62451
+ async function ensureWorkspaceBinding(config, workspacePath, agentContext, sessionId, cwd) {
62362
62452
  if (!isWorkspaceEnrolled(config, workspacePath)) return;
62363
62453
  if (hasWorkspaceBindingDecision(config.workspaceBindings[workspacePath])) return;
62364
62454
  if (await inheritWorktreeBinding(config, cwd, workspacePath)) return;
@@ -62371,7 +62461,7 @@ async function ensureWorkspaceBinding(config, workspacePath, sessionId, cwd) {
62371
62461
  }
62372
62462
  let projects;
62373
62463
  try {
62374
- projects = await fetchUserProjects(config);
62464
+ projects = await fetchUserProjects(config, agentContext);
62375
62465
  } catch (e) {
62376
62466
  log.debug(`local-agent: failed to load user projects: ${e.message}`);
62377
62467
  return;
@@ -62407,7 +62497,7 @@ function isBindPromptTool(tool) {
62407
62497
  const kind = modelAgentKind(tool);
62408
62498
  return kind === "codebuddy" || kind === "workbuddy";
62409
62499
  }
62410
- async function emitBindingHint(config, workspacePath, sessionId, cwd) {
62500
+ async function emitBindingHint(config, workspacePath, agentContext, sessionId, cwd) {
62411
62501
  if (!isWorkspaceEnrolled(config, workspacePath)) return;
62412
62502
  if (hasWorkspaceBindingDecision(config.workspaceBindings[workspacePath])) return;
62413
62503
  if (await inheritWorktreeBinding(config, cwd, workspacePath)) return;
@@ -62420,7 +62510,7 @@ async function emitBindingHint(config, workspacePath, sessionId, cwd) {
62420
62510
  }
62421
62511
  let projects;
62422
62512
  try {
62423
- projects = await fetchUserProjects(config);
62513
+ projects = await fetchUserProjects(config, agentContext);
62424
62514
  } catch {
62425
62515
  return;
62426
62516
  }
@@ -62634,14 +62724,19 @@ function stampWorkspaceTool(config, currentPath, tool) {
62634
62724
  const binding = config.workspaceBindings[currentPath];
62635
62725
  if (!binding?.enrolledAt) return false;
62636
62726
  const normalized = normalizeAgentType(tool);
62637
- if (binding.ideType === normalized) return false;
62727
+ const key = credentialKey({ tool });
62728
+ const agentKeys = binding.agentKeys ?? [];
62729
+ if (binding.ideType === normalized && agentKeys.includes(key)) return false;
62638
62730
  binding.ideType = normalized;
62731
+ binding.agentKeys = [.../* @__PURE__ */ new Set([...agentKeys, key])];
62639
62732
  return true;
62640
62733
  }
62641
62734
  function selectToolWorkspaces(config, currentPath, currentTool) {
62642
62735
  return Object.keys(config.workspaceBindings).filter((wsPath) => {
62643
62736
  const b2 = config.workspaceBindings[wsPath];
62644
62737
  if (!b2.enrolledAt) return false;
62738
+ const key = credentialKey({ tool: currentTool });
62739
+ if (b2.agentKeys?.includes(key)) return true;
62645
62740
  const wsTool = b2.ideType ?? (wsPath === currentPath ? currentTool : void 0);
62646
62741
  return wsTool === currentTool;
62647
62742
  });
@@ -63399,7 +63494,7 @@ async function hookDeliveryProblem(teamConfig, localConfig2, tool, block) {
63399
63494
  const length = parts.filter(Boolean).join("\n\n").length;
63400
63495
  return length > hook.limit ? `${tool} cannot load this project's instructions: with the HTTP prompts they are ${length} characters, over the ${hook.limit}-character limit of its prompt section, so ${tool} skips them. Shorten the prompts for this project.` : null;
63401
63496
  }
63402
- async function ackCommand(config, tag, command, status2, version2, error2) {
63497
+ async function ackCommand(config, tag, context, command, status2, version2, error2) {
63403
63498
  await localAgentFetch(config, tag, "ack", {
63404
63499
  method: "POST",
63405
63500
  body: JSON.stringify({
@@ -63409,7 +63504,7 @@ async function ackCommand(config, tag, command, status2, version2, error2) {
63409
63504
  error: error2 ?? "",
63410
63505
  version: version2
63411
63506
  })
63412
- });
63507
+ }, { context });
63413
63508
  }
63414
63509
  function requireModelString(value, field) {
63415
63510
  if (typeof value !== "string" || !value.trim()) {
@@ -64386,7 +64481,7 @@ async function processCommands(config, commands, context) {
64386
64481
  }
64387
64482
  try {
64388
64483
  const version2 = await executeCommand(config, command, context);
64389
- await ackCommand(config, tag, command, "success", version2);
64484
+ await ackCommand(config, tag, context, command, "success", version2);
64390
64485
  if (command.type === "apply_model_config") modelConfigApplied = true;
64391
64486
  log.debug(`${tag} command ${command.id} (${command.type ?? ""}) succeeded`);
64392
64487
  if (command.type === "uninstall_teamai") {
@@ -64397,7 +64492,7 @@ async function processCommands(config, commands, context) {
64397
64492
  const error2 = e.message;
64398
64493
  log.error(`${tag} command ${command.id} failed: ${error2}`);
64399
64494
  try {
64400
- await ackCommand(config, tag, command, "failed", void 0, error2);
64495
+ await ackCommand(config, tag, context, command, "failed", void 0, error2);
64401
64496
  } catch (ackError) {
64402
64497
  log.debug(`${tag} failed to ack command ${command.id}: ${ackError.message}`);
64403
64498
  }
@@ -64428,10 +64523,10 @@ async function syncLocalAgent(context) {
64428
64523
  if (workspacePath && isWorkspaceEnrolled(config, workspacePath)) {
64429
64524
  const sid = context.event?.sessionId;
64430
64525
  if (context.event?.type === "session_start") {
64431
- await ensureWorkspaceBinding(config, workspacePath, sid, context.cwd);
64526
+ await ensureWorkspaceBinding(config, workspacePath, context, sid, context.cwd);
64432
64527
  }
64433
64528
  if (context.event?.type === "prompt_submit") {
64434
- await emitBindingHint(config, workspacePath, sid, context.cwd);
64529
+ await emitBindingHint(config, workspacePath, context, sid, context.cwd);
64435
64530
  }
64436
64531
  }
64437
64532
  }
@@ -64460,7 +64555,8 @@ async function syncLocalAgent(context) {
64460
64555
  await localAgentFetch(config, tag, "report", {
64461
64556
  method: "POST",
64462
64557
  body: JSON.stringify(reportPayload)
64463
- });
64558
+ }, { context });
64559
+ await promoteLegacyCredential(config, context);
64464
64560
  log.debug(`${tag} report OK`);
64465
64561
  }
64466
64562
  const syncPayload = await buildSyncPayload(config, context);
@@ -64469,7 +64565,7 @@ async function syncLocalAgent(context) {
64469
64565
  tag,
64470
64566
  "sync",
64471
64567
  { method: "POST", body: JSON.stringify(syncPayload) },
64472
- { redactResponseLog: true }
64568
+ { redactResponseLog: true, context }
64473
64569
  );
64474
64570
  const cmds = syncResponse.cmds;
64475
64571
  const commands = cmds && cmds.length > 0 ? cmds : syncResponse.commands ?? [];
@@ -64482,7 +64578,7 @@ async function syncLocalAgent(context) {
64482
64578
  await localAgentFetch(config, tag, "report", {
64483
64579
  method: "POST",
64484
64580
  body: JSON.stringify(reportPayload)
64485
- });
64581
+ }, { context });
64486
64582
  log.debug(`${tag} model config report OK`);
64487
64583
  }
64488
64584
  }
@@ -64611,8 +64707,16 @@ async function reportAndSyncFromHook(stdin, tool) {
64611
64707
  }
64612
64708
  }
64613
64709
  async function writeTokenFile(tokenPath, token) {
64614
- await fs35.promises.writeFile(tokenPath, token + "\n", { mode: 384 });
64615
- await fs35.promises.chmod(tokenPath, 384);
64710
+ await ensureDir(path76.dirname(tokenPath));
64711
+ const tmp = `${tokenPath}.${process.pid}.${createHash10("sha256").update(`${tokenPath}:${Date.now()}:${Math.random()}`).digest("hex").slice(0, 12)}.tmp`;
64712
+ try {
64713
+ await fs35.promises.writeFile(tmp, token + "\n", { mode: 384, flag: "wx" });
64714
+ await fs35.promises.chmod(tmp, 384);
64715
+ await fs35.promises.rename(tmp, tokenPath);
64716
+ } catch (error2) {
64717
+ await fs35.promises.rm(tmp, { force: true }).catch(() => void 0);
64718
+ throw error2;
64719
+ }
64616
64720
  }
64617
64721
  async function initLocalAgentHttp(options2) {
64618
64722
  const endpoint = normalizeEndpoint(options2.endpoint);
@@ -64623,20 +64727,45 @@ async function initLocalAgentHttp(options2) {
64623
64727
  if (existing2 && !options2.force && normalizeEndpoint(existing2.endpoint) !== endpoint) {
64624
64728
  throw new Error("HTTP local agent is initialized with another endpoint. Re-run with --force to overwrite.");
64625
64729
  }
64730
+ const requestedAgents = [...new Set((options2.filterAgents ?? []).map((agent) => agent.trim()).filter(Boolean))];
64731
+ if (options2.token?.startsWith("sk-") && requestedAgents.length !== 1) {
64732
+ throw new Error("A ClawPro instance token requires exactly one --agent.");
64733
+ }
64734
+ const sameEndpoint = Boolean(existing2 && normalizeEndpoint(existing2.endpoint) === endpoint);
64626
64735
  const config = {
64627
64736
  endpoint,
64628
- token: options2.token ?? existing2?.token,
64629
- createdAt: existing2?.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
64737
+ // A token without --agent keeps the legacy machine-wide behavior. An
64738
+ // agent-scoped setup writes a credential file below and must not replace it.
64739
+ token: requestedAgents.length !== 1 ? options2.token ?? (sameEndpoint ? existing2?.token : void 0) : sameEndpoint ? existing2?.token : void 0,
64740
+ agentCredentials: sameEndpoint ? existing2?.agentCredentials : void 0,
64741
+ createdAt: sameEndpoint ? existing2?.createdAt ?? (/* @__PURE__ */ new Date()).toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
64630
64742
  workspaceStateVersion: 1,
64631
- workspaceBindings: existing2?.workspaceBindings ?? {},
64632
- userGroupId: existing2?.userGroupId,
64633
- userGroupName: existing2?.userGroupName
64634
- };
64743
+ workspaceBindings: sameEndpoint ? existing2?.workspaceBindings ?? {} : {},
64744
+ userGroupId: sameEndpoint ? existing2?.userGroupId : void 0,
64745
+ userGroupName: sameEndpoint ? existing2?.userGroupName : void 0,
64746
+ routes: sameEndpoint ? existing2?.routes : void 0
64747
+ };
64748
+ const configuredKeys = [];
64749
+ if (requestedAgents.length === 1 && options2.token) {
64750
+ configuredKeys.push(await writeAgentCredential(
64751
+ config,
64752
+ { tool: requestedAgents[0] },
64753
+ options2.token
64754
+ ));
64755
+ } else if (requestedAgents.length === 1) {
64756
+ const key = credentialKey({ tool: requestedAgents[0] });
64757
+ if (config.agentCredentials?.[key]) configuredKeys.push(key);
64758
+ }
64635
64759
  const workspacePath = await resolveWorkspacePath(options2.workspacePath ?? process.cwd());
64636
- if (workspacePath) await enrollWorkspace(config, workspacePath);
64760
+ if (workspacePath) await enrollWorkspace(config, workspacePath, configuredKeys);
64637
64761
  await ensureDir(getLocalAgentHome());
64638
64762
  await saveLocalAgentConfig(config);
64639
- if (options2.token) {
64763
+ if (existing2 && !sameEndpoint) {
64764
+ await remove(path76.join(getLocalAgentHome(), credentialEndpointDir(existing2.endpoint))).catch((error2) => {
64765
+ log.warn(`Could not remove credentials for the previous HTTP endpoint: ${error2.message}`);
64766
+ });
64767
+ }
64768
+ if (options2.token && requestedAgents.length !== 1) {
64640
64769
  await writeTokenFile(getTokenPath(), options2.token);
64641
64770
  }
64642
64771
  const teamConfig = createLocalAgentTeamConfig(endpoint);
@@ -65242,7 +65371,7 @@ __export(git_exclude_delivered_exports, {
65242
65371
  describeUnreadableGitExcludeSetting: () => describeUnreadableGitExcludeSetting,
65243
65372
  reportDeliveredGitExclude: () => reportDeliveredGitExclude
65244
65373
  });
65245
- import { createHash as createHash10 } from "crypto";
65374
+ import { createHash as createHash11 } from "crypto";
65246
65375
  import path79 from "path";
65247
65376
  function createDeliveryRecorder() {
65248
65377
  const reports = /* @__PURE__ */ new Map();
@@ -65293,7 +65422,7 @@ function deliveredOwnerElsewhere(localConfig2) {
65293
65422
  }
65294
65423
  function partitionId(localConfig2) {
65295
65424
  const dataHome = getDataHome(localConfig2);
65296
- return /-([0-9a-f]{16})$/.exec(path79.basename(dataHome))?.[1] ?? createHash10("sha256").update(path79.resolve(dataHome)).digest("hex").slice(0, 16);
65425
+ return /-([0-9a-f]{16})$/.exec(path79.basename(dataHome))?.[1] ?? createHash11("sha256").update(path79.resolve(dataHome)).digest("hex").slice(0, 16);
65297
65426
  }
65298
65427
  function partitionOwner(localConfig2, name) {
65299
65428
  return {
@@ -66046,15 +66175,19 @@ async function initHttp(url, options2) {
66046
66175
  await reconcileHooksForInit(teamConfig, localConfig2, filterAgents2);
66047
66176
  const { initLocalAgentHttp: initLocalAgentHttp2 } = await Promise.resolve().then(() => (init_local_agent(), local_agent_exports));
66048
66177
  try {
66178
+ const explicitLocalAgentToken = options2.token?.trim() || process.env.TEAMAI_API_TOKEN?.trim() || process.env.TEAMAI_API_KEY?.trim();
66049
66179
  await initLocalAgentHttp2({
66050
66180
  endpoint: url,
66051
- token: options2.token,
66181
+ token: explicitLocalAgentToken || (filterAgents2 ? void 0 : apiKey),
66052
66182
  force: options2.force,
66053
66183
  filterAgents: filterAgents2,
66054
66184
  workspacePath: projectRoot ?? process.cwd()
66055
66185
  });
66056
66186
  } catch (e) {
66057
- log.debug(`Local agent init: ${e.message}`);
66187
+ log.error(`Local agent init failed: ${e.message}`);
66188
+ process.exitCode = 1;
66189
+ closePrompt();
66190
+ return;
66058
66191
  }
66059
66192
  await runInitScript(localConfig2, "postInit", options2.dryRun, true);
66060
66193
  log.success("teamai initialized (HTTP read-only)!");
@@ -67395,7 +67528,7 @@ __export(learnings_publish_exports, {
67395
67528
  publishLearningsMaintenance: () => publishLearningsMaintenance,
67396
67529
  publishQueuedLearnings: () => publishQueuedLearnings
67397
67530
  });
67398
- import { createHash as createHash11 } from "crypto";
67531
+ import { createHash as createHash12 } from "crypto";
67399
67532
  import path83 from "path";
67400
67533
  import fs40 from "fs";
67401
67534
  function commitMessageFor(username) {
@@ -67596,7 +67729,7 @@ async function hasUncommittedChange(checkout, rel) {
67596
67729
  }
67597
67730
  async function contentDigest(file) {
67598
67731
  if (!fs40.existsSync(file)) return null;
67599
- return createHash11("sha256").update(await fs40.promises.readFile(file)).digest("hex");
67732
+ return createHash12("sha256").update(await fs40.promises.readFile(file)).digest("hex");
67600
67733
  }
67601
67734
  async function maintenanceRecordsDir(checkout) {
67602
67735
  const gitPath2 = (await createGitWithBlockTimeout(checkout).raw(["rev-parse", "--git-path", "teamai-maintenance"])).trim();
@@ -71050,7 +71183,7 @@ var init_definition = __esm({
71050
71183
  });
71051
71184
 
71052
71185
  // src/scorers/cache.ts
71053
- import { createHash as createHash12 } from "crypto";
71186
+ import { createHash as createHash13 } from "crypto";
71054
71187
  import fs48 from "fs/promises";
71055
71188
  import path95 from "path";
71056
71189
  function cacheDir(config) {
@@ -71193,7 +71326,7 @@ async function syncScorerDefinitions(config, options2 = {}) {
71193
71326
  }
71194
71327
  const { name } = parsed.definition;
71195
71328
  if (parsed.definition.isolation === "verified") result.verified.push(relativePath);
71196
- const sourceHash = createHash12("sha256").update(content).digest("hex");
71329
+ const sourceHash = createHash13("sha256").update(content).digest("hex");
71197
71330
  const revision = await (reachable ??= remotelyReachableRevision(knowledgeRoot));
71198
71331
  const holds = await revisionHoldsSources(knowledgeRoot, revision, [{ path: relativePath, content }]);
71199
71332
  const previous = await withoutStaleTeamRevision(knowledgeRoot, await readCache2(config, name));
@@ -74358,7 +74491,7 @@ __export(cache_exports, {
74358
74491
  syncWorkflowDefinitions: () => syncWorkflowDefinitions,
74359
74492
  workflowsRunBy: () => workflowsRunBy
74360
74493
  });
74361
- import { createHash as createHash13 } from "crypto";
74494
+ import { createHash as createHash14 } from "crypto";
74362
74495
  import fs49 from "fs/promises";
74363
74496
  import os11 from "os";
74364
74497
  import path97 from "path";
@@ -74563,7 +74696,7 @@ async function syncWorkflowDefinitions(config, options2 = {}) {
74563
74696
  checked.push({ stem, relativePath, diagnostics: resolved2.diagnostics });
74564
74697
  continue;
74565
74698
  }
74566
- const hash2 = createHash13("sha256").update(content);
74699
+ const hash2 = createHash14("sha256").update(content);
74567
74700
  for (const source of resolved2.sources) {
74568
74701
  hash2.update("\0").update(source.path).update("\0").update(source.content);
74569
74702
  }
@@ -74700,7 +74833,7 @@ async function loadWorkflowTree(config, cached) {
74700
74833
  if (failed4) return { failed: failed4 };
74701
74834
  const teamRevision = cached.teamRevision !== void 0 && revisions.every((revision) => revision === cached.teamRevision) ? cached.teamRevision : void 0;
74702
74835
  if (hashes.length === 0) return { workflows, sourceHash: cached.sourceHash, ...teamRevision ? { teamRevision } : {} };
74703
- const hash2 = createHash13("sha256").update(cached.sourceHash);
74836
+ const hash2 = createHash14("sha256").update(cached.sourceHash);
74704
74837
  for (const [name, sourceHash] of hashes.sort(([left], [right]) => left.localeCompare(right))) {
74705
74838
  hash2.update("\0").update(name).update("\0").update(sourceHash);
74706
74839
  }
@@ -77195,7 +77328,7 @@ __export(team_push_exports, {
77195
77328
  withDroppedRollouts: () => withDroppedRollouts
77196
77329
  });
77197
77330
  import fs55 from "fs";
77198
- import { createHash as createHash14 } from "crypto";
77331
+ import { createHash as createHash15 } from "crypto";
77199
77332
  import path105 from "path";
77200
77333
  async function readExistingStats(statsPath) {
77201
77334
  try {
@@ -77364,7 +77497,7 @@ function tokenDelta(cur, prev) {
77364
77497
  };
77365
77498
  }
77366
77499
  function segmentKey(transcript2) {
77367
- return createHash14("sha256").update(transcript2).digest("hex").slice(0, 16);
77500
+ return createHash15("sha256").update(transcript2).digest("hex").slice(0, 16);
77368
77501
  }
77369
77502
  function reportedSegments(entry) {
77370
77503
  const segments2 = {};
@@ -78236,7 +78369,7 @@ var init_delivery_schema = __esm({
78236
78369
  });
78237
78370
 
78238
78371
  // src/workflow/snapshot.ts
78239
- import { createHash as createHash15 } from "crypto";
78372
+ import { createHash as createHash16 } from "crypto";
78240
78373
  import fs56 from "fs";
78241
78374
  import path106 from "path";
78242
78375
  function withCommitIds(schema) {
@@ -78253,7 +78386,7 @@ function snapshotText(snapshot) {
78253
78386
  `;
78254
78387
  }
78255
78388
  function definitionHash(definition, workflows = {}) {
78256
- return createHash15("sha256").update(canonicalJson2({ definition, workflows })).digest("hex");
78389
+ return createHash16("sha256").update(canonicalJson2({ definition, workflows })).digest("hex");
78257
78390
  }
78258
78391
  function snapshotBody(snapshot) {
78259
78392
  const { snapshot: _format, run: _run, owner: _owner, ownedAt: _ownedAt, stateRevision: _revision, write: _write, ...body } = snapshot;
@@ -79216,7 +79349,7 @@ var init_records = __esm({
79216
79349
  });
79217
79350
 
79218
79351
  // src/scorers/label.ts
79219
- import { createHash as createHash16 } from "crypto";
79352
+ import { createHash as createHash17 } from "crypto";
79220
79353
  function sumUsage(first2, second) {
79221
79354
  if (!first2 || !second) return first2 ?? second;
79222
79355
  const tokens = (left, right) => left === void 0 && right === void 0 ? void 0 : (left ?? 0) + (right ?? 0);
@@ -79244,10 +79377,10 @@ function labelKey(label) {
79244
79377
  return canonicalJson2({ scorer: label.scorer, sourceHash: label.rubric.sourceHash, subject: label.subject, judge: label.judge.kind });
79245
79378
  }
79246
79379
  function labelId(label) {
79247
- return createHash16("sha256").update(labelKey(label)).digest("hex");
79380
+ return createHash17("sha256").update(labelKey(label)).digest("hex");
79248
79381
  }
79249
79382
  function labelVersion(label) {
79250
- return createHash16("sha256").update(canonicalJson2(label)).digest("hex");
79383
+ return createHash17("sha256").update(canonicalJson2(label)).digest("hex");
79251
79384
  }
79252
79385
  function newestLabels(labels) {
79253
79386
  const newest = /* @__PURE__ */ new Map();
@@ -88979,7 +89112,7 @@ var init_scrub = __esm({
88979
89112
  });
88980
89113
 
88981
89114
  // src/session-flow/agent-session.ts
88982
- import { createHash as createHash19 } from "crypto";
89115
+ import { createHash as createHash20 } from "crypto";
88983
89116
  import fs77 from "fs";
88984
89117
  import path129 from "path";
88985
89118
  function noAdapter(platform3, use, os25 = process.platform) {
@@ -89061,7 +89194,7 @@ async function writeCopyOnce(target, { session, sourcePlatform, cwd }) {
89061
89194
  } catch (e) {
89062
89195
  return { status: "failed", failure: { code: "invalid_workspace", cwd, message: messageOf(e) } };
89063
89196
  }
89064
- const key = createHash19("sha256").update(`${targetPlatform}\0${targetId}`).digest("hex").slice(0, 16);
89197
+ const key = createHash20("sha256").update(`${targetPlatform}\0${targetId}`).digest("hex").slice(0, 16);
89065
89198
  const lockPath = path129.join(getTeamaiHomeDir(), "locks", `session-copy-${key}.lock`);
89066
89199
  for (let attempt = 1; !await acquireLock(lockPath); attempt++) {
89067
89200
  if (attempt === COPY_LOCK_ATTEMPTS) {
@@ -90269,12 +90402,12 @@ var init_settings = __esm({
90269
90402
  });
90270
90403
 
90271
90404
  // src/scorers/entry.ts
90272
- import { createHash as createHash20 } from "crypto";
90405
+ import { createHash as createHash21 } from "crypto";
90273
90406
  function entryIdOf(scorer, subject) {
90274
- return `s${createHash20("sha256").update(canonicalJson2({ scorer, subject })).digest("hex").slice(0, 13)}`;
90407
+ return `s${createHash21("sha256").update(canonicalJson2({ scorer, subject })).digest("hex").slice(0, 13)}`;
90275
90408
  }
90276
90409
  function sessionEntryIdOf(scorer, sourceHash, subject) {
90277
- return `s${createHash20("sha256").update(canonicalJson2({ scorer, sourceHash, subject })).digest("hex").slice(0, 13)}`;
90410
+ return `s${createHash21("sha256").update(canonicalJson2({ scorer, sourceHash, subject })).digest("hex").slice(0, 13)}`;
90278
90411
  }
90279
90412
  function isLeaseRef(value) {
90280
90413
  return LEASE_REF.test(value);
@@ -90426,11 +90559,11 @@ var init_evidence = __esm({
90426
90559
  });
90427
90560
 
90428
90561
  // src/scorers/sampling.ts
90429
- import { createHash as createHash21 } from "crypto";
90562
+ import { createHash as createHash22 } from "crypto";
90430
90563
  function isSampled(scorer, subject, samplingRate) {
90431
90564
  if (samplingRate <= 0) return false;
90432
90565
  if (samplingRate >= 100) return true;
90433
- const digest = createHash21("sha256").update(canonicalJson2({ scorer, ...subject })).digest();
90566
+ const digest = createHash22("sha256").update(canonicalJson2({ scorer, ...subject })).digest();
90434
90567
  return digest.readUInt32BE(0) % 1e4 < samplingRate * 100;
90435
90568
  }
90436
90569
  var init_sampling = __esm({
@@ -91094,7 +91227,7 @@ var init_workspace = __esm({
91094
91227
  });
91095
91228
 
91096
91229
  // src/workflow/worktree.ts
91097
- import { createHash as createHash22 } from "crypto";
91230
+ import { createHash as createHash23 } from "crypto";
91098
91231
  import { execFile as execFile6, spawn as spawn6 } from "child_process";
91099
91232
  import fs83 from "fs/promises";
91100
91233
  import path137 from "path";
@@ -91155,7 +91288,7 @@ function git(cwd, args, options2) {
91155
91288
  }
91156
91289
  function worktreePath2(main2, branch) {
91157
91290
  const safe = branch.replace(/[^A-Za-z0-9]+/g, "-").replace(/^-|-$/g, "") || "step";
91158
- const hash2 = createHash22("sha256").update(branch).digest("hex").slice(0, 12);
91291
+ const hash2 = createHash23("sha256").update(branch).digest("hex").slice(0, 12);
91159
91292
  return path137.join(main2, ".teamai", "workflow-worktrees", `${safe}-${hash2}`);
91160
91293
  }
91161
91294
  function stepCheckout(active, branch) {
@@ -92020,7 +92153,7 @@ var init_scoring_evidence = __esm({
92020
92153
  import * as fs85 from "fs";
92021
92154
  import * as path139 from "path";
92022
92155
  import { execFileSync as execFileSync7 } from "child_process";
92023
- import { createHash as createHash23, randomUUID as randomUUID13 } from "crypto";
92156
+ import { createHash as createHash24, randomUUID as randomUUID13 } from "crypto";
92024
92157
  function utcNow() {
92025
92158
  return (/* @__PURE__ */ new Date()).toISOString();
92026
92159
  }
@@ -92152,7 +92285,7 @@ function assertNoSymlinkedAncestors(target, root) {
92152
92285
  }
92153
92286
  async function withSessionPublicationLock(repoRoot, fn) {
92154
92287
  const real = await fs85.promises.realpath(repoRoot).catch(() => path139.resolve(repoRoot));
92155
- const key = createHash23("sha256").update(real).digest("hex").slice(0, 16);
92288
+ const key = createHash24("sha256").update(real).digest("hex").slice(0, 16);
92156
92289
  const lockPath = path139.join(getTeamaiHomeDir(), "locks", `session-publish-${key}.lock`);
92157
92290
  for (let attempt = 1; !await acquireLock(lockPath); attempt++) {
92158
92291
  if (attempt === INDEX_LOCK_ATTEMPTS) return { status: "busy", lockPath };
@@ -92166,7 +92299,7 @@ async function withSessionPublicationLock(repoRoot, fn) {
92166
92299
  }
92167
92300
  async function withSessionIndexLock(repoRoot, fn) {
92168
92301
  const real = await fs85.promises.realpath(repoRoot).catch(() => path139.resolve(repoRoot));
92169
- const key = createHash23("sha256").update(path139.join(real, "sessions")).digest("hex").slice(0, 16);
92302
+ const key = createHash24("sha256").update(path139.join(real, "sessions")).digest("hex").slice(0, 16);
92170
92303
  const lockPath = path139.join(getTeamaiHomeDir(), "locks", `sessions-${key}.lock`);
92171
92304
  for (let attempt = 1; !await acquireLock(lockPath); attempt++) {
92172
92305
  if (attempt === INDEX_LOCK_ATTEMPTS) return { status: "busy", lockPath };
@@ -106305,7 +106438,7 @@ __export(source_exports, {
106305
106438
  sourceSyncWarnings: () => sourceSyncWarnings
106306
106439
  });
106307
106440
  import path158 from "path";
106308
- import { createHash as createHash24 } from "crypto";
106441
+ import { createHash as createHash25 } from "crypto";
106309
106442
  function sourceLockPath() {
106310
106443
  return path158.join(getUserHome(), ".teamai", ".source-lifecycle-lock");
106311
106444
  }
@@ -106345,7 +106478,7 @@ async function listSourceNames() {
106345
106478
  }
106346
106479
  }
106347
106480
  function getSourceRepoId(source) {
106348
- return createHash24("sha256").update(source.repo.trim()).digest("hex");
106481
+ return createHash25("sha256").update(source.repo.trim()).digest("hex");
106349
106482
  }
106350
106483
  function getSourceRepoCacheDir(source) {
106351
106484
  return path158.join(getUserHome(), ".teamai", "source-repos", getSourceRepoId(source));
@@ -106367,7 +106500,7 @@ async function listInstallationRecords() {
106367
106500
  return records2;
106368
106501
  }
106369
106502
  function getSourceManifestPath(sourceName, localConfig2) {
106370
- const installationId = createHash24("sha256").update(JSON.stringify([
106503
+ const installationId = createHash25("sha256").update(JSON.stringify([
106371
106504
  path158.resolve(resolveBaseDir(localConfig2)),
106372
106505
  path158.resolve(localConfig2.repo.localPath)
106373
106506
  ])).digest("hex");
@@ -106755,6 +106888,7 @@ async function sourceAddHttp(endpoint, options2) {
106755
106888
  endpoint: trimmed2,
106756
106889
  token: options2.token,
106757
106890
  force: true,
106891
+ filterAgents: normalizeAgentList(options2.agent),
106758
106892
  workspacePath: mainConfig?.projectRoot ?? process.cwd()
106759
106893
  });
106760
106894
  log.success(`HTTP source added (${trimmed2}).`);
@@ -107483,6 +107617,7 @@ var init_source2 = __esm({
107483
107617
  init_builtin_skills();
107484
107618
  init_home();
107485
107619
  init_update();
107620
+ init_known_agents();
107486
107621
  init_path_safety();
107487
107622
  init_types5();
107488
107623
  }
@@ -107994,13 +108129,13 @@ __export(builtin_skills_exports, {
107994
108129
  skillsGuardBase: () => skillsGuardBase
107995
108130
  });
107996
108131
  import fs95 from "fs";
107997
- import { createHash as createHash25 } from "crypto";
108132
+ import { createHash as createHash26 } from "crypto";
107998
108133
  import path161 from "path";
107999
108134
  function isCliOwnedSkillName(name) {
108000
108135
  return BUILTIN_SKILL_NAMES.has(name) || LEGACY_BUILTIN_SKILL_NAMES.has(name);
108001
108136
  }
108002
108137
  function packagedSkillDigest(content) {
108003
- return createHash25("sha256").update(content).digest("hex");
108138
+ return createHash26("sha256").update(content).digest("hex");
108004
108139
  }
108005
108140
  async function ownedSkillFiles(skillName, paths) {
108006
108141
  const owned = /* @__PURE__ */ new Map();
@@ -108126,7 +108261,7 @@ async function removeOwnedFiles(dir, owned, baseDir, backupDir) {
108126
108261
  }
108127
108262
  function skillBackupDir(baseDir, tool, skillRoot, skillName) {
108128
108263
  const rootSlug = skillRoot.replace(/[\\/:]+/g, "-").replace(/^-+/, "");
108129
- const baseSlug = `${path161.basename(baseDir) || "root"}-${createHash25("sha256").update(baseDir).digest("hex").slice(0, 8)}`;
108264
+ const baseSlug = `${path161.basename(baseDir) || "root"}-${createHash26("sha256").update(baseDir).digest("hex").slice(0, 8)}`;
108130
108265
  return path161.join(getUserHome(), ".teamai", "removed-skills", PRUNE_RUN_ID, baseSlug, tool, rootSlug, skillName);
108131
108266
  }
108132
108267
  async function skillsGuardBase(scopeRoot, skillsDir) {
@@ -113272,7 +113407,7 @@ __export(types_exports, {
113272
113407
  usesBranchWorktree: () => usesBranchWorktree
113273
113408
  });
113274
113409
  import path171 from "path";
113275
- import { createHash as createHash26 } from "crypto";
113410
+ import { createHash as createHash27 } from "crypto";
113276
113411
  function parseInstallScope(value) {
113277
113412
  const parsed = InstallScopeSchema.safeParse(value);
113278
113413
  if (!parsed.success) throw new Error(`Invalid scope "${value}". Use "workspace" or "user".`);
@@ -113340,7 +113475,7 @@ function managedMcpManifestKey(tool, projectScope) {
113340
113475
  return projectScope ? `${owner}:project` : owner;
113341
113476
  }
113342
113477
  function managedMcpWorkspaceId(workspaceRoot) {
113343
- return createHash26("sha1").update(workspaceRoot).digest("hex").slice(0, 12);
113478
+ return createHash27("sha1").update(workspaceRoot).digest("hex").slice(0, 12);
113344
113479
  }
113345
113480
  function managedMcpManifestPath(dataHome, workspaceRoot) {
113346
113481
  if (workspaceRoot) {
@@ -114801,7 +114936,7 @@ var init_types5 = __esm({
114801
114936
 
114802
114937
  // src/claude-hook-host.ts
114803
114938
  import fs99 from "fs";
114804
- import { createHash as createHash27 } from "crypto";
114939
+ import { createHash as createHash28 } from "crypto";
114805
114940
  import path172 from "path";
114806
114941
  function copilotRunsEntries(data) {
114807
114942
  const file = data;
@@ -114809,7 +114944,7 @@ function copilotRunsEntries(data) {
114809
114944
  return Object.entries(file.hooks).flatMap(([event, entries2]) => !Array.isArray(entries2) ? [] : entries2.filter((entry) => entry?.type === "command").flatMap((entry) => [entry.bash, entry.powershell, entry.command].filter((command) => typeof command === "string").map((command) => [event, entry.matcher, command])));
114810
114945
  }
114811
114946
  function copilotCopyKey(event, matcher, command) {
114812
- return createHash27("sha256").update(JSON.stringify([event, matcher && matcher !== "*" ? matcher : "", command])).digest("hex");
114947
+ return createHash28("sha256").update(JSON.stringify([event, matcher && matcher !== "*" ? matcher : "", command])).digest("hex");
114813
114948
  }
114814
114949
  function claudeHookOtherHostSkip(copilotEvent, copilotMatcher, command) {
114815
114950
  if (!copilotEvent) return CURSOR_HOOK_SKIP;
@@ -114891,7 +115026,7 @@ var init_claude_hook_host = __esm({
114891
115026
  });
114892
115027
 
114893
115028
  // src/copilot-hook-claim.ts
114894
- import { createHash as createHash28 } from "crypto";
115029
+ import { createHash as createHash29 } from "crypto";
114895
115030
  import fs100 from "fs";
114896
115031
  import path173 from "path";
114897
115032
  function claimDay(raw) {
@@ -114919,7 +115054,7 @@ function claimCopilotHookEvent(event, matcher, raw, env3 = process.env) {
114919
115054
  if (!day) return true;
114920
115055
  const root = path173.join(getTeamaiHomeDir(), CLAIMS_DIR);
114921
115056
  removeOldClaims(root, day);
114922
- const key = createHash28("sha256").update(JSON.stringify([env3.COPILOT_AGENT_SESSION_ID ?? "", event, matcher, raw])).digest("hex");
115057
+ const key = createHash29("sha256").update(JSON.stringify([env3.COPILOT_AGENT_SESSION_ID ?? "", event, matcher, raw])).digest("hex");
114923
115058
  try {
114924
115059
  fs100.mkdirSync(path173.join(root, day), { recursive: true });
114925
115060
  fs100.writeFileSync(path173.join(root, day, key), "", { flag: "wx" });
@@ -115558,7 +115693,7 @@ __export(hooks_exports2, {
115558
115693
  unregisterCheckoutFromSharedManifest: () => unregisterCheckoutFromSharedManifest
115559
115694
  });
115560
115695
  import path176 from "path";
115561
- import { createHash as createHash29 } from "crypto";
115696
+ import { createHash as createHash30 } from "crypto";
115562
115697
  import { isDeepStrictEqual as isDeepStrictEqual10 } from "util";
115563
115698
  import { realpathSync as realpathSync6 } from "fs";
115564
115699
  import { lstat as lstat2, readdir as readdir2, rm as rm2 } from "fs/promises";
@@ -116303,7 +116438,7 @@ function copilotPowershellCommand(command) {
116303
116438
  return match[1] === "bash" ? `${match[2]} 2>$null; exit 0` : `& ${match[1]} -lc "${match[2]} 2>/dev/null"; exit 0`;
116304
116439
  }
116305
116440
  function copilotGlobalSource(file) {
116306
- return createHash29("sha256").update(path176.resolve(file)).digest("hex");
116441
+ return createHash30("sha256").update(path176.resolve(file)).digest("hex");
116307
116442
  }
116308
116443
  function toCopilotEntry(def, globalSource) {
116309
116444
  const command = globalSource && def.source === "builtin" ? def.command.replace("--tool copilot", `--tool copilot --copilot-global ${copilotGlobalSource(globalSource)}`) : def.command;
@@ -117621,7 +117756,7 @@ async function codexTrustTargets(teamConfig, localConfig2, selectedAgents) {
117621
117756
  };
117622
117757
  }
117623
117758
  async function codexTrustFingerprint(targets) {
117624
- const hash2 = createHash29("sha256").update(JSON.stringify({ ...targets, inputs: void 0 }));
117759
+ const hash2 = createHash30("sha256").update(JSON.stringify({ ...targets, inputs: void 0 }));
117625
117760
  for (const file of targets.inputs) hash2.update(`\0${file}\0${await readFileSafe(file) ?? ""}`);
117626
117761
  hash2.update(`\0${codexBuildsIdentity()}`);
117627
117762
  return hash2.digest("hex");
@@ -124100,7 +124235,7 @@ var init_overlay = __esm({
124100
124235
  });
124101
124236
 
124102
124237
  // src/workflow/place/worktree-snapshot.ts
124103
- import { createHash as createHash30 } from "crypto";
124238
+ import { createHash as createHash31 } from "crypto";
124104
124239
  import { execFile as execFile9 } from "child_process";
124105
124240
  import fs106 from "fs/promises";
124106
124241
  import path185 from "path";
@@ -124128,7 +124263,7 @@ async function hashPath(workspace, relative3) {
124128
124263
  try {
124129
124264
  const stats = await fs106.lstat(full);
124130
124265
  const bytes = stats.isSymbolicLink() ? await fs106.readlink(full) : await fs106.readFile(full);
124131
- return createHash30("sha256").update(bytes).digest("hex");
124266
+ return createHash31("sha256").update(bytes).digest("hex");
124132
124267
  } catch {
124133
124268
  return "missing";
124134
124269
  }
@@ -124458,7 +124593,7 @@ var init_setup = __esm({
124458
124593
  });
124459
124594
 
124460
124595
  // src/workflow/place/writer.ts
124461
- import { createHash as createHash31 } from "crypto";
124596
+ import { createHash as createHash32 } from "crypto";
124462
124597
  import fs109 from "fs/promises";
124463
124598
  import path188 from "path";
124464
124599
  async function mergeBranches({ dir, run: run3, step, executor, merge }) {
@@ -124491,7 +124626,7 @@ async function conflictsPath(dir) {
124491
124626
  return path188.resolve(dir, printed);
124492
124627
  }
124493
124628
  function hashText(text2) {
124494
- return createHash31("sha256").update(text2).digest("hex");
124629
+ return createHash32("sha256").update(text2).digest("hex");
124495
124630
  }
124496
124631
  async function rememberConflicts(dir) {
124497
124632
  const current = await conflictContents(dir);
@@ -131159,7 +131294,7 @@ var init_session_cmd = __esm({
131159
131294
  // src/dashboard/workspaces.ts
131160
131295
  import fs119 from "fs/promises";
131161
131296
  import path206 from "path";
131162
- import { createHash as createHash32 } from "crypto";
131297
+ import { createHash as createHash33 } from "crypto";
131163
131298
  async function configAt(home) {
131164
131299
  try {
131165
131300
  return LocalConfigSchema.parse(import_yaml42.default.parse(await fs119.readFile(path206.join(home, "config.yaml"), "utf8")));
@@ -131194,7 +131329,7 @@ async function dashboardWorkspaces(events) {
131194
131329
  if (!config) return;
131195
131330
  seen.add(anchor);
131196
131331
  result.push({
131197
- id: createHash32("sha256").update(anchor).digest("hex").slice(0, 24),
131332
+ id: createHash33("sha256").update(anchor).digest("hex").slice(0, 24),
131198
131333
  label: path206.basename(root),
131199
131334
  scope: "project",
131200
131335
  root,
@@ -132259,7 +132394,7 @@ __export(distribution_exports, {
132259
132394
  saveProjects: () => saveProjects,
132260
132395
  saveRoles: () => saveRoles
132261
132396
  });
132262
- import { createHash as createHash33 } from "crypto";
132397
+ import { createHash as createHash34 } from "crypto";
132263
132398
  function assertRolesEditable(ownConfig) {
132264
132399
  if (!ownConfig.roleAssignment) return;
132265
132400
  throw new HttpError(409, `Roles are assigned in ${ROLE_ASSIGNMENTS_FILE} in the team repo and cannot be changed here. Open a merge request against that file, or ask a code owner of manifest/ to.`);
@@ -132273,7 +132408,7 @@ function selectionOf2(config) {
132273
132408
  }
132274
132409
  function revisionOf(config) {
132275
132410
  const identity2 = { scope: config.scope, dataHome: config.dataHome ?? null, projectRoot: config.projectRoot ?? null };
132276
- return createHash33("sha256").update(JSON.stringify({ identity: identity2, selection: selectionOf2(config) })).digest("hex").slice(0, 16);
132411
+ return createHash34("sha256").update(JSON.stringify({ identity: identity2, selection: selectionOf2(config) })).digest("hex").slice(0, 16);
132277
132412
  }
132278
132413
  async function readManifest3(kind, load2, repoPath) {
132279
132414
  try {
@@ -135181,7 +135316,7 @@ var init_graph_index_schema = __esm({
135181
135316
  });
135182
135317
 
135183
135318
  // src/wiki-engine/code-knowledge/code-collector.ts
135184
- import { createHash as createHash34 } from "crypto";
135319
+ import { createHash as createHash35 } from "crypto";
135185
135320
  import { execFile as execFile10 } from "child_process";
135186
135321
  import { readFile as readFile7, readdir as readdir4, stat as stat5 } from "fs/promises";
135187
135322
  import path215 from "path";
@@ -135225,7 +135360,7 @@ async function collectCode(options2) {
135225
135360
  path: filePath,
135226
135361
  relativePath,
135227
135362
  language,
135228
- sha256: createHash34("sha256").update(content).digest("hex"),
135363
+ sha256: createHash35("sha256").update(content).digest("hex"),
135229
135364
  content,
135230
135365
  isKeyFile: isKeyFile(relativePath, language)
135231
135366
  });
@@ -142785,7 +142920,7 @@ var init_code_knowledge_recall = __esm({
142785
142920
  });
142786
142921
 
142787
142922
  // src/codebase-freshness.ts
142788
- import { createHash as createHash35 } from "crypto";
142923
+ import { createHash as createHash36 } from "crypto";
142789
142924
  import { lstat as lstat5, readFile as readFile16, readdir as readdir10, realpath as realpath10, stat as stat11 } from "fs/promises";
142790
142925
  import path235 from "path";
142791
142926
  function errorCode(error2) {
@@ -142971,7 +143106,7 @@ async function checkOneSource(source, manifest, checkout) {
142971
143106
  if (!fileStat.isFile()) return unknown();
142972
143107
  try {
142973
143108
  const content = await readFile16(actualPath, "utf8");
142974
- const actualHash = createHash35("sha256").update(content).digest("hex");
143109
+ const actualHash = createHash36("sha256").update(content).digest("hex");
142975
143110
  return {
142976
143111
  ...source,
142977
143112
  freshness: actualHash === expectedHash ? "current" : "stale",
@@ -153408,7 +153543,7 @@ sourceCmd.command("remove <name>").description("Remove a source and clean up its
153408
153543
  const { sourceRemove: sourceRemove2 } = await Promise.resolve().then(() => (init_source2(), source_exports));
153409
153544
  await sourceRemove2(name, globalOpts);
153410
153545
  });
153411
- sourceCmd.command("add-http <endpoint>").description("Add an HTTP source (report/sync/ack) alongside a git main repo").option("--token <key>", "API token for the HTTP endpoint (stored 0600, never committed)").option("--force", "Overwrite an existing HTTP source config").action(async (endpoint, cmdOpts) => {
153546
+ sourceCmd.command("add-http <endpoint>").description("Add an HTTP source (report/sync/ack) alongside a git main repo").option("--token <key>", "API token for the HTTP endpoint (stored 0600, never committed)").option("--agent <name>", "Agent instance that owns this token (repeat setup for each agent)", (val, acc) => acc.concat(val), []).option("--force", "Overwrite an existing HTTP source config").action(async (endpoint, cmdOpts) => {
153412
153547
  const globalOpts = program2.opts();
153413
153548
  const { sourceAddHttp: sourceAddHttp2 } = await Promise.resolve().then(() => (init_source2(), source_exports));
153414
153549
  await sourceAddHttp2(endpoint, { ...globalOpts, ...cmdOpts });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@team-ai/teamai-cli",
3
- "version": "0.30.4",
3
+ "version": "0.30.5",
4
4
  "description": "TeamAI — Make Every Team AI Native (skill sync + shared knowledge base, powered by Git)",
5
5
  "type": "module",
6
6
  "bin": {
@@ -175,6 +175,7 @@ Generated: do not edit by hand. Regenerate with
175
175
  - `teamai source remove <name>` — Remove a source and clean up its skills
176
176
  - `teamai source add-http <endpoint>` — Add an HTTP source (report/sync/ack) alongside a git main repo
177
177
  - `--token <key>` — API token for the HTTP endpoint (stored 0600, never committed)
178
+ - `--agent <name>` — Agent instance that owns this token (repeat setup for each agent)
178
179
  - `--force` — Overwrite an existing HTTP source config
179
180
  - `teamai source remove-http` — Remove the HTTP source and clean up its resources
180
181
  - `teamai source list` — List all configured sources
@@ -104,11 +104,19 @@ was skipped and why.
104
104
  cannot use Git. If the admin provides an HTTP endpoint + API key instead, use:
105
105
 
106
106
  ```bash
107
- teamai init --http https://your-team-host/api --token <api-key>
107
+ teamai init --http https://your-team-host/api --token <api-key> --agent <tool>
108
108
  ```
109
109
 
110
110
  This is a read-only consumer mode — `push` / `contribute` are not available, but
111
- skills and rules still sync.
111
+ skills and rules still sync. Run it from each workspace that should be managed:
112
+ the user-level hooks are shared by the machine, but an unrelated workspace is
113
+ not reported or allowed to receive workspace resources. ClawPro project binding
114
+ is optional; skipping it keeps general workspace sync enabled while declining
115
+ resources tied to a specific project. Treat each linked Git worktree as a
116
+ separate workspace and run HTTP setup in each one that should be managed.
117
+ ClawPro instance tokens are Agent-specific. On a machine with multiple AI tools,
118
+ run setup once per tool with its own `--agent` and token; TeamAI keeps those
119
+ credentials separate while allowing them to manage the same workspace.
112
120
 
113
121
  **Claude Code or Codex kept in a different directory (`CLAUDE_CONFIG_DIR`,
114
122
  `CODEX_HOME`):** `init` records that directory (as `toolRoots.claude` /