zas-agent 0.2.0 → 0.3.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.
- package/CHANGELOG.md +30 -1
- package/README.md +22 -6
- package/dist/cli.js +26 -19
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.3.0] - 2026-09-03
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Pairing again in a profile that is already paired replaces the agent
|
|
15
|
+
instead of adding a second one. The terminal opens the pairing as the old
|
|
16
|
+
agent, the approval page says which agent it replaces and fills in its
|
|
17
|
+
name and channels, and the old agent is revoked in the same step that
|
|
18
|
+
creates the new one. If the server no longer accepts the old agent, `pair`
|
|
19
|
+
says so and creates a new agent.
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- The help text, the tool descriptions and the README say "this agent" where
|
|
24
|
+
they said "this machine": a pairing is one profile's key pair, and one
|
|
25
|
+
machine can hold several.
|
|
26
|
+
|
|
27
|
+
## [0.2.1] - 2026-09-03
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- The `claude mcp add` and `codex mcp add` lines the terminal prints after
|
|
32
|
+
pairing quote the `--` separator. In PowerShell the npm-installed `claude`
|
|
33
|
+
and `codex` commands are script shims, and PowerShell kept a bare `--` for
|
|
34
|
+
itself, so `claude mcp add` refused `-y` as an unknown option.
|
|
35
|
+
|
|
10
36
|
## [0.2.0] - 2026-09-03
|
|
11
37
|
|
|
12
38
|
### Changed
|
|
@@ -49,6 +75,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
49
75
|
two separate identities that cannot read each other's keys.
|
|
50
76
|
- Install snippets for Claude Code and Codex, printed by `zas-agent pair`.
|
|
51
77
|
|
|
52
|
-
[Unreleased]: https://github.com/soke1556/zas-agent/compare/v0.
|
|
78
|
+
[Unreleased]: https://github.com/soke1556/zas-agent/compare/v0.3.0...HEAD
|
|
79
|
+
[0.3.0]: https://github.com/soke1556/zas-agent/compare/v0.2.1...v0.3.0
|
|
80
|
+
[0.2.1]: https://github.com/soke1556/zas-agent/compare/v0.2.0...v0.2.1
|
|
81
|
+
[0.2.0]: https://github.com/soke1556/zas-agent/compare/v0.1.1...v0.2.0
|
|
53
82
|
[0.1.1]: https://github.com/soke1556/zas-agent/compare/v0.1.0...v0.1.1
|
|
54
83
|
[0.1.0]: https://github.com/soke1556/zas-agent/releases/tag/v0.1.0
|
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ get a short-lived session.
|
|
|
35
35
|
|
|
36
36
|
## Install
|
|
37
37
|
|
|
38
|
-
Pair the
|
|
38
|
+
Pair the agent first, then hand the command to your harness.
|
|
39
39
|
|
|
40
40
|
**Pair**
|
|
41
41
|
|
|
@@ -46,13 +46,13 @@ npx -y zas-agent pair --profile claude-code
|
|
|
46
46
|
**Claude Code**
|
|
47
47
|
|
|
48
48
|
```
|
|
49
|
-
claude mcp add zas -- npx -y zas-agent --profile claude-code
|
|
49
|
+
claude mcp add zas "--" npx -y zas-agent --profile claude-code
|
|
50
50
|
```
|
|
51
51
|
|
|
52
52
|
**Codex**
|
|
53
53
|
|
|
54
54
|
```
|
|
55
|
-
codex mcp add zas -- npx -y zas-agent --profile codex
|
|
55
|
+
codex mcp add zas "--" npx -y zas-agent --profile codex
|
|
56
56
|
```
|
|
57
57
|
|
|
58
58
|
Codex by hand, if you would rather edit `~/.codex/config.toml`:
|
|
@@ -168,7 +168,7 @@ string ever reaches a terminal.
|
|
|
168
168
|
|
|
169
169
|
| Code | What it means |
|
|
170
170
|
| --- | --- |
|
|
171
|
-
| `not_paired` | This
|
|
171
|
+
| `not_paired` | This agent is not paired yet. |
|
|
172
172
|
| `identity_corrupt` | The identity file on disk is damaged. |
|
|
173
173
|
| `agent_revoked` | The owner revoked this agent. |
|
|
174
174
|
| `agent_forbidden` | Only the account owner can do that. |
|
|
@@ -203,8 +203,8 @@ stack trace.
|
|
|
203
203
|
|
|
204
204
|
| Tool | What it does |
|
|
205
205
|
| --- | --- |
|
|
206
|
-
| `zas_status` | Says whether this
|
|
207
|
-
| `zas_pair` | Pairs this
|
|
206
|
+
| `zas_status` | Says whether this agent is paired with a Zas account, and lists the owner's channels it may send to or read from. |
|
|
207
|
+
| `zas_pair` | Pairs this agent with a Zas account. The first call returns a URL for the owner to open; a later call says whether they approved. If the page shows a code, a call with `code` claims with it. In a profile that is already paired, approval replaces the old agent. |
|
|
208
208
|
| `zas_send_file` | Sends a file from this machine into one of the owner's channels. Returns the item id, or a job id when the upload takes longer than a minute. |
|
|
209
209
|
| `zas_send_note` | Sends a note — plain text, or a code snippet with its language — into one of the owner's channels. |
|
|
210
210
|
| `zas_list_items` | Lists the most recent items in one of the owner's channels. Needs a grant that includes reading. |
|
|
@@ -260,6 +260,22 @@ Deleting the directory makes this machine forget the agent. It does not revoke
|
|
|
260
260
|
anything: the account side is closed from the web app, under
|
|
261
261
|
Settings → Agents → Revoke.
|
|
262
262
|
|
|
263
|
+
## Pairing again
|
|
264
|
+
|
|
265
|
+
A pairing is one profile's key pair, not the machine and not the program. A
|
|
266
|
+
profile holds one agent. Running `zas-agent pair` in a profile that is already
|
|
267
|
+
paired opens a replacement: the terminal signs the request with the old
|
|
268
|
+
identity, the approval page says which agent it replaces and fills in its name
|
|
269
|
+
and channels, and the old agent is revoked in the same step that creates the
|
|
270
|
+
new one. Its row stays under Settings → Agents as revoked until you remove it,
|
|
271
|
+
and it keeps costing a slot until then. If the old agent was already revoked
|
|
272
|
+
or removed, `pair` says so and creates a new agent.
|
|
273
|
+
|
|
274
|
+
One machine that runs Claude Code and Codex has two profiles (`claude-code`
|
|
275
|
+
and `codex`), two agents, two approvals and two rows. Revoking one does not
|
|
276
|
+
touch the other. Two programs pointed at the same `--profile` act as one
|
|
277
|
+
agent: same keys, same channels, one row.
|
|
278
|
+
|
|
263
279
|
## Configuration
|
|
264
280
|
|
|
265
281
|
| Setting | Default | What it changes |
|
package/dist/cli.js
CHANGED
|
@@ -570,10 +570,10 @@ function packageName() {
|
|
|
570
570
|
return true ? "zas-agent" : "zas-agent";
|
|
571
571
|
}
|
|
572
572
|
function claudeSnippet(profile) {
|
|
573
|
-
return `claude mcp add zas -- npx -y ${packageName()} --profile ${profile}`;
|
|
573
|
+
return `claude mcp add zas "--" npx -y ${packageName()} --profile ${profile}`;
|
|
574
574
|
}
|
|
575
575
|
function codexSnippet(profile) {
|
|
576
|
-
return `codex mcp add zas -- npx -y ${packageName()} --profile ${profile}`;
|
|
576
|
+
return `codex mcp add zas "--" npx -y ${packageName()} --profile ${profile}`;
|
|
577
577
|
}
|
|
578
578
|
function kindForProfile(profile) {
|
|
579
579
|
if (profile === "claude-code") return "claude_code";
|
|
@@ -604,22 +604,28 @@ async function runPair(opts) {
|
|
|
604
604
|
const sleep2 = opts.sleep ?? defaultSleep;
|
|
605
605
|
const now = opts.now ?? (() => Date.now());
|
|
606
606
|
const existing = loadIdentity(opts.profile);
|
|
607
|
-
if (existing) {
|
|
608
|
-
opts.log(
|
|
609
|
-
`This profile is already paired as \u201C${existing.name}\u201D. A new agent will be created; revoke the old one from Settings \u2192 Agents.`
|
|
610
|
-
);
|
|
611
|
-
}
|
|
612
607
|
const host = (opts.host ?? hostname()).slice(0, AGENT_HOST_MAX);
|
|
613
608
|
const keys = newKeyMaterial();
|
|
614
609
|
const endpoints = { ...defaultEndpoints(), api_base: opts.apiBase };
|
|
615
|
-
const
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
{
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
610
|
+
const request = { kind: opts.kind, host, x25519_public: keys.x25519_public, p256_public: keys.p256_public, claim: true };
|
|
611
|
+
let created = null;
|
|
612
|
+
let replacing = false;
|
|
613
|
+
if (existing) {
|
|
614
|
+
try {
|
|
615
|
+
const old = new ZasClient({ ...existing, api_base: opts.apiBase }, { fetch: opts.fetch, now });
|
|
616
|
+
created = await old.api("POST", "/agents/me/pairings", request);
|
|
617
|
+
replacing = true;
|
|
618
|
+
opts.log(`This profile is paired as \u201C${existing.name}\u201D. Approving this pairing replaces that agent.`);
|
|
619
|
+
} catch (err) {
|
|
620
|
+
const code = err instanceof ZasError ? err.code : "network";
|
|
621
|
+
opts.log(
|
|
622
|
+
`This profile was paired as \u201C${existing.name}\u201D, but the server no longer accepts that agent (${code}). A new agent will be created; remove the old one from Settings \u2192 Agents.`
|
|
623
|
+
);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
if (!created) {
|
|
627
|
+
created = await apiPublic(opts.apiBase, "POST", "/v1/agents/pairings", request, {}, opts.fetch);
|
|
628
|
+
}
|
|
623
629
|
let claimed = null;
|
|
624
630
|
let inFlight = null;
|
|
625
631
|
const wake = deferred();
|
|
@@ -780,6 +786,7 @@ async function runPair(opts) {
|
|
|
780
786
|
opts.log(
|
|
781
787
|
[
|
|
782
788
|
`Done: the agent \u201C${identity.name}\u201D is paired with your account.`,
|
|
789
|
+
...replacing ? ["It replaces the previous agent of this profile, which is now revoked."] : [],
|
|
783
790
|
...install
|
|
784
791
|
].join("\n")
|
|
785
792
|
);
|
|
@@ -1869,7 +1876,7 @@ async function sendNote(ctx, input) {
|
|
|
1869
1876
|
|
|
1870
1877
|
// src/server.ts
|
|
1871
1878
|
function agentVersion() {
|
|
1872
|
-
return true ? "0.
|
|
1879
|
+
return true ? "0.3.0" : "0.0.0-dev";
|
|
1873
1880
|
}
|
|
1874
1881
|
var AGENT_CUE = " The owner sees every item this agent sends with the >_ agent mark and this agent's name, on every device.";
|
|
1875
1882
|
var PAIR_ANNOUNCE_MS = 15e3;
|
|
@@ -1913,7 +1920,7 @@ function buildServer(profile, deps = {}) {
|
|
|
1913
1920
|
return text2({ job_id: job.id, status: "running", phase: job.phase });
|
|
1914
1921
|
};
|
|
1915
1922
|
server.registerTool("zas_status", {
|
|
1916
|
-
description: "Say whether this
|
|
1923
|
+
description: "Say whether this agent is paired with a Zas account, and list the owner's channels it may send to or read from." + AGENT_CUE
|
|
1917
1924
|
}, async () => {
|
|
1918
1925
|
try {
|
|
1919
1926
|
if (!(deps.identity ?? loadIdentity(profile))) {
|
|
@@ -1941,7 +1948,7 @@ function buildServer(profile, deps = {}) {
|
|
|
1941
1948
|
});
|
|
1942
1949
|
let pairing = null;
|
|
1943
1950
|
server.registerTool("zas_pair", {
|
|
1944
|
-
description: "Pair this
|
|
1951
|
+
description: "Pair this agent with a Zas account. The first call returns a URL for the owner to open; a later call says whether they approved. If the page shows a code, call again with `code`. In a profile that is already paired, approval replaces the old agent." + AGENT_CUE,
|
|
1945
1952
|
inputSchema: {
|
|
1946
1953
|
code: z.string().optional().describe("The code the pairing page shows when the browser could not reach this machine.")
|
|
1947
1954
|
}
|
|
@@ -2123,7 +2130,7 @@ var USAGE = [
|
|
|
2123
2130
|
"zas-agent \u2014 send files and notes from a coding agent into your Zas channels.",
|
|
2124
2131
|
"",
|
|
2125
2132
|
" zas-agent [--profile <name>] serve the MCP tools over stdio",
|
|
2126
|
-
" zas-agent pair [--profile <name>] pair this
|
|
2133
|
+
" zas-agent pair [--profile <name>] pair this agent with a Zas account",
|
|
2127
2134
|
" [--kind claude_code|codex|other] [--host <name>] [--no-open]",
|
|
2128
2135
|
" zas-agent --version"
|
|
2129
2136
|
].join("\n");
|