@vforsh/argus 0.4.0 → 0.5.0

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 (36) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/argus.js +1108 -558
  3. package/dist/cli/program.d.ts +11 -1
  4. package/dist/cli/program.d.ts.map +1 -1
  5. package/dist/cli/program.js +14 -9
  6. package/dist/cli/program.js.map +1 -1
  7. package/dist/cli/register/index.d.ts.map +1 -1
  8. package/dist/cli/register/index.js +2 -0
  9. package/dist/cli/register/index.js.map +1 -1
  10. package/dist/cli/register/sessionCommands.d.ts +3 -0
  11. package/dist/cli/register/sessionCommands.d.ts.map +1 -0
  12. package/dist/cli/register/sessionCommands.js +24 -0
  13. package/dist/cli/register/sessionCommands.js.map +1 -0
  14. package/dist/output/io.d.ts +7 -0
  15. package/dist/output/io.d.ts.map +1 -1
  16. package/dist/output/io.js +21 -2
  17. package/dist/output/io.js.map +1 -1
  18. package/dist/session/runSession.d.ts +15 -0
  19. package/dist/session/runSession.d.ts.map +1 -0
  20. package/dist/session/runSession.js +184 -0
  21. package/dist/session/runSession.js.map +1 -0
  22. package/dist/session/sessionArgv.d.ts +42 -0
  23. package/dist/session/sessionArgv.d.ts.map +1 -0
  24. package/dist/session/sessionArgv.js +224 -0
  25. package/dist/session/sessionArgv.js.map +1 -0
  26. package/dist/session/sessionDispatch.d.ts +21 -0
  27. package/dist/session/sessionDispatch.d.ts.map +1 -0
  28. package/dist/session/sessionDispatch.js +137 -0
  29. package/dist/session/sessionDispatch.js.map +1 -0
  30. package/dist/session/stdioCapture.d.ts +33 -0
  31. package/dist/session/stdioCapture.d.ts.map +1 -0
  32. package/dist/session/stdioCapture.js +56 -0
  33. package/dist/session/stdioCapture.js.map +1 -0
  34. package/dist/skill/argus/SKILL.md +29 -0
  35. package/dist/skill/argus/reference/SESSION.md +153 -0
  36. package/package.json +5 -5
@@ -0,0 +1,153 @@
1
+ # Session Transport
2
+
3
+ `argus session` serves many commands from one process over stdin/stdout. Use it when a harness
4
+ issues dozens of sequential commands against the same watcher: each one-shot `argus` invocation
5
+ pays Node startup plus watcher discovery (~100-200ms), and the session pays it once.
6
+
7
+ ```bash
8
+ argus session app
9
+ argus session app --request-timeout 30s
10
+ argus session app --reconnect
11
+ ```
12
+
13
+ The watcher id is resolved once and pinned. Every request runs the same Commander action the
14
+ one-shot CLI would run, with `--json` forced on, so payloads match `argus <cmd> --json` byte for
15
+ byte and a host can switch transports without changing how it parses results.
16
+
17
+ ---
18
+
19
+ ## Framing
20
+
21
+ stdin takes one JSON object per line; stdout answers with one JSON object per line and nothing
22
+ else. Human output goes to stderr.
23
+
24
+ The first line is written before any request is read:
25
+
26
+ ```json
27
+ { "type": "ready", "protocolVersion": 1, "argusVersion": "0.4.0", "watcher": { "id": "app", "host": "127.0.0.1", "port": 51733 } }
28
+ ```
29
+
30
+ ### Request
31
+
32
+ | Field | Type | Notes |
33
+ | --------- | ---------------- | ------------------------------------------------------------------ |
34
+ | `id` | string \| number | Optional; echoed on the response. Omit only if you match by order. |
35
+ | `cmd` | string | Command path, space-separated. Aliases work (`js`, `ext`, `wait`). |
36
+ | `args` | object | Named arguments. Mutually exclusive with `argv`. |
37
+ | `argv` | string[] | Raw CLI tokens. Mutually exclusive with `args`. |
38
+ | `timeout` | string \| number | Per-request watchdog (`"30s"`, or milliseconds). `0` disables. |
39
+
40
+ ```json
41
+ {"id": 1, "cmd": "eval", "args": {"expression": "location.href"}}
42
+ {"id": 2, "cmd": "eval-until", "args": {"expression": "window.APP_READY", "totalTimeout": "30s"}}
43
+ {"id": 3, "cmd": "click", "args": {"selector": "button.submit"}}
44
+ {"id": 4, "cmd": "drag", "argv": ["--selector", "canvas", "--pos", "320,240", "--by", "80,-30"]}
45
+ {"id": 5, "cmd": "screenshot", "args": {"out": "./shot.png"}}
46
+ {"id": 6, "cmd": "dom tree", "args": {"selector": "body", "depth": 2}}
47
+ ```
48
+
49
+ `args` keys are resolved against the command's own definition, so anything the CLI accepts is
50
+ reachable:
51
+
52
+ - **Options** match by camelCase name, long flag, or short flag: `totalTimeout`, `total-timeout`,
53
+ and `q` all work.
54
+ - **Positional arguments** match by their declared name (`key`/`value` for `storage local set`,
55
+ `role` for `locate role`) and are filled in declaration order. The leading watcher id is
56
+ injected for you.
57
+ - **An option wins over a positional of the same name.** `{"expression": "…"}` on `eval` becomes
58
+ `--expression`, the spelling the CLI already documents as equivalent to the positional.
59
+ - **Repeatable options** take an array: `{"arg": ["level=10", "mode=fast"]}`.
60
+ - **Switches** take a boolean: `{"all": true}`, `{"await": false}` (which sends `--no-await`).
61
+
62
+ ### Response
63
+
64
+ ```json
65
+ {"id": 1, "ok": true, "result": {"ok": true, "result": "https://app.example/", "type": "string", "exception": null}, "durationMs": 8}
66
+ {"id": 2, "ok": false, "error": {"message": "Total timeout exceeded (30s)", "code": "session_command_failed"}, "exitCode": 1, "durationMs": 30014}
67
+ ```
68
+
69
+ - `result` is the command's `--json` document. A command that streams newline-delimited JSON
70
+ (`eval --interval`) yields an array plus `"stream": true`; output that is not JSON at all comes
71
+ back verbatim as a string plus `"raw": true`.
72
+ - `stderr` is present when the command wrote any, on success or failure. It is also mirrored to
73
+ the session's own stderr, so a human tailing the process still sees it live.
74
+ - `durationMs` is the wall-clock time the CLI spent on the request.
75
+
76
+ ### Control requests
77
+
78
+ | `cmd` | Effect |
79
+ | ------ | ------------------------------------------------------------ |
80
+ | `ping` | Answers `{"pong": true, "watcher": "<id>"}` without any I/O. |
81
+ | `quit` | Answers, then closes the session with exit code 0. |
82
+
83
+ ---
84
+
85
+ ## Semantics
86
+
87
+ **Ordering.** Requests are served strictly in submission order. Pipelining still pays off — the
88
+ host can keep writing while a command is in flight — but responses arrive in the order the
89
+ requests did.
90
+
91
+ **Timeouts.** A request that outlives its watchdog is answered with `session_request_timeout` and
92
+ the session moves on. The abandoned command keeps its own output buffer, so nothing it writes
93
+ later can land in a later response.
94
+
95
+ **Error isolation.** A malformed line, an unknown command, or a failing command answers
96
+ `ok: false` and the session stays up. The `error.code` values specific to this transport are
97
+ `session_invalid_request`, `session_unknown_command`, `session_command_rejected`,
98
+ `session_request_timeout`, and `session_command_failed`; a watcher-side failure carries its own
99
+ code through unchanged.
100
+
101
+ **Watcher loss.** By default the session is fail-fast: after a failed request it probes the
102
+ watcher, and if the watcher is gone it writes a notice to stderr and exits `1`. Pass `--reconnect`
103
+ to keep it alive instead — every request re-resolves the id through the registry, so a watcher
104
+ restarted under the same id (even on a new port) is picked up on the next request.
105
+
106
+ **Shutdown.** `{"cmd": "quit"}` or EOF on stdin exits `0`. Requests still queued on stdin when the
107
+ session exits — after a `quit`, or after watcher loss — are not answered; fail them on the host
108
+ side when the process exits.
109
+
110
+ ---
111
+
112
+ ## Not available in a session
113
+
114
+ Commands that never return on their own, or that would read the stream the transport owns, are
115
+ refused with `session_command_rejected`:
116
+
117
+ - `start`, `chrome start`, `watcher start`, `watcher native-host` — daemons; run them as their own
118
+ process and point the session at the resulting watcher.
119
+ - `logs tail`, `net tail`, `net sse` — stream until interrupted.
120
+ - `session` — no nesting.
121
+ - Any request carrying `--stdin` or a `-` expression. Use `--file` or an inline expression.
122
+
123
+ ---
124
+
125
+ ## Host sketch
126
+
127
+ ```js
128
+ import { spawn } from 'node:child_process'
129
+ import readline from 'node:readline'
130
+
131
+ const proc = spawn('argus', ['session', 'app'], { stdio: ['pipe', 'pipe', 'inherit'] })
132
+ const lines = readline.createInterface({ input: proc.stdout })
133
+ const pending = new Map()
134
+ let nextId = 0
135
+
136
+ lines.on('line', (line) => {
137
+ const message = JSON.parse(line)
138
+ if (message.type === 'ready') return
139
+ pending.get(message.id)?.(message)
140
+ pending.delete(message.id)
141
+ })
142
+
143
+ const run = (cmd, args) =>
144
+ new Promise((resolve) => {
145
+ const id = ++nextId
146
+ pending.set(id, resolve)
147
+ proc.stdin.write(`${JSON.stringify({ id, cmd, args })}\n`)
148
+ })
149
+
150
+ await run('eval-until', { expression: 'window.APP_READY', totalTimeout: '30s' })
151
+ await run('click', { selector: 'button.start' })
152
+ proc.stdin.end()
153
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vforsh/argus",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/vforsh/argus.git",
@@ -30,10 +30,10 @@
30
30
  "access": "public"
31
31
  },
32
32
  "dependencies": {
33
- "@vforsh/argus-client": "^0.4.0",
34
- "@vforsh/argus-core": "^0.4.0",
35
- "@vforsh/argus-plugin-api": "^0.4.0",
36
- "@vforsh/argus-watcher": "^0.4.0",
33
+ "@vforsh/argus-client": "^0.5.0",
34
+ "@vforsh/argus-core": "^0.5.0",
35
+ "@vforsh/argus-plugin-api": "^0.5.0",
36
+ "@vforsh/argus-watcher": "^0.5.0",
37
37
  "commander": "14.0.2",
38
38
  "esbuild": "0.25.12",
39
39
  "prettier": "3.7.4"