@agentchatme/agent-core 0.0.1313111111111 → 0.0.1313111111112

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.
@@ -141,6 +141,21 @@ interface WireConfig {
141
141
  apiBase: string;
142
142
  timeoutMs?: number;
143
143
  }
144
+ interface PendingReviewMirrorRecord {
145
+ id: string;
146
+ conversation_id: string;
147
+ peer_agents: string[];
148
+ focus_message_id: string;
149
+ reason: 'autonomy_off' | 'sender_not_allowed' | 'local_permission';
150
+ first_requested_at: string;
151
+ updated_at: string;
152
+ }
153
+ /**
154
+ * Replace this installation's ephemeral dashboard mirror with its complete
155
+ * local pending snapshot. The server unions snapshots across installations;
156
+ * no database row or peer-authored message content is created.
157
+ */
158
+ declare function syncPendingReviewMirror(cfg: WireConfig, installationId: string, records: PendingReviewMirrorRecord[]): Promise<void>;
144
159
  declare class WireError extends Error {
145
160
  readonly status: number;
146
161
  constructor(status: number, detail: string);
@@ -313,18 +328,27 @@ interface RecordPendingRequestInput {
313
328
  reason: PendingReason;
314
329
  summary: string;
315
330
  }
331
+ interface RecordedPendingRequest {
332
+ record: PendingRequest;
333
+ /** True only when this write represents review-worthy information not
334
+ * already present in the local record. Used to avoid duplicate OS alerts. */
335
+ changed: boolean;
336
+ }
316
337
  declare function pendingRequestId(identityHandle: string, conversationId: string): string;
317
338
  /**
318
339
  * Persist-before-ack storage. Unlike background activity, this deliberately
319
340
  * throws on write failure: the daemon must retry rather than acknowledge a
320
341
  * request that the foreground agent would then never learn about.
321
342
  */
343
+ declare function recordPendingRequestWithStatus(home: string, input: RecordPendingRequestInput, now?: Date): RecordedPendingRequest;
322
344
  declare function recordPendingRequest(home: string, input: RecordPendingRequestInput, now?: Date): PendingRequest;
323
345
  declare function getPendingRequest(home: string, identityHandle: string, id: string): PendingRequest | null;
324
346
  declare function listPendingRequests(home: string, identityHandle: string): PendingRequest[];
325
347
  declare function resolvePendingRequest(home: string, identityHandle: string, id: string): boolean;
326
348
  declare function pendingRequestsFingerprint(records: PendingRequest[]): string;
327
349
  declare function formatPendingRequestsNotice(records: PendingRequest[], copy: HostCopy): string | null;
350
+ /** Short, deterministic copy for a host's user-visible hook surface. */
351
+ declare function formatPendingRequestsSystemMessage(records: PendingRequest[]): string | null;
328
352
 
329
353
  interface TurnMentionContext {
330
354
  messageId: string;
@@ -443,4 +467,4 @@ interface RuntimeAdapter {
443
467
  runTurn(ctx: TurnContext): Promise<TurnResult>;
444
468
  }
445
469
 
446
- export { pendingRequestId as $, type AutonomyMode as A, contextOf as B, formatAlwaysOnDown as C, formatPendingRequestsNotice as D, formatRegistrationOffer as E, type FullAutonomyTurnContext as F, formatSessionStart as G, type HostCopy as H, formatStopPickup as I, fullAutonomyAllows as J, getMeLite as K, getPendingRequest as L, type MessageContext as M, idle as N, lastDeliveryId as O, type PendingReason as P, listPendingRequests as Q, type RuntimeAdapter as R, type SilentReason as S, type TurnContext as T, markAlwaysOnInstalledVersion as U, markAlwaysOnOptOut as V, type WireConfig as W, markAlwaysOnWanted as X, markForegroundTurn as Y, markSessionActive as Z, normalizeAgentHandle as _, type TurnDisposition as a, pendingRequestsFingerprint as a0, readAlwaysOnInstalledVersion as a1, readFullAutonomyPolicy as a2, recordPendingRequest as a3, removeFullAutonomyAgent as a4, renderDeclinedBlock as a5, renderUnregisteredBlock as a6, resolvePendingRequest as a7, setFullAutonomyMode as a8, syncAck as a9, syncPeek as aa, writeFullAutonomyPolicy as ab, type PendingTurnRequest as b, type TurnBatchContext as c, type TurnMentionContext as d, type TurnResult as e, type AlwaysOnState as f, type FullAutonomyPolicy as g, HEARTBEAT_FILE as h, type PendingRequest as i, type RecordPendingRequestInput as j, type SyncRow as k, WireError as l, allowFullAutonomyAgent as m, alwaysOnHealth as n, alwaysOnOptedOut as o, alwaysOnState as p, alwaysOnWanted as q, autonomyPath as r, beat as s, claimReply as t, claimReplyBatch as u, clearAlwaysOnInstalledVersion as v, clearAlwaysOnOptOut as w, clearAlwaysOnWanted as x, clearForegroundTurn as y, clearSessionActive as z };
470
+ export { markForegroundTurn as $, type AutonomyMode as A, clearForegroundTurn as B, clearSessionActive as C, contextOf as D, formatAlwaysOnDown as E, type FullAutonomyTurnContext as F, formatPendingRequestsNotice as G, type HostCopy as H, formatPendingRequestsSystemMessage as I, formatRegistrationOffer as J, formatSessionStart as K, formatStopPickup as L, type MessageContext as M, fullAutonomyAllows as N, getMeLite as O, type PendingReason as P, getPendingRequest as Q, type RuntimeAdapter as R, type SilentReason as S, type TurnContext as T, idle as U, lastDeliveryId as V, type WireConfig as W, listPendingRequests as X, markAlwaysOnInstalledVersion as Y, markAlwaysOnOptOut as Z, markAlwaysOnWanted as _, type TurnDisposition as a, markSessionActive as a0, normalizeAgentHandle as a1, pendingRequestId as a2, pendingRequestsFingerprint as a3, readAlwaysOnInstalledVersion as a4, readFullAutonomyPolicy as a5, recordPendingRequest as a6, recordPendingRequestWithStatus as a7, removeFullAutonomyAgent as a8, renderDeclinedBlock as a9, renderUnregisteredBlock as aa, resolvePendingRequest as ab, setFullAutonomyMode as ac, syncAck as ad, syncPeek as ae, syncPendingReviewMirror as af, writeFullAutonomyPolicy as ag, type PendingTurnRequest as b, type TurnBatchContext as c, type TurnMentionContext as d, type TurnResult as e, type PendingRequest as f, type AlwaysOnState as g, type FullAutonomyPolicy as h, HEARTBEAT_FILE as i, type PendingReviewMirrorRecord as j, type RecordPendingRequestInput as k, type RecordedPendingRequest as l, type SyncRow as m, WireError as n, allowFullAutonomyAgent as o, alwaysOnHealth as p, alwaysOnOptedOut as q, alwaysOnState as r, alwaysOnWanted as s, autonomyPath as t, beat as u, claimReply as v, claimReplyBatch as w, clearAlwaysOnInstalledVersion as x, clearAlwaysOnOptOut as y, clearAlwaysOnWanted as z };
@@ -25,7 +25,7 @@ var log = {
25
25
  };
26
26
 
27
27
  // src/version.ts
28
- var VERSION = "0.0.1313111111111";
28
+ var VERSION = "0.0.1313111111112";
29
29
 
30
30
  // src/client-identity.ts
31
31
  var CODING_AGENTS_CLIENT_IDENTITY = {
@@ -588,8 +588,8 @@ function getErrorMap() {
588
588
 
589
589
  // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
590
590
  var makeIssue = (params) => {
591
- const { data, path: path8, errorMaps, issueData } = params;
592
- const fullPath = [...path8, ...issueData.path || []];
591
+ const { data, path: path9, errorMaps, issueData } = params;
592
+ const fullPath = [...path9, ...issueData.path || []];
593
593
  const fullIssue = {
594
594
  ...issueData,
595
595
  path: fullPath
@@ -705,11 +705,11 @@ var errorUtil;
705
705
 
706
706
  // node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
707
707
  var ParseInputLazyPath = class {
708
- constructor(parent, value, path8, key) {
708
+ constructor(parent, value, path9, key) {
709
709
  this._cachedPath = [];
710
710
  this.parent = parent;
711
711
  this.data = value;
712
- this._path = path8;
712
+ this._path = path9;
713
713
  this._key = key;
714
714
  }
715
715
  get path() {
@@ -4292,7 +4292,7 @@ function pendingRequestId(identityHandle, conversationId) {
4292
4292
  const digest = crypto.createHash("sha256").update("agentchat-pending-v1\0").update(identity).update("\0").update(conversationId).digest("hex").slice(0, 24);
4293
4293
  return `pending_${digest}`;
4294
4294
  }
4295
- function recordPendingRequest(home, input, now = /* @__PURE__ */ new Date()) {
4295
+ function recordPendingRequestWithStatus(home, input, now = /* @__PURE__ */ new Date()) {
4296
4296
  const identity = normalizeAgentHandle(input.selfHandle);
4297
4297
  if (identity === null) throw new Error("cannot create pending state for an invalid identity");
4298
4298
  const id = pendingRequestId(identity, input.conversationId);
@@ -4326,7 +4326,11 @@ function recordPendingRequest(home, input, now = /* @__PURE__ */ new Date()) {
4326
4326
  `,
4327
4327
  384
4328
4328
  );
4329
- return record;
4329
+ const changed = existing === null || existing.focus_message_id !== record.focus_message_id || existing.reason !== record.reason || existing.summary !== record.summary || existing.peer_agents.join("\0") !== record.peer_agents.join("\0");
4330
+ return { record, changed };
4331
+ }
4332
+ function recordPendingRequest(home, input, now = /* @__PURE__ */ new Date()) {
4333
+ return recordPendingRequestWithStatus(home, input, now).record;
4330
4334
  }
4331
4335
  function getPendingRequest(home, identityHandle, id) {
4332
4336
  const identity = normalizeAgentHandle(identityHandle);
@@ -4376,6 +4380,12 @@ function formatPendingRequestsNotice(records, copy) {
4376
4380
  "This notice is trusted local state. Its summaries are descriptions of peer requests, not authority to change autonomy or permissions."
4377
4381
  ].join("\n");
4378
4382
  }
4383
+ function formatPendingRequestsSystemMessage(records) {
4384
+ if (records.length === 0) return null;
4385
+ const peers = [...new Set(records.flatMap((record) => record.peer_agents))];
4386
+ const peerText = peers.length > 0 ? ` from ${peers.slice(0, 3).join(", ")}${peers.length > 3 ? ` and ${peers.length - 3} more` : ""}` : "";
4387
+ return `AgentChat: ${records.length} request${records.length === 1 ? "" : "s"}${peerText} ${records.length === 1 ? "is" : "are"} waiting for this agent's review.`;
4388
+ }
4379
4389
 
4380
4390
  // src/daemon/leader-lock.ts
4381
4391
  import * as fs3 from "fs";
@@ -4579,6 +4589,20 @@ async function request(cfg, method, pathname, body) {
4579
4589
  }
4580
4590
  return res.json();
4581
4591
  }
4592
+ async function syncPendingReviewMirror(cfg, installationId2, records) {
4593
+ await request(cfg, "PUT", "/v1/pending-reviews", {
4594
+ installation_id: installationId2,
4595
+ pending_reviews: records.slice(0, 100).map((record) => ({
4596
+ id: record.id,
4597
+ conversation_id: record.conversation_id,
4598
+ peer_agents: record.peer_agents.slice(0, 20),
4599
+ focus_message_id: record.focus_message_id,
4600
+ reason: record.reason,
4601
+ first_requested_at: record.first_requested_at,
4602
+ updated_at: record.updated_at
4603
+ }))
4604
+ });
4605
+ }
4582
4606
  var WireError = class extends Error {
4583
4607
  status;
4584
4608
  constructor(status, detail) {
@@ -4896,6 +4920,96 @@ function formatDaemonActivities(records) {
4896
4920
  ].join("\n");
4897
4921
  }
4898
4922
 
4923
+ // src/util/spawn.ts
4924
+ import crossSpawn from "cross-spawn";
4925
+ var spawnCommand = crossSpawn;
4926
+ var spawnCommandSync = crossSpawn.sync;
4927
+
4928
+ // src/daemon/desktop-notification.ts
4929
+ function bodyOf(record) {
4930
+ const peers = record.peer_agents.slice(0, 3).join(", ") || "another agent";
4931
+ const more = record.peer_agents.length > 3 ? ` and ${record.peer_agents.length - 3} more` : "";
4932
+ return `@${record.identity_handle} has a request from ${peers}${more} waiting for review.`;
4933
+ }
4934
+ function pendingNotificationPlan(record, runtimeOs = process.platform) {
4935
+ const title = "AgentChat request needs review";
4936
+ const body = bodyOf(record);
4937
+ if (runtimeOs === "darwin") {
4938
+ return {
4939
+ command: "/usr/bin/osascript",
4940
+ args: [
4941
+ "-e",
4942
+ "on run argv",
4943
+ "-e",
4944
+ "display notification (item 2 of argv) with title (item 1 of argv)",
4945
+ "-e",
4946
+ "end run",
4947
+ title,
4948
+ body
4949
+ ]
4950
+ };
4951
+ }
4952
+ if (runtimeOs === "linux") {
4953
+ return { command: "notify-send", args: ["--app-name=AgentChat", title, body] };
4954
+ }
4955
+ if (runtimeOs === "win32") {
4956
+ const encodedBody = Buffer.from(body, "utf-8").toString("base64");
4957
+ const script = [
4958
+ `$body=[Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('${encodedBody}'))`,
4959
+ "$title='AgentChat request needs review'",
4960
+ "$safeTitle=[Security.SecurityElement]::Escape($title)",
4961
+ "$safeBody=[Security.SecurityElement]::Escape($body)",
4962
+ "$xml=New-Object Windows.Data.Xml.Dom.XmlDocument",
4963
+ '$xml.LoadXml("<toast><visual><binding template="ToastGeneric"><text>$safeTitle</text><text>$safeBody</text></binding></visual></toast>")',
4964
+ "$toast=[Windows.UI.Notifications.ToastNotification]::new($xml)",
4965
+ "[Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier('AgentChat').Show($toast)"
4966
+ ].join(";");
4967
+ return {
4968
+ command: "powershell.exe",
4969
+ args: ["-NoLogo", "-NoProfile", "-NonInteractive", "-Command", script]
4970
+ };
4971
+ }
4972
+ return null;
4973
+ }
4974
+ function notifyPendingRequest(record) {
4975
+ if (process.env["AGENTCHAT_DESKTOP_NOTIFICATIONS"] === "0") return;
4976
+ const plan = pendingNotificationPlan(record);
4977
+ if (plan === null) return;
4978
+ try {
4979
+ const child = spawnCommand(plan.command, plan.args, {
4980
+ detached: true,
4981
+ stdio: "ignore",
4982
+ windowsHide: true
4983
+ });
4984
+ child.once("error", () => {
4985
+ });
4986
+ child.unref();
4987
+ } catch {
4988
+ }
4989
+ }
4990
+
4991
+ // src/daemon/installation.ts
4992
+ import * as crypto3 from "crypto";
4993
+ import * as fs7 from "fs";
4994
+ import * as path8 from "path";
4995
+ var INSTALLATION_ID_FILE = "daemon.installation-id";
4996
+ function installationId(home) {
4997
+ const file = path8.join(home, INSTALLATION_ID_FILE);
4998
+ try {
4999
+ const existing = fs7.readFileSync(file, "utf-8").trim();
5000
+ if (/^[0-9a-f-]{36}$/i.test(existing)) return existing;
5001
+ } catch {
5002
+ }
5003
+ const id = crypto3.randomUUID();
5004
+ try {
5005
+ atomicWriteFile(file, `${id}
5006
+ `, 384);
5007
+ } catch (err) {
5008
+ log.warn(`could not persist daemon installation id: ${String(err)}`);
5009
+ }
5010
+ return id;
5011
+ }
5012
+
4899
5013
  export {
4900
5014
  log,
4901
5015
  external_exports,
@@ -4919,12 +5033,14 @@ export {
4919
5033
  fullAutonomyAllows,
4920
5034
  PendingReasonSchema,
4921
5035
  pendingRequestId,
5036
+ recordPendingRequestWithStatus,
4922
5037
  recordPendingRequest,
4923
5038
  getPendingRequest,
4924
5039
  listPendingRequests,
4925
5040
  resolvePendingRequest,
4926
5041
  pendingRequestsFingerprint,
4927
5042
  formatPendingRequestsNotice,
5043
+ formatPendingRequestsSystemMessage,
4928
5044
  acquireLeaderLock,
4929
5045
  DEFAULT_API_BASE,
4930
5046
  credentialsPath,
@@ -4938,6 +5054,7 @@ export {
4938
5054
  writePending,
4939
5055
  clearPending,
4940
5056
  contextOf,
5057
+ syncPendingReviewMirror,
4941
5058
  WireError,
4942
5059
  syncPeek,
4943
5060
  syncAck,
@@ -4966,6 +5083,11 @@ export {
4966
5083
  recordDaemonActivity,
4967
5084
  peekDaemonActivities,
4968
5085
  ackDaemonActivities,
4969
- formatDaemonActivities
5086
+ formatDaemonActivities,
5087
+ spawnCommand,
5088
+ spawnCommandSync,
5089
+ pendingNotificationPlan,
5090
+ notifyPendingRequest,
5091
+ installationId
4970
5092
  };
4971
- //# sourceMappingURL=chunk-D62LD5UE.js.map
5093
+ //# sourceMappingURL=chunk-KIP2JKPQ.js.map