codiedev 0.2.1 → 0.3.2
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/cli.d.ts +16 -0
- package/dist/cli.js +111 -0
- package/dist/commands/inbox.d.ts +2 -0
- package/dist/commands/inbox.js +106 -0
- package/dist/commands/note.d.ts +1 -0
- package/dist/commands/note.js +28 -0
- package/dist/commands/ping.d.ts +1 -0
- package/dist/commands/ping.js +55 -0
- package/dist/commands/promote.d.ts +1 -0
- package/dist/commands/promote.js +41 -0
- package/dist/commands/pull.d.ts +1 -0
- package/dist/commands/pull.js +106 -0
- package/dist/commands/push.d.ts +1 -0
- package/dist/commands/push.js +104 -0
- package/dist/commands/shared.d.ts +24 -0
- package/dist/commands/shared.js +143 -0
- package/dist/connect.d.ts +1 -2
- package/dist/connect.js +4 -8
- package/dist/mcp.d.ts +12 -0
- package/dist/mcp.js +425 -0
- package/dist/utils.d.ts +12 -0
- package/dist/utils.js +62 -0
- package/package.json +12 -6
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CodieDev CLI dispatcher.
|
|
4
|
+
*
|
|
5
|
+
* Subcommands:
|
|
6
|
+
* codiedev connect — link agent CLIs to your org
|
|
7
|
+
* codiedev push <file> — author/update a spec/review/decision/etc.
|
|
8
|
+
* codiedev pull <key> — fetch an artifact by filename key
|
|
9
|
+
* codiedev ping <user> "<msg>" — send a message (optionally --with <key>)
|
|
10
|
+
* codiedev inbox — list pings (use --unread to filter)
|
|
11
|
+
* codiedev read <ping-id> — mark read + show full message
|
|
12
|
+
* codiedev note "<text>" — capture a thought
|
|
13
|
+
* codiedev promote <artifact-id> — promote an extracted artifact to authored
|
|
14
|
+
* codiedev help — show this help
|
|
15
|
+
*/
|
|
16
|
+
export {};
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* CodieDev CLI dispatcher.
|
|
5
|
+
*
|
|
6
|
+
* Subcommands:
|
|
7
|
+
* codiedev connect — link agent CLIs to your org
|
|
8
|
+
* codiedev push <file> — author/update a spec/review/decision/etc.
|
|
9
|
+
* codiedev pull <key> — fetch an artifact by filename key
|
|
10
|
+
* codiedev ping <user> "<msg>" — send a message (optionally --with <key>)
|
|
11
|
+
* codiedev inbox — list pings (use --unread to filter)
|
|
12
|
+
* codiedev read <ping-id> — mark read + show full message
|
|
13
|
+
* codiedev note "<text>" — capture a thought
|
|
14
|
+
* codiedev promote <artifact-id> — promote an extracted artifact to authored
|
|
15
|
+
* codiedev help — show this help
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
const connect_1 = require("./connect");
|
|
19
|
+
const push_1 = require("./commands/push");
|
|
20
|
+
const pull_1 = require("./commands/pull");
|
|
21
|
+
const ping_1 = require("./commands/ping");
|
|
22
|
+
const inbox_1 = require("./commands/inbox");
|
|
23
|
+
const note_1 = require("./commands/note");
|
|
24
|
+
const promote_1 = require("./commands/promote");
|
|
25
|
+
const HELP = `
|
|
26
|
+
CodieDev CLI
|
|
27
|
+
|
|
28
|
+
Connect:
|
|
29
|
+
codiedev connect Link Claude Code / Codex to your org
|
|
30
|
+
|
|
31
|
+
Artifacts:
|
|
32
|
+
codiedev push <file.md> Author or update an artifact
|
|
33
|
+
codiedev pull <key> [--version N] [--out path]
|
|
34
|
+
Fetch an artifact (stdout by default)
|
|
35
|
+
codiedev promote <artifact-id> Promote an auto-extracted artifact
|
|
36
|
+
to an authored one
|
|
37
|
+
|
|
38
|
+
Messaging:
|
|
39
|
+
codiedev ping <user> "<msg>" [--with <key>]
|
|
40
|
+
Send a message to a teammate
|
|
41
|
+
codiedev inbox [--unread] [--limit N] Show messages
|
|
42
|
+
codiedev read <ping-id> Mark read + show full message
|
|
43
|
+
|
|
44
|
+
Capture:
|
|
45
|
+
codiedev note "<text>" Capture a passing thought
|
|
46
|
+
|
|
47
|
+
Other:
|
|
48
|
+
codiedev help Show this help
|
|
49
|
+
codiedev version Show version
|
|
50
|
+
|
|
51
|
+
Backend: ${process.env.CODIEDEV_URL ?? "https://codiedev.com"}
|
|
52
|
+
`.trim();
|
|
53
|
+
async function main() {
|
|
54
|
+
const [, , command, ...rest] = process.argv;
|
|
55
|
+
if (!command || command === "help" || command === "--help" || command === "-h") {
|
|
56
|
+
console.log(HELP);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (command === "version" || command === "--version" || command === "-v") {
|
|
60
|
+
// Package version is replaced at publish via tsc — for now, print the source-of-truth.
|
|
61
|
+
console.log("codiedev cli");
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
switch (command) {
|
|
66
|
+
case "connect":
|
|
67
|
+
await (0, connect_1.runConnect)();
|
|
68
|
+
return;
|
|
69
|
+
case "push":
|
|
70
|
+
await (0, push_1.runPush)(rest);
|
|
71
|
+
return;
|
|
72
|
+
case "pull":
|
|
73
|
+
await (0, pull_1.runPull)(rest);
|
|
74
|
+
return;
|
|
75
|
+
case "ping":
|
|
76
|
+
await (0, ping_1.runPing)(rest);
|
|
77
|
+
return;
|
|
78
|
+
case "inbox":
|
|
79
|
+
case "check":
|
|
80
|
+
// Support `codiedev check inbox` as an alias.
|
|
81
|
+
if (command === "check" && rest[0] === "inbox") {
|
|
82
|
+
await (0, inbox_1.runInbox)(rest.slice(1));
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
await (0, inbox_1.runInbox)(rest);
|
|
86
|
+
}
|
|
87
|
+
return;
|
|
88
|
+
case "read":
|
|
89
|
+
await (0, inbox_1.runRead)(rest);
|
|
90
|
+
return;
|
|
91
|
+
case "note":
|
|
92
|
+
await (0, note_1.runNote)(rest);
|
|
93
|
+
return;
|
|
94
|
+
case "promote":
|
|
95
|
+
await (0, promote_1.runPromote)(rest);
|
|
96
|
+
return;
|
|
97
|
+
default:
|
|
98
|
+
console.error(`Unknown command: ${command}`);
|
|
99
|
+
console.error(HELP);
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
console.error("Unexpected error:", err.message);
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
main().catch((err) => {
|
|
109
|
+
console.error("Unexpected error:", err);
|
|
110
|
+
process.exit(1);
|
|
111
|
+
});
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runInbox = runInbox;
|
|
4
|
+
exports.runRead = runRead;
|
|
5
|
+
const shared_1 = require("./shared");
|
|
6
|
+
function parseInboxArgs(args) {
|
|
7
|
+
let unreadOnly = false;
|
|
8
|
+
let limit;
|
|
9
|
+
for (let i = 0; i < args.length; i++) {
|
|
10
|
+
const a = args[i];
|
|
11
|
+
if (a === "--unread" || a === "-u")
|
|
12
|
+
unreadOnly = true;
|
|
13
|
+
else if ((a === "--limit" || a === "-n") && i + 1 < args.length) {
|
|
14
|
+
const n = Number(args[++i]);
|
|
15
|
+
if (Number.isInteger(n) && n > 0)
|
|
16
|
+
limit = n;
|
|
17
|
+
}
|
|
18
|
+
else if (a.startsWith("--limit=")) {
|
|
19
|
+
const n = Number(a.slice("--limit=".length));
|
|
20
|
+
if (Number.isInteger(n) && n > 0)
|
|
21
|
+
limit = n;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return { unreadOnly, limit };
|
|
25
|
+
}
|
|
26
|
+
async function runInbox(args) {
|
|
27
|
+
const { unreadOnly, limit } = parseInboxArgs(args);
|
|
28
|
+
const config = (0, shared_1.requireConfig)();
|
|
29
|
+
try {
|
|
30
|
+
const res = await (0, shared_1.apiRequest)("GET", "/api/cli/inbox", {
|
|
31
|
+
config,
|
|
32
|
+
query: {
|
|
33
|
+
unreadOnly: unreadOnly ? "1" : undefined,
|
|
34
|
+
limit,
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
const pings = res.pings;
|
|
38
|
+
const unreadCount = pings.filter((p) => !p.readAt).length;
|
|
39
|
+
if (pings.length === 0) {
|
|
40
|
+
console.log(unreadOnly ? "No unread messages." : "Inbox is empty.");
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
console.log(`Inbox · ${pings.length} ${unreadOnly ? "unread" : "recent"}${unreadOnly ? "" : ` · ${unreadCount} unread`}`);
|
|
44
|
+
console.log();
|
|
45
|
+
for (const p of pings) {
|
|
46
|
+
const dot = p.readAt ? "·" : "●";
|
|
47
|
+
const from = p.from?.name ?? "unknown";
|
|
48
|
+
const when = (0, shared_1.timeAgo)(p.createdAt);
|
|
49
|
+
const where = p.subjectKey ? ` · on ${p.subjectKey}` : "";
|
|
50
|
+
const preview = p.preview || "(no body)";
|
|
51
|
+
console.log(`${dot} ${from}${where} · ${when}`);
|
|
52
|
+
console.log(` ${preview}`);
|
|
53
|
+
console.log(` id: ${p.pingId}`);
|
|
54
|
+
console.log();
|
|
55
|
+
}
|
|
56
|
+
console.log(`Mark read: codiedev read <ping-id>`);
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
console.error(`Inbox failed: ${err.message}`);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async function runRead(args) {
|
|
64
|
+
const pingId = args.find((a) => !a.startsWith("--"));
|
|
65
|
+
if (!pingId) {
|
|
66
|
+
console.error("Usage: codiedev read <ping-id>");
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
const config = (0, shared_1.requireConfig)();
|
|
70
|
+
try {
|
|
71
|
+
// First, fetch inbox so we can show the full body (markRead endpoint
|
|
72
|
+
// doesn't return content).
|
|
73
|
+
const listRes = await (0, shared_1.apiRequest)("GET", "/api/cli/inbox", {
|
|
74
|
+
config,
|
|
75
|
+
query: { limit: 100 },
|
|
76
|
+
});
|
|
77
|
+
const ping = listRes.pings.find((p) => p.pingId === pingId);
|
|
78
|
+
if (!ping) {
|
|
79
|
+
console.error(`Ping not found: ${pingId}`);
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
await (0, shared_1.apiRequest)("POST", "/api/cli/markRead", {
|
|
83
|
+
config,
|
|
84
|
+
body: { pingId },
|
|
85
|
+
});
|
|
86
|
+
const from = ping.from?.name ?? "unknown";
|
|
87
|
+
const when = (0, shared_1.timeAgo)(ping.createdAt);
|
|
88
|
+
const where = ping.subjectKey ? ` · on ${ping.subjectKey}` : "";
|
|
89
|
+
console.log(`From: ${from} <${ping.from?.email ?? ""}>`);
|
|
90
|
+
console.log(`Sent: ${when}${where}`);
|
|
91
|
+
if (ping.subject?.title) {
|
|
92
|
+
console.log(`Subject: ${ping.subject.title} (${ping.subject.type}${ping.subject.version ? ` v${ping.subject.version}` : ""})`);
|
|
93
|
+
}
|
|
94
|
+
console.log();
|
|
95
|
+
console.log(ping.body || "(empty)");
|
|
96
|
+
console.log();
|
|
97
|
+
console.log("✓ Marked as read");
|
|
98
|
+
if (ping.subjectKey) {
|
|
99
|
+
console.log(`Pull: codiedev pull ${ping.subjectKey}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
console.error(`Read failed: ${err.message}`);
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runNote(args: string[]): Promise<void>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runNote = runNote;
|
|
4
|
+
const shared_1 = require("./shared");
|
|
5
|
+
async function runNote(args) {
|
|
6
|
+
const positional = args.filter((a) => !a.startsWith("--"));
|
|
7
|
+
if (positional.length === 0) {
|
|
8
|
+
console.error('Usage: codiedev note "<text>"');
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
11
|
+
const body = (0, shared_1.stripQuotes)(positional.join(" ")).trim();
|
|
12
|
+
if (!body) {
|
|
13
|
+
console.error("Note body is empty.");
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
const config = (0, shared_1.requireConfig)();
|
|
17
|
+
try {
|
|
18
|
+
const res = await (0, shared_1.apiRequest)("POST", "/api/cli/note", {
|
|
19
|
+
config,
|
|
20
|
+
body: { body },
|
|
21
|
+
});
|
|
22
|
+
console.log(`✓ Noted (${res.key})`);
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
console.error(`Note failed: ${err.message}`);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runPing(args: string[]): Promise<void>;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runPing = runPing;
|
|
4
|
+
const shared_1 = require("./shared");
|
|
5
|
+
function parseArgs(args) {
|
|
6
|
+
let to;
|
|
7
|
+
const positional = [];
|
|
8
|
+
let subjectKey;
|
|
9
|
+
for (let i = 0; i < args.length; i++) {
|
|
10
|
+
const a = args[i];
|
|
11
|
+
if ((a === "--with" || a === "-w") && i + 1 < args.length) {
|
|
12
|
+
subjectKey = args[++i];
|
|
13
|
+
}
|
|
14
|
+
else if (a.startsWith("--with=")) {
|
|
15
|
+
subjectKey = a.slice("--with=".length);
|
|
16
|
+
}
|
|
17
|
+
else if (!a.startsWith("--")) {
|
|
18
|
+
positional.push(a);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (positional.length < 2) {
|
|
22
|
+
console.error("Usage: codiedev ping <user> \"<message>\" [--with <artifact-key>]");
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
to = positional[0];
|
|
26
|
+
// Join remaining positionals in case the shell split the message on spaces
|
|
27
|
+
// despite quoting (happens with some escape sequences).
|
|
28
|
+
const body = (0, shared_1.stripQuotes)(positional.slice(1).join(" "));
|
|
29
|
+
return { to, body, subjectKey };
|
|
30
|
+
}
|
|
31
|
+
async function runPing(args) {
|
|
32
|
+
const { to, body, subjectKey } = parseArgs(args);
|
|
33
|
+
const config = (0, shared_1.requireConfig)();
|
|
34
|
+
try {
|
|
35
|
+
const res = await (0, shared_1.apiRequest)("POST", "/api/cli/ping", {
|
|
36
|
+
config,
|
|
37
|
+
body: { to, body, subjectKey },
|
|
38
|
+
});
|
|
39
|
+
console.log(`✓ Pinged ${res.recipient.name} <${res.recipient.email}>${subjectKey ? ` on ${subjectKey}` : ""}`);
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
const e = err;
|
|
43
|
+
if (e.status === 409 && e.body?.candidates?.length) {
|
|
44
|
+
console.error(`${e.message}: multiple matches for "${to}":`);
|
|
45
|
+
for (const c of e.body.candidates) {
|
|
46
|
+
console.error(` - ${c.name} <${c.email}>`);
|
|
47
|
+
}
|
|
48
|
+
console.error(`Try a more specific name or email.`);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
console.error(`Ping failed: ${e.message}`);
|
|
52
|
+
}
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runPromote(args: string[]): Promise<void>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runPromote = runPromote;
|
|
4
|
+
const shared_1 = require("./shared");
|
|
5
|
+
function parseArgs(args) {
|
|
6
|
+
let artifactId;
|
|
7
|
+
let keyOverride;
|
|
8
|
+
for (let i = 0; i < args.length; i++) {
|
|
9
|
+
const a = args[i];
|
|
10
|
+
if ((a === "--key" || a === "-k") && i + 1 < args.length) {
|
|
11
|
+
keyOverride = args[++i];
|
|
12
|
+
}
|
|
13
|
+
else if (a.startsWith("--key=")) {
|
|
14
|
+
keyOverride = a.slice("--key=".length);
|
|
15
|
+
}
|
|
16
|
+
else if (!a.startsWith("--") && !artifactId) {
|
|
17
|
+
artifactId = a;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (!artifactId) {
|
|
21
|
+
console.error("Usage: codiedev promote <extracted-artifact-id> [--key spec-foo.md]");
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
return { artifactId, keyOverride };
|
|
25
|
+
}
|
|
26
|
+
async function runPromote(args) {
|
|
27
|
+
const { artifactId, keyOverride } = parseArgs(args);
|
|
28
|
+
const config = (0, shared_1.requireConfig)();
|
|
29
|
+
try {
|
|
30
|
+
const res = await (0, shared_1.apiRequest)("POST", "/api/cli/promote", {
|
|
31
|
+
config,
|
|
32
|
+
body: { artifactId, keyOverride },
|
|
33
|
+
});
|
|
34
|
+
console.log(`✓ Promoted to authored artifact ${res.key}`);
|
|
35
|
+
console.log(` id: ${res.artifactId}`);
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
console.error(`Promote failed: ${err.message}`);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runPull(args: string[]): Promise<void>;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.runPull = runPull;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const shared_1 = require("./shared");
|
|
40
|
+
function parseArgs(args) {
|
|
41
|
+
let key;
|
|
42
|
+
let version;
|
|
43
|
+
let out;
|
|
44
|
+
for (let i = 0; i < args.length; i++) {
|
|
45
|
+
const a = args[i];
|
|
46
|
+
if ((a === "--version" || a === "-v") && i + 1 < args.length) {
|
|
47
|
+
const n = Number(args[++i]);
|
|
48
|
+
if (Number.isInteger(n) && n > 0)
|
|
49
|
+
version = n;
|
|
50
|
+
}
|
|
51
|
+
else if (a.startsWith("--version=")) {
|
|
52
|
+
const n = Number(a.slice("--version=".length));
|
|
53
|
+
if (Number.isInteger(n) && n > 0)
|
|
54
|
+
version = n;
|
|
55
|
+
}
|
|
56
|
+
else if ((a === "--out" || a === "-o") && i + 1 < args.length) {
|
|
57
|
+
out = args[++i];
|
|
58
|
+
}
|
|
59
|
+
else if (a.startsWith("--out=")) {
|
|
60
|
+
out = a.slice("--out=".length);
|
|
61
|
+
}
|
|
62
|
+
else if (!a.startsWith("--") && !key) {
|
|
63
|
+
key = a;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (!key) {
|
|
67
|
+
console.error("Usage: codiedev pull <key> [--version N] [--out path.md]");
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
return { key, version, out };
|
|
71
|
+
}
|
|
72
|
+
async function runPull(args) {
|
|
73
|
+
const { key, version, out } = parseArgs(args);
|
|
74
|
+
const config = (0, shared_1.requireConfig)();
|
|
75
|
+
try {
|
|
76
|
+
const res = await (0, shared_1.apiRequest)("GET", "/api/cli/pull", {
|
|
77
|
+
config,
|
|
78
|
+
query: { key, version },
|
|
79
|
+
});
|
|
80
|
+
const a = res.artifact;
|
|
81
|
+
if (out) {
|
|
82
|
+
const absolute = path.isAbsolute(out) ? out : path.resolve(process.cwd(), out);
|
|
83
|
+
fs.writeFileSync(absolute, a.markdown, "utf8");
|
|
84
|
+
console.log(`✓ Pulled ${a.key} v${a.version ?? 1} (${a.type}) → ${absolute}`);
|
|
85
|
+
console.log(` title: ${a.title}`);
|
|
86
|
+
console.log(` lifecycle: ${a.lifecycle ?? "draft"}`);
|
|
87
|
+
console.log(` updated: ${(0, shared_1.timeAgo)(a.updatedAt ?? a.createdAt)}`);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
// Stream to stdout — preserves shell pipes like `codiedev pull spec-214.md | less`.
|
|
91
|
+
process.stdout.write(a.markdown);
|
|
92
|
+
if (!a.markdown.endsWith("\n"))
|
|
93
|
+
process.stdout.write("\n");
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
const e = err;
|
|
98
|
+
if (e.status === 404) {
|
|
99
|
+
console.error(`Not found: ${key}${version ? ` v${version}` : ""}`);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
console.error(`Pull failed: ${e.message}`);
|
|
103
|
+
}
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runPush(args: string[]): Promise<void>;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.runPush = runPush;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const shared_1 = require("./shared");
|
|
40
|
+
const VALID_TYPES = new Set([
|
|
41
|
+
"spec",
|
|
42
|
+
"bugfix",
|
|
43
|
+
"decision",
|
|
44
|
+
"proposal",
|
|
45
|
+
"review",
|
|
46
|
+
"note",
|
|
47
|
+
]);
|
|
48
|
+
function parseArgs(args) {
|
|
49
|
+
let file;
|
|
50
|
+
let type;
|
|
51
|
+
for (let i = 0; i < args.length; i++) {
|
|
52
|
+
const a = args[i];
|
|
53
|
+
if (a === "--type" && i + 1 < args.length) {
|
|
54
|
+
type = args[++i];
|
|
55
|
+
}
|
|
56
|
+
else if (a.startsWith("--type=")) {
|
|
57
|
+
type = a.slice("--type=".length);
|
|
58
|
+
}
|
|
59
|
+
else if (!a.startsWith("--") && !file) {
|
|
60
|
+
file = a;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (!file) {
|
|
64
|
+
console.error("Usage: codiedev push <file.md> [--type spec|bugfix|decision|proposal|review|note]");
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
if (type && !VALID_TYPES.has(type)) {
|
|
68
|
+
console.error(`Invalid --type. Valid types: ${[...VALID_TYPES].join(", ")}`);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
return { file, type };
|
|
72
|
+
}
|
|
73
|
+
async function runPush(args) {
|
|
74
|
+
const { file, type } = parseArgs(args);
|
|
75
|
+
const config = (0, shared_1.requireConfig)();
|
|
76
|
+
let absolute = file;
|
|
77
|
+
if (!path.isAbsolute(absolute)) {
|
|
78
|
+
absolute = path.resolve(process.cwd(), file);
|
|
79
|
+
}
|
|
80
|
+
if (!fs.existsSync(absolute)) {
|
|
81
|
+
console.error(`File not found: ${absolute}`);
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
const markdown = fs.readFileSync(absolute, "utf8");
|
|
85
|
+
if (!markdown.trim()) {
|
|
86
|
+
console.error(`File is empty: ${absolute}`);
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
const filename = path.basename(absolute);
|
|
90
|
+
try {
|
|
91
|
+
const res = await (0, shared_1.apiRequest)("POST", "/api/cli/push", {
|
|
92
|
+
config,
|
|
93
|
+
body: { filename, markdown, type },
|
|
94
|
+
});
|
|
95
|
+
console.log(`✓ Pushed ${filename}`);
|
|
96
|
+
console.log(` type: ${res.type}`);
|
|
97
|
+
console.log(` version: v${res.version}`);
|
|
98
|
+
console.log(` id: ${res.artifactId}`);
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
console.error(`Push failed: ${err.message}`);
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { CodiedevConfig } from "../utils";
|
|
2
|
+
/**
|
|
3
|
+
* Require a connected CodieDev config. Exits the process with a helpful
|
|
4
|
+
* message if the user hasn't run `codiedev connect` yet.
|
|
5
|
+
*/
|
|
6
|
+
export declare function requireConfig(): CodiedevConfig;
|
|
7
|
+
/**
|
|
8
|
+
* Perform an authenticated HTTP request against the CodieDev backend.
|
|
9
|
+
* Returns the parsed JSON response body. Throws on non-2xx.
|
|
10
|
+
*/
|
|
11
|
+
export declare function apiRequest<T = unknown>(method: "GET" | "POST", path: string, options: {
|
|
12
|
+
config: CodiedevConfig;
|
|
13
|
+
body?: Record<string, unknown>;
|
|
14
|
+
query?: Record<string, string | number | undefined>;
|
|
15
|
+
}): Promise<T>;
|
|
16
|
+
/**
|
|
17
|
+
* Relative-time formatter for inbox / listing output.
|
|
18
|
+
*/
|
|
19
|
+
export declare function timeAgo(ts: number): string;
|
|
20
|
+
/**
|
|
21
|
+
* Strip surrounding quotes from a CLI argument if the user wrapped it.
|
|
22
|
+
* `codiedev ping maya "hey"` on some shells passes the quotes through.
|
|
23
|
+
*/
|
|
24
|
+
export declare function stripQuotes(s: string): string;
|