autark-cli 0.1.2 → 0.1.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.
- package/README.md +20 -12
- package/autark.mjs +99 -36
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,26 +20,34 @@ autark login verify your@email.com --code 123456
|
|
|
20
20
|
|
|
21
21
|
## Use
|
|
22
22
|
|
|
23
|
+
Autark is ID-first. Use `product list` / `context` to discover IDs, then pass IDs for writes. `slug/H01` remains a convenience alias.
|
|
24
|
+
|
|
23
25
|
```sh
|
|
24
26
|
# products
|
|
25
|
-
autark product upsert --slug chrome-relay --name "
|
|
26
|
-
autark product list
|
|
27
|
+
autark product upsert --slug chrome-relay --name "Chrome Relay" --tagline "..."
|
|
28
|
+
autark product list # prints slug, visibility, id, name
|
|
29
|
+
autark context chrome-relay
|
|
30
|
+
|
|
31
|
+
autark context --product-id <product_id>
|
|
27
32
|
|
|
28
33
|
# hypotheses
|
|
29
|
-
autark hypothesis create --product
|
|
30
|
-
autark hypothesis
|
|
34
|
+
autark hypothesis create --product-id <product_id> --md @./H01.md --code H01 --title "..."
|
|
35
|
+
autark context --hypothesis-id <hypothesis_id>
|
|
36
|
+
autark hypothesis status --hypothesis-id <hypothesis_id> --status active # active|inactive|dead
|
|
37
|
+
|
|
38
|
+
# aliases still work
|
|
39
|
+
autark hypothesis create --product chrome-relay --md @./H01.md --code H01
|
|
40
|
+
autark context chrome-relay/H01
|
|
41
|
+
autark hypothesis status chrome-relay/H01 --status inactive
|
|
31
42
|
|
|
32
43
|
# runs
|
|
33
|
-
autark run start --hypothesis
|
|
34
|
-
autark run finish --run <run_id> --narrative @./narrative.md
|
|
44
|
+
autark run start --hypothesis-id <hypothesis_id>
|
|
45
|
+
autark run finish --run-id <run_id> --narrative @./narrative.md
|
|
35
46
|
|
|
36
47
|
# actions (anything the agent did during a run)
|
|
37
|
-
autark log action --run <run_id> --channel email --title "..." \
|
|
48
|
+
autark log action --run-id <run_id> --channel email --title "..." \
|
|
38
49
|
--recipient person@example.com --agentmail-thread-id <thread_id>
|
|
39
|
-
autark log action --run <run_id> --channel github --title "..." --url https://github.com/...
|
|
40
|
-
|
|
41
|
-
# context (full hypothesis state for an agent picking up work)
|
|
42
|
-
autark context chrome-relay/H01
|
|
50
|
+
autark log action --run-id <run_id> --channel github --title "..." --url https://github.com/...
|
|
43
51
|
|
|
44
52
|
autark me
|
|
45
53
|
autark logout
|
|
@@ -53,4 +61,4 @@ autark logout
|
|
|
53
61
|
|
|
54
62
|
The CLI is a thin HTTP client over a Cloudflare Worker that holds the InstantDB admin token. Magic-link auth via InstantDB. Token saved to `~/.autark/credentials.json` after login.
|
|
55
63
|
|
|
56
|
-
The web at autark.kushalsm.com
|
|
64
|
+
The web at autark.kushalsm.com reads from InstantDB. Writes should go through the Worker/CLI path; dashboard direct writes are being phased out.
|
package/autark.mjs
CHANGED
|
@@ -4,10 +4,8 @@
|
|
|
4
4
|
// Auth: magic-link flow saves a refresh_token to ~/.autark/credentials.json.
|
|
5
5
|
// Every subsequent command sends it as `Authorization: Bearer <token>`.
|
|
6
6
|
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
// calls, formats output. Replace this binary in any language tomorrow and
|
|
10
|
-
// the system still works.
|
|
7
|
+
// The CLI is ID-first: once a product/hypothesis/run exists, use its id.
|
|
8
|
+
// slug/Hxx remains as a convenience alias for humans.
|
|
11
9
|
|
|
12
10
|
import fs from 'node:fs'
|
|
13
11
|
import os from 'node:os'
|
|
@@ -116,7 +114,7 @@ async function productList() {
|
|
|
116
114
|
return
|
|
117
115
|
}
|
|
118
116
|
for (const p of result.products) {
|
|
119
|
-
console.log(`${(p.slug || '').padEnd(20)} ${(p.visibility || '').padEnd(8)} ${p.name || ''}`)
|
|
117
|
+
console.log(`${(p.slug || '').padEnd(20)} ${(p.visibility || '').padEnd(8)} ${(p.id || '').padEnd(36)} ${p.name || ''}`)
|
|
120
118
|
}
|
|
121
119
|
}
|
|
122
120
|
|
|
@@ -124,45 +122,65 @@ async function productList() {
|
|
|
124
122
|
|
|
125
123
|
async function hypothesisCreate(rest) {
|
|
126
124
|
const opts = parseArgs(rest)
|
|
127
|
-
const
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
product, code, md,
|
|
133
|
-
title: title || undefined,
|
|
125
|
+
const md = readValue(required(opts.md, '--md'))
|
|
126
|
+
const body = {
|
|
127
|
+
md,
|
|
128
|
+
code: opts.code || undefined,
|
|
129
|
+
title: opts.title || undefined,
|
|
134
130
|
status: opts.status || undefined,
|
|
135
|
-
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
let result
|
|
134
|
+
if (opts['product-id'] || opts.product_id) {
|
|
135
|
+
const productId = opts['product-id'] || opts.product_id
|
|
136
|
+
result = await api('POST', `/v1/products/${encodeURIComponent(productId)}/hypotheses`, body)
|
|
137
|
+
} else {
|
|
138
|
+
body.product = required(opts.product, '--product or --product-id')
|
|
139
|
+
result = await api('POST', '/v1/hypotheses', body)
|
|
140
|
+
}
|
|
136
141
|
console.log(result.id)
|
|
137
142
|
}
|
|
138
143
|
|
|
139
144
|
async function hypothesisStatus(rest) {
|
|
140
145
|
const opts = parseArgs(rest)
|
|
141
|
-
const ref = required(opts._[0] || opts.hypothesis, 'hypothesis (e.g. chrome-relay/H01)')
|
|
142
146
|
const status = required(opts.status, '--status')
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if (!hypId)
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
let hypId = opts['hypothesis-id'] || opts.hypothesis_id || opts.id
|
|
148
|
+
let label = hypId
|
|
149
|
+
|
|
150
|
+
if (!hypId) {
|
|
151
|
+
const ref = required(opts._[0] || opts.hypothesis, 'hypothesis id or product/Hxx')
|
|
152
|
+
const [productSlug, code] = splitHypothesisRef(ref)
|
|
153
|
+
const ctx = await api('GET', `/v1/context/${encodeURIComponent(productSlug)}/${encodeURIComponent(code)}`)
|
|
154
|
+
hypId = ctx.hypothesis?.id
|
|
155
|
+
label = ref
|
|
156
|
+
}
|
|
157
|
+
if (!hypId) throw new Error('hypothesis not found')
|
|
158
|
+
|
|
159
|
+
const result = await api('PATCH', `/v1/hypotheses/${encodeURIComponent(hypId)}/status`, { status })
|
|
160
|
+
console.log(`${label} → ${result.status}`)
|
|
149
161
|
}
|
|
150
162
|
|
|
151
163
|
// =============================================================== runs
|
|
152
164
|
|
|
153
165
|
async function runStart(rest) {
|
|
154
166
|
const opts = parseArgs(rest)
|
|
155
|
-
|
|
156
|
-
const [
|
|
157
|
-
|
|
167
|
+
let result
|
|
168
|
+
const hypId = opts['hypothesis-id'] || opts.hypothesis_id
|
|
169
|
+
if (hypId) {
|
|
170
|
+
result = await api('POST', `/v1/hypotheses/${encodeURIComponent(hypId)}/runs`, {})
|
|
171
|
+
} else {
|
|
172
|
+
const ref = required(opts.hypothesis || opts._[0], '--hypothesis-id <id> or --hypothesis <slug/Hxx>')
|
|
173
|
+
const [productSlug, code] = splitHypothesisRef(ref)
|
|
174
|
+
result = await api('POST', '/v1/runs', { product: productSlug, hypothesis: code })
|
|
175
|
+
}
|
|
158
176
|
console.log(result.id)
|
|
159
177
|
}
|
|
160
178
|
|
|
161
179
|
async function runFinish(rest) {
|
|
162
180
|
const opts = parseArgs(rest)
|
|
163
|
-
const id
|
|
181
|
+
const id = required(opts['run-id'] || opts.run_id || opts.run, '--run-id')
|
|
164
182
|
const narrative = readValue(required(opts.narrative, '--narrative'))
|
|
165
|
-
const result = await api('PATCH', `/v1/runs/${id}/finish`, { narrative_md: narrative })
|
|
183
|
+
const result = await api('PATCH', `/v1/runs/${encodeURIComponent(id)}/finish`, { narrative_md: narrative })
|
|
166
184
|
console.log(`${result.id} finished_at=${result.finished_at}`)
|
|
167
185
|
}
|
|
168
186
|
|
|
@@ -170,11 +188,10 @@ async function runFinish(rest) {
|
|
|
170
188
|
|
|
171
189
|
async function logAction(rest) {
|
|
172
190
|
const opts = parseArgs(rest)
|
|
173
|
-
const run = required(opts.run, '--run')
|
|
191
|
+
const run = required(opts['run-id'] || opts.run_id || opts.run, '--run-id')
|
|
174
192
|
const channel = required(opts.channel, '--channel')
|
|
175
193
|
const title = required(opts.title, '--title')
|
|
176
|
-
const result = await api('POST',
|
|
177
|
-
run,
|
|
194
|
+
const result = await api('POST', `/v1/runs/${encodeURIComponent(run)}/actions`, {
|
|
178
195
|
channel,
|
|
179
196
|
title,
|
|
180
197
|
url: opts.url || undefined,
|
|
@@ -190,11 +207,51 @@ async function logAction(rest) {
|
|
|
190
207
|
|
|
191
208
|
async function context(rest) {
|
|
192
209
|
const opts = parseArgs(rest)
|
|
193
|
-
|
|
194
|
-
|
|
210
|
+
|
|
211
|
+
if (opts['product-id'] || opts.product_id) {
|
|
212
|
+
const productId = opts['product-id'] || opts.product_id
|
|
213
|
+
return printProductContext(await api('GET', `/v1/products/${encodeURIComponent(productId)}/context`))
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (opts['hypothesis-id'] || opts.hypothesis_id) {
|
|
217
|
+
const hypId = opts['hypothesis-id'] || opts.hypothesis_id
|
|
218
|
+
return printHypothesisContext(await api('GET', `/v1/hypotheses/${encodeURIComponent(hypId)}/context`))
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const ref = required(opts._[0] || opts.hypothesis, 'product slug, product/Hxx, --product-id, or --hypothesis-id')
|
|
222
|
+
const parts = ref.split('/')
|
|
223
|
+
const productSlug = parts[0]
|
|
224
|
+
const code = parts[1]
|
|
225
|
+
|
|
226
|
+
if (!code) {
|
|
227
|
+
return printProductContext(await api('GET', `/v1/context/${encodeURIComponent(productSlug)}`))
|
|
228
|
+
}
|
|
229
|
+
|
|
195
230
|
const result = await api('GET', `/v1/context/${encodeURIComponent(productSlug)}/${encodeURIComponent(code)}`)
|
|
231
|
+
return printHypothesisContext(result)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function printProductContext(r) {
|
|
235
|
+
console.log(`# ${r.product.slug} — ${r.product.name}`)
|
|
236
|
+
console.log(`id: ${r.product.id}`)
|
|
237
|
+
if (r.product.tagline) console.log(`> ${r.product.tagline}`)
|
|
238
|
+
if (r.product.url) console.log(`> ${r.product.url}`)
|
|
239
|
+
console.log(`\n## Brief\n`)
|
|
240
|
+
console.log(r.product.brief?.trim() || '(no brief set — owner can add one at https://autark.kushalsm.com)')
|
|
241
|
+
console.log(`\n## Hypotheses (${r.hypotheses.length})\n`)
|
|
242
|
+
if (!r.hypotheses.length) {
|
|
243
|
+
console.log('(none yet — create one with: autark hypothesis create --product-id <product_id> --md @hyp.md)')
|
|
244
|
+
} else {
|
|
245
|
+
for (const h of r.hypotheses) {
|
|
246
|
+
console.log(`- [${h.status}] ${h.code} id=${h.id} — ${h.title} (runs: ${h.run_count})`)
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
196
250
|
|
|
251
|
+
function printHypothesisContext(result) {
|
|
197
252
|
console.log(`# ${result.product.slug}/${result.hypothesis.code} — ${result.hypothesis.title}\n`)
|
|
253
|
+
console.log(`product_id: ${result.product.id}`)
|
|
254
|
+
console.log(`hypothesis_id: ${result.hypothesis.id}`)
|
|
198
255
|
console.log(`Status: ${result.hypothesis.status}\n`)
|
|
199
256
|
console.log(result.hypothesis.hypothesis_md)
|
|
200
257
|
for (const run of result.runs) {
|
|
@@ -309,17 +366,23 @@ function usage() {
|
|
|
309
366
|
autark me show signed-in user
|
|
310
367
|
|
|
311
368
|
autark product upsert --slug <slug> --name <name> [--url <url>] [--tagline <text>] [--brief @./brief.md] [--visibility private|public]
|
|
312
|
-
autark product list
|
|
369
|
+
autark product list prints slug, visibility, id, name
|
|
313
370
|
|
|
314
|
-
autark hypothesis create --product <
|
|
315
|
-
autark hypothesis
|
|
371
|
+
autark hypothesis create --product-id <id> --md @./hyp.md [--code H01] [--title <t>]
|
|
372
|
+
autark hypothesis create --product <slug> --md @./hyp.md [--code H01] [--title <t>] # alias
|
|
373
|
+
autark hypothesis status --hypothesis-id <id> --status active|inactive|dead
|
|
374
|
+
autark hypothesis status <slug>/<H01> --status active|inactive|dead # alias
|
|
316
375
|
|
|
317
|
-
autark run start --hypothesis <
|
|
318
|
-
autark run
|
|
376
|
+
autark run start --hypothesis-id <id>
|
|
377
|
+
autark run start --hypothesis <slug>/<H01> # alias
|
|
378
|
+
autark run finish --run-id <id> --narrative @./run.md
|
|
319
379
|
|
|
320
|
-
autark log action --run <id> --channel <c> --title <t> [--url <u>]
|
|
380
|
+
autark log action --run-id <id> --channel <c> --title <t> [--url <u>]
|
|
321
381
|
[--agentmail-thread-id <uuid>] [--recipient <email>]
|
|
322
382
|
[--metadata @./meta.json]
|
|
323
383
|
|
|
384
|
+
autark context --product-id <id>
|
|
385
|
+
autark context --hypothesis-id <id>
|
|
386
|
+
autark context <slug>
|
|
324
387
|
autark context <slug>/<H01>`)
|
|
325
388
|
}
|
package/package.json
CHANGED