@dmsdc-ai/aterm-darwin-arm64 0.1.39 → 0.1.40

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.
Binary file
@@ -0,0 +1,225 @@
1
+ #!/usr/bin/env bash
2
+ # aterm — CLI for aterm internal workspace communication
3
+ # Sends NDJSON over $ATERM_IPC_SOCKET. Falls back to telepty outside aterm.
4
+ set -euo pipefail
5
+
6
+ ATERM_IPC_SOCKET="${ATERM_IPC_SOCKET:-}"
7
+
8
+ # State directory for task board and lessons
9
+ STATE_DIR="${PWD}/state"
10
+
11
+ tasks_file() { echo "${STATE_DIR}/task-queue.json"; }
12
+ lessons_file() { echo "${STATE_DIR}/lessons.json"; }
13
+
14
+ ensure_state_dir() { mkdir -p "$STATE_DIR"; }
15
+
16
+ ensure_tasks_file() {
17
+ ensure_state_dir
18
+ local f; f="$(tasks_file)"
19
+ [ -f "$f" ] || echo '{"tasks":[],"completed":[]}' > "$f"
20
+ }
21
+
22
+ ensure_lessons_file() {
23
+ ensure_state_dir
24
+ local f; f="$(lessons_file)"
25
+ [ -f "$f" ] || echo '{"invariants":[],"failed":[]}' > "$f"
26
+ }
27
+
28
+ aterm_ipc() {
29
+ python3 -c '
30
+ import socket, sys, json
31
+
32
+ sock_path = sys.argv[1]
33
+ action = sys.argv[2]
34
+ args = sys.argv[3:]
35
+
36
+ payloads = {
37
+ "list": lambda: {"action": "ListWorkspaces"},
38
+ "inject": lambda: {"action": "Inject", "workspace": args[0],
39
+ "text": " ".join(args[1:]),
40
+ "from": __import__("os").environ.get("ATERM_WORKSPACE_NAME")},
41
+ "status": lambda: {"action": "WorkspaceStatus", "workspace": args[0]},
42
+ "focus": lambda: {"action": "FocusWorkspace", "workspace": args[0]},
43
+ }
44
+
45
+ payload = json.dumps(payloads[action]()) + "\n"
46
+
47
+ sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
48
+ try:
49
+ sock.settimeout(5)
50
+ sock.connect(sock_path)
51
+ sock.sendall(payload.encode())
52
+ sock.shutdown(socket.SHUT_WR)
53
+ data = b""
54
+ while True:
55
+ chunk = sock.recv(4096)
56
+ if not chunk:
57
+ break
58
+ data += chunk
59
+ if b"\n" in data:
60
+ break
61
+ resp = json.loads(data.decode().strip().split("\n")[0])
62
+
63
+ if resp.get("status") == "Error":
64
+ print(json.dumps({"error": resp["message"]}), file=sys.stderr)
65
+ sys.exit(1)
66
+ elif action == "list":
67
+ print(json.dumps({"sessions": resp.get("data", [])}))
68
+ elif action == "status":
69
+ print(json.dumps(resp.get("data", {})))
70
+ else:
71
+ print(json.dumps({"status": "ok"}))
72
+ except Exception as e:
73
+ print(json.dumps({"error": str(e)}), file=sys.stderr)
74
+ sys.exit(1)
75
+ finally:
76
+ sock.close()
77
+ ' "$ATERM_IPC_SOCKET" "$@"
78
+ }
79
+
80
+ case "${1:-help}" in
81
+ list)
82
+ if [[ -z "$ATERM_IPC_SOCKET" ]]; then exec telepty list "${@:2}"; fi
83
+ aterm_ipc list ;;
84
+ inject)
85
+ if [[ -z "$ATERM_IPC_SOCKET" ]]; then exec telepty inject "${@:2}"; fi
86
+ [[ $# -lt 3 ]] && { echo '{"error":"usage: aterm inject <workspace> <text>"}' >&2; exit 1; }
87
+ aterm_ipc inject "${@:2}" ;;
88
+ status)
89
+ if [[ -z "$ATERM_IPC_SOCKET" ]]; then exec telepty status "${@:2}"; fi
90
+ [[ $# -lt 2 ]] && { echo '{"error":"usage: aterm status <workspace>"}' >&2; exit 1; }
91
+ aterm_ipc status "$2" ;;
92
+ focus)
93
+ [[ -z "$ATERM_IPC_SOCKET" ]] && { echo '{"error":"focus requires aterm (ATERM_IPC_SOCKET not set)"}' >&2; exit 1; }
94
+ [[ $# -lt 2 ]] && { echo '{"error":"usage: aterm focus <workspace>"}' >&2; exit 1; }
95
+ aterm_ipc focus "$2" ;;
96
+ tasks)
97
+ ensure_tasks_file
98
+ case "${2:-list}" in
99
+ list)
100
+ python3 -c '
101
+ import json, sys
102
+ with open(sys.argv[1]) as f: data = json.load(f)
103
+ if not data.get("tasks"):
104
+ print("No pending tasks.")
105
+ sys.exit(0)
106
+ for i, t in enumerate(data["tasks"]):
107
+ tid = t.get("id", i)
108
+ desc = t.get("description", t) if isinstance(t, dict) else t
109
+ print(f" [{tid}] {desc}")
110
+ ' "$(tasks_file)" ;;
111
+ add)
112
+ [[ $# -lt 3 ]] && { echo '{"error":"usage: aterm tasks add <description>"}' >&2; exit 1; }
113
+ python3 -c '
114
+ import json, sys, time
115
+ f = sys.argv[1]; desc = " ".join(sys.argv[2:])
116
+ with open(f) as fh: data = json.load(fh)
117
+ tid = int(time.time() * 1000) % 100000
118
+ data["tasks"].append({"id": tid, "description": desc})
119
+ with open(f, "w") as fh: json.dump(data, fh, indent=2, ensure_ascii=False); fh.write("\n")
120
+ print(json.dumps({"status":"ok","id": tid}))
121
+ ' "$(tasks_file)" "${@:3}" ;;
122
+ done)
123
+ [[ $# -lt 3 ]] && { echo '{"error":"usage: aterm tasks done <id>"}' >&2; exit 1; }
124
+ python3 -c '
125
+ import json, sys
126
+ f = sys.argv[1]; target = int(sys.argv[2])
127
+ with open(f) as fh: data = json.load(fh)
128
+ found = None
129
+ for i, t in enumerate(data["tasks"]):
130
+ tid = t.get("id", i) if isinstance(t, dict) else i
131
+ if tid == target:
132
+ found = data["tasks"].pop(i)
133
+ break
134
+ if not found:
135
+ print(json.dumps({"error": f"task {target} not found"}), file=sys.stderr); sys.exit(1)
136
+ data.setdefault("completed", []).append(found)
137
+ with open(f, "w") as fh: json.dump(data, fh, indent=2, ensure_ascii=False); fh.write("\n")
138
+ print(json.dumps({"status":"ok","id": target}))
139
+ ' "$(tasks_file)" "$3" ;;
140
+ *) echo '{"error":"usage: aterm tasks [list|add|done]"}' >&2; exit 1 ;;
141
+ esac ;;
142
+ lessons)
143
+ ensure_lessons_file
144
+ case "${2:-list}" in
145
+ list)
146
+ python3 -c '
147
+ import json, sys
148
+ with open(sys.argv[1]) as f: data = json.load(f)
149
+ inv = data.get("invariants", [])
150
+ fail = data.get("failed", [])
151
+ if not inv and not fail:
152
+ print("No lessons recorded.")
153
+ sys.exit(0)
154
+ if inv:
155
+ print("Invariants:")
156
+ for l in inv: print(f" - {l}")
157
+ if fail:
158
+ print("Failed patterns:")
159
+ for l in fail: print(f" - {l}")
160
+ ' "$(lessons_file)" ;;
161
+ add)
162
+ [[ $# -lt 3 ]] && { echo '{"error":"usage: aterm lessons add <lesson> [--type invariant|failed]"}' >&2; exit 1; }
163
+ python3 -c '
164
+ import json, sys
165
+ f = sys.argv[1]; lesson = sys.argv[2]
166
+ ltype = "invariants"
167
+ if "--type" in sys.argv:
168
+ idx = sys.argv.index("--type")
169
+ if idx + 1 < len(sys.argv) and sys.argv[idx+1] == "failed":
170
+ ltype = "failed"
171
+ with open(f) as fh: data = json.load(fh)
172
+ data.setdefault(ltype, []).append(lesson)
173
+ with open(f, "w") as fh: json.dump(data, fh, indent=2, ensure_ascii=False); fh.write("\n")
174
+ print(json.dumps({"status":"ok","type": ltype}))
175
+ ' "$(lessons_file)" "${@:3}" ;;
176
+ *) echo '{"error":"usage: aterm lessons [list|add]"}' >&2; exit 1 ;;
177
+ esac ;;
178
+ help|--help|-h)
179
+ cat <<'HELP'
180
+ # aterm — AI-native terminal session communication
181
+
182
+ ## Commands
183
+
184
+ | Command | Description |
185
+ |---------|-------------|
186
+ | `aterm list` | List all workspaces (JSON) |
187
+ | `aterm inject <workspace> <text>` | Send text to a workspace |
188
+ | `aterm status <workspace>` | Check workspace status |
189
+ | `aterm focus <workspace>` | Focus a workspace tab |
190
+ | `aterm tasks` | List pending tasks |
191
+ | `aterm tasks add '<description>'` | Add a new task |
192
+ | `aterm tasks done <id>` | Mark task as completed |
193
+ | `aterm lessons` | List recorded lessons |
194
+ | `aterm lessons add '<lesson>'` | Add a lesson (invariant) |
195
+ | `aterm lessons add '<lesson>' --type failed` | Add a failed pattern |
196
+ | `aterm help` | Show this help |
197
+
198
+ ## Natural Language → Command Mapping
199
+
200
+ ### Internal sessions (same aterm, $ATERM_IPC_SOCKET set)
201
+ | Natural language | Command |
202
+ |-----------------|---------|
203
+ | 'list sessions' / '세션 목록 보여줘' | `aterm list` |
204
+ | 'send build to ghostty' / 'ghostty에 빌드 실행해줘' | `aterm inject ghostty 'make build'` |
205
+ | 'check cmux status' / 'cmux 세션 상태 확인해줘' | `aterm status cmux` |
206
+ | 'show tasks' / '태스크 목록 보여줘' | `aterm tasks` |
207
+ | 'add task: implement API' / '태스크 추가해줘: API 구현' | `aterm tasks add 'API 구현'` |
208
+ | 'task 42 done' / '태스크 42 완료' | `aterm tasks done 42` |
209
+ | 'show lessons' / '레슨 보여줘' | `aterm lessons` |
210
+ | 'add lesson: this pattern failed' / '레슨 추가' | `aterm lessons add 'this pattern failed'` |
211
+
212
+ ### External sessions (other terminal/machine, $ATERM_IPC_SOCKET unset)
213
+ | Natural language | Command |
214
+ |-----------------|---------|
215
+ | 'list external sessions' / '외부 세션 목록' | `telepty list` |
216
+ | 'message deliberation session' | `telepty inject aigentry-deliberation-claude 'message'` |
217
+
218
+ ## Detection Rules
219
+ - `$ATERM_IPC_SOCKET` set → inside aterm. Use `aterm` commands.
220
+ - `$ATERM_IPC_SOCKET` unset → outside aterm. Use `telepty` commands.
221
+ - `aterm` falls back to `telepty` automatically for list/inject/status.
222
+ HELP
223
+ ;;
224
+ *) echo "{\"error\":\"unknown command: $1\"}" >&2; exit 1 ;;
225
+ esac
@@ -3,17 +3,29 @@
3
3
  <plist version="1.0">
4
4
  <dict>
5
5
  <key>files</key>
6
- <dict/>
6
+ <dict>
7
+ <key>Resources/bin/aterm</key>
8
+ <data>
9
+ gFvuG9DaXYDL7UTWZL/Tq5PcKnc=
10
+ </data>
11
+ </dict>
7
12
  <key>files2</key>
8
13
  <dict>
9
14
  <key>Frameworks/libaterm_core.dylib</key>
10
15
  <dict>
11
16
  <key>cdhash</key>
12
17
  <data>
13
- ooi5+vQ640BmC1YjDJ3VHjotVnk=
18
+ uYvXBprRTfl+0wtcioq+d1tWf6U=
14
19
  </data>
15
20
  <key>requirement</key>
16
- <string>cdhash H"a288b9faf43ae340660b56230c9dd51e3a2d5679"</string>
21
+ <string>cdhash H"b98bd7069ad14df97ed30b5c8a8abe775b567fa5"</string>
22
+ </dict>
23
+ <key>Resources/bin/aterm</key>
24
+ <dict>
25
+ <key>hash2</key>
26
+ <data>
27
+ MK+VFroryYcLv27zSIhkens5mXnx7gSJjhf90/iwmdQ=
28
+ </data>
17
29
  </dict>
18
30
  </dict>
19
31
  <key>rules</key>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dmsdc-ai/aterm-darwin-arm64",
3
- "version": "0.1.39",
3
+ "version": "0.1.40",
4
4
  "description": "darwin-arm64 native bundle for @dmsdc-ai/aterm",
5
5
  "type": "module",
6
6
  "files": [