@agentshouse/kit 0.1.0-alpha.8 → 0.2.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.
Files changed (83) hide show
  1. package/README.md +14 -1740
  2. package/dist/api.js +11 -0
  3. package/dist/home.js +24 -0
  4. package/dist/house-main.js +4 -0
  5. package/dist/kit-main.js +16 -0
  6. package/dist/login.js +112 -0
  7. package/dist/resident.js +10 -0
  8. package/dist/stream.js +31 -0
  9. package/package.json +16 -11
  10. package/bin/connect-linux.sh +0 -134
  11. package/bin/kit.js +0 -1023
  12. package/bootstrap.json +0 -17
  13. package/src/acp.js +0 -99
  14. package/src/adapter-mcp.js +0 -44
  15. package/src/adapter.js +0 -252
  16. package/src/agent-logins.js +0 -65
  17. package/src/agents.js +0 -504
  18. package/src/apply.js +0 -29
  19. package/src/attach.js +0 -52
  20. package/src/binding.js +0 -90
  21. package/src/blocks.js +0 -156
  22. package/src/bridge.js +0 -449
  23. package/src/bytes.js +0 -89
  24. package/src/channel.js +0 -37
  25. package/src/command.js +0 -109
  26. package/src/configuration.js +0 -465
  27. package/src/connector-login.js +0 -91
  28. package/src/connector.js +0 -107
  29. package/src/continuation.js +0 -61
  30. package/src/contract.js +0 -363
  31. package/src/conversation-originals.js +0 -143
  32. package/src/custom/authorization.js +0 -63
  33. package/src/declaration.js +0 -35
  34. package/src/delivery.js +0 -191
  35. package/src/directory.js +0 -102
  36. package/src/draft.js +0 -89
  37. package/src/google/calendar.js +0 -177
  38. package/src/google/declared.js +0 -146
  39. package/src/google/drive.js +0 -435
  40. package/src/google/gateway.js +0 -166
  41. package/src/google/gmail.js +0 -249
  42. package/src/google/id.js +0 -1
  43. package/src/google/oauth.js +0 -273
  44. package/src/google/source.js +0 -25
  45. package/src/hook.js +0 -376
  46. package/src/host.js +0 -121
  47. package/src/house-main.js +0 -79
  48. package/src/house.js +0 -1090
  49. package/src/inbound.js +0 -175
  50. package/src/instance/google.js +0 -1
  51. package/src/kit-work-stream.js +0 -84
  52. package/src/launcher-main.js +0 -19
  53. package/src/launcher.js +0 -276
  54. package/src/local-files.js +0 -113
  55. package/src/login.js +0 -274
  56. package/src/mcp.js +0 -71
  57. package/src/migrator.js +0 -248
  58. package/src/mount.js +0 -582
  59. package/src/operation.js +0 -20
  60. package/src/original.js +0 -631
  61. package/src/peer.js +0 -124
  62. package/src/plan.js +0 -57
  63. package/src/question.js +0 -316
  64. package/src/refusal.js +0 -79
  65. package/src/repository.js +0 -521
  66. package/src/session-bin/house +0 -2
  67. package/src/settlement.js +0 -57
  68. package/src/setup.js +0 -190
  69. package/src/source-originals.js +0 -116
  70. package/src/source.js +0 -286
  71. package/src/starter-set/grilling/LICENSE +0 -21
  72. package/src/starter-set/grilling/SKILL.md +0 -30
  73. package/src/starter-set/grilling/agents/openai.yaml +0 -3
  74. package/src/starter-set.js +0 -17
  75. package/src/state.js +0 -157
  76. package/src/sync-library.js +0 -293
  77. package/src/sync-state.js +0 -120
  78. package/src/sync.js +0 -482
  79. package/src/telegram.js +0 -1045
  80. package/src/terminal.js +0 -57
  81. package/src/tmux.js +0 -119
  82. package/src/worker.js +0 -925
  83. package/src/workspace.js +0 -500
package/src/peer.js DELETED
@@ -1,124 +0,0 @@
1
- import { connect } from "node:net";
2
- import { setTimeout as delay } from "node:timers/promises";
3
- import { readFrames, writeFrame } from "./channel.js";
4
- import { BRIDGE_RECONNECT_MAX_MS, BRIDGE_RECONNECT_MS } from "./contract.js";
5
- import { KitRefusal } from "./refusal.js";
6
-
7
- function connected(path) {
8
- return new Promise((resolve, reject) => {
9
- const socket = connect(path);
10
- socket.once("connect", () => resolve(socket));
11
- socket.once("error", reject);
12
- });
13
- }
14
-
15
- export function bridgePeer(options) {
16
- const outbound = [];
17
- const drains = [];
18
- let socket = null;
19
- let ready = false;
20
- let ended = false;
21
- let greeting = null;
22
- let refuse;
23
- const refused = new Promise((_, reject) => {
24
- refuse = reject;
25
- });
26
-
27
- function flush() {
28
- while (ready && socket !== null && outbound.length > 0) {
29
- if (socket.destroyed || socket.writableEnded) {
30
- socket = null;
31
- return;
32
- }
33
- options.onSend?.(outbound[0]);
34
- writeFrame(socket, outbound[0]);
35
- outbound.shift();
36
- }
37
- if (outbound.length === 0) for (const settle of drains.splice(0)) settle();
38
- }
39
-
40
- function received(frame) {
41
- if (greeting === null) {
42
- options.onFrame?.(frame);
43
- return;
44
- }
45
- const settle = greeting;
46
- greeting = null;
47
- settle(frame);
48
- }
49
-
50
- async function attach(first) {
51
- let backoff = BRIDGE_RECONNECT_MS;
52
- const retry = async () => {
53
- if (first) throw new KitRefusal("kit_bridge_unavailable", options.socket);
54
- await delay(backoff);
55
- backoff = Math.min(backoff * 2, BRIDGE_RECONNECT_MAX_MS);
56
- };
57
- while (!ended) {
58
- let opened;
59
- try {
60
- opened = await connected(options.socket);
61
- } catch {
62
- await retry();
63
- continue;
64
- }
65
- socket = opened;
66
- ready = false;
67
- opened.on("error", () => opened.destroy());
68
- const answer = new Promise((resolve) => {
69
- greeting = resolve;
70
- });
71
- const departure = new Promise((resolve) => opened.once("close", () => resolve(null)));
72
- readFrames(opened, { onFrame: received, onRefusal: () => opened.destroy() });
73
- writeFrame(opened, {
74
- type: "hello",
75
- role: options.role,
76
- nonce: options.nonce,
77
- ...options.hello(),
78
- });
79
- const greeted = await Promise.race([answer, departure]);
80
- if (greeted === null) {
81
- greeting = null;
82
- socket = null;
83
- await retry();
84
- continue;
85
- }
86
- if (!options.greeted(greeted)) {
87
- ended = true;
88
- socket = null;
89
- opened.destroy();
90
- throw new KitRefusal("kit_bridge_refused", typeof greeted.code === "string" ? greeted.code : null);
91
- }
92
- ready = true;
93
- flush();
94
- void keep(opened).catch(refuse);
95
- return greeted;
96
- }
97
- return null;
98
- }
99
-
100
- async function keep(current) {
101
- if (!current.destroyed) await new Promise((resolve) => current.once("close", resolve));
102
- if (socket === current) socket = null;
103
- ready = false;
104
- if (ended) return;
105
- await attach(false);
106
- }
107
-
108
- return {
109
- refused,
110
- open: () => attach(options.retryInitial !== true),
111
- send(frame) {
112
- outbound.push(frame);
113
- flush();
114
- },
115
- drained: () => outbound.length === 0 ? Promise.resolve() : new Promise((resolve) => drains.push(resolve)),
116
- end() {
117
- ended = true;
118
- const current = socket;
119
- socket = null;
120
- if (current === null || current.destroyed || current.writableEnded) return Promise.resolve();
121
- return new Promise((resolve) => current.end(resolve));
122
- },
123
- };
124
- }
package/src/plan.js DELETED
@@ -1,57 +0,0 @@
1
- const PLAN_INTERVAL_MS = 500;
2
-
3
- function steps(entries) {
4
- if (!Array.isArray(entries) || entries.length === 0) return null;
5
- return entries.map((entry) => ({ label: entry.content, status: entry.status }));
6
- }
7
-
8
- export function observedPlans(options) {
9
- const intervalMs = options.intervalMs ?? PLAN_INTERVAL_MS;
10
- const now = options.now ?? (() => Date.now());
11
- let timer = null;
12
- let sentAt = null;
13
- let sent = null;
14
- let latest = null;
15
- let completed = false;
16
-
17
- function write(terminal) {
18
- if (latest === null) return;
19
- const serialized = JSON.stringify(latest);
20
- if (!terminal && serialized === sent) return;
21
- sent = serialized;
22
- sentAt = now();
23
- options.send({ steps: latest, terminal });
24
- }
25
-
26
- function cancel() {
27
- if (timer === null) return;
28
- clearTimeout(timer);
29
- timer = null;
30
- }
31
-
32
- return {
33
- observe(entries) {
34
- if (completed) return;
35
- const observed = steps(entries);
36
- if (observed === null) return;
37
- latest = observed;
38
- if (timer !== null) return;
39
- const wait = sentAt === null ? 0 : sentAt + intervalMs - now();
40
- if (wait <= 0) {
41
- write(false);
42
- return;
43
- }
44
- timer = setTimeout(() => {
45
- timer = null;
46
- write(false);
47
- }, wait);
48
- timer.unref?.();
49
- },
50
- complete() {
51
- if (completed) return;
52
- completed = true;
53
- cancel();
54
- write(true);
55
- },
56
- };
57
- }
package/src/question.js DELETED
@@ -1,316 +0,0 @@
1
- import {
2
- ELICITATION_FORM_MODE,
3
- ELICITATION_FREE_TEXT_META,
4
- ELICITATION_SECRET_META,
5
- ELICITATION_URL_MODE,
6
- SECRET_CEREMONY_STEPS_MAX,
7
- SECRET_STEP_LABEL_MAX,
8
- SECRET_STEP_TEXT_MAX,
9
- NATIVE_CODEX_META,
10
- NATIVE_CUSTOM_ANSWER_META,
11
- NATIVE_OTHER_OPTION,
12
- NATIVE_USER_NOTE_ROLE,
13
- INTERACTION_OPTIONS_MAX,
14
- INTERACTION_PROPERTY_MAX,
15
- } from "./contract.js";
16
-
17
- function declared(value) {
18
- return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
19
- }
20
-
21
- function withoutNativeMeta(value) {
22
- if (Array.isArray(value)) return value.map(withoutNativeMeta);
23
- const plain = declared(value);
24
- if (plain === null) return value;
25
- return Object.fromEntries(
26
- Object.entries(plain)
27
- .filter(([key]) => key !== "_meta")
28
- .map(([key, nested]) => [key, withoutNativeMeta(nested)]),
29
- );
30
- }
31
-
32
- function nativeCompanion(declaration) {
33
- const meta = declared(declaration?._meta);
34
- if (meta === null) return null;
35
- const custom = declared(meta[NATIVE_CUSTOM_ANSWER_META]);
36
- if (typeof custom?.questionId === "string") {
37
- return { question: custom.questionId, other: null };
38
- }
39
- const codex = declared(meta[NATIVE_CODEX_META]);
40
- if (codex?.role === NATIVE_USER_NOTE_ROLE && typeof codex.questionId === "string") {
41
- return { question: codex.questionId, other: NATIVE_OTHER_OPTION };
42
- }
43
- return null;
44
- }
45
-
46
- function nativeSecret(declaration) {
47
- return declared(declaration?._meta)?.[NATIVE_CODEX_META]?.isSecret === true;
48
- }
49
-
50
- function choiceHolder(declaration) {
51
- return declaration?.type === "array" ? declared(declaration.items) : declared(declaration);
52
- }
53
-
54
- function choiceValues(declaration) {
55
- const holder = choiceHolder(declaration);
56
- const titled = holder?.oneOf ?? holder?.anyOf;
57
- if (Array.isArray(titled)) {
58
- return titled.map((option) => option?.const).filter((value) => typeof value === "string");
59
- }
60
- if (Array.isArray(holder?.enum)) {
61
- return holder.enum.filter((value) => typeof value === "string");
62
- }
63
- return [];
64
- }
65
-
66
- function withoutChoice(holder, dropped) {
67
- if (Array.isArray(holder.oneOf)) {
68
- return { ...holder, oneOf: holder.oneOf.filter((option) => option?.const !== dropped) };
69
- }
70
- if (Array.isArray(holder.anyOf)) {
71
- return { ...holder, anyOf: holder.anyOf.filter((option) => option?.const !== dropped) };
72
- }
73
- if (Array.isArray(holder.enum)) {
74
- return { ...holder, enum: holder.enum.filter((value) => value !== dropped) };
75
- }
76
- return holder;
77
- }
78
-
79
- function withoutOtherChoice(declaration, dropped) {
80
- const holder = choiceHolder(declaration);
81
- if (dropped === null || holder === null) return declaration;
82
- if (declaration.type === "array") {
83
- return { ...declaration, items: withoutChoice(holder, dropped) };
84
- }
85
- return withoutChoice(holder, dropped);
86
- }
87
-
88
- function forwarded(declaration, name, marked) {
89
- const plain = declared(declaration);
90
- if (plain === null) return declaration;
91
- const titled =
92
- typeof plain.title === "string" && plain.title !== "" ? plain : { ...plain, title: name };
93
- return marked ? { ...titled, _meta: { [ELICITATION_FREE_TEXT_META]: true } } : titled;
94
- }
95
-
96
- function foldedConventions(properties) {
97
- const companions = new Map();
98
- const conventions = new Map();
99
- for (const [name, declaration] of Object.entries(properties)) {
100
- const companion = nativeCompanion(declaration);
101
- if (companion === null || !Object.hasOwn(properties, companion.question)) continue;
102
- companions.set(name, companion.question);
103
- conventions.set(companion.question, {
104
- companion: name,
105
- other: companion.other,
106
- options: choiceValues(withoutOtherChoice(properties[companion.question], companion.other)),
107
- });
108
- }
109
- return { companions, conventions };
110
- }
111
-
112
- function bounded(text, limit, fallback) {
113
- const said = typeof text === "string" ? text.trim() : "";
114
- return said === "" ? fallback : said.slice(0, limit);
115
- }
116
-
117
- const VISIT_LABEL = "Open the provider flow";
118
- const COLLECT_LABEL = "Paste what it gives you";
119
-
120
- export function elicitedVisit(params, correlation) {
121
- if (params?.mode !== ELICITATION_URL_MODE || typeof params.url !== "string") return null;
122
- let opened;
123
- try {
124
- opened = new URL(params.url);
125
- } catch {
126
- return null;
127
- }
128
- if (opened.protocol !== "https:") return null;
129
- return {
130
- form: {
131
- correlation: correlation.correlation,
132
- provider_turn: correlation.providerTurn,
133
- message: bounded(params.message, SECRET_STEP_TEXT_MAX, VISIT_LABEL),
134
- requested_schema: {
135
- type: "object",
136
- properties: {
137
- visited: { type: "boolean", title: bounded(params.message, 200, VISIT_LABEL) },
138
- },
139
- },
140
- _meta: { [ELICITATION_SECRET_META]: true },
141
- },
142
- ceremony: {
143
- steps: [
144
- {
145
- kind: "visit",
146
- label: bounded(params.message, SECRET_STEP_LABEL_MAX, VISIT_LABEL),
147
- url: params.url,
148
- },
149
- ],
150
- },
151
- convention: {},
152
- };
153
- }
154
-
155
- function secretCeremony(message, properties) {
156
- const steps = [];
157
- const shown = bounded(message, SECRET_STEP_TEXT_MAX, "");
158
- if (shown !== "") steps.push({ kind: "show", label: "What the Agent is asking", text: shown });
159
- for (const [name, declaration] of Object.entries(properties)) {
160
- if (steps.length >= SECRET_CEREMONY_STEPS_MAX) break;
161
- const property = declared(declaration);
162
- steps.push({
163
- kind: "collect",
164
- label: bounded(property?.title, SECRET_STEP_LABEL_MAX, COLLECT_LABEL),
165
- name,
166
- ...(typeof property?.description === "string" && property.description !== ""
167
- ? { description: property.description.slice(0, SECRET_STEP_TEXT_MAX) }
168
- : {}),
169
- });
170
- }
171
- return steps.length === 0 ? null : { steps };
172
- }
173
-
174
- export function elicitedForm(params, correlation) {
175
- if (params?.mode !== ELICITATION_FORM_MODE) return null;
176
- const schema = declared(params.requestedSchema);
177
- if (schema === null) return null;
178
- const properties = declared(schema.properties) ?? {};
179
- const { companions, conventions } = foldedConventions(properties);
180
- const carried = {};
181
- for (const [name, declaration] of Object.entries(properties)) {
182
- if (companions.has(name)) continue;
183
- const convention = conventions.get(name);
184
- const listed =
185
- convention === undefined ? declaration : withoutOtherChoice(declaration, convention.other);
186
- carried[name] = forwarded(withoutNativeMeta(listed), name, convention !== undefined);
187
- }
188
- const { _meta: _schemaMeta, properties: _properties, required, ...rest } = schema;
189
- const secret = Object.values(properties).some(nativeSecret);
190
- const ceremony = secret ? secretCeremony(params.message, carried) : null;
191
- if (secret && ceremony === null) return null;
192
- return {
193
- ...(ceremony === null ? {} : { ceremony }),
194
- form: {
195
- correlation: correlation.correlation,
196
- provider_turn: correlation.providerTurn,
197
- message: typeof params.message === "string" ? params.message : "",
198
- requested_schema: {
199
- ...withoutNativeMeta(rest),
200
- properties: carried,
201
- ...(Array.isArray(required)
202
- ? { required: required.filter((name) => !companions.has(name)) }
203
- : {}),
204
- },
205
- ...(secret ? { _meta: { [ELICITATION_SECRET_META]: true } } : {}),
206
- },
207
- convention: Object.fromEntries(conventions),
208
- };
209
- }
210
-
211
- function nativeAnswer(content, name, convention, value) {
212
- if (Array.isArray(value)) {
213
- content[name] = value.filter((item) => convention.options.includes(item));
214
- const typed = value.filter((item) => !convention.options.includes(item));
215
- if (typed.length > 0) content[convention.companion] = typed.join(", ");
216
- return;
217
- }
218
- if (typeof value !== "string" || convention.options.includes(value)) {
219
- content[name] = value;
220
- return;
221
- }
222
- content[convention.companion] = value;
223
- if (convention.other !== null) content[name] = convention.other;
224
- }
225
-
226
- export function elicitationResponse(convention, response) {
227
- if (response?.action !== "accept") return { action: "decline" };
228
- const content = {};
229
- for (const [name, value] of Object.entries(response.content)) {
230
- const native = convention[name];
231
- if (native === undefined) content[name] = value;
232
- else nativeAnswer(content, name, native, value);
233
- }
234
- return { action: "accept", content };
235
- }
236
-
237
- function grokOption(option) {
238
- if (typeof option?.label !== "string" || option.label.length === 0) return null;
239
- return {
240
- const: option.label,
241
- title: option.label,
242
- ...(typeof option.description === "string" && option.description.length > 0
243
- ? { description: option.description }
244
- : {}),
245
- };
246
- }
247
-
248
- export function grokForm(params, correlation) {
249
- if (params?.mode !== "default" && params?.mode !== "plan") return null;
250
- if (
251
- !Array.isArray(params.questions) ||
252
- params.questions.length === 0 ||
253
- params.questions.length > INTERACTION_PROPERTY_MAX
254
- ) {
255
- return null;
256
- }
257
- const properties = {};
258
- const questions = {};
259
- const named = new Set();
260
- for (const [position, question] of params.questions.entries()) {
261
- if (
262
- typeof question?.question !== "string" ||
263
- question.question.length === 0 ||
264
- named.has(question.question) ||
265
- !Array.isArray(question.options) ||
266
- question.options.length > INTERACTION_OPTIONS_MAX
267
- ) {
268
- return null;
269
- }
270
- const options = question.options.map(grokOption);
271
- if (options.some((option) => option === null)) return null;
272
- const labels = options.map((option) => option.const);
273
- if (new Set(labels).size !== labels.length) return null;
274
- const name = `question_${position}`;
275
- const choices = options.length === 0 ? {} : { oneOf: options };
276
- properties[name] =
277
- question.multiSelect === true
278
- ? {
279
- type: "array",
280
- title: question.question,
281
- items: { type: "string", ...choices },
282
- uniqueItems: true,
283
- }
284
- : { type: "string", title: question.question, ...choices };
285
- questions[name] = question.question;
286
- named.add(question.question);
287
- }
288
- return {
289
- form: {
290
- correlation: correlation.correlation,
291
- provider_turn: correlation.providerTurn,
292
- message: `Grok Build needs your input before it continues${params.mode === "plan" ? " its plan" : ""}.`,
293
- requested_schema: {
294
- type: "object",
295
- properties,
296
- required: Object.keys(properties),
297
- },
298
- },
299
- convention: questions,
300
- };
301
- }
302
-
303
- export function grokResponse(convention, response) {
304
- if (response?.action !== "accept") return { outcome: "cancelled" };
305
- const answers = {};
306
- for (const [name, question] of Object.entries(convention)) {
307
- const value = response.content?.[name];
308
- if (typeof value === "string") answers[question] = [value];
309
- else if (Array.isArray(value) && value.every((item) => typeof item === "string")) {
310
- answers[question] = value;
311
- } else {
312
- return { outcome: "cancelled" };
313
- }
314
- }
315
- return { outcome: "accepted", answers };
316
- }
package/src/refusal.js DELETED
@@ -1,79 +0,0 @@
1
- export class KitRefusal extends Error {
2
- constructor(code, detail = null) {
3
- super(detail === null ? code : `${code}: ${detail}`);
4
- this.code = code;
5
- }
6
- }
7
-
8
- export class EpochReportRequired extends Error {
9
- constructor(epoch) {
10
- super(`epoch_report_required: ${epoch}`);
11
- this.code = "epoch_report_required";
12
- }
13
- }
14
-
15
- export class HousePending extends Error {
16
- constructor(pending) {
17
- super("pending");
18
- this.pending = pending;
19
- this.retryAfterSeconds = pending.retry_after;
20
- }
21
- }
22
-
23
- function typedCode(answer) {
24
- const code = answer?.error?.code;
25
- return typeof code === "string" && code !== "" ? code : null;
26
- }
27
-
28
- export function houseRefusal(status, answer, path = null) {
29
- const code = typedCode(answer);
30
- if (status >= 500 && code === null) return new KitRefusal("kit_house_unavailable", path);
31
- if (status === 409 && code === "epoch_report_required") {
32
- return new EpochReportRequired(answer.error.log_epoch);
33
- }
34
- const refusal = new KitRefusal(code ?? `house_http_${status}`, answer?.error?.declaration ?? null);
35
- refusal.status = status;
36
- refusal.payload = answer;
37
- return refusal;
38
- }
39
-
40
- export function housePending(answer) {
41
- const pending = answer?.pending;
42
- if (typeof pending !== "object" || pending === null || Array.isArray(pending)) return null;
43
- if (!Number.isSafeInteger(pending.retry_after) || pending.retry_after < 1) return null;
44
- return new HousePending(pending);
45
- }
46
-
47
- export function throwHouseAnswer(status, answer, path = null) {
48
- if (status === 202) {
49
- const pending = housePending(answer);
50
- if (pending !== null) throw pending;
51
- throw new KitRefusal("kit_house_unavailable", path);
52
- }
53
- if (status < 200 || status >= 300) throw houseRefusal(status, answer, path);
54
- }
55
-
56
- export function houseAnswered(error) {
57
- return error instanceof KitRefusal && error.status !== undefined;
58
- }
59
-
60
- export function houseAnsweredFailure(error) {
61
- return houseAnswered(error) && error.status >= 500;
62
- }
63
-
64
- export function houseFailed(error) {
65
- return (
66
- error instanceof HousePending ||
67
- (houseAnsweredFailure(error) && error.payload.error.retryable === true) ||
68
- (error instanceof KitRefusal && error.code === "kit_house_unavailable")
69
- );
70
- }
71
-
72
- export function formatCommandError(error) {
73
- if (!(error instanceof Error)) return "kit_command_failed";
74
- if (error instanceof HousePending) return JSON.stringify({ pending: error.pending });
75
- if (error instanceof KitRefusal && error.payload !== undefined) {
76
- return `${error.message}\n${JSON.stringify(error.payload)}`;
77
- }
78
- return error.message;
79
- }