@locusai/sdk 0.14.5 → 0.15.1
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/agent/worker.js +39 -4
- package/dist/ai/claude-runner.d.ts +1 -0
- package/dist/ai/claude-runner.d.ts.map +1 -1
- package/dist/ai/codex-runner.d.ts +1 -0
- package/dist/ai/codex-runner.d.ts.map +1 -1
- package/dist/events.d.ts +2 -0
- package/dist/events.d.ts.map +1 -1
- package/dist/index-node.d.ts +1 -0
- package/dist/index-node.d.ts.map +1 -1
- package/dist/index-node.js +277 -4
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -0
- package/dist/modules/suggestions.d.ts +12 -0
- package/dist/modules/suggestions.d.ts.map +1 -0
- package/dist/proposals/context-gatherer.d.ts +32 -0
- package/dist/proposals/context-gatherer.d.ts.map +1 -0
- package/dist/proposals/index.d.ts +4 -0
- package/dist/proposals/index.d.ts.map +1 -0
- package/dist/proposals/proposal-engine.d.ts +21 -0
- package/dist/proposals/proposal-engine.d.ts.map +1 -0
- package/package.json +7 -5
package/dist/agent/worker.js
CHANGED
|
@@ -307,6 +307,29 @@ var init_sprints = __esm(() => {
|
|
|
307
307
|
};
|
|
308
308
|
});
|
|
309
309
|
|
|
310
|
+
// src/modules/suggestions.ts
|
|
311
|
+
var SuggestionsModule;
|
|
312
|
+
var init_suggestions = __esm(() => {
|
|
313
|
+
SuggestionsModule = class SuggestionsModule extends BaseModule {
|
|
314
|
+
async create(workspaceId, data) {
|
|
315
|
+
const { data: res } = await this.api.post(`/workspaces/${workspaceId}/suggestions`, data);
|
|
316
|
+
return res.suggestion;
|
|
317
|
+
}
|
|
318
|
+
async list(workspaceId, params) {
|
|
319
|
+
const { data } = await this.api.get(`/workspaces/${workspaceId}/suggestions`, { params });
|
|
320
|
+
return data.suggestions;
|
|
321
|
+
}
|
|
322
|
+
async get(workspaceId, id) {
|
|
323
|
+
const { data } = await this.api.get(`/workspaces/${workspaceId}/suggestions/${id}`);
|
|
324
|
+
return data.suggestion;
|
|
325
|
+
}
|
|
326
|
+
async updateStatus(workspaceId, id, status) {
|
|
327
|
+
const { data } = await this.api.patch(`/workspaces/${workspaceId}/suggestions/${id}/status`, status);
|
|
328
|
+
return data.suggestion;
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
});
|
|
332
|
+
|
|
310
333
|
// src/modules/tasks.ts
|
|
311
334
|
var import_shared, TasksModule;
|
|
312
335
|
var init_tasks = __esm(() => {
|
|
@@ -483,6 +506,7 @@ var exports_src = {};
|
|
|
483
506
|
__export(exports_src, {
|
|
484
507
|
WorkspacesModule: () => WorkspacesModule,
|
|
485
508
|
TasksModule: () => TasksModule,
|
|
509
|
+
SuggestionsModule: () => SuggestionsModule,
|
|
486
510
|
SprintsModule: () => SprintsModule,
|
|
487
511
|
OrganizationsModule: () => OrganizationsModule,
|
|
488
512
|
LocusEvent: () => LocusEvent,
|
|
@@ -511,6 +535,7 @@ class LocusClient {
|
|
|
511
535
|
docs;
|
|
512
536
|
ci;
|
|
513
537
|
instances;
|
|
538
|
+
suggestions;
|
|
514
539
|
constructor(config) {
|
|
515
540
|
this.emitter = new LocusEmitter;
|
|
516
541
|
this.api = import_axios.default.create({
|
|
@@ -531,6 +556,7 @@ class LocusClient {
|
|
|
531
556
|
this.docs = new DocsModule(this.api, this.emitter);
|
|
532
557
|
this.ci = new CiModule(this.api, this.emitter);
|
|
533
558
|
this.instances = new InstancesModule(this.api, this.emitter);
|
|
559
|
+
this.suggestions = new SuggestionsModule(this.api, this.emitter);
|
|
534
560
|
if (config.retryOptions) {
|
|
535
561
|
this.setupRetryInterceptor(config.retryOptions);
|
|
536
562
|
}
|
|
@@ -600,6 +626,7 @@ var init_src = __esm(() => {
|
|
|
600
626
|
init_invitations();
|
|
601
627
|
init_organizations();
|
|
602
628
|
init_sprints();
|
|
629
|
+
init_suggestions();
|
|
603
630
|
init_tasks();
|
|
604
631
|
init_workspaces();
|
|
605
632
|
init_discussion_types();
|
|
@@ -612,6 +639,7 @@ var init_src = __esm(() => {
|
|
|
612
639
|
init_invitations();
|
|
613
640
|
init_organizations();
|
|
614
641
|
init_sprints();
|
|
642
|
+
init_suggestions();
|
|
615
643
|
init_tasks();
|
|
616
644
|
init_workspaces();
|
|
617
645
|
});
|
|
@@ -883,6 +911,7 @@ class ClaudeRunner {
|
|
|
883
911
|
currentToolName;
|
|
884
912
|
activeTools = new Map;
|
|
885
913
|
activeProcess = null;
|
|
914
|
+
aborted = false;
|
|
886
915
|
timeoutMs;
|
|
887
916
|
constructor(projectPath, model = DEFAULT_MODEL[PROVIDER.CLAUDE], log, timeoutMs) {
|
|
888
917
|
this.model = model;
|
|
@@ -895,6 +924,7 @@ class ClaudeRunner {
|
|
|
895
924
|
}
|
|
896
925
|
abort() {
|
|
897
926
|
if (this.activeProcess && !this.activeProcess.killed) {
|
|
927
|
+
this.aborted = true;
|
|
898
928
|
this.activeProcess.kill("SIGTERM");
|
|
899
929
|
this.activeProcess = null;
|
|
900
930
|
}
|
|
@@ -953,6 +983,7 @@ class ClaudeRunner {
|
|
|
953
983
|
return args;
|
|
954
984
|
}
|
|
955
985
|
async* runStream(prompt) {
|
|
986
|
+
this.aborted = false;
|
|
956
987
|
const args = this.buildCliArgs();
|
|
957
988
|
const env = getAugmentedEnv({
|
|
958
989
|
FORCE_COLOR: "1",
|
|
@@ -1047,7 +1078,7 @@ class ClaudeRunner {
|
|
|
1047
1078
|
process.stderr.write(`${stderrBuffer}
|
|
1048
1079
|
`);
|
|
1049
1080
|
}
|
|
1050
|
-
if (code !== 0 && !errorMessage) {
|
|
1081
|
+
if (code !== 0 && !errorMessage && !this.aborted) {
|
|
1051
1082
|
const detail = stderrFull.trim() || lastResultContent.trim();
|
|
1052
1083
|
errorMessage = this.createExecutionError(code, detail).message;
|
|
1053
1084
|
this.eventEmitter?.emitErrorOccurred(errorMessage, `EXIT_${code}`);
|
|
@@ -1192,6 +1223,7 @@ class ClaudeRunner {
|
|
|
1192
1223
|
return null;
|
|
1193
1224
|
}
|
|
1194
1225
|
executeRun(prompt) {
|
|
1226
|
+
this.aborted = false;
|
|
1195
1227
|
return new Promise((resolve2, reject) => {
|
|
1196
1228
|
const args = this.buildCliArgs();
|
|
1197
1229
|
const env = getAugmentedEnv({
|
|
@@ -1244,7 +1276,7 @@ class ClaudeRunner {
|
|
|
1244
1276
|
}
|
|
1245
1277
|
process.stdout.write(`
|
|
1246
1278
|
`);
|
|
1247
|
-
if (code === 0) {
|
|
1279
|
+
if (code === 0 || this.aborted) {
|
|
1248
1280
|
resolve2(finalResult);
|
|
1249
1281
|
} else {
|
|
1250
1282
|
const detail = errorOutput.trim() || finalResult.trim();
|
|
@@ -1311,6 +1343,7 @@ class CodexRunner {
|
|
|
1311
1343
|
log;
|
|
1312
1344
|
reasoningEffort;
|
|
1313
1345
|
activeProcess = null;
|
|
1346
|
+
aborted = false;
|
|
1314
1347
|
eventEmitter;
|
|
1315
1348
|
currentToolName;
|
|
1316
1349
|
timeoutMs;
|
|
@@ -1326,11 +1359,13 @@ class CodexRunner {
|
|
|
1326
1359
|
}
|
|
1327
1360
|
abort() {
|
|
1328
1361
|
if (this.activeProcess && !this.activeProcess.killed) {
|
|
1362
|
+
this.aborted = true;
|
|
1329
1363
|
this.activeProcess.kill("SIGTERM");
|
|
1330
1364
|
this.activeProcess = null;
|
|
1331
1365
|
}
|
|
1332
1366
|
}
|
|
1333
1367
|
async run(prompt) {
|
|
1368
|
+
this.aborted = false;
|
|
1334
1369
|
const maxRetries = 3;
|
|
1335
1370
|
let lastError = null;
|
|
1336
1371
|
for (let attempt = 1;attempt <= maxRetries; attempt++) {
|
|
@@ -1446,7 +1481,7 @@ class CodexRunner {
|
|
|
1446
1481
|
});
|
|
1447
1482
|
codex.on("close", (code) => {
|
|
1448
1483
|
this.activeProcess = null;
|
|
1449
|
-
if (code === 0) {
|
|
1484
|
+
if (code === 0 || this.aborted) {
|
|
1450
1485
|
const result = this.readOutput(outputPath, finalOutput);
|
|
1451
1486
|
this.cleanupTempFile(outputPath);
|
|
1452
1487
|
if (result && finalContent.trim().length === 0) {
|
|
@@ -1559,7 +1594,7 @@ class CodexRunner {
|
|
|
1559
1594
|
});
|
|
1560
1595
|
codex.on("close", (code) => {
|
|
1561
1596
|
this.activeProcess = null;
|
|
1562
|
-
if (code === 0) {
|
|
1597
|
+
if (code === 0 || this.aborted) {
|
|
1563
1598
|
const result = this.readOutput(outputPath, output);
|
|
1564
1599
|
this.cleanupTempFile(outputPath);
|
|
1565
1600
|
resolve2(result);
|
|
@@ -10,6 +10,7 @@ export declare class ClaudeRunner implements AiRunner {
|
|
|
10
10
|
private currentToolName?;
|
|
11
11
|
private activeTools;
|
|
12
12
|
private activeProcess;
|
|
13
|
+
private aborted;
|
|
13
14
|
timeoutMs: number;
|
|
14
15
|
constructor(projectPath: string, model?: string, log?: LogFn | undefined, timeoutMs?: number);
|
|
15
16
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-runner.d.ts","sourceRoot":"","sources":["../../src/ai/claude-runner.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAc,MAAM,kBAAkB,CAAC;AAGhE,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAmC5C,qBAAa,YAAa,YAAW,QAAQ;
|
|
1
|
+
{"version":3,"file":"claude-runner.d.ts","sourceRoot":"","sources":["../../src/ai/claude-runner.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAc,MAAM,kBAAkB,CAAC;AAGhE,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAmC5C,qBAAa,YAAa,YAAW,QAAQ;IAWzC,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,GAAG,CAAC;IAXd,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,YAAY,CAAC,CAAmB;IACxC,OAAO,CAAC,eAAe,CAAC,CAAS;IACjC,OAAO,CAAC,WAAW,CAA+C;IAClE,OAAO,CAAC,aAAa,CAA6B;IAClD,OAAO,CAAC,OAAO,CAAS;IACxB,SAAS,EAAE,MAAM,CAAC;gBAGhB,WAAW,EAAE,MAAM,EACX,KAAK,GAAE,MAAuC,EAC9C,GAAG,CAAC,EAAE,KAAK,YAAA,EACnB,SAAS,CAAC,EAAE,MAAM;IAMpB;;OAEG;IACH,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAIhD;;OAEG;IACH,KAAK,IAAI,IAAI;IAQP,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA8B1C,OAAO,CAAC,WAAW;IA0BnB,OAAO,CAAC,YAAY;IAgBb,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAAC,WAAW,EAAE,IAAI,EAAE,OAAO,CAAC;IA4K5E;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAiCzB,OAAO,CAAC,sBAAsB;IAW9B,OAAO,CAAC,wBAAwB;IAYhC,OAAO,CAAC,kBAAkB;IAwE1B,OAAO,CAAC,UAAU;IAgFlB,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,WAAW;IAanB,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,oBAAoB;CAO7B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex-runner.d.ts","sourceRoot":"","sources":["../../src/ai/codex-runner.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAK5C,qBAAa,WAAY,YAAW,QAAQ;
|
|
1
|
+
{"version":3,"file":"codex-runner.d.ts","sourceRoot":"","sources":["../../src/ai/codex-runner.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAK5C,qBAAa,WAAY,YAAW,QAAQ;IAQxC,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,GAAG,CAAC;IACZ,OAAO,CAAC,eAAe,CAAC;IAV1B,OAAO,CAAC,aAAa,CAA6B;IAClD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAAC,CAAmB;IACxC,OAAO,CAAC,eAAe,CAAC,CAAS;IACjC,SAAS,EAAE,MAAM,CAAC;gBAGR,WAAW,EAAE,MAAM,EACnB,KAAK,GAAE,MAAsC,EAC7C,GAAG,CAAC,EAAE,KAAK,YAAA,EACX,eAAe,CAAC,EAAE,MAAM,YAAA,EAChC,SAAS,CAAC,EAAE,MAAM;IAKpB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAIhD;;OAEG;IACH,KAAK,IAAI,IAAI;IAQP,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA6B1C,OAAO,CAAC,WAAW;IA0BZ,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAAC,WAAW,EAAE,IAAI,EAAE,OAAO,CAAC;IA8J5E,OAAO,CAAC,iBAAiB;IA+BzB,OAAO,CAAC,UAAU;IAyDlB,OAAO,CAAC,SAAS;IAqBjB;;;OAGG;IACH,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,UAAU;IAYlB,OAAO,CAAC,qBAAqB;IAY7B,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,KAAK;CAGd"}
|
package/dist/events.d.ts
CHANGED
|
@@ -15,8 +15,10 @@ export declare class LocusEmitter extends EventEmitter {
|
|
|
15
15
|
on(event: LocusEvent.TOKEN_EXPIRED, listener: () => void): this;
|
|
16
16
|
on(event: LocusEvent.AUTH_ERROR, listener: (error: Error) => void): this;
|
|
17
17
|
on(event: LocusEvent.REQUEST_ERROR, listener: (error: Error) => void): this;
|
|
18
|
+
on(event: string, listener: (...args: unknown[]) => void): this;
|
|
18
19
|
emit(event: LocusEvent.TOKEN_EXPIRED): boolean;
|
|
19
20
|
emit(event: LocusEvent.AUTH_ERROR, error: Error): boolean;
|
|
20
21
|
emit(event: LocusEvent.REQUEST_ERROR, error: Error): boolean;
|
|
22
|
+
emit(event: string, ...args: unknown[]): boolean;
|
|
21
23
|
}
|
|
22
24
|
//# sourceMappingURL=events.d.ts.map
|
package/dist/events.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEhD,oBAAY,UAAU;IACpB,aAAa,kBAAkB;IAC/B,UAAU,eAAe;IACzB,aAAa,kBAAkB;CAChC;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,qBAAa,YAAa,SAAQ,YAAY;IAC5C,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,aAAa,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAC/D,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,UAAU,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IACxE,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,aAAa,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAC3E,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI;IAQ/D,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,aAAa,GAAG,OAAO;IAC9C,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,UAAU,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO;IACzD,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,aAAa,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO;IAC5D,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO;CAIjD"}
|
package/dist/index-node.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export * from "./git/index.js";
|
|
|
16
16
|
export * from "./index.js";
|
|
17
17
|
export { AgentOrchestrator, type AgentState, type OrchestratorConfig, } from "./orchestrator/index.js";
|
|
18
18
|
export * from "./planning/index.js";
|
|
19
|
+
export * from "./proposals/index.js";
|
|
19
20
|
export { c } from "./utils/colors.js";
|
|
20
21
|
export { extractJsonFromLLMOutput } from "./utils/json-extractor.js";
|
|
21
22
|
export { parseJsonWithSchema } from "./utils/structured-output.js";
|
package/dist/index-node.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-node.d.ts","sourceRoot":"","sources":["../src/index-node.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,cAAc,kBAAkB,CAAC;AAEjC,cAAc,eAAe,CAAC;AAE9B,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEzD,cAAc,uBAAuB,CAAC;AAEtC,cAAc,iBAAiB,CAAC;AAEhC,cAAc,gBAAgB,CAAC;AAE/B,cAAc,YAAY,CAAC;AAE3B,OAAO,EACL,iBAAiB,EACjB,KAAK,UAAU,EACf,KAAK,kBAAkB,GACxB,MAAM,yBAAyB,CAAC;AAEjC,cAAc,qBAAqB,CAAC;AAEpC,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAC;AACtC,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index-node.d.ts","sourceRoot":"","sources":["../src/index-node.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,cAAc,kBAAkB,CAAC;AAEjC,cAAc,eAAe,CAAC;AAE9B,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEzD,cAAc,uBAAuB,CAAC;AAEtC,cAAc,iBAAiB,CAAC;AAEhC,cAAc,gBAAgB,CAAC;AAE/B,cAAc,YAAY,CAAC;AAE3B,OAAO,EACL,iBAAiB,EACjB,KAAK,UAAU,EACf,KAAK,kBAAkB,GACxB,MAAM,yBAAyB,CAAC;AAEjC,cAAc,qBAAqB,CAAC;AAEpC,cAAc,sBAAsB,CAAC;AAErC,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAC;AACtC,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC"}
|
package/dist/index-node.js
CHANGED
|
@@ -307,6 +307,29 @@ var init_sprints = __esm(() => {
|
|
|
307
307
|
};
|
|
308
308
|
});
|
|
309
309
|
|
|
310
|
+
// src/modules/suggestions.ts
|
|
311
|
+
var SuggestionsModule;
|
|
312
|
+
var init_suggestions = __esm(() => {
|
|
313
|
+
SuggestionsModule = class SuggestionsModule extends BaseModule {
|
|
314
|
+
async create(workspaceId, data) {
|
|
315
|
+
const { data: res } = await this.api.post(`/workspaces/${workspaceId}/suggestions`, data);
|
|
316
|
+
return res.suggestion;
|
|
317
|
+
}
|
|
318
|
+
async list(workspaceId, params) {
|
|
319
|
+
const { data } = await this.api.get(`/workspaces/${workspaceId}/suggestions`, { params });
|
|
320
|
+
return data.suggestions;
|
|
321
|
+
}
|
|
322
|
+
async get(workspaceId, id) {
|
|
323
|
+
const { data } = await this.api.get(`/workspaces/${workspaceId}/suggestions/${id}`);
|
|
324
|
+
return data.suggestion;
|
|
325
|
+
}
|
|
326
|
+
async updateStatus(workspaceId, id, status) {
|
|
327
|
+
const { data } = await this.api.patch(`/workspaces/${workspaceId}/suggestions/${id}/status`, status);
|
|
328
|
+
return data.suggestion;
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
});
|
|
332
|
+
|
|
310
333
|
// src/modules/tasks.ts
|
|
311
334
|
var import_shared, TasksModule;
|
|
312
335
|
var init_tasks = __esm(() => {
|
|
@@ -483,6 +506,7 @@ var exports_src = {};
|
|
|
483
506
|
__export(exports_src, {
|
|
484
507
|
WorkspacesModule: () => WorkspacesModule,
|
|
485
508
|
TasksModule: () => TasksModule,
|
|
509
|
+
SuggestionsModule: () => SuggestionsModule,
|
|
486
510
|
SprintsModule: () => SprintsModule,
|
|
487
511
|
OrganizationsModule: () => OrganizationsModule,
|
|
488
512
|
LocusEvent: () => LocusEvent,
|
|
@@ -511,6 +535,7 @@ class LocusClient {
|
|
|
511
535
|
docs;
|
|
512
536
|
ci;
|
|
513
537
|
instances;
|
|
538
|
+
suggestions;
|
|
514
539
|
constructor(config) {
|
|
515
540
|
this.emitter = new LocusEmitter;
|
|
516
541
|
this.api = import_axios.default.create({
|
|
@@ -531,6 +556,7 @@ class LocusClient {
|
|
|
531
556
|
this.docs = new DocsModule(this.api, this.emitter);
|
|
532
557
|
this.ci = new CiModule(this.api, this.emitter);
|
|
533
558
|
this.instances = new InstancesModule(this.api, this.emitter);
|
|
559
|
+
this.suggestions = new SuggestionsModule(this.api, this.emitter);
|
|
534
560
|
if (config.retryOptions) {
|
|
535
561
|
this.setupRetryInterceptor(config.retryOptions);
|
|
536
562
|
}
|
|
@@ -600,6 +626,7 @@ var init_src = __esm(() => {
|
|
|
600
626
|
init_invitations();
|
|
601
627
|
init_organizations();
|
|
602
628
|
init_sprints();
|
|
629
|
+
init_suggestions();
|
|
603
630
|
init_tasks();
|
|
604
631
|
init_workspaces();
|
|
605
632
|
init_discussion_types();
|
|
@@ -612,6 +639,7 @@ var init_src = __esm(() => {
|
|
|
612
639
|
init_invitations();
|
|
613
640
|
init_organizations();
|
|
614
641
|
init_sprints();
|
|
642
|
+
init_suggestions();
|
|
615
643
|
init_tasks();
|
|
616
644
|
init_workspaces();
|
|
617
645
|
});
|
|
@@ -883,6 +911,7 @@ class ClaudeRunner {
|
|
|
883
911
|
currentToolName;
|
|
884
912
|
activeTools = new Map;
|
|
885
913
|
activeProcess = null;
|
|
914
|
+
aborted = false;
|
|
886
915
|
timeoutMs;
|
|
887
916
|
constructor(projectPath, model = DEFAULT_MODEL[PROVIDER.CLAUDE], log, timeoutMs) {
|
|
888
917
|
this.model = model;
|
|
@@ -895,6 +924,7 @@ class ClaudeRunner {
|
|
|
895
924
|
}
|
|
896
925
|
abort() {
|
|
897
926
|
if (this.activeProcess && !this.activeProcess.killed) {
|
|
927
|
+
this.aborted = true;
|
|
898
928
|
this.activeProcess.kill("SIGTERM");
|
|
899
929
|
this.activeProcess = null;
|
|
900
930
|
}
|
|
@@ -953,6 +983,7 @@ class ClaudeRunner {
|
|
|
953
983
|
return args;
|
|
954
984
|
}
|
|
955
985
|
async* runStream(prompt) {
|
|
986
|
+
this.aborted = false;
|
|
956
987
|
const args = this.buildCliArgs();
|
|
957
988
|
const env = getAugmentedEnv({
|
|
958
989
|
FORCE_COLOR: "1",
|
|
@@ -1047,7 +1078,7 @@ class ClaudeRunner {
|
|
|
1047
1078
|
process.stderr.write(`${stderrBuffer}
|
|
1048
1079
|
`);
|
|
1049
1080
|
}
|
|
1050
|
-
if (code !== 0 && !errorMessage) {
|
|
1081
|
+
if (code !== 0 && !errorMessage && !this.aborted) {
|
|
1051
1082
|
const detail = stderrFull.trim() || lastResultContent.trim();
|
|
1052
1083
|
errorMessage = this.createExecutionError(code, detail).message;
|
|
1053
1084
|
this.eventEmitter?.emitErrorOccurred(errorMessage, `EXIT_${code}`);
|
|
@@ -1192,6 +1223,7 @@ class ClaudeRunner {
|
|
|
1192
1223
|
return null;
|
|
1193
1224
|
}
|
|
1194
1225
|
executeRun(prompt) {
|
|
1226
|
+
this.aborted = false;
|
|
1195
1227
|
return new Promise((resolve2, reject) => {
|
|
1196
1228
|
const args = this.buildCliArgs();
|
|
1197
1229
|
const env = getAugmentedEnv({
|
|
@@ -1244,7 +1276,7 @@ class ClaudeRunner {
|
|
|
1244
1276
|
}
|
|
1245
1277
|
process.stdout.write(`
|
|
1246
1278
|
`);
|
|
1247
|
-
if (code === 0) {
|
|
1279
|
+
if (code === 0 || this.aborted) {
|
|
1248
1280
|
resolve2(finalResult);
|
|
1249
1281
|
} else {
|
|
1250
1282
|
const detail = errorOutput.trim() || finalResult.trim();
|
|
@@ -1311,6 +1343,7 @@ class CodexRunner {
|
|
|
1311
1343
|
log;
|
|
1312
1344
|
reasoningEffort;
|
|
1313
1345
|
activeProcess = null;
|
|
1346
|
+
aborted = false;
|
|
1314
1347
|
eventEmitter;
|
|
1315
1348
|
currentToolName;
|
|
1316
1349
|
timeoutMs;
|
|
@@ -1326,11 +1359,13 @@ class CodexRunner {
|
|
|
1326
1359
|
}
|
|
1327
1360
|
abort() {
|
|
1328
1361
|
if (this.activeProcess && !this.activeProcess.killed) {
|
|
1362
|
+
this.aborted = true;
|
|
1329
1363
|
this.activeProcess.kill("SIGTERM");
|
|
1330
1364
|
this.activeProcess = null;
|
|
1331
1365
|
}
|
|
1332
1366
|
}
|
|
1333
1367
|
async run(prompt) {
|
|
1368
|
+
this.aborted = false;
|
|
1334
1369
|
const maxRetries = 3;
|
|
1335
1370
|
let lastError = null;
|
|
1336
1371
|
for (let attempt = 1;attempt <= maxRetries; attempt++) {
|
|
@@ -1446,7 +1481,7 @@ class CodexRunner {
|
|
|
1446
1481
|
});
|
|
1447
1482
|
codex.on("close", (code) => {
|
|
1448
1483
|
this.activeProcess = null;
|
|
1449
|
-
if (code === 0) {
|
|
1484
|
+
if (code === 0 || this.aborted) {
|
|
1450
1485
|
const result = this.readOutput(outputPath, finalOutput);
|
|
1451
1486
|
this.cleanupTempFile(outputPath);
|
|
1452
1487
|
if (result && finalContent.trim().length === 0) {
|
|
@@ -1559,7 +1594,7 @@ class CodexRunner {
|
|
|
1559
1594
|
});
|
|
1560
1595
|
codex.on("close", (code) => {
|
|
1561
1596
|
this.activeProcess = null;
|
|
1562
|
-
if (code === 0) {
|
|
1597
|
+
if (code === 0 || this.aborted) {
|
|
1563
1598
|
const result = this.readOutput(outputPath, output);
|
|
1564
1599
|
this.cleanupTempFile(outputPath);
|
|
1565
1600
|
resolve2(result);
|
|
@@ -2851,9 +2886,11 @@ __export(exports_index_node, {
|
|
|
2851
2886
|
WorkspacesModule: () => WorkspacesModule,
|
|
2852
2887
|
TasksModule: () => TasksModule,
|
|
2853
2888
|
TaskExecutor: () => TaskExecutor,
|
|
2889
|
+
SuggestionsModule: () => SuggestionsModule,
|
|
2854
2890
|
SprintsModule: () => SprintsModule,
|
|
2855
2891
|
ReviewerWorker: () => ReviewerWorker,
|
|
2856
2892
|
ReviewService: () => ReviewService,
|
|
2893
|
+
ProposalEngine: () => ProposalEngine,
|
|
2857
2894
|
PromptBuilder: () => PromptBuilder,
|
|
2858
2895
|
PrService: () => PrService,
|
|
2859
2896
|
PlanningMeeting: () => PlanningMeeting,
|
|
@@ -2884,6 +2921,7 @@ __export(exports_index_node, {
|
|
|
2884
2921
|
DiscussionFacilitator: () => DiscussionFacilitator,
|
|
2885
2922
|
DEFAULT_MODEL: () => DEFAULT_MODEL,
|
|
2886
2923
|
ContextTracker: () => ContextTracker,
|
|
2924
|
+
ContextGatherer: () => ContextGatherer,
|
|
2887
2925
|
CodexRunner: () => CodexRunner,
|
|
2888
2926
|
CodebaseIndexerService: () => CodebaseIndexerService,
|
|
2889
2927
|
CodebaseIndexer: () => CodebaseIndexer,
|
|
@@ -5651,5 +5689,240 @@ class PlanningMeeting {
|
|
|
5651
5689
|
};
|
|
5652
5690
|
}
|
|
5653
5691
|
}
|
|
5692
|
+
// src/proposals/context-gatherer.ts
|
|
5693
|
+
var import_node_child_process8 = require("node:child_process");
|
|
5694
|
+
var import_node_fs12 = require("node:fs");
|
|
5695
|
+
var import_node_path13 = require("node:path");
|
|
5696
|
+
|
|
5697
|
+
class ContextGatherer {
|
|
5698
|
+
async gather(projectPath, client, workspaceId) {
|
|
5699
|
+
const [activeSprint, allTasks, skippedSuggestions] = await Promise.all([
|
|
5700
|
+
this.fetchActiveSprint(client, workspaceId),
|
|
5701
|
+
this.fetchTasks(client, workspaceId),
|
|
5702
|
+
this.fetchSkippedSuggestions(client, workspaceId)
|
|
5703
|
+
]);
|
|
5704
|
+
const sprintTasks = activeSprint ? allTasks.filter((t) => t.sprintId === activeSprint.id) : [];
|
|
5705
|
+
const backlogTasks = allTasks.filter((t) => !t.sprintId);
|
|
5706
|
+
const gitLog = this.readGitLog(projectPath);
|
|
5707
|
+
const artifactContents = this.readArtifacts(projectPath);
|
|
5708
|
+
const locusInstructions = this.readLocusInstructions(projectPath);
|
|
5709
|
+
return {
|
|
5710
|
+
activeSprint,
|
|
5711
|
+
sprintTasks,
|
|
5712
|
+
backlogTasks,
|
|
5713
|
+
gitLog,
|
|
5714
|
+
artifactContents,
|
|
5715
|
+
locusInstructions,
|
|
5716
|
+
skippedSuggestions
|
|
5717
|
+
};
|
|
5718
|
+
}
|
|
5719
|
+
async fetchActiveSprint(client, workspaceId) {
|
|
5720
|
+
try {
|
|
5721
|
+
return await client.sprints.getActive(workspaceId);
|
|
5722
|
+
} catch {
|
|
5723
|
+
return null;
|
|
5724
|
+
}
|
|
5725
|
+
}
|
|
5726
|
+
async fetchTasks(client, workspaceId) {
|
|
5727
|
+
try {
|
|
5728
|
+
return await client.tasks.list(workspaceId);
|
|
5729
|
+
} catch {
|
|
5730
|
+
return [];
|
|
5731
|
+
}
|
|
5732
|
+
}
|
|
5733
|
+
async fetchSkippedSuggestions(client, workspaceId) {
|
|
5734
|
+
try {
|
|
5735
|
+
return await client.suggestions.list(workspaceId, { status: "SKIPPED" });
|
|
5736
|
+
} catch {
|
|
5737
|
+
return [];
|
|
5738
|
+
}
|
|
5739
|
+
}
|
|
5740
|
+
readGitLog(projectPath) {
|
|
5741
|
+
try {
|
|
5742
|
+
return import_node_child_process8.execFileSync("git", ["log", "--oneline", "--no-decorate", "-n", "20"], {
|
|
5743
|
+
cwd: projectPath,
|
|
5744
|
+
encoding: "utf-8",
|
|
5745
|
+
timeout: 1e4,
|
|
5746
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
5747
|
+
}).trim();
|
|
5748
|
+
} catch {
|
|
5749
|
+
return "";
|
|
5750
|
+
}
|
|
5751
|
+
}
|
|
5752
|
+
readArtifacts(projectPath) {
|
|
5753
|
+
const artifactsDir = import_node_path13.join(projectPath, ".locus", "artifacts");
|
|
5754
|
+
if (!import_node_fs12.existsSync(artifactsDir))
|
|
5755
|
+
return [];
|
|
5756
|
+
try {
|
|
5757
|
+
const files = import_node_fs12.readdirSync(artifactsDir).filter((f) => f.endsWith(".md"));
|
|
5758
|
+
return files.slice(0, 10).map((name) => ({
|
|
5759
|
+
name,
|
|
5760
|
+
content: import_node_fs12.readFileSync(import_node_path13.join(artifactsDir, name), "utf-8").slice(0, 2000)
|
|
5761
|
+
}));
|
|
5762
|
+
} catch {
|
|
5763
|
+
return [];
|
|
5764
|
+
}
|
|
5765
|
+
}
|
|
5766
|
+
readLocusInstructions(projectPath) {
|
|
5767
|
+
const locusPath = import_node_path13.join(projectPath, ".locus", "LOCUS.md");
|
|
5768
|
+
if (!import_node_fs12.existsSync(locusPath))
|
|
5769
|
+
return null;
|
|
5770
|
+
try {
|
|
5771
|
+
return import_node_fs12.readFileSync(locusPath, "utf-8").slice(0, 3000);
|
|
5772
|
+
} catch {
|
|
5773
|
+
return null;
|
|
5774
|
+
}
|
|
5775
|
+
}
|
|
5776
|
+
}
|
|
5777
|
+
// src/proposals/proposal-engine.ts
|
|
5778
|
+
init_factory();
|
|
5779
|
+
var import_shared6 = require("@locusai/shared");
|
|
5780
|
+
class ProposalEngine {
|
|
5781
|
+
contextGatherer;
|
|
5782
|
+
constructor(contextGatherer) {
|
|
5783
|
+
this.contextGatherer = contextGatherer ?? new ContextGatherer;
|
|
5784
|
+
}
|
|
5785
|
+
async runProposalCycle(projectPath, client, workspaceId) {
|
|
5786
|
+
const context = await this.contextGatherer.gather(projectPath, client, workspaceId);
|
|
5787
|
+
return this.generateProposals(context, projectPath, client, workspaceId);
|
|
5788
|
+
}
|
|
5789
|
+
async generateProposals(context, projectPath, client, workspaceId) {
|
|
5790
|
+
const prompt = this.buildPrompt(context);
|
|
5791
|
+
const runner = createAiRunner(undefined, {
|
|
5792
|
+
projectPath,
|
|
5793
|
+
timeoutMs: 5 * 60 * 1000,
|
|
5794
|
+
maxTurns: 1
|
|
5795
|
+
});
|
|
5796
|
+
let aiResponse;
|
|
5797
|
+
try {
|
|
5798
|
+
aiResponse = await runner.run(prompt);
|
|
5799
|
+
} catch {
|
|
5800
|
+
return [];
|
|
5801
|
+
}
|
|
5802
|
+
const proposals = this.parseResponse(aiResponse);
|
|
5803
|
+
const created = [];
|
|
5804
|
+
for (const proposal of proposals) {
|
|
5805
|
+
if (this.isDuplicate(proposal.title, context.skippedSuggestions)) {
|
|
5806
|
+
continue;
|
|
5807
|
+
}
|
|
5808
|
+
try {
|
|
5809
|
+
const suggestion = await client.suggestions.create(workspaceId, {
|
|
5810
|
+
type: import_shared6.SuggestionType.NEXT_STEP,
|
|
5811
|
+
title: proposal.title,
|
|
5812
|
+
description: proposal.description,
|
|
5813
|
+
metadata: {
|
|
5814
|
+
complexity: proposal.complexity,
|
|
5815
|
+
relatedBacklogItem: proposal.relatedBacklogItem,
|
|
5816
|
+
source: "proposal-engine"
|
|
5817
|
+
}
|
|
5818
|
+
});
|
|
5819
|
+
created.push(suggestion);
|
|
5820
|
+
} catch {}
|
|
5821
|
+
}
|
|
5822
|
+
return created;
|
|
5823
|
+
}
|
|
5824
|
+
buildPrompt(context) {
|
|
5825
|
+
const sections = [];
|
|
5826
|
+
sections.push("You are a proactive software engineering advisor. Based on the project context below, propose 1-3 high-value next steps the team should take. Focus on actionable, impactful work.");
|
|
5827
|
+
if (context.activeSprint) {
|
|
5828
|
+
const sprintInfo = `Sprint: ${context.activeSprint.name} (${context.activeSprint.status})`;
|
|
5829
|
+
const tasksByStatus = this.groupTasksByStatus(context.sprintTasks);
|
|
5830
|
+
sections.push(`## Current Sprint
|
|
5831
|
+
${sprintInfo}
|
|
5832
|
+
${tasksByStatus}`);
|
|
5833
|
+
}
|
|
5834
|
+
if (context.backlogTasks.length > 0) {
|
|
5835
|
+
const backlogList = context.backlogTasks.slice(0, 15).map((t) => `- [${t.priority}] ${t.title}${t.description ? `: ${t.description.slice(0, 100)}` : ""}`).join(`
|
|
5836
|
+
`);
|
|
5837
|
+
sections.push(`## Backlog Items
|
|
5838
|
+
${backlogList}`);
|
|
5839
|
+
}
|
|
5840
|
+
if (context.gitLog) {
|
|
5841
|
+
sections.push(`## Recent Commits (last 20)
|
|
5842
|
+
${context.gitLog}`);
|
|
5843
|
+
}
|
|
5844
|
+
if (context.artifactContents.length > 0) {
|
|
5845
|
+
const artifacts = context.artifactContents.map((a) => `### ${a.name}
|
|
5846
|
+
${a.content}`).join(`
|
|
5847
|
+
|
|
5848
|
+
`);
|
|
5849
|
+
sections.push(`## Product Context
|
|
5850
|
+
${artifacts}`);
|
|
5851
|
+
}
|
|
5852
|
+
if (context.locusInstructions) {
|
|
5853
|
+
sections.push(`## Project Instructions
|
|
5854
|
+
${context.locusInstructions}`);
|
|
5855
|
+
}
|
|
5856
|
+
if (context.skippedSuggestions.length > 0) {
|
|
5857
|
+
const skipped = context.skippedSuggestions.map((s) => `- ${s.title}`).join(`
|
|
5858
|
+
`);
|
|
5859
|
+
sections.push(`## Previously Skipped Proposals (do NOT re-propose these)
|
|
5860
|
+
${skipped}`);
|
|
5861
|
+
}
|
|
5862
|
+
sections.push(`## Instructions
|
|
5863
|
+
Propose 1-3 high-value next steps. For each, respond with exactly this format:
|
|
5864
|
+
|
|
5865
|
+
PROPOSAL_START
|
|
5866
|
+
Title: <clear, concise title>
|
|
5867
|
+
Description: <what to do and why, 2-4 sentences>
|
|
5868
|
+
Complexity: <low|medium|high>
|
|
5869
|
+
Related Backlog: <title of related backlog item, or "none">
|
|
5870
|
+
PROPOSAL_END
|
|
5871
|
+
|
|
5872
|
+
Rules:
|
|
5873
|
+
- Focus on what would deliver the most value right now
|
|
5874
|
+
- Align with the current sprint goals when possible
|
|
5875
|
+
- Don't propose things that are already in progress
|
|
5876
|
+
- Don't re-propose previously skipped suggestions
|
|
5877
|
+
- Keep proposals specific and actionable`);
|
|
5878
|
+
return sections.join(`
|
|
5879
|
+
|
|
5880
|
+
`);
|
|
5881
|
+
}
|
|
5882
|
+
parseResponse(response) {
|
|
5883
|
+
const proposals = [];
|
|
5884
|
+
const blocks = response.split("PROPOSAL_START");
|
|
5885
|
+
for (const block of blocks) {
|
|
5886
|
+
const endIdx = block.indexOf("PROPOSAL_END");
|
|
5887
|
+
if (endIdx === -1)
|
|
5888
|
+
continue;
|
|
5889
|
+
const content = block.slice(0, endIdx).trim();
|
|
5890
|
+
const title = this.extractField(content, "Title");
|
|
5891
|
+
const description = this.extractField(content, "Description");
|
|
5892
|
+
const complexity = this.extractField(content, "Complexity") ?? "medium";
|
|
5893
|
+
const relatedRaw = this.extractField(content, "Related Backlog");
|
|
5894
|
+
const relatedBacklogItem = relatedRaw && relatedRaw.toLowerCase() !== "none" ? relatedRaw : null;
|
|
5895
|
+
if (title && description) {
|
|
5896
|
+
proposals.push({
|
|
5897
|
+
title: title.slice(0, 200),
|
|
5898
|
+
description: description.slice(0, 2000),
|
|
5899
|
+
complexity: complexity.toLowerCase(),
|
|
5900
|
+
relatedBacklogItem
|
|
5901
|
+
});
|
|
5902
|
+
}
|
|
5903
|
+
}
|
|
5904
|
+
return proposals.slice(0, 3);
|
|
5905
|
+
}
|
|
5906
|
+
extractField(content, field) {
|
|
5907
|
+
const regex = new RegExp(`^${field}:\\s*(.+)`, "im");
|
|
5908
|
+
const match = content.match(regex);
|
|
5909
|
+
return match ? match[1].trim() : null;
|
|
5910
|
+
}
|
|
5911
|
+
isDuplicate(title, skipped) {
|
|
5912
|
+
const normalized = title.toLowerCase().trim();
|
|
5913
|
+
return skipped.some((s) => {
|
|
5914
|
+
const skippedNorm = s.title.toLowerCase().trim();
|
|
5915
|
+
return skippedNorm === normalized || skippedNorm.includes(normalized) || normalized.includes(skippedNorm);
|
|
5916
|
+
});
|
|
5917
|
+
}
|
|
5918
|
+
groupTasksByStatus(tasks2) {
|
|
5919
|
+
const groups = {};
|
|
5920
|
+
for (const t of tasks2) {
|
|
5921
|
+
groups[t.status] = (groups[t.status] ?? 0) + 1;
|
|
5922
|
+
}
|
|
5923
|
+
return Object.entries(groups).map(([status, count]) => `- ${status}: ${count} task(s)`).join(`
|
|
5924
|
+
`);
|
|
5925
|
+
}
|
|
5926
|
+
}
|
|
5654
5927
|
// src/index-node.ts
|
|
5655
5928
|
init_colors();
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { InstancesModule } from "./modules/instances.js";
|
|
|
6
6
|
import { InvitationsModule } from "./modules/invitations.js";
|
|
7
7
|
import { OrganizationsModule } from "./modules/organizations.js";
|
|
8
8
|
import { SprintsModule } from "./modules/sprints.js";
|
|
9
|
+
import { SuggestionsModule } from "./modules/suggestions.js";
|
|
9
10
|
import { TasksModule } from "./modules/tasks.js";
|
|
10
11
|
import { WorkspacesModule } from "./modules/workspaces.js";
|
|
11
12
|
export type { Discussion, DiscussionInsight, DiscussionMessage, } from "./discussion/discussion-types.js";
|
|
@@ -18,6 +19,7 @@ export * from "./modules/instances.js";
|
|
|
18
19
|
export * from "./modules/invitations.js";
|
|
19
20
|
export * from "./modules/organizations.js";
|
|
20
21
|
export * from "./modules/sprints.js";
|
|
22
|
+
export * from "./modules/suggestions.js";
|
|
21
23
|
export * from "./modules/tasks.js";
|
|
22
24
|
export * from "./modules/workspaces.js";
|
|
23
25
|
export declare class LocusClient {
|
|
@@ -32,6 +34,7 @@ export declare class LocusClient {
|
|
|
32
34
|
readonly docs: DocsModule;
|
|
33
35
|
readonly ci: CiModule;
|
|
34
36
|
readonly instances: InstancesModule;
|
|
37
|
+
readonly suggestions: SuggestionsModule;
|
|
35
38
|
constructor(config: LocusConfig);
|
|
36
39
|
private setupRetryInterceptor;
|
|
37
40
|
private setupInterceptors;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAc,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAc,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAI3D,YAAY,EACV,UAAU,EACV,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,gBAAgB,GACjB,MAAM,kCAAkC,CAAC;AAE1C,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AAEzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AAExC,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAgB;IACpC,SAAgB,OAAO,EAAE,YAAY,CAAC;IAEtC,SAAgB,IAAI,EAAE,UAAU,CAAC;IACjC,SAAgB,KAAK,EAAE,WAAW,CAAC;IACnC,SAAgB,OAAO,EAAE,aAAa,CAAC;IACvC,SAAgB,UAAU,EAAE,gBAAgB,CAAC;IAC7C,SAAgB,aAAa,EAAE,mBAAmB,CAAC;IACnD,SAAgB,WAAW,EAAE,iBAAiB,CAAC;IAC/C,SAAgB,IAAI,EAAE,UAAU,CAAC;IACjC,SAAgB,EAAE,EAAE,QAAQ,CAAC;IAC7B,SAAgB,SAAS,EAAE,eAAe,CAAC;IAC3C,SAAgB,WAAW,EAAE,iBAAiB,CAAC;gBAEnC,MAAM,EAAE,WAAW;IA+B/B,OAAO,CAAC,qBAAqB;IAmC7B,OAAO,CAAC,iBAAiB;IAmDlB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;CAOrC"}
|
package/dist/index.js
CHANGED
|
@@ -307,6 +307,29 @@ var init_sprints = __esm(() => {
|
|
|
307
307
|
};
|
|
308
308
|
});
|
|
309
309
|
|
|
310
|
+
// src/modules/suggestions.ts
|
|
311
|
+
var SuggestionsModule;
|
|
312
|
+
var init_suggestions = __esm(() => {
|
|
313
|
+
SuggestionsModule = class SuggestionsModule extends BaseModule {
|
|
314
|
+
async create(workspaceId, data) {
|
|
315
|
+
const { data: res } = await this.api.post(`/workspaces/${workspaceId}/suggestions`, data);
|
|
316
|
+
return res.suggestion;
|
|
317
|
+
}
|
|
318
|
+
async list(workspaceId, params) {
|
|
319
|
+
const { data } = await this.api.get(`/workspaces/${workspaceId}/suggestions`, { params });
|
|
320
|
+
return data.suggestions;
|
|
321
|
+
}
|
|
322
|
+
async get(workspaceId, id) {
|
|
323
|
+
const { data } = await this.api.get(`/workspaces/${workspaceId}/suggestions/${id}`);
|
|
324
|
+
return data.suggestion;
|
|
325
|
+
}
|
|
326
|
+
async updateStatus(workspaceId, id, status) {
|
|
327
|
+
const { data } = await this.api.patch(`/workspaces/${workspaceId}/suggestions/${id}/status`, status);
|
|
328
|
+
return data.suggestion;
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
});
|
|
332
|
+
|
|
310
333
|
// src/modules/tasks.ts
|
|
311
334
|
var import_shared, TasksModule;
|
|
312
335
|
var init_tasks = __esm(() => {
|
|
@@ -483,6 +506,7 @@ var exports_src = {};
|
|
|
483
506
|
__export(exports_src, {
|
|
484
507
|
WorkspacesModule: () => WorkspacesModule,
|
|
485
508
|
TasksModule: () => TasksModule,
|
|
509
|
+
SuggestionsModule: () => SuggestionsModule,
|
|
486
510
|
SprintsModule: () => SprintsModule,
|
|
487
511
|
OrganizationsModule: () => OrganizationsModule,
|
|
488
512
|
LocusEvent: () => LocusEvent,
|
|
@@ -511,6 +535,7 @@ class LocusClient {
|
|
|
511
535
|
docs;
|
|
512
536
|
ci;
|
|
513
537
|
instances;
|
|
538
|
+
suggestions;
|
|
514
539
|
constructor(config) {
|
|
515
540
|
this.emitter = new LocusEmitter;
|
|
516
541
|
this.api = import_axios.default.create({
|
|
@@ -531,6 +556,7 @@ class LocusClient {
|
|
|
531
556
|
this.docs = new DocsModule(this.api, this.emitter);
|
|
532
557
|
this.ci = new CiModule(this.api, this.emitter);
|
|
533
558
|
this.instances = new InstancesModule(this.api, this.emitter);
|
|
559
|
+
this.suggestions = new SuggestionsModule(this.api, this.emitter);
|
|
534
560
|
if (config.retryOptions) {
|
|
535
561
|
this.setupRetryInterceptor(config.retryOptions);
|
|
536
562
|
}
|
|
@@ -600,6 +626,7 @@ var init_src = __esm(() => {
|
|
|
600
626
|
init_invitations();
|
|
601
627
|
init_organizations();
|
|
602
628
|
init_sprints();
|
|
629
|
+
init_suggestions();
|
|
603
630
|
init_tasks();
|
|
604
631
|
init_workspaces();
|
|
605
632
|
init_discussion_types();
|
|
@@ -612,6 +639,7 @@ var init_src = __esm(() => {
|
|
|
612
639
|
init_invitations();
|
|
613
640
|
init_organizations();
|
|
614
641
|
init_sprints();
|
|
642
|
+
init_suggestions();
|
|
615
643
|
init_tasks();
|
|
616
644
|
init_workspaces();
|
|
617
645
|
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { CreateSuggestion, Suggestion, UpdateSuggestionStatus } from "@locusai/shared";
|
|
2
|
+
import { BaseModule } from "./base.js";
|
|
3
|
+
export interface SuggestionListOptions {
|
|
4
|
+
status?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class SuggestionsModule extends BaseModule {
|
|
7
|
+
create(workspaceId: string, data: CreateSuggestion): Promise<Suggestion>;
|
|
8
|
+
list(workspaceId: string, params?: SuggestionListOptions): Promise<Suggestion[]>;
|
|
9
|
+
get(workspaceId: string, id: string): Promise<Suggestion>;
|
|
10
|
+
updateStatus(workspaceId: string, id: string, status: UpdateSuggestionStatus): Promise<Suggestion>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=suggestions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suggestions.d.ts","sourceRoot":"","sources":["../../src/modules/suggestions.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,sBAAsB,EACvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAUvC,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,iBAAkB,SAAQ,UAAU;IACzC,MAAM,CACV,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,UAAU,CAAC;IAQhB,IAAI,CACR,WAAW,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,qBAAqB,GAC7B,OAAO,CAAC,UAAU,EAAE,CAAC;IAQlB,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAOzD,YAAY,CAChB,WAAW,EAAE,MAAM,EACnB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,sBAAsB,GAC7B,OAAO,CAAC,UAAU,CAAC;CAOvB"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Sprint, Suggestion, Task } from "@locusai/shared";
|
|
2
|
+
import type { LocusClient } from "../index.js";
|
|
3
|
+
export interface ProposalContext {
|
|
4
|
+
/** Active sprint, if any */
|
|
5
|
+
activeSprint: Sprint | null;
|
|
6
|
+
/** Tasks in the current sprint */
|
|
7
|
+
sprintTasks: Task[];
|
|
8
|
+
/** Backlog tasks not yet assigned to a sprint */
|
|
9
|
+
backlogTasks: Task[];
|
|
10
|
+
/** Recent git commit log (last 20 commits) */
|
|
11
|
+
gitLog: string;
|
|
12
|
+
/** Product context from .locus/artifacts/ */
|
|
13
|
+
artifactContents: ArtifactFile[];
|
|
14
|
+
/** Project-specific instructions from .locus/LOCUS.md */
|
|
15
|
+
locusInstructions: string | null;
|
|
16
|
+
/** Previously skipped suggestions (for deduplication) */
|
|
17
|
+
skippedSuggestions: Suggestion[];
|
|
18
|
+
}
|
|
19
|
+
export interface ArtifactFile {
|
|
20
|
+
name: string;
|
|
21
|
+
content: string;
|
|
22
|
+
}
|
|
23
|
+
export declare class ContextGatherer {
|
|
24
|
+
gather(projectPath: string, client: LocusClient, workspaceId: string): Promise<ProposalContext>;
|
|
25
|
+
private fetchActiveSprint;
|
|
26
|
+
private fetchTasks;
|
|
27
|
+
private fetchSkippedSuggestions;
|
|
28
|
+
private readGitLog;
|
|
29
|
+
private readArtifacts;
|
|
30
|
+
private readLocusInstructions;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=context-gatherer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-gatherer.d.ts","sourceRoot":"","sources":["../../src/proposals/context-gatherer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAM/C,MAAM,WAAW,eAAe;IAC9B,4BAA4B;IAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,kCAAkC;IAClC,WAAW,EAAE,IAAI,EAAE,CAAC;IACpB,iDAAiD;IACjD,YAAY,EAAE,IAAI,EAAE,CAAC;IACrB,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,gBAAgB,EAAE,YAAY,EAAE,CAAC;IACjC,yDAAyD;IACzD,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,yDAAyD;IACzD,kBAAkB,EAAE,UAAU,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD,qBAAa,eAAe;IACpB,MAAM,CACV,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,WAAW,EACnB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,eAAe,CAAC;YAkCb,iBAAiB;YAWjB,UAAU;YAWV,uBAAuB;IAerC,OAAO,CAAC,UAAU;IAiBlB,OAAO,CAAC,aAAa;IAgBrB,OAAO,CAAC,qBAAqB;CAU9B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/proposals/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type Suggestion } from "@locusai/shared";
|
|
2
|
+
import type { LocusClient } from "../index.js";
|
|
3
|
+
import { ContextGatherer, type ProposalContext } from "./context-gatherer.js";
|
|
4
|
+
export declare class ProposalEngine {
|
|
5
|
+
private readonly contextGatherer;
|
|
6
|
+
constructor(contextGatherer?: ContextGatherer);
|
|
7
|
+
/**
|
|
8
|
+
* Full proposal cycle: gather context → generate proposals → create suggestions.
|
|
9
|
+
*/
|
|
10
|
+
runProposalCycle(projectPath: string, client: LocusClient, workspaceId: string): Promise<Suggestion[]>;
|
|
11
|
+
/**
|
|
12
|
+
* Generate proposals from gathered context, deduplicate, and create suggestions.
|
|
13
|
+
*/
|
|
14
|
+
generateProposals(context: ProposalContext, projectPath: string, client: LocusClient, workspaceId: string): Promise<Suggestion[]>;
|
|
15
|
+
private buildPrompt;
|
|
16
|
+
private parseResponse;
|
|
17
|
+
private extractField;
|
|
18
|
+
private isDuplicate;
|
|
19
|
+
private groupTasksByStatus;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=proposal-engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proposal-engine.d.ts","sourceRoot":"","sources":["../../src/proposals/proposal-engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAkB,MAAM,iBAAiB,CAAC;AAElE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAiB9E,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkB;gBAEtC,eAAe,CAAC,EAAE,eAAe;IAI7C;;OAEG;IACG,gBAAgB,CACpB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,WAAW,EACnB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,UAAU,EAAE,CAAC;IASxB;;OAEG;IACG,iBAAiB,CACrB,OAAO,EAAE,eAAe,EACxB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,WAAW,EACnB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,UAAU,EAAE,CAAC;IAiDxB,OAAO,CAAC,WAAW;IA+EnB,OAAO,CAAC,aAAa;IA+BrB,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,WAAW;IAiBnB,OAAO,CAAC,kBAAkB;CAU3B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@locusai/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"README.md"
|
|
24
24
|
],
|
|
25
25
|
"scripts": {
|
|
26
|
-
"build": "bun build ./src/index.ts ./src/index-node.ts ./src/agent/worker.ts --outdir ./dist --target node --format cjs --external axios --external events --external globby --external @locusai/shared --external zod && tsc -p tsconfig.build.json --emitDeclarationOnly",
|
|
26
|
+
"build": "bun build ./src/index.ts ./src/index-node.ts ./src/agent/worker.ts --outdir ./dist --target node --format cjs --external axios --external events --external globby --external @locusai/shared --external zod --external node-cron && tsc -p tsconfig.build.json --emitDeclarationOnly",
|
|
27
27
|
"dev": "tsc --watch",
|
|
28
28
|
"lint": "biome lint .",
|
|
29
29
|
"test": "bun test",
|
|
@@ -31,14 +31,16 @@
|
|
|
31
31
|
"clean": "rm -rf node_modules"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@locusai/shared": "^0.
|
|
34
|
+
"@locusai/shared": "^0.15.1",
|
|
35
35
|
"axios": "^1.13.2",
|
|
36
36
|
"events": "^3.3.0",
|
|
37
37
|
"globby": "^14.0.2",
|
|
38
|
+
"node-cron": "^3.0.3",
|
|
38
39
|
"zod": "^4.3.6"
|
|
39
40
|
},
|
|
40
41
|
"devDependencies": {
|
|
41
|
-
"
|
|
42
|
-
"@types/node": "^
|
|
42
|
+
"@types/node": "^22.10.7",
|
|
43
|
+
"@types/node-cron": "^3.0.11",
|
|
44
|
+
"typescript": "^5.8.3"
|
|
43
45
|
}
|
|
44
46
|
}
|