clawspec 1.0.15 → 1.0.16
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/package.json +1 -1
- package/src/control/keywords.ts +18 -2
- package/src/orchestrator/service.ts +0 -20
- package/src/watchers/notifier.ts +1 -0
- package/src/utils/debug-log.ts +0 -14
package/package.json
CHANGED
package/src/control/keywords.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
|
|
1
2
|
export type ClawSpecKeywordKind =
|
|
2
3
|
| "plan"
|
|
3
4
|
| "work"
|
|
@@ -59,11 +60,26 @@ export function extractEmbeddedClawSpecKeyword(text: string): ClawSpecKeywordInt
|
|
|
59
60
|
return direct;
|
|
60
61
|
}
|
|
61
62
|
|
|
62
|
-
|
|
63
|
-
|
|
63
|
+
const lines = text.split(/\r?\n/);
|
|
64
|
+
for (const line of lines) {
|
|
65
|
+
const trimmed = line.trim();
|
|
66
|
+
if (!trimmed) continue;
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
// Try parsing the whole line first
|
|
70
|
+
const parsed = parseClawSpecKeyword(trimmed);
|
|
64
71
|
if (parsed) {
|
|
65
72
|
return parsed;
|
|
66
73
|
}
|
|
74
|
+
|
|
75
|
+
// Try each word in the line
|
|
76
|
+
const words = trimmed.split(/\s+/);
|
|
77
|
+
for (const word of words) {
|
|
78
|
+
const wordParsed = parseClawSpecKeyword(word);
|
|
79
|
+
if (wordParsed) {
|
|
80
|
+
return wordParsed;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
67
83
|
}
|
|
68
84
|
|
|
69
85
|
return null;
|
|
@@ -6,7 +6,6 @@ import type {
|
|
|
6
6
|
PluginCommandResult,
|
|
7
7
|
PluginLogger,
|
|
8
8
|
} from "openclaw/plugin-sdk";
|
|
9
|
-
import { debugLog } from "../utils/debug-log.ts";
|
|
10
9
|
import { ProjectMemoryStore } from "../memory/store.ts";
|
|
11
10
|
import { OpenSpecClient, OpenSpecCommandError } from "../openspec/cli.ts";
|
|
12
11
|
import { parseTasksFile } from "../openspec/tasks.ts";
|
|
@@ -250,9 +249,7 @@ export class ClawSpecService {
|
|
|
250
249
|
event: PromptBuildEvent,
|
|
251
250
|
ctx: PromptBuildContext,
|
|
252
251
|
): Promise<{ prependContext?: string; prependSystemContext?: string } | void> {
|
|
253
|
-
debugLog(`[handleBeforePromptBuild] prompt="${event.prompt}", trigger=${ctx.trigger}`);
|
|
254
252
|
if (!shouldHandleUserVisiblePrompt(ctx.trigger)) {
|
|
255
|
-
debugLog(`[handleBeforePromptBuild] Skipped: non-user trigger`);
|
|
256
253
|
this.logger.debug?.(
|
|
257
254
|
`[clawspec] skipping prompt injection for non-user trigger "${ctx.trigger ?? "unknown"}".`,
|
|
258
255
|
);
|
|
@@ -260,7 +257,6 @@ export class ClawSpecService {
|
|
|
260
257
|
}
|
|
261
258
|
|
|
262
259
|
const keyword = extractEmbeddedClawSpecKeyword(event.prompt);
|
|
263
|
-
debugLog(`[handleBeforePromptBuild] keyword=${keyword?.command}`);
|
|
264
260
|
if (keyword) {
|
|
265
261
|
this.logger.debug?.(
|
|
266
262
|
`[clawspec] detected control keyword "${keyword.command}" for prompt build (session=${ctx.sessionKey ?? "unknown"}).`,
|
|
@@ -320,21 +316,16 @@ export class ClawSpecService {
|
|
|
320
316
|
|
|
321
317
|
switch (keyword.kind) {
|
|
322
318
|
case "plan": {
|
|
323
|
-
debugLog(`[cs-plan] Triggered for project: ${match?.project.changeName}`);
|
|
324
319
|
if (!match?.project.repoPath || !match.project.changeName) {
|
|
325
|
-
debugLog(`[cs-plan] Missing repoPath or changeName`);
|
|
326
320
|
return this.buildPluginReplyInjection(
|
|
327
321
|
event.prompt,
|
|
328
322
|
"Select a project and create a change first with `/clawspec use <project-name>` and `/clawspec proposal <change-name> [description]`.",
|
|
329
323
|
);
|
|
330
324
|
}
|
|
331
|
-
debugLog(`[cs-plan] Calling startVisiblePlanningSync`);
|
|
332
325
|
const planningSync = await this.startVisiblePlanningSync(match.channelKey, match.project, ctx, event.prompt, "apply");
|
|
333
326
|
if ("prependContext" in planningSync || "prependSystemContext" in planningSync) {
|
|
334
|
-
debugLog(`[cs-plan] Returning prompt injection`);
|
|
335
327
|
return planningSync;
|
|
336
328
|
}
|
|
337
|
-
debugLog(`[cs-plan] Returning plugin reply`);
|
|
338
329
|
return this.buildPluginReplyInjection(event.prompt, planningSync.text ?? "");
|
|
339
330
|
}
|
|
340
331
|
case "work":
|
|
@@ -767,19 +758,16 @@ export class ClawSpecService {
|
|
|
767
758
|
userPrompt: string,
|
|
768
759
|
mode: ExecutionMode,
|
|
769
760
|
): Promise<{ prependContext?: string; prependSystemContext?: string } | PluginCommandResult> {
|
|
770
|
-
debugLog(`[startVisiblePlanningSync] Called for ${project.changeName}`);
|
|
771
761
|
this.logger.info(`[clawspec] startVisiblePlanningSync called for ${project.changeName}`);
|
|
772
762
|
void project;
|
|
773
763
|
void mode;
|
|
774
764
|
|
|
775
765
|
const prepared = await this.preparePlanningSync(channelKey);
|
|
776
766
|
if ("result" in prepared) {
|
|
777
|
-
debugLog(`[startVisiblePlanningSync] preparePlanningSync failed`);
|
|
778
767
|
this.logger.warn(`[clawspec] preparePlanningSync returned error: ${prepared.result.text}`);
|
|
779
768
|
return prepared.result;
|
|
780
769
|
}
|
|
781
770
|
|
|
782
|
-
debugLog(`[startVisiblePlanningSync] Updating state to planning`);
|
|
783
771
|
const startedAt = new Date().toISOString();
|
|
784
772
|
const runningProject = await this.stateStore.updateProject(channelKey, (current) => ({
|
|
785
773
|
...current,
|
|
@@ -793,7 +781,6 @@ export class ClawSpecService {
|
|
|
793
781
|
execution: undefined,
|
|
794
782
|
lastExecutionAt: startedAt,
|
|
795
783
|
}));
|
|
796
|
-
debugLog(`[startVisiblePlanningSync] State updated: status=${runningProject.status}, phase=${runningProject.phase}, sessionKey=${runningProject.boundSessionKey}`);
|
|
797
784
|
this.logger.info(`[clawspec] Project state updated: status=planning, phase=planning_sync, boundSessionKey=${runningProject.boundSessionKey}`);
|
|
798
785
|
|
|
799
786
|
return await this.buildPlanningSyncInjection(runningProject, userPrompt, prepared.instructionResults);
|
|
@@ -912,7 +899,6 @@ export class ClawSpecService {
|
|
|
912
899
|
}
|
|
913
900
|
|
|
914
901
|
async handleAgentEnd(event: AgentEndEvent, ctx: PromptBuildContext): Promise<void> {
|
|
915
|
-
debugLog(`[agent_end] Called, sessionKey=${ctx.sessionKey}`);
|
|
916
902
|
const runningProject = await this.findRunningProjectBySessionKey(ctx.sessionKey);
|
|
917
903
|
if (runningProject?.repoPath && runningProject.changeName) {
|
|
918
904
|
const project = runningProject;
|
|
@@ -977,9 +963,7 @@ export class ClawSpecService {
|
|
|
977
963
|
|
|
978
964
|
const planningProject = await this.findPlanningProjectBySessionKey(ctx.sessionKey)
|
|
979
965
|
?? await this.findPlanningProjectByContext(ctx);
|
|
980
|
-
debugLog(`[agent_end] Planning project: ${planningProject?.changeName}, status=${planningProject?.status}, phase=${planningProject?.phase}`);
|
|
981
966
|
if (planningProject) {
|
|
982
|
-
debugLog(`[agent_end] Calling finalizePlanningTurn`);
|
|
983
967
|
this.logger.info(`[clawspec] agent_end: found planning project ${planningProject.changeName}, calling finalizePlanningTurn`);
|
|
984
968
|
await this.finalizePlanningTurn(planningProject, event);
|
|
985
969
|
return;
|
|
@@ -2428,10 +2412,8 @@ export class ClawSpecService {
|
|
|
2428
2412
|
}
|
|
2429
2413
|
|
|
2430
2414
|
private async finalizePlanningTurn(project: ProjectState, event: AgentEndEvent): Promise<void> {
|
|
2431
|
-
debugLog(`[finalizePlanningTurn] Called for ${project.changeName}, success=${event.success}`);
|
|
2432
2415
|
this.logger.info(`[clawspec] finalizePlanningTurn called for ${project.changeName}, success=${event.success}`);
|
|
2433
2416
|
if (!project.repoPath || !project.changeName) {
|
|
2434
|
-
debugLog(`[finalizePlanningTurn] Skipped: missing repoPath or changeName`);
|
|
2435
2417
|
this.logger.warn(`[clawspec] finalizePlanningTurn skipped: missing repoPath or changeName`);
|
|
2436
2418
|
return;
|
|
2437
2419
|
}
|
|
@@ -2491,9 +2473,7 @@ export class ClawSpecService {
|
|
|
2491
2473
|
}
|
|
2492
2474
|
}
|
|
2493
2475
|
|
|
2494
|
-
debugLog(`[finalizePlanningTurn] Writing snapshot`);
|
|
2495
2476
|
const snapshot = await journalStore.writeSnapshot(repoStatePaths.planningJournalSnapshotFile, project.changeName, timestamp);
|
|
2496
|
-
debugLog(`[finalizePlanningTurn] Snapshot written: entryCount=${snapshot.entryCount}, lastEntryAt=${snapshot.lastEntryAt}`);
|
|
2497
2477
|
this.logger.info(`[clawspec] Planning snapshot written for ${project.changeName}: entryCount=${snapshot.entryCount}, lastEntryAt=${snapshot.lastEntryAt}`);
|
|
2498
2478
|
this.logger.info(`[clawspec] Updating project state: status=${status}, phase=${phase}, dirty=${journalDirty}`);
|
|
2499
2479
|
await this.writeLatestSummary(repoStatePaths, latestSummary);
|
package/src/watchers/notifier.ts
CHANGED
package/src/utils/debug-log.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { appendFileSync } from "node:fs";
|
|
2
|
-
import { homedir } from "node:os";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
|
|
5
|
-
const LOG_FILE = path.join(homedir(), ".openclaw", "clawspec-debug.log");
|
|
6
|
-
|
|
7
|
-
export function debugLog(message: string): void {
|
|
8
|
-
try {
|
|
9
|
-
const timestamp = new Date().toISOString();
|
|
10
|
-
appendFileSync(LOG_FILE, `${timestamp} ${message}\n`);
|
|
11
|
-
} catch {
|
|
12
|
-
// ignore
|
|
13
|
-
}
|
|
14
|
-
}
|