@inerrata-corporation/errata 2.0.7-dev.2797 → 2.0.7-dev.2821

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.
Files changed (2) hide show
  1. package/errata.mjs +80 -11
  2. package/package.json +1 -1
package/errata.mjs CHANGED
@@ -79931,7 +79931,7 @@ function createWatchBreaker(deps) {
79931
79931
  }
79932
79932
 
79933
79933
  // src/engine.ts
79934
- var DAEMON_VERSION = true ? "2.0.7-dev.2797" : "2.0.0-alpha.0";
79934
+ var DAEMON_VERSION = true ? "2.0.7-dev.2821" : "2.0.0-alpha.0";
79935
79935
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
79936
79936
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
79937
79937
  var GIT_OP_MUTE_MS = 4e3;
@@ -85034,16 +85034,28 @@ async function loginOAuthDevice(opts) {
85034
85034
  if (approvedInstallation !== opts.installationId) {
85035
85035
  throw new Error("approved installation does not match the terminal request");
85036
85036
  }
85037
- const resourceResponse = await fetchFn(device.resource, {
85037
+ return exchangeDeviceSession({
85038
+ fetchFn,
85039
+ resourceUrl: device.resource,
85040
+ deviceSession,
85041
+ installationId: approvedInstallation,
85042
+ clientId,
85043
+ scope
85044
+ });
85045
+ }
85046
+ async function exchangeDeviceSession(opts) {
85047
+ const fetchFn = opts.fetchFn ?? fetch;
85048
+ const scope = opts.scope ?? DEFAULT_OAUTH_SCOPE;
85049
+ const resourceResponse = await fetchFn(opts.resourceUrl, {
85038
85050
  method: "POST",
85039
85051
  headers: {
85040
- authorization: `Bearer ${deviceSession}`,
85052
+ authorization: `Bearer ${opts.deviceSession}`,
85041
85053
  "content-type": "application/json",
85042
85054
  accept: "application/json"
85043
85055
  },
85044
85056
  body: JSON.stringify({
85045
- installationId: approvedInstallation,
85046
- clientId,
85057
+ installationId: opts.installationId,
85058
+ clientId: opts.clientId,
85047
85059
  scopes: scope.split(/\s+/).filter((value) => !["openid", "profile", "email", "offline_access"].includes(value))
85048
85060
  })
85049
85061
  });
@@ -85052,12 +85064,12 @@ async function loginOAuthDevice(opts) {
85052
85064
  throw new Error(`device resource exchange failed: HTTP ${resourceResponse.status}`);
85053
85065
  }
85054
85066
  return {
85055
- installationId: approvedInstallation,
85056
- clientId,
85057
- tokenEndpoint: device.resource,
85067
+ installationId: opts.installationId,
85068
+ clientId: opts.clientId,
85069
+ tokenEndpoint: opts.resourceUrl,
85058
85070
  tokens: {
85059
85071
  accessToken: resource["access_token"],
85060
- refreshToken: deviceSession,
85072
+ refreshToken: opts.deviceSession,
85061
85073
  ...typeof resource["expires_in"] === "number" ? { expiresInSec: resource["expires_in"] } : {}
85062
85074
  }
85063
85075
  };
@@ -85271,7 +85283,10 @@ async function linkThroughConsole(opts) {
85271
85283
  return {
85272
85284
  status: "approved",
85273
85285
  decision,
85274
- installationId: typeof payload?.["installation_id"] === "string" ? payload["installation_id"] : null
85286
+ installationId: typeof payload?.["installation_id"] === "string" ? payload["installation_id"] : null,
85287
+ deviceSession: typeof payload?.["access_token"] === "string" ? payload["access_token"] : null,
85288
+ resourceUrl: device.resource,
85289
+ clientId
85275
85290
  };
85276
85291
  }
85277
85292
  return { status: "expired" };
@@ -89261,6 +89276,50 @@ async function linkRegisteredWorkspaces(cfg) {
89261
89276
  }
89262
89277
  }
89263
89278
  }
89279
+ async function bindWorkspaceToLinkInstallation(cfg, out2, orgId) {
89280
+ const installationId = out2.installationId;
89281
+ if (!out2.deviceSession) {
89282
+ console.warn(
89283
+ ` note: the project is in another org; run \`errata login --device --installation ${installationId} --profile <name>\` then \`errata workspace bind . --profile <name>\``
89284
+ );
89285
+ return null;
89286
+ }
89287
+ try {
89288
+ const minted = await exchangeDeviceSession({
89289
+ resourceUrl: out2.resourceUrl,
89290
+ deviceSession: out2.deviceSession,
89291
+ installationId,
89292
+ clientId: out2.clientId
89293
+ });
89294
+ const existing = Object.entries(cfg.installationProfiles).find(([, p]) => p.installationId === installationId)?.[0];
89295
+ let profileName = existing ?? `link-${orgId.slice(0, 8)}`;
89296
+ for (let i2 = 2; !existing && cfg.installationProfiles[profileName]; i2++) profileName = `link-${orgId.slice(0, 8)}-${i2}`;
89297
+ const next = {
89298
+ ...cfg,
89299
+ installationProfiles: {
89300
+ ...cfg.installationProfiles,
89301
+ [profileName]: {
89302
+ installationId,
89303
+ cloudUrl: cfg.cloudUrl,
89304
+ apiKey: null,
89305
+ accessToken: minted.tokens.accessToken,
89306
+ refreshToken: minted.tokens.refreshToken ?? null,
89307
+ tokenEndpoint: minted.tokenEndpoint,
89308
+ oauthClientId: minted.clientId,
89309
+ activeAgent: null
89310
+ }
89311
+ }
89312
+ };
89313
+ saveConfig(next);
89314
+ setWorkspaceBinding(workspaceEntryForPath(ROOT)?.id ?? ROOT, profileName);
89315
+ return { config: next, profileName };
89316
+ } catch (err2) {
89317
+ console.warn(
89318
+ ` note: the project is linked, but this workspace could not take the other org's credential (${err2 instanceof Error ? err2.message : String(err2)}); run \`errata login --device --installation ${installationId} --profile <name>\` then \`errata workspace bind . --profile <name>\``
89319
+ );
89320
+ return null;
89321
+ }
89322
+ }
89264
89323
  async function cmdLink(args2) {
89265
89324
  const flag = (name2) => {
89266
89325
  const i2 = args2.indexOf(name2);
@@ -89340,12 +89399,22 @@ async function cmdLink(args2) {
89340
89399
  );
89341
89400
  await refreshLinkedCodexHooks(args2);
89342
89401
  if (applied.wroteIgnore) console.log("wrote .errataignore (starter) \u2014 edit it; it is your hard control");
89402
+ let reportClient = authedCloudClient(applied.config);
89403
+ if (out3.installationId && out3.installationId !== activeProfile?.installationId) {
89404
+ const bound = await bindWorkspaceToLinkInstallation(applied.config, out3, d.orgId);
89405
+ if (bound) {
89406
+ reportClient = authedCloudClientForProfile(bound.config, bound.profileName);
89407
+ console.log(
89408
+ `this workspace now uses installation ${out3.installationId.slice(0, 8)} (profile ${bound.profileName}) in org ${d.orgId.slice(0, 8)}; your machine default is unchanged`
89409
+ );
89410
+ }
89411
+ }
89343
89412
  if (!hasCloudCredential(cfg)) {
89344
89413
  console.log(" note: run `errata login` so this daemon can sync under the link and report the history stage.");
89345
89414
  return;
89346
89415
  }
89347
89416
  const consents = historyConsents(applied.profile);
89348
- const reported = await reportHistoryStage(authedCloudClient(applied.config), applied.profile, (line) => console.warn(line));
89417
+ const reported = await reportHistoryStage(reportClient, applied.profile, (line) => console.warn(line));
89349
89418
  if (reported?.consents) {
89350
89419
  const synced = applyConsents(applied.profile, applied.config, reported.consents, (/* @__PURE__ */ new Date()).toISOString());
89351
89420
  if (synced.changed) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.7-dev.2797",
3
+ "version": "2.0.7-dev.2821",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {