zas-agent 0.7.0 → 0.8.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 +26 -1
- package/dist/cli.js +22 -10
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.8.0] - 2026-09-06
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- A channel you joined, but did not create, can now be granted to an agent.
|
|
15
|
+
Its owner has to allow the agent first. Until they answer, the grant is
|
|
16
|
+
written and waiting: the key is real and it opens nothing.
|
|
17
|
+
- `grant_pending`. A tool call on a channel whose owner has not answered says
|
|
18
|
+
so, and says to ask them, rather than reporting the grant as missing.
|
|
19
|
+
- `foreign_limit` on pairing. A plan allows an agent a number of channels of
|
|
20
|
+
other people, and the free plan allows fewer of those than of your own.
|
|
21
|
+
- `zas_status` marks such a channel as waiting for its owner.
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- Reading a channel somebody else created said `read_forbidden` on a grant
|
|
26
|
+
that plainly said `send · read`, while sending into the same channel
|
|
27
|
+
worked. Sending goes through the API, which knows which account holds a
|
|
28
|
+
channel; reading goes to Firestore directly, and the agent looked under
|
|
29
|
+
its own owner, where a shared channel is not kept. The server now says
|
|
30
|
+
where each channel lives, and reads, Directo offers and Directo fallbacks
|
|
31
|
+
all address that account. A channel of your own is unchanged: it is in
|
|
32
|
+
your own account, which is where it was always read from.
|
|
33
|
+
|
|
10
34
|
## [0.7.0] - 2026-09-05
|
|
11
35
|
|
|
12
36
|
### Added
|
|
@@ -279,7 +303,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
279
303
|
two separate identities that cannot read each other's keys.
|
|
280
304
|
- Install snippets for Claude Code and Codex, printed by `zas-agent pair`.
|
|
281
305
|
|
|
282
|
-
[Unreleased]: https://github.com/soke1556/zas-agent/compare/v0.
|
|
306
|
+
[Unreleased]: https://github.com/soke1556/zas-agent/compare/v0.8.0...HEAD
|
|
307
|
+
[0.8.0]: https://github.com/soke1556/zas-agent/compare/v0.7.0...v0.8.0
|
|
283
308
|
[0.7.0]: https://github.com/soke1556/zas-agent/compare/v0.6.3...v0.7.0
|
|
284
309
|
[0.6.3]: https://github.com/soke1556/zas-agent/compare/v0.6.2...v0.6.3
|
|
285
310
|
[0.6.2]: https://github.com/soke1556/zas-agent/compare/v0.6.1...v0.6.2
|
package/dist/cli.js
CHANGED
|
@@ -159,6 +159,7 @@ var SENTENCES = {
|
|
|
159
159
|
agent_forbidden: "This agent cannot do that; only the account owner can.",
|
|
160
160
|
agent_revoked: "The owner revoked this agent. Pair again with \u201Czas-agent pair\u201D.",
|
|
161
161
|
grant_missing: "This agent has no access to that channel. The owner adds it from Settings \u2192 Agents.",
|
|
162
|
+
grant_pending: "That channel belongs to somebody else, and its owner has not allowed this agent yet. Ask them to allow it in Zas.",
|
|
162
163
|
not_found: "That item is not in the channel.",
|
|
163
164
|
invalid_cap: "That file is no longer available.",
|
|
164
165
|
write_failed: "The file could not be saved to the destination.",
|
|
@@ -187,6 +188,7 @@ var SENTENCES = {
|
|
|
187
188
|
pairing_claimed: "This pairing was already claimed. Pair again with \u201Czas-agent pair\u201D.",
|
|
188
189
|
agent_limit: "The account cannot take another agent. The owner deletes one from Settings \u2192 Agents.",
|
|
189
190
|
grant_limit: "The plan allows fewer channels per agent than this pairing grants.",
|
|
191
|
+
foreign_limit: "The plan allows this agent fewer channels of other people than this pairing asks for.",
|
|
190
192
|
feature_disabled: "Agents are not enabled for this account yet.",
|
|
191
193
|
upload_failed: "The upload failed. Try again.",
|
|
192
194
|
oprf_failed: "Zas did not answer correctly while preparing the file. Try again.",
|
|
@@ -1036,8 +1038,8 @@ function keepUrls(servers, keep) {
|
|
|
1036
1038
|
const kept = [];
|
|
1037
1039
|
for (const server of servers) {
|
|
1038
1040
|
const urls = typeof server.urls === "string" ? [server.urls] : server.urls ?? [];
|
|
1039
|
-
const
|
|
1040
|
-
if (
|
|
1041
|
+
const usable2 = urls.filter(keep);
|
|
1042
|
+
if (usable2.length > 0) kept.push({ ...server, urls: usable2 });
|
|
1041
1043
|
}
|
|
1042
1044
|
return kept;
|
|
1043
1045
|
}
|
|
@@ -2075,15 +2077,22 @@ function channelNameOf(identity, grant) {
|
|
|
2075
2077
|
throw new ZasError("key_stale", 0);
|
|
2076
2078
|
}
|
|
2077
2079
|
}
|
|
2080
|
+
function channelAccountOf(identity, grant) {
|
|
2081
|
+
return grant.channel_owner_uid !== void 0 && grant.channel_owner_uid !== "" ? grant.channel_owner_uid : identity.owner_uid;
|
|
2082
|
+
}
|
|
2078
2083
|
var fold = (value) => value.trim().toLowerCase();
|
|
2084
|
+
function usable(grant) {
|
|
2085
|
+
if (grant.pending) throw new ZasError("grant_pending", 0);
|
|
2086
|
+
return grant;
|
|
2087
|
+
}
|
|
2079
2088
|
function resolveChannel(identity, grants, channel) {
|
|
2080
2089
|
if (channel === void 0 || fold(channel) === "") {
|
|
2081
|
-
if (grants.length === 1) return grants[0];
|
|
2090
|
+
if (grants.length === 1) return usable(grants[0]);
|
|
2082
2091
|
throw new ZasError("grant_missing", 0);
|
|
2083
2092
|
}
|
|
2084
2093
|
const wanted = channel.trim();
|
|
2085
2094
|
const byId = grants.find((g) => g.channel_id === wanted);
|
|
2086
|
-
if (byId) return byId;
|
|
2095
|
+
if (byId) return usable(byId);
|
|
2087
2096
|
const folded = fold(wanted);
|
|
2088
2097
|
const byName = grants.filter((g) => {
|
|
2089
2098
|
try {
|
|
@@ -2092,7 +2101,7 @@ function resolveChannel(identity, grants, channel) {
|
|
|
2092
2101
|
return false;
|
|
2093
2102
|
}
|
|
2094
2103
|
});
|
|
2095
|
-
if (byName.length === 1) return byName[0];
|
|
2104
|
+
if (byName.length === 1) return usable(byName[0]);
|
|
2096
2105
|
throw new ZasError("grant_missing", 0);
|
|
2097
2106
|
}
|
|
2098
2107
|
|
|
@@ -2784,7 +2793,7 @@ async function sendDirect(ctx, input, report2, deps = {}) {
|
|
|
2784
2793
|
...stamp
|
|
2785
2794
|
});
|
|
2786
2795
|
const route = `/direct/${cid}/${id}`;
|
|
2787
|
-
const offerPath = `accounts/${
|
|
2796
|
+
const offerPath = `accounts/${channelAccountOf(ctx.identity, grant)}/channels/${cid}/direct/${id}`;
|
|
2788
2797
|
const setState = (state) => ctx.client.api("POST", `${route}/state`, { state, ...stamp }).then(() => void 0, () => void 0);
|
|
2789
2798
|
const claimBy = startedAt + (deps.offerWaitMs ?? OFFER_WAIT_MS);
|
|
2790
2799
|
for (; ; ) {
|
|
@@ -3060,7 +3069,7 @@ function nameFrom(channelKey, grant) {
|
|
|
3060
3069
|
}
|
|
3061
3070
|
}
|
|
3062
3071
|
function linksParent(identity, grant) {
|
|
3063
|
-
return `accounts/${identity
|
|
3072
|
+
return `accounts/${channelAccountOf(identity, grant)}/channels/${grant.channel_id}`;
|
|
3064
3073
|
}
|
|
3065
3074
|
function linkPath(identity, grant, id) {
|
|
3066
3075
|
return `projects/${identity.firestore_project}/databases/(default)/documents/${linksParent(identity, grant)}/links/${id}`;
|
|
@@ -3341,11 +3350,12 @@ async function receiveDirect(ctx, input, report2, deps = {}) {
|
|
|
3341
3350
|
const channelName = channelLabel(ctx, grant);
|
|
3342
3351
|
const cid = grant.channel_id;
|
|
3343
3352
|
const owner = ctx.identity.owner_uid;
|
|
3353
|
+
const account = channelAccountOf(ctx.identity, grant);
|
|
3344
3354
|
const device = deps.device ?? newDeviceToken();
|
|
3345
3355
|
const { seal, open } = sealer(key, grant.key_version);
|
|
3346
3356
|
const stamp = { device, owner_uid: owner };
|
|
3347
3357
|
const startedAt = now();
|
|
3348
|
-
const channelPath = `accounts/${
|
|
3358
|
+
const channelPath = `accounts/${account}/channels/${cid}`;
|
|
3349
3359
|
report2("waiting");
|
|
3350
3360
|
const waitUntil = startedAt + (deps.offerWaitMs ?? OFFER_WAIT_MS2);
|
|
3351
3361
|
let id;
|
|
@@ -3480,6 +3490,7 @@ async function receiveDirect(ctx, input, report2, deps = {}) {
|
|
|
3480
3490
|
channel_name: channelName,
|
|
3481
3491
|
offer_id: offerId,
|
|
3482
3492
|
owner_uid: owner,
|
|
3493
|
+
channel_account: account,
|
|
3483
3494
|
device,
|
|
3484
3495
|
...input.dest !== void 0 ? { dest: input.dest } : {},
|
|
3485
3496
|
meta: offered,
|
|
@@ -3495,7 +3506,7 @@ async function receiveDirectFallback(ctx, record, report2, deps = {}) {
|
|
|
3495
3506
|
const { open } = sealer(record.key, record.key_version);
|
|
3496
3507
|
const stamp = { device: record.device, owner_uid: record.owner_uid };
|
|
3497
3508
|
const base = `/direct/${record.channel_id}/${record.offer_id}/fallback`;
|
|
3498
|
-
const offerPath = `accounts/${record.
|
|
3509
|
+
const offerPath = `accounts/${record.channel_account}/channels/${record.channel_id}/direct/${record.offer_id}`;
|
|
3499
3510
|
const doc = await ctx.client.firestoreGet(offerPath);
|
|
3500
3511
|
const enc = stringField2(doc, "fallback_meta_enc");
|
|
3501
3512
|
let meta;
|
|
@@ -4088,7 +4099,7 @@ async function report(client, properties) {
|
|
|
4088
4099
|
|
|
4089
4100
|
// src/server.ts
|
|
4090
4101
|
function agentVersion() {
|
|
4091
|
-
return true ? "0.
|
|
4102
|
+
return true ? "0.8.0" : "0.0.0-dev";
|
|
4092
4103
|
}
|
|
4093
4104
|
var AGENT_CUE = " The owner sees every item this agent sends with the >_ agent mark and this agent's name, on every device.";
|
|
4094
4105
|
var PAIR_ANNOUNCE_MS = 15e3;
|
|
@@ -4098,6 +4109,7 @@ var delay = (ms) => new Promise((resolve2) => {
|
|
|
4098
4109
|
setTimeout(resolve2, ms);
|
|
4099
4110
|
});
|
|
4100
4111
|
function rightsOf(grant) {
|
|
4112
|
+
if (grant.pending) return "waiting for the channel\u2019s owner";
|
|
4101
4113
|
const rights = [];
|
|
4102
4114
|
if (grant.send && grant.mode !== "view") rights.push(grant.direct_mode ? "send (Directo)" : "send");
|
|
4103
4115
|
if (grant.read) rights.push(grant.direct_mode ? "receive (Directo)" : "read");
|
package/package.json
CHANGED