office-core 0.1.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/.runtime-dist/scripts/bundle-host-package.js +46 -0
- package/.runtime-dist/scripts/demo-multi-agent.js +130 -0
- package/.runtime-dist/scripts/home-agent-host.js +1403 -0
- package/.runtime-dist/scripts/host-doctor.js +28 -0
- package/.runtime-dist/scripts/host-login.js +32 -0
- package/.runtime-dist/scripts/host-menu.js +227 -0
- package/.runtime-dist/scripts/host-open.js +20 -0
- package/.runtime-dist/scripts/install-host.js +108 -0
- package/.runtime-dist/scripts/lib/host-config.js +171 -0
- package/.runtime-dist/scripts/lib/local-runner.js +287 -0
- package/.runtime-dist/scripts/office-cli.js +698 -0
- package/.runtime-dist/scripts/run-local-project.js +277 -0
- package/.runtime-dist/src/auth/session-token.js +62 -0
- package/.runtime-dist/src/discord/outbox-ledger.js +56 -0
- package/.runtime-dist/src/do/AgentDO.js +205 -0
- package/.runtime-dist/src/do/GatewayShardDO.js +9 -0
- package/.runtime-dist/src/do/ProjectDO.js +829 -0
- package/.runtime-dist/src/do/TaskDO.js +356 -0
- package/.runtime-dist/src/index.js +123 -0
- package/.runtime-dist/src/project/office-view.js +405 -0
- package/.runtime-dist/src/project/read-model.js +79 -0
- package/.runtime-dist/src/routes/agents-bootstrap.js +9 -0
- package/.runtime-dist/src/routes/agents-descriptor.js +12 -0
- package/.runtime-dist/src/routes/agents-events.js +17 -0
- package/.runtime-dist/src/routes/agents-heartbeat.js +21 -0
- package/.runtime-dist/src/routes/agents-task-context.js +17 -0
- package/.runtime-dist/src/routes/bundles.js +198 -0
- package/.runtime-dist/src/routes/local-host.js +49 -0
- package/.runtime-dist/src/routes/projects.js +119 -0
- package/.runtime-dist/src/routes/tasks.js +67 -0
- package/.runtime-dist/src/task/reducer.js +464 -0
- package/.runtime-dist/src/types/project.js +1 -0
- package/.runtime-dist/src/types/protocol.js +3 -0
- package/.runtime-dist/src/types/runtime.js +1 -0
- package/README.md +148 -0
- package/bin/double-penetration-host.mjs +83 -0
- package/package.json +48 -0
- package/public/index.html +1581 -0
- package/public/install-host.ps1 +64 -0
- package/scripts/run-runtime-script.mjs +43 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { copyFile, mkdir, rm } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
import { spawnSync } from "node:child_process";
|
|
5
|
+
void main().catch((error) => {
|
|
6
|
+
console.error(error);
|
|
7
|
+
process.exitCode = 1;
|
|
8
|
+
});
|
|
9
|
+
async function main() {
|
|
10
|
+
const rootDir = process.cwd();
|
|
11
|
+
const result = process.platform === "win32"
|
|
12
|
+
? spawnSync("cmd.exe", ["/d", "/s", "/c", "npm pack --json"], {
|
|
13
|
+
cwd: rootDir,
|
|
14
|
+
encoding: "utf8",
|
|
15
|
+
windowsHide: true,
|
|
16
|
+
})
|
|
17
|
+
: spawnSync("npm", ["pack", "--json"], {
|
|
18
|
+
cwd: rootDir,
|
|
19
|
+
encoding: "utf8",
|
|
20
|
+
windowsHide: true,
|
|
21
|
+
});
|
|
22
|
+
if (result.status !== 0) {
|
|
23
|
+
throw new Error(`npm pack failed\n${result.stdout}\n${result.stderr}`.trim());
|
|
24
|
+
}
|
|
25
|
+
const pack = JSON.parse(String(result.stdout).trim())?.[0];
|
|
26
|
+
if (!pack?.filename) {
|
|
27
|
+
throw new Error("npm pack did not return a filename");
|
|
28
|
+
}
|
|
29
|
+
const sourceTarball = path.join(rootDir, pack.filename);
|
|
30
|
+
const downloadsDir = path.join(rootDir, "public", "downloads");
|
|
31
|
+
await mkdir(downloadsDir, { recursive: true });
|
|
32
|
+
const versionedTarget = path.join(downloadsDir, pack.filename);
|
|
33
|
+
const stableTargets = [
|
|
34
|
+
path.join(downloadsDir, "office-core.tgz"),
|
|
35
|
+
path.join(downloadsDir, "office-host.tgz"),
|
|
36
|
+
path.join(downloadsDir, "dp-host.tgz"),
|
|
37
|
+
path.join(downloadsDir, "double-penetration-host.tgz"),
|
|
38
|
+
];
|
|
39
|
+
await copyFile(sourceTarball, versionedTarget);
|
|
40
|
+
for (const stableTarget of stableTargets) {
|
|
41
|
+
await copyFile(sourceTarball, stableTarget);
|
|
42
|
+
}
|
|
43
|
+
await rm(sourceTarball, { force: true });
|
|
44
|
+
console.log(`Host package bundled: ${stableTargets[0]}`);
|
|
45
|
+
console.log(`Versioned package: ${versionedTarget}`);
|
|
46
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
const baseUrl = process.env.OFFICE_BASE_URL ?? "http://127.0.0.1:8787";
|
|
2
|
+
async function main() {
|
|
3
|
+
console.log(`Using Office Core at ${baseUrl}`);
|
|
4
|
+
const createdTask = await postJson(`${baseUrl}/api/tasks`, {
|
|
5
|
+
project_id: "prj_demo",
|
|
6
|
+
discord_event_id: `discord:${Date.now()}`,
|
|
7
|
+
channel_id: "discord-project-channel",
|
|
8
|
+
title: "Multi-agent office smoke test",
|
|
9
|
+
raw_content: "Stand up two agents, align, claim, and report progress.",
|
|
10
|
+
requested_by_discord_user_id: "human_demo",
|
|
11
|
+
});
|
|
12
|
+
console.log("Created task:", createdTask);
|
|
13
|
+
const agentA = await bootstrapAgent("agent_alpha", createdTask.task_id);
|
|
14
|
+
const agentB = await bootstrapAgent("agent_bravo", createdTask.task_id);
|
|
15
|
+
console.log("Bootstrapped agents:", {
|
|
16
|
+
alpha: agentA.fence,
|
|
17
|
+
bravo: agentB.fence,
|
|
18
|
+
});
|
|
19
|
+
const manifest = await getJson(`${baseUrl}${agentA.descriptor.manifest_fetch_url}`, agentA.session_token);
|
|
20
|
+
console.log("Fetched manifest:", manifest.manifest_id, manifest.blobs?.length ?? 0);
|
|
21
|
+
await sendAgentCommand(agentA.session_token, {
|
|
22
|
+
...commandBase("cmd_alpha_status", "agent_alpha", createdTask.task_id),
|
|
23
|
+
type: "status.upsert",
|
|
24
|
+
payload: { task_summary: "Reading project brief", state: "active" },
|
|
25
|
+
});
|
|
26
|
+
await sendAgentCommand(agentA.session_token, {
|
|
27
|
+
...commandBase("cmd_alpha_understanding", "agent_alpha", createdTask.task_id),
|
|
28
|
+
type: "understanding.submit",
|
|
29
|
+
payload: { text: "Need a shared task map and one executor", confidence: "high" },
|
|
30
|
+
});
|
|
31
|
+
await sendAgentCommand(agentB.session_token, {
|
|
32
|
+
...commandBase("cmd_bravo_status", "agent_bravo", createdTask.task_id),
|
|
33
|
+
type: "status.upsert",
|
|
34
|
+
payload: { task_summary: "Checking agent flow", state: "active" },
|
|
35
|
+
});
|
|
36
|
+
await sendAgentCommand(agentB.session_token, {
|
|
37
|
+
...commandBase("cmd_bravo_understanding", "agent_bravo", createdTask.task_id),
|
|
38
|
+
type: "understanding.submit",
|
|
39
|
+
payload: { text: "Need one alignment message then execution", confidence: "medium" },
|
|
40
|
+
});
|
|
41
|
+
await postJson(`${baseUrl}/api/tasks/${createdTask.task_id}/human-confirm`, {
|
|
42
|
+
actor_id: "human_demo",
|
|
43
|
+
type: "accept",
|
|
44
|
+
});
|
|
45
|
+
const claim = await sendAgentCommand(agentA.session_token, {
|
|
46
|
+
...commandBase("cmd_alpha_claim", "agent_alpha", createdTask.task_id, 2),
|
|
47
|
+
type: "execution.claim",
|
|
48
|
+
payload: { scope: "full", approach_summary: "Take the first implementation pass." },
|
|
49
|
+
});
|
|
50
|
+
const claimToken = claim.results?.[0]?.claim_token?.claim_token;
|
|
51
|
+
if (!claimToken) {
|
|
52
|
+
throw new Error(`Claim failed: ${JSON.stringify(claim)}`);
|
|
53
|
+
}
|
|
54
|
+
await sendAgentCommand(agentA.session_token, {
|
|
55
|
+
...commandBase("cmd_alpha_progress", "agent_alpha", createdTask.task_id, 3),
|
|
56
|
+
type: "progress.update",
|
|
57
|
+
claim_token: claimToken,
|
|
58
|
+
payload: { summary: "Prototype path is running with two agents.", percent_complete: 35 },
|
|
59
|
+
});
|
|
60
|
+
const task = await getJson(`${baseUrl}/api/tasks/${createdTask.task_id}`);
|
|
61
|
+
const project = await getJson(`${baseUrl}/api/projects/prj_demo`);
|
|
62
|
+
const status = await getJson(`${baseUrl}/api/projects/prj_demo/status`);
|
|
63
|
+
console.log("\nTask snapshot:");
|
|
64
|
+
console.dir(task, { depth: null });
|
|
65
|
+
console.log("\nProject summary:");
|
|
66
|
+
console.dir(project, { depth: null });
|
|
67
|
+
console.log("\nStatus feed:");
|
|
68
|
+
console.dir(status, { depth: null });
|
|
69
|
+
}
|
|
70
|
+
function commandBase(commandId, agentId, taskId, observedTaskVersion = 1) {
|
|
71
|
+
return {
|
|
72
|
+
protocol_version: "1.0",
|
|
73
|
+
command_schema_version: 1,
|
|
74
|
+
command_id: commandId,
|
|
75
|
+
session_id: "placeholder",
|
|
76
|
+
session_epoch: 1,
|
|
77
|
+
agent_id: agentId,
|
|
78
|
+
task_id: taskId,
|
|
79
|
+
observed_task_version: observedTaskVersion,
|
|
80
|
+
bundle_seq: 1,
|
|
81
|
+
sent_at: new Date().toISOString(),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
async function bootstrapAgent(agentId, taskId) {
|
|
85
|
+
return postJson(`${baseUrl}/api/agents/bootstrap`, {
|
|
86
|
+
agent_id: agentId,
|
|
87
|
+
display_name: agentId,
|
|
88
|
+
workspace_id: "ws_demo",
|
|
89
|
+
active_project_id: "prj_demo",
|
|
90
|
+
active_task_id: taskId,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
async function sendAgentCommand(token, command) {
|
|
94
|
+
const claims = parseSessionToken(token);
|
|
95
|
+
if (!claims) {
|
|
96
|
+
throw new Error("Invalid session token returned by bootstrap");
|
|
97
|
+
}
|
|
98
|
+
const body = structuredClone(command);
|
|
99
|
+
body.session_id = claims.session_id;
|
|
100
|
+
body.session_epoch = claims.session_epoch;
|
|
101
|
+
return postJson(`${baseUrl}/api/agents/events`, { commands: [body] }, token);
|
|
102
|
+
}
|
|
103
|
+
async function getJson(url, token) {
|
|
104
|
+
const response = await fetch(url, {
|
|
105
|
+
headers: token ? { authorization: `Bearer ${token}` } : {},
|
|
106
|
+
});
|
|
107
|
+
if (!response.ok) {
|
|
108
|
+
throw new Error(`GET ${url} failed: ${response.status} ${await response.text()}`);
|
|
109
|
+
}
|
|
110
|
+
return response.json();
|
|
111
|
+
}
|
|
112
|
+
async function postJson(url, body, token) {
|
|
113
|
+
const response = await fetch(url, {
|
|
114
|
+
method: "POST",
|
|
115
|
+
headers: {
|
|
116
|
+
"content-type": "application/json",
|
|
117
|
+
...(token ? { authorization: `Bearer ${token}` } : {}),
|
|
118
|
+
},
|
|
119
|
+
body: JSON.stringify(body),
|
|
120
|
+
});
|
|
121
|
+
if (!response.ok) {
|
|
122
|
+
throw new Error(`POST ${url} failed: ${response.status} ${await response.text()}`);
|
|
123
|
+
}
|
|
124
|
+
return response.json();
|
|
125
|
+
}
|
|
126
|
+
void main().catch((error) => {
|
|
127
|
+
console.error(error);
|
|
128
|
+
process.exitCode = 1;
|
|
129
|
+
});
|
|
130
|
+
import { parseSessionToken } from "../src/auth/session-token.js";
|