@agentshouse/kit 0.0.1 → 0.1.0-alpha.1
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/LICENSE +21 -0
- package/README.md +1696 -2
- package/bin/connect-linux.sh +127 -0
- package/bin/kit.js +1023 -0
- package/package.json +33 -3
- package/src/acp.js +99 -0
- package/src/adapter-mcp.js +44 -0
- package/src/adapter.js +252 -0
- package/src/agent-logins.js +65 -0
- package/src/agents.js +449 -0
- package/src/apply.js +29 -0
- package/src/attach.js +52 -0
- package/src/binding.js +90 -0
- package/src/blocks.js +156 -0
- package/src/bridge.js +449 -0
- package/src/bytes.js +89 -0
- package/src/channel.js +37 -0
- package/src/command.js +109 -0
- package/src/configuration.js +465 -0
- package/src/connector-login.js +91 -0
- package/src/connector.js +107 -0
- package/src/continuation.js +61 -0
- package/src/contract.js +363 -0
- package/src/conversation-originals.js +143 -0
- package/src/custom/authorization.js +63 -0
- package/src/declaration.js +35 -0
- package/src/delivery.js +191 -0
- package/src/directory.js +102 -0
- package/src/draft.js +89 -0
- package/src/google/calendar.js +177 -0
- package/src/google/declared.js +146 -0
- package/src/google/drive.js +435 -0
- package/src/google/gateway.js +166 -0
- package/src/google/gmail.js +249 -0
- package/src/google/id.js +1 -0
- package/src/google/oauth.js +273 -0
- package/src/google/source.js +25 -0
- package/src/hook.js +376 -0
- package/src/host.js +121 -0
- package/src/house-main.js +79 -0
- package/src/house.js +1085 -0
- package/src/inbound.js +175 -0
- package/src/instance/google.js +1 -0
- package/src/launcher-main.js +19 -0
- package/src/launcher.js +276 -0
- package/src/local-files.js +113 -0
- package/src/login.js +274 -0
- package/src/mcp.js +71 -0
- package/src/migrator.js +248 -0
- package/src/mount.js +582 -0
- package/src/operation.js +20 -0
- package/src/original.js +631 -0
- package/src/peer.js +124 -0
- package/src/plan.js +57 -0
- package/src/question.js +316 -0
- package/src/refusal.js +79 -0
- package/src/repository.js +521 -0
- package/src/session-bin/house +2 -0
- package/src/settlement.js +57 -0
- package/src/setup.js +185 -0
- package/src/source-originals.js +116 -0
- package/src/source.js +286 -0
- package/src/starter-set/grilling/LICENSE +21 -0
- package/src/starter-set/grilling/SKILL.md +30 -0
- package/src/starter-set/grilling/agents/openai.yaml +3 -0
- package/src/starter-set.js +17 -0
- package/src/state.js +157 -0
- package/src/sync-library.js +293 -0
- package/src/sync-state.js +116 -0
- package/src/sync.js +477 -0
- package/src/telegram.js +1045 -0
- package/src/terminal.js +57 -0
- package/src/tmux.js +119 -0
- package/src/worker.js +756 -0
- package/src/workspace.js +500 -0
package/src/terminal.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EXECUTION_FAILURE_CAUSE_MAX,
|
|
3
|
+
EXECUTION_OUTCOMES,
|
|
4
|
+
PROVIDER_CAPACITY_EXHAUSTED,
|
|
5
|
+
PROVIDER_CONTINUATION_UNAVAILABLE,
|
|
6
|
+
PROVIDER_REFUSED,
|
|
7
|
+
} from "./contract.js";
|
|
8
|
+
|
|
9
|
+
export function reportedCause(failure) {
|
|
10
|
+
const named =
|
|
11
|
+
failure.detail === null || failure.detail === undefined
|
|
12
|
+
? failure.code
|
|
13
|
+
: `${failure.code}: ${failure.detail}`;
|
|
14
|
+
return named.slice(0, EXECUTION_FAILURE_CAUSE_MAX);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function failedReport(failure) {
|
|
18
|
+
return { outcome: "failed", cause: reportedCause(failure) };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function terminalReport(observed) {
|
|
22
|
+
if (observed.capacityExhausted) {
|
|
23
|
+
return { outcome: "failed", cause: PROVIDER_CAPACITY_EXHAUSTED };
|
|
24
|
+
}
|
|
25
|
+
if (observed.providerRefused) {
|
|
26
|
+
return { outcome: "failed", cause: PROVIDER_REFUSED };
|
|
27
|
+
}
|
|
28
|
+
if (observed.failure !== null && observed.failure !== undefined) {
|
|
29
|
+
return failedReport(observed.failure);
|
|
30
|
+
}
|
|
31
|
+
if (observed.turnCompleted && !observed.conversation) return { outcome: "completed", cause: null };
|
|
32
|
+
if (observed.continuable) return null;
|
|
33
|
+
return { outcome: "failed", cause: PROVIDER_CONTINUATION_UNAVAILABLE };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function reportedNote(reported) {
|
|
37
|
+
return { operation: reported.operation, outcome: reported.outcome, cause: reported.cause };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function retainedReport(stored) {
|
|
41
|
+
if (stored === null || stored === undefined) return null;
|
|
42
|
+
if (typeof stored !== "object" || Array.isArray(stored)) return undefined;
|
|
43
|
+
if (typeof stored.operation !== "string" || stored.operation.length === 0) return undefined;
|
|
44
|
+
if (!EXECUTION_OUTCOMES.includes(stored.outcome)) return undefined;
|
|
45
|
+
if (stored.outcome === "completed") {
|
|
46
|
+
if (stored.cause !== null) return undefined;
|
|
47
|
+
return { operation: stored.operation, outcome: stored.outcome, cause: null };
|
|
48
|
+
}
|
|
49
|
+
if (
|
|
50
|
+
typeof stored.cause !== "string" ||
|
|
51
|
+
stored.cause.length === 0 ||
|
|
52
|
+
stored.cause.length > EXECUTION_FAILURE_CAUSE_MAX
|
|
53
|
+
) {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
return { operation: stored.operation, outcome: stored.outcome, cause: stored.cause };
|
|
57
|
+
}
|
package/src/tmux.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
2
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { runCommand, withoutHouseCredentials } from "./command.js";
|
|
5
|
+
import { TMUX_COMMAND_TIMEOUT_MS, TMUX_SUPPORTED_MINIMUM } from "./contract.js";
|
|
6
|
+
import { KitRefusal } from "./refusal.js";
|
|
7
|
+
|
|
8
|
+
const VERSION_LINE = /^tmux (?:next-)?(\d+)\.(\d+)/;
|
|
9
|
+
const SESSION_NAME = /^[a-f0-9]{16}$/;
|
|
10
|
+
|
|
11
|
+
const PREREQUISITE =
|
|
12
|
+
`the Environment owner must install tmux ${TMUX_SUPPORTED_MINIMUM} or newer and make it reachable on PATH; ` +
|
|
13
|
+
"House Kit never installs, upgrades, or replaces tmux";
|
|
14
|
+
|
|
15
|
+
function parsedVersion(line) {
|
|
16
|
+
const found = VERSION_LINE.exec(line.trim());
|
|
17
|
+
return found === null ? null : [Number(found[1]), Number(found[2])];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const REQUIRED_VERSION = parsedVersion(`tmux ${TMUX_SUPPORTED_MINIMUM}`);
|
|
21
|
+
|
|
22
|
+
const NAMESPACE_CONFIGURATION = "set-option -g -w remain-on-exit off\n";
|
|
23
|
+
|
|
24
|
+
export function tmuxNamespace(directory) {
|
|
25
|
+
return `house-kit-${createHash("sha256").update(directory).digest("hex").slice(0, 16)}`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function workerRuntime(directory, tmux) {
|
|
29
|
+
return {
|
|
30
|
+
tmux,
|
|
31
|
+
namespace: tmuxNamespace(directory),
|
|
32
|
+
configuration: join(directory, "tmux", "namespace.conf"),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function workerSessionName() {
|
|
37
|
+
return randomBytes(8).toString("hex");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function namespaced(runtime, args) {
|
|
41
|
+
return runCommand({
|
|
42
|
+
command: [runtime.tmux, "-L", runtime.namespace, "-f", runtime.configuration, ...args],
|
|
43
|
+
environment: {},
|
|
44
|
+
stdin: "",
|
|
45
|
+
timeoutMs: TMUX_COMMAND_TIMEOUT_MS,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export async function readyTmux(runtime) {
|
|
50
|
+
let reported;
|
|
51
|
+
try {
|
|
52
|
+
reported = await runCommand({
|
|
53
|
+
command: [runtime.tmux, "-V"],
|
|
54
|
+
environment: {},
|
|
55
|
+
stdin: "",
|
|
56
|
+
timeoutMs: TMUX_COMMAND_TIMEOUT_MS,
|
|
57
|
+
});
|
|
58
|
+
} catch (refusal) {
|
|
59
|
+
if (refusal instanceof KitRefusal && refusal.code === "kit_command_unavailable") {
|
|
60
|
+
throw new KitRefusal("kit_tmux_unavailable", PREREQUISITE);
|
|
61
|
+
}
|
|
62
|
+
throw refusal;
|
|
63
|
+
}
|
|
64
|
+
if (reported.status !== 0) throw new KitRefusal("kit_tmux_unavailable", PREREQUISITE);
|
|
65
|
+
const found = parsedVersion(reported.stdout);
|
|
66
|
+
if (found === null) {
|
|
67
|
+
throw new KitRefusal(
|
|
68
|
+
"kit_tmux_unsupported",
|
|
69
|
+
`this Environment reports "${reported.stdout.trim()}"; ${PREREQUISITE}`,
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
if (found[0] < REQUIRED_VERSION[0] || (found[0] === REQUIRED_VERSION[0] && found[1] < REQUIRED_VERSION[1])) {
|
|
73
|
+
throw new KitRefusal(
|
|
74
|
+
"kit_tmux_unsupported",
|
|
75
|
+
`this Environment has tmux ${found[0]}.${found[1]}; ${PREREQUISITE}`,
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
await mkdir(join(runtime.configuration, ".."), { recursive: true, mode: 0o700 });
|
|
79
|
+
await writeFile(runtime.configuration, NAMESPACE_CONFIGURATION, { mode: 0o600 });
|
|
80
|
+
return `${found[0]}.${found[1]}`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export async function createSession(runtime, options) {
|
|
84
|
+
if (!SESSION_NAME.test(options.session)) {
|
|
85
|
+
throw new KitRefusal("kit_tmux_session_invalid", options.session);
|
|
86
|
+
}
|
|
87
|
+
const environment = Object.entries(withoutHouseCredentials(options.environment)).flatMap(
|
|
88
|
+
([name, value]) => ["-e", `${name}=${value}`],
|
|
89
|
+
);
|
|
90
|
+
const created = await namespaced(runtime, [
|
|
91
|
+
"new-session",
|
|
92
|
+
"-d",
|
|
93
|
+
"-s",
|
|
94
|
+
options.session,
|
|
95
|
+
"-c",
|
|
96
|
+
options.workingDirectory,
|
|
97
|
+
...environment,
|
|
98
|
+
"--",
|
|
99
|
+
...options.command,
|
|
100
|
+
]);
|
|
101
|
+
if (created.status !== 0) {
|
|
102
|
+
throw new KitRefusal("kit_tmux_session_refused", created.stderr.trim() || null);
|
|
103
|
+
}
|
|
104
|
+
return options.session;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export async function sessionPresent(runtime, session) {
|
|
108
|
+
const asked = await namespaced(runtime, ["has-session", "-t", `=${session}`]);
|
|
109
|
+
return asked.status === 0;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export async function destroySession(runtime, session) {
|
|
113
|
+
const killed = await namespaced(runtime, ["kill-session", "-t", `=${session}`]);
|
|
114
|
+
if (killed.status === 0) return true;
|
|
115
|
+
if (await sessionPresent(runtime, session)) {
|
|
116
|
+
throw new KitRefusal("kit_tmux_session_persistent", session);
|
|
117
|
+
}
|
|
118
|
+
return false;
|
|
119
|
+
}
|