@forloop-cc/forloop-cli 0.2.1 → 0.2.2

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ForLoop
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -63,7 +63,7 @@ npm install -g @forloop-cc/forloop-cli
63
63
 
64
64
  ```bash
65
65
  forloop --version
66
- # Output: forloop 0.2.0
66
+ # Output: forloop 0.2.1
67
67
  ```
68
68
 
69
69
  ---
@@ -28,7 +28,7 @@ function buildSchema(options) {
28
28
  }
29
29
  function scanCommandPath(argv, globalOptions = []) {
30
30
  const globalSchema = buildSchema(globalOptions);
31
- const path6 = [];
31
+ const path3 = [];
32
32
  let i = 0;
33
33
  while (i < argv.length) {
34
34
  const arg = argv[i];
@@ -48,10 +48,10 @@ function scanCommandPath(argv, globalOptions = []) {
48
48
  i++;
49
49
  continue;
50
50
  }
51
- path6.push(arg);
51
+ path3.push(arg);
52
52
  i++;
53
53
  }
54
- return path6;
54
+ return path3;
55
55
  }
56
56
  function parseFlags(argv, options) {
57
57
  const schema = buildSchema(options);
@@ -142,727 +142,8 @@ var GLOBAL_OPTIONS = [
142
142
  { flag: "--version", description: "Print version" }
143
143
  ];
144
144
 
145
- // ../forloop-opencode-plugin-planner/plugins/capabilities/token-storage.ts
146
- import { promises as fs } from "fs";
147
- import path from "path";
148
- var getTokenPath = () => {
149
- return path.join(
150
- process.env.HOME || process.env.USERPROFILE || ".",
151
- ".config",
152
- "forloop",
153
- "tokens.json"
154
- );
155
- };
156
- async function loadTokens() {
157
- const tokenPath = getTokenPath();
158
- try {
159
- const content = await fs.readFile(tokenPath, "utf-8");
160
- return JSON.parse(content);
161
- } catch (error) {
162
- if (error.code === "ENOENT") {
163
- return {
164
- version: "1.0",
165
- note: "ForLoop API tokens - do not share",
166
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
167
- };
168
- }
169
- throw error;
170
- }
171
- }
172
- async function saveTokens(tokens) {
173
- const tokenPath = getTokenPath();
174
- const configDir = path.dirname(tokenPath);
175
- await fs.mkdir(configDir, { recursive: true });
176
- await fs.writeFile(
177
- tokenPath,
178
- JSON.stringify(tokens, null, 2),
179
- { mode: 384 }
180
- );
181
- }
182
- async function getToken(profile) {
183
- const tokens = await loadTokens();
184
- if (profile && tokens.profiles?.[profile]) {
185
- return tokens.profiles[profile];
186
- }
187
- if (tokens.default) return tokens.default;
188
- if (tokens.profiles?.["default"]) return tokens.profiles["default"];
189
- return null;
190
- }
191
- async function setToken(token, profile) {
192
- const tokens = await loadTokens();
193
- tokens.version = "1.0";
194
- tokens.note = "ForLoop API tokens - do not share";
195
- if (profile) {
196
- if (!tokens.profiles) {
197
- tokens.profiles = {};
198
- }
199
- tokens.profiles[profile] = token;
200
- } else {
201
- tokens.default = token;
202
- }
203
- tokens.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
204
- await saveTokens(tokens);
205
- }
206
- async function clearToken(profile) {
207
- const tokens = await loadTokens();
208
- if (profile) {
209
- if (tokens.profiles) {
210
- delete tokens.profiles[profile];
211
- }
212
- } else {
213
- delete tokens.default;
214
- }
215
- tokens.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
216
- await saveTokens(tokens);
217
- }
218
-
219
- // ../forloop-opencode-plugin-planner/plugins/capabilities/config.ts
220
- import fs2 from "fs";
221
- import path2 from "path";
222
- var PROD_API_URL = "https://api.forloop.cc";
223
- var DEV_API_URL = "https://api.dev.forloop.cc";
224
- var PROD_TOKENS_URL = "https://forloop.cc/profile?tab=api-tokens";
225
- var DEV_TOKENS_URL = "https://dev.forloop.cc/profile?tab=api-tokens";
226
- var readJsonFileIfExists = (filePath) => {
227
- try {
228
- if (!fs2.existsSync(filePath)) return null;
229
- const raw = fs2.readFileSync(filePath, "utf-8");
230
- return JSON.parse(raw);
231
- } catch {
232
- return null;
233
- }
234
- };
235
- var getHomeDir = () => {
236
- return process.env.HOME || process.env.USERPROFILE || "";
237
- };
238
- var getProjectConfig = () => {
239
- return readJsonFileIfExists(path2.join(process.cwd(), "opencode.json"));
240
- };
241
- var getGlobalConfig = () => {
242
- const home = getHomeDir();
243
- if (!home) return null;
244
- return readJsonFileIfExists(path2.join(home, ".config", "opencode", "config.json"));
245
- };
246
- var getNested = (obj, keys) => {
247
- let cur = obj;
248
- for (const key of keys) {
249
- if (!cur || typeof cur !== "object") return void 0;
250
- cur = cur[key];
251
- }
252
- return cur;
253
- };
254
- var isTruthy = (value) => {
255
- if (typeof value === "boolean") return value;
256
- if (typeof value === "string") return value.toLowerCase() === "true" || value === "1";
257
- return false;
258
- };
259
- var normalizeUrl = (value) => {
260
- if (typeof value !== "string") return null;
261
- const trimmed = value.trim();
262
- if (!trimmed) return null;
263
- return trimmed;
264
- };
265
- var isDevUrl = (apiUrl) => {
266
- return apiUrl.includes("api.dev.forloop.cc") || apiUrl.includes("dev.forloop.cc");
267
- };
268
- var resolveAllowDev = (projectConfig, globalConfig) => {
269
- return isTruthy(process.env.FORLOOP_ALLOW_DEV) || isTruthy(getNested(projectConfig, ["forloop", "allowDev"])) || isTruthy(getNested(globalConfig, ["forloop", "allowDev"]));
270
- };
271
- var resolveApiUrl = (projectConfig, globalConfig, allowDev) => {
272
- const envApiUrl = normalizeUrl(process.env.FORLOOP_API_URL || process.env.FORLOOP_API_BASE);
273
- if (envApiUrl) {
274
- if (isDevUrl(envApiUrl) && !allowDev) {
275
- console.warn("[ForLoop Config] Dev API URL ignored (set FORLOOP_ALLOW_DEV=true to enable)");
276
- return PROD_API_URL;
277
- }
278
- return envApiUrl;
279
- }
280
- const envName = normalizeUrl(process.env.FORLOOP_ENV);
281
- if (envName) {
282
- if (envName === "production") return PROD_API_URL;
283
- if (envName === "development") {
284
- if (!allowDev) {
285
- console.warn("[ForLoop Config] FORLOOP_ENV=development ignored (set FORLOOP_ALLOW_DEV=true to enable)");
286
- return PROD_API_URL;
287
- }
288
- return DEV_API_URL;
289
- }
290
- }
291
- const projectApiUrl = normalizeUrl(getNested(projectConfig, ["forloop", "apiUrl"]));
292
- if (projectApiUrl) {
293
- if (isDevUrl(projectApiUrl) && !allowDev) {
294
- console.warn("[ForLoop Config] Project dev API URL ignored (set forloop.allowDev=true or FORLOOP_ALLOW_DEV=true)");
295
- return PROD_API_URL;
296
- }
297
- return projectApiUrl;
298
- }
299
- const globalApiUrl = normalizeUrl(getNested(globalConfig, ["forloop", "apiUrl"]));
300
- if (globalApiUrl) {
301
- if (isDevUrl(globalApiUrl) && !allowDev) {
302
- console.warn("[ForLoop Config] Global dev API URL ignored (set forloop.allowDev=true or FORLOOP_ALLOW_DEV=true)");
303
- return PROD_API_URL;
304
- }
305
- return globalApiUrl;
306
- }
307
- return PROD_API_URL;
308
- };
309
- var detectEnvironment = (apiUrl) => {
310
- if (apiUrl.includes("dev.forloop.cc")) {
311
- return "development";
312
- }
313
- if (apiUrl.includes("api.forloop.cc")) {
314
- return "production";
315
- }
316
- return "custom";
317
- };
318
- var getConfig = () => {
319
- const projectConfig = getProjectConfig();
320
- const globalConfig = getGlobalConfig();
321
- const allowDev = resolveAllowDev(projectConfig, globalConfig);
322
- const apiUrl = resolveApiUrl(projectConfig, globalConfig, allowDev);
323
- return {
324
- apiUrl,
325
- environment: detectEnvironment(apiUrl),
326
- tokenStorage: "global",
327
- debug: process.env.FORLOOP_DEBUG === "true",
328
- allowDev
329
- };
330
- };
331
- var getTokensUrl = () => {
332
- const config = getConfig();
333
- if (config.environment === "development") return DEV_TOKENS_URL;
334
- return PROD_TOKENS_URL;
335
- };
336
- var isLambdaExecution = () => {
337
- const forced = (process.env.FORLOOP_EXECUTION_CONTEXT || "").toLowerCase();
338
- if (forced === "lambda" || forced === "aws_lambda" || forced === "aws-lambda") return true;
339
- return !!(process.env.AWS_LAMBDA_FUNCTION_NAME || process.env.AWS_EXECUTION_ENV || process.env.LAMBDA_TASK_ROOT);
340
- };
341
-
342
- // ../forloop-opencode-plugin-planner/plugins/capabilities/auth.ts
343
- function detectTokenType(token) {
344
- if (!token) return null;
345
- if (token.startsWith("floop_")) {
346
- return "api_key";
347
- }
348
- const parts = token.split(".");
349
- if (parts.length === 3 && parts.every((p) => p.length > 0)) {
350
- const base64urlRegex = /^[A-Za-z0-9_-]+$/;
351
- if (parts.every((p) => base64urlRegex.test(p))) {
352
- return "jwt";
353
- }
354
- }
355
- return null;
356
- }
357
- async function validateToken(providedToken) {
358
- const token = providedToken || await getToken();
359
- if (!token) {
360
- return {
361
- valid: false,
362
- error: "No API token configured. Please create a token at " + getTokensUrl()
363
- };
364
- }
365
- const tokenType = detectTokenType(token);
366
- if (!tokenType) {
367
- return {
368
- valid: false,
369
- error: "Unrecognized token format. Use either a ForLoop API key (floop_*) or a valid JWT token."
370
- };
371
- }
372
- if (tokenType === "jwt") {
373
- const isLambda = isLambdaExecution();
374
- if (!isLambda) {
375
- return {
376
- valid: false,
377
- error: "JWT tokens are only supported in Lambda execution. Please use a ForLoop API key (floop_*) for local execution."
378
- };
379
- }
380
- return {
381
- valid: true,
382
- token,
383
- tokenType: "jwt"
384
- };
385
- }
386
- return {
387
- valid: true,
388
- token,
389
- tokenType: "api_key"
390
- };
391
- }
392
-
393
- // ../forloop-opencode-plugin-planner/plugins/capabilities/api-client.ts
394
- var APIError = class extends Error {
395
- constructor(code, message, status) {
396
- super(message);
397
- this.code = code;
398
- this.status = status;
399
- this.name = "APIError";
400
- }
401
- };
402
- var ForLoopAPIClient = class {
403
- config;
404
- defaultHeaders;
405
- tokenType;
406
- jwtExchangePromise;
407
- constructor(config) {
408
- this.config = {
409
- timeout: 3e4,
410
- retryCount: 3,
411
- ...config
412
- };
413
- this.defaultHeaders = {
414
- "Content-Type": "application/json"
415
- };
416
- this.tokenType = detectTokenType(config.token);
417
- this.jwtExchangePromise = null;
418
- }
419
- setToken(token) {
420
- this.config.token = token;
421
- this.tokenType = detectTokenType(token);
422
- }
423
- async ensureOpencodeApiToken(endpoint) {
424
- if (this.tokenType !== "jwt") return;
425
- if (!endpoint.startsWith("/api/opencode/")) return;
426
- if (endpoint.startsWith("/api/opencode/auth/tokens")) return;
427
- if (!this.jwtExchangePromise) {
428
- this.jwtExchangePromise = this.exchangeJwtForApiToken();
429
- }
430
- const token = await this.jwtExchangePromise;
431
- this.setToken(token);
432
- }
433
- async exchangeJwtForApiToken() {
434
- const url = `${this.config.baseUrl}/api/opencode/auth/tokens`;
435
- const jwt = this.config.token;
436
- const scopes = [
437
- "sprint:read",
438
- "sprint:write",
439
- "story:read",
440
- "story:write",
441
- "story:delete",
442
- "agent:read",
443
- "agent:query",
444
- "profile:read",
445
- "organization:read",
446
- "organization:write",
447
- "organization:delete"
448
- ];
449
- const name = `lambda-planner-${Date.now()}`;
450
- const response = await fetch(url, {
451
- method: "POST",
452
- headers: {
453
- ...this.defaultHeaders,
454
- Authorization: `Bearer ${jwt}`
455
- },
456
- body: JSON.stringify({
457
- name,
458
- expiresIn: "7d",
459
- scopes
460
- }),
461
- signal: AbortSignal.timeout(this.config.timeout)
462
- });
463
- if (!response.ok) {
464
- throw await this.parseError(response);
465
- }
466
- const payload = await response.json();
467
- const token = typeof payload?.token === "string" ? payload.token.trim() : "";
468
- if (!token) {
469
- throw new APIError("invalid_token_exchange", "Token exchange returned empty token", 500);
470
- }
471
- await setToken(token);
472
- return token;
473
- }
474
- /**
475
- * Get auth headers based on token type
476
- * - JWT tokens: Authorization: Bearer <token>
477
- * - API keys: X-API-Token: <token>
478
- */
479
- getAuthHeaders() {
480
- const headers = {};
481
- if (this.tokenType === "jwt") {
482
- headers["Authorization"] = `Bearer ${this.config.token}`;
483
- } else {
484
- headers["X-API-Token"] = this.config.token;
485
- }
486
- return headers;
487
- }
488
- async request(endpoint, options = {}) {
489
- await this.ensureOpencodeApiToken(endpoint);
490
- const url = `${this.config.baseUrl}${endpoint}`;
491
- let lastError = null;
492
- for (let attempt = 1; attempt <= this.config.retryCount; attempt++) {
493
- try {
494
- const response = await fetch(url, {
495
- ...options,
496
- headers: {
497
- ...this.defaultHeaders,
498
- ...this.getAuthHeaders(),
499
- // Dynamic auth headers based on token type
500
- ...options.headers || {}
501
- },
502
- signal: AbortSignal.timeout(this.config.timeout)
503
- });
504
- if (!response.ok) {
505
- const error = await this.parseError(response);
506
- throw error;
507
- }
508
- return response.json();
509
- } catch (error) {
510
- lastError = error;
511
- if (error instanceof APIError && error.status >= 400 && error.status < 500) {
512
- throw error;
513
- }
514
- if (attempt < this.config.retryCount) {
515
- await this.sleep(Math.pow(2, attempt) * 100);
516
- }
517
- }
518
- }
519
- throw lastError || new Error("Request failed");
520
- }
521
- async parseError(response) {
522
- try {
523
- const body = await response.json();
524
- return new APIError(body.error || "UnknownError", body.message || response.statusText, response.status);
525
- } catch {
526
- return new APIError("UnknownError", response.statusText, response.status);
527
- }
528
- }
529
- sleep(ms) {
530
- return new Promise((resolve) => setTimeout(resolve, ms));
531
- }
532
- async listSprints(params) {
533
- const query = new URLSearchParams(params);
534
- const response = await this.request(`/api/opencode/sprints?${query}`);
535
- return Array.isArray(response) ? response : response.data || [];
536
- }
537
- async getSprint(id, options) {
538
- const query = new URLSearchParams({
539
- includeStories: options?.includeStories !== false ? "true" : "false",
540
- includeFiles: options?.includeFiles !== false ? "true" : "false"
541
- });
542
- return this.request(`/api/opencode/sprints/${id}?${query}`);
543
- }
544
- async createSprint(data) {
545
- return this.request("/api/opencode/sprints", {
546
- method: "POST",
547
- body: JSON.stringify(data)
548
- });
549
- }
550
- async updateSprint(id, data) {
551
- return this.request(`/api/opencode/sprints/${id}`, {
552
- method: "PUT",
553
- body: JSON.stringify(data)
554
- });
555
- }
556
- async deleteSprint(id) {
557
- await this.request(`/api/opencode/sprints/${id}`, {
558
- method: "DELETE"
559
- });
560
- }
561
- async createStory(data) {
562
- return this.request("/api/opencode/stories", {
563
- method: "POST",
564
- body: JSON.stringify(data)
565
- });
566
- }
567
- async getStory(id, options) {
568
- const params = new URLSearchParams();
569
- if (options?.includeComments) params.set("includeComments", "true");
570
- const query = params.toString() ? `?${params.toString()}` : "";
571
- return this.request(`/api/opencode/stories/${id}${query}`);
572
- }
573
- async updateStory(id, data) {
574
- return this.request(`/api/opencode/stories/${id}`, {
575
- method: "PUT",
576
- body: JSON.stringify(data)
577
- });
578
- }
579
- async deleteStory(id) {
580
- await this.request(`/api/opencode/stories/${id}`, {
581
- method: "DELETE"
582
- });
583
- }
584
- async listTemplates() {
585
- return this.request("/api/opencode/templates");
586
- }
587
- async getUserProfile() {
588
- return this.request("/api/opencode/user/profile");
589
- }
590
- async getUserQuotas() {
591
- return this.request("/api/opencode/user/quotas");
592
- }
593
- async getOrganizationQuotas(orgId) {
594
- return this.request(`/api/opencode/organization/${orgId}/quotas`);
595
- }
596
- async listOrganizations() {
597
- return this.request("/api/opencode/organizations");
598
- }
599
- async getOwnedOrganizations() {
600
- return this.request("/api/opencode/organizations/owned");
601
- }
602
- async getOrganization(id) {
603
- return this.request(`/api/opencode/organizations/${id}`);
604
- }
605
- async createOrganization(data) {
606
- return this.request("/api/opencode/organizations", {
607
- method: "POST",
608
- body: JSON.stringify(data)
609
- });
610
- }
611
- async updateOrganization(id, data) {
612
- return this.request(`/api/opencode/organizations/${id}`, {
613
- method: "PUT",
614
- body: JSON.stringify(data)
615
- });
616
- }
617
- async deleteOrganization(id) {
618
- await this.request(`/api/opencode/organizations/${id}`, {
619
- method: "DELETE"
620
- });
621
- }
622
- async chatWithAI(request) {
623
- return this.request("/api/opencode/agents/chat", {
624
- method: "POST",
625
- body: JSON.stringify(request)
626
- });
627
- }
628
- async getDeveloperStatus(sprintId) {
629
- return this.request(`/api/opencode/sprints/${sprintId}/developer-status`);
630
- }
631
- async getStorySuggestions(sprintId, storyId) {
632
- return this.request("/api/opencode/agents/suggestions", {
633
- method: "POST",
634
- body: JSON.stringify({ sprintId, storyId })
635
- });
636
- }
637
- async getAITasks(sprintId) {
638
- const query = sprintId ? new URLSearchParams({ sprintId: String(sprintId) }) : new URLSearchParams();
639
- return this.request(`/api/opencode/agents/tasks?${query}`);
640
- }
641
- async getSprintSummaries(sprintId) {
642
- return this.request(`/api/opencode/agents/summary?sprintId=${sprintId}`);
643
- }
644
- async getAgentSuggestions(request) {
645
- return this.request("/api/agents/suggestions", {
646
- method: "POST",
647
- body: JSON.stringify(request)
648
- });
649
- }
650
- async getStoryBreakdown(storyId) {
651
- return this.request(`/api/agents/stories/${storyId}/breakdown`);
652
- }
653
- async getStoryEstimate(storyId) {
654
- return this.request(`/api/agents/stories/${storyId}/estimate`);
655
- }
656
- async getConversationHistory(params) {
657
- const query = new URLSearchParams();
658
- if (params?.sprintId) query.append("sprintId", String(params.sprintId));
659
- if (params?.limit) query.append("limit", String(params.limit));
660
- return this.request(`/api/opencode/messages?${query}`);
661
- }
662
- async clearConversationHistory(params) {
663
- const query = new URLSearchParams();
664
- if (params?.sprintId) query.append("sprintId", String(params.sprintId));
665
- query.append("confirm", "true");
666
- return this.request(`/api/opencode/messages?${query}`, {
667
- method: "DELETE"
668
- });
669
- }
670
- async createPresignedUpload(data) {
671
- return this.request("/api/opencode/files/presign", {
672
- method: "POST",
673
- body: JSON.stringify(data)
674
- });
675
- }
676
- async completeUpload(data) {
677
- return this.request("/api/opencode/files/complete", {
678
- method: "POST",
679
- body: JSON.stringify(data)
680
- });
681
- }
682
- async getSprintFiles(sprintId) {
683
- return this.request(`/api/opencode/files/sprint/${sprintId}`);
684
- }
685
- async deleteFile(fileId) {
686
- await this.request(`/api/opencode/files/${fileId}`, {
687
- method: "DELETE"
688
- });
689
- }
690
- async logFileRead(fileId) {
691
- await this.request(`/api/opencode/files/${fileId}/read`, {
692
- method: "POST"
693
- });
694
- }
695
- async getFileDownloadUrl(fileId) {
696
- return this.request(`/api/opencode/files/download/${fileId}`);
697
- }
698
- async getFileOpenUrl(fileId) {
699
- return this.request(`/api/opencode/files/open-url/${fileId}`);
700
- }
701
- async updateFilePosition(fileId, data) {
702
- return this.request(`/api/opencode/files/${fileId}/position`, {
703
- method: "PUT",
704
- body: JSON.stringify(data)
705
- });
706
- }
707
- async listAiAgents() {
708
- const response = await this.request("/api/opencode/ai/agents");
709
- return response.agents || [];
710
- }
711
- async updateSprintAiAgents(sprintId, enabledAgentKeys) {
712
- const response = await this.request(`/api/opencode/sprints/${sprintId}/ai-agents`, {
713
- method: "PUT",
714
- body: JSON.stringify({ enabledAgentKeys })
715
- });
716
- return response.sprintAiAgents || [];
717
- }
718
- async updateSchedule(storyId, data) {
719
- return this.updateStory(storyId, {
720
- title: data.title,
721
- description: data.description,
722
- metadata: data
723
- });
724
- }
725
- async recordMessage(data) {
726
- return this.request("/api/opencode/messages", {
727
- method: "POST",
728
- body: JSON.stringify(data)
729
- });
730
- }
731
- async removeMessage(messageId, sprintId, sessionId) {
732
- await this.request(`/api/opencode/messages/${encodeURIComponent(messageId)}`, {
733
- method: "DELETE",
734
- body: JSON.stringify({ sprintId, sessionId })
735
- });
736
- }
737
- };
738
-
739
- // ../forloop-opencode-plugin-planner/plugins/tools/sprint-tools.ts
740
- import { tool } from "@opencode-ai/plugin";
741
-
742
- // ../forloop-opencode-plugin-planner/plugins/capabilities/context-resolver.ts
743
- import { exec } from "child_process";
744
- import { promisify } from "util";
745
- import * as fs3 from "fs";
746
- import * as path3 from "path";
747
- var execAsync = promisify(exec);
748
- async function getCurrentBranch(directory) {
749
- try {
750
- const result = await execAsync("git rev-parse --abbrev-ref HEAD", {
751
- cwd: directory
752
- });
753
- return result.stdout.trim();
754
- } catch (error) {
755
- throw new Error("Git not available or not in a repository");
756
- }
757
- }
758
- async function resolveSprintFromBranch(branch) {
759
- const match = branch.match(/sprint-(\d+)/);
760
- if (match) {
761
- return parseInt(match[1], 10);
762
- }
763
- return null;
764
- }
765
- async function resolveSprintId(providedId, directory) {
766
- if (providedId) {
767
- return { sprintId: providedId, source: "provided" };
768
- }
769
- const envSprintId = process.env.FORLOOP_SPRINT_ID;
770
- if (envSprintId) {
771
- return { sprintId: parseInt(envSprintId, 10), source: "env" };
772
- }
773
- const manifestSprintId = getActiveSprintIdFromManifest(directory);
774
- if (manifestSprintId) {
775
- return { sprintId: manifestSprintId, source: "manifest" };
776
- }
777
- try {
778
- const branch = await getCurrentBranch(directory);
779
- const sprintId = await resolveSprintFromBranch(branch);
780
- if (sprintId) {
781
- return { sprintId, branch, source: "branch" };
782
- }
783
- } catch (error) {
784
- }
785
- return { source: "config" };
786
- }
787
- function getActiveSprintIdFromManifest(directory) {
788
- const candidates = [];
789
- if (directory) {
790
- candidates.push(path3.join(directory, ".forloop", "manifest.json"));
791
- }
792
- const home = process.env.HOME;
793
- if (home) {
794
- candidates.push(path3.join(home, ".forloop", "manifest.json"));
795
- }
796
- for (const filePath of candidates) {
797
- try {
798
- if (!fs3.existsSync(filePath)) continue;
799
- const raw = fs3.readFileSync(filePath, "utf8");
800
- const parsed = JSON.parse(raw);
801
- const id = parsed?.activeSprintId;
802
- if (Number.isFinite(id)) return Number(id);
803
- } catch {
804
- }
805
- }
806
- return null;
807
- }
808
- var DEFAULT_HOME = "/tmp/home";
809
- function getSprintDir(sprintId) {
810
- return `sprint-${sprintId}`;
811
- }
812
- function getForloopRoot(sprintId) {
813
- const home = process.env.HOME || DEFAULT_HOME;
814
- const root = path3.join(home, ".forloop");
815
- if (sprintId !== void 0) {
816
- return path3.join(root, getSprintDir(sprintId));
817
- }
818
- return root;
819
- }
820
-
821
- // ../forloop-opencode-plugin-planner/plugins/tools/story-tools.ts
822
- import { tool as tool2 } from "@opencode-ai/plugin";
823
-
824
- // ../forloop-opencode-plugin-planner/plugins/tools/template-tools.ts
825
- import { tool as tool3 } from "@opencode-ai/plugin";
826
-
827
- // ../forloop-opencode-plugin-planner/plugins/tools/user-tools.ts
828
- import { tool as tool4 } from "@opencode-ai/plugin";
829
-
830
- // ../forloop-opencode-plugin-planner/plugins/tools/organization-tools.ts
831
- import { tool as tool5 } from "@opencode-ai/plugin";
832
-
833
- // ../forloop-opencode-plugin-planner/plugins/tools/file-tools.ts
834
- import { tool as tool6 } from "@opencode-ai/plugin";
835
-
836
- // ../forloop-opencode-plugin-planner/plugins/tools/schedule-tools.ts
837
- import { tool as tool7 } from "@opencode-ai/plugin";
838
-
839
- // ../forloop-opencode-plugin-planner/plugins/tools/folder-tools.ts
840
- import { tool as tool8 } from "@opencode-ai/plugin";
841
-
842
- // ../forloop-opencode-plugin-planner/plugins/tools/sync-tools.ts
843
- import { tool as tool9 } from "@opencode-ai/plugin";
844
-
845
- // ../forloop-opencode-plugin-planner/plugins/tools/agent-tools.ts
846
- import { tool as tool10 } from "@opencode-ai/plugin";
847
-
848
- // ../forloop-opencode-plugin-planner/plugins/tools/agent-suggestion-tools.ts
849
- import { tool as tool11 } from "@opencode-ai/plugin";
850
-
851
- // ../forloop-opencode-plugin-planner/plugins/tools/agent-sprint-tools.ts
852
- import { tool as tool12 } from "@opencode-ai/plugin";
853
-
854
- // ../forloop-opencode-plugin-planner/plugins/tools/ai-trigger-tools.ts
855
- import { tool as tool13 } from "@opencode-ai/plugin";
856
-
857
- // ../forloop-opencode-plugin-planner/plugins/tools/developer-status-tool.ts
858
- import { tool as tool14 } from "@opencode-ai/plugin";
859
-
860
- // ../forloop-opencode-plugin-planner/plugins/hooks/shell-env.ts
861
- import { exec as exec2 } from "child_process";
862
- import { promisify as promisify2 } from "util";
863
- var execAsync2 = promisify2(exec2);
864
-
865
145
  // src/commands/auth/index.ts
146
+ import { getToken, setToken, clearToken, validateToken } from "@forloop-cc/forloop-opencode-plugin-planner";
866
147
  function createAuthCommands() {
867
148
  return {
868
149
  "auth login": createAuthLoginCommand(),
@@ -930,6 +211,7 @@ function createAuthLogoutCommand() {
930
211
  }
931
212
 
932
213
  // src/commands/story.ts
214
+ import { ForLoopAPIClient, getToken as getToken2, getConfig } from "@forloop-cc/forloop-opencode-plugin-planner";
933
215
  function createStoryCommands() {
934
216
  return {
935
217
  "story create": createStoryCreateCommand(),
@@ -940,7 +222,7 @@ function createStoryCommands() {
940
222
  }
941
223
  async function getClient() {
942
224
  const config = getConfig();
943
- const token = await getToken();
225
+ const token = await getToken2();
944
226
  if (!token) {
945
227
  console.error("Error: No API token configured. Run: forloop auth login --api-key <token>");
946
228
  process.exit(1);
@@ -1130,6 +412,7 @@ function createStoryDeleteCommand() {
1130
412
  }
1131
413
 
1132
414
  // src/commands/sprint.ts
415
+ import { ForLoopAPIClient as ForLoopAPIClient2, getToken as getToken3, resolveSprintId as resolveSprintId2, getConfig as getConfig2 } from "@forloop-cc/forloop-opencode-plugin-planner";
1133
416
  function createSprintCommands() {
1134
417
  return {
1135
418
  "sprint get": createSprintGetCommand(),
@@ -1140,13 +423,13 @@ function createSprintCommands() {
1140
423
  };
1141
424
  }
1142
425
  async function getClient2() {
1143
- const config = getConfig();
1144
- const token = await getToken();
426
+ const config = getConfig2();
427
+ const token = await getToken3();
1145
428
  if (!token) {
1146
429
  console.error("Error: No API token configured. Run: forloop auth login --api-key <token>");
1147
430
  process.exit(1);
1148
431
  }
1149
- const client = new ForLoopAPIClient({ token, baseUrl: config.apiUrl });
432
+ const client = new ForLoopAPIClient2({ token, baseUrl: config.apiUrl });
1150
433
  return { client };
1151
434
  }
1152
435
  function formatDate(dateString) {
@@ -1167,7 +450,7 @@ function createSprintGetCommand() {
1167
450
  const resolved = await getClient2();
1168
451
  if (!resolved) return;
1169
452
  const { client } = resolved;
1170
- const resolution = await resolveSprintId(flags.id);
453
+ const resolution = await resolveSprintId2(flags.id);
1171
454
  if (!resolution.sprintId) {
1172
455
  console.error("Error: No sprint ID resolved. Use --id, set FORLOOP_SPRINT_ID, or use a sprint-XXX branch.");
1173
456
  process.exit(1);
@@ -1316,6 +599,7 @@ function createSprintDeleteCommand() {
1316
599
  }
1317
600
 
1318
601
  // src/commands/org.ts
602
+ import { ForLoopAPIClient as ForLoopAPIClient3, getToken as getToken4, getConfig as getConfig3 } from "@forloop-cc/forloop-opencode-plugin-planner";
1319
603
  function createOrgCommands() {
1320
604
  return {
1321
605
  "org list": createOrgListCommand(),
@@ -1325,13 +609,13 @@ function createOrgCommands() {
1325
609
  };
1326
610
  }
1327
611
  async function getClient3() {
1328
- const config = getConfig();
1329
- const token = await getToken();
612
+ const config = getConfig3();
613
+ const token = await getToken4();
1330
614
  if (!token) {
1331
615
  console.error("Error: No API token configured. Run: forloop auth login --api-key <token>");
1332
616
  process.exit(1);
1333
617
  }
1334
- return { client: new ForLoopAPIClient({ token, baseUrl: config.apiUrl }) };
618
+ return { client: new ForLoopAPIClient3({ token, baseUrl: config.apiUrl }) };
1335
619
  }
1336
620
  function createOrgListCommand() {
1337
621
  return defineCommand({
@@ -1439,6 +723,7 @@ function createOrgUpdateCommand() {
1439
723
  }
1440
724
 
1441
725
  // src/commands/template.ts
726
+ import { ForLoopAPIClient as ForLoopAPIClient4, getToken as getToken5, getConfig as getConfig4 } from "@forloop-cc/forloop-opencode-plugin-planner";
1442
727
  function createTemplateCommands() {
1443
728
  return {
1444
729
  "template list": createTemplateListCommand()
@@ -1451,13 +736,13 @@ function createTemplateListCommand() {
1451
736
  usage: "forloop template list",
1452
737
  examples: ["forloop template list"],
1453
738
  async run(_config) {
1454
- const config = getConfig();
1455
- const token = await getToken();
739
+ const config = getConfig4();
740
+ const token = await getToken5();
1456
741
  if (!token) {
1457
742
  console.error("Error: No API token configured.");
1458
743
  process.exit(1);
1459
744
  }
1460
- const client = new ForLoopAPIClient({ token, baseUrl: config.apiUrl });
745
+ const client = new ForLoopAPIClient4({ token, baseUrl: config.apiUrl });
1461
746
  const templates = await client.listTemplates();
1462
747
  const active = templates.filter((t) => !t.deletedAt);
1463
748
  if (!active.length) {
@@ -1479,6 +764,7 @@ function createTemplateListCommand() {
1479
764
  }
1480
765
 
1481
766
  // src/commands/agent.ts
767
+ import { ForLoopAPIClient as ForLoopAPIClient5, getToken as getToken6, resolveSprintId as resolveSprintId3, getConfig as getConfig5 } from "@forloop-cc/forloop-opencode-plugin-planner";
1482
768
  function createAgentCommands() {
1483
769
  return {
1484
770
  "agent history": createAgentHistoryCommand(),
@@ -1487,13 +773,13 @@ function createAgentCommands() {
1487
773
  };
1488
774
  }
1489
775
  async function getClient4() {
1490
- const config = getConfig();
1491
- const token = await getToken();
776
+ const config = getConfig5();
777
+ const token = await getToken6();
1492
778
  if (!token) {
1493
779
  console.error("Error: No API token configured.");
1494
780
  process.exit(1);
1495
781
  }
1496
- return { client: new ForLoopAPIClient({ token, baseUrl: config.apiUrl }) };
782
+ return { client: new ForLoopAPIClient5({ token, baseUrl: config.apiUrl }) };
1497
783
  }
1498
784
  function createAgentHistoryCommand() {
1499
785
  return defineCommand({
@@ -1509,7 +795,7 @@ function createAgentHistoryCommand() {
1509
795
  const resolved = await getClient4();
1510
796
  if (!resolved) return;
1511
797
  const { client } = resolved;
1512
- const resolution = await resolveSprintId(flags.sprint);
798
+ const resolution = await resolveSprintId3(flags.sprint);
1513
799
  const sprintId = resolution.sprintId || flags.sprint;
1514
800
  const history = await client.getConversationHistory({
1515
801
  sprintId,
@@ -1580,7 +866,7 @@ function createDeveloperStatusCommand() {
1580
866
  const resolved = await getClient4();
1581
867
  if (!resolved) return;
1582
868
  const { client } = resolved;
1583
- const resolution = await resolveSprintId(flags.sprint);
869
+ const resolution = await resolveSprintId3(flags.sprint);
1584
870
  if (!resolution.sprintId) {
1585
871
  console.error("Error: No sprint ID resolved.");
1586
872
  process.exit(1);
@@ -1592,11 +878,11 @@ function createDeveloperStatusCommand() {
1592
878
  console.log(`Sprint #${resolution.sprintId}: ${sprint.storiesDone || 0}/${sprint.storiesTotal || 0} stories done.`);
1593
879
  return;
1594
880
  }
1595
- const exec3 = status.execution || {};
881
+ const exec = status.execution || {};
1596
882
  const task = status.task || {};
1597
- console.log(`Developer Task: ${exec3.status}`);
883
+ console.log(`Developer Task: ${exec.status}`);
1598
884
  console.log(`Sprint: #${resolution.sprintId}`);
1599
- if (exec3.startedAt) console.log(`Started: ${new Date(exec3.startedAt).toLocaleString()}`);
885
+ if (exec.startedAt) console.log(`Started: ${new Date(exec.startedAt).toLocaleString()}`);
1600
886
  if (task.branchName) console.log(`Branch: ${task.branchName}`);
1601
887
  if (task.errorMessage) console.log(`Error: ${task.errorMessage}`);
1602
888
  console.log(`Progress: ${sprint.storiesDone || 0}/${sprint.storiesTotal || 0} done, ${sprint.storiesInProgress || 0} in progress.`);
@@ -1605,6 +891,7 @@ function createDeveloperStatusCommand() {
1605
891
  }
1606
892
 
1607
893
  // src/commands/user.ts
894
+ import { ForLoopAPIClient as ForLoopAPIClient6, getToken as getToken7, getConfig as getConfig6 } from "@forloop-cc/forloop-opencode-plugin-planner";
1608
895
  function createUserCommands() {
1609
896
  return {
1610
897
  "user profile": createUserProfileCommand(),
@@ -1613,13 +900,13 @@ function createUserCommands() {
1613
900
  };
1614
901
  }
1615
902
  async function getClient5() {
1616
- const config = getConfig();
1617
- const token = await getToken();
903
+ const config = getConfig6();
904
+ const token = await getToken7();
1618
905
  if (!token) {
1619
906
  console.error("Error: No API token configured.");
1620
907
  process.exit(1);
1621
908
  }
1622
- return { client: new ForLoopAPIClient({ token, baseUrl: config.apiUrl }) };
909
+ return { client: new ForLoopAPIClient6({ token, baseUrl: config.apiUrl }) };
1623
910
  }
1624
911
  function createUserProfileCommand() {
1625
912
  return defineCommand({
@@ -1679,8 +966,9 @@ function createOrgQuotasCommand() {
1679
966
  }
1680
967
 
1681
968
  // src/commands/file.ts
1682
- import * as fs4 from "fs";
1683
- import * as path4 from "path";
969
+ import { ForLoopAPIClient as ForLoopAPIClient7, getToken as getToken8, getConfig as getConfig7 } from "@forloop-cc/forloop-opencode-plugin-planner";
970
+ import * as fs from "fs";
971
+ import * as path from "path";
1684
972
  function createFileCommands() {
1685
973
  return {
1686
974
  "file upload": createFileUploadCommand(),
@@ -1690,13 +978,13 @@ function createFileCommands() {
1690
978
  };
1691
979
  }
1692
980
  async function getClient6() {
1693
- const config = getConfig();
1694
- const token = await getToken();
981
+ const config = getConfig7();
982
+ const token = await getToken8();
1695
983
  if (!token) {
1696
984
  console.error("Error: No API token configured.");
1697
985
  process.exit(1);
1698
986
  }
1699
- return { client: new ForLoopAPIClient({ token, baseUrl: config.apiUrl }) };
987
+ return { client: new ForLoopAPIClient7({ token, baseUrl: config.apiUrl }) };
1700
988
  }
1701
989
  var mimeTypes = {
1702
990
  ".png": "image/png",
@@ -1735,13 +1023,13 @@ function createFileUploadCommand() {
1735
1023
  if (!resolved) return;
1736
1024
  const { client } = resolved;
1737
1025
  const filePath = flags.path;
1738
- if (!fs4.existsSync(filePath)) {
1026
+ if (!fs.existsSync(filePath)) {
1739
1027
  console.error(`Error: File not found: ${filePath}`);
1740
1028
  process.exit(1);
1741
1029
  }
1742
- const fileContent = fs4.readFileSync(filePath);
1743
- const fileName = path4.basename(filePath);
1744
- const ext = path4.extname(fileName);
1030
+ const fileContent = fs.readFileSync(filePath);
1031
+ const fileName = path.basename(filePath);
1032
+ const ext = path.extname(fileName);
1745
1033
  const contentType = mimeTypes[ext] || "application/octet-stream";
1746
1034
  const presign = await client.createPresignedUpload({
1747
1035
  sprintId: flags.sprint,
@@ -1844,6 +1132,7 @@ function createFileDownloadCommand() {
1844
1132
  }
1845
1133
 
1846
1134
  // src/commands/folder.ts
1135
+ import { ForLoopAPIClient as ForLoopAPIClient8, getToken as getToken9, getConfig as getConfig8 } from "@forloop-cc/forloop-opencode-plugin-planner";
1847
1136
  function createFolderCommands() {
1848
1137
  return {
1849
1138
  "folder create": createFolderCreateCommand()
@@ -1862,13 +1151,13 @@ function createFolderCreateCommand() {
1862
1151
  ],
1863
1152
  examples: ['forloop folder create --title "Project Docs" --sprint 1 --permissions team'],
1864
1153
  async run(_config, flags) {
1865
- const config = getConfig();
1866
- const token = await getToken();
1154
+ const config = getConfig8();
1155
+ const token = await getToken9();
1867
1156
  if (!token) {
1868
1157
  console.error("Error: No API token configured.");
1869
1158
  process.exit(1);
1870
1159
  }
1871
- const client = new ForLoopAPIClient({ token, baseUrl: config.apiUrl });
1160
+ const client = new ForLoopAPIClient8({ token, baseUrl: config.apiUrl });
1872
1161
  const story = await client.createStory({
1873
1162
  title: flags.title,
1874
1163
  description: flags.description,
@@ -1883,8 +1172,9 @@ function createFolderCreateCommand() {
1883
1172
  }
1884
1173
 
1885
1174
  // src/commands/sync.ts
1886
- import * as fs5 from "fs";
1887
- import * as path5 from "path";
1175
+ import { ForLoopAPIClient as ForLoopAPIClient9, getToken as getToken10, resolveSprintId as resolveSprintId4, getConfig as getConfig9, getForloopRoot } from "@forloop-cc/forloop-opencode-plugin-planner";
1176
+ import * as fs2 from "fs";
1177
+ import * as path2 from "path";
1888
1178
  function createSyncCommands() {
1889
1179
  return {
1890
1180
  "sync aivy-folder": createSyncAivyFolderCommand(),
@@ -1894,13 +1184,13 @@ function createSyncCommands() {
1894
1184
  };
1895
1185
  }
1896
1186
  async function getClient7() {
1897
- const config = getConfig();
1898
- const token = await getToken();
1187
+ const config = getConfig9();
1188
+ const token = await getToken10();
1899
1189
  if (!token) {
1900
1190
  console.error("Error: No API token configured.");
1901
1191
  process.exit(1);
1902
1192
  }
1903
- return { client: new ForLoopAPIClient({ token, baseUrl: config.apiUrl }) };
1193
+ return { client: new ForLoopAPIClient9({ token, baseUrl: config.apiUrl }) };
1904
1194
  }
1905
1195
  function createSyncAivyFolderCommand() {
1906
1196
  return defineCommand({
@@ -1916,7 +1206,7 @@ function createSyncAivyFolderCommand() {
1916
1206
  const resolved = await getClient7();
1917
1207
  if (!resolved) return;
1918
1208
  const { client } = resolved;
1919
- const resolution = await resolveSprintId(flags.sprint);
1209
+ const resolution = await resolveSprintId4(flags.sprint);
1920
1210
  if (!resolution.sprintId) {
1921
1211
  console.error("Error: No sprint ID resolved.");
1922
1212
  process.exit(1);
@@ -1953,7 +1243,7 @@ function createAivyDocGetCommand() {
1953
1243
  const resolved = await getClient7();
1954
1244
  if (!resolved) return;
1955
1245
  const { client } = resolved;
1956
- const resolution = await resolveSprintId(flags.sprint);
1246
+ const resolution = await resolveSprintId4(flags.sprint);
1957
1247
  if (!resolution.sprintId) {
1958
1248
  console.error("Error: No sprint ID resolved.");
1959
1249
  process.exit(1);
@@ -1987,14 +1277,14 @@ function createS3ToLocalCommand() {
1987
1277
  const resolved = await getClient7();
1988
1278
  if (!resolved) return;
1989
1279
  const { client } = resolved;
1990
- const resolution = await resolveSprintId(flags.sprint);
1280
+ const resolution = await resolveSprintId4(flags.sprint);
1991
1281
  if (!resolution.sprintId) {
1992
1282
  console.error("Error: No sprint ID resolved.");
1993
1283
  process.exit(1);
1994
1284
  }
1995
1285
  const files = await client.getSprintFiles(resolution.sprintId);
1996
1286
  const localRoot = getForloopRoot(resolution.sprintId);
1997
- fs5.mkdirSync(localRoot, { recursive: true });
1287
+ fs2.mkdirSync(localRoot, { recursive: true });
1998
1288
  let downloaded = 0;
1999
1289
  let skipped = 0;
2000
1290
  for (const file of files) {
@@ -2009,9 +1299,9 @@ function createS3ToLocalCommand() {
2009
1299
  if (res.ok) {
2010
1300
  const buf = Buffer.from(await res.arrayBuffer());
2011
1301
  const kind = name.startsWith("knowledge-") ? "knowledge" : name.startsWith("plan-") ? "plan" : name.startsWith("task-") ? "task" : "other";
2012
- const dir = path5.join(localRoot, kind);
2013
- fs5.mkdirSync(dir, { recursive: true });
2014
- fs5.writeFileSync(path5.join(dir, name), buf);
1302
+ const dir = path2.join(localRoot, kind);
1303
+ fs2.mkdirSync(dir, { recursive: true });
1304
+ fs2.writeFileSync(path2.join(dir, name), buf);
2015
1305
  downloaded++;
2016
1306
  }
2017
1307
  }
@@ -2035,18 +1325,18 @@ function createLocalToS3Command() {
2035
1325
  const resolved = await getClient7();
2036
1326
  if (!resolved) return;
2037
1327
  const { client } = resolved;
2038
- const resolution = await resolveSprintId(flags.sprint);
1328
+ const resolution = await resolveSprintId4(flags.sprint);
2039
1329
  if (!resolution.sprintId) {
2040
1330
  console.error("Error: No sprint ID resolved.");
2041
1331
  process.exit(1);
2042
1332
  }
2043
1333
  const filePath = flags.path;
2044
- if (!fs5.existsSync(filePath)) {
1334
+ if (!fs2.existsSync(filePath)) {
2045
1335
  console.error(`Error: File not found: ${filePath}`);
2046
1336
  process.exit(1);
2047
1337
  }
2048
- const fileBuf = fs5.readFileSync(filePath);
2049
- const fileName = path5.basename(filePath);
1338
+ const fileBuf = fs2.readFileSync(filePath);
1339
+ const fileName = path2.basename(filePath);
2050
1340
  const contentType = "text/markdown";
2051
1341
  const folder = flags.folder || "project";
2052
1342
  const presign = await client.createPresignedUpload({
@@ -2077,12 +1367,12 @@ function createLocalToS3Command() {
2077
1367
  var CommandRegistry = class {
2078
1368
  root = { children: /* @__PURE__ */ new Map() };
2079
1369
  constructor(commands) {
2080
- for (const [path6, cmd] of Object.entries(commands)) {
2081
- this.register(path6, cmd);
1370
+ for (const [path3, cmd] of Object.entries(commands)) {
1371
+ this.register(path3, cmd);
2082
1372
  }
2083
1373
  }
2084
- register(path6, command) {
2085
- const parts = path6.split(" ");
1374
+ register(path3, command) {
1375
+ const parts = path3.split(" ");
2086
1376
  let node = this.root;
2087
1377
  for (const part of parts) {
2088
1378
  if (!node.children.has(part)) {
@@ -2362,7 +1652,10 @@ Tip: ${suggestion}
2362
1652
  }
2363
1653
 
2364
1654
  // src/main.ts
2365
- var CLI_VERSION = "0.2.0";
1655
+ import { getConfig as getConfig10 } from "@forloop-cc/forloop-opencode-plugin-planner";
1656
+ import { getToken as getToken11 } from "@forloop-cc/forloop-opencode-plugin-planner";
1657
+ import { detectTokenType } from "@forloop-cc/forloop-opencode-plugin-planner";
1658
+ var CLI_VERSION = "0.2.2";
2366
1659
  process.on("SIGINT", () => {
2367
1660
  process.stderr.write("\nInterrupted. Exiting.\n");
2368
1661
  process.exit(130);
@@ -2389,7 +1682,7 @@ async function main() {
2389
1682
  if (commandPath.length === 0) {
2390
1683
  registry.printHelp([], process.stderr);
2391
1684
  try {
2392
- const token2 = await getToken();
1685
+ const token2 = await getToken11();
2393
1686
  if (token2) {
2394
1687
  const tokenType = detectTokenType(token2);
2395
1688
  const masked = token2.slice(0, 8) + "..." + token2.slice(-4);
@@ -2410,8 +1703,8 @@ async function main() {
2410
1703
  const { command, extra } = registry.resolve(commandPath);
2411
1704
  const flags = parseFlags(argv, [...GLOBAL_OPTIONS, ...command.options ?? []]);
2412
1705
  if (extra.length > 0) flags._positional = extra;
2413
- const pluginConfig = getConfig();
2414
- const token = await getToken();
1706
+ const pluginConfig = getConfig10();
1707
+ const token = await getToken11();
2415
1708
  const isNoAuth = NO_AUTH_COMMANDS.some(
2416
1709
  (cmd) => cmd.every((c, i) => commandPath[i] === c)
2417
1710
  );
package/package.json CHANGED
@@ -1,9 +1,13 @@
1
1
  {
2
2
  "name": "@forloop-cc/forloop-cli",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Command-line interface for the ForLoop AI development platform",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
+ "homepage": "https://github.com/forloop-cc/forloop-cli#readme",
8
+ "bugs": {
9
+ "url": "https://github.com/forloop-cc/forloop-cli/issues"
10
+ },
7
11
  "keywords": [
8
12
  "forloop",
9
13
  "cli",
@@ -13,10 +17,10 @@
13
17
  ],
14
18
  "repository": {
15
19
  "type": "git",
16
- "url": "https://github.com/forloop-cc/forloop-cli"
20
+ "url": "git+https://github.com/forloop-cc/forloop-cli.git"
17
21
  },
18
22
  "bin": {
19
- "forloop": "./dist/forloop.mjs"
23
+ "forloop": "dist/forloop"
20
24
  },
21
25
  "files": [
22
26
  "dist/",
@@ -36,7 +40,7 @@
36
40
  "prepublishOnly": "npm run build"
37
41
  },
38
42
  "dependencies": {
39
- "@forloop/opencode-plugin": "^2.2.0",
43
+ "@forloop-cc/forloop-opencode-plugin-planner": "^2.2.0",
40
44
  "@opencode-ai/plugin": "^1.3.0"
41
45
  },
42
46
  "devDependencies": {