@trevonistrevon/pi-loop 0.4.6 → 0.4.7
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/index.js +47 -5
- package/package.json +1 -1
- package/src/index.ts +52 -5
package/dist/index.js
CHANGED
|
@@ -926,6 +926,34 @@ Use MonitorList to find the monitor ID, then stop it with this tool.`,
|
|
|
926
926
|
const active = loops.filter(l => l.status === "active").length;
|
|
927
927
|
ui.notify(`${active}/${loops.length} active loops (max 25)`, "info");
|
|
928
928
|
}
|
|
929
|
+
const AUTO_TASK_WORKER_THRESHOLD = 5;
|
|
930
|
+
const AUTO_TASK_WORKER_PROMPT = "Run TaskList, pick next pending task, mark it in_progress, implement it, run validation, complete it. If no pending tasks remain, call LoopDelete on your own loop ID.";
|
|
931
|
+
function findAutoTaskWorkerLoop() {
|
|
932
|
+
return store.list().find(entry => entry.status === "active"
|
|
933
|
+
&& entry.prompt === AUTO_TASK_WORKER_PROMPT
|
|
934
|
+
&& triggerHasEventSource(entry.trigger, "tasks:created"));
|
|
935
|
+
}
|
|
936
|
+
async function ensureAutoTaskWorkerLoop(taskStore) {
|
|
937
|
+
if (taskStore.pendingCount() < AUTO_TASK_WORKER_THRESHOLD)
|
|
938
|
+
return { created: false };
|
|
939
|
+
const existing = findAutoTaskWorkerLoop();
|
|
940
|
+
if (existing)
|
|
941
|
+
return { entry: existing, created: false };
|
|
942
|
+
const trigger = {
|
|
943
|
+
type: "hybrid",
|
|
944
|
+
cron: "*/5 * * * *",
|
|
945
|
+
event: { source: "tasks:created" },
|
|
946
|
+
debounceMs: 30000,
|
|
947
|
+
};
|
|
948
|
+
const entry = store.create(trigger, AUTO_TASK_WORKER_PROMPT, {
|
|
949
|
+
recurring: true,
|
|
950
|
+
maxFires: 30,
|
|
951
|
+
});
|
|
952
|
+
triggerSystem.add(entry);
|
|
953
|
+
await maybeBootstrapTaskLoop(entry);
|
|
954
|
+
widget.update();
|
|
955
|
+
return { entry, created: true };
|
|
956
|
+
}
|
|
929
957
|
async function createNativeTaskInteractively(ui) {
|
|
930
958
|
if (!nativeTaskStore) {
|
|
931
959
|
ui.notify("Native tasks are unavailable while pi-tasks is active", "warning");
|
|
@@ -936,8 +964,18 @@ Use MonitorList to find the monitor ID, then stop it with this tool.`,
|
|
|
936
964
|
return;
|
|
937
965
|
const description = await ui.input("Task description") || subject;
|
|
938
966
|
const entry = nativeTaskStore.create(subject, description);
|
|
967
|
+
pi.events.emit("tasks:created", {
|
|
968
|
+
taskId: entry.id,
|
|
969
|
+
subject: entry.subject,
|
|
970
|
+
description: entry.description,
|
|
971
|
+
status: entry.status,
|
|
972
|
+
});
|
|
973
|
+
const worker = await ensureAutoTaskWorkerLoop(nativeTaskStore);
|
|
939
974
|
widget.update();
|
|
940
975
|
ui.notify(`Task #${entry.id} created`, "info");
|
|
976
|
+
if (worker.created && worker.entry) {
|
|
977
|
+
ui.notify(`Worker loop #${worker.entry.id} auto-created`, "info");
|
|
978
|
+
}
|
|
941
979
|
}
|
|
942
980
|
async function viewNativeTasks(ui) {
|
|
943
981
|
if (!nativeTaskStore) {
|
|
@@ -1022,8 +1060,12 @@ Use MonitorList to find the monitor ID, then stop it with this tool.`,
|
|
|
1022
1060
|
description: entry.description,
|
|
1023
1061
|
status: entry.status,
|
|
1024
1062
|
});
|
|
1063
|
+
const worker = await ensureAutoTaskWorkerLoop(nativeTaskStore);
|
|
1025
1064
|
widget.update();
|
|
1026
1065
|
ctx.ui.notify(`Task #${entry.id} created`, "info");
|
|
1066
|
+
if (worker.created && worker.entry) {
|
|
1067
|
+
ctx.ui.notify(`Worker loop #${worker.entry.id} auto-created`, "info");
|
|
1068
|
+
}
|
|
1027
1069
|
return;
|
|
1028
1070
|
}
|
|
1029
1071
|
await viewNativeTasks(ctx.ui);
|
|
@@ -1047,7 +1089,7 @@ Fields:
|
|
|
1047
1089
|
subject: Type.String({ description: "Brief actionable title for the task" }),
|
|
1048
1090
|
description: Type.String({ description: "Detailed description of what needs to be done" }),
|
|
1049
1091
|
}),
|
|
1050
|
-
execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
1092
|
+
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
1051
1093
|
const entry = taskStore.create(params.subject, params.description);
|
|
1052
1094
|
pi.events.emit("tasks:created", {
|
|
1053
1095
|
taskId: entry.id,
|
|
@@ -1055,12 +1097,12 @@ Fields:
|
|
|
1055
1097
|
description: entry.description,
|
|
1056
1098
|
status: entry.status,
|
|
1057
1099
|
});
|
|
1100
|
+
const worker = await ensureAutoTaskWorkerLoop(taskStore);
|
|
1058
1101
|
widget.update();
|
|
1059
|
-
const
|
|
1060
|
-
|
|
1061
|
-
? `\n(${pending} pending tasks — consider creating a worker loop: LoopCreate trigger='tasks:created' recurring: true maxFires: 30 prompt='Run TaskList, pick next pending task, mark it in_progress, implement it, run validation, complete it. If no pending tasks remain, call LoopDelete on your own loop ID.')`
|
|
1102
|
+
const autoLoopMsg = worker.created && worker.entry
|
|
1103
|
+
? `\nWorker loop #${worker.entry.id} auto-created`
|
|
1062
1104
|
: "";
|
|
1063
|
-
return Promise.resolve(textResult(`Task #${entry.id} created: ${entry.subject}${
|
|
1105
|
+
return Promise.resolve(textResult(`Task #${entry.id} created: ${entry.subject}${autoLoopMsg}`));
|
|
1064
1106
|
},
|
|
1065
1107
|
});
|
|
1066
1108
|
pi.registerTool({
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1005,6 +1005,39 @@ Use MonitorList to find the monitor ID, then stop it with this tool.`,
|
|
|
1005
1005
|
ui.notify(`${active}/${loops.length} active loops (max 25)`, "info");
|
|
1006
1006
|
}
|
|
1007
1007
|
|
|
1008
|
+
const AUTO_TASK_WORKER_THRESHOLD = 5;
|
|
1009
|
+
const AUTO_TASK_WORKER_PROMPT = "Run TaskList, pick next pending task, mark it in_progress, implement it, run validation, complete it. If no pending tasks remain, call LoopDelete on your own loop ID.";
|
|
1010
|
+
|
|
1011
|
+
function findAutoTaskWorkerLoop(): LoopEntry | undefined {
|
|
1012
|
+
return store.list().find(entry =>
|
|
1013
|
+
entry.status === "active"
|
|
1014
|
+
&& entry.prompt === AUTO_TASK_WORKER_PROMPT
|
|
1015
|
+
&& triggerHasEventSource(entry.trigger, "tasks:created")
|
|
1016
|
+
);
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
async function ensureAutoTaskWorkerLoop(taskStore: TaskStore): Promise<{ entry?: LoopEntry; created: boolean }> {
|
|
1020
|
+
if (taskStore.pendingCount() < AUTO_TASK_WORKER_THRESHOLD) return { created: false };
|
|
1021
|
+
|
|
1022
|
+
const existing = findAutoTaskWorkerLoop();
|
|
1023
|
+
if (existing) return { entry: existing, created: false };
|
|
1024
|
+
|
|
1025
|
+
const trigger: Trigger = {
|
|
1026
|
+
type: "hybrid",
|
|
1027
|
+
cron: "*/5 * * * *",
|
|
1028
|
+
event: { source: "tasks:created" },
|
|
1029
|
+
debounceMs: 30000,
|
|
1030
|
+
};
|
|
1031
|
+
const entry = store.create(trigger, AUTO_TASK_WORKER_PROMPT, {
|
|
1032
|
+
recurring: true,
|
|
1033
|
+
maxFires: 30,
|
|
1034
|
+
});
|
|
1035
|
+
triggerSystem.add(entry);
|
|
1036
|
+
await maybeBootstrapTaskLoop(entry);
|
|
1037
|
+
widget.update();
|
|
1038
|
+
return { entry, created: true };
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1008
1041
|
async function createNativeTaskInteractively(ui: ExtensionUIContext) {
|
|
1009
1042
|
if (!nativeTaskStore) {
|
|
1010
1043
|
ui.notify("Native tasks are unavailable while pi-tasks is active", "warning");
|
|
@@ -1015,8 +1048,18 @@ Use MonitorList to find the monitor ID, then stop it with this tool.`,
|
|
|
1015
1048
|
if (!subject) return;
|
|
1016
1049
|
const description = await ui.input("Task description") || subject;
|
|
1017
1050
|
const entry = nativeTaskStore.create(subject, description);
|
|
1051
|
+
pi.events.emit("tasks:created", {
|
|
1052
|
+
taskId: entry.id,
|
|
1053
|
+
subject: entry.subject,
|
|
1054
|
+
description: entry.description,
|
|
1055
|
+
status: entry.status,
|
|
1056
|
+
});
|
|
1057
|
+
const worker = await ensureAutoTaskWorkerLoop(nativeTaskStore);
|
|
1018
1058
|
widget.update();
|
|
1019
1059
|
ui.notify(`Task #${entry.id} created`, "info");
|
|
1060
|
+
if (worker.created && worker.entry) {
|
|
1061
|
+
ui.notify(`Worker loop #${worker.entry.id} auto-created`, "info");
|
|
1062
|
+
}
|
|
1020
1063
|
}
|
|
1021
1064
|
|
|
1022
1065
|
async function viewNativeTasks(ui: ExtensionUIContext): Promise<void> {
|
|
@@ -1103,8 +1146,12 @@ Use MonitorList to find the monitor ID, then stop it with this tool.`,
|
|
|
1103
1146
|
description: entry.description,
|
|
1104
1147
|
status: entry.status,
|
|
1105
1148
|
});
|
|
1149
|
+
const worker = await ensureAutoTaskWorkerLoop(nativeTaskStore);
|
|
1106
1150
|
widget.update();
|
|
1107
1151
|
ctx.ui.notify(`Task #${entry.id} created`, "info");
|
|
1152
|
+
if (worker.created && worker.entry) {
|
|
1153
|
+
ctx.ui.notify(`Worker loop #${worker.entry.id} auto-created`, "info");
|
|
1154
|
+
}
|
|
1108
1155
|
return;
|
|
1109
1156
|
}
|
|
1110
1157
|
await viewNativeTasks(ctx.ui);
|
|
@@ -1129,7 +1176,7 @@ Fields:
|
|
|
1129
1176
|
subject: Type.String({ description: "Brief actionable title for the task" }),
|
|
1130
1177
|
description: Type.String({ description: "Detailed description of what needs to be done" }),
|
|
1131
1178
|
}),
|
|
1132
|
-
execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
1179
|
+
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
1133
1180
|
const entry = taskStore.create(params.subject, params.description);
|
|
1134
1181
|
pi.events.emit("tasks:created", {
|
|
1135
1182
|
taskId: entry.id,
|
|
@@ -1137,13 +1184,13 @@ Fields:
|
|
|
1137
1184
|
description: entry.description,
|
|
1138
1185
|
status: entry.status,
|
|
1139
1186
|
});
|
|
1187
|
+
const worker = await ensureAutoTaskWorkerLoop(taskStore);
|
|
1140
1188
|
widget.update();
|
|
1141
1189
|
|
|
1142
|
-
const
|
|
1143
|
-
|
|
1144
|
-
? `\n(${pending} pending tasks — consider creating a worker loop: LoopCreate trigger='tasks:created' recurring: true maxFires: 30 prompt='Run TaskList, pick next pending task, mark it in_progress, implement it, run validation, complete it. If no pending tasks remain, call LoopDelete on your own loop ID.')`
|
|
1190
|
+
const autoLoopMsg = worker.created && worker.entry
|
|
1191
|
+
? `\nWorker loop #${worker.entry.id} auto-created`
|
|
1145
1192
|
: "";
|
|
1146
|
-
return Promise.resolve(textResult(`Task #${entry.id} created: ${entry.subject}${
|
|
1193
|
+
return Promise.resolve(textResult(`Task #${entry.id} created: ${entry.subject}${autoLoopMsg}`));
|
|
1147
1194
|
},
|
|
1148
1195
|
});
|
|
1149
1196
|
|