@agentshouse/kit 0.2.1-cd9cbd8b6428c → 0.2.1-cfe564e35b4a5
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 +19 -19
- package/dist/acp.js +16 -93
- package/dist/agents.js +81 -39
- package/dist/api.js +30 -2
- package/dist/app-git.js +64 -0
- package/dist/bootstrap.json +4 -4
- package/dist/bridge.js +35 -52
- package/dist/clis.js +95 -65
- package/dist/codex-main.js +58 -0
- package/dist/conversations.js +284 -236
- package/dist/copies.js +146 -129
- package/dist/end.js +8 -0
- package/dist/events.js +521 -0
- package/dist/files.js +14 -0
- package/dist/house-main.js +41 -12
- package/dist/instructions.js +4 -3
- package/dist/kit-main.js +3 -0
- package/dist/login.js +23 -98
- package/dist/logout.js +16 -13
- package/dist/parts.js +64 -0
- package/dist/refusals.js +12 -0
- package/dist/resident.js +24 -22
- package/dist/scope.js +203 -0
- package/dist/secret-input.js +4 -1
- package/dist/shell.js +3 -0
- package/dist/sign-in.js +34 -9
- package/dist/skills.js +1 -1
- package/dist/stream.js +29 -4
- package/dist/transcription.js +54 -6
- package/dist/update.js +2 -0
- package/dist/work.js +348 -0
- package/package.json +2 -2
- package/dist/blocks.js +0 -51
package/dist/copies.js
CHANGED
|
@@ -2,7 +2,7 @@ import { parse } from '@agentshouse/mdmodel';
|
|
|
2
2
|
import { randomUUID } from 'node:crypto';
|
|
3
3
|
import { mkdir, readFile, readdir, realpath, rename, rm, rmdir, stat, writeFile } from 'node:fs/promises';
|
|
4
4
|
import { dirname, join } from 'node:path';
|
|
5
|
-
import { HouseRefusal } from './api.js';
|
|
5
|
+
import { finalRefusal, HouseRefusal, retrying } from './api.js';
|
|
6
6
|
import { blobId, blobText, git, HOUSE_REF, importCommits, localCopies, revision, run, succeeded, tree, } from './git.js';
|
|
7
7
|
import { kitHome } from './home.js';
|
|
8
8
|
import { operationId } from './operation.js';
|
|
@@ -11,7 +11,6 @@ import { changed } from './translate.js';
|
|
|
11
11
|
import { relayed } from './relay.js';
|
|
12
12
|
const BRANCH = 'main';
|
|
13
13
|
const PROVENANCE = '_provenance';
|
|
14
|
-
const REPLICA_RETRY_MS = 30_000;
|
|
15
14
|
const IDENTITY = { GIT_COMMITTER_NAME: 'House Kit', GIT_COMMITTER_EMAIL: 'house-kit@localhost' };
|
|
16
15
|
function causeOf(error) {
|
|
17
16
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -33,6 +32,22 @@ function rebaseFixes(refusal) {
|
|
|
33
32
|
function short(commit) {
|
|
34
33
|
return commit.slice(0, 12);
|
|
35
34
|
}
|
|
35
|
+
function moved(before, after) {
|
|
36
|
+
if (before.house !== after.house)
|
|
37
|
+
return [`${rootOf(after.room_handle)}: ${HOUSE_REF} is at ${short(after.house)}`];
|
|
38
|
+
return before.position === after.position ? [] : [`${rootOf(after.room_handle)}: read-only files refreshed`];
|
|
39
|
+
}
|
|
40
|
+
function expiredAuthority(error) {
|
|
41
|
+
if (!(error instanceof HouseRefusal))
|
|
42
|
+
return undefined;
|
|
43
|
+
try {
|
|
44
|
+
const { error: refused } = JSON.parse(error.text);
|
|
45
|
+
return refused?.code === 'position_expired' && typeof refused.authority === 'string' ? refused.authority : undefined;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
36
51
|
function covers(path, prefix) {
|
|
37
52
|
return prefix === '' || path === prefix || path.startsWith(`${prefix}/`);
|
|
38
53
|
}
|
|
@@ -41,11 +56,11 @@ function sidecar(path) {
|
|
|
41
56
|
segments.splice(-1, 0, PROVENANCE);
|
|
42
57
|
return segments.join('/');
|
|
43
58
|
}
|
|
44
|
-
function rootOf(
|
|
45
|
-
return
|
|
59
|
+
function rootOf(handle) {
|
|
60
|
+
return `/rooms/${handle}`;
|
|
46
61
|
}
|
|
47
62
|
function relative(path) {
|
|
48
|
-
return path.replace(/^\/
|
|
63
|
+
return path.replace(/^\/rooms\/[^/]+\//, '');
|
|
49
64
|
}
|
|
50
65
|
function declaredWritable(path, copy) {
|
|
51
66
|
const deepest = (scopes) => Math.max(-1, ...scopes.filter((scope) => covers(path, scope)).map((scope) => scope.length));
|
|
@@ -153,19 +168,18 @@ export class LocalCopies {
|
|
|
153
168
|
house;
|
|
154
169
|
copies = new Map();
|
|
155
170
|
queues = new Map();
|
|
156
|
-
|
|
157
|
-
selecting = Promise.resolve();
|
|
171
|
+
answering = Promise.resolve();
|
|
158
172
|
constructor(house) {
|
|
159
173
|
this.house = house;
|
|
160
174
|
this.owner = {
|
|
161
175
|
key: 'owner',
|
|
162
176
|
submit: async (operation, changes) => {
|
|
163
177
|
try {
|
|
164
|
-
const outcome = await house.post('/kit/door/batch', { operation_id: operation, changes });
|
|
178
|
+
const outcome = await retrying(() => house.post('/kit/door/batch', { operation_id: operation, changes }));
|
|
165
179
|
return { accepted: outcome.contents };
|
|
166
180
|
}
|
|
167
181
|
catch (error) {
|
|
168
|
-
if (!(error
|
|
182
|
+
if (!finalRefusal(error))
|
|
169
183
|
throw error;
|
|
170
184
|
return {
|
|
171
185
|
refused: refusalOf(error.text) ?? { code: '', text: `House refused it with ${error.status}`, conflicts: [] },
|
|
@@ -177,7 +191,7 @@ export class LocalCopies {
|
|
|
177
191
|
async load() {
|
|
178
192
|
const home = join(kitHome(), 'local-copies');
|
|
179
193
|
const names = (await readdir(join(home, 'rooms')).catch(() => [])).filter((name) => name.endsWith('.json'));
|
|
180
|
-
for (const path of
|
|
194
|
+
for (const path of names.map((name) => join(home, 'rooms', name))) {
|
|
181
195
|
const text = await readFile(path, 'utf8').catch(() => null);
|
|
182
196
|
if (text === null)
|
|
183
197
|
continue;
|
|
@@ -186,47 +200,68 @@ export class LocalCopies {
|
|
|
186
200
|
}
|
|
187
201
|
}
|
|
188
202
|
async mapping() {
|
|
189
|
-
await this.
|
|
203
|
+
await this.answering;
|
|
190
204
|
return [...this.copies.values()]
|
|
191
205
|
.filter((copy) => copy.active)
|
|
192
|
-
.map((copy) => `${rootOf(copy)}: ${copy.repository}`)
|
|
206
|
+
.map((copy) => `${rootOf(copy.room_handle)}: ${copy.repository}`)
|
|
193
207
|
.sort();
|
|
194
208
|
}
|
|
195
|
-
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}
|
|
200
|
-
async reselect() {
|
|
201
|
-
const { local_copy: chosen } = await this.house.post('/kit/local-copy/selection', {});
|
|
202
|
-
const selected = [
|
|
203
|
-
...(chosen?.rooms ?? [])
|
|
204
|
-
.filter((room) => room.room_handle !== null)
|
|
205
|
-
.map((room) => ({ key: `rooms/${room.room_ref}`, private: false, handle: room.room_handle })),
|
|
206
|
-
...(chosen?.private === true ? [{ key: 'private', private: true, handle: null }] : []),
|
|
207
|
-
];
|
|
208
|
-
const keys = new Set(selected.map((scope) => scope.key));
|
|
209
|
-
const work = [];
|
|
210
|
-
for (const key of this.copies.keys()) {
|
|
211
|
-
if (keys.has(key))
|
|
212
|
-
continue;
|
|
213
|
-
work.push(this.exclusive(key, async () => {
|
|
214
|
-
const copy = this.copies.get(key);
|
|
215
|
-
if (copy.active)
|
|
216
|
-
await this.save({ ...copy, active: false });
|
|
217
|
-
}));
|
|
218
|
-
}
|
|
219
|
-
for (const scope of selected)
|
|
220
|
-
work.push(this.exclusive(scope.key, () => this.apply(scope)).catch(logged));
|
|
221
|
-
await Promise.all(work);
|
|
209
|
+
async connected() {
|
|
210
|
+
const copied = await this.answered(() => this.fetched(false));
|
|
211
|
+
if (copied.refused)
|
|
212
|
+
logged(copied.text);
|
|
222
213
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
214
|
+
fetch() {
|
|
215
|
+
return this.answered(() => this.fetched(true));
|
|
216
|
+
}
|
|
217
|
+
answered(work) {
|
|
218
|
+
const answered = this.answering.then(work);
|
|
219
|
+
this.answering = answered.catch(() => undefined);
|
|
220
|
+
return answered;
|
|
221
|
+
}
|
|
222
|
+
async fetched(refreshing) {
|
|
223
|
+
const { local_copy: answer } = await this.house.post('/kit/local-copy/selection', {});
|
|
224
|
+
const synced = new Map(answer.rooms.map((room) => [`rooms/${room.room_ref}`, room.room_handle]));
|
|
225
|
+
return this.holding([...new Set([...this.copies.keys(), ...synced.keys()])].sort(), async () => {
|
|
226
|
+
const said = [];
|
|
227
|
+
let refused = false;
|
|
228
|
+
for (const copy of this.copies.values()) {
|
|
229
|
+
if (synced.has(copy.key) || !copy.active)
|
|
230
|
+
continue;
|
|
231
|
+
await this.save({ ...copy, active: false });
|
|
232
|
+
said.push(`${rootOf(copy.room_handle)}: no longer synced to this Environment; its files stay`);
|
|
233
|
+
}
|
|
234
|
+
const current = [];
|
|
235
|
+
for (const [key, handle] of synced) {
|
|
236
|
+
try {
|
|
237
|
+
const held = this.copies.get(key);
|
|
238
|
+
if (held === undefined || !(await exists(held.repository))) {
|
|
239
|
+
said.push(await this.materialize(key, handle));
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
const copy = held.room_handle === handle ? held : await this.save({ ...held, room_handle: handle });
|
|
243
|
+
if (copy.active)
|
|
244
|
+
current.push(copy);
|
|
245
|
+
else
|
|
246
|
+
said.push(...moved(copy, await this.save(await this.received({ ...copy, active: true }))));
|
|
247
|
+
}
|
|
248
|
+
catch (error) {
|
|
249
|
+
refused = true;
|
|
250
|
+
said.push(`${rootOf(handle)}: ${causeOf(error)}`);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
if (refreshing && current.length > 0) {
|
|
254
|
+
try {
|
|
255
|
+
const refreshed = await this.refreshed(current);
|
|
256
|
+
current.forEach((copy, index) => said.push(...moved(copy, refreshed[index])));
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
refused = true;
|
|
260
|
+
said.push(error instanceof HouseRefusal ? (refusalOf(error.text)?.text ?? causeOf(error)) : causeOf(error));
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return { refused, text: said.length === 0 ? 'Nothing new from House.' : said.join('\n') };
|
|
264
|
+
});
|
|
230
265
|
}
|
|
231
266
|
async observed(report) {
|
|
232
267
|
const key = await this.keyAt(dirname(report.common));
|
|
@@ -276,19 +311,12 @@ export class LocalCopies {
|
|
|
276
311
|
this.queues.set(key, queued.catch(() => undefined));
|
|
277
312
|
return queued;
|
|
278
313
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
this.delivering.add(key);
|
|
283
|
-
void this.exclusive(key, async () => {
|
|
284
|
-
this.delivering.delete(key);
|
|
285
|
-
const copy = this.copies.get(key);
|
|
286
|
-
if (copy.active)
|
|
287
|
-
await this.save(await this.caughtUp(copy));
|
|
288
|
-
}).catch(logged);
|
|
314
|
+
holding(keys, work) {
|
|
315
|
+
const [key, ...rest] = keys;
|
|
316
|
+
return key === undefined ? work() : this.exclusive(key, () => this.holding(rest, work));
|
|
289
317
|
}
|
|
290
318
|
async save(copy) {
|
|
291
|
-
const path = join(kitHome(), 'local-copies',
|
|
319
|
+
const path = join(kitHome(), 'local-copies', `${copy.key}.json`);
|
|
292
320
|
await mkdir(dirname(path), { recursive: true, mode: 0o700 });
|
|
293
321
|
const temporary = `${path}.${process.pid}`;
|
|
294
322
|
await writeFile(temporary, JSON.stringify(copy), { mode: 0o600 });
|
|
@@ -296,8 +324,8 @@ export class LocalCopies {
|
|
|
296
324
|
this.copies.set(copy.key, copy);
|
|
297
325
|
return copy;
|
|
298
326
|
}
|
|
299
|
-
async read(
|
|
300
|
-
const prefixes = [rootOf(
|
|
327
|
+
async read(handle) {
|
|
328
|
+
const prefixes = [rootOf(handle)];
|
|
301
329
|
const discovery = await this.house.post('/kit/door/discover', { prefixes });
|
|
302
330
|
let bundle = await this.house.post('/kit/door/bootstrap', { prefixes });
|
|
303
331
|
if ('transfer' in bundle)
|
|
@@ -331,46 +359,13 @@ export class LocalCopies {
|
|
|
331
359
|
}
|
|
332
360
|
return read;
|
|
333
361
|
}
|
|
334
|
-
async
|
|
335
|
-
|
|
336
|
-
if (
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
copy = await this.save({ ...copy, room_handle: scope.handle });
|
|
342
|
-
if (!copy.active) {
|
|
343
|
-
await this.save(await this.received({ ...copy, active: true }));
|
|
344
|
-
return;
|
|
345
|
-
}
|
|
346
|
-
const discovery = await this.house.post('/kit/door/discover', {
|
|
347
|
-
prefixes: [rootOf(copy)],
|
|
348
|
-
});
|
|
349
|
-
const authority = discovery.authorities.find((entry) => entry.room_ref === copy.room_ref);
|
|
350
|
-
if (authority === undefined)
|
|
351
|
-
return;
|
|
352
|
-
if (authority.managed_replication !== 'admitted') {
|
|
353
|
-
logged(`operation_denied: ${rootOf(copy)} is not synchronized to this Environment`);
|
|
354
|
-
return;
|
|
355
|
-
}
|
|
356
|
-
if (JSON.stringify([authority.operations.write, authority.protected_paths]) !==
|
|
357
|
-
JSON.stringify([copy.write, copy.protected])) {
|
|
358
|
-
await this.save(await this.received(copy));
|
|
359
|
-
return;
|
|
360
|
-
}
|
|
361
|
-
await this.save(await this.caughtUp(copy));
|
|
362
|
-
}
|
|
363
|
-
async materialize(scope) {
|
|
364
|
-
const read = await this.read({ private: scope.private, room_handle: scope.handle });
|
|
365
|
-
if (read === null) {
|
|
366
|
-
logged(`House serves nothing of ${rootOf({ private: scope.private, room_handle: scope.handle })} to copy`);
|
|
367
|
-
return;
|
|
368
|
-
}
|
|
369
|
-
const repository = scope.private ? join(localCopies(), 'private') : join(localCopies(), 'rooms', read.anchor);
|
|
370
|
-
if (await exists(repository)) {
|
|
371
|
-
logged(`${repository} already exists and House Kit leaves it as it is`);
|
|
372
|
-
return;
|
|
373
|
-
}
|
|
362
|
+
async materialize(key, handle) {
|
|
363
|
+
const read = await this.read(handle);
|
|
364
|
+
if (read === null)
|
|
365
|
+
throw new Error('House serves nothing of it to copy');
|
|
366
|
+
const repository = join(localCopies(), 'rooms', read.anchor);
|
|
367
|
+
if (await exists(repository))
|
|
368
|
+
throw new Error(`${repository} already exists and House Kit leaves it as it is`);
|
|
374
369
|
const staging = join(dirname(repository), `.${randomUUID()}`);
|
|
375
370
|
await mkdir(staging, { recursive: true });
|
|
376
371
|
let house;
|
|
@@ -378,7 +373,7 @@ export class LocalCopies {
|
|
|
378
373
|
try {
|
|
379
374
|
await git(staging, ['init', '-q', '-b', BRANCH]);
|
|
380
375
|
house = await importCommits(staging, [
|
|
381
|
-
{ message: `House ${rootOf(
|
|
376
|
+
{ message: `House ${rootOf(handle)}`, from: null, files: read.writable },
|
|
382
377
|
]);
|
|
383
378
|
await git(staging, ['update-ref', `refs/heads/${BRANCH}`, house]);
|
|
384
379
|
await git(staging, ['reset', '-q', '--hard']);
|
|
@@ -391,10 +386,9 @@ export class LocalCopies {
|
|
|
391
386
|
throw error;
|
|
392
387
|
}
|
|
393
388
|
await this.save({
|
|
394
|
-
key
|
|
395
|
-
private: scope.private,
|
|
389
|
+
key,
|
|
396
390
|
room_ref: read.anchor,
|
|
397
|
-
room_handle:
|
|
391
|
+
room_handle: handle,
|
|
398
392
|
repository,
|
|
399
393
|
active: true,
|
|
400
394
|
house,
|
|
@@ -406,13 +400,14 @@ export class LocalCopies {
|
|
|
406
400
|
manifests: { [house]: { parent: null, files: read.revisions } },
|
|
407
401
|
moves: [],
|
|
408
402
|
});
|
|
403
|
+
return `${rootOf(handle)}: copied to ${repository}`;
|
|
409
404
|
}
|
|
410
405
|
async received(copy) {
|
|
411
|
-
const read = await this.read(copy);
|
|
406
|
+
const read = await this.read(copy.room_handle);
|
|
412
407
|
if (read === null)
|
|
413
408
|
return copy;
|
|
414
409
|
const house = await importCommits(copy.repository, [
|
|
415
|
-
{ message: `House ${rootOf(copy)} at position ${read.position}`, from: copy.house, replaces: true, files: read.writable },
|
|
410
|
+
{ message: `House ${rootOf(copy.room_handle)} at position ${read.position}`, from: copy.house, replaces: true, files: read.writable },
|
|
416
411
|
]);
|
|
417
412
|
const removed = copy.read_only.filter((path) => !read.readOnly.has(path));
|
|
418
413
|
const readOnly = await readOnlyPlaced(copy.repository, copy.read_only, read.readOnly, removed);
|
|
@@ -429,30 +424,52 @@ export class LocalCopies {
|
|
|
429
424
|
await ignoreRules(copy.repository, [...read.writable.keys()], next);
|
|
430
425
|
return next;
|
|
431
426
|
}
|
|
432
|
-
async
|
|
433
|
-
|
|
434
|
-
|
|
427
|
+
async refreshed(copies) {
|
|
428
|
+
const discovery = await this.house.post('/kit/door/discover', {
|
|
429
|
+
prefixes: copies.map((copy) => rootOf(copy.room_handle)),
|
|
430
|
+
});
|
|
431
|
+
const regranted = new Map();
|
|
432
|
+
for (const copy of copies) {
|
|
433
|
+
const authority = discovery.authorities.find((entry) => entry.room_ref === copy.room_ref);
|
|
434
|
+
if (authority !== undefined &&
|
|
435
|
+
JSON.stringify([authority.operations.write, authority.protected_paths]) !== JSON.stringify([copy.write, copy.protected])) {
|
|
436
|
+
regranted.set(copy.key, await this.save(await this.received(copy)));
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
const caught = await this.caughtUp(copies.filter((copy) => !regranted.has(copy.key)), false);
|
|
440
|
+
return copies.map((copy) => regranted.get(copy.key) ?? caught.find((held) => held.key === copy.key));
|
|
441
|
+
}
|
|
442
|
+
async caughtUp(copies, whole) {
|
|
443
|
+
const caught = new Map(copies.map((copy) => [copy.key, copy]));
|
|
444
|
+
let asking = [...copies];
|
|
445
|
+
while (asking.length > 0) {
|
|
435
446
|
let answer;
|
|
436
447
|
try {
|
|
437
448
|
answer = await this.house.post('/kit/door/enumerate', {
|
|
438
|
-
prefixes:
|
|
439
|
-
positions:
|
|
449
|
+
prefixes: asking.map((copy) => rootOf(copy.room_handle)),
|
|
450
|
+
positions: asking.map((copy) => ({ authority: copy.room_ref, position: copy.position, log_epoch: copy.log_epoch })),
|
|
440
451
|
});
|
|
441
452
|
}
|
|
442
453
|
catch (error) {
|
|
443
|
-
const
|
|
444
|
-
if (
|
|
445
|
-
return this.received(copy);
|
|
446
|
-
if (code !== 'replica_behind')
|
|
454
|
+
const expired = asking.find((copy) => copy.room_ref === expiredAuthority(error));
|
|
455
|
+
if (expired === undefined)
|
|
447
456
|
throw error;
|
|
448
|
-
|
|
449
|
-
|
|
457
|
+
caught.set(expired.key, await this.save(await this.received(expired)));
|
|
458
|
+
asking = asking.filter((copy) => copy !== expired);
|
|
459
|
+
continue;
|
|
460
|
+
}
|
|
461
|
+
const advanced = [];
|
|
462
|
+
for (const copy of asking) {
|
|
463
|
+
const view = answer.authorities.find((entry) => entry.authority === copy.room_ref);
|
|
464
|
+
if (view === undefined || (view.position === copy.position && view.log_epoch === copy.log_epoch))
|
|
465
|
+
continue;
|
|
466
|
+
const next = await this.save(await this.incorporated(copy, view.changes, view.position, view.log_epoch));
|
|
467
|
+
caught.set(copy.key, next);
|
|
468
|
+
advanced.push(next);
|
|
450
469
|
}
|
|
451
|
-
|
|
452
|
-
if (view === undefined || (view.position === copy.position && view.log_epoch === copy.log_epoch))
|
|
453
|
-
return copy;
|
|
454
|
-
copy = await this.save(await this.incorporated(copy, view.changes, view.position, view.log_epoch));
|
|
470
|
+
asking = whole ? advanced : [];
|
|
455
471
|
}
|
|
472
|
+
return copies.map((copy) => caught.get(copy.key));
|
|
456
473
|
}
|
|
457
474
|
async incorporated(copy, changes, position, logEpoch) {
|
|
458
475
|
const houseTree = await tree(copy.repository, copy.house);
|
|
@@ -485,7 +502,7 @@ export class LocalCopies {
|
|
|
485
502
|
let { house, manifests } = copy;
|
|
486
503
|
if (files.size > 0) {
|
|
487
504
|
house = await importCommits(copy.repository, [
|
|
488
|
-
{ message: `House ${rootOf(copy)} at position ${position}`, from: copy.house, files },
|
|
505
|
+
{ message: `House ${rootOf(copy.room_handle)} at position ${position}`, from: copy.house, files },
|
|
489
506
|
]);
|
|
490
507
|
manifests = { ...manifests, [house]: { parent: copy.house, files: revisions } };
|
|
491
508
|
}
|
|
@@ -516,7 +533,7 @@ export class LocalCopies {
|
|
|
516
533
|
copy = await this.save(without(copy));
|
|
517
534
|
}
|
|
518
535
|
if (!copy.active) {
|
|
519
|
-
return { refused: true, text: `${rootOf(copy)} is no longer synced to this Environment, so House takes no push from it` };
|
|
536
|
+
return { refused: true, text: `${rootOf(copy.room_handle)} is no longer synced to this Environment, so House takes no push from it` };
|
|
520
537
|
}
|
|
521
538
|
const listed = (await git(copy.repository, ['rev-list', '--topo-order', commit])).split('\n');
|
|
522
539
|
const base = listed.find((ancestor) => ancestor in copy.manifests);
|
|
@@ -550,7 +567,7 @@ export class LocalCopies {
|
|
|
550
567
|
return this.settle(submitted, caller);
|
|
551
568
|
}
|
|
552
569
|
async derived(copy, base, commit) {
|
|
553
|
-
const root = rootOf(copy);
|
|
570
|
+
const root = rootOf(copy.room_handle);
|
|
554
571
|
const before = await tree(copy.repository, base);
|
|
555
572
|
const after = await tree(copy.repository, commit);
|
|
556
573
|
const moved = movedPaths(copy.moves, before, after);
|
|
@@ -611,7 +628,7 @@ export class LocalCopies {
|
|
|
611
628
|
const rebased = rebaseFixes(outcome.refused);
|
|
612
629
|
let settled = await this.save(without(copy));
|
|
613
630
|
try {
|
|
614
|
-
settled =
|
|
631
|
+
settled = (await this.caughtUp([settled], true))[0];
|
|
615
632
|
}
|
|
616
633
|
catch {
|
|
617
634
|
return {
|
|
@@ -630,9 +647,9 @@ export class LocalCopies {
|
|
|
630
647
|
}
|
|
631
648
|
async recovered(copy) {
|
|
632
649
|
const push = copy.push;
|
|
633
|
-
const current =
|
|
650
|
+
const current = (await this.caughtUp([copy], true))[0];
|
|
634
651
|
const house = await tree(copy.repository, current.house);
|
|
635
|
-
const root = rootOf(current);
|
|
652
|
+
const root = rootOf(current.room_handle);
|
|
636
653
|
if (!(await this.landed(copy.repository, push.changes, house, await tree(copy.repository, push.commit)))) {
|
|
637
654
|
await this.save(without(current));
|
|
638
655
|
return {
|
|
@@ -674,7 +691,7 @@ export class LocalCopies {
|
|
|
674
691
|
const push = copy.push;
|
|
675
692
|
let written = push.written;
|
|
676
693
|
if (push.changes.some((change) => change.op === 'rename')) {
|
|
677
|
-
copy =
|
|
694
|
+
copy = (await this.caughtUp([copy], true))[0];
|
|
678
695
|
const house = await tree(copy.repository, copy.house);
|
|
679
696
|
const sent = await tree(copy.repository, push.house);
|
|
680
697
|
if (push.changes.some((change) => change.op === 'rename' && !house.has(relative(change.to)))) {
|
|
@@ -688,7 +705,7 @@ export class LocalCopies {
|
|
|
688
705
|
written = [
|
|
689
706
|
...written,
|
|
690
707
|
{
|
|
691
|
-
path: `${rootOf(copy)}/${path}`,
|
|
708
|
+
path: `${rootOf(copy.room_handle)}/${path}`,
|
|
692
709
|
revision: entry === undefined ? null : (revisionAt(copy, copy.house, path) ?? null),
|
|
693
710
|
content: entry === undefined ? null : await blobText(copy.repository, entry, path),
|
|
694
711
|
},
|
|
@@ -708,7 +725,7 @@ export class LocalCopies {
|
|
|
708
725
|
}
|
|
709
726
|
const edits = new Map([...files].filter(([path, content]) => (content === null ? selected.has(path) : selected.get(path) !== blobId(content))));
|
|
710
727
|
const received = [...files.keys()].filter((path) => revisionAt(copy, copy.house, path) === revisionAt(copy, push.house, path));
|
|
711
|
-
const accepted = `House ${rootOf(copy)} with ${push.commit} accepted`;
|
|
728
|
+
const accepted = `House ${rootOf(copy.room_handle)} with ${push.commit} accepted`;
|
|
712
729
|
const house = await importCommits(copy.repository, [
|
|
713
730
|
...(edits.size === 0 ? [] : [{ message: accepted, from: push.commit, files: edits }]),
|
|
714
731
|
{
|
package/dist/end.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { killDescendants } from './scope.js';
|
|
2
|
+
export const REPLACED = 'another Kit started for this Environment';
|
|
3
|
+
export const SIGN_IN_AGAIN = 'sign in again';
|
|
4
|
+
export function end(reason) {
|
|
5
|
+
process.stderr.write(`kit: ${reason}\n`);
|
|
6
|
+
killDescendants();
|
|
7
|
+
process.exit(0);
|
|
8
|
+
}
|