@agentshouse/kit 0.2.1-c5d36e97b0fea → 0.2.1-c5d51f1e4ce19
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 +25 -24
- package/dist/agents.js +73 -7
- package/dist/api.js +6 -2
- package/dist/bootstrap.json +4 -4
- package/dist/chatgpt.js +32 -0
- package/dist/clis.js +42 -9
- package/dist/conversations.js +29 -9
- package/dist/copies.js +36 -26
- package/dist/end.js +17 -3
- package/dist/enrol-main.js +7 -1
- package/dist/events.js +3 -0
- package/dist/files.js +7 -1
- package/dist/git.js +11 -8
- package/dist/home.js +81 -6
- package/dist/house-cli.js +291 -0
- package/dist/house-main.js +7 -188
- package/dist/instructions.js +7 -31
- package/dist/kit-cli.js +68 -0
- package/dist/kit-main.js +8 -22
- package/dist/login.js +102 -21
- package/dist/parts.js +34 -16
- package/dist/placement.js +48 -0
- package/dist/relay.js +12 -2
- package/dist/resident.js +15 -6
- package/dist/service-main.js +9 -0
- package/dist/service.js +33 -0
- package/dist/skills.js +81 -12
- package/dist/stream.js +66 -15
- package/dist/transcription.js +3 -3
- package/dist/update.js +28 -6
- package/dist/wire.js +6 -0
- package/how-we-work.md +13 -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/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
|
@@ -3,7 +3,7 @@ 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
5
|
import { finalRefusal, HouseRefusal, retrying } from './api.js';
|
|
6
|
-
import { blobId, blobText, git, HOUSE_REF, importCommits, localCopies, revision, run, succeeded, tree, } from './git.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,6 +29,10 @@ 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
|
}
|
|
@@ -42,7 +46,7 @@ function expiredAuthority(error) {
|
|
|
42
46
|
return undefined;
|
|
43
47
|
try {
|
|
44
48
|
const { error: refused } = JSON.parse(error.text);
|
|
45
|
-
return refused?.code === '
|
|
49
|
+
return refused?.code === 'expired' && typeof refused.authority === 'string' ? refused.authority : undefined;
|
|
46
50
|
}
|
|
47
51
|
catch {
|
|
48
52
|
return undefined;
|
|
@@ -168,7 +172,7 @@ export class LocalCopies {
|
|
|
168
172
|
house;
|
|
169
173
|
copies = new Map();
|
|
170
174
|
queues = new Map();
|
|
171
|
-
|
|
175
|
+
answering = Promise.resolve();
|
|
172
176
|
constructor(house) {
|
|
173
177
|
this.house = house;
|
|
174
178
|
this.owner = {
|
|
@@ -200,39 +204,39 @@ export class LocalCopies {
|
|
|
200
204
|
}
|
|
201
205
|
}
|
|
202
206
|
async mapping() {
|
|
203
|
-
await this.
|
|
207
|
+
await this.answering;
|
|
204
208
|
return [...this.copies.values()]
|
|
205
209
|
.filter((copy) => copy.active)
|
|
206
210
|
.map((copy) => `${rootOf(copy.room_handle)}: ${copy.repository}`)
|
|
207
211
|
.sort();
|
|
208
212
|
}
|
|
209
|
-
async
|
|
210
|
-
const
|
|
211
|
-
if (
|
|
212
|
-
logged(
|
|
213
|
+
async connected() {
|
|
214
|
+
const copied = await this.answered(() => this.fetched(false));
|
|
215
|
+
if (copied.refused)
|
|
216
|
+
logged(copied.text);
|
|
213
217
|
}
|
|
214
218
|
fetch() {
|
|
215
|
-
return this.
|
|
219
|
+
return this.answered(() => this.fetched(true));
|
|
216
220
|
}
|
|
217
|
-
|
|
218
|
-
const
|
|
219
|
-
this.
|
|
220
|
-
return
|
|
221
|
+
answered(work) {
|
|
222
|
+
const answered = this.answering.then(work);
|
|
223
|
+
this.answering = answered.catch(() => undefined);
|
|
224
|
+
return answered;
|
|
221
225
|
}
|
|
222
226
|
async fetched(refreshing) {
|
|
223
|
-
const { local_copy:
|
|
224
|
-
const
|
|
225
|
-
return this.holding([...new Set([...this.copies.keys(), ...
|
|
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 () => {
|
|
226
230
|
const said = [];
|
|
227
231
|
let refused = false;
|
|
228
232
|
for (const copy of this.copies.values()) {
|
|
229
|
-
if (
|
|
233
|
+
if (synced.has(copy.key) || !copy.active)
|
|
230
234
|
continue;
|
|
231
235
|
await this.save({ ...copy, active: false });
|
|
232
236
|
said.push(`${rootOf(copy.room_handle)}: no longer synced to this Environment; its files stay`);
|
|
233
237
|
}
|
|
234
238
|
const current = [];
|
|
235
|
-
for (const [key, handle] of
|
|
239
|
+
for (const [key, handle] of synced) {
|
|
236
240
|
try {
|
|
237
241
|
const held = this.copies.get(key);
|
|
238
242
|
if (held === undefined || !(await exists(held.repository))) {
|
|
@@ -572,7 +576,13 @@ export class LocalCopies {
|
|
|
572
576
|
const after = await tree(copy.repository, commit);
|
|
573
577
|
const moved = movedPaths(copy.moves, before, after);
|
|
574
578
|
const arrived = new Set(moved.values());
|
|
575
|
-
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);
|
|
576
586
|
const changes = [];
|
|
577
587
|
for (const path of [...new Set([...before.keys(), ...after.keys()])].sort()) {
|
|
578
588
|
if (arrived.has(path))
|
|
@@ -585,7 +595,7 @@ export class LocalCopies {
|
|
|
585
595
|
changes.push({ op: 'rename', path: `${root}/${path}`, to: `${root}/${to}`, base: known });
|
|
586
596
|
const moving = after.get(to);
|
|
587
597
|
if (moving !== prior) {
|
|
588
|
-
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) });
|
|
589
599
|
}
|
|
590
600
|
continue;
|
|
591
601
|
}
|
|
@@ -594,9 +604,9 @@ export class LocalCopies {
|
|
|
594
604
|
if (next === undefined)
|
|
595
605
|
changes.push({ op: 'remove', path: `${root}/${path}`, base: known });
|
|
596
606
|
else if (prior === undefined)
|
|
597
|
-
changes.push({ op: 'create', path: `${root}/${path}`, content: await text(next
|
|
607
|
+
changes.push({ op: 'create', path: `${root}/${path}`, content: await text(next) });
|
|
598
608
|
else
|
|
599
|
-
changes.push(...changed(`${root}/${path}`, path, known, await text(prior
|
|
609
|
+
changes.push(...changed(`${root}/${path}`, path, known, await text(prior), await text(next)));
|
|
600
610
|
}
|
|
601
611
|
return changes;
|
|
602
612
|
}
|
|
@@ -623,7 +633,7 @@ export class LocalCopies {
|
|
|
623
633
|
const { upload, ...unstaged } = copy.push;
|
|
624
634
|
return this.settle(await this.save({ ...copy, push: unstaged }), caller, true);
|
|
625
635
|
}
|
|
626
|
-
if (outcome.refused.code === '
|
|
636
|
+
if (outcome.refused.code === 'expired')
|
|
627
637
|
return this.recovered(copy);
|
|
628
638
|
const rebased = rebaseFixes(outcome.refused);
|
|
629
639
|
let settled = await this.save(without(copy));
|
|
@@ -663,7 +673,7 @@ export class LocalCopies {
|
|
|
663
673
|
written.push({
|
|
664
674
|
path: `${root}/${path}`,
|
|
665
675
|
revision: entry === undefined ? null : (revisionAt(current, current.house, path) ?? null),
|
|
666
|
-
content: entry === undefined ? null : await blobText(copy.repository, entry
|
|
676
|
+
content: entry === undefined ? null : await blobText(copy.repository, entry),
|
|
667
677
|
});
|
|
668
678
|
}
|
|
669
679
|
return this.finished(await this.save({ ...current, push: { ...push, state: 'accepted', written } }));
|
|
@@ -707,7 +717,7 @@ export class LocalCopies {
|
|
|
707
717
|
{
|
|
708
718
|
path: `${rootOf(copy.room_handle)}/${path}`,
|
|
709
719
|
revision: entry === undefined ? null : (revisionAt(copy, copy.house, path) ?? null),
|
|
710
|
-
content: entry === undefined ? null : await blobText(copy.repository, entry
|
|
720
|
+
content: entry === undefined ? null : await blobText(copy.repository, entry),
|
|
711
721
|
},
|
|
712
722
|
];
|
|
713
723
|
}
|
|
@@ -752,7 +762,7 @@ export class LocalCopies {
|
|
|
752
762
|
async landed(repository, changes, house, selected) {
|
|
753
763
|
const text = async (path) => {
|
|
754
764
|
const entry = house.get(relative(path));
|
|
755
|
-
return entry === undefined ? undefined : blobText(repository, entry
|
|
765
|
+
return entry === undefined ? undefined : blobText(repository, entry);
|
|
756
766
|
};
|
|
757
767
|
for (const change of changes) {
|
|
758
768
|
const current = await text(change.path);
|
package/dist/end.js
CHANGED
|
@@ -1,8 +1,22 @@
|
|
|
1
|
+
import { forgetRejected } from './home.js';
|
|
2
|
+
import { installCommand } from './placement.js';
|
|
1
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
|
+
});
|
package/dist/events.js
CHANGED
|
@@ -512,6 +512,9 @@ class GrokReader extends Reader {
|
|
|
512
512
|
return [];
|
|
513
513
|
}
|
|
514
514
|
}
|
|
515
|
+
export function answeredFailure(answer) {
|
|
516
|
+
return answer._meta?.jetbrains?.air?.sessionFailure?.title ?? null;
|
|
517
|
+
}
|
|
515
518
|
export function readerFor(kind) {
|
|
516
519
|
if (kind === 'claude-agent-acp')
|
|
517
520
|
return new ClaudeReader();
|
package/dist/files.js
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
1
2
|
import { mkdir, writeFile } from 'node:fs/promises';
|
|
2
3
|
import { join } from 'node:path';
|
|
3
4
|
import { HouseRefusal, retrying } from './api.js';
|
|
4
5
|
import { relayed } from './relay.js';
|
|
6
|
+
export function verified(bytes, sha256, name) {
|
|
7
|
+
if (createHash('sha256').update(bytes).digest('hex') !== sha256)
|
|
8
|
+
throw new Error(`${name} did not arrive whole; download it again`);
|
|
9
|
+
return bytes;
|
|
10
|
+
}
|
|
5
11
|
export async function placeFiles(house, directory, files, signal) {
|
|
6
12
|
const paths = [];
|
|
7
13
|
for (const file of files) {
|
|
@@ -16,7 +22,7 @@ export async function placeFiles(house, directory, files, signal) {
|
|
|
16
22
|
});
|
|
17
23
|
await mkdir(folder, { recursive: true });
|
|
18
24
|
const path = join(folder, file.name);
|
|
19
|
-
await writeFile(path, Buffer.from(await answer.arrayBuffer()));
|
|
25
|
+
await writeFile(path, verified(Buffer.from(await answer.arrayBuffer()), file.sha256, file.name));
|
|
20
26
|
paths.push(path);
|
|
21
27
|
}
|
|
22
28
|
return paths;
|
package/dist/git.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
|
+
import { isUtf8 } from 'node:buffer';
|
|
2
3
|
import { createHash } from 'node:crypto';
|
|
3
4
|
import { join } from 'node:path';
|
|
4
5
|
import { withoutProxy } from './clis.js';
|
|
@@ -48,14 +49,16 @@ export async function tree(repository, commit) {
|
|
|
48
49
|
}
|
|
49
50
|
return entries;
|
|
50
51
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
52
|
+
const TEXT_MAX_BYTES = 16 * 1024 * 1024;
|
|
53
|
+
async function blob(repository, object) {
|
|
54
|
+
return (await run(repository, ['cat-file', 'blob', object])).stdout;
|
|
55
|
+
}
|
|
56
|
+
export async function blobText(repository, object) {
|
|
57
|
+
return (await blob(repository, object)).toString('utf8');
|
|
58
|
+
}
|
|
59
|
+
export async function isText(repository, object) {
|
|
60
|
+
const bytes = await blob(repository, object);
|
|
61
|
+
return bytes.length <= TEXT_MAX_BYTES && isUtf8(bytes) && !bytes.includes(0);
|
|
59
62
|
}
|
|
60
63
|
export function blobId(content) {
|
|
61
64
|
const bytes = Buffer.from(content, 'utf8');
|
package/dist/home.js
CHANGED
|
@@ -1,13 +1,49 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { accessSync, chmodSync, constants, existsSync, linkSync, lstatSync, mkdirSync, readFileSync, renameSync, rmSync } from 'node:fs';
|
|
2
3
|
import { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
|
|
3
|
-
import { homedir } from 'node:os';
|
|
4
|
+
import { homedir, tmpdir } from 'node:os';
|
|
4
5
|
import { join } from 'node:path';
|
|
6
|
+
import { selectRelay } from './relay.js';
|
|
5
7
|
const ENROLMENT = 'credential.json';
|
|
6
8
|
const DISCONNECTED = 'disconnected.json';
|
|
7
9
|
const CONFIGURATION = 'kit.json';
|
|
8
10
|
const OWN_AGENT = 'own-agent.json';
|
|
11
|
+
const RESTART = 'restart';
|
|
12
|
+
let defaulted;
|
|
13
|
+
function writable(directory) {
|
|
14
|
+
try {
|
|
15
|
+
accessSync(directory, constants.W_OK | constants.X_OK);
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function ownTemporaryHome() {
|
|
23
|
+
const home = join(tmpdir(), `house-kit-${process.getuid()}`);
|
|
24
|
+
try {
|
|
25
|
+
mkdirSync(home, { mode: 0o700 });
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
if (error.code !== 'EEXIST')
|
|
29
|
+
throw error;
|
|
30
|
+
}
|
|
31
|
+
const found = lstatSync(home);
|
|
32
|
+
if (found.isSymbolicLink())
|
|
33
|
+
throw new Error(`${home} is a symbolic link`);
|
|
34
|
+
if (!found.isDirectory())
|
|
35
|
+
throw new Error(`${home} is not a directory`);
|
|
36
|
+
if (found.uid !== process.getuid())
|
|
37
|
+
throw new Error(`${home} is not owned by this User`);
|
|
38
|
+
chmodSync(home, 0o700);
|
|
39
|
+
return home;
|
|
40
|
+
}
|
|
41
|
+
function defaultHome() {
|
|
42
|
+
const home = join(homedir(), '.house-kit');
|
|
43
|
+
return existsSync(home) || writable(homedir()) ? home : ownTemporaryHome();
|
|
44
|
+
}
|
|
9
45
|
export function kitHome() {
|
|
10
|
-
return process.env.HOUSE_KIT_HOME
|
|
46
|
+
return process.env.HOUSE_KIT_HOME || (defaulted ??= defaultHome());
|
|
11
47
|
}
|
|
12
48
|
export function workspaceRoot() {
|
|
13
49
|
return process.env.HOUSE_KIT_WORKSPACE ?? '/agents/house';
|
|
@@ -28,12 +64,15 @@ export async function readHome(name) {
|
|
|
28
64
|
export async function writeHome(name, value) {
|
|
29
65
|
const home = kitHome();
|
|
30
66
|
await mkdir(home, { recursive: true, mode: 0o700 });
|
|
31
|
-
const temporary = join(home, `${name}.${
|
|
67
|
+
const temporary = join(home, `${name}.${randomUUID()}`);
|
|
32
68
|
await writeFile(temporary, `${JSON.stringify(value)}\n`, { mode: 0o600 });
|
|
33
69
|
await rename(temporary, join(home, name));
|
|
34
70
|
}
|
|
35
|
-
export function readEnrolment() {
|
|
36
|
-
|
|
71
|
+
export async function readEnrolment() {
|
|
72
|
+
const enrolment = await readHome(ENROLMENT);
|
|
73
|
+
if (enrolment !== null)
|
|
74
|
+
selectRelay(process.env.HOUSE_KIT_RELAY || enrolment.relay);
|
|
75
|
+
return enrolment;
|
|
37
76
|
}
|
|
38
77
|
export async function writeEnrolment(enrolment) {
|
|
39
78
|
await writeHome(ENROLMENT, enrolment);
|
|
@@ -42,13 +81,49 @@ export async function writeEnrolment(enrolment) {
|
|
|
42
81
|
export function readDisconnected() {
|
|
43
82
|
return readHome(DISCONNECTED);
|
|
44
83
|
}
|
|
84
|
+
export function forgetDisconnected() {
|
|
85
|
+
return rm(join(kitHome(), DISCONNECTED), { force: true });
|
|
86
|
+
}
|
|
45
87
|
export async function forgetEnrolment({ house, environment }) {
|
|
46
88
|
await writeHome(DISCONNECTED, { house, environment });
|
|
47
89
|
await rm(join(kitHome(), ENROLMENT), { force: true });
|
|
48
90
|
}
|
|
91
|
+
export async function forgetRejected(rejected) {
|
|
92
|
+
const held = await readHome(ENROLMENT);
|
|
93
|
+
if (held?.credential !== rejected)
|
|
94
|
+
return;
|
|
95
|
+
await writeHome(DISCONNECTED, { house: held.house, environment: held.environment });
|
|
96
|
+
const enrolment = join(kitHome(), ENROLMENT);
|
|
97
|
+
const taken = `${enrolment}.${process.pid}`;
|
|
98
|
+
try {
|
|
99
|
+
renameSync(enrolment, taken);
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
if (error.code === 'ENOENT')
|
|
103
|
+
return;
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
106
|
+
if (JSON.parse(readFileSync(taken, 'utf8')).credential !== rejected) {
|
|
107
|
+
try {
|
|
108
|
+
linkSync(taken, enrolment);
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
if (error.code !== 'EEXIST')
|
|
112
|
+
throw error;
|
|
113
|
+
}
|
|
114
|
+
rmSync(join(kitHome(), DISCONNECTED), { force: true });
|
|
115
|
+
}
|
|
116
|
+
rmSync(taken);
|
|
117
|
+
}
|
|
49
118
|
export function enrolled() {
|
|
50
119
|
return existsSync(join(kitHome(), ENROLMENT));
|
|
51
120
|
}
|
|
121
|
+
export function restartAsked() {
|
|
122
|
+
return existsSync(join(kitHome(), RESTART));
|
|
123
|
+
}
|
|
124
|
+
export function forgetRestart() {
|
|
125
|
+
return rm(join(kitHome(), RESTART), { force: true });
|
|
126
|
+
}
|
|
52
127
|
export function readOwnAgent() {
|
|
53
128
|
return readHome(OWN_AGENT);
|
|
54
129
|
}
|