@saga-ai/cli 0.7.0 → 0.7.1

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.
Files changed (3) hide show
  1. package/README.md +24 -0
  2. package/dist/cli.cjs +21 -2
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -16,6 +16,7 @@ npx @saga-ai/cli init
16
16
  npx @saga-ai/cli find <query>
17
17
  npx @saga-ai/cli worktree <epic-slug> <story-slug>
18
18
  npx @saga-ai/cli implement <story-slug>
19
+ npx @saga-ai/cli sessions list
19
20
  npx @saga-ai/cli dashboard
20
21
  ```
21
22
 
@@ -49,6 +50,7 @@ saga find auth --type epic
49
50
 
50
51
  Options:
51
52
  - `--type <type>` - Type to search for: `epic` or `story` (default: story)
53
+ - `--status <status>` - Filter stories by status: `ready`, `completed`, `blocked`, etc.
52
54
 
53
55
  Returns JSON with:
54
56
  - `found: true` + `data` - Single match found
@@ -83,15 +85,37 @@ saga implement my-story
83
85
  saga implement my-story --max-cycles 5
84
86
  saga implement my-story --max-time 30
85
87
  saga implement my-story --model sonnet
88
+ saga implement my-story --attached --stream
86
89
  ```
87
90
 
88
91
  Options:
89
92
  - `--max-cycles <n>` - Maximum number of worker cycles (default: 10)
90
93
  - `--max-time <n>` - Maximum time in minutes (default: 60)
91
94
  - `--model <name>` - Model to use (default: opus)
95
+ - `--attached` - Run in attached mode (synchronous). Default is detached (runs in tmux session)
96
+ - `--stream` - Stream worker output to stdout (only works with `--attached`)
97
+
98
+ By default, `implement` runs in **detached mode** using a tmux session. This allows the worker to continue running even if your terminal disconnects. Use `saga sessions` to monitor detached sessions.
92
99
 
93
100
  **Note:** Requires `SAGA_PLUGIN_ROOT` environment variable to be set. This is automatically configured when running via the SAGA plugin.
94
101
 
102
+ ### `saga sessions`
103
+
104
+ Manage tmux sessions created by detached `implement` runs.
105
+
106
+ ```bash
107
+ saga sessions list # List all SAGA sessions
108
+ saga sessions status <name> # Check if session is running
109
+ saga sessions logs <name> # Stream session output
110
+ saga sessions kill <name> # Terminate a session
111
+ ```
112
+
113
+ Subcommands:
114
+ - `list` - Returns JSON array of all SAGA sessions with name, status, and output file
115
+ - `status <name>` - Returns JSON `{running: boolean}` for the session
116
+ - `logs <name>` - Streams the session output file via `tail -f`
117
+ - `kill <name>` - Terminates the session, returns JSON `{killed: boolean}`
118
+
95
119
  ### `saga dashboard`
96
120
 
97
121
  Start the SAGA dashboard server for viewing epics, stories, and progress.
package/dist/cli.cjs CHANGED
@@ -1042,6 +1042,22 @@ function formatStreamLine(line) {
1042
1042
  return null;
1043
1043
  }
1044
1044
  }
1045
+ function extractStructuredOutputFromToolCall(lines) {
1046
+ for (let i = lines.length - 1; i >= 0; i--) {
1047
+ try {
1048
+ const data = JSON.parse(lines[i]);
1049
+ if (data.type === "assistant" && data.message?.content) {
1050
+ for (const block of data.message.content) {
1051
+ if (block.type === "tool_use" && block.name === "StructuredOutput") {
1052
+ return block.input;
1053
+ }
1054
+ }
1055
+ }
1056
+ } catch {
1057
+ }
1058
+ }
1059
+ return null;
1060
+ }
1045
1061
  function parseStreamingResult(buffer) {
1046
1062
  const lines = buffer.split("\n").filter((line) => line.trim());
1047
1063
  for (let i = lines.length - 1; i >= 0; i--) {
@@ -1051,10 +1067,13 @@ function parseStreamingResult(buffer) {
1051
1067
  if (data.is_error) {
1052
1068
  throw new Error(`Worker failed: ${data.result || "Unknown error"}`);
1053
1069
  }
1054
- if (!data.structured_output) {
1070
+ let output = data.structured_output;
1071
+ if (!output) {
1072
+ output = extractStructuredOutputFromToolCall(lines);
1073
+ }
1074
+ if (!output) {
1055
1075
  throw new Error("Worker result missing structured_output");
1056
1076
  }
1057
- const output = data.structured_output;
1058
1077
  if (!VALID_STATUSES.has(output.status)) {
1059
1078
  throw new Error(`Invalid status: ${output.status}`);
1060
1079
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saga-ai/cli",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "description": "CLI for SAGA - Structured Autonomous Goal Achievement",
5
5
  "type": "module",
6
6
  "bin": {