amorphous-cli 0.1.8 → 0.1.10
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 +1 -1
- package/hooks/session-start.mjs +1 -1
- package/lib/api.mjs +17 -17
- package/lib/commands.mjs +3 -3
- package/lib/help.mjs +1 -1
- package/lib/login.mjs +1 -1
- package/lib/serve.mjs +1 -1
- package/lib/session.mjs +5 -5
- package/lib/tool-result.test.mjs +2 -2
- package/lib/update-check.mjs +1 -1
- package/lib/update-check.test.mjs +3 -3
- package/package.json +1 -1
- package/skill/amorphous/SKILL.md +10 -10
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# amorphous-cli
|
|
2
2
|
|
|
3
|
-
Make whatever you want, yourself, with your own agent, or with others. And whatever you want can be private, public, or even have users.
|
|
3
|
+
Make whatever you want, yourself, with your own agent, or with others. And whatever you want can be private, public, or even have users of its own.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
npx amorphous-cli@latest setup
|
package/hooks/session-start.mjs
CHANGED
|
@@ -48,7 +48,7 @@ if (target === 'cursor') {
|
|
|
48
48
|
process.stdout.write(
|
|
49
49
|
`${JSON.stringify({
|
|
50
50
|
additional_context:
|
|
51
|
-
'The Amorphous skill on this machine was just updated. Read ~/.agents/skills/amorphous/SKILL.md and follow it.
|
|
51
|
+
'The Amorphous skill on this machine was just updated. Read ~/.agents/skills/amorphous/SKILL.md and follow it. Install the CLI with npm install -g amorphous-cli@latest and invoke it as amorphous-cli.',
|
|
52
52
|
})}\n`,
|
|
53
53
|
)
|
|
54
54
|
} else {
|
package/lib/api.mjs
CHANGED
|
@@ -2,24 +2,24 @@ import { cliAppFetchOrigin, cliAppHostHeader } from './config.mjs'
|
|
|
2
2
|
import { ensureFreshSession } from './session.mjs'
|
|
3
3
|
|
|
4
4
|
const FRIENDLY = {
|
|
5
|
-
'You already own 2 abstracts': 'You already own 2 abstracts. Run:
|
|
6
|
-
'This abstract already has 8 people': 'This abstract already has 8 people. Run:
|
|
5
|
+
'You already own 2 abstracts': 'You already own 2 abstracts. Run: amorphous-cli list',
|
|
6
|
+
'This abstract already has 8 people': 'This abstract already has 8 people. Run: amorphous-cli people',
|
|
7
7
|
'User not found': 'No account with that email yet.',
|
|
8
|
-
'Grant failed': 'Could not invite. Run:
|
|
9
|
-
'Cannot revoke owner': "You can't remove the owner. Run:
|
|
10
|
-
'Cannot remove yourself': "You can't remove yourself. Run:
|
|
11
|
-
'Collection not found': 'Folder not found. Run:
|
|
12
|
-
Forbidden: "You don't have access. Run:
|
|
13
|
-
'Not Found': 'Not found. Run:
|
|
14
|
-
'Owner required': 'Only the owner can do that. Run:
|
|
15
|
-
'id required': 'Missing id. Run:
|
|
16
|
-
'userId required': 'Pass an email or id. Run:
|
|
17
|
-
'Invalid body': 'Invalid request. Run:
|
|
18
|
-
'Name required': 'Name required. Run:
|
|
19
|
-
'Create failed': 'Could not create the abstract. Run:
|
|
20
|
-
'Publish failed': 'Could not publish. Run:
|
|
21
|
-
'File too large': 'That file is too large. Run:
|
|
22
|
-
'Not logged in. Run: amorphous login <email>': 'Not signed in. Run:
|
|
8
|
+
'Grant failed': 'Could not invite. Run: amorphous-cli people',
|
|
9
|
+
'Cannot revoke owner': "You can't remove the owner. Run: amorphous-cli people",
|
|
10
|
+
'Cannot remove yourself': "You can't remove yourself. Run: amorphous-cli people",
|
|
11
|
+
'Collection not found': 'Folder not found. Run: amorphous-cli folder list',
|
|
12
|
+
Forbidden: "You don't have access. Run: amorphous-cli list",
|
|
13
|
+
'Not Found': 'Not found. Run: amorphous-cli list',
|
|
14
|
+
'Owner required': 'Only the owner can do that. Run: amorphous-cli people',
|
|
15
|
+
'id required': 'Missing id. Run: amorphous-cli list',
|
|
16
|
+
'userId required': 'Pass an email or id. Run: amorphous-cli people',
|
|
17
|
+
'Invalid body': 'Invalid request. Run: amorphous-cli pull',
|
|
18
|
+
'Name required': 'Name required. Run: amorphous-cli rename --name <name>',
|
|
19
|
+
'Create failed': 'Could not create the abstract. Run: amorphous-cli list',
|
|
20
|
+
'Publish failed': 'Could not publish. Run: amorphous-cli push',
|
|
21
|
+
'File too large': 'That file is too large. Run: amorphous-cli pull',
|
|
22
|
+
'Not logged in. Run: amorphous login <email>': 'Not signed in. Run: amorphous-cli login',
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
export function friendlyMessage(raw) {
|
package/lib/commands.mjs
CHANGED
|
@@ -77,7 +77,7 @@ function writeMeta(cwd, abstractId) {
|
|
|
77
77
|
function requireMeta(cwd) {
|
|
78
78
|
const meta = readMeta(cwd)
|
|
79
79
|
if (!meta?.abstractId) {
|
|
80
|
-
throw new Error('No .amorphous.json here. Run
|
|
80
|
+
throw new Error('No .amorphous.json here. Run amorphous-cli create first.')
|
|
81
81
|
}
|
|
82
82
|
return meta.abstractId
|
|
83
83
|
}
|
|
@@ -339,7 +339,7 @@ async function cmdPush(cwd, rest) {
|
|
|
339
339
|
body: JSON.stringify({ records: localRecords }),
|
|
340
340
|
})
|
|
341
341
|
if (refused?.length) {
|
|
342
|
-
console.error(`Skipped (already live): ${refused.join(', ')}. Run:
|
|
342
|
+
console.error(`Skipped (already live): ${refused.join(', ')}. Run: amorphous-cli pull`)
|
|
343
343
|
}
|
|
344
344
|
}
|
|
345
345
|
const { html, css, js } = readProjectFiles(cwd)
|
|
@@ -799,6 +799,6 @@ export async function runCommand(argv, cwd = process.cwd()) {
|
|
|
799
799
|
if (rest[0] === 'member') return cmdSpaceMember(rest.slice(1))
|
|
800
800
|
throw new Error('Use folder instead.')
|
|
801
801
|
default:
|
|
802
|
-
throw new Error(`Unknown command “${raw}”. Run
|
|
802
|
+
throw new Error(`Unknown command “${raw}”. Run amorphous-cli --help.`)
|
|
803
803
|
}
|
|
804
804
|
}
|
package/lib/help.mjs
CHANGED
|
@@ -29,7 +29,7 @@ export const ROOT_HELP = `Amorphous
|
|
|
29
29
|
folder people People on a folder
|
|
30
30
|
rename --name Rename
|
|
31
31
|
|
|
32
|
-
Run
|
|
32
|
+
Run amorphous-cli <command> --help for flags. Pass --json where you need machine output.
|
|
33
33
|
`
|
|
34
34
|
|
|
35
35
|
export const COMMAND_HELP = {
|
package/lib/login.mjs
CHANGED
|
@@ -70,7 +70,7 @@ async function loginViaMailpit(supabase, email, redirectTo, sinceMs) {
|
|
|
70
70
|
async function readCode(email) {
|
|
71
71
|
if (!process.stdin.isTTY) {
|
|
72
72
|
throw new Error(
|
|
73
|
-
`Code sent to ${email}. Read it from that inbox, then run:
|
|
73
|
+
`Code sent to ${email}. Read it from that inbox, then run: amorphous-cli login ${email} --code <code>`,
|
|
74
74
|
)
|
|
75
75
|
}
|
|
76
76
|
const rl = createInterface({ input: process.stdin, output: process.stderr })
|
package/lib/serve.mjs
CHANGED
|
@@ -219,7 +219,7 @@ export function startServe(options) {
|
|
|
219
219
|
if (options.prodFetch) return options.prodFetch(abstractId, path, init, session)
|
|
220
220
|
const cookie = await ensurePass()
|
|
221
221
|
if (!cookie && init.auth !== false) {
|
|
222
|
-
return new Response(JSON.stringify({ message: 'Not signed in. Run:
|
|
222
|
+
return new Response(JSON.stringify({ message: 'Not signed in. Run: amorphous-cli login' }), {
|
|
223
223
|
status: 401,
|
|
224
224
|
headers: { 'Content-Type': 'application/json' },
|
|
225
225
|
})
|
package/lib/session.mjs
CHANGED
|
@@ -58,7 +58,7 @@ async function withCredentialLock(dir, fn) {
|
|
|
58
58
|
/* the other process released it */
|
|
59
59
|
}
|
|
60
60
|
if (Date.now() - started > LOCK_WAIT_MS) {
|
|
61
|
-
throw new Error('Not signed in. Run:
|
|
61
|
+
throw new Error('Not signed in. Run: amorphous-cli login')
|
|
62
62
|
}
|
|
63
63
|
await sleep(25)
|
|
64
64
|
}
|
|
@@ -115,11 +115,11 @@ export async function ensureFreshSession(options = {}) {
|
|
|
115
115
|
const now = options.now ?? Date.now()
|
|
116
116
|
const session = loadSession()
|
|
117
117
|
if (!session?.access_token) {
|
|
118
|
-
throw new Error('Not signed in. Run:
|
|
118
|
+
throw new Error('Not signed in. Run: amorphous-cli login')
|
|
119
119
|
}
|
|
120
120
|
if (!options.force && !sessionNeedsRefresh(session, now)) return session
|
|
121
121
|
if (!session.refresh_token) {
|
|
122
|
-
throw new Error('Not signed in. Run:
|
|
122
|
+
throw new Error('Not signed in. Run: amorphous-cli login')
|
|
123
123
|
}
|
|
124
124
|
const refresh = options.refresh ?? refreshWithSupabase
|
|
125
125
|
try {
|
|
@@ -135,7 +135,7 @@ export async function ensureFreshSession(options = {}) {
|
|
|
135
135
|
) {
|
|
136
136
|
return again
|
|
137
137
|
}
|
|
138
|
-
throw new Error('Not signed in. Run:
|
|
138
|
+
throw new Error('Not signed in. Run: amorphous-cli login')
|
|
139
139
|
}
|
|
140
140
|
})
|
|
141
141
|
}
|
|
@@ -148,7 +148,7 @@ export function accessToken() {
|
|
|
148
148
|
export function authHeaders(extra = {}) {
|
|
149
149
|
const token = accessToken()
|
|
150
150
|
if (!token) {
|
|
151
|
-
throw new Error('Not signed in. Run:
|
|
151
|
+
throw new Error('Not signed in. Run: amorphous-cli login')
|
|
152
152
|
}
|
|
153
153
|
return {
|
|
154
154
|
Authorization: `Bearer ${token}`,
|
package/lib/tool-result.test.mjs
CHANGED
|
@@ -2,14 +2,14 @@ import assert from 'node:assert/strict'
|
|
|
2
2
|
import test from 'node:test'
|
|
3
3
|
import { toolText } from './tool-result.mjs'
|
|
4
4
|
|
|
5
|
-
const NUDGE = 'Run:
|
|
5
|
+
const NUDGE = 'Run: npm install -g amorphous-cli@latest && amorphous-cli setup'
|
|
6
6
|
|
|
7
7
|
test('a successful command keeps stderr the model must see', () => {
|
|
8
8
|
assert.equal(toolText('[{"id":"a"}]', `${NUDGE}\n`, 0), `[{"id":"a"}]\n${NUDGE}`)
|
|
9
9
|
})
|
|
10
10
|
|
|
11
11
|
test('a failed command returns the error text', () => {
|
|
12
|
-
assert.equal(toolText('', 'Not signed in. Run:
|
|
12
|
+
assert.equal(toolText('', 'Not signed in. Run: amorphous-cli login\n', 1), 'Not signed in. Run: amorphous-cli login')
|
|
13
13
|
})
|
|
14
14
|
|
|
15
15
|
test('empty success is ok', () => {
|
package/lib/update-check.mjs
CHANGED
|
@@ -8,7 +8,7 @@ import { userSkillDirs } from './agent-contract.mjs'
|
|
|
8
8
|
import { CLI_VERSION } from './version.mjs'
|
|
9
9
|
|
|
10
10
|
const CACHE_TTL_MS = 24 * 60 * 60 * 1000
|
|
11
|
-
const NUDGE = 'Run:
|
|
11
|
+
const NUDGE = 'Run: npm install -g amorphous-cli@latest && amorphous-cli setup\n'
|
|
12
12
|
|
|
13
13
|
function parseVersion(v) {
|
|
14
14
|
if (typeof v !== 'string') return null
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
startUpdateCheck,
|
|
15
15
|
} from './update-check.mjs'
|
|
16
16
|
|
|
17
|
-
const NUDGE = 'Run:
|
|
17
|
+
const NUDGE = 'Run: npm install -g amorphous-cli@latest && amorphous-cli setup\n'
|
|
18
18
|
|
|
19
19
|
test('compareVersions', () => {
|
|
20
20
|
assert.equal(compareVersions('1.0.0', '1.0.0'), 0)
|
|
@@ -252,7 +252,7 @@ test('non-setup refreshes a stale skill when registry matches', async () => {
|
|
|
252
252
|
await update.finish()
|
|
253
253
|
assert.equal(err, '')
|
|
254
254
|
assert.equal(readFileSync(join(d0, '.amorphous-version'), 'utf8').trim(), CLI_VERSION)
|
|
255
|
-
assert.match(readFileSync(join(d0, 'SKILL.md'), 'utf8'), /
|
|
255
|
+
assert.match(readFileSync(join(d0, 'SKILL.md'), 'utf8'), /npm install -g amorphous-cli@latest/)
|
|
256
256
|
})
|
|
257
257
|
|
|
258
258
|
test('a newer registry is not copied over the installed skill', async () => {
|
|
@@ -291,6 +291,6 @@ test('integration help skips update check file', () => {
|
|
|
291
291
|
encoding: 'utf8',
|
|
292
292
|
})
|
|
293
293
|
assert.equal(r.status, 0)
|
|
294
|
-
assert.ok(!r.stderr.includes('Run:
|
|
294
|
+
assert.ok(!r.stderr.includes('Run: npm install -g amorphous-cli@latest && amorphous-cli setup'))
|
|
295
295
|
assert.throws(() => readFileSync(cacheFile(home)), { code: 'ENOENT' })
|
|
296
296
|
})
|
package/package.json
CHANGED
package/skill/amorphous/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: amorphous
|
|
|
3
3
|
description: Make whatever you want, yourself, with your own agent, or with others. Use when someone wants an abstract other people can open, or wants to invite people, publish, or change an abstract.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
Make whatever you want, yourself, with your own agent, or with others. And whatever you want can be private, public, or even have users.
|
|
6
|
+
Make whatever you want, yourself, with your own agent, or with others. And whatever you want can be private, public, or even have users of its own.
|
|
7
7
|
|
|
8
8
|
## Files
|
|
9
9
|
|
|
@@ -32,18 +32,18 @@ A private record belongs to the signed-in person who wrote it. The abstract does
|
|
|
32
32
|
|
|
33
33
|
## Loop
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
Install the CLI once with `npm install -g amorphous-cli@latest`, then call it as `amorphous-cli <command>`. If a command prints `Run: npm install -g amorphous-cli@latest && amorphous-cli setup`, run that line, then repeat the command.
|
|
36
36
|
|
|
37
|
-
1. If you are not signed in, run `
|
|
38
|
-
2. `
|
|
37
|
+
1. If you are not signed in, run `amorphous-cli login`. Show the person the link it prints and ask them to finish in the browser. Do not ask for an email or a code.
|
|
38
|
+
2. `amorphous-cli create --name "..."` in a folder, or `amorphous-cli pull` when `.amorphous.json` is already there.
|
|
39
39
|
3. Edit the files to match what they asked for. `me` and `names` are how the abstract knows who is here.
|
|
40
|
-
4. `
|
|
41
|
-
5. `
|
|
42
|
-
6. `
|
|
43
|
-
7. `
|
|
44
|
-
8. `
|
|
40
|
+
4. `amorphous-cli serve` and open that URL. It reloads when the files change. Records on that page start in this folder. Switch the page to prod to read and write the abstract's records.
|
|
41
|
+
5. `amorphous-cli push` sends the source. `amorphous-cli push --data` also sends the records in this folder.
|
|
42
|
+
6. `amorphous-cli preview` and open that URL.
|
|
43
|
+
7. `amorphous-cli publish --live`
|
|
44
|
+
8. `amorphous-cli invite <email> use` or `edit` or `view`. It prints a link and does not send an email. Give them that link. They open it and sign in with that email.
|
|
45
45
|
|
|
46
|
-
`
|
|
46
|
+
`amorphous-cli visibility anyone` lets anyone view and write shared records. `amorphous-cli visibility members` keeps the abstract to invited people.
|
|
47
47
|
|
|
48
48
|
Do not make a public abstract that lets anyone keep adding shared records, such as an open list. Those records stay on the abstract and use up its storage. Keep shared records to a set you replace, or keep the abstract to invited people.
|
|
49
49
|
|