grokbox 0.0.1 → 0.1.0-alpha.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.
- package/LICENSE +21 -0
- package/README.md +214 -16
- package/THIRD_PARTY_NOTICES +29 -0
- package/bin/grokbox +13 -0
- package/bin/runtime.d.ts +13 -0
- package/bin/runtime.js +27 -0
- package/dist/index.js +14104 -0
- package/package.json +43 -10
- package/skills/core.md +90 -44
- package/bin/grok-bot +0 -2
- package/src/commands/agents.ts +0 -110
- package/src/commands/doctor.ts +0 -50
- package/src/commands/events.ts +0 -123
- package/src/commands/history.ts +0 -65
- package/src/commands/is.ts +0 -23
- package/src/commands/memory.ts +0 -47
- package/src/commands/roster.ts +0 -11
- package/src/commands/send.ts +0 -72
- package/src/deps.ts +0 -49
- package/src/errors.ts +0 -132
- package/src/gateway.ts +0 -421
- package/src/index.ts +0 -6
- package/src/opts.ts +0 -52
- package/src/output.ts +0 -58
- package/src/program.ts +0 -213
- package/src/redaction.ts +0 -130
- package/src/registry.ts +0 -202
- package/src/skills.ts +0 -55
- package/src/util.ts +0 -59
package/src/commands/memory.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import type { CliDeps } from "../deps.ts";
|
|
2
|
-
import { usage } from "../errors.ts";
|
|
3
|
-
import { GatewayClient, gatewayMeta } from "../gateway.ts";
|
|
4
|
-
import { writeSuccess } from "../output.ts";
|
|
5
|
-
import { ioFromOpts } from "../opts.ts";
|
|
6
|
-
import { projectMemory } from "../redaction.ts";
|
|
7
|
-
import { MEMORY_UPSTREAM_CAP } from "../registry.ts";
|
|
8
|
-
import { parseInteger } from "../util.ts";
|
|
9
|
-
|
|
10
|
-
export async function runMemoryList(
|
|
11
|
-
deps: CliDeps,
|
|
12
|
-
raw: {
|
|
13
|
-
json?: boolean;
|
|
14
|
-
table?: boolean;
|
|
15
|
-
timeoutMs?: string;
|
|
16
|
-
agent?: string;
|
|
17
|
-
limit?: string;
|
|
18
|
-
content?: boolean;
|
|
19
|
-
},
|
|
20
|
-
): Promise<void> {
|
|
21
|
-
const io = ioFromOpts(raw);
|
|
22
|
-
const includeContent = Boolean(raw.content);
|
|
23
|
-
if (io.table) throw usage("memory list does not support --table.");
|
|
24
|
-
const agentId = raw.agent;
|
|
25
|
-
if (!agentId) throw usage("--agent is required.");
|
|
26
|
-
const limit = parseInteger(raw.limit, {
|
|
27
|
-
name: "--limit",
|
|
28
|
-
min: 1,
|
|
29
|
-
max: MEMORY_UPSTREAM_CAP,
|
|
30
|
-
defaultValue: 100,
|
|
31
|
-
});
|
|
32
|
-
const client = new GatewayClient(deps);
|
|
33
|
-
const { result, discovery } = await client.getAgentMemories(agentId, io.timeoutMs);
|
|
34
|
-
const source = Array.isArray(result) ? result : [];
|
|
35
|
-
const sliced = source.slice(0, limit);
|
|
36
|
-
writeSuccess(
|
|
37
|
-
deps.stdout,
|
|
38
|
-
{
|
|
39
|
-
agentId,
|
|
40
|
-
returned: sliced.length,
|
|
41
|
-
sourceCount: source.length,
|
|
42
|
-
sourceMayBeTruncated: source.length === MEMORY_UPSTREAM_CAP,
|
|
43
|
-
memories: sliced.map((row) => projectMemory(row, includeContent)),
|
|
44
|
-
},
|
|
45
|
-
gatewayMeta(discovery),
|
|
46
|
-
);
|
|
47
|
-
}
|
package/src/commands/roster.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { CliError, usage } from "../errors.ts";
|
|
2
|
-
import { isRecord } from "../util.ts";
|
|
3
|
-
|
|
4
|
-
export function findRosterRow(agents: unknown[], id: string): Record<string, unknown> {
|
|
5
|
-
if (id.length === 0) throw usage("Agent id is required.");
|
|
6
|
-
const row = agents.find((item): item is Record<string, unknown> => isRecord(item) && item.id === id);
|
|
7
|
-
if (!row) {
|
|
8
|
-
throw new CliError("target_not_found", "No roster row matched that id.");
|
|
9
|
-
}
|
|
10
|
-
return row;
|
|
11
|
-
}
|
package/src/commands/send.ts
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import type { CliDeps } from "../deps.ts";
|
|
2
|
-
import { CliError, usage } from "../errors.ts";
|
|
3
|
-
import { GatewayClient, gatewayMeta } from "../gateway.ts";
|
|
4
|
-
import { writeSuccess } from "../output.ts";
|
|
5
|
-
import { ioFromOpts, readPrompt } from "../opts.ts";
|
|
6
|
-
import { agentKind } from "../redaction.ts";
|
|
7
|
-
import { assertUuidV4, isRecord } from "../util.ts";
|
|
8
|
-
import { findRosterRow } from "./roster.ts";
|
|
9
|
-
|
|
10
|
-
export async function runSend(
|
|
11
|
-
deps: CliDeps,
|
|
12
|
-
raw: {
|
|
13
|
-
json?: boolean;
|
|
14
|
-
table?: boolean;
|
|
15
|
-
timeoutMs?: string;
|
|
16
|
-
agent?: string;
|
|
17
|
-
group?: string;
|
|
18
|
-
text?: string;
|
|
19
|
-
nonce?: string;
|
|
20
|
-
},
|
|
21
|
-
): Promise<void> {
|
|
22
|
-
const io = ioFromOpts(raw);
|
|
23
|
-
if (io.table) throw usage("This command does not support --table.");
|
|
24
|
-
const agentId = raw.agent;
|
|
25
|
-
const groupId = raw.group;
|
|
26
|
-
if ((agentId === undefined) === (groupId === undefined)) {
|
|
27
|
-
throw usage("Provide exactly one of --agent or --group.");
|
|
28
|
-
}
|
|
29
|
-
const wantedKind = agentId !== undefined ? "agent" : "group";
|
|
30
|
-
const targetId = (agentId ?? groupId) as string;
|
|
31
|
-
const prompt = await readPrompt(raw.text, deps);
|
|
32
|
-
const clientNonce = raw.nonce === undefined ? deps.randomUUID() : assertUuidV4(raw.nonce, "--nonce");
|
|
33
|
-
const client = new GatewayClient(deps);
|
|
34
|
-
const { agents } = await client.listAgents(io.timeoutMs);
|
|
35
|
-
const row = findRosterRow(agents, targetId);
|
|
36
|
-
const actualKind = agentKind(row);
|
|
37
|
-
if (actualKind !== wantedKind) {
|
|
38
|
-
throw new CliError(
|
|
39
|
-
"target_kind_mismatch",
|
|
40
|
-
wantedKind === "agent"
|
|
41
|
-
? "--agent matched a group id."
|
|
42
|
-
: "--group matched a non-group agent id.",
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
try {
|
|
46
|
-
const { result, discovery } = await client.sendPrompt(
|
|
47
|
-
{ agentId: String(row.id), prompt, clientNonce },
|
|
48
|
-
io.timeoutMs,
|
|
49
|
-
);
|
|
50
|
-
const accepted = !isRecord(result) || result.accepted !== false;
|
|
51
|
-
if (!accepted) {
|
|
52
|
-
throw new CliError("gateway_internal", "Gateway did not accept the send.");
|
|
53
|
-
}
|
|
54
|
-
writeSuccess(
|
|
55
|
-
deps.stdout,
|
|
56
|
-
{
|
|
57
|
-
status: "accepted",
|
|
58
|
-
accepted: true,
|
|
59
|
-
target: { id: String(row.id), kind: actualKind },
|
|
60
|
-
clientNonce,
|
|
61
|
-
},
|
|
62
|
-
gatewayMeta(discovery),
|
|
63
|
-
);
|
|
64
|
-
} catch (error) {
|
|
65
|
-
if (error instanceof CliError && error.code === "send_delivery_unknown") {
|
|
66
|
-
throw new CliError("send_delivery_unknown", error.message, {
|
|
67
|
-
context: { clientNonce, target: { id: String(row.id), kind: actualKind } },
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
throw error;
|
|
71
|
-
}
|
|
72
|
-
}
|
package/src/deps.ts
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { join } from "node:path";
|
|
2
|
-
import cliPackage from "../package.json" with { type: "json" };
|
|
3
|
-
import { DEFAULT_DISCOVERY_PATH } from "./registry.ts";
|
|
4
|
-
import type { Writable } from "./output.ts";
|
|
5
|
-
|
|
6
|
-
export type FetchFn = typeof fetch;
|
|
7
|
-
|
|
8
|
-
export type CliDeps = {
|
|
9
|
-
discoveryPath: string;
|
|
10
|
-
fetch: FetchFn;
|
|
11
|
-
now: () => number;
|
|
12
|
-
randomUUID: () => string;
|
|
13
|
-
readFile: (path: string) => Promise<string>;
|
|
14
|
-
stdout: Writable;
|
|
15
|
-
stderr: Writable;
|
|
16
|
-
stdinIsTTY: boolean;
|
|
17
|
-
readStdin: () => Promise<string>;
|
|
18
|
-
skillsDir: string;
|
|
19
|
-
cliVersion: string;
|
|
20
|
-
idleWatchdogMs: number;
|
|
21
|
-
signal?: AbortSignal;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export const CLI_VERSION: string = cliPackage.version;
|
|
25
|
-
|
|
26
|
-
export function createProductionDeps(): CliDeps {
|
|
27
|
-
return {
|
|
28
|
-
discoveryPath: DEFAULT_DISCOVERY_PATH,
|
|
29
|
-
fetch: globalThis.fetch.bind(globalThis),
|
|
30
|
-
now: () => Date.now(),
|
|
31
|
-
randomUUID: () => crypto.randomUUID(),
|
|
32
|
-
readFile: async (path) => await Bun.file(path).text(),
|
|
33
|
-
stdout: {
|
|
34
|
-
write(chunk) {
|
|
35
|
-
process.stdout.write(chunk);
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
stderr: {
|
|
39
|
-
write(chunk) {
|
|
40
|
-
process.stderr.write(chunk);
|
|
41
|
-
},
|
|
42
|
-
},
|
|
43
|
-
stdinIsTTY: Boolean(process.stdin.isTTY),
|
|
44
|
-
readStdin: async () => await Bun.stdin.text(),
|
|
45
|
-
skillsDir: join(import.meta.dir, "..", "skills"),
|
|
46
|
-
cliVersion: CLI_VERSION,
|
|
47
|
-
idleWatchdogMs: 45_000,
|
|
48
|
-
};
|
|
49
|
-
}
|
package/src/errors.ts
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
export const EXIT_CODES = {
|
|
2
|
-
ok: 0,
|
|
3
|
-
invalid_usage: 2,
|
|
4
|
-
discovery_unavailable: 3,
|
|
5
|
-
gateway_unreachable: 4,
|
|
6
|
-
gateway_bad_request: 10,
|
|
7
|
-
gateway_unauthorized: 11,
|
|
8
|
-
gateway_forbidden: 12,
|
|
9
|
-
gateway_not_found: 13,
|
|
10
|
-
gateway_conflict: 14,
|
|
11
|
-
gateway_internal: 15,
|
|
12
|
-
send_delivery_unknown: 16,
|
|
13
|
-
target_not_found: 17,
|
|
14
|
-
target_kind_mismatch: 18,
|
|
15
|
-
} as const;
|
|
16
|
-
|
|
17
|
-
export type ErrorCode = Exclude<keyof typeof EXIT_CODES, "ok">;
|
|
18
|
-
|
|
19
|
-
export type ErrorBody = {
|
|
20
|
-
code: ErrorCode;
|
|
21
|
-
message: string;
|
|
22
|
-
httpStatus?: number;
|
|
23
|
-
failureCode?: string;
|
|
24
|
-
retryable: boolean;
|
|
25
|
-
context?: {
|
|
26
|
-
clientNonce: string;
|
|
27
|
-
target: { id: string; kind: "agent" | "group" };
|
|
28
|
-
};
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
const RETRYABLE: Record<ErrorCode, boolean> = {
|
|
32
|
-
invalid_usage: false,
|
|
33
|
-
discovery_unavailable: false,
|
|
34
|
-
gateway_unreachable: true,
|
|
35
|
-
gateway_bad_request: false,
|
|
36
|
-
gateway_unauthorized: false,
|
|
37
|
-
gateway_forbidden: false,
|
|
38
|
-
gateway_not_found: false,
|
|
39
|
-
gateway_conflict: false,
|
|
40
|
-
gateway_internal: true,
|
|
41
|
-
send_delivery_unknown: false,
|
|
42
|
-
target_not_found: false,
|
|
43
|
-
target_kind_mismatch: false,
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
export class CliError extends Error {
|
|
47
|
-
readonly code: ErrorCode;
|
|
48
|
-
readonly httpStatus?: number;
|
|
49
|
-
readonly failureCode?: string;
|
|
50
|
-
readonly retryable: boolean;
|
|
51
|
-
readonly context?: ErrorBody["context"];
|
|
52
|
-
|
|
53
|
-
constructor(
|
|
54
|
-
code: ErrorCode,
|
|
55
|
-
message: string,
|
|
56
|
-
extras: {
|
|
57
|
-
httpStatus?: number;
|
|
58
|
-
failureCode?: string;
|
|
59
|
-
retryable?: boolean;
|
|
60
|
-
context?: ErrorBody["context"];
|
|
61
|
-
} = {},
|
|
62
|
-
) {
|
|
63
|
-
super(message);
|
|
64
|
-
this.name = "CliError";
|
|
65
|
-
this.code = code;
|
|
66
|
-
this.httpStatus = extras.httpStatus;
|
|
67
|
-
this.failureCode = extras.failureCode;
|
|
68
|
-
this.retryable = extras.retryable ?? RETRYABLE[code];
|
|
69
|
-
this.context = extras.context;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
get exitCode(): number {
|
|
73
|
-
return EXIT_CODES[this.code];
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
toErrorBody(): ErrorBody {
|
|
77
|
-
const body: ErrorBody = {
|
|
78
|
-
code: this.code,
|
|
79
|
-
message: this.message,
|
|
80
|
-
retryable: this.retryable,
|
|
81
|
-
};
|
|
82
|
-
if (this.httpStatus !== undefined) body.httpStatus = this.httpStatus;
|
|
83
|
-
if (this.failureCode !== undefined) body.failureCode = this.failureCode;
|
|
84
|
-
if (this.context !== undefined) body.context = this.context;
|
|
85
|
-
return body;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export function usage(message: string): CliError {
|
|
90
|
-
return new CliError("invalid_usage", message);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export function httpStatusToError(
|
|
94
|
-
status: number,
|
|
95
|
-
failureCode: string | undefined,
|
|
96
|
-
fallbackMessage: string,
|
|
97
|
-
): CliError {
|
|
98
|
-
if (status === 400) {
|
|
99
|
-
return new CliError("gateway_bad_request", "Gateway rejected the request body.", {
|
|
100
|
-
httpStatus: 400,
|
|
101
|
-
failureCode,
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
if (status === 401) {
|
|
105
|
-
return new CliError("gateway_unauthorized", "Gateway rejected the credentials.", {
|
|
106
|
-
httpStatus: 401,
|
|
107
|
-
failureCode,
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
if (status === 403) {
|
|
111
|
-
return new CliError("gateway_forbidden", "Gateway forbade the request.", {
|
|
112
|
-
httpStatus: 403,
|
|
113
|
-
failureCode,
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
if (status === 404) {
|
|
117
|
-
return new CliError("gateway_not_found", "Gateway method or path was not found.", {
|
|
118
|
-
httpStatus: 404,
|
|
119
|
-
failureCode,
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
if (status === 409) {
|
|
123
|
-
return new CliError("gateway_conflict", "Gateway rejected the request.", {
|
|
124
|
-
httpStatus: 409,
|
|
125
|
-
failureCode,
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
return new CliError("gateway_internal", fallbackMessage, {
|
|
129
|
-
httpStatus: status,
|
|
130
|
-
failureCode,
|
|
131
|
-
});
|
|
132
|
-
}
|