@codegrammer/co-od 0.1.3 → 0.1.4
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/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.js +168 -0
- package/dist/index.js +7 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function run(args: string[]): Promise<void>;
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import * as api from "../api-client.js";
|
|
2
|
+
import { getAdapter } from "../adapters/index.js";
|
|
3
|
+
import { writeFileSync, mkdirSync, existsSync } from "node:fs";
|
|
4
|
+
import { join, basename } from "node:path";
|
|
5
|
+
import { homedir } from "node:os";
|
|
6
|
+
function parseArgs(args) {
|
|
7
|
+
const parsed = {
|
|
8
|
+
dir: process.cwd(),
|
|
9
|
+
provider: "claude",
|
|
10
|
+
};
|
|
11
|
+
for (let i = 0; i < args.length; i++) {
|
|
12
|
+
if (args[i] === "--dir" && args[i + 1]) {
|
|
13
|
+
parsed.dir = args[++i];
|
|
14
|
+
}
|
|
15
|
+
else if (args[i] === "--name" && args[i + 1]) {
|
|
16
|
+
parsed.name = args[++i];
|
|
17
|
+
}
|
|
18
|
+
else if (args[i] === "--provider" && args[i + 1]) {
|
|
19
|
+
parsed.provider = args[++i];
|
|
20
|
+
}
|
|
21
|
+
else if (args[i] === "--server" && args[i + 1]) {
|
|
22
|
+
parsed.server = args[++i];
|
|
23
|
+
}
|
|
24
|
+
else if (!args[i].startsWith("--") && !parsed.name) {
|
|
25
|
+
parsed.name = args[i];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return parsed;
|
|
29
|
+
}
|
|
30
|
+
function timestamp() {
|
|
31
|
+
return new Date().toISOString().slice(11, 19);
|
|
32
|
+
}
|
|
33
|
+
export async function run(args) {
|
|
34
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
35
|
+
console.error(`Usage: co-od init [name] [--dir <path>] [--provider claude|codex|openclaw]
|
|
36
|
+
|
|
37
|
+
Sets up a new co-ode project:
|
|
38
|
+
1. Creates a room on co-od.dev
|
|
39
|
+
2. Links it to your local project directory
|
|
40
|
+
3. Adds a default agent
|
|
41
|
+
4. Generates a .co-od config file
|
|
42
|
+
5. Ready to go — start giving tasks
|
|
43
|
+
|
|
44
|
+
Examples:
|
|
45
|
+
co-od init # Uses current dir name as room name
|
|
46
|
+
co-od init "my-saas-app" # Custom room name
|
|
47
|
+
co-od init --provider codex # Use Codex as default agent
|
|
48
|
+
co-od init --dir ~/projects/app # Different directory
|
|
49
|
+
`);
|
|
50
|
+
process.exit(0);
|
|
51
|
+
}
|
|
52
|
+
const parsed = parseArgs(args);
|
|
53
|
+
if (parsed.server) {
|
|
54
|
+
process.env.CO_ODE_SERVER = parsed.server;
|
|
55
|
+
}
|
|
56
|
+
// Ensure logged in
|
|
57
|
+
const token = api.getSessionToken();
|
|
58
|
+
if (!token) {
|
|
59
|
+
console.error(`[${timestamp()}] Not logged in. Run: co-od login`);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
const projectDir = parsed.dir;
|
|
63
|
+
const roomName = parsed.name || basename(projectDir);
|
|
64
|
+
console.error(`\n co-od init\n`);
|
|
65
|
+
console.error(` project: ${projectDir}`);
|
|
66
|
+
console.error(` room: ${roomName}`);
|
|
67
|
+
console.error(` provider: ${parsed.provider}\n`);
|
|
68
|
+
// Step 1: Check provider is available
|
|
69
|
+
console.error(` [1/5] Checking ${parsed.provider} CLI...`);
|
|
70
|
+
const adapter = getAdapter(parsed.provider);
|
|
71
|
+
const available = await adapter.available();
|
|
72
|
+
if (!available) {
|
|
73
|
+
console.error(` ✗ ${adapter.name} not found on PATH`);
|
|
74
|
+
console.error(` Install it first, then run co-od init again.`);
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
console.error(` ✓ ${adapter.name} available`);
|
|
78
|
+
// Step 2: Create room
|
|
79
|
+
console.error(` [2/5] Creating room "${roomName}"...`);
|
|
80
|
+
let roomId;
|
|
81
|
+
try {
|
|
82
|
+
const res = await api.post("/api/rooms", { name: roomName });
|
|
83
|
+
roomId = res.roomId || res.room?._id || "";
|
|
84
|
+
if (!roomId)
|
|
85
|
+
throw new Error("No room ID returned");
|
|
86
|
+
console.error(` ✓ Room created: ${roomId.slice(0, 12)}...`);
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
console.error(` ✗ Failed to create room: ${err}`);
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
// Step 3: Add default agent
|
|
93
|
+
console.error(` [3/5] Adding default agent...`);
|
|
94
|
+
let agentId;
|
|
95
|
+
try {
|
|
96
|
+
const agentName = parsed.provider === "codex" ? "Codex Builder"
|
|
97
|
+
: parsed.provider === "openclaw" ? "OpenClaw Agent"
|
|
98
|
+
: "Claude Builder";
|
|
99
|
+
const res = await api.post(`/api/rooms/${roomId}/agents`, {
|
|
100
|
+
name: agentName,
|
|
101
|
+
type: "builder",
|
|
102
|
+
executionMode: parsed.provider === "codex" ? "local_codex" : "local_claude_code",
|
|
103
|
+
provider: parsed.provider === "codex" ? "openai"
|
|
104
|
+
: parsed.provider === "openclaw" ? "openclaw"
|
|
105
|
+
: "anthropic",
|
|
106
|
+
permissions: {
|
|
107
|
+
"fs.read": true,
|
|
108
|
+
"fs.write": true,
|
|
109
|
+
"fs.applyPatch": true,
|
|
110
|
+
"exec.run": true,
|
|
111
|
+
"net.egress": false,
|
|
112
|
+
"ports.expose": false,
|
|
113
|
+
"secrets.read": false,
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
agentId = res.agentId || "";
|
|
117
|
+
console.error(` ✓ Agent "${agentName}" added`);
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
console.error(` ✗ Failed to add agent: ${err}`);
|
|
121
|
+
agentId = "";
|
|
122
|
+
}
|
|
123
|
+
// Step 4: Save config
|
|
124
|
+
console.error(` [4/5] Saving config...`);
|
|
125
|
+
const config = {
|
|
126
|
+
roomId,
|
|
127
|
+
roomName,
|
|
128
|
+
projectDir,
|
|
129
|
+
provider: parsed.provider,
|
|
130
|
+
agentId,
|
|
131
|
+
server: api.getBaseUrl(),
|
|
132
|
+
createdAt: new Date().toISOString(),
|
|
133
|
+
};
|
|
134
|
+
// Save to project dir
|
|
135
|
+
const configPath = join(projectDir, ".co-od.json");
|
|
136
|
+
try {
|
|
137
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
138
|
+
console.error(` ✓ ${configPath}`);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
console.error(` ✗ Could not write ${configPath}`);
|
|
142
|
+
}
|
|
143
|
+
// Also save room mapping to global config
|
|
144
|
+
const globalConfigDir = join(homedir(), ".co-od");
|
|
145
|
+
const roomsMapPath = join(globalConfigDir, "rooms.json");
|
|
146
|
+
try {
|
|
147
|
+
mkdirSync(globalConfigDir, { recursive: true });
|
|
148
|
+
let rooms = {};
|
|
149
|
+
if (existsSync(roomsMapPath)) {
|
|
150
|
+
rooms = JSON.parse(require("node:fs").readFileSync(roomsMapPath, "utf-8"));
|
|
151
|
+
}
|
|
152
|
+
rooms[roomId] = { roomId, projectDir, name: roomName };
|
|
153
|
+
writeFileSync(roomsMapPath, JSON.stringify(rooms, null, 2) + "\n", "utf-8");
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
// Non-fatal
|
|
157
|
+
}
|
|
158
|
+
// Step 5: Done
|
|
159
|
+
console.error(` [5/5] Ready!\n`);
|
|
160
|
+
console.error(` Your room is live. Next steps:\n`);
|
|
161
|
+
console.error(` co-od run ${roomId.slice(0, 12)} "describe your task" # run a single task`);
|
|
162
|
+
console.error(` co-od daemon ${roomId.slice(0, 12)} --auto-execute # autonomous mode`);
|
|
163
|
+
console.error(` co-od share # invite teammates\n`);
|
|
164
|
+
console.error(` Or open in browser:`);
|
|
165
|
+
console.error(` ${api.getBaseUrl()}/rooms/${roomId}\n`);
|
|
166
|
+
// Output JSON for scripting
|
|
167
|
+
console.log(JSON.stringify(config, null, 2));
|
|
168
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
const VERSION = "0.1.0";
|
|
4
4
|
const COMMANDS = {
|
|
5
|
+
init: { desc: "Set up a new co-ode project", usage: "co-od init [name] [--dir <path>] [--provider claude|codex|openclaw]" },
|
|
5
6
|
login: { desc: "Authenticate with co-ode", usage: "co-od login [--token <t>]" },
|
|
6
7
|
rooms: { desc: "List your rooms", usage: "co-od rooms [--json]" },
|
|
7
8
|
run: { desc: "Execute a single task in a room", usage: "co-od run <room> <goal> [--provider claude|codex|openclaw] [--dir <path>] [--json]" },
|
|
8
9
|
join: { desc: "Join a room as an interactive agent", usage: "co-od join <room> [--invite-token <tok>] [--dir <path>]" },
|
|
9
|
-
daemon: { desc: "Autonomous watch mode for a room", usage: "co-od daemon <room> [--as <name>] [--auto-execute] [--
|
|
10
|
+
daemon: { desc: "Autonomous watch mode for a room", usage: "co-od daemon <room> [--as <name>] [--auto-execute] [--handoff-to <agent>]" },
|
|
10
11
|
share: { desc: "Generate a relay code for teammates", usage: "co-od share [--provider claude|codex|openclaw]" },
|
|
11
12
|
connect: { desc: "Connect to a relay via code", usage: "co-od connect <code>" },
|
|
12
13
|
status: { desc: "Show current login and running state", usage: "co-od status [--json]" },
|
|
@@ -58,6 +59,11 @@ async function main() {
|
|
|
58
59
|
}
|
|
59
60
|
// Route to command
|
|
60
61
|
switch (command) {
|
|
62
|
+
case "init": {
|
|
63
|
+
const { run } = await import("./commands/init.js");
|
|
64
|
+
await run(commandArgs);
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
61
67
|
case "login": {
|
|
62
68
|
const { run } = await import("./commands/login.js");
|
|
63
69
|
await run(commandArgs);
|