@agentshouse/kit 0.2.1-c2c600f2d2b30 → 0.2.1-c2f0855c31ca3
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 +26 -26
- package/dist/acp.js +16 -93
- package/dist/agents.js +70 -32
- package/dist/api.js +25 -3
- package/dist/app-git.js +64 -0
- package/dist/bootstrap.json +4 -4
- package/dist/bridge.js +33 -52
- package/dist/chatgpt.js +26 -0
- package/dist/clis.js +116 -70
- package/dist/codex-main.js +58 -0
- package/dist/conversations.js +284 -236
- package/dist/copies.js +148 -113
- package/dist/end.js +18 -4
- package/dist/enrol-main.js +7 -1
- package/dist/events.js +521 -0
- package/dist/files.js +21 -1
- package/dist/git.js +11 -8
- package/dist/home.js +78 -6
- package/dist/house-main.js +186 -56
- package/dist/instructions.js +9 -32
- package/dist/kit-main.js +54 -6
- package/dist/login.js +94 -104
- package/dist/logout.js +16 -13
- package/dist/parts.js +82 -0
- package/dist/placement.js +48 -0
- package/dist/refusals.js +12 -0
- package/dist/relay.js +12 -2
- package/dist/resident.js +38 -27
- package/dist/scope.js +203 -0
- package/dist/secret-input.js +2 -2
- package/dist/service-main.js +9 -0
- package/dist/service.js +33 -0
- package/dist/shell.js +3 -0
- package/dist/sign-in.js +34 -10
- package/dist/skills.js +80 -12
- package/dist/stream.js +12 -7
- package/dist/transcription.js +57 -11
- package/dist/update.js +28 -6
- package/dist/wire.js +6 -0
- package/dist/work.js +348 -0
- package/how-we-work.md +11 -3
- package/package.json +3 -2
- package/skills/ask-matt/SKILL.md +17 -11
- package/skills/ask-matt/agents/openai.yaml +1 -0
- package/skills/code-review/SKILL.md +5 -5
- package/skills/codebase-design/DESIGN-IT-TWICE.md +1 -1
- package/skills/codebase-design/SKILL.md +0 -2
- package/skills/diagnosing-bugs/SKILL.md +2 -4
- package/skills/domain-modeling/{CONTEXT-FORMAT.md → GLOSSARY-FORMAT.md} +10 -10
- package/skills/domain-modeling/SKILL.md +12 -14
- package/skills/grill-me/SKILL.md +1 -2
- package/skills/grill-me/agents/openai.yaml +1 -0
- package/skills/grill-with-docs/SKILL.md +1 -2
- package/skills/grill-with-docs/agents/openai.yaml +1 -0
- package/skills/grilling/SKILL.md +2 -2
- package/skills/handoff/SKILL.md +2 -3
- package/skills/handoff/agents/openai.yaml +1 -0
- package/skills/implement/SKILL.md +5 -4
- package/skills/implement/agents/openai.yaml +1 -0
- package/skills/implement-spec/SKILL.md +40 -0
- package/skills/implement-spec/agents/openai.yaml +5 -0
- package/skills/improve-codebase-architecture/SKILL.md +6 -7
- package/skills/improve-codebase-architecture/agents/openai.yaml +1 -0
- package/skills/pr/CREDITS.md +3 -0
- package/skills/pr/LICENSE +21 -0
- package/skills/pr/SKILL.md +170 -0
- package/skills/pr/agents/openai.yaml +3 -0
- package/skills/prototype/SKILL.md +0 -2
- package/skills/research/SKILL.md +0 -2
- package/skills/retro/LICENSE +21 -0
- package/skills/retro/SKILL.md +44 -0
- package/skills/retro/agents/openai.yaml +5 -0
- package/skills/tdd/SKILL.md +2 -4
- package/skills/teach/SKILL.md +3 -4
- package/skills/teach/agents/openai.yaml +1 -0
- package/skills/to-questionnaire/SKILL.md +1 -2
- package/skills/to-questionnaire/agents/openai.yaml +1 -0
- package/skills/to-spec/SKILL.md +1 -2
- package/skills/to-spec/agents/openai.yaml +1 -0
- package/skills/to-tickets/SKILL.md +3 -4
- package/skills/to-tickets/agents/openai.yaml +1 -0
- package/skills/triage/AGENT-BRIEF.md +207 -0
- package/skills/triage/LICENSE +21 -0
- package/skills/triage/OUT-OF-SCOPE.md +105 -0
- package/skills/triage/SKILL.md +112 -0
- package/skills/triage/agents/openai.yaml +5 -0
- package/skills/wait-what/SKILL.md +2 -3
- package/skills/wait-what/agents/openai.yaml +1 -0
- package/skills/wayfinder/SKILL.md +5 -6
- package/skills/wayfinder/agents/openai.yaml +1 -0
- package/skills/wizard/LICENSE +21 -0
- package/skills/wizard/SKILL.md +44 -0
- package/skills/wizard/agents/openai.yaml +3 -0
- package/skills/wizard/template.sh +223 -0
- package/skills/writing-for-agents/SKILL.md +0 -2
- package/dist/blocks.js +0 -51
- package/skills/resolving-merge-conflicts/SKILL.md +0 -16
- package/skills/resolving-merge-conflicts/agents/openai.yaml +0 -3
- /package/skills/{resolving-merge-conflicts → implement-spec}/LICENSE +0 -0
package/dist/copies.js
CHANGED
|
@@ -2,8 +2,8 @@ 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';
|
|
6
|
-
import { blobId, blobText, git, HOUSE_REF, importCommits, localCopies, revision, run, succeeded, tree, } from './git.js';
|
|
5
|
+
import { finalRefusal, HouseRefusal, retrying } from './api.js';
|
|
6
|
+
import { blobId, blobText, git, isText, 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';
|
|
9
9
|
import { refusalOf } from './refusals.js';
|
|
@@ -29,9 +29,29 @@ const REBASED = new Set([
|
|
|
29
29
|
function rebaseFixes(refusal) {
|
|
30
30
|
return refusal.code === 'edit_conflict' && refusal.conflicts.some((code) => REBASED.has(code));
|
|
31
31
|
}
|
|
32
|
+
function textOnly(paths) {
|
|
33
|
+
const [named, them] = paths.length === 1 ? [`${paths[0]} is`, 'it'] : [`${paths.join(', ')} are`, 'them'];
|
|
34
|
+
return `${named} not text, and house push sends text only; remove ${them} from the commit and place ${them} with house upload`;
|
|
35
|
+
}
|
|
32
36
|
function short(commit) {
|
|
33
37
|
return commit.slice(0, 12);
|
|
34
38
|
}
|
|
39
|
+
function moved(before, after) {
|
|
40
|
+
if (before.house !== after.house)
|
|
41
|
+
return [`${rootOf(after.room_handle)}: ${HOUSE_REF} is at ${short(after.house)}`];
|
|
42
|
+
return before.position === after.position ? [] : [`${rootOf(after.room_handle)}: read-only files refreshed`];
|
|
43
|
+
}
|
|
44
|
+
function expiredAuthority(error) {
|
|
45
|
+
if (!(error instanceof HouseRefusal))
|
|
46
|
+
return undefined;
|
|
47
|
+
try {
|
|
48
|
+
const { error: refused } = JSON.parse(error.text);
|
|
49
|
+
return refused?.code === 'expired' && typeof refused.authority === 'string' ? refused.authority : undefined;
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
35
55
|
function covers(path, prefix) {
|
|
36
56
|
return prefix === '' || path === prefix || path.startsWith(`${prefix}/`);
|
|
37
57
|
}
|
|
@@ -152,19 +172,18 @@ export class LocalCopies {
|
|
|
152
172
|
house;
|
|
153
173
|
copies = new Map();
|
|
154
174
|
queues = new Map();
|
|
155
|
-
|
|
156
|
-
selecting = Promise.resolve();
|
|
175
|
+
answering = Promise.resolve();
|
|
157
176
|
constructor(house) {
|
|
158
177
|
this.house = house;
|
|
159
178
|
this.owner = {
|
|
160
179
|
key: 'owner',
|
|
161
180
|
submit: async (operation, changes) => {
|
|
162
181
|
try {
|
|
163
|
-
const outcome = await house.post('/kit/door/batch', { operation_id: operation, changes });
|
|
182
|
+
const outcome = await retrying(() => house.post('/kit/door/batch', { operation_id: operation, changes }));
|
|
164
183
|
return { accepted: outcome.contents };
|
|
165
184
|
}
|
|
166
185
|
catch (error) {
|
|
167
|
-
if (!(error
|
|
186
|
+
if (!finalRefusal(error))
|
|
168
187
|
throw error;
|
|
169
188
|
return {
|
|
170
189
|
refused: refusalOf(error.text) ?? { code: '', text: `House refused it with ${error.status}`, conflicts: [] },
|
|
@@ -185,42 +204,68 @@ export class LocalCopies {
|
|
|
185
204
|
}
|
|
186
205
|
}
|
|
187
206
|
async mapping() {
|
|
188
|
-
await this.
|
|
207
|
+
await this.answering;
|
|
189
208
|
return [...this.copies.values()]
|
|
190
209
|
.filter((copy) => copy.active)
|
|
191
210
|
.map((copy) => `${rootOf(copy.room_handle)}: ${copy.repository}`)
|
|
192
211
|
.sort();
|
|
193
212
|
}
|
|
194
|
-
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
199
|
-
async reselect() {
|
|
200
|
-
const { local_copy: chosen } = await this.house.post('/kit/local-copy/selection', {});
|
|
201
|
-
const selected = (chosen?.rooms ?? []).flatMap((room) => room.room_handle === null ? [] : [{ key: `rooms/${room.room_ref}`, handle: room.room_handle }]);
|
|
202
|
-
const keys = new Set(selected.map((scope) => scope.key));
|
|
203
|
-
const work = [];
|
|
204
|
-
for (const key of this.copies.keys()) {
|
|
205
|
-
if (keys.has(key))
|
|
206
|
-
continue;
|
|
207
|
-
work.push(this.exclusive(key, async () => {
|
|
208
|
-
const copy = this.copies.get(key);
|
|
209
|
-
if (copy.active)
|
|
210
|
-
await this.save({ ...copy, active: false });
|
|
211
|
-
}));
|
|
212
|
-
}
|
|
213
|
-
for (const scope of selected)
|
|
214
|
-
work.push(this.exclusive(scope.key, () => this.apply(scope)).catch(logged));
|
|
215
|
-
await Promise.all(work);
|
|
213
|
+
async connected() {
|
|
214
|
+
const copied = await this.answered(() => this.fetched(false));
|
|
215
|
+
if (copied.refused)
|
|
216
|
+
logged(copied.text);
|
|
216
217
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
218
|
+
fetch() {
|
|
219
|
+
return this.answered(() => this.fetched(true));
|
|
220
|
+
}
|
|
221
|
+
answered(work) {
|
|
222
|
+
const answered = this.answering.then(work);
|
|
223
|
+
this.answering = answered.catch(() => undefined);
|
|
224
|
+
return answered;
|
|
225
|
+
}
|
|
226
|
+
async fetched(refreshing) {
|
|
227
|
+
const { local_copy: answer } = await this.house.post('/kit/local-copy/selection', {});
|
|
228
|
+
const synced = new Map(answer.rooms.map((room) => [`rooms/${room.room_ref}`, room.room_handle]));
|
|
229
|
+
return this.holding([...new Set([...this.copies.keys(), ...synced.keys()])].sort(), async () => {
|
|
230
|
+
const said = [];
|
|
231
|
+
let refused = false;
|
|
232
|
+
for (const copy of this.copies.values()) {
|
|
233
|
+
if (synced.has(copy.key) || !copy.active)
|
|
234
|
+
continue;
|
|
235
|
+
await this.save({ ...copy, active: false });
|
|
236
|
+
said.push(`${rootOf(copy.room_handle)}: no longer synced to this Environment; its files stay`);
|
|
237
|
+
}
|
|
238
|
+
const current = [];
|
|
239
|
+
for (const [key, handle] of synced) {
|
|
240
|
+
try {
|
|
241
|
+
const held = this.copies.get(key);
|
|
242
|
+
if (held === undefined || !(await exists(held.repository))) {
|
|
243
|
+
said.push(await this.materialize(key, handle));
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
const copy = held.room_handle === handle ? held : await this.save({ ...held, room_handle: handle });
|
|
247
|
+
if (copy.active)
|
|
248
|
+
current.push(copy);
|
|
249
|
+
else
|
|
250
|
+
said.push(...moved(copy, await this.save(await this.received({ ...copy, active: true }))));
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
refused = true;
|
|
254
|
+
said.push(`${rootOf(handle)}: ${causeOf(error)}`);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
if (refreshing && current.length > 0) {
|
|
258
|
+
try {
|
|
259
|
+
const refreshed = await this.refreshed(current);
|
|
260
|
+
current.forEach((copy, index) => said.push(...moved(copy, refreshed[index])));
|
|
261
|
+
}
|
|
262
|
+
catch (error) {
|
|
263
|
+
refused = true;
|
|
264
|
+
said.push(error instanceof HouseRefusal ? (refusalOf(error.text)?.text ?? causeOf(error)) : causeOf(error));
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return { refused, text: said.length === 0 ? 'Nothing new from House.' : said.join('\n') };
|
|
268
|
+
});
|
|
224
269
|
}
|
|
225
270
|
async observed(report) {
|
|
226
271
|
const key = await this.keyAt(dirname(report.common));
|
|
@@ -270,16 +315,9 @@ export class LocalCopies {
|
|
|
270
315
|
this.queues.set(key, queued.catch(() => undefined));
|
|
271
316
|
return queued;
|
|
272
317
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
this.delivering.add(key);
|
|
277
|
-
void this.exclusive(key, async () => {
|
|
278
|
-
this.delivering.delete(key);
|
|
279
|
-
const copy = this.copies.get(key);
|
|
280
|
-
if (copy.active)
|
|
281
|
-
await this.save(await this.caughtUp(copy));
|
|
282
|
-
}).catch(logged);
|
|
318
|
+
holding(keys, work) {
|
|
319
|
+
const [key, ...rest] = keys;
|
|
320
|
+
return key === undefined ? work() : this.exclusive(key, () => this.holding(rest, work));
|
|
283
321
|
}
|
|
284
322
|
async save(copy) {
|
|
285
323
|
const path = join(kitHome(), 'local-copies', `${copy.key}.json`);
|
|
@@ -325,46 +363,13 @@ export class LocalCopies {
|
|
|
325
363
|
}
|
|
326
364
|
return read;
|
|
327
365
|
}
|
|
328
|
-
async
|
|
329
|
-
|
|
330
|
-
if (
|
|
331
|
-
|
|
332
|
-
return;
|
|
333
|
-
}
|
|
334
|
-
if (copy.room_handle !== scope.handle)
|
|
335
|
-
copy = await this.save({ ...copy, room_handle: scope.handle });
|
|
336
|
-
if (!copy.active) {
|
|
337
|
-
await this.save(await this.received({ ...copy, active: true }));
|
|
338
|
-
return;
|
|
339
|
-
}
|
|
340
|
-
const discovery = await this.house.post('/kit/door/discover', {
|
|
341
|
-
prefixes: [rootOf(copy.room_handle)],
|
|
342
|
-
});
|
|
343
|
-
const authority = discovery.authorities.find((entry) => entry.room_ref === copy.room_ref);
|
|
344
|
-
if (authority === undefined)
|
|
345
|
-
return;
|
|
346
|
-
if (authority.managed_replication !== 'admitted') {
|
|
347
|
-
logged(`operation_denied: ${rootOf(copy.room_handle)} is not synchronized to this Environment`);
|
|
348
|
-
return;
|
|
349
|
-
}
|
|
350
|
-
if (JSON.stringify([authority.operations.write, authority.protected_paths]) !==
|
|
351
|
-
JSON.stringify([copy.write, copy.protected])) {
|
|
352
|
-
await this.save(await this.received(copy));
|
|
353
|
-
return;
|
|
354
|
-
}
|
|
355
|
-
await this.save(await this.caughtUp(copy));
|
|
356
|
-
}
|
|
357
|
-
async materialize(scope) {
|
|
358
|
-
const read = await this.read(scope.handle);
|
|
359
|
-
if (read === null) {
|
|
360
|
-
logged(`House serves nothing of ${rootOf(scope.handle)} to copy`);
|
|
361
|
-
return;
|
|
362
|
-
}
|
|
366
|
+
async materialize(key, handle) {
|
|
367
|
+
const read = await this.read(handle);
|
|
368
|
+
if (read === null)
|
|
369
|
+
throw new Error('House serves nothing of it to copy');
|
|
363
370
|
const repository = join(localCopies(), 'rooms', read.anchor);
|
|
364
|
-
if (await exists(repository))
|
|
365
|
-
|
|
366
|
-
return;
|
|
367
|
-
}
|
|
371
|
+
if (await exists(repository))
|
|
372
|
+
throw new Error(`${repository} already exists and House Kit leaves it as it is`);
|
|
368
373
|
const staging = join(dirname(repository), `.${randomUUID()}`);
|
|
369
374
|
await mkdir(staging, { recursive: true });
|
|
370
375
|
let house;
|
|
@@ -372,7 +377,7 @@ export class LocalCopies {
|
|
|
372
377
|
try {
|
|
373
378
|
await git(staging, ['init', '-q', '-b', BRANCH]);
|
|
374
379
|
house = await importCommits(staging, [
|
|
375
|
-
{ message: `House ${rootOf(
|
|
380
|
+
{ message: `House ${rootOf(handle)}`, from: null, files: read.writable },
|
|
376
381
|
]);
|
|
377
382
|
await git(staging, ['update-ref', `refs/heads/${BRANCH}`, house]);
|
|
378
383
|
await git(staging, ['reset', '-q', '--hard']);
|
|
@@ -385,9 +390,9 @@ export class LocalCopies {
|
|
|
385
390
|
throw error;
|
|
386
391
|
}
|
|
387
392
|
await this.save({
|
|
388
|
-
key
|
|
393
|
+
key,
|
|
389
394
|
room_ref: read.anchor,
|
|
390
|
-
room_handle:
|
|
395
|
+
room_handle: handle,
|
|
391
396
|
repository,
|
|
392
397
|
active: true,
|
|
393
398
|
house,
|
|
@@ -399,6 +404,7 @@ export class LocalCopies {
|
|
|
399
404
|
manifests: { [house]: { parent: null, files: read.revisions } },
|
|
400
405
|
moves: [],
|
|
401
406
|
});
|
|
407
|
+
return `${rootOf(handle)}: copied to ${repository}`;
|
|
402
408
|
}
|
|
403
409
|
async received(copy) {
|
|
404
410
|
const read = await this.read(copy.room_handle);
|
|
@@ -422,29 +428,52 @@ export class LocalCopies {
|
|
|
422
428
|
await ignoreRules(copy.repository, [...read.writable.keys()], next);
|
|
423
429
|
return next;
|
|
424
430
|
}
|
|
425
|
-
async
|
|
426
|
-
|
|
427
|
-
|
|
431
|
+
async refreshed(copies) {
|
|
432
|
+
const discovery = await this.house.post('/kit/door/discover', {
|
|
433
|
+
prefixes: copies.map((copy) => rootOf(copy.room_handle)),
|
|
434
|
+
});
|
|
435
|
+
const regranted = new Map();
|
|
436
|
+
for (const copy of copies) {
|
|
437
|
+
const authority = discovery.authorities.find((entry) => entry.room_ref === copy.room_ref);
|
|
438
|
+
if (authority !== undefined &&
|
|
439
|
+
JSON.stringify([authority.operations.write, authority.protected_paths]) !== JSON.stringify([copy.write, copy.protected])) {
|
|
440
|
+
regranted.set(copy.key, await this.save(await this.received(copy)));
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
const caught = await this.caughtUp(copies.filter((copy) => !regranted.has(copy.key)), false);
|
|
444
|
+
return copies.map((copy) => regranted.get(copy.key) ?? caught.find((held) => held.key === copy.key));
|
|
445
|
+
}
|
|
446
|
+
async caughtUp(copies, whole) {
|
|
447
|
+
const caught = new Map(copies.map((copy) => [copy.key, copy]));
|
|
448
|
+
let asking = [...copies];
|
|
449
|
+
while (asking.length > 0) {
|
|
428
450
|
let answer;
|
|
429
451
|
try {
|
|
430
452
|
answer = await this.house.post('/kit/door/enumerate', {
|
|
431
|
-
prefixes:
|
|
432
|
-
positions:
|
|
453
|
+
prefixes: asking.map((copy) => rootOf(copy.room_handle)),
|
|
454
|
+
positions: asking.map((copy) => ({ authority: copy.room_ref, position: copy.position, log_epoch: copy.log_epoch })),
|
|
433
455
|
});
|
|
434
456
|
}
|
|
435
457
|
catch (error) {
|
|
436
|
-
const
|
|
437
|
-
if (
|
|
438
|
-
return this.received(copy);
|
|
439
|
-
if (code !== 'replica_behind')
|
|
458
|
+
const expired = asking.find((copy) => copy.room_ref === expiredAuthority(error));
|
|
459
|
+
if (expired === undefined)
|
|
440
460
|
throw error;
|
|
441
|
-
|
|
461
|
+
caught.set(expired.key, await this.save(await this.received(expired)));
|
|
462
|
+
asking = asking.filter((copy) => copy !== expired);
|
|
463
|
+
continue;
|
|
464
|
+
}
|
|
465
|
+
const advanced = [];
|
|
466
|
+
for (const copy of asking) {
|
|
467
|
+
const view = answer.authorities.find((entry) => entry.authority === copy.room_ref);
|
|
468
|
+
if (view === undefined || (view.position === copy.position && view.log_epoch === copy.log_epoch))
|
|
469
|
+
continue;
|
|
470
|
+
const next = await this.save(await this.incorporated(copy, view.changes, view.position, view.log_epoch));
|
|
471
|
+
caught.set(copy.key, next);
|
|
472
|
+
advanced.push(next);
|
|
442
473
|
}
|
|
443
|
-
|
|
444
|
-
if (view === undefined || (view.position === copy.position && view.log_epoch === copy.log_epoch))
|
|
445
|
-
return copy;
|
|
446
|
-
copy = await this.save(await this.incorporated(copy, view.changes, view.position, view.log_epoch));
|
|
474
|
+
asking = whole ? advanced : [];
|
|
447
475
|
}
|
|
476
|
+
return copies.map((copy) => caught.get(copy.key));
|
|
448
477
|
}
|
|
449
478
|
async incorporated(copy, changes, position, logEpoch) {
|
|
450
479
|
const houseTree = await tree(copy.repository, copy.house);
|
|
@@ -547,7 +576,13 @@ export class LocalCopies {
|
|
|
547
576
|
const after = await tree(copy.repository, commit);
|
|
548
577
|
const moved = movedPaths(copy.moves, before, after);
|
|
549
578
|
const arrived = new Set(moved.values());
|
|
550
|
-
const
|
|
579
|
+
const binary = [];
|
|
580
|
+
for (const [path, entry] of after)
|
|
581
|
+
if (before.get(path) !== entry && !(await isText(copy.repository, entry)))
|
|
582
|
+
binary.push(path);
|
|
583
|
+
if (binary.length > 0)
|
|
584
|
+
throw new Error(textOnly(binary));
|
|
585
|
+
const text = (entry) => blobText(copy.repository, entry);
|
|
551
586
|
const changes = [];
|
|
552
587
|
for (const path of [...new Set([...before.keys(), ...after.keys()])].sort()) {
|
|
553
588
|
if (arrived.has(path))
|
|
@@ -560,7 +595,7 @@ export class LocalCopies {
|
|
|
560
595
|
changes.push({ op: 'rename', path: `${root}/${path}`, to: `${root}/${to}`, base: known });
|
|
561
596
|
const moving = after.get(to);
|
|
562
597
|
if (moving !== prior) {
|
|
563
|
-
changes.push({ op: 'replace', path: `${root}/${to}`, base: known, content: await text(moving
|
|
598
|
+
changes.push({ op: 'replace', path: `${root}/${to}`, base: known, content: await text(moving) });
|
|
564
599
|
}
|
|
565
600
|
continue;
|
|
566
601
|
}
|
|
@@ -569,9 +604,9 @@ export class LocalCopies {
|
|
|
569
604
|
if (next === undefined)
|
|
570
605
|
changes.push({ op: 'remove', path: `${root}/${path}`, base: known });
|
|
571
606
|
else if (prior === undefined)
|
|
572
|
-
changes.push({ op: 'create', path: `${root}/${path}`, content: await text(next
|
|
607
|
+
changes.push({ op: 'create', path: `${root}/${path}`, content: await text(next) });
|
|
573
608
|
else
|
|
574
|
-
changes.push(...changed(`${root}/${path}`, path, known, await text(prior
|
|
609
|
+
changes.push(...changed(`${root}/${path}`, path, known, await text(prior), await text(next)));
|
|
575
610
|
}
|
|
576
611
|
return changes;
|
|
577
612
|
}
|
|
@@ -598,12 +633,12 @@ export class LocalCopies {
|
|
|
598
633
|
const { upload, ...unstaged } = copy.push;
|
|
599
634
|
return this.settle(await this.save({ ...copy, push: unstaged }), caller, true);
|
|
600
635
|
}
|
|
601
|
-
if (outcome.refused.code === '
|
|
636
|
+
if (outcome.refused.code === 'expired')
|
|
602
637
|
return this.recovered(copy);
|
|
603
638
|
const rebased = rebaseFixes(outcome.refused);
|
|
604
639
|
let settled = await this.save(without(copy));
|
|
605
640
|
try {
|
|
606
|
-
settled =
|
|
641
|
+
settled = (await this.caughtUp([settled], true))[0];
|
|
607
642
|
}
|
|
608
643
|
catch {
|
|
609
644
|
return {
|
|
@@ -622,7 +657,7 @@ export class LocalCopies {
|
|
|
622
657
|
}
|
|
623
658
|
async recovered(copy) {
|
|
624
659
|
const push = copy.push;
|
|
625
|
-
const current =
|
|
660
|
+
const current = (await this.caughtUp([copy], true))[0];
|
|
626
661
|
const house = await tree(copy.repository, current.house);
|
|
627
662
|
const root = rootOf(current.room_handle);
|
|
628
663
|
if (!(await this.landed(copy.repository, push.changes, house, await tree(copy.repository, push.commit)))) {
|
|
@@ -638,7 +673,7 @@ export class LocalCopies {
|
|
|
638
673
|
written.push({
|
|
639
674
|
path: `${root}/${path}`,
|
|
640
675
|
revision: entry === undefined ? null : (revisionAt(current, current.house, path) ?? null),
|
|
641
|
-
content: entry === undefined ? null : await blobText(copy.repository, entry
|
|
676
|
+
content: entry === undefined ? null : await blobText(copy.repository, entry),
|
|
642
677
|
});
|
|
643
678
|
}
|
|
644
679
|
return this.finished(await this.save({ ...current, push: { ...push, state: 'accepted', written } }));
|
|
@@ -666,7 +701,7 @@ export class LocalCopies {
|
|
|
666
701
|
const push = copy.push;
|
|
667
702
|
let written = push.written;
|
|
668
703
|
if (push.changes.some((change) => change.op === 'rename')) {
|
|
669
|
-
copy =
|
|
704
|
+
copy = (await this.caughtUp([copy], true))[0];
|
|
670
705
|
const house = await tree(copy.repository, copy.house);
|
|
671
706
|
const sent = await tree(copy.repository, push.house);
|
|
672
707
|
if (push.changes.some((change) => change.op === 'rename' && !house.has(relative(change.to)))) {
|
|
@@ -682,7 +717,7 @@ export class LocalCopies {
|
|
|
682
717
|
{
|
|
683
718
|
path: `${rootOf(copy.room_handle)}/${path}`,
|
|
684
719
|
revision: entry === undefined ? null : (revisionAt(copy, copy.house, path) ?? null),
|
|
685
|
-
content: entry === undefined ? null : await blobText(copy.repository, entry
|
|
720
|
+
content: entry === undefined ? null : await blobText(copy.repository, entry),
|
|
686
721
|
},
|
|
687
722
|
];
|
|
688
723
|
}
|
|
@@ -727,7 +762,7 @@ export class LocalCopies {
|
|
|
727
762
|
async landed(repository, changes, house, selected) {
|
|
728
763
|
const text = async (path) => {
|
|
729
764
|
const entry = house.get(relative(path));
|
|
730
|
-
return entry === undefined ? undefined : blobText(repository, entry
|
|
765
|
+
return entry === undefined ? undefined : blobText(repository, entry);
|
|
731
766
|
};
|
|
732
767
|
for (const change of changes) {
|
|
733
768
|
const current = await text(change.path);
|
package/dist/end.js
CHANGED
|
@@ -1,8 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { forgetRejected } from './home.js';
|
|
2
|
+
import { installCommand } from './placement.js';
|
|
3
|
+
import { killDescendants } from './scope.js';
|
|
2
4
|
export const REPLACED = 'another Kit started for this Environment';
|
|
3
|
-
|
|
4
|
-
export function end(reason) {
|
|
5
|
+
function exit(reason, status) {
|
|
5
6
|
process.stderr.write(`kit: ${reason}\n`);
|
|
6
7
|
killDescendants();
|
|
7
|
-
process.exit(
|
|
8
|
+
process.exit(status);
|
|
9
|
+
}
|
|
10
|
+
export function end(reason) {
|
|
11
|
+
exit(reason, 0);
|
|
12
|
+
}
|
|
13
|
+
export function restart(reason) {
|
|
14
|
+
exit(reason, 1);
|
|
15
|
+
}
|
|
16
|
+
export function updateRequired(house) {
|
|
17
|
+
end(`This Kit is too old for House. Update it: ${installCommand(house)}`);
|
|
18
|
+
}
|
|
19
|
+
export async function signInAgain(rejected) {
|
|
20
|
+
await forgetRejected(rejected);
|
|
21
|
+
restart('sign in again');
|
|
8
22
|
}
|
package/dist/enrol-main.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
2
|
import { writeEnrolment } from './home.js';
|
|
3
3
|
const [house, environment] = process.argv.slice(2);
|
|
4
|
-
|
|
4
|
+
const relay = process.env.HOUSE_KIT_RELAY || undefined;
|
|
5
|
+
await writeEnrolment({
|
|
6
|
+
house: house,
|
|
7
|
+
...(relay === undefined ? {} : { relay }),
|
|
8
|
+
environment: environment,
|
|
9
|
+
credential: readFileSync(0, 'utf8').trim(),
|
|
10
|
+
});
|