@agentforge-io/core 2.0.15 → 2.0.16

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.
@@ -24,3 +24,25 @@ export interface Message {
24
24
  }
25
25
  export type NewConversation = Pick<Conversation, 'userId' | 'agentId'> & Partial<Omit<Conversation, 'id' | 'createdAt' | 'updatedAt'>>;
26
26
  export type NewMessage = Omit<Message, 'id' | 'createdAt'>;
27
+ /**
28
+ * Minimal payload for the agent-editor's conversation sidebar. The full
29
+ * `Conversation + messages[]` is too heavy to ship for 50 rows; this
30
+ * shape carries the bare minimum the UI needs to render a row and
31
+ * decide which one to load in full.
32
+ *
33
+ * `intent` is the first user message of the conversation, truncated to
34
+ * 120 chars server-side. `null` when the conversation has no user
35
+ * message yet (rare but possible mid-create).
36
+ */
37
+ export interface ConversationListItem {
38
+ id: string;
39
+ userId: string;
40
+ agentId: string;
41
+ status: ConversationStatus;
42
+ intent: string | null;
43
+ messageCount: number;
44
+ totalInputTokens: number;
45
+ totalOutputTokens: number;
46
+ createdAt: Date;
47
+ updatedAt: Date;
48
+ }
@@ -1,5 +1,5 @@
1
1
  import type { ConversationRepository, MessageRepository } from './index';
2
- import type { Conversation, NewConversation, Message, NewMessage } from '../domain/conversation';
2
+ import type { Conversation, ConversationListItem, NewConversation, Message, NewMessage } from '../domain/conversation';
3
3
  import type { ConversationStatus } from '../types/agent.types';
4
4
  export declare class InMemoryConversationRepository implements ConversationRepository {
5
5
  private byId;
@@ -11,6 +11,13 @@ export declare class InMemoryConversationRepository implements ConversationRepos
11
11
  limit?: number;
12
12
  offset?: number;
13
13
  }): Promise<Conversation[]>;
14
+ listForAgent(agentId: string, opts?: {
15
+ limit?: number;
16
+ offset?: number;
17
+ }): Promise<{
18
+ items: ConversationListItem[];
19
+ totalCount: number;
20
+ }>;
14
21
  updateStats(id: string, patch: {
15
22
  status?: ConversationStatus;
16
23
  addInputTokens?: number;
@@ -41,6 +41,32 @@ class InMemoryConversationRepository {
41
41
  const end = opts.limit ? start + opts.limit : undefined;
42
42
  return items.slice(start, end);
43
43
  }
44
+ async listForAgent(agentId, opts = {}) {
45
+ // In-memory variant doesn't have access to the message store —
46
+ // those live in a sibling repo. We return `intent: null` here; the
47
+ // TypeORM impl is the one that materializes intent from messages.
48
+ // Good enough for tests + demos that just want to exercise the
49
+ // listing contract.
50
+ const all = Array.from(this.byId.values()).filter((c) => c.agentId === agentId);
51
+ all.sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());
52
+ const start = opts.offset ?? 0;
53
+ const end = opts.limit ? start + opts.limit : undefined;
54
+ return {
55
+ items: all.slice(start, end).map((c) => ({
56
+ id: c.id,
57
+ userId: c.userId,
58
+ agentId: c.agentId,
59
+ status: c.status,
60
+ intent: null,
61
+ messageCount: c.messageCount,
62
+ totalInputTokens: c.totalInputTokens,
63
+ totalOutputTokens: c.totalOutputTokens,
64
+ createdAt: c.createdAt,
65
+ updatedAt: c.updatedAt,
66
+ })),
67
+ totalCount: all.length,
68
+ };
69
+ }
44
70
  async updateStats(id, patch) {
45
71
  const c = this.byId.get(id);
46
72
  if (!c)
@@ -1,4 +1,4 @@
1
- import type { Conversation, NewConversation, Message, NewMessage } from '../domain/conversation';
1
+ import type { Conversation, ConversationListItem, NewConversation, Message, NewMessage } from '../domain/conversation';
2
2
  import type { ChatToken, NewChatToken, ChatTokenPatch } from '../domain/chat-token';
3
3
  import type { McpServerRecord, NewMcpServerRecord, McpServerRecordPatch } from '../domain/mcp-server';
4
4
  import type { ConnectorAuth, NewConnectorAuth, ConnectorAuthPatch } from '../domain/connector-auth';
@@ -22,6 +22,26 @@ export interface ConversationRepository {
22
22
  limit?: number;
23
23
  offset?: number;
24
24
  }): Promise<Conversation[]>;
25
+ /**
26
+ * List every conversation an agent has had, regardless of user. Used by
27
+ * the agent-editor's "Conversations" panel — operators need visibility
28
+ * into all traffic the agent saw, not just their own.
29
+ *
30
+ * Tenant scoping is enforced one layer up (host service), since the SDK
31
+ * doesn't carry tenant context. Pass `agentId` only after verifying it
32
+ * belongs to the caller's tenant.
33
+ *
34
+ * The optional `intent` field on each item is the first user message's
35
+ * content, truncated to 120 chars — server-side so the wire payload
36
+ * stays small (the list is for a sidebar, not for replaying messages).
37
+ */
38
+ listForAgent(agentId: string, opts?: {
39
+ limit?: number;
40
+ offset?: number;
41
+ }): Promise<{
42
+ items: ConversationListItem[];
43
+ totalCount: number;
44
+ }>;
25
45
  updateStats(id: string, patch: {
26
46
  status?: ConversationStatus;
27
47
  addInputTokens?: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentforge-io/core",
3
- "version": "2.0.15",
3
+ "version": "2.0.16",
4
4
  "description": "Framework-free AI runtime SDK. Owns: agent loop (Anthropic), conversations, tools, streaming, agent-job queue, SdkHooks. Identity, billing, infra (email/uploads/secrets) live in the host's modules — not here.",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",