agent-office 0.2.2 → 0.2.4

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,9 +24,10 @@ export interface AgentMode {
24
24
  export interface AgenticCodingServer {
25
25
  /**
26
26
  * Create a new session.
27
+ * @param title display title shown in the OpenCode UI.
27
28
  * @returns the server-assigned session ID.
28
29
  */
29
- createSession(): Promise<string>;
30
+ createSession(title: string): Promise<string>;
30
31
  /**
31
32
  * Permanently delete a session.
32
33
  */
@@ -47,13 +48,6 @@ export interface AgenticCodingServer {
47
48
  * @param limit maximum number of messages to return (server may cap this).
48
49
  */
49
50
  getMessages(sessionID: string, limit?: number): Promise<SessionMessage[]>;
50
- /**
51
- * Reset a session to a specific message.
52
- *
53
- * Implementations should abort any in-progress generation before reverting
54
- * so callers don't need to worry about "session is busy" errors.
55
- */
56
- revertSession(sessionID: string, messageID: string): Promise<void>;
57
51
  /**
58
52
  * Return the list of agent modes the server knows about.
59
53
  */
@@ -2,10 +2,9 @@ import type { AgenticCodingServer, SessionMessage, AgentMode } from "./agentic-c
2
2
  export declare class OpenCodeCodingServer implements AgenticCodingServer {
3
3
  private client;
4
4
  constructor(baseURL: string);
5
- createSession(): Promise<string>;
5
+ createSession(title: string): Promise<string>;
6
6
  deleteSession(sessionID: string): Promise<void>;
7
7
  sendMessage(sessionID: string, text: string, agent: string, system: string): Promise<void>;
8
8
  getMessages(sessionID: string, limit?: number): Promise<SessionMessage[]>;
9
- revertSession(sessionID: string, messageID: string): Promise<void>;
10
9
  getAgentModes(): Promise<AgentMode[]>;
11
10
  }
@@ -9,8 +9,8 @@ export class OpenCodeCodingServer {
9
9
  constructor(baseURL) {
10
10
  this.client = createOpencodeClient({ baseUrl: baseURL, directory: cwd() });
11
11
  }
12
- async createSession() {
13
- const { data: session } = await this.client.session.create();
12
+ async createSession(title) {
13
+ const { data: session } = await this.client.session.create({ title });
14
14
  if (!session)
15
15
  throw new Error("OpenCode returned no session");
16
16
  return session.id;
@@ -37,12 +37,6 @@ export class OpenCodeCodingServer {
37
37
  parts: m.parts,
38
38
  }));
39
39
  }
40
- async revertSession(sessionID, messageID) {
41
- // Abort any in-progress generation first — swallow errors because the
42
- // session may not be busy.
43
- await this.client.session.abort({ sessionID }).catch(() => { });
44
- await this.client.session.revert({ sessionID, messageID });
45
- }
46
40
  async getAgentModes() {
47
41
  const { data: config } = await this.client.config.get();
48
42
  const agent = config?.agent ?? {};
@@ -632,6 +632,7 @@ export function SessionList({ serverUrl, password, contentHeight, onSubViewChang
632
632
  setMode("browse");
633
633
  setActionError(null);
634
634
  setActionMsg(null);
635
+ reload();
635
636
  }
636
637
  });
637
638
  const handleCreate = async (name) => {
@@ -732,7 +733,7 @@ export function SessionList({ serverUrl, password, contentHeight, onSubViewChang
732
733
  setMode("reverting");
733
734
  try {
734
735
  await revertToStart(target.name);
735
- setActionMsg(`Session "${target.name}" reverted to first message and restarted.`);
736
+ setActionMsg(`Session "${target.name}" reset to a fresh session.`);
736
737
  setMode("create-done");
737
738
  reload();
738
739
  }
@@ -751,7 +752,7 @@ export function SessionList({ serverUrl, password, contentHeight, onSubViewChang
751
752
  const result = await revertAll();
752
753
  const failed = result.results.filter((r) => !r.ok);
753
754
  if (failed.length === 0) {
754
- setActionMsg(`All ${result.total} session(s) reverted and restarted.`);
755
+ setActionMsg(`All ${result.total} session(s) reset to fresh sessions.`);
755
756
  }
756
757
  else {
757
758
  setActionMsg(`Reverted ${result.total - failed.length}/${result.total} sessions. Failed: ${failed.map((f) => f.name).join(", ")}`);
@@ -34,7 +34,7 @@ export function TailMessages({ serverUrl, password, onBack, contentHeight }) {
34
34
  try {
35
35
  const msgs = await getMessages(name, 50);
36
36
  setMessages(msgs);
37
- setScrollOffset(0);
37
+ setScrollOffset(Infinity);
38
38
  setStage("viewing");
39
39
  }
40
40
  catch (err) {
@@ -191,7 +191,7 @@ export function createRouter(sql, agenticCodingServer, serverUrl, scheduler, mem
191
191
  }
192
192
  let opencodeSessionId;
193
193
  try {
194
- opencodeSessionId = await agenticCodingServer.createSession();
194
+ opencodeSessionId = await agenticCodingServer.createSession(`agent-office: ${trimmedName} ${new Date().toISOString()}`);
195
195
  }
196
196
  catch (err) {
197
197
  console.error("OpenCode session.create error:", err);
@@ -353,18 +353,13 @@ export function createRouter(sql, agenticCodingServer, serverUrl, scheduler, mem
353
353
  }
354
354
  const session = rows[0];
355
355
  try {
356
- const messages = await agenticCodingServer.getMessages(session.session_id);
357
- if (messages.length === 0) {
358
- res.status(400).json({ error: "Session has no messages to revert to" });
359
- return;
360
- }
361
- const firstMessage = messages[0];
362
- if (!firstMessage.id) {
363
- res.status(500).json({ error: "Failed to get first message ID" });
364
- return;
365
- }
366
- await agenticCodingServer.revertSession(session.session_id, firstMessage.id);
367
- res.json({ ok: true, messageID: firstMessage.id });
356
+ // Delete the old OpenCode session and create a fresh one
357
+ await agenticCodingServer.deleteSession(session.session_id);
358
+ const newSessionId = await agenticCodingServer.createSession(`agent-office: ${name} ${new Date().toISOString()}`);
359
+ await sql `
360
+ UPDATE sessions SET session_id = ${newSessionId} WHERE name = ${name}
361
+ `;
362
+ res.json({ ok: true });
368
363
  }
369
364
  catch (err) {
370
365
  console.error("POST /sessions/:name/revert-to-start error:", err);
@@ -373,22 +368,17 @@ export function createRouter(sql, agenticCodingServer, serverUrl, scheduler, mem
373
368
  });
374
369
  router.post("/sessions/revert-all", async (_req, res) => {
375
370
  const allSessions = await sql `
376
- SELECT id, name, session_id, agent_code, agent, status, created_at FROM sessions
371
+ SELECT id, name, session_id FROM sessions
377
372
  `;
378
373
  const results = [];
379
374
  for (const session of allSessions) {
380
375
  try {
381
- const messages = await agenticCodingServer.getMessages(session.session_id);
382
- if (messages.length === 0) {
383
- results.push({ name: session.name, ok: false, error: "No messages" });
384
- continue;
385
- }
386
- const firstMessage = messages[0];
387
- if (!firstMessage.id) {
388
- results.push({ name: session.name, ok: false, error: "Failed to get first message ID" });
389
- continue;
390
- }
391
- await agenticCodingServer.revertSession(session.session_id, firstMessage.id);
376
+ // Delete the old OpenCode session and create a fresh one
377
+ await agenticCodingServer.deleteSession(session.session_id);
378
+ const newSessionId = await agenticCodingServer.createSession(`agent-office: ${session.name} ${new Date().toISOString()}`);
379
+ await sql `
380
+ UPDATE sessions SET session_id = ${newSessionId} WHERE name = ${session.name}
381
+ `;
392
382
  results.push({ name: session.name, ok: true });
393
383
  }
394
384
  catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-office",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "An office for your AI agents",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -34,7 +34,7 @@
34
34
  "dependencies": {
35
35
  "@inkjs/ui": "^2.0.0",
36
36
  "@opencode-ai/sdk": "^1.2.10",
37
- "agent-office": "0.2.1",
37
+ "agent-office": "^0.2.2",
38
38
  "commander": "^14.0.0",
39
39
  "croner": "^10.0.1",
40
40
  "dotenv": "^17.0.0",