@mnemom/mnemom 0.17.3-next.3 → 0.17.3-next.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.
@@ -195,6 +195,13 @@ export function buildGoalShowView(record, body, opts) {
195
195
  L.push(fmt.label("verdict: ", v
196
196
  ? `${v.verdict.toUpperCase()} at turn ${v.turn}${v.superseded ? " (superseded)" : ""}`
197
197
  : fmt.dim("none yet")));
198
+ const unverified = body.unverified_mid_turn_messages ?? [];
199
+ if (unverified.length) {
200
+ L.push(fmt.label("unverified: ", fmt.dim("mid-turn messages seen in tool output; they did NOT change the goal")));
201
+ for (const u of unverified) {
202
+ L.push(` ${formatRelativeAge(u.at)} ${JSON.stringify(u.text)}`);
203
+ }
204
+ }
198
205
  if (body.threads) {
199
206
  L.push(fmt.label("threads:", ""));
200
207
  for (const t of body.threads) {
@@ -115,6 +115,8 @@ export interface AgentShowOptions {
115
115
  /** Why the live read could not happen, from the thrown error. */
116
116
  export declare function unavailableReason(err: unknown): string;
117
117
  /** `rev N[ · pinned]` from a live show body, or `rev 0 (no goal yet)`. */
118
+ /** Longest goal statement `agent show` prints inline; `mnemom agent goal show` has the full text. */
119
+ export declare const LIVE_GOAL_STATEMENT_MAX = 80;
118
120
  export declare function liveGoalLine(body: GoalShowResponse): string;
119
121
  /** `mnemom agent show [ref] [--json]` */
120
122
  export declare function agentShowCommand(ref: string | undefined, opts: AgentShowOptions, deps: SessionCommandDeps): Promise<void>;
@@ -274,10 +274,19 @@ export function unavailableReason(err) {
274
274
  return err instanceof Error ? err.message : String(err);
275
275
  }
276
276
  /** `rev N[ · pinned]` from a live show body, or `rev 0 (no goal yet)`. */
277
+ /** Longest goal statement `agent show` prints inline; `mnemom agent goal show` has the full text. */
278
+ export const LIVE_GOAL_STATEMENT_MAX = 80;
277
279
  export function liveGoalLine(body) {
278
280
  if (!body.intent)
279
281
  return "rev 0 (no goal yet)";
280
- return `rev ${body.intent.revision}${body.intent.pinned ? " · pinned" : ""}`;
282
+ const rev = `rev ${body.intent.revision}${body.intent.pinned ? " · pinned" : ""}`;
283
+ const statement = body.intent.statement.replace(/\s+/g, " ").trim();
284
+ if (!statement)
285
+ return rev;
286
+ if (statement.length <= LIVE_GOAL_STATEMENT_MAX)
287
+ return `${rev} — "${statement}"`;
288
+ const cut = statement.slice(0, LIVE_GOAL_STATEMENT_MAX - 1).trimEnd();
289
+ return `${rev} — "${cut}…" (full: mnemom agent goal show)`;
281
290
  }
282
291
  /** `mnemom agent show [ref] [--json]` */
283
292
  export async function agentShowCommand(ref, opts, deps) {
@@ -1,6 +1,9 @@
1
+ import { type OrgListItem } from "../lib/api.js";
1
2
  export interface AgentsListOptions {
2
- /** Scope to a single org. When omitted, aggregates across every org you belong to. */
3
+ /** Org slug OR org_id to scope to. Omit → the active org, or every org if none is set. */
3
4
  org?: string;
5
+ /** Aggregate across every org you belong to, ignoring the active org. */
6
+ all?: boolean;
4
7
  }
5
8
  export declare function agentsListCommand(options?: AgentsListOptions): Promise<void>;
6
9
  export interface AgentsClaimOptions {
@@ -25,6 +28,16 @@ export interface AgentsClaimOptions {
25
28
  * derivation (gateway/src/index.ts) and agent-proof.ts on the API side.
26
29
  */
27
30
  export declare function deriveHashProof(apiKey: string, agentName?: string): string;
31
+ /**
32
+ * Resolve an `--org <slug>` value to an org_id. Accepts either a slug or a raw
33
+ * org_id (both are matched against the caller's memberships). Returns the
34
+ * resolved org_id, or throws a teaching error listing the caller's orgs when
35
+ * the value matches none of them.
36
+ */
37
+ export declare function resolveOrgId(slugOrId: string, orgs: OrgListItem[], hint?: {
38
+ lead: string;
39
+ tail: string;
40
+ }): string;
28
41
  /**
29
42
  * `mnemom agent claim <id-or-name> [--org <slug>] (--key <k> | --hash-proof <h>)`
30
43
  *
@@ -15,11 +15,54 @@ export async function agentsListCommand(options = {}) {
15
15
  console.log(fmt.dim(" To list org-scoped agents, log in with a session: mnemom login") + "\n");
16
16
  return;
17
17
  }
18
+ let scope = { kind: "all" };
19
+ if (cred.type === "jwt") {
20
+ if (options.org && options.all) {
21
+ console.log(fmt.error("Pass --org or --all, not both.") + "\n");
22
+ process.exit(1);
23
+ return;
24
+ }
25
+ if (options.org) {
26
+ // Resolve slug-or-id against your memberships BEFORE the fleet read: the
27
+ // fleet route takes an org_id, so a raw slug there 403s as "Permission denied".
28
+ let orgs;
29
+ try {
30
+ orgs = await listMyOrgs();
31
+ }
32
+ catch (err) {
33
+ const msg = err instanceof Error ? err.message : String(err);
34
+ console.log(fmt.error(`Failed to read your orgs: ${msg}`) + "\n");
35
+ process.exit(1);
36
+ return;
37
+ }
38
+ try {
39
+ const orgId = resolveOrgId(options.org, orgs, LIST_ORG_HINT);
40
+ scope = { kind: "org", orgId, label: options.org.trim() };
41
+ }
42
+ catch (err) {
43
+ const msg = err instanceof Error ? err.message : String(err);
44
+ console.log(fmt.error(msg) + "\n");
45
+ process.exit(1);
46
+ return;
47
+ }
48
+ }
49
+ else if (!options.all) {
50
+ const active = getActiveOrg();
51
+ if (active) {
52
+ scope = { kind: "org", orgId: active.org_id, label: active.slug };
53
+ console.error(fmt.dim(` Showing active org ${active.name} (${active.slug}) — --all for every org.`) +
54
+ "\n");
55
+ }
56
+ }
57
+ }
18
58
  // Show the Org column only when a JWT session aggregates across all orgs.
19
- const showOrg = cred.type === "jwt" && !options.org;
59
+ const showOrg = cred.type === "jwt" && scope.kind === "all";
20
60
  let agents;
21
61
  try {
22
- agents = cred.type === "api-key" ? await listAgents() : await listOrgAgents(options.org);
62
+ agents =
63
+ cred.type === "api-key"
64
+ ? await listAgents()
65
+ : await listOrgAgents(scope.kind === "org" ? scope.orgId : undefined);
23
66
  }
24
67
  catch (err) {
25
68
  const msg = err instanceof Error ? err.message : String(err);
@@ -27,7 +70,9 @@ export async function agentsListCommand(options = {}) {
27
70
  process.exit(1);
28
71
  }
29
72
  if (agents.length === 0) {
30
- console.log(options.org ? ` No agents found in org '${options.org}'.\n` : " No agents found.\n");
73
+ console.log(scope.kind === "org"
74
+ ? ` No agents found in org '${scope.label}'.\n`
75
+ : " No agents found.\n");
31
76
  return;
32
77
  }
33
78
  const nameW = 24;
@@ -87,15 +132,22 @@ export function deriveHashProof(apiKey, agentName) {
87
132
  * resolved org_id, or throws a teaching error listing the caller's orgs when
88
133
  * the value matches none of them.
89
134
  */
90
- function resolveOrgId(slugOrId, orgs) {
135
+ export function resolveOrgId(slugOrId, orgs, hint = CLAIM_ORG_HINT) {
91
136
  const needle = slugOrId.trim();
92
137
  const match = orgs.find((o) => o.slug === needle) ?? orgs.find((o) => o.org_id === needle);
93
138
  if (match)
94
139
  return match.org_id;
95
140
  const choices = orgs.map((o) => ` ${o.slug.padEnd(24)} ${o.name}`).join("\n");
96
- throw new Error(`No org of yours matches '${needle}'. You can claim into one of:\n${choices}\n` +
97
- ` Pass --org <slug>, or omit --org to land in your personal org.`);
141
+ throw new Error(`No org of yours matches '${needle}'. ${hint.lead}\n${choices}\n ${hint.tail}`);
98
142
  }
143
+ const CLAIM_ORG_HINT = {
144
+ lead: "You can claim into one of:",
145
+ tail: "Pass --org <slug>, or omit --org to land in your personal org.",
146
+ };
147
+ const LIST_ORG_HINT = {
148
+ lead: "Your orgs:",
149
+ tail: "Pass --org <slug>, or --all for every org.",
150
+ };
99
151
  /** The not-a-member 403 code emitted by the merged endpoint. */
100
152
  const NOT_A_MEMBER_CODE = "agent_org_not_member";
101
153
  /**
package/dist/index.js CHANGED
@@ -677,11 +677,12 @@ policyCmd
677
677
  // ============================================================================
678
678
  agentCmd
679
679
  .command("list")
680
- .description("List agents across the orgs you belong to (ADR-062 org-scoped)")
681
- .option("--org <id>", "Scope to a single org (default: all orgs you belong to)")
680
+ .description("List the agents in your active org (set with `mnemom org use`), or every org you belong to if none is set (ADR-062 org-scoped)")
681
+ .option("--org <slug-or-id>", "Scope to one org, by slug or id (default: the active org)")
682
+ .option("--all", "List agents across every org you belong to, ignoring the active org")
682
683
  .action(async (opts) => {
683
684
  try {
684
- await agentsListCommand({ org: opts.org });
685
+ await agentsListCommand({ org: opts.org, all: opts.all });
685
686
  }
686
687
  catch (error) {
687
688
  console.error("Error:", error instanceof Error ? error.message : error);
@@ -99,6 +99,21 @@ export interface GoalShowResponse {
99
99
  verdict: GoalVerdictView | null;
100
100
  last_revision: number;
101
101
  threads?: GoalThreadRow[];
102
+ /**
103
+ * IG4 steer: mid-turn messages found in a tool_result. RECORD ONLY: tool output can forge one,
104
+ * so they never changed the goal. Absent when there are none.
105
+ */
106
+ unverified_mid_turn_messages?: GoalUnverifiedMessage[];
107
+ }
108
+ export interface GoalUnverifiedMessage {
109
+ /**
110
+ * Clipped to 500 chars by the gateway. UNTRUSTED: it can be attacker-written tool output, so a
111
+ * consumer must escape it (the CLI prints it JSON-quoted; a web view must never render it as HTML).
112
+ */
113
+ text: string;
114
+ chars: number;
115
+ hash: string;
116
+ at: string;
102
117
  }
103
118
  export interface GoalPinResponse {
104
119
  conversation_id: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mnemom/mnemom",
3
- "version": "0.17.3-next.3",
3
+ "version": "0.17.3-next.5",
4
4
  "description": "Transparent AI agent tracing",
5
5
  "type": "module",
6
6
  "bin": {