@ganglion/xacpx-relay 0.9.6 → 0.9.8

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
@@ -907,11 +907,17 @@ function createApp(deps) {
907
907
  app.get("/api/active-turns", (c) => {
908
908
  const account = c.get("account");
909
909
  const turns = [];
910
+ const usage = [];
911
+ const commands = [];
910
912
  for (const inst of deps.instances.listByAccount(account.id)) {
911
913
  for (const t of deps.activeTurns?.(inst.id) ?? [])
912
914
  turns.push(t);
915
+ for (const u of deps.sessionUsage?.(inst.id) ?? [])
916
+ usage.push(u);
917
+ for (const cmd of deps.sessionCommands?.(inst.id) ?? [])
918
+ commands.push(cmd);
913
919
  }
914
- return c.json({ turns });
920
+ return c.json({ turns, usage, commands });
915
921
  });
916
922
  app.get("/api/instances/:id/sessions/:alias/messages", (c) => {
917
923
  const account = c.get("account");
@@ -1048,6 +1054,28 @@ async function createRelayRuntime(dbPath, options = {}) {
1048
1054
  const webGateway = new WebGateway;
1049
1055
  const turnBuffers = new Map;
1050
1056
  const key = (instanceId, alias) => `${instanceId}\x00${alias}`;
1057
+ const sessionUsage = new Map;
1058
+ const listSessionUsage = (instanceId) => {
1059
+ const prefix = `${instanceId}\x00`;
1060
+ const out = [];
1061
+ for (const [k, u] of sessionUsage) {
1062
+ if (!k.startsWith(prefix))
1063
+ continue;
1064
+ out.push({ instanceId, sessionAlias: k.slice(prefix.length), used: u.used, size: u.size, ...u.cost ? { cost: u.cost } : {}, ...u.breakdown ? { breakdown: u.breakdown } : {} });
1065
+ }
1066
+ return out;
1067
+ };
1068
+ const sessionCommands = new Map;
1069
+ const listSessionCommands = (instanceId) => {
1070
+ const prefix = `${instanceId}\x00`;
1071
+ const out = [];
1072
+ for (const [k, commands] of sessionCommands) {
1073
+ if (!k.startsWith(prefix))
1074
+ continue;
1075
+ out.push({ instanceId, sessionAlias: k.slice(prefix.length), commands });
1076
+ }
1077
+ return out;
1078
+ };
1051
1079
  const listActiveTurns = (instanceId) => {
1052
1080
  const prefix = `${instanceId}\x00`;
1053
1081
  const out = [];
@@ -1098,6 +1126,12 @@ async function createRelayRuntime(dbPath, options = {}) {
1098
1126
  for (const k of turnBuffers.keys())
1099
1127
  if (k.startsWith(prefix))
1100
1128
  turnBuffers.delete(k);
1129
+ for (const k of sessionUsage.keys())
1130
+ if (k.startsWith(prefix))
1131
+ sessionUsage.delete(k);
1132
+ for (const k of sessionCommands.keys())
1133
+ if (k.startsWith(prefix))
1134
+ sessionCommands.delete(k);
1101
1135
  }
1102
1136
  webGateway.broadcast(accountId, { kind: "instance-status", instanceId, online });
1103
1137
  },
@@ -1140,6 +1174,10 @@ async function createRelayRuntime(dbPath, options = {}) {
1140
1174
  const structured = hasStructured ? { toolSteps: steps, ...hasReasoning ? { reasoning: a.reasoning } : {}, ...a.parts.length ? { parts: a.parts } : {} } : undefined;
1141
1175
  messages.append(instanceId, event.sessionAlias, "out", a.text, structured);
1142
1176
  }
1177
+ } else if (event.type === "turn-usage") {
1178
+ sessionUsage.set(key(instanceId, event.sessionAlias), { used: event.used, size: event.size, ...event.cost ? { cost: event.cost } : {}, ...event.breakdown ? { breakdown: event.breakdown } : {} });
1179
+ } else if (event.type === "agent-commands") {
1180
+ sessionCommands.set(key(instanceId, event.sessionAlias), event.commands);
1143
1181
  } else if (event.type === "session-history") {
1144
1182
  const existing = messages.listBySession(accountId, instanceId, event.sessionAlias, { limit: 1 });
1145
1183
  if (existing.messages.length === 0) {
@@ -1162,6 +1200,8 @@ async function createRelayRuntime(dbPath, options = {}) {
1162
1200
  historyRetentionDays: options.historyRetentionDays ?? 30,
1163
1201
  maxMessagesPerSession: MAX_MESSAGES_PER_SESSION,
1164
1202
  activeTurns: listActiveTurns,
1203
+ sessionUsage: listSessionUsage,
1204
+ sessionCommands: listSessionCommands,
1165
1205
  trustProxy: options.trustProxy,
1166
1206
  checkUpdate: createRelayUpdateChecker({ current: readRelayVersion() })
1167
1207
  });
@@ -1,5 +1,5 @@
1
1
  import { Hono } from "hono";
2
- import { type LiveTurnSnapshotDto } from "@ganglion/xacpx-relay-protocol";
2
+ import { type LiveTurnSnapshotDto, type SessionCommandsSnapshotDto, type SessionUsageSnapshotDto } from "@ganglion/xacpx-relay-protocol";
3
3
  import type { AccountRow, AccountStore } from "../stores/accounts.js";
4
4
  import type { InstanceStore } from "../stores/instances.js";
5
5
  import type { MessageStore } from "../stores/messages.js";
@@ -15,6 +15,10 @@ export interface AppDeps {
15
15
  messages: MessageStore;
16
16
  /** Snapshot the in-flight turns for an instance (for the active-turns endpoint). */
17
17
  activeTurns?: (instanceId: string) => LiveTurnSnapshotDto[];
18
+ /** Snapshot the latest per-session context-usage for an instance (for the active-turns endpoint). */
19
+ sessionUsage?: (instanceId: string) => SessionUsageSnapshotDto[];
20
+ /** Snapshot the latest per-session agent-advertised commands for an instance (for the active-turns endpoint). */
21
+ sessionCommands?: (instanceId: string) => SessionCommandsSnapshotDto[];
18
22
  webRoot?: string;
19
23
  sessionTtlMs?: number;
20
24
  pairingTtlMs?: number;
@@ -1 +1 @@
1
- .stream-md>:first-child{margin-top:0}.stream-md>:last-child{margin-bottom:0}.stream-md p{margin:.5em 0;line-height:1.5}.stream-md h1,.stream-md h2,.stream-md h3,.stream-md h4{margin:.8em 0 .4em;font-weight:600;line-height:1.3}.stream-md h1{font-size:1.3em}.stream-md h2{font-size:1.2em}.stream-md h3{font-size:1.1em}.stream-md ul,.stream-md ol{margin:.5em 0;padding-left:1.4em}.stream-md ul{list-style:disc}.stream-md ol{list-style:decimal}.stream-md li{margin:.2em 0}.stream-md a{color:rgb(var(--c-accent));text-decoration:underline}.stream-md code{background:rgb(var(--c-surface));color:rgb(var(--c-fg));border-radius:4px;padding:.1em .3em;font-family:JetBrains Mono,ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12.5px}.stream-md pre{background:rgb(var(--c-bg));color:rgb(var(--c-fg));border:1px solid rgb(var(--c-border));border-radius:8px;padding:.65em .85em;overflow-x:auto;margin:.6em 0;box-shadow:var(--shadow-e1)}.stream-md pre::-webkit-scrollbar{height:8px}.stream-md pre::-webkit-scrollbar-thumb{background:rgb(var(--c-fg-muted) / .28);border-radius:8px}.stream-md pre::-webkit-scrollbar-track{background:transparent}.stream-md pre code{background:transparent;padding:0;color:inherit;font-size:13px;line-height:1.6}.stream-md .hljs-keyword,.stream-md .hljs-built_in,.stream-md .hljs-name,.stream-md .hljs-tag{color:rgb(var(--c-accent))}.stream-md .hljs-string,.stream-md .hljs-attr,.stream-md .hljs-symbol{color:rgb(var(--c-run))}.stream-md .hljs-comment,.stream-md .hljs-quote{color:rgb(var(--c-fg-muted))}.stream-md .hljs-number,.stream-md .hljs-literal{color:rgb(var(--c-info))}.stream-md blockquote{border-left:3px solid rgb(var(--c-border));margin:.6em 0;padding-left:.8em;color:rgb(var(--c-fg-muted))}.stream-md .md-table-wrap{max-width:100%;overflow-x:auto;margin:.6em 0}.stream-md .md-table-wrap::-webkit-scrollbar{height:8px}.stream-md .md-table-wrap::-webkit-scrollbar-thumb{background:rgb(var(--c-fg-muted) / .28);border-radius:8px}.stream-md .md-table-wrap::-webkit-scrollbar-track{background:transparent}.stream-md table{border-collapse:collapse}.stream-md img{max-width:100%;height:auto}.stream-md th,.stream-md td{border:1px solid rgb(var(--c-border));padding:.3em .6em}.stream-md hr{border:none;border-top:1px solid rgb(var(--c-border));margin:.8em 0}.cv-row[data-v-a7278286]{content-visibility:auto;contain-intrinsic-size:auto 88px}
1
+ .stream-md>:first-child{margin-top:0}.stream-md>:last-child{margin-bottom:0}.stream-md p{margin:.5em 0;line-height:1.5}.stream-md h1,.stream-md h2,.stream-md h3,.stream-md h4{margin:.8em 0 .4em;font-weight:600;line-height:1.3}.stream-md h1{font-size:1.3em}.stream-md h2{font-size:1.2em}.stream-md h3{font-size:1.1em}.stream-md ul,.stream-md ol{margin:.5em 0;padding-left:1.4em}.stream-md ul{list-style:disc}.stream-md ol{list-style:decimal}.stream-md li{margin:.2em 0}.stream-md a{color:rgb(var(--c-accent));text-decoration:underline}.stream-md code{background:rgb(var(--c-surface));color:rgb(var(--c-fg));border-radius:4px;padding:.1em .3em;font-family:JetBrains Mono,ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12.5px}.stream-md pre{background:rgb(var(--c-bg));color:rgb(var(--c-fg));border:1px solid rgb(var(--c-border));border-radius:8px;padding:.65em .85em;overflow-x:auto;margin:.6em 0;box-shadow:var(--shadow-e1)}.stream-md pre::-webkit-scrollbar{height:8px}.stream-md pre::-webkit-scrollbar-thumb{background:rgb(var(--c-fg-muted) / .28);border-radius:8px}.stream-md pre::-webkit-scrollbar-track{background:transparent}.stream-md pre code{background:transparent;padding:0;color:inherit;font-size:13px;line-height:1.6}.stream-md .hljs-keyword,.stream-md .hljs-built_in,.stream-md .hljs-name,.stream-md .hljs-tag{color:rgb(var(--c-accent))}.stream-md .hljs-string,.stream-md .hljs-attr,.stream-md .hljs-symbol{color:rgb(var(--c-run))}.stream-md .hljs-comment,.stream-md .hljs-quote{color:rgb(var(--c-fg-muted))}.stream-md .hljs-number,.stream-md .hljs-literal{color:rgb(var(--c-info))}.stream-md blockquote{border-left:3px solid rgb(var(--c-border));margin:.6em 0;padding-left:.8em;color:rgb(var(--c-fg-muted))}.stream-md .md-table-wrap{max-width:100%;overflow-x:auto;margin:.6em 0}.stream-md .md-table-wrap::-webkit-scrollbar{height:8px}.stream-md .md-table-wrap::-webkit-scrollbar-thumb{background:rgb(var(--c-fg-muted) / .28);border-radius:8px}.stream-md .md-table-wrap::-webkit-scrollbar-track{background:transparent}.stream-md table{border-collapse:collapse}.stream-md img{max-width:100%;height:auto}.stream-md th,.stream-md td{border:1px solid rgb(var(--c-border));padding:.3em .6em}.stream-md hr{border:none;border-top:1px solid rgb(var(--c-border));margin:.8em 0}.cv-row[data-v-419a9f24]{content-visibility:auto;contain-intrinsic-size:auto 88px}