@sofer_agent/cli 0.3.6 → 0.3.7

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/chat.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- /** Interactive chat TUI with promus-style polish. */
1
+ /** Interactive chat TUI with promus-style polish + session resume. */
2
2
  export declare function chatCommand(): Promise<void>;
3
3
  //# sourceMappingURL=chat.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../src/chat.ts"],"names":[],"mappings":"AAIA,qDAAqD;AACrD,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAoBjD"}
1
+ {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../src/chat.ts"],"names":[],"mappings":"AAuDA,sEAAsE;AACtE,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAsCjD"}
package/dist/chat.js CHANGED
@@ -1,10 +1,57 @@
1
- import { loadConfig, SoferAgent } from "@sofer_agent/core";
2
- import { requireSecrets } from "./secrets.js";
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { dirname } from "node:path";
3
+ import { agentPaths, loadConfig, shortAgentId, SoferAgent, } from "@sofer_agent/core";
4
+ import { loadSecrets } from "./env.js";
3
5
  import { SoferTui } from "./tui.js";
4
- /** Interactive chat TUI with promus-style polish. */
6
+ function sessionPath(config) {
7
+ if (config.agentObjectId) {
8
+ return agentPaths.agent(shortAgentId(config.agentObjectId)).activityLog;
9
+ }
10
+ if (config.memwal.accountId) {
11
+ return agentPaths.agent(shortAgentId(config.memwal.accountId)).activityLog;
12
+ }
13
+ return null;
14
+ }
15
+ function loadSession(path) {
16
+ if (!existsSync(path))
17
+ return [];
18
+ const messages = [];
19
+ const raw = readFileSync(path, "utf8");
20
+ for (const line of raw.split("\n")) {
21
+ if (!line.trim())
22
+ continue;
23
+ try {
24
+ const entry = JSON.parse(line);
25
+ messages.push({ role: entry.role, content: entry.content });
26
+ }
27
+ catch {
28
+ // skip malformed lines
29
+ }
30
+ }
31
+ return messages;
32
+ }
33
+ function saveSession(path, messages) {
34
+ const lines = messages.map((m) => JSON.stringify({ role: m.role, content: m.content }));
35
+ mkdirSync(dirname(path), { recursive: true });
36
+ writeFileSync(path, `${lines.join("\n")}\n`, "utf8");
37
+ }
38
+ /** Interactive chat TUI with promus-style polish + session resume. */
5
39
  export async function chatCommand() {
6
40
  const config = loadConfig();
7
- const agent = await SoferAgent.create(config, requireSecrets());
41
+ const secrets = loadSecrets();
42
+ if (!secrets.suiSecretKey || !secrets.anthropicApiKey) {
43
+ console.error("Missing secrets. Run `sofer init` first.");
44
+ process.exit(1);
45
+ }
46
+ const agent = await SoferAgent.create(config, { suiSecretKey: secrets.suiSecretKey, anthropicApiKey: secrets.anthropicApiKey });
47
+ // Session resume
48
+ const sp = sessionPath(config);
49
+ if (sp) {
50
+ const history = loadSession(sp);
51
+ if (history.length > 0) {
52
+ agent.loadHistory(history);
53
+ }
54
+ }
8
55
  const tui = new SoferTui(agent, config);
9
56
  await tui.run(async (line, signal) => {
10
57
  try {
@@ -20,6 +67,10 @@ export async function chatCommand() {
20
67
  tui.addMessage("error", e instanceof Error ? e.message : String(e));
21
68
  }
22
69
  }
70
+ // Save session after each turn
71
+ if (sp) {
72
+ saveSession(sp, agent.getHistory());
73
+ }
23
74
  tui.render();
24
75
  });
25
76
  }
package/dist/chat.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"chat.js","sourceRoot":"","sources":["../src/chat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC,qDAAqD;AACrD,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC;IAEhE,MAAM,GAAG,GAAG,IAAI,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAExC,MAAM,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;QACnC,IAAI,CAAC;YACH,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC3D,GAAG,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YAC9B,GAAG,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,SAAS,CAAC,WAAW,EAAE,WAAW,EAAE,SAAS,CAAC,YAAY,EAAE,CAAC,CAAC;QAC1F,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;gBACpB,GAAG,CAAC,UAAU,CAAC,QAAQ,EAAE,yBAAyB,CAAC,CAAC;YACtD,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YACtE,CAAC;QACH,CAAC;QACD,GAAG,CAAC,MAAM,EAAE,CAAC;IACf,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"chat.js","sourceRoot":"","sources":["../src/chat.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sofer_agent/cli",
3
- "version": "0.3.6",
3
+ "version": "0.3.7",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "sofer": "./dist/bin.js"
@@ -26,7 +26,7 @@
26
26
  ],
27
27
  "dependencies": {
28
28
  "@clack/prompts": "^1.5.1",
29
- "@sofer_agent/core": "0.3.1"
29
+ "@sofer_agent/core": "0.3.2"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@types/node": "^22.10.2",
package/src/chat.ts CHANGED
@@ -1,11 +1,76 @@
1
- import { loadConfig, SoferAgent } from "@sofer_agent/core";
2
- import { requireSecrets } from "./secrets.js";
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { dirname } from "node:path";
3
+ import {
4
+ agentPaths,
5
+ type SoferConfig,
6
+ loadConfig,
7
+ shortAgentId,
8
+ SoferAgent,
9
+ } from "@sofer_agent/core";
10
+ import { loadSecrets } from "./env.js";
3
11
  import { SoferTui } from "./tui.js";
4
12
 
5
- /** Interactive chat TUI with promus-style polish. */
13
+ /** Serializable message for JSONL session storage. */
14
+ interface SessionMessage {
15
+ role: string;
16
+ content: unknown; // Anthropic ContentBlock[]
17
+ }
18
+
19
+ interface SessionLine {
20
+ role: SessionMessage["role"];
21
+ content: SessionMessage["content"];
22
+ }
23
+
24
+ function sessionPath(config: SoferConfig): string | null {
25
+ if (config.agentObjectId) {
26
+ return agentPaths.agent(shortAgentId(config.agentObjectId)).activityLog;
27
+ }
28
+ if (config.memwal.accountId) {
29
+ return agentPaths.agent(shortAgentId(config.memwal.accountId)).activityLog;
30
+ }
31
+ return null;
32
+ }
33
+
34
+ function loadSession(path: string): SessionMessage[] {
35
+ if (!existsSync(path)) return [];
36
+ const messages: SessionMessage[] = [];
37
+ const raw = readFileSync(path, "utf8");
38
+ for (const line of raw.split("\n")) {
39
+ if (!line.trim()) continue;
40
+ try {
41
+ const entry = JSON.parse(line) as SessionLine;
42
+ messages.push({ role: entry.role, content: entry.content });
43
+ } catch {
44
+ // skip malformed lines
45
+ }
46
+ }
47
+ return messages;
48
+ }
49
+
50
+ function saveSession(path: string, messages: SessionMessage[]): void {
51
+ const lines = messages.map((m) => JSON.stringify({ role: m.role, content: m.content }));
52
+ mkdirSync(dirname(path), { recursive: true });
53
+ writeFileSync(path, `${lines.join("\n")}\n`, "utf8");
54
+ }
55
+
56
+ /** Interactive chat TUI with promus-style polish + session resume. */
6
57
  export async function chatCommand(): Promise<void> {
7
58
  const config = loadConfig();
8
- const agent = await SoferAgent.create(config, requireSecrets());
59
+ const secrets = loadSecrets();
60
+ if (!secrets.suiSecretKey || !secrets.anthropicApiKey) {
61
+ console.error("Missing secrets. Run `sofer init` first.");
62
+ process.exit(1);
63
+ }
64
+ const agent = await SoferAgent.create(config, { suiSecretKey: secrets.suiSecretKey, anthropicApiKey: secrets.anthropicApiKey });
65
+
66
+ // Session resume
67
+ const sp = sessionPath(config);
68
+ if (sp) {
69
+ const history = loadSession(sp);
70
+ if (history.length > 0) {
71
+ agent.loadHistory(history);
72
+ }
73
+ }
9
74
 
10
75
  const tui = new SoferTui(agent, config);
11
76
 
@@ -21,6 +86,10 @@ export async function chatCommand(): Promise<void> {
21
86
  tui.addMessage("error", e instanceof Error ? e.message : String(e));
22
87
  }
23
88
  }
89
+ // Save session after each turn
90
+ if (sp) {
91
+ saveSession(sp, agent.getHistory());
92
+ }
24
93
  tui.render();
25
94
  });
26
95
  }