Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 07a2ec3ab2 | |||
| b14bab5ed2 |
+59
-52
@@ -83,58 +83,6 @@ type CursorEvent =
|
|||||||
| CursorToolCallEvent
|
| CursorToolCallEvent
|
||||||
| CursorResultEvent;
|
| CursorResultEvent;
|
||||||
|
|
||||||
const messageHandlers = {
|
|
||||||
system: (_event: CursorSystemEvent) => {
|
|
||||||
// system init events - no logging needed
|
|
||||||
},
|
|
||||||
user: (_event: CursorUserEvent) => {
|
|
||||||
// user messages already logged in prompt box
|
|
||||||
},
|
|
||||||
thinking: (_event: CursorThinkingEvent) => {
|
|
||||||
// thinking events are internal - no logging needed
|
|
||||||
},
|
|
||||||
assistant: (event: CursorAssistantEvent) => {
|
|
||||||
// only log finalized messages (ones with model_call_id)
|
|
||||||
// cursor emits each message twice: once without model_call_id, then again with it
|
|
||||||
if (event.model_call_id) {
|
|
||||||
const text = event.message?.content?.[0]?.text;
|
|
||||||
if (text?.trim()) {
|
|
||||||
log.box(text.trim(), { title: "Cursor" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tool_call: (event: CursorToolCallEvent) => {
|
|
||||||
if (event.subtype === "started") {
|
|
||||||
// handle both MCP tools and built-in tools (bash, WebFetch, etc)
|
|
||||||
const mcpToolCall = event.tool_call?.mcpToolCall;
|
|
||||||
const builtinToolCall = (event.tool_call as any)?.builtinToolCall;
|
|
||||||
|
|
||||||
if (mcpToolCall?.args?.toolName && mcpToolCall?.args?.args) {
|
|
||||||
log.toolCall({
|
|
||||||
toolName: mcpToolCall.args.toolName,
|
|
||||||
input: mcpToolCall.args.args,
|
|
||||||
});
|
|
||||||
} else if (builtinToolCall?.args?.name && builtinToolCall?.args?.args) {
|
|
||||||
log.toolCall({
|
|
||||||
toolName: builtinToolCall.args.name,
|
|
||||||
input: builtinToolCall.args.args,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else if (event.subtype === "completed") {
|
|
||||||
const isError = event.tool_call?.mcpToolCall?.result?.success?.isError;
|
|
||||||
if (isError) {
|
|
||||||
log.warning("Tool call failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
result: async (event: CursorResultEvent) => {
|
|
||||||
if (event.subtype === "success" && event.duration_ms) {
|
|
||||||
const durationSec = (event.duration_ms / 1000).toFixed(1);
|
|
||||||
log.debug(`Cursor completed in ${durationSec}s`);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export const cursor = agent({
|
export const cursor = agent({
|
||||||
name: "cursor",
|
name: "cursor",
|
||||||
install: async () => {
|
install: async () => {
|
||||||
@@ -146,6 +94,60 @@ export const cursor = agent({
|
|||||||
run: async ({ payload, apiKey, cliPath, mcpServers }) => {
|
run: async ({ payload, apiKey, cliPath, mcpServers }) => {
|
||||||
configureCursorMcpServers({ mcpServers, cliPath });
|
configureCursorMcpServers({ mcpServers, cliPath });
|
||||||
|
|
||||||
|
// track logged messages to avoid duplicates
|
||||||
|
const loggedAssistantMessages = new Set<string>();
|
||||||
|
|
||||||
|
// moved into `run` because it is stateful
|
||||||
|
// it tracks logged assistant messages to avoid duplicates
|
||||||
|
const messageHandlers = {
|
||||||
|
system: (_event: CursorSystemEvent) => {
|
||||||
|
// system init events - no logging needed
|
||||||
|
},
|
||||||
|
user: (_event: CursorUserEvent) => {
|
||||||
|
// user messages already logged in prompt box
|
||||||
|
},
|
||||||
|
thinking: (_event: CursorThinkingEvent) => {
|
||||||
|
// thinking events are internal - no logging needed
|
||||||
|
},
|
||||||
|
assistant: (event: CursorAssistantEvent) => {
|
||||||
|
const text = event.message?.content?.[0]?.text?.trim();
|
||||||
|
if (text && !loggedAssistantMessages.has(text)) {
|
||||||
|
loggedAssistantMessages.add(text);
|
||||||
|
log.box(text, { title: "Cursor" });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tool_call: (event: CursorToolCallEvent) => {
|
||||||
|
if (event.subtype === "started") {
|
||||||
|
// handle both MCP tools and built-in tools (bash, WebFetch, etc)
|
||||||
|
const mcpToolCall = event.tool_call?.mcpToolCall;
|
||||||
|
const builtinToolCall = (event.tool_call as any)?.builtinToolCall;
|
||||||
|
|
||||||
|
if (mcpToolCall?.args?.toolName && mcpToolCall?.args?.args) {
|
||||||
|
log.toolCall({
|
||||||
|
toolName: mcpToolCall.args.toolName,
|
||||||
|
input: mcpToolCall.args.args,
|
||||||
|
});
|
||||||
|
} else if (builtinToolCall?.args?.name && builtinToolCall?.args?.args) {
|
||||||
|
log.toolCall({
|
||||||
|
toolName: builtinToolCall.args.name,
|
||||||
|
input: builtinToolCall.args.args,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (event.subtype === "completed") {
|
||||||
|
const isError = event.tool_call?.mcpToolCall?.result?.success?.isError;
|
||||||
|
if (isError) {
|
||||||
|
log.warning("Tool call failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
result: async (event: CursorResultEvent) => {
|
||||||
|
if (event.subtype === "success" && event.duration_ms) {
|
||||||
|
const durationSec = (event.duration_ms / 1000).toFixed(1);
|
||||||
|
log.debug(`Cursor completed in ${durationSec}s`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const fullPrompt = addInstructions(payload);
|
const fullPrompt = addInstructions(payload);
|
||||||
|
|
||||||
@@ -188,6 +190,11 @@ export const cursor = agent({
|
|||||||
try {
|
try {
|
||||||
const event = JSON.parse(text) as CursorEvent;
|
const event = JSON.parse(text) as CursorEvent;
|
||||||
|
|
||||||
|
// skip debug logging for empty thinking deltas
|
||||||
|
if (event.type === "thinking" && event.subtype === "delta" && !event.text) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// route to appropriate handler
|
// route to appropriate handler
|
||||||
const handler = messageHandlers[event.type as keyof typeof messageHandlers];
|
const handler = messageHandlers[event.type as keyof typeof messageHandlers];
|
||||||
if (handler) {
|
if (handler) {
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ Before starting any work, you must first determine which mode to use by examinin
|
|||||||
|
|
||||||
Available modes:
|
Available modes:
|
||||||
|
|
||||||
${[...modes, ...payload.modes].map((w) => ` - "${w.name}": ${w.description}`).join("\n")}
|
${(payload.modes.length > 0 ? payload.modes : modes).map((w) => ` - "${w.name}": ${w.description}`).join("\n")}
|
||||||
|
|
||||||
**IMPORTANT**: The first thing you must do is:
|
**IMPORTANT**: The first thing you must do is:
|
||||||
1. Examine the user's request/prompt carefully
|
1. Examine the user's request/prompt carefully
|
||||||
|
|||||||
@@ -83859,7 +83859,7 @@ function query({
|
|||||||
// package.json
|
// package.json
|
||||||
var package_default = {
|
var package_default = {
|
||||||
name: "@pullfrog/action",
|
name: "@pullfrog/action",
|
||||||
version: "0.0.118",
|
version: "0.0.119",
|
||||||
type: "module",
|
type: "module",
|
||||||
files: [
|
files: [
|
||||||
"index.js",
|
"index.js",
|
||||||
@@ -92367,7 +92367,7 @@ Before starting any work, you must first determine which mode to use by examinin
|
|||||||
|
|
||||||
Available modes:
|
Available modes:
|
||||||
|
|
||||||
${[...modes, ...payload.modes].map((w) => ` - "${w.name}": ${w.description}`).join("\n")}
|
${(payload.modes.length > 0 ? payload.modes : modes).map((w) => ` - "${w.name}": ${w.description}`).join("\n")}
|
||||||
|
|
||||||
**IMPORTANT**: The first thing you must do is:
|
**IMPORTANT**: The first thing you must do is:
|
||||||
1. Examine the user's request/prompt carefully
|
1. Examine the user's request/prompt carefully
|
||||||
@@ -93390,50 +93390,6 @@ import { spawn as spawn3 } from "node:child_process";
|
|||||||
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync2 } from "node:fs";
|
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync2 } from "node:fs";
|
||||||
import { homedir as homedir2 } from "node:os";
|
import { homedir as homedir2 } from "node:os";
|
||||||
import { join as join6 } from "node:path";
|
import { join as join6 } from "node:path";
|
||||||
var messageHandlers3 = {
|
|
||||||
system: (_event) => {
|
|
||||||
},
|
|
||||||
user: (_event) => {
|
|
||||||
},
|
|
||||||
thinking: (_event) => {
|
|
||||||
},
|
|
||||||
assistant: (event) => {
|
|
||||||
if (event.model_call_id) {
|
|
||||||
const text = event.message?.content?.[0]?.text;
|
|
||||||
if (text?.trim()) {
|
|
||||||
log.box(text.trim(), { title: "Cursor" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tool_call: (event) => {
|
|
||||||
if (event.subtype === "started") {
|
|
||||||
const mcpToolCall = event.tool_call?.mcpToolCall;
|
|
||||||
const builtinToolCall = event.tool_call?.builtinToolCall;
|
|
||||||
if (mcpToolCall?.args?.toolName && mcpToolCall?.args?.args) {
|
|
||||||
log.toolCall({
|
|
||||||
toolName: mcpToolCall.args.toolName,
|
|
||||||
input: mcpToolCall.args.args
|
|
||||||
});
|
|
||||||
} else if (builtinToolCall?.args?.name && builtinToolCall?.args?.args) {
|
|
||||||
log.toolCall({
|
|
||||||
toolName: builtinToolCall.args.name,
|
|
||||||
input: builtinToolCall.args.args
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else if (event.subtype === "completed") {
|
|
||||||
const isError = event.tool_call?.mcpToolCall?.result?.success?.isError;
|
|
||||||
if (isError) {
|
|
||||||
log.warning("Tool call failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
result: async (event) => {
|
|
||||||
if (event.subtype === "success" && event.duration_ms) {
|
|
||||||
const durationSec = (event.duration_ms / 1e3).toFixed(1);
|
|
||||||
log.debug(`Cursor completed in ${durationSec}s`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var cursor = agent({
|
var cursor = agent({
|
||||||
name: "cursor",
|
name: "cursor",
|
||||||
install: async () => {
|
install: async () => {
|
||||||
@@ -93444,6 +93400,50 @@ var cursor = agent({
|
|||||||
},
|
},
|
||||||
run: async ({ payload, apiKey, cliPath, mcpServers }) => {
|
run: async ({ payload, apiKey, cliPath, mcpServers }) => {
|
||||||
configureCursorMcpServers({ mcpServers, cliPath });
|
configureCursorMcpServers({ mcpServers, cliPath });
|
||||||
|
const loggedAssistantMessages = /* @__PURE__ */ new Set();
|
||||||
|
const messageHandlers4 = {
|
||||||
|
system: (_event) => {
|
||||||
|
},
|
||||||
|
user: (_event) => {
|
||||||
|
},
|
||||||
|
thinking: (_event) => {
|
||||||
|
},
|
||||||
|
assistant: (event) => {
|
||||||
|
const text = event.message?.content?.[0]?.text?.trim();
|
||||||
|
if (text && !loggedAssistantMessages.has(text)) {
|
||||||
|
loggedAssistantMessages.add(text);
|
||||||
|
log.box(text, { title: "Cursor" });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tool_call: (event) => {
|
||||||
|
if (event.subtype === "started") {
|
||||||
|
const mcpToolCall = event.tool_call?.mcpToolCall;
|
||||||
|
const builtinToolCall = event.tool_call?.builtinToolCall;
|
||||||
|
if (mcpToolCall?.args?.toolName && mcpToolCall?.args?.args) {
|
||||||
|
log.toolCall({
|
||||||
|
toolName: mcpToolCall.args.toolName,
|
||||||
|
input: mcpToolCall.args.args
|
||||||
|
});
|
||||||
|
} else if (builtinToolCall?.args?.name && builtinToolCall?.args?.args) {
|
||||||
|
log.toolCall({
|
||||||
|
toolName: builtinToolCall.args.name,
|
||||||
|
input: builtinToolCall.args.args
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (event.subtype === "completed") {
|
||||||
|
const isError = event.tool_call?.mcpToolCall?.result?.success?.isError;
|
||||||
|
if (isError) {
|
||||||
|
log.warning("Tool call failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
result: async (event) => {
|
||||||
|
if (event.subtype === "success" && event.duration_ms) {
|
||||||
|
const durationSec = (event.duration_ms / 1e3).toFixed(1);
|
||||||
|
log.debug(`Cursor completed in ${durationSec}s`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
try {
|
try {
|
||||||
const fullPrompt = addInstructions(payload);
|
const fullPrompt = addInstructions(payload);
|
||||||
log.info("Running Cursor CLI...");
|
log.info("Running Cursor CLI...");
|
||||||
@@ -93479,7 +93479,10 @@ var cursor = agent({
|
|||||||
stdout += text;
|
stdout += text;
|
||||||
try {
|
try {
|
||||||
const event = JSON.parse(text);
|
const event = JSON.parse(text);
|
||||||
const handler2 = messageHandlers3[event.type];
|
if (event.type === "thinking" && event.subtype === "delta" && !event.text) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const handler2 = messageHandlers4[event.type];
|
||||||
if (handler2) {
|
if (handler2) {
|
||||||
await handler2(event);
|
await handler2(event);
|
||||||
}
|
}
|
||||||
@@ -93640,7 +93643,7 @@ async function spawn4(options) {
|
|||||||
|
|
||||||
// agents/gemini.ts
|
// agents/gemini.ts
|
||||||
var assistantMessageBuffer = "";
|
var assistantMessageBuffer = "";
|
||||||
var messageHandlers4 = {
|
var messageHandlers3 = {
|
||||||
init: (_event) => {
|
init: (_event) => {
|
||||||
assistantMessageBuffer = "";
|
assistantMessageBuffer = "";
|
||||||
},
|
},
|
||||||
@@ -93740,7 +93743,7 @@ var gemini = agent({
|
|||||||
log.debug(`[gemini stdout] ${trimmed}`);
|
log.debug(`[gemini stdout] ${trimmed}`);
|
||||||
try {
|
try {
|
||||||
const event = JSON.parse(trimmed);
|
const event = JSON.parse(trimmed);
|
||||||
const handler2 = messageHandlers4[event.type];
|
const handler2 = messageHandlers3[event.type];
|
||||||
if (handler2) {
|
if (handler2) {
|
||||||
await handler2(event);
|
await handler2(event);
|
||||||
}
|
}
|
||||||
@@ -122737,7 +122740,7 @@ function parsePayload(inputs) {
|
|||||||
agent: null,
|
agent: null,
|
||||||
prompt: inputs.prompt,
|
prompt: inputs.prompt,
|
||||||
event: {
|
event: {
|
||||||
trigger: "workflow_dispatch"
|
trigger: "unknown"
|
||||||
},
|
},
|
||||||
modes
|
modes
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -135,6 +135,10 @@ export type PayloadEvent =
|
|||||||
| {
|
| {
|
||||||
trigger: "workflow_dispatch";
|
trigger: "workflow_dispatch";
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
trigger: "unknown";
|
||||||
|
[key: string]: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
// payload type for agent execution
|
// payload type for agent execution
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
summarize https://github.com/pullfrogai/scratch/issues/56, its status, and pertinent discussion on the issue
|
Tell me a joke
|
||||||
@@ -263,7 +263,7 @@ function parsePayload(inputs: Inputs): Payload {
|
|||||||
agent: null,
|
agent: null,
|
||||||
prompt: inputs.prompt,
|
prompt: inputs.prompt,
|
||||||
event: {
|
event: {
|
||||||
trigger: "workflow_dispatch",
|
trigger: "unknown",
|
||||||
},
|
},
|
||||||
modes,
|
modes,
|
||||||
};
|
};
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@pullfrog/action",
|
"name": "@pullfrog/action",
|
||||||
"version": "0.0.118",
|
"version": "0.0.119",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"files": [
|
"files": [
|
||||||
"index.js",
|
"index.js",
|
||||||
|
|||||||
Reference in New Issue
Block a user