pi-kot 0.1.38 → 0.1.39

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.
Files changed (114) hide show
  1. package/README.md +68 -104
  2. package/dist/client/assets/index-B959AkDe.css +1 -0
  3. package/dist/client/assets/index-BH5vWV2p.js +192 -0
  4. package/dist/client/assets/index-BH5vWV2p.js.map +1 -0
  5. package/dist/client/assets/{vendor-icons-B8pSAnO8.js → vendor-icons-xTgSApeH.js} +2 -2
  6. package/dist/client/assets/vendor-icons-xTgSApeH.js.map +1 -0
  7. package/dist/client/assets/{vendor-markdown-BHwes4Q7.js → vendor-markdown-DUXj0nma.js} +2 -2
  8. package/dist/client/assets/{vendor-markdown-BHwes4Q7.js.map → vendor-markdown-DUXj0nma.js.map} +1 -1
  9. package/dist/client/assets/{vendor-prism-ChBCet0U.js → vendor-prism-tzddbd4Y.js} +2 -2
  10. package/dist/client/assets/{vendor-prism-ChBCet0U.js.map → vendor-prism-tzddbd4Y.js.map} +1 -1
  11. package/dist/client/index.html +5 -5
  12. package/dist/server/ask-user-question/plan-review-registry.d.ts +49 -0
  13. package/dist/server/ask-user-question/plan-review-registry.d.ts.map +1 -0
  14. package/dist/server/ask-user-question/plan-review-registry.js +179 -0
  15. package/dist/server/ask-user-question/plan-review-registry.js.map +1 -0
  16. package/dist/server/ask-user-question/plannotator-registry.d.ts +49 -0
  17. package/dist/server/ask-user-question/plannotator-registry.d.ts.map +1 -0
  18. package/dist/server/ask-user-question/plannotator-registry.js +179 -0
  19. package/dist/server/ask-user-question/plannotator-registry.js.map +1 -0
  20. package/dist/server/ask-user-question/plannotator-submit-plan-tool.d.ts +6 -0
  21. package/dist/server/ask-user-question/plannotator-submit-plan-tool.d.ts.map +1 -0
  22. package/dist/server/ask-user-question/plannotator-submit-plan-tool.js +124 -0
  23. package/dist/server/ask-user-question/plannotator-submit-plan-tool.js.map +1 -0
  24. package/dist/server/ask-user-question/plannotator-submit-plan.test.d.ts +2 -0
  25. package/dist/server/ask-user-question/plannotator-submit-plan.test.d.ts.map +1 -0
  26. package/dist/server/ask-user-question/plannotator-submit-plan.test.js +62 -0
  27. package/dist/server/ask-user-question/plannotator-submit-plan.test.js.map +1 -0
  28. package/dist/server/ask-user-question/submit-plan-tool.d.ts +4 -0
  29. package/dist/server/ask-user-question/submit-plan-tool.d.ts.map +1 -0
  30. package/dist/server/ask-user-question/submit-plan-tool.js +120 -0
  31. package/dist/server/ask-user-question/submit-plan-tool.js.map +1 -0
  32. package/dist/server/ask-user-question/submit-plan.test.d.ts +2 -0
  33. package/dist/server/ask-user-question/submit-plan.test.d.ts.map +1 -0
  34. package/dist/server/ask-user-question/submit-plan.test.js +62 -0
  35. package/dist/server/ask-user-question/submit-plan.test.js.map +1 -0
  36. package/dist/server/event-stream.d.ts +8 -0
  37. package/dist/server/event-stream.d.ts.map +1 -1
  38. package/dist/server/event-stream.js +81 -0
  39. package/dist/server/event-stream.js.map +1 -1
  40. package/dist/server/extension-manager.d.ts.map +1 -1
  41. package/dist/server/extension-manager.js +0 -10
  42. package/dist/server/extension-manager.js.map +1 -1
  43. package/dist/server/extension-ui-bridge.d.ts +6 -0
  44. package/dist/server/extension-ui-bridge.d.ts.map +1 -1
  45. package/dist/server/extension-ui-bridge.js +65 -4
  46. package/dist/server/extension-ui-bridge.js.map +1 -1
  47. package/dist/server/extension-ui-bridge.test.d.ts +2 -0
  48. package/dist/server/extension-ui-bridge.test.d.ts.map +1 -0
  49. package/dist/server/extension-ui-bridge.test.js +40 -0
  50. package/dist/server/extension-ui-bridge.test.js.map +1 -0
  51. package/dist/server/index.d.ts.map +1 -1
  52. package/dist/server/index.js +17 -0
  53. package/dist/server/index.js.map +1 -1
  54. package/dist/server/path-refs.d.ts +1 -0
  55. package/dist/server/path-refs.d.ts.map +1 -1
  56. package/dist/server/path-refs.js +29 -2
  57. package/dist/server/path-refs.js.map +1 -1
  58. package/dist/server/path-refs.test.js +37 -0
  59. package/dist/server/path-refs.test.js.map +1 -1
  60. package/dist/server/plan-mode-extension.d.ts +10 -0
  61. package/dist/server/plan-mode-extension.d.ts.map +1 -0
  62. package/dist/server/plan-mode-extension.js +80 -0
  63. package/dist/server/plan-mode-extension.js.map +1 -0
  64. package/dist/server/plan-mode-extension.test.d.ts +2 -0
  65. package/dist/server/plan-mode-extension.test.d.ts.map +1 -0
  66. package/dist/server/plan-mode-extension.test.js +99 -0
  67. package/dist/server/plan-mode-extension.test.js.map +1 -0
  68. package/dist/server/routes/artifacts.d.ts +10 -0
  69. package/dist/server/routes/artifacts.d.ts.map +1 -1
  70. package/dist/server/routes/artifacts.js +102 -73
  71. package/dist/server/routes/artifacts.js.map +1 -1
  72. package/dist/server/routes/artifacts.test.d.ts +2 -0
  73. package/dist/server/routes/artifacts.test.d.ts.map +1 -0
  74. package/dist/server/routes/artifacts.test.js +144 -0
  75. package/dist/server/routes/artifacts.test.js.map +1 -0
  76. package/dist/server/routes/auth.d.ts.map +1 -1
  77. package/dist/server/routes/auth.js +17 -4
  78. package/dist/server/routes/auth.js.map +1 -1
  79. package/dist/server/routes/plan-review.d.ts +3 -0
  80. package/dist/server/routes/plan-review.d.ts.map +1 -0
  81. package/dist/server/routes/plan-review.js +149 -0
  82. package/dist/server/routes/plan-review.js.map +1 -0
  83. package/dist/server/routes/plan-review.test.d.ts +2 -0
  84. package/dist/server/routes/plan-review.test.d.ts.map +1 -0
  85. package/dist/server/routes/plan-review.test.js +68 -0
  86. package/dist/server/routes/plan-review.test.js.map +1 -0
  87. package/dist/server/routes/skills.d.ts.map +1 -1
  88. package/dist/server/routes/skills.js +52 -3
  89. package/dist/server/routes/skills.js.map +1 -1
  90. package/dist/server/session-store.d.ts +2 -0
  91. package/dist/server/session-store.d.ts.map +1 -1
  92. package/dist/server/session-store.js +21 -1
  93. package/dist/server/session-store.js.map +1 -1
  94. package/dist/server/skill-policy.d.ts +10 -3
  95. package/dist/server/skill-policy.d.ts.map +1 -1
  96. package/dist/server/skill-policy.js +31 -6
  97. package/dist/server/skill-policy.js.map +1 -1
  98. package/dist/server/skill-policy.test.d.ts +2 -0
  99. package/dist/server/skill-policy.test.d.ts.map +1 -0
  100. package/dist/server/skill-policy.test.js +102 -0
  101. package/dist/server/skill-policy.test.js.map +1 -0
  102. package/dist/server/ui-settings-store.d.ts +0 -2
  103. package/dist/server/ui-settings-store.d.ts.map +1 -1
  104. package/dist/server/ui-settings-store.js +1 -5
  105. package/dist/server/ui-settings-store.js.map +1 -1
  106. package/package.json +4 -4
  107. package/dist/client/assets/index-DczdsIBb.css +0 -1
  108. package/dist/client/assets/index-DsAokEBF.js +0 -191
  109. package/dist/client/assets/index-DsAokEBF.js.map +0 -1
  110. package/dist/client/assets/vendor-icons-B8pSAnO8.js.map +0 -1
  111. package/dist/server/file-watcher.d.ts +0 -16
  112. package/dist/server/file-watcher.d.ts.map +0 -1
  113. package/dist/server/file-watcher.js +0 -84
  114. package/dist/server/file-watcher.js.map +0 -1
@@ -8,17 +8,17 @@
8
8
  <link rel="preconnect" href="https://fonts.googleapis.com" />
9
9
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
10
10
  <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+Mono:wght@400;500;600;700&display=swap" rel="stylesheet" />
11
- <script type="module" crossorigin src="/assets/index-DsAokEBF.js"></script>
11
+ <script type="module" crossorigin src="/assets/index-BH5vWV2p.js"></script>
12
12
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-QTnfLwEv.js">
13
- <link rel="modulepreload" crossorigin href="/assets/vendor-icons-B8pSAnO8.js">
14
- <link rel="modulepreload" crossorigin href="/assets/vendor-prism-ChBCet0U.js">
13
+ <link rel="modulepreload" crossorigin href="/assets/vendor-icons-xTgSApeH.js">
14
+ <link rel="modulepreload" crossorigin href="/assets/vendor-prism-tzddbd4Y.js">
15
15
  <link rel="modulepreload" crossorigin href="/assets/vendor-katex-4z5K3dyr.js">
16
- <link rel="modulepreload" crossorigin href="/assets/vendor-markdown-BHwes4Q7.js">
16
+ <link rel="modulepreload" crossorigin href="/assets/vendor-markdown-DUXj0nma.js">
17
17
  <link rel="modulepreload" crossorigin href="/assets/vendor-codemirror-BB16Y9B-.js">
18
18
  <link rel="modulepreload" crossorigin href="/assets/vendor-xterm-DXwh06H3.js">
19
19
  <link rel="stylesheet" crossorigin href="/assets/vendor-katex-CYlHEDRF.css">
20
20
  <link rel="stylesheet" crossorigin href="/assets/vendor-xterm-BrP-ENHg.css">
21
- <link rel="stylesheet" crossorigin href="/assets/index-DczdsIBb.css">
21
+ <link rel="stylesheet" crossorigin href="/assets/index-B959AkDe.css">
22
22
  </head>
23
23
  <body>
24
24
  <div id="root"></div>
@@ -0,0 +1,49 @@
1
+ export interface PendingPlanReview {
2
+ requestId: string;
3
+ sessionId: string;
4
+ planFilePath: string;
5
+ planContent: string;
6
+ cwd: string;
7
+ createdAt: Date;
8
+ }
9
+ export interface PlanReviewDecision {
10
+ approved: boolean;
11
+ feedback?: string;
12
+ updatedContent?: string;
13
+ }
14
+ export interface PlanReviewToolResult {
15
+ content: Array<{
16
+ type: "text";
17
+ text: string;
18
+ }>;
19
+ details: Record<string, unknown>;
20
+ }
21
+ export type PlanReviewEvent = {
22
+ type: "plan_review_requested";
23
+ sessionId: string;
24
+ requestId: string;
25
+ planFilePath: string;
26
+ planContent: string;
27
+ } | {
28
+ type: "plan_review_resolved";
29
+ sessionId: string;
30
+ requestId: string;
31
+ approved: boolean;
32
+ reason: "answered" | "cancelled" | "aborted" | "superseded";
33
+ };
34
+ type Listener = (event: PlanReviewEvent) => void;
35
+ export declare function subscribePlanReview(fn: Listener): () => void;
36
+ export declare function registerPendingPlanReview(args: {
37
+ sessionId: string;
38
+ planFilePath: string;
39
+ planContent: string;
40
+ cwd: string;
41
+ signal?: AbortSignal;
42
+ }): {
43
+ requestId: string;
44
+ result: Promise<PlanReviewToolResult>;
45
+ };
46
+ export declare function resolvePendingPlanReview(requestId: string, expectedSessionId: string, decision: PlanReviewDecision): Promise<boolean>;
47
+ export declare function getPendingPlanReviewsForSession(sessionId: string): PendingPlanReview[];
48
+ export {};
49
+ //# sourceMappingURL=plan-review-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-review-registry.d.ts","sourceRoot":"","sources":["../../src/ask-user-question/plan-review-registry.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,MAAM,eAAe,GACvB;IACE,IAAI,EAAE,uBAAuB,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB,GACD;IACE,IAAI,EAAE,sBAAsB,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,SAAS,GAAG,YAAY,CAAC;CAC7D,CAAC;AASN,KAAK,QAAQ,GAAG,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;AAGjD,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,GAAG,MAAM,IAAI,CAG5D;AAYD,wBAAgB,yBAAyB,CAAC,IAAI,EAAE;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAA;CAAE,CAwE/D;AASD,wBAAsB,wBAAwB,CAC5C,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,MAAM,EACzB,QAAQ,EAAE,kBAAkB,GAC3B,OAAO,CAAC,OAAO,CAAC,CAkElB;AAED,wBAAgB,+BAA+B,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAetF"}
@@ -0,0 +1,179 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { resolve } from "node:path";
3
+ import { writeFile } from "node:fs/promises";
4
+ const byRequestId = new Map();
5
+ const bySessionId = new Map();
6
+ const listeners = new Set();
7
+ export function subscribePlanReview(fn) {
8
+ listeners.add(fn);
9
+ return () => listeners.delete(fn);
10
+ }
11
+ function notify(event) {
12
+ for (const fn of listeners) {
13
+ try {
14
+ fn(event);
15
+ }
16
+ catch {
17
+ // best-effort
18
+ }
19
+ }
20
+ }
21
+ export function registerPendingPlanReview(args) {
22
+ const requestId = randomUUID();
23
+ // If there is already a pending review for this session, supersede it
24
+ const existingId = bySessionId.get(args.sessionId);
25
+ if (existingId !== undefined) {
26
+ const existing = byRequestId.get(existingId);
27
+ if (existing !== undefined) {
28
+ byRequestId.delete(existingId);
29
+ bySessionId.delete(args.sessionId);
30
+ existing.resolve({
31
+ content: [{ type: "text", text: "Replaced by a new plan review submission." }],
32
+ details: { approved: false, cancelled: true, error: "superseded" },
33
+ });
34
+ notify({
35
+ type: "plan_review_resolved",
36
+ sessionId: args.sessionId,
37
+ requestId: existingId,
38
+ approved: false,
39
+ reason: "superseded",
40
+ });
41
+ }
42
+ }
43
+ let resolveFn;
44
+ const result = new Promise((resolve) => {
45
+ resolveFn = resolve;
46
+ });
47
+ const entry = {
48
+ requestId,
49
+ sessionId: args.sessionId,
50
+ planFilePath: args.planFilePath,
51
+ planContent: args.planContent,
52
+ cwd: args.cwd,
53
+ createdAt: new Date(),
54
+ resolve: resolveFn,
55
+ };
56
+ byRequestId.set(requestId, entry);
57
+ bySessionId.set(args.sessionId, requestId);
58
+ if (args.signal !== undefined) {
59
+ const onAbort = () => {
60
+ if (byRequestId.has(requestId)) {
61
+ removeEntry(requestId);
62
+ notify({
63
+ type: "plan_review_resolved",
64
+ sessionId: args.sessionId,
65
+ requestId,
66
+ approved: false,
67
+ reason: "aborted",
68
+ });
69
+ resolveFn({
70
+ content: [{ type: "text", text: "The plan review was cancelled or the agent was aborted." }],
71
+ details: { approved: false, cancelled: true, error: "aborted" },
72
+ });
73
+ }
74
+ };
75
+ if (args.signal.aborted)
76
+ onAbort();
77
+ else
78
+ args.signal.addEventListener("abort", onAbort, { once: true });
79
+ }
80
+ notify({
81
+ type: "plan_review_requested",
82
+ sessionId: args.sessionId,
83
+ requestId,
84
+ planFilePath: args.planFilePath,
85
+ planContent: args.planContent,
86
+ });
87
+ return { requestId, result };
88
+ }
89
+ function removeEntry(requestId) {
90
+ const e = byRequestId.get(requestId);
91
+ if (e === undefined)
92
+ return;
93
+ byRequestId.delete(requestId);
94
+ bySessionId.delete(e.sessionId);
95
+ }
96
+ export async function resolvePendingPlanReview(requestId, expectedSessionId, decision) {
97
+ const e = byRequestId.get(requestId);
98
+ if (e === undefined)
99
+ return false;
100
+ if (e.sessionId !== expectedSessionId)
101
+ return false;
102
+ removeEntry(requestId);
103
+ // If the user edited the plan directly before deciding, save changes to disk
104
+ if (typeof decision.updatedContent === "string" && decision.updatedContent.length > 0) {
105
+ try {
106
+ const fullPath = resolve(e.cwd, e.planFilePath);
107
+ await writeFile(fullPath, decision.updatedContent, "utf-8");
108
+ }
109
+ catch (err) {
110
+ console.error(`Failed to save updated plan to ${e.planFilePath}:`, err);
111
+ }
112
+ }
113
+ notify({
114
+ type: "plan_review_resolved",
115
+ sessionId: e.sessionId,
116
+ requestId,
117
+ approved: decision.approved,
118
+ reason: "answered",
119
+ });
120
+ const doneMsg = "After completing each step, include [DONE:n] in your response where n is the step number.";
121
+ const feedback = decision.feedback?.trim();
122
+ if (decision.approved) {
123
+ if (feedback) {
124
+ e.resolve({
125
+ content: [
126
+ {
127
+ type: "text",
128
+ text: `Plan approved with notes! You now have full tool access (read, bash, edit, write). Execute the plan in ${e.planFilePath}. ${doneMsg}\n\n## Implementation Notes\n\nThe user approved your plan but added the following notes to consider during implementation:\n\n${feedback}\n\nProceed with implementation, incorporating these notes where applicable.`,
129
+ },
130
+ ],
131
+ details: { approved: true, feedback },
132
+ });
133
+ }
134
+ else {
135
+ e.resolve({
136
+ content: [
137
+ {
138
+ type: "text",
139
+ text: `Plan approved. You now have full tool access (read, bash, edit, write). Execute the plan in ${e.planFilePath}. ${doneMsg}`,
140
+ },
141
+ ],
142
+ details: { approved: true },
143
+ });
144
+ }
145
+ }
146
+ else {
147
+ const feedbackText = feedback ||
148
+ "The user requested revisions to this plan. Please review your draft, address any questions, and update the plan file before resubmitting.";
149
+ e.resolve({
150
+ content: [
151
+ {
152
+ type: "text",
153
+ text: `YOUR PLAN WAS NOT APPROVED.\n\nYou MUST revise the plan to address ALL of the feedback below before calling submit_plan again.\n\nRules:\n- Your plan is saved at: ${e.planFilePath}\n You can edit this file to make targeted changes, then pass its path to submit_plan.\n- Do not resubmit the same plan unchanged.\n- Do NOT change the plan title (first # heading) unless the user explicitly asks you to.\n\n${feedbackText}`,
154
+ },
155
+ ],
156
+ details: { approved: false, feedback: feedbackText },
157
+ });
158
+ }
159
+ return true;
160
+ }
161
+ export function getPendingPlanReviewsForSession(sessionId) {
162
+ const id = bySessionId.get(sessionId);
163
+ if (id === undefined)
164
+ return [];
165
+ const e = byRequestId.get(id);
166
+ if (e === undefined)
167
+ return [];
168
+ return [
169
+ {
170
+ requestId: e.requestId,
171
+ sessionId: e.sessionId,
172
+ planFilePath: e.planFilePath,
173
+ planContent: e.planContent,
174
+ cwd: e.cwd,
175
+ createdAt: e.createdAt,
176
+ },
177
+ ];
178
+ }
179
+ //# sourceMappingURL=plan-review-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-review-registry.js","sourceRoot":"","sources":["../../src/ask-user-question/plan-review-registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ export interface PendingPlanReview {
2
+ requestId: string;
3
+ sessionId: string;
4
+ planFilePath: string;
5
+ planContent: string;
6
+ cwd: string;
7
+ createdAt: Date;
8
+ }
9
+ export interface PlanReviewDecision {
10
+ approved: boolean;
11
+ feedback?: string;
12
+ updatedContent?: string;
13
+ }
14
+ export interface PlanReviewToolResult {
15
+ content: Array<{
16
+ type: "text";
17
+ text: string;
18
+ }>;
19
+ details: Record<string, unknown>;
20
+ }
21
+ export type PlanReviewEvent = {
22
+ type: "plannotator_plan_review_requested";
23
+ sessionId: string;
24
+ requestId: string;
25
+ planFilePath: string;
26
+ planContent: string;
27
+ } | {
28
+ type: "plannotator_plan_review_resolved";
29
+ sessionId: string;
30
+ requestId: string;
31
+ approved: boolean;
32
+ reason: "answered" | "cancelled" | "aborted" | "superseded";
33
+ };
34
+ type Listener = (event: PlanReviewEvent) => void;
35
+ export declare function subscribePlanReview(fn: Listener): () => void;
36
+ export declare function registerPendingPlanReview(args: {
37
+ sessionId: string;
38
+ planFilePath: string;
39
+ planContent: string;
40
+ cwd: string;
41
+ signal?: AbortSignal;
42
+ }): {
43
+ requestId: string;
44
+ result: Promise<PlanReviewToolResult>;
45
+ };
46
+ export declare function resolvePendingPlanReview(requestId: string, expectedSessionId: string, decision: PlanReviewDecision): Promise<boolean>;
47
+ export declare function getPendingPlanReviewsForSession(sessionId: string): PendingPlanReview[];
48
+ export {};
49
+ //# sourceMappingURL=plannotator-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plannotator-registry.d.ts","sourceRoot":"","sources":["../../src/ask-user-question/plannotator-registry.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,MAAM,eAAe,GACvB;IACE,IAAI,EAAE,mCAAmC,CAAC;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB,GACD;IACE,IAAI,EAAE,kCAAkC,CAAC;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,SAAS,GAAG,YAAY,CAAC;CAC7D,CAAC;AASN,KAAK,QAAQ,GAAG,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;AAGjD,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,GAAG,MAAM,IAAI,CAG5D;AAYD,wBAAgB,yBAAyB,CAAC,IAAI,EAAE;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAA;CAAE,CAwE/D;AASD,wBAAsB,wBAAwB,CAC5C,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,MAAM,EACzB,QAAQ,EAAE,kBAAkB,GAC3B,OAAO,CAAC,OAAO,CAAC,CAkElB;AAED,wBAAgB,+BAA+B,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAetF"}
@@ -0,0 +1,179 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { resolve } from "node:path";
3
+ import { writeFile } from "node:fs/promises";
4
+ const byRequestId = new Map();
5
+ const bySessionId = new Map();
6
+ const listeners = new Set();
7
+ export function subscribePlanReview(fn) {
8
+ listeners.add(fn);
9
+ return () => listeners.delete(fn);
10
+ }
11
+ function notify(event) {
12
+ for (const fn of listeners) {
13
+ try {
14
+ fn(event);
15
+ }
16
+ catch {
17
+ // best-effort
18
+ }
19
+ }
20
+ }
21
+ export function registerPendingPlanReview(args) {
22
+ const requestId = randomUUID();
23
+ // If there is already a pending review for this session, supersede it
24
+ const existingId = bySessionId.get(args.sessionId);
25
+ if (existingId !== undefined) {
26
+ const existing = byRequestId.get(existingId);
27
+ if (existing !== undefined) {
28
+ byRequestId.delete(existingId);
29
+ bySessionId.delete(args.sessionId);
30
+ existing.resolve({
31
+ content: [{ type: "text", text: "Replaced by a new plan review submission." }],
32
+ details: { approved: false, cancelled: true, error: "superseded" },
33
+ });
34
+ notify({
35
+ type: "plannotator_plan_review_resolved",
36
+ sessionId: args.sessionId,
37
+ requestId: existingId,
38
+ approved: false,
39
+ reason: "superseded",
40
+ });
41
+ }
42
+ }
43
+ let resolveFn;
44
+ const result = new Promise((resolve) => {
45
+ resolveFn = resolve;
46
+ });
47
+ const entry = {
48
+ requestId,
49
+ sessionId: args.sessionId,
50
+ planFilePath: args.planFilePath,
51
+ planContent: args.planContent,
52
+ cwd: args.cwd,
53
+ createdAt: new Date(),
54
+ resolve: resolveFn,
55
+ };
56
+ byRequestId.set(requestId, entry);
57
+ bySessionId.set(args.sessionId, requestId);
58
+ if (args.signal !== undefined) {
59
+ const onAbort = () => {
60
+ if (byRequestId.has(requestId)) {
61
+ removeEntry(requestId);
62
+ notify({
63
+ type: "plannotator_plan_review_resolved",
64
+ sessionId: args.sessionId,
65
+ requestId,
66
+ approved: false,
67
+ reason: "aborted",
68
+ });
69
+ resolveFn({
70
+ content: [{ type: "text", text: "The plan review was cancelled or the agent was aborted." }],
71
+ details: { approved: false, cancelled: true, error: "aborted" },
72
+ });
73
+ }
74
+ };
75
+ if (args.signal.aborted)
76
+ onAbort();
77
+ else
78
+ args.signal.addEventListener("abort", onAbort, { once: true });
79
+ }
80
+ notify({
81
+ type: "plannotator_plan_review_requested",
82
+ sessionId: args.sessionId,
83
+ requestId,
84
+ planFilePath: args.planFilePath,
85
+ planContent: args.planContent,
86
+ });
87
+ return { requestId, result };
88
+ }
89
+ function removeEntry(requestId) {
90
+ const e = byRequestId.get(requestId);
91
+ if (e === undefined)
92
+ return;
93
+ byRequestId.delete(requestId);
94
+ bySessionId.delete(e.sessionId);
95
+ }
96
+ export async function resolvePendingPlanReview(requestId, expectedSessionId, decision) {
97
+ const e = byRequestId.get(requestId);
98
+ if (e === undefined)
99
+ return false;
100
+ if (e.sessionId !== expectedSessionId)
101
+ return false;
102
+ removeEntry(requestId);
103
+ // If the user edited the plan directly before deciding, save changes to disk
104
+ if (typeof decision.updatedContent === "string" && decision.updatedContent.length > 0) {
105
+ try {
106
+ const fullPath = resolve(e.cwd, e.planFilePath);
107
+ await writeFile(fullPath, decision.updatedContent, "utf-8");
108
+ }
109
+ catch (err) {
110
+ console.error(`Failed to save updated plan to ${e.planFilePath}:`, err);
111
+ }
112
+ }
113
+ notify({
114
+ type: "plannotator_plan_review_resolved",
115
+ sessionId: e.sessionId,
116
+ requestId,
117
+ approved: decision.approved,
118
+ reason: "answered",
119
+ });
120
+ const doneMsg = "After completing each step, include [DONE:n] in your response where n is the step number.";
121
+ const feedback = decision.feedback?.trim();
122
+ if (decision.approved) {
123
+ if (feedback) {
124
+ e.resolve({
125
+ content: [
126
+ {
127
+ type: "text",
128
+ text: `Plan approved with notes! You now have full tool access (read, bash, edit, write). Execute the plan in ${e.planFilePath}. ${doneMsg}\n\n## Implementation Notes\n\nThe user approved your plan but added the following notes to consider during implementation:\n\n${feedback}\n\nProceed with implementation, incorporating these notes where applicable.`,
129
+ },
130
+ ],
131
+ details: { approved: true, feedback },
132
+ });
133
+ }
134
+ else {
135
+ e.resolve({
136
+ content: [
137
+ {
138
+ type: "text",
139
+ text: `Plan approved. You now have full tool access (read, bash, edit, write). Execute the plan in ${e.planFilePath}. ${doneMsg}`,
140
+ },
141
+ ],
142
+ details: { approved: true },
143
+ });
144
+ }
145
+ }
146
+ else {
147
+ const feedbackText = feedback ||
148
+ "The user requested revisions to this plan. Please review your draft, address any questions, and update the plan file before resubmitting.";
149
+ e.resolve({
150
+ content: [
151
+ {
152
+ type: "text",
153
+ text: `YOUR PLAN WAS NOT APPROVED.\n\nYou MUST revise the plan to address ALL of the feedback below before calling plannotator_submit_plan again.\n\nRules:\n- Your plan is saved at: ${e.planFilePath}\n You can edit this file to make targeted changes, then pass its path to plannotator_submit_plan.\n- Do not resubmit the same plan unchanged.\n- Do NOT change the plan title (first # heading) unless the user explicitly asks you to.\n\n${feedbackText}`,
154
+ },
155
+ ],
156
+ details: { approved: false, feedback: feedbackText },
157
+ });
158
+ }
159
+ return true;
160
+ }
161
+ export function getPendingPlanReviewsForSession(sessionId) {
162
+ const id = bySessionId.get(sessionId);
163
+ if (id === undefined)
164
+ return [];
165
+ const e = byRequestId.get(id);
166
+ if (e === undefined)
167
+ return [];
168
+ return [
169
+ {
170
+ requestId: e.requestId,
171
+ sessionId: e.sessionId,
172
+ planFilePath: e.planFilePath,
173
+ planContent: e.planContent,
174
+ cwd: e.cwd,
175
+ createdAt: e.createdAt,
176
+ },
177
+ ];
178
+ }
179
+ //# sourceMappingURL=plannotator-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plannotator-registry.js","sourceRoot":"","sources":["../../src/ask-user-question/plannotator-registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { ToolDefinition } from "@earendil-works/pi-coding-agent";
2
+ export declare const PLANNOTATOR_SUBMIT_PLAN_TOOL_NAME = "plannotator_submit_plan";
3
+ export declare const SUBMIT_PLAN_TOOL_NAME = "submit_plan";
4
+ export declare function createSubmitPlanTool(sessionId: string, toolName?: string): ToolDefinition;
5
+ export declare function createPlannotatorSubmitPlanTool(sessionId: string): ToolDefinition;
6
+ //# sourceMappingURL=plannotator-submit-plan-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plannotator-submit-plan-tool.d.ts","sourceRoot":"","sources":["../../src/ask-user-question/plannotator-submit-plan-tool.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAGtE,eAAO,MAAM,iCAAiC,4BAA4B,CAAC;AAC3E,eAAO,MAAM,qBAAqB,gBAAgB,CAAC;AASnD,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,SAAwB,GAAG,cAAc,CAkHxG;AAED,wBAAgB,+BAA+B,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,CAEjF"}
@@ -0,0 +1,124 @@
1
+ import { existsSync, readFileSync, statSync } from "node:fs";
2
+ import { isAbsolute, normalize, relative, resolve } from "node:path";
3
+ import { registerPendingPlanReview } from "./plannotator-registry.js";
4
+ export const PLANNOTATOR_SUBMIT_PLAN_TOOL_NAME = "plannotator_submit_plan";
5
+ export const SUBMIT_PLAN_TOOL_NAME = "submit_plan";
6
+ function isPlanWritePathAllowed(filePath, cwd) {
7
+ if (!/\.(?:md|mdx)$/i.test(filePath))
8
+ return false;
9
+ const target = isAbsolute(filePath) ? normalize(filePath) : resolve(cwd, filePath);
10
+ const rel = relative(cwd, target);
11
+ return !rel.startsWith("..") && !isAbsolute(rel);
12
+ }
13
+ export function createSubmitPlanTool(sessionId, toolName = SUBMIT_PLAN_TOOL_NAME) {
14
+ return {
15
+ name: toolName,
16
+ label: "Submit Plan",
17
+ description: "Submit your implementation plan for user review. " +
18
+ "Call this after drafting your plan as a markdown file anywhere inside the working directory. " +
19
+ "Pass the path to the plan file (e.g. PLAN.md or plans/auth.md). " +
20
+ "The user will review the plan in a native side panel and can edit, approve, or request revisions. " +
21
+ "If revisions are requested, edit the same file in place, then call this tool again.",
22
+ parameters: {
23
+ type: "object",
24
+ additionalProperties: false,
25
+ required: ["filePath"],
26
+ properties: {
27
+ filePath: {
28
+ type: "string",
29
+ description: "Path to the markdown plan file, relative to the working directory. Must end in .md or .mdx and resolve inside cwd.",
30
+ },
31
+ },
32
+ },
33
+ async execute(_toolCallId, params, signal, _onUpdate, ctx) {
34
+ const inputPath = params?.filePath?.trim();
35
+ if (!inputPath) {
36
+ return {
37
+ content: [
38
+ {
39
+ type: "text",
40
+ text: `Error: ${toolName} requires a filePath argument pointing to your markdown plan file (e.g. "PLAN.md" or "plans/auth.md").`,
41
+ },
42
+ ],
43
+ details: { approved: false },
44
+ };
45
+ }
46
+ const cwd = ctx?.cwd ?? process.cwd();
47
+ if (!isPlanWritePathAllowed(inputPath, cwd)) {
48
+ return {
49
+ content: [
50
+ {
51
+ type: "text",
52
+ text: `Error: plan file must be a markdown file (.md or .mdx) inside the working directory. Rejected: ${inputPath}`,
53
+ },
54
+ ],
55
+ details: { approved: false },
56
+ };
57
+ }
58
+ const fullPath = resolve(cwd, inputPath);
59
+ try {
60
+ if (!existsSync(fullPath) || !statSync(fullPath).isFile()) {
61
+ return {
62
+ content: [
63
+ {
64
+ type: "text",
65
+ text: `Error: ${inputPath} does not exist or is not a regular file. Write your plan using the write tool first, then call ${toolName} with its path.`,
66
+ },
67
+ ],
68
+ details: { approved: false },
69
+ };
70
+ }
71
+ }
72
+ catch (err) {
73
+ return {
74
+ content: [
75
+ {
76
+ type: "text",
77
+ text: `Error: cannot access ${inputPath}: ${err instanceof Error ? err.message : String(err)}`,
78
+ },
79
+ ],
80
+ details: { approved: false },
81
+ };
82
+ }
83
+ let planContent;
84
+ try {
85
+ planContent = readFileSync(fullPath, "utf-8");
86
+ }
87
+ catch (err) {
88
+ return {
89
+ content: [
90
+ {
91
+ type: "text",
92
+ text: `Error: failed to read ${inputPath}: ${err instanceof Error ? err.message : String(err)}`,
93
+ },
94
+ ],
95
+ details: { approved: false },
96
+ };
97
+ }
98
+ if (planContent.trim().length === 0) {
99
+ return {
100
+ content: [
101
+ {
102
+ type: "text",
103
+ text: `Error: ${inputPath} is empty. Write your plan first, then call ${toolName} again.`,
104
+ },
105
+ ],
106
+ details: { approved: false },
107
+ };
108
+ }
109
+ // Register with the in-memory plan review registry and wait for the user to review
110
+ const { result } = registerPendingPlanReview({
111
+ sessionId,
112
+ planFilePath: inputPath,
113
+ planContent,
114
+ cwd,
115
+ signal,
116
+ });
117
+ return await result;
118
+ },
119
+ };
120
+ }
121
+ export function createPlannotatorSubmitPlanTool(sessionId) {
122
+ return createSubmitPlanTool(sessionId, PLANNOTATOR_SUBMIT_PLAN_TOOL_NAME);
123
+ }
124
+ //# sourceMappingURL=plannotator-submit-plan-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plannotator-submit-plan-tool.js","sourceRoot":"","sources":["../../src/ask-user-question/plannotator-submit-plan-tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=plannotator-submit-plan.test.d.ts.map