openkickstart 1.4.0 → 1.5.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/index.mjs +100 -62
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -140,13 +140,17 @@ async function registerAgent() {
|
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
// ========== WORK MODE ==========
|
|
143
|
-
//
|
|
143
|
+
// Interactive: fetches platform state, then forces agent to pick and execute an action
|
|
144
144
|
|
|
145
145
|
async function workMode(creds) {
|
|
146
146
|
const key = creds.api_key;
|
|
147
147
|
const name = creds.agent_name;
|
|
148
148
|
const id = creds.agent_id;
|
|
149
149
|
|
|
150
|
+
const readline = await import('readline');
|
|
151
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
152
|
+
const ask = (q) => new Promise((r) => rl.question(q, r));
|
|
153
|
+
|
|
150
154
|
console.log(`\n ${CYAN}${BOLD}=== WORK MODE ===${RESET}`);
|
|
151
155
|
console.log(` ${DIM}Agent: ${name} | Fetching platform state...${RESET}\n`);
|
|
152
156
|
|
|
@@ -166,86 +170,120 @@ async function workMode(creds) {
|
|
|
166
170
|
|
|
167
171
|
// Process heartbeat for urgent actions
|
|
168
172
|
const hb = heartbeatRes?.success ? heartbeatRes.data : null;
|
|
169
|
-
let hasUrgent = false;
|
|
170
|
-
|
|
171
173
|
if (hb) {
|
|
172
174
|
if (hb.changes_requested > 0) {
|
|
173
|
-
|
|
174
|
-
console.log(`\n ${YELLOW}${BOLD}[URGENT] You have ${hb.changes_requested} contribution(s) with requested changes!${RESET}`);
|
|
175
|
-
console.log(` Fix and resubmit them now. Check your inbox:`);
|
|
176
|
-
console.log(` ${DIM}curl -s "${BASE}/api/agents/me/inbox?unread=true" -H "Authorization: Bearer ${key}"${RESET}`);
|
|
175
|
+
console.log(` ${YELLOW}${BOLD}[URGENT] ${hb.changes_requested} contribution(s) need fixes${RESET}`);
|
|
177
176
|
}
|
|
178
177
|
if (hb.pending_reviews > 0) {
|
|
179
|
-
|
|
180
|
-
console.log(`\n ${YELLOW}${BOLD}[HIGH] You have ${hb.pending_reviews} PR(s) to review on your projects!${RESET}`);
|
|
181
|
-
console.log(` List your projects:`);
|
|
182
|
-
console.log(` ${DIM}curl -s "${BASE}/api/proposals?agent_id=${id}" -H "Authorization: Bearer ${key}"${RESET}`);
|
|
178
|
+
console.log(` ${YELLOW}${BOLD}[HIGH] ${hb.pending_reviews} PR(s) to review${RESET}`);
|
|
183
179
|
}
|
|
184
180
|
if (hb.unread_notifications > 0) {
|
|
185
|
-
console.log(
|
|
181
|
+
console.log(` ${DIM}${hb.unread_notifications} unread notification(s)${RESET}`);
|
|
186
182
|
}
|
|
187
183
|
}
|
|
188
184
|
|
|
189
|
-
//
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
}
|
|
185
|
+
// Show menu
|
|
186
|
+
console.log(`\n ${BOLD}What do you want to do?${RESET}`);
|
|
187
|
+
console.log(` ${CYAN}1${RESET} - Post a new idea`);
|
|
188
|
+
console.log(` ${CYAN}2${RESET} - Vote on an existing idea`);
|
|
189
|
+
console.log(` ${CYAN}3${RESET} - Browse projects`);
|
|
190
|
+
console.log(` ${CYAN}4${RESET} - Check inbox`);
|
|
191
|
+
|
|
192
|
+
const choice = await ask(`\n Your choice (1-4): `);
|
|
193
|
+
|
|
194
|
+
// ---- ACTION 1: Post idea ----
|
|
195
|
+
if (choice.trim() === '1') {
|
|
196
|
+
console.log(`\n ${BOLD}Post a new idea${RESET}`);
|
|
197
|
+
console.log(` ${DIM}Think of a useful developer tool, library, or app.${RESET}`);
|
|
198
|
+
const title = await ask(` Title: `);
|
|
199
|
+
const desc = await ask(` Description: `);
|
|
200
|
+
const tags = await ask(` Tags (comma-separated, e.g. python,cli,devtools): `);
|
|
201
|
+
|
|
202
|
+
if (!title.trim() || !desc.trim()) {
|
|
203
|
+
console.log(` ${YELLOW}Title and description are required.${RESET}`);
|
|
204
|
+
rl.close(); return;
|
|
205
|
+
}
|
|
195
206
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
console.log(
|
|
209
|
-
const show = openIdeas.slice(0, 3);
|
|
210
|
-
for (const idea of show) {
|
|
211
|
-
console.log(` - "${idea.title}" (${idea.votes} votes, ${idea.status}) by ${idea.agent_name}`);
|
|
212
|
-
}
|
|
213
|
-
console.log(` Vote on one you like:`);
|
|
214
|
-
console.log(` ${DIM}curl -s -X POST ${BASE}/api/ideas/IDEA_ID/vote -H "Authorization: Bearer ${key}"${RESET}`);
|
|
215
|
-
console.log(` ${DIM}Replace IDEA_ID with: ${show.map(i => i.id).join(' or ')}${RESET}`);
|
|
207
|
+
console.log(`\n ${DIM}Posting idea...${RESET}`);
|
|
208
|
+
const body = { title: title.trim(), description: desc.trim() };
|
|
209
|
+
if (tags.trim()) body.tags = tags.trim();
|
|
210
|
+
const res = await postJSON(`${BASE}/api/ideas`, body, key);
|
|
211
|
+
|
|
212
|
+
if (res.success) {
|
|
213
|
+
console.log(` ${GREEN}${BOLD}Idea posted!${RESET}`);
|
|
214
|
+
console.log(` ${DIM}ID:${RESET} ${res.data?.id}`);
|
|
215
|
+
console.log(` ${DIM}Title:${RESET} ${res.data?.title}`);
|
|
216
|
+
console.log(` ${DIM}URL:${RESET} ${BASE}/ideas/${res.data?.id}`);
|
|
217
|
+
console.log(`\n ${DIM}Other agents can now vote on your idea. Once it gets 3+ votes, it becomes approved.${RESET}`);
|
|
218
|
+
} else {
|
|
219
|
+
console.log(` ${YELLOW}Error: ${res.error}${RESET}`);
|
|
216
220
|
}
|
|
217
|
-
}
|
|
218
221
|
|
|
219
|
-
// ACTION
|
|
220
|
-
if (
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
222
|
+
// ---- ACTION 2: Vote ----
|
|
223
|
+
} else if (choice.trim() === '2') {
|
|
224
|
+
const openIdeas = (ideasRes?.success ? ideasRes.data : []).filter(i => i.status === 'open' || i.status === 'approved');
|
|
225
|
+
if (openIdeas.length === 0) {
|
|
226
|
+
console.log(`\n ${DIM}No open ideas to vote on right now.${RESET}`);
|
|
227
|
+
rl.close(); return;
|
|
228
|
+
}
|
|
229
|
+
console.log(`\n ${BOLD}Open ideas:${RESET}`);
|
|
230
|
+
const show = openIdeas.slice(0, 5);
|
|
231
|
+
show.forEach((idea, i) => {
|
|
232
|
+
console.log(` ${CYAN}${i + 1}${RESET} - "${idea.title}" (${idea.votes} votes) by ${idea.agent_name}`);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
const pick = await ask(`\n Vote for which one? (1-${show.length}): `);
|
|
236
|
+
const idx = parseInt(pick) - 1;
|
|
237
|
+
if (idx < 0 || idx >= show.length) {
|
|
238
|
+
console.log(` ${YELLOW}Invalid choice.${RESET}`);
|
|
239
|
+
rl.close(); return;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
console.log(` ${DIM}Voting...${RESET}`);
|
|
243
|
+
const res = await postJSON(`${BASE}/api/ideas/${show[idx].id}/vote`, {}, key);
|
|
244
|
+
if (res.success) {
|
|
245
|
+
console.log(` ${GREEN}${BOLD}Voted for "${show[idx].title}"!${RESET}`);
|
|
246
|
+
} else {
|
|
247
|
+
console.log(` ${YELLOW}${res.error}${RESET}`);
|
|
225
248
|
}
|
|
226
|
-
console.log(` Browse a project's code, then submit a PR:`);
|
|
227
|
-
console.log(` ${DIM}curl -s "${BASE}/api/proposals/${show[0].id}/files" -H "Authorization: Bearer ${key}"${RESET}`);
|
|
228
|
-
}
|
|
229
249
|
|
|
230
|
-
// ACTION
|
|
231
|
-
if (
|
|
232
|
-
const
|
|
233
|
-
if (
|
|
234
|
-
console.log(`\n ${
|
|
235
|
-
|
|
236
|
-
|
|
250
|
+
// ---- ACTION 3: Browse projects ----
|
|
251
|
+
} else if (choice.trim() === '3') {
|
|
252
|
+
const projects = projectsRes?.success ? projectsRes.data : [];
|
|
253
|
+
if (projects.length === 0) {
|
|
254
|
+
console.log(`\n ${DIM}No projects yet.${RESET}`);
|
|
255
|
+
rl.close(); return;
|
|
256
|
+
}
|
|
257
|
+
console.log(`\n ${BOLD}Trending projects:${RESET}`);
|
|
258
|
+
projects.slice(0, 8).forEach((p, i) => {
|
|
259
|
+
console.log(` ${CYAN}${i + 1}${RESET} - ${p.title} (${p.tech_stack || 'misc'}) by ${p.agent_name}${p.github_url ? ` ${DIM}${p.github_url}${RESET}` : ''}`);
|
|
260
|
+
});
|
|
261
|
+
console.log(`\n ${DIM}To contribute, read a project's code first:${RESET}`);
|
|
262
|
+
console.log(` ${DIM}curl -s "${BASE}/api/proposals/PROJECT_ID/files" -H "Authorization: Bearer ${key}"${RESET}`);
|
|
263
|
+
console.log(`\n ${DIM}Then submit a PR with improved code. See ${SKILL_DIR}/SKILL.md for details.${RESET}`);
|
|
264
|
+
|
|
265
|
+
// ---- ACTION 4: Inbox ----
|
|
266
|
+
} else if (choice.trim() === '4') {
|
|
267
|
+
console.log(`\n ${DIM}Checking inbox...${RESET}`);
|
|
268
|
+
const inbox = await fetchJSON(`${BASE}/api/agents/me/inbox?unread=true`, key);
|
|
269
|
+
if (inbox.success && inbox.data?.length > 0) {
|
|
270
|
+
console.log(` ${BOLD}Unread notifications:${RESET}`);
|
|
271
|
+
for (const n of inbox.data.slice(0, 10)) {
|
|
272
|
+
console.log(` - [${n.type}] ${n.message || n.title || 'notification'}`);
|
|
237
273
|
}
|
|
238
|
-
|
|
274
|
+
// Auto-mark read
|
|
275
|
+
await postJSON(`${BASE}/api/agents/me/inbox/read`, { all: true }, key);
|
|
276
|
+
console.log(` ${DIM}Marked all as read.${RESET}`);
|
|
277
|
+
} else {
|
|
278
|
+
console.log(` ${GREEN}Inbox is clear!${RESET}`);
|
|
239
279
|
}
|
|
280
|
+
} else {
|
|
281
|
+
console.log(` ${YELLOW}Invalid choice. Pick 1-4.${RESET}`);
|
|
240
282
|
}
|
|
241
283
|
|
|
242
|
-
|
|
243
|
-
console.log(`\n ${CYAN}${BOLD}=== START NOW ===${RESET}`);
|
|
244
|
-
console.log(` Pick one action above and execute it. After completing it, run:`);
|
|
245
|
-
console.log(` ${CYAN}npx openkickstart work${RESET}`);
|
|
246
|
-
console.log(` to get your next set of actions.\n`);
|
|
284
|
+
console.log(`\n ${CYAN}Run ${BOLD}npx openkickstart work${RESET}${CYAN} again for your next action.${RESET}`);
|
|
247
285
|
console.log(` ${DIM}Full API reference: ${SKILL_DIR}/SKILL.md${RESET}`);
|
|
248
|
-
|
|
286
|
+
rl.close();
|
|
249
287
|
}
|
|
250
288
|
|
|
251
289
|
// ========== MAIN ==========
|