@locusai/cli 0.11.6 → 0.11.8
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/bin/agent/worker.js +562 -69
- package/bin/locus.js +858 -298
- package/package.json +2 -2
package/bin/locus.js
CHANGED
|
@@ -6324,9 +6324,6 @@ function extractJsonFromLLMOutput(raw) {
|
|
|
6324
6324
|
if (codeBlockMatch) {
|
|
6325
6325
|
return codeBlockMatch[1]?.trim() || "";
|
|
6326
6326
|
}
|
|
6327
|
-
if (trimmed.startsWith("{")) {
|
|
6328
|
-
return trimmed;
|
|
6329
|
-
}
|
|
6330
6327
|
const startIdx = trimmed.indexOf("{");
|
|
6331
6328
|
if (startIdx === -1) {
|
|
6332
6329
|
return trimmed;
|
|
@@ -6340,19 +6337,19 @@ function extractJsonFromLLMOutput(raw) {
|
|
|
6340
6337
|
escaped = false;
|
|
6341
6338
|
continue;
|
|
6342
6339
|
}
|
|
6343
|
-
if (
|
|
6344
|
-
|
|
6340
|
+
if (inString) {
|
|
6341
|
+
if (ch === "\\") {
|
|
6342
|
+
escaped = true;
|
|
6343
|
+
} else if (ch === '"') {
|
|
6344
|
+
inString = false;
|
|
6345
|
+
}
|
|
6345
6346
|
continue;
|
|
6346
6347
|
}
|
|
6347
6348
|
if (ch === '"') {
|
|
6348
|
-
inString =
|
|
6349
|
-
|
|
6350
|
-
}
|
|
6351
|
-
if (inString)
|
|
6352
|
-
continue;
|
|
6353
|
-
if (ch === "{")
|
|
6349
|
+
inString = true;
|
|
6350
|
+
} else if (ch === "{") {
|
|
6354
6351
|
depth++;
|
|
6355
|
-
else if (ch === "}") {
|
|
6352
|
+
} else if (ch === "}") {
|
|
6356
6353
|
depth--;
|
|
6357
6354
|
if (depth === 0) {
|
|
6358
6355
|
return trimmed.slice(startIdx, i + 1);
|
|
@@ -7123,9 +7120,7 @@ class ClaudeRunner {
|
|
|
7123
7120
|
"stream-json",
|
|
7124
7121
|
"--include-partial-messages",
|
|
7125
7122
|
"--model",
|
|
7126
|
-
this.model
|
|
7127
|
-
"--settings",
|
|
7128
|
-
SANDBOX_SETTINGS
|
|
7123
|
+
this.model
|
|
7129
7124
|
];
|
|
7130
7125
|
const env = getAugmentedEnv({
|
|
7131
7126
|
FORCE_COLOR: "1",
|
|
@@ -7374,9 +7369,7 @@ class ClaudeRunner {
|
|
|
7374
7369
|
"stream-json",
|
|
7375
7370
|
"--include-partial-messages",
|
|
7376
7371
|
"--model",
|
|
7377
|
-
this.model
|
|
7378
|
-
"--settings",
|
|
7379
|
-
SANDBOX_SETTINGS
|
|
7372
|
+
this.model
|
|
7380
7373
|
];
|
|
7381
7374
|
const env = getAugmentedEnv({
|
|
7382
7375
|
FORCE_COLOR: "1",
|
|
@@ -7478,21 +7471,11 @@ ${c.primary("[Claude]")} ${c.bold(`Running ${content_block.name}...`)}
|
|
|
7478
7471
|
return new Error(message);
|
|
7479
7472
|
}
|
|
7480
7473
|
}
|
|
7481
|
-
var
|
|
7474
|
+
var DEFAULT_TIMEOUT_MS;
|
|
7482
7475
|
var init_claude_runner = __esm(() => {
|
|
7483
7476
|
init_config();
|
|
7484
7477
|
init_colors();
|
|
7485
7478
|
init_resolve_bin();
|
|
7486
|
-
SANDBOX_SETTINGS = JSON.stringify({
|
|
7487
|
-
permissions: {
|
|
7488
|
-
deny: ["Read(../**)", "Edit(../**)"]
|
|
7489
|
-
},
|
|
7490
|
-
sandbox: {
|
|
7491
|
-
enabled: true,
|
|
7492
|
-
autoAllow: true,
|
|
7493
|
-
allowUnsandboxedCommands: false
|
|
7494
|
-
}
|
|
7495
|
-
});
|
|
7496
7479
|
DEFAULT_TIMEOUT_MS = 60 * 60 * 1000;
|
|
7497
7480
|
});
|
|
7498
7481
|
|
|
@@ -37982,12 +37965,536 @@ var init_models = __esm(() => {
|
|
|
37982
37965
|
init_workspace();
|
|
37983
37966
|
});
|
|
37984
37967
|
|
|
37968
|
+
// ../shared/src/protocol/envelope.ts
|
|
37969
|
+
var PROTOCOL_VERSION = 1, ProtocolVersionSchema, ProtocolEnvelopeSchema;
|
|
37970
|
+
var init_envelope = __esm(() => {
|
|
37971
|
+
init_zod();
|
|
37972
|
+
ProtocolVersionSchema = exports_external.literal(PROTOCOL_VERSION);
|
|
37973
|
+
ProtocolEnvelopeSchema = exports_external.object({
|
|
37974
|
+
protocol: ProtocolVersionSchema,
|
|
37975
|
+
type: exports_external.string()
|
|
37976
|
+
});
|
|
37977
|
+
});
|
|
37978
|
+
|
|
37979
|
+
// ../shared/src/protocol/errors.ts
|
|
37980
|
+
var ProtocolErrorCode, ProtocolErrorCodeSchema, ProtocolErrorSchema;
|
|
37981
|
+
var init_errors3 = __esm(() => {
|
|
37982
|
+
init_zod();
|
|
37983
|
+
ProtocolErrorCode = {
|
|
37984
|
+
CLI_NOT_FOUND: "CLI_NOT_FOUND",
|
|
37985
|
+
AUTH_EXPIRED: "AUTH_EXPIRED",
|
|
37986
|
+
NETWORK_TIMEOUT: "NETWORK_TIMEOUT",
|
|
37987
|
+
CONTEXT_LIMIT: "CONTEXT_LIMIT",
|
|
37988
|
+
MALFORMED_EVENT: "MALFORMED_EVENT",
|
|
37989
|
+
PROCESS_CRASHED: "PROCESS_CRASHED",
|
|
37990
|
+
SESSION_NOT_FOUND: "SESSION_NOT_FOUND",
|
|
37991
|
+
UNKNOWN: "UNKNOWN"
|
|
37992
|
+
};
|
|
37993
|
+
ProtocolErrorCodeSchema = exports_external.enum(ProtocolErrorCode);
|
|
37994
|
+
ProtocolErrorSchema = exports_external.object({
|
|
37995
|
+
code: ProtocolErrorCodeSchema,
|
|
37996
|
+
message: exports_external.string(),
|
|
37997
|
+
details: exports_external.unknown().optional(),
|
|
37998
|
+
recoverable: exports_external.boolean()
|
|
37999
|
+
});
|
|
38000
|
+
});
|
|
38001
|
+
|
|
38002
|
+
// ../shared/src/protocol/cli-stream.ts
|
|
38003
|
+
function createCliStreamEvent(type, sessionId, payload) {
|
|
38004
|
+
return CliStreamEventSchema.parse({
|
|
38005
|
+
protocol: PROTOCOL_VERSION,
|
|
38006
|
+
type,
|
|
38007
|
+
sessionId,
|
|
38008
|
+
timestamp: Date.now(),
|
|
38009
|
+
payload
|
|
38010
|
+
});
|
|
38011
|
+
}
|
|
38012
|
+
var CliStreamEventType, CliStreamEventTypeSchema, CliStreamBaseSchema, CliStartEventSchema, CliTextDeltaEventSchema, CliThinkingEventSchema, CliToolStartedEventSchema, CliToolCompletedEventSchema, CliStatusEventSchema, CliErrorEventSchema, CliDoneEventSchema, CliStreamEventSchema;
|
|
38013
|
+
var init_cli_stream = __esm(() => {
|
|
38014
|
+
init_zod();
|
|
38015
|
+
init_envelope();
|
|
38016
|
+
init_errors3();
|
|
38017
|
+
CliStreamEventType = {
|
|
38018
|
+
START: "start",
|
|
38019
|
+
TEXT_DELTA: "text_delta",
|
|
38020
|
+
THINKING: "thinking",
|
|
38021
|
+
TOOL_STARTED: "tool_started",
|
|
38022
|
+
TOOL_COMPLETED: "tool_completed",
|
|
38023
|
+
STATUS: "status",
|
|
38024
|
+
ERROR: "error",
|
|
38025
|
+
DONE: "done"
|
|
38026
|
+
};
|
|
38027
|
+
CliStreamEventTypeSchema = exports_external.enum(CliStreamEventType);
|
|
38028
|
+
CliStreamBaseSchema = exports_external.object({
|
|
38029
|
+
protocol: ProtocolVersionSchema,
|
|
38030
|
+
sessionId: exports_external.string(),
|
|
38031
|
+
timestamp: exports_external.number()
|
|
38032
|
+
});
|
|
38033
|
+
CliStartEventSchema = CliStreamBaseSchema.extend({
|
|
38034
|
+
type: exports_external.literal(CliStreamEventType.START),
|
|
38035
|
+
payload: exports_external.object({
|
|
38036
|
+
command: exports_external.string(),
|
|
38037
|
+
model: exports_external.string().optional(),
|
|
38038
|
+
provider: exports_external.string().optional(),
|
|
38039
|
+
cwd: exports_external.string().optional()
|
|
38040
|
+
})
|
|
38041
|
+
});
|
|
38042
|
+
CliTextDeltaEventSchema = CliStreamBaseSchema.extend({
|
|
38043
|
+
type: exports_external.literal(CliStreamEventType.TEXT_DELTA),
|
|
38044
|
+
payload: exports_external.object({
|
|
38045
|
+
content: exports_external.string()
|
|
38046
|
+
})
|
|
38047
|
+
});
|
|
38048
|
+
CliThinkingEventSchema = CliStreamBaseSchema.extend({
|
|
38049
|
+
type: exports_external.literal(CliStreamEventType.THINKING),
|
|
38050
|
+
payload: exports_external.object({
|
|
38051
|
+
content: exports_external.string().optional()
|
|
38052
|
+
})
|
|
38053
|
+
});
|
|
38054
|
+
CliToolStartedEventSchema = CliStreamBaseSchema.extend({
|
|
38055
|
+
type: exports_external.literal(CliStreamEventType.TOOL_STARTED),
|
|
38056
|
+
payload: exports_external.object({
|
|
38057
|
+
tool: exports_external.string(),
|
|
38058
|
+
toolId: exports_external.string().optional(),
|
|
38059
|
+
parameters: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
|
|
38060
|
+
})
|
|
38061
|
+
});
|
|
38062
|
+
CliToolCompletedEventSchema = CliStreamBaseSchema.extend({
|
|
38063
|
+
type: exports_external.literal(CliStreamEventType.TOOL_COMPLETED),
|
|
38064
|
+
payload: exports_external.object({
|
|
38065
|
+
tool: exports_external.string(),
|
|
38066
|
+
toolId: exports_external.string().optional(),
|
|
38067
|
+
success: exports_external.boolean(),
|
|
38068
|
+
duration: exports_external.number().optional(),
|
|
38069
|
+
error: exports_external.string().optional()
|
|
38070
|
+
})
|
|
38071
|
+
});
|
|
38072
|
+
CliStatusEventSchema = CliStreamBaseSchema.extend({
|
|
38073
|
+
type: exports_external.literal(CliStreamEventType.STATUS),
|
|
38074
|
+
payload: exports_external.object({
|
|
38075
|
+
status: exports_external.string(),
|
|
38076
|
+
message: exports_external.string().optional()
|
|
38077
|
+
})
|
|
38078
|
+
});
|
|
38079
|
+
CliErrorEventSchema = CliStreamBaseSchema.extend({
|
|
38080
|
+
type: exports_external.literal(CliStreamEventType.ERROR),
|
|
38081
|
+
payload: exports_external.object({
|
|
38082
|
+
error: ProtocolErrorSchema
|
|
38083
|
+
})
|
|
38084
|
+
});
|
|
38085
|
+
CliDoneEventSchema = CliStreamBaseSchema.extend({
|
|
38086
|
+
type: exports_external.literal(CliStreamEventType.DONE),
|
|
38087
|
+
payload: exports_external.object({
|
|
38088
|
+
exitCode: exports_external.number().int(),
|
|
38089
|
+
duration: exports_external.number(),
|
|
38090
|
+
toolsUsed: exports_external.array(exports_external.string()).optional(),
|
|
38091
|
+
tokensUsed: exports_external.number().optional(),
|
|
38092
|
+
success: exports_external.boolean()
|
|
38093
|
+
})
|
|
38094
|
+
});
|
|
38095
|
+
CliStreamEventSchema = exports_external.discriminatedUnion("type", [
|
|
38096
|
+
CliStartEventSchema,
|
|
38097
|
+
CliTextDeltaEventSchema,
|
|
38098
|
+
CliThinkingEventSchema,
|
|
38099
|
+
CliToolStartedEventSchema,
|
|
38100
|
+
CliToolCompletedEventSchema,
|
|
38101
|
+
CliStatusEventSchema,
|
|
38102
|
+
CliErrorEventSchema,
|
|
38103
|
+
CliDoneEventSchema
|
|
38104
|
+
]);
|
|
38105
|
+
});
|
|
38106
|
+
|
|
38107
|
+
// ../shared/src/protocol/context.ts
|
|
38108
|
+
var ActiveFileContextSchema, SelectionContextSchema, WorkspaceContextSchema, ContextPayloadSchema;
|
|
38109
|
+
var init_context = __esm(() => {
|
|
38110
|
+
init_zod();
|
|
38111
|
+
ActiveFileContextSchema = exports_external.object({
|
|
38112
|
+
filePath: exports_external.string(),
|
|
38113
|
+
languageId: exports_external.string().optional()
|
|
38114
|
+
});
|
|
38115
|
+
SelectionContextSchema = exports_external.object({
|
|
38116
|
+
filePath: exports_external.string(),
|
|
38117
|
+
languageId: exports_external.string().optional(),
|
|
38118
|
+
startLine: exports_external.number().int().min(0),
|
|
38119
|
+
startColumn: exports_external.number().int().min(0),
|
|
38120
|
+
endLine: exports_external.number().int().min(0),
|
|
38121
|
+
endColumn: exports_external.number().int().min(0),
|
|
38122
|
+
text: exports_external.string()
|
|
38123
|
+
});
|
|
38124
|
+
WorkspaceContextSchema = exports_external.object({
|
|
38125
|
+
rootPath: exports_external.string(),
|
|
38126
|
+
name: exports_external.string().optional()
|
|
38127
|
+
});
|
|
38128
|
+
ContextPayloadSchema = exports_external.object({
|
|
38129
|
+
workspace: WorkspaceContextSchema.optional(),
|
|
38130
|
+
activeFile: ActiveFileContextSchema.optional(),
|
|
38131
|
+
selection: SelectionContextSchema.optional()
|
|
38132
|
+
});
|
|
38133
|
+
});
|
|
38134
|
+
|
|
38135
|
+
// ../shared/src/protocol/session.ts
|
|
38136
|
+
var SessionStatus, SessionStatusSchema, SessionTransitionEvent, SessionTransitionEventSchema, SESSION_TRANSITIONS, TERMINAL_STATUSES, SessionMetadataSchema, SessionSummarySchema;
|
|
38137
|
+
var init_session = __esm(() => {
|
|
38138
|
+
init_zod();
|
|
38139
|
+
SessionStatus = {
|
|
38140
|
+
IDLE: "idle",
|
|
38141
|
+
STARTING: "starting",
|
|
38142
|
+
RUNNING: "running",
|
|
38143
|
+
STREAMING: "streaming",
|
|
38144
|
+
COMPLETED: "completed",
|
|
38145
|
+
CANCELED: "canceled",
|
|
38146
|
+
INTERRUPTED: "interrupted",
|
|
38147
|
+
FAILED: "failed",
|
|
38148
|
+
RESUMING: "resuming"
|
|
38149
|
+
};
|
|
38150
|
+
SessionStatusSchema = exports_external.enum(SessionStatus);
|
|
38151
|
+
SessionTransitionEvent = {
|
|
38152
|
+
CREATE_SESSION: "create_session",
|
|
38153
|
+
CLI_SPAWNED: "cli_spawned",
|
|
38154
|
+
FIRST_TEXT_DELTA: "first_text_delta",
|
|
38155
|
+
RESULT_RECEIVED: "result_received",
|
|
38156
|
+
USER_STOP: "user_stop",
|
|
38157
|
+
PROCESS_LOST: "process_lost",
|
|
38158
|
+
RESUME: "resume",
|
|
38159
|
+
ERROR: "error"
|
|
38160
|
+
};
|
|
38161
|
+
SessionTransitionEventSchema = exports_external.enum(SessionTransitionEvent);
|
|
38162
|
+
SESSION_TRANSITIONS = [
|
|
38163
|
+
{
|
|
38164
|
+
from: SessionStatus.IDLE,
|
|
38165
|
+
event: SessionTransitionEvent.CREATE_SESSION,
|
|
38166
|
+
to: SessionStatus.STARTING
|
|
38167
|
+
},
|
|
38168
|
+
{
|
|
38169
|
+
from: SessionStatus.STARTING,
|
|
38170
|
+
event: SessionTransitionEvent.CLI_SPAWNED,
|
|
38171
|
+
to: SessionStatus.RUNNING
|
|
38172
|
+
},
|
|
38173
|
+
{
|
|
38174
|
+
from: SessionStatus.STARTING,
|
|
38175
|
+
event: SessionTransitionEvent.ERROR,
|
|
38176
|
+
to: SessionStatus.FAILED
|
|
38177
|
+
},
|
|
38178
|
+
{
|
|
38179
|
+
from: SessionStatus.RUNNING,
|
|
38180
|
+
event: SessionTransitionEvent.FIRST_TEXT_DELTA,
|
|
38181
|
+
to: SessionStatus.STREAMING
|
|
38182
|
+
},
|
|
38183
|
+
{
|
|
38184
|
+
from: SessionStatus.RUNNING,
|
|
38185
|
+
event: SessionTransitionEvent.USER_STOP,
|
|
38186
|
+
to: SessionStatus.CANCELED
|
|
38187
|
+
},
|
|
38188
|
+
{
|
|
38189
|
+
from: SessionStatus.RUNNING,
|
|
38190
|
+
event: SessionTransitionEvent.PROCESS_LOST,
|
|
38191
|
+
to: SessionStatus.INTERRUPTED
|
|
38192
|
+
},
|
|
38193
|
+
{
|
|
38194
|
+
from: SessionStatus.RUNNING,
|
|
38195
|
+
event: SessionTransitionEvent.ERROR,
|
|
38196
|
+
to: SessionStatus.FAILED
|
|
38197
|
+
},
|
|
38198
|
+
{
|
|
38199
|
+
from: SessionStatus.STREAMING,
|
|
38200
|
+
event: SessionTransitionEvent.RESULT_RECEIVED,
|
|
38201
|
+
to: SessionStatus.COMPLETED
|
|
38202
|
+
},
|
|
38203
|
+
{
|
|
38204
|
+
from: SessionStatus.STREAMING,
|
|
38205
|
+
event: SessionTransitionEvent.USER_STOP,
|
|
38206
|
+
to: SessionStatus.CANCELED
|
|
38207
|
+
},
|
|
38208
|
+
{
|
|
38209
|
+
from: SessionStatus.STREAMING,
|
|
38210
|
+
event: SessionTransitionEvent.PROCESS_LOST,
|
|
38211
|
+
to: SessionStatus.INTERRUPTED
|
|
38212
|
+
},
|
|
38213
|
+
{
|
|
38214
|
+
from: SessionStatus.STREAMING,
|
|
38215
|
+
event: SessionTransitionEvent.ERROR,
|
|
38216
|
+
to: SessionStatus.FAILED
|
|
38217
|
+
},
|
|
38218
|
+
{
|
|
38219
|
+
from: SessionStatus.INTERRUPTED,
|
|
38220
|
+
event: SessionTransitionEvent.RESUME,
|
|
38221
|
+
to: SessionStatus.RESUMING
|
|
38222
|
+
},
|
|
38223
|
+
{
|
|
38224
|
+
from: SessionStatus.RESUMING,
|
|
38225
|
+
event: SessionTransitionEvent.CLI_SPAWNED,
|
|
38226
|
+
to: SessionStatus.RUNNING
|
|
38227
|
+
},
|
|
38228
|
+
{
|
|
38229
|
+
from: SessionStatus.RESUMING,
|
|
38230
|
+
event: SessionTransitionEvent.ERROR,
|
|
38231
|
+
to: SessionStatus.FAILED
|
|
38232
|
+
},
|
|
38233
|
+
{
|
|
38234
|
+
from: SessionStatus.COMPLETED,
|
|
38235
|
+
event: SessionTransitionEvent.CREATE_SESSION,
|
|
38236
|
+
to: SessionStatus.STARTING
|
|
38237
|
+
},
|
|
38238
|
+
{
|
|
38239
|
+
from: SessionStatus.CANCELED,
|
|
38240
|
+
event: SessionTransitionEvent.CREATE_SESSION,
|
|
38241
|
+
to: SessionStatus.STARTING
|
|
38242
|
+
},
|
|
38243
|
+
{
|
|
38244
|
+
from: SessionStatus.FAILED,
|
|
38245
|
+
event: SessionTransitionEvent.CREATE_SESSION,
|
|
38246
|
+
to: SessionStatus.STARTING
|
|
38247
|
+
}
|
|
38248
|
+
];
|
|
38249
|
+
TERMINAL_STATUSES = new Set([
|
|
38250
|
+
SessionStatus.COMPLETED,
|
|
38251
|
+
SessionStatus.CANCELED,
|
|
38252
|
+
SessionStatus.FAILED
|
|
38253
|
+
]);
|
|
38254
|
+
SessionMetadataSchema = exports_external.object({
|
|
38255
|
+
sessionId: exports_external.string(),
|
|
38256
|
+
status: SessionStatusSchema,
|
|
38257
|
+
model: exports_external.string().optional(),
|
|
38258
|
+
createdAt: exports_external.number(),
|
|
38259
|
+
updatedAt: exports_external.number(),
|
|
38260
|
+
title: exports_external.string().optional()
|
|
38261
|
+
});
|
|
38262
|
+
SessionSummarySchema = exports_external.object({
|
|
38263
|
+
sessionId: exports_external.string(),
|
|
38264
|
+
status: SessionStatusSchema,
|
|
38265
|
+
model: exports_external.string().optional(),
|
|
38266
|
+
title: exports_external.string().optional(),
|
|
38267
|
+
createdAt: exports_external.number(),
|
|
38268
|
+
updatedAt: exports_external.number(),
|
|
38269
|
+
messageCount: exports_external.number(),
|
|
38270
|
+
toolCount: exports_external.number()
|
|
38271
|
+
});
|
|
38272
|
+
});
|
|
38273
|
+
|
|
38274
|
+
// ../shared/src/protocol/host-events.ts
|
|
38275
|
+
var HostEventType, HostEventTypeSchema, TimelineEntryKind, TimelineEntryKindSchema, TimelineEntrySchema, SessionStateEventSchema, TextDeltaEventSchema, ToolStartedEventSchema, ToolCompletedEventSchema, ThinkingEventSchema, ErrorEventSchema, SessionListEventSchema, SessionCompletedEventSchema, HostEventSchema;
|
|
38276
|
+
var init_host_events = __esm(() => {
|
|
38277
|
+
init_zod();
|
|
38278
|
+
init_envelope();
|
|
38279
|
+
init_errors3();
|
|
38280
|
+
init_session();
|
|
38281
|
+
HostEventType = {
|
|
38282
|
+
SESSION_STATE: "session_state",
|
|
38283
|
+
TEXT_DELTA: "text_delta",
|
|
38284
|
+
TOOL_STARTED: "tool_started",
|
|
38285
|
+
TOOL_COMPLETED: "tool_completed",
|
|
38286
|
+
THINKING: "thinking",
|
|
38287
|
+
ERROR: "error",
|
|
38288
|
+
SESSION_LIST: "session_list",
|
|
38289
|
+
SESSION_COMPLETED: "session_completed"
|
|
38290
|
+
};
|
|
38291
|
+
HostEventTypeSchema = exports_external.enum(HostEventType);
|
|
38292
|
+
TimelineEntryKind = {
|
|
38293
|
+
MESSAGE: "message",
|
|
38294
|
+
TOOL_CALL: "tool_call",
|
|
38295
|
+
STATUS: "status",
|
|
38296
|
+
ERROR: "error",
|
|
38297
|
+
DONE: "done"
|
|
38298
|
+
};
|
|
38299
|
+
TimelineEntryKindSchema = exports_external.enum(TimelineEntryKind);
|
|
38300
|
+
TimelineEntrySchema = exports_external.object({
|
|
38301
|
+
id: exports_external.string(),
|
|
38302
|
+
kind: TimelineEntryKindSchema,
|
|
38303
|
+
timestamp: exports_external.number(),
|
|
38304
|
+
data: exports_external.record(exports_external.string(), exports_external.unknown())
|
|
38305
|
+
});
|
|
38306
|
+
SessionStateEventSchema = exports_external.object({
|
|
38307
|
+
protocol: ProtocolVersionSchema,
|
|
38308
|
+
type: exports_external.literal(HostEventType.SESSION_STATE),
|
|
38309
|
+
payload: exports_external.object({
|
|
38310
|
+
sessionId: exports_external.string(),
|
|
38311
|
+
status: SessionStatusSchema,
|
|
38312
|
+
metadata: SessionMetadataSchema.optional(),
|
|
38313
|
+
timeline: exports_external.array(TimelineEntrySchema).optional()
|
|
38314
|
+
})
|
|
38315
|
+
});
|
|
38316
|
+
TextDeltaEventSchema = exports_external.object({
|
|
38317
|
+
protocol: ProtocolVersionSchema,
|
|
38318
|
+
type: exports_external.literal(HostEventType.TEXT_DELTA),
|
|
38319
|
+
payload: exports_external.object({
|
|
38320
|
+
sessionId: exports_external.string(),
|
|
38321
|
+
content: exports_external.string()
|
|
38322
|
+
})
|
|
38323
|
+
});
|
|
38324
|
+
ToolStartedEventSchema = exports_external.object({
|
|
38325
|
+
protocol: ProtocolVersionSchema,
|
|
38326
|
+
type: exports_external.literal(HostEventType.TOOL_STARTED),
|
|
38327
|
+
payload: exports_external.object({
|
|
38328
|
+
sessionId: exports_external.string(),
|
|
38329
|
+
tool: exports_external.string(),
|
|
38330
|
+
toolId: exports_external.string().optional(),
|
|
38331
|
+
parameters: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
|
|
38332
|
+
})
|
|
38333
|
+
});
|
|
38334
|
+
ToolCompletedEventSchema = exports_external.object({
|
|
38335
|
+
protocol: ProtocolVersionSchema,
|
|
38336
|
+
type: exports_external.literal(HostEventType.TOOL_COMPLETED),
|
|
38337
|
+
payload: exports_external.object({
|
|
38338
|
+
sessionId: exports_external.string(),
|
|
38339
|
+
tool: exports_external.string(),
|
|
38340
|
+
toolId: exports_external.string().optional(),
|
|
38341
|
+
result: exports_external.unknown().optional(),
|
|
38342
|
+
duration: exports_external.number().optional(),
|
|
38343
|
+
success: exports_external.boolean(),
|
|
38344
|
+
error: exports_external.string().optional()
|
|
38345
|
+
})
|
|
38346
|
+
});
|
|
38347
|
+
ThinkingEventSchema = exports_external.object({
|
|
38348
|
+
protocol: ProtocolVersionSchema,
|
|
38349
|
+
type: exports_external.literal(HostEventType.THINKING),
|
|
38350
|
+
payload: exports_external.object({
|
|
38351
|
+
sessionId: exports_external.string(),
|
|
38352
|
+
content: exports_external.string().optional()
|
|
38353
|
+
})
|
|
38354
|
+
});
|
|
38355
|
+
ErrorEventSchema = exports_external.object({
|
|
38356
|
+
protocol: ProtocolVersionSchema,
|
|
38357
|
+
type: exports_external.literal(HostEventType.ERROR),
|
|
38358
|
+
payload: exports_external.object({
|
|
38359
|
+
sessionId: exports_external.string().optional(),
|
|
38360
|
+
error: ProtocolErrorSchema
|
|
38361
|
+
})
|
|
38362
|
+
});
|
|
38363
|
+
SessionListEventSchema = exports_external.object({
|
|
38364
|
+
protocol: ProtocolVersionSchema,
|
|
38365
|
+
type: exports_external.literal(HostEventType.SESSION_LIST),
|
|
38366
|
+
payload: exports_external.object({
|
|
38367
|
+
sessions: exports_external.array(SessionSummarySchema)
|
|
38368
|
+
})
|
|
38369
|
+
});
|
|
38370
|
+
SessionCompletedEventSchema = exports_external.object({
|
|
38371
|
+
protocol: ProtocolVersionSchema,
|
|
38372
|
+
type: exports_external.literal(HostEventType.SESSION_COMPLETED),
|
|
38373
|
+
payload: exports_external.object({
|
|
38374
|
+
sessionId: exports_external.string(),
|
|
38375
|
+
summary: exports_external.string().optional()
|
|
38376
|
+
})
|
|
38377
|
+
});
|
|
38378
|
+
HostEventSchema = exports_external.discriminatedUnion("type", [
|
|
38379
|
+
SessionStateEventSchema,
|
|
38380
|
+
TextDeltaEventSchema,
|
|
38381
|
+
ToolStartedEventSchema,
|
|
38382
|
+
ToolCompletedEventSchema,
|
|
38383
|
+
ThinkingEventSchema,
|
|
38384
|
+
ErrorEventSchema,
|
|
38385
|
+
SessionListEventSchema,
|
|
38386
|
+
SessionCompletedEventSchema
|
|
38387
|
+
]);
|
|
38388
|
+
});
|
|
38389
|
+
|
|
38390
|
+
// ../shared/src/protocol/ui-intents.ts
|
|
38391
|
+
var UIIntentType, UIIntentTypeSchema, SubmitPromptIntentSchema, StopSessionIntentSchema, ResumeSessionIntentSchema, RequestSessionsIntentSchema, RequestSessionDetailIntentSchema, ClearSessionIntentSchema, WebviewReadyIntentSchema, UIIntentSchema;
|
|
38392
|
+
var init_ui_intents = __esm(() => {
|
|
38393
|
+
init_zod();
|
|
38394
|
+
init_context();
|
|
38395
|
+
init_envelope();
|
|
38396
|
+
UIIntentType = {
|
|
38397
|
+
SUBMIT_PROMPT: "submit_prompt",
|
|
38398
|
+
STOP_SESSION: "stop_session",
|
|
38399
|
+
RESUME_SESSION: "resume_session",
|
|
38400
|
+
REQUEST_SESSIONS: "request_sessions",
|
|
38401
|
+
REQUEST_SESSION_DETAIL: "request_session_detail",
|
|
38402
|
+
CLEAR_SESSION: "clear_session",
|
|
38403
|
+
WEBVIEW_READY: "webview_ready"
|
|
38404
|
+
};
|
|
38405
|
+
UIIntentTypeSchema = exports_external.enum(UIIntentType);
|
|
38406
|
+
SubmitPromptIntentSchema = exports_external.object({
|
|
38407
|
+
protocol: ProtocolVersionSchema,
|
|
38408
|
+
type: exports_external.literal(UIIntentType.SUBMIT_PROMPT),
|
|
38409
|
+
payload: exports_external.object({
|
|
38410
|
+
text: exports_external.string().min(1),
|
|
38411
|
+
context: ContextPayloadSchema.optional()
|
|
38412
|
+
})
|
|
38413
|
+
});
|
|
38414
|
+
StopSessionIntentSchema = exports_external.object({
|
|
38415
|
+
protocol: ProtocolVersionSchema,
|
|
38416
|
+
type: exports_external.literal(UIIntentType.STOP_SESSION),
|
|
38417
|
+
payload: exports_external.object({
|
|
38418
|
+
sessionId: exports_external.string()
|
|
38419
|
+
})
|
|
38420
|
+
});
|
|
38421
|
+
ResumeSessionIntentSchema = exports_external.object({
|
|
38422
|
+
protocol: ProtocolVersionSchema,
|
|
38423
|
+
type: exports_external.literal(UIIntentType.RESUME_SESSION),
|
|
38424
|
+
payload: exports_external.object({
|
|
38425
|
+
sessionId: exports_external.string()
|
|
38426
|
+
})
|
|
38427
|
+
});
|
|
38428
|
+
RequestSessionsIntentSchema = exports_external.object({
|
|
38429
|
+
protocol: ProtocolVersionSchema,
|
|
38430
|
+
type: exports_external.literal(UIIntentType.REQUEST_SESSIONS),
|
|
38431
|
+
payload: exports_external.object({}).optional()
|
|
38432
|
+
});
|
|
38433
|
+
RequestSessionDetailIntentSchema = exports_external.object({
|
|
38434
|
+
protocol: ProtocolVersionSchema,
|
|
38435
|
+
type: exports_external.literal(UIIntentType.REQUEST_SESSION_DETAIL),
|
|
38436
|
+
payload: exports_external.object({
|
|
38437
|
+
sessionId: exports_external.string()
|
|
38438
|
+
})
|
|
38439
|
+
});
|
|
38440
|
+
ClearSessionIntentSchema = exports_external.object({
|
|
38441
|
+
protocol: ProtocolVersionSchema,
|
|
38442
|
+
type: exports_external.literal(UIIntentType.CLEAR_SESSION),
|
|
38443
|
+
payload: exports_external.object({
|
|
38444
|
+
sessionId: exports_external.string()
|
|
38445
|
+
})
|
|
38446
|
+
});
|
|
38447
|
+
WebviewReadyIntentSchema = exports_external.object({
|
|
38448
|
+
protocol: ProtocolVersionSchema,
|
|
38449
|
+
type: exports_external.literal(UIIntentType.WEBVIEW_READY),
|
|
38450
|
+
payload: exports_external.object({}).optional()
|
|
38451
|
+
});
|
|
38452
|
+
UIIntentSchema = exports_external.discriminatedUnion("type", [
|
|
38453
|
+
SubmitPromptIntentSchema,
|
|
38454
|
+
StopSessionIntentSchema,
|
|
38455
|
+
ResumeSessionIntentSchema,
|
|
38456
|
+
RequestSessionsIntentSchema,
|
|
38457
|
+
RequestSessionDetailIntentSchema,
|
|
38458
|
+
ClearSessionIntentSchema,
|
|
38459
|
+
WebviewReadyIntentSchema
|
|
38460
|
+
]);
|
|
38461
|
+
});
|
|
38462
|
+
|
|
38463
|
+
// ../shared/src/protocol/helpers.ts
|
|
38464
|
+
function createProtocolError(code, message, options) {
|
|
38465
|
+
return {
|
|
38466
|
+
code,
|
|
38467
|
+
message,
|
|
38468
|
+
details: options?.details,
|
|
38469
|
+
recoverable: options?.recoverable ?? false
|
|
38470
|
+
};
|
|
38471
|
+
}
|
|
38472
|
+
var init_helpers = __esm(() => {
|
|
38473
|
+
init_envelope();
|
|
38474
|
+
init_host_events();
|
|
38475
|
+
init_session();
|
|
38476
|
+
init_ui_intents();
|
|
38477
|
+
});
|
|
38478
|
+
|
|
38479
|
+
// ../shared/src/protocol/index.ts
|
|
38480
|
+
var init_protocol = __esm(() => {
|
|
38481
|
+
init_cli_stream();
|
|
38482
|
+
init_context();
|
|
38483
|
+
init_envelope();
|
|
38484
|
+
init_errors3();
|
|
38485
|
+
init_helpers();
|
|
38486
|
+
init_host_events();
|
|
38487
|
+
init_session();
|
|
38488
|
+
init_ui_intents();
|
|
38489
|
+
});
|
|
38490
|
+
|
|
37985
38491
|
// ../shared/src/index.ts
|
|
37986
38492
|
var init_src = __esm(() => {
|
|
37987
38493
|
init_common();
|
|
37988
38494
|
init_constants();
|
|
37989
38495
|
init_enums();
|
|
37990
38496
|
init_models();
|
|
38497
|
+
init_protocol();
|
|
37991
38498
|
});
|
|
37992
38499
|
|
|
37993
38500
|
// ../sdk/src/modules/tasks.ts
|
|
@@ -38273,11 +38780,11 @@ ${line}`;
|
|
|
38273
38780
|
writeFileSync3(this.progressPath, updated);
|
|
38274
38781
|
}
|
|
38275
38782
|
getFullContext() {
|
|
38276
|
-
const
|
|
38783
|
+
const context2 = this.readContext();
|
|
38277
38784
|
const progress = this.readProgress();
|
|
38278
38785
|
const parts = [];
|
|
38279
|
-
if (
|
|
38280
|
-
parts.push(
|
|
38786
|
+
if (context2.trim()) {
|
|
38787
|
+
parts.push(context2.trim());
|
|
38281
38788
|
}
|
|
38282
38789
|
if (progress.trim()) {
|
|
38283
38790
|
parts.push(progress.trim());
|
|
@@ -38602,10 +39109,10 @@ ${task2.description || "No description provided."}
|
|
|
38602
39109
|
let hasLocalContext = false;
|
|
38603
39110
|
if (existsSync6(contextPath)) {
|
|
38604
39111
|
try {
|
|
38605
|
-
const
|
|
38606
|
-
if (
|
|
39112
|
+
const context2 = readFileSync6(contextPath, "utf-8");
|
|
39113
|
+
if (context2.trim().length > 20) {
|
|
38607
39114
|
prompt += `## Project Context (Local)
|
|
38608
|
-
${
|
|
39115
|
+
${context2}
|
|
38609
39116
|
|
|
38610
39117
|
`;
|
|
38611
39118
|
hasLocalContext = true;
|
|
@@ -38735,10 +39242,10 @@ ${query}
|
|
|
38735
39242
|
let hasLocalContext = false;
|
|
38736
39243
|
if (existsSync6(contextPath)) {
|
|
38737
39244
|
try {
|
|
38738
|
-
const
|
|
38739
|
-
if (
|
|
39245
|
+
const context2 = readFileSync6(contextPath, "utf-8");
|
|
39246
|
+
if (context2.trim().length > 20) {
|
|
38740
39247
|
prompt += `## Project Context (Local)
|
|
38741
|
-
${
|
|
39248
|
+
${context2}
|
|
38742
39249
|
|
|
38743
39250
|
`;
|
|
38744
39251
|
hasLocalContext = true;
|
|
@@ -39696,10 +40203,10 @@ class HistoryManager {
|
|
|
39696
40203
|
getSessionPath(sessionId) {
|
|
39697
40204
|
return join7(this.historyDir, `${sessionId}.json`);
|
|
39698
40205
|
}
|
|
39699
|
-
saveSession(
|
|
39700
|
-
const filePath = this.getSessionPath(
|
|
39701
|
-
|
|
39702
|
-
writeFileSync4(filePath, JSON.stringify(
|
|
40206
|
+
saveSession(session2) {
|
|
40207
|
+
const filePath = this.getSessionPath(session2.id);
|
|
40208
|
+
session2.updatedAt = Date.now();
|
|
40209
|
+
writeFileSync4(filePath, JSON.stringify(session2, null, 2), "utf-8");
|
|
39703
40210
|
}
|
|
39704
40211
|
loadSession(sessionId) {
|
|
39705
40212
|
const filePath = this.getSessionPath(sessionId);
|
|
@@ -39730,9 +40237,9 @@ class HistoryManager {
|
|
|
39730
40237
|
let sessions = [];
|
|
39731
40238
|
for (const file2 of files) {
|
|
39732
40239
|
if (file2.endsWith(".json")) {
|
|
39733
|
-
const
|
|
39734
|
-
if (
|
|
39735
|
-
sessions.push(
|
|
40240
|
+
const session2 = this.loadSession(file2.replace(".json", ""));
|
|
40241
|
+
if (session2) {
|
|
40242
|
+
sessions.push(session2);
|
|
39736
40243
|
}
|
|
39737
40244
|
}
|
|
39738
40245
|
}
|
|
@@ -39754,7 +40261,7 @@ class HistoryManager {
|
|
|
39754
40261
|
}
|
|
39755
40262
|
if (options.query) {
|
|
39756
40263
|
const query = options.query.toLowerCase();
|
|
39757
|
-
filtered = filtered.filter((
|
|
40264
|
+
filtered = filtered.filter((session2) => session2.messages.some((msg) => msg.content.toLowerCase().includes(query)));
|
|
39758
40265
|
}
|
|
39759
40266
|
const offset = options.offset ?? 0;
|
|
39760
40267
|
const limit = options.limit ?? filtered.length;
|
|
@@ -39790,8 +40297,8 @@ class HistoryManager {
|
|
|
39790
40297
|
let deleted = 0;
|
|
39791
40298
|
if (sessions.length > this.maxSessions) {
|
|
39792
40299
|
const sessionsToDelete = sessions.slice(this.maxSessions);
|
|
39793
|
-
for (const
|
|
39794
|
-
if (this.deleteSession(
|
|
40300
|
+
for (const session2 of sessionsToDelete) {
|
|
40301
|
+
if (this.deleteSession(session2.id)) {
|
|
39795
40302
|
deleted++;
|
|
39796
40303
|
}
|
|
39797
40304
|
}
|
|
@@ -40487,7 +40994,14 @@ function plannedTasksToCreatePayloads(plan, sprintId) {
|
|
|
40487
40994
|
}
|
|
40488
40995
|
function parseSprintPlanFromAI(raw, directive) {
|
|
40489
40996
|
const jsonStr = extractJsonFromLLMOutput(raw);
|
|
40490
|
-
let parsed
|
|
40997
|
+
let parsed;
|
|
40998
|
+
try {
|
|
40999
|
+
parsed = JSON.parse(jsonStr);
|
|
41000
|
+
} catch (err) {
|
|
41001
|
+
const preview = jsonStr.slice(0, 200);
|
|
41002
|
+
throw new Error(`Failed to parse sprint plan JSON: ${err instanceof Error ? err.message : String(err)}
|
|
41003
|
+
Extracted JSON preview: ${preview}`);
|
|
41004
|
+
}
|
|
40491
41005
|
if (parsed.revisedPlan) {
|
|
40492
41006
|
parsed = parsed.revisedPlan;
|
|
40493
41007
|
}
|
|
@@ -40676,78 +41190,6 @@ var init_plan_manager = __esm(() => {
|
|
|
40676
41190
|
init_sprint_plan();
|
|
40677
41191
|
});
|
|
40678
41192
|
|
|
40679
|
-
// ../sdk/src/planning/agents/architect.ts
|
|
40680
|
-
function buildArchitectPrompt(input) {
|
|
40681
|
-
let prompt = `# Role: Software Architect
|
|
40682
|
-
|
|
40683
|
-
You are a Software Architect participating in an async sprint planning meeting. The Tech Lead has produced an initial task breakdown. Your job is to refine it.
|
|
40684
|
-
|
|
40685
|
-
## CEO Directive
|
|
40686
|
-
> ${input.directive}
|
|
40687
|
-
`;
|
|
40688
|
-
if (input.feedback) {
|
|
40689
|
-
prompt += `
|
|
40690
|
-
## CEO Feedback on Previous Plan
|
|
40691
|
-
> ${input.feedback}
|
|
40692
|
-
|
|
40693
|
-
IMPORTANT: Ensure the refined plan addresses this feedback.
|
|
40694
|
-
`;
|
|
40695
|
-
}
|
|
40696
|
-
prompt += `
|
|
40697
|
-
## Project Context
|
|
40698
|
-
${input.projectContext || "No project context available."}
|
|
40699
|
-
|
|
40700
|
-
## Tech Lead's Task Breakdown
|
|
40701
|
-
${input.techLeadOutput}
|
|
40702
|
-
|
|
40703
|
-
## Your Task
|
|
40704
|
-
|
|
40705
|
-
Review and refine the Tech Lead's breakdown:
|
|
40706
|
-
|
|
40707
|
-
1. **Ordering** — Order tasks so that foundational work comes first. Tasks that produce outputs consumed by later tasks must appear earlier in the list. Foundation tasks (schemas, config, shared code) must be listed before tasks that build on them. The array index IS the execution order.
|
|
40708
|
-
2. **Risk Assessment** — Flag tasks that are risky, underestimated, or have unknowns.
|
|
40709
|
-
3. **Task Merging** — If two tasks are trivially small and related, merge them.
|
|
40710
|
-
4. **Complexity Scoring** — Rate each task 1-5 (1=trivial, 5=very complex).
|
|
40711
|
-
5. **Missing Tasks** — Add any tasks the Tech Lead missed (database migrations, configuration, testing, etc.).
|
|
40712
|
-
6. **Description Quality** — Review and improve each task description to be a clear, actionable implementation guide. Each description must tell the executing agent exactly what to do, where to do it (specific files/modules), how to do it (patterns, utilities, data flow), and what is NOT in scope. Vague descriptions like "Add authentication" must be rewritten with specific file paths, implementation approach, and boundaries.
|
|
40713
|
-
|
|
40714
|
-
## CRITICAL: Task Ordering & Dependencies
|
|
40715
|
-
|
|
40716
|
-
Tasks are executed SEQUENTIALLY by a single agent on ONE branch. The agent works through tasks in array order. Each completed task's changes are available to subsequent tasks. You MUST enforce these rules:
|
|
40717
|
-
|
|
40718
|
-
1. **Order tasks by dependency.** Foundation tasks (schemas, config, shared code) must come first. Tasks that build on earlier work must appear later in the list.
|
|
40719
|
-
2. **Each task must be self-contained for its scope.** A task can depend on earlier tasks (they run sequentially), but must include all changes needed for its own goal.
|
|
40720
|
-
3. **Split tasks at logical boundaries.** Since tasks run sequentially on the same branch, splitting is safe — later tasks see earlier changes. Split when it improves clarity and reviewability.
|
|
40721
|
-
4. **Flag risks.** In your risk assessment, call out tasks that are complex or have unknowns.
|
|
40722
|
-
|
|
40723
|
-
## Output Format
|
|
40724
|
-
|
|
40725
|
-
Your entire response must be a single JSON object — no text before it, no text after it, no markdown code blocks, no explanation. Start your response with the "{" character:
|
|
40726
|
-
|
|
40727
|
-
{
|
|
40728
|
-
"tasks": [
|
|
40729
|
-
{
|
|
40730
|
-
"title": "string",
|
|
40731
|
-
"description": "string (detailed implementation guide: what to do, where to do it, how to do it, and boundaries)",
|
|
40732
|
-
"assigneeRole": "BACKEND | FRONTEND | QA | PM | DESIGN",
|
|
40733
|
-
"priority": "HIGH | MEDIUM | LOW | CRITICAL",
|
|
40734
|
-
"labels": ["string"],
|
|
40735
|
-
"acceptanceCriteria": ["string"],
|
|
40736
|
-
"complexity": 3
|
|
40737
|
-
}
|
|
40738
|
-
],
|
|
40739
|
-
"risks": [
|
|
40740
|
-
{
|
|
40741
|
-
"description": "string",
|
|
40742
|
-
"mitigation": "string",
|
|
40743
|
-
"severity": "low | medium | high"
|
|
40744
|
-
}
|
|
40745
|
-
],
|
|
40746
|
-
"architectureNotes": "string (notes for the Sprint Organizer about parallelism opportunities and constraints)"
|
|
40747
|
-
}`;
|
|
40748
|
-
return prompt;
|
|
40749
|
-
}
|
|
40750
|
-
|
|
40751
41193
|
// ../sdk/src/planning/agents/cross-task-reviewer.ts
|
|
40752
41194
|
function buildCrossTaskReviewerPrompt(input) {
|
|
40753
41195
|
let prompt = `# Role: Cross-Task Reviewer (Architect + Engineer + Planner)
|
|
@@ -40783,7 +41225,7 @@ IMPORTANT: Ensure the reviewed plan still addresses this feedback.
|
|
|
40783
41225
|
${input.projectContext || "No project context available."}
|
|
40784
41226
|
|
|
40785
41227
|
## Sprint Plan to Review
|
|
40786
|
-
${input.
|
|
41228
|
+
${input.plannerOutput}
|
|
40787
41229
|
|
|
40788
41230
|
## Your Review Checklist
|
|
40789
41231
|
|
|
@@ -40862,11 +41304,11 @@ IMPORTANT:
|
|
|
40862
41304
|
return prompt;
|
|
40863
41305
|
}
|
|
40864
41306
|
|
|
40865
|
-
// ../sdk/src/planning/agents/
|
|
40866
|
-
function
|
|
40867
|
-
let prompt = `# Role: Sprint
|
|
41307
|
+
// ../sdk/src/planning/agents/planner.ts
|
|
41308
|
+
function buildPlannerPrompt(input) {
|
|
41309
|
+
let prompt = `# Role: Sprint Planner
|
|
40868
41310
|
|
|
40869
|
-
You are a Sprint
|
|
41311
|
+
You are a Sprint Planner — an expert engineer, architect, and project organizer rolled into one. Your job is to take a CEO directive and produce a complete, ready-to-execute sprint plan in a single pass.
|
|
40870
41312
|
|
|
40871
41313
|
## CEO Directive
|
|
40872
41314
|
> ${input.directive}
|
|
@@ -40876,40 +41318,64 @@ You are a Sprint Organizer finalizing the sprint plan from a planning meeting. T
|
|
|
40876
41318
|
## CEO Feedback on Previous Plan
|
|
40877
41319
|
> ${input.feedback}
|
|
40878
41320
|
|
|
40879
|
-
IMPORTANT: The
|
|
41321
|
+
IMPORTANT: Incorporate this feedback into your plan. The CEO has reviewed a previous plan and wants changes.
|
|
40880
41322
|
`;
|
|
40881
41323
|
}
|
|
40882
41324
|
prompt += `
|
|
40883
|
-
##
|
|
40884
|
-
${input.
|
|
41325
|
+
## Project Context
|
|
41326
|
+
${input.projectContext || "No project context available."}
|
|
41327
|
+
|
|
41328
|
+
## Codebase Structure
|
|
41329
|
+
${input.codebaseIndex || "No codebase index available."}
|
|
40885
41330
|
|
|
40886
41331
|
## Your Task
|
|
40887
41332
|
|
|
40888
|
-
|
|
41333
|
+
Analyze the directive and produce a **complete sprint plan** with the following:
|
|
40889
41334
|
|
|
40890
|
-
1. **Sprint Name** — A concise, memorable name
|
|
41335
|
+
1. **Sprint Name** — A concise, memorable name (2-4 words)
|
|
40891
41336
|
2. **Sprint Goal** — One paragraph describing what this sprint delivers
|
|
40892
|
-
3. **
|
|
40893
|
-
4. **
|
|
40894
|
-
5. **
|
|
40895
|
-
|
|
40896
|
-
|
|
40897
|
-
Guidelines:
|
|
40898
|
-
- The order of tasks in the array determines execution order. Tasks are dispatched sequentially from first to last.
|
|
40899
|
-
- Foundation tasks (schemas, config, shared code) must appear before tasks that build on them
|
|
40900
|
-
- Since tasks execute sequentially on one branch, later tasks can depend on earlier tasks' outputs
|
|
40901
|
-
- Ensure acceptance criteria are specific and testable
|
|
40902
|
-
- Keep the sprint focused — if it's too large (>12 tasks), consider reducing scope
|
|
40903
|
-
- Ensure every task description reads as a standalone implementation brief — not a summary
|
|
41337
|
+
3. **Duration Estimate** — How many days this sprint will take with a single agent working sequentially
|
|
41338
|
+
4. **Task Breakdown** — An ordered list of tasks that fully implement the directive
|
|
41339
|
+
5. **Risk Assessment** — Potential risks with mitigations
|
|
41340
|
+
|
|
41341
|
+
### Task Requirements
|
|
40904
41342
|
|
|
40905
|
-
|
|
41343
|
+
For each task, provide:
|
|
41344
|
+
- **Title** — Clear, action-oriented (e.g., "Implement user registration API endpoint")
|
|
41345
|
+
- **Description** — A detailed, actionable implementation guide (see below)
|
|
41346
|
+
- **Assignee Role** — BACKEND, FRONTEND, QA, PM, or DESIGN
|
|
41347
|
+
- **Priority** — CRITICAL, HIGH, MEDIUM, or LOW
|
|
41348
|
+
- **Complexity** — 1 (trivial) to 5 (very complex)
|
|
41349
|
+
- **Labels** — Relevant tags (e.g., "api", "database", "ui", "auth")
|
|
41350
|
+
- **Acceptance Criteria** — Specific, testable conditions for completion
|
|
40906
41351
|
|
|
40907
|
-
|
|
41352
|
+
### CRITICAL: Task Description Requirements
|
|
40908
41353
|
|
|
40909
|
-
|
|
40910
|
-
|
|
40911
|
-
|
|
40912
|
-
|
|
41354
|
+
Each task description will be handed to an INDEPENDENT agent as its primary instruction. The agent will have access to the codebase but NO context about the planning meeting. Each description MUST include:
|
|
41355
|
+
|
|
41356
|
+
1. **What to do** — Clearly state the goal and expected behavior/outcome
|
|
41357
|
+
2. **Where to do it** — List specific files, modules, or directories to modify or create. Reference existing code paths when extending functionality
|
|
41358
|
+
3. **How to do it** — Key implementation details: which patterns to follow, which existing utilities or services to use, what the data flow looks like
|
|
41359
|
+
4. **Boundaries** — What is NOT in scope for this task to prevent overlap with other tasks
|
|
41360
|
+
|
|
41361
|
+
Bad example: "Add authentication to the API."
|
|
41362
|
+
Good example: "Implement JWT-based authentication middleware in src/middleware/auth.ts. Create a verifyToken middleware that extracts the Bearer token from the Authorization header, validates it using the existing JWT_SECRET from env config, and attaches the decoded user payload to req.user. Apply this middleware to all routes in src/routes/protected/. This task does NOT include user registration or password reset — those are handled separately."
|
|
41363
|
+
|
|
41364
|
+
### CRITICAL: Task Ordering Rules
|
|
41365
|
+
|
|
41366
|
+
Tasks are executed SEQUENTIALLY by a single agent on ONE branch. The agent works through tasks in array order. Therefore:
|
|
41367
|
+
|
|
41368
|
+
1. **Foundation first.** Place foundational tasks (schemas, config, shared code) at the beginning. Later tasks can build on earlier ones since they run in sequence.
|
|
41369
|
+
2. **No forward dependencies.** A task must NOT depend on a task that appears later in the list.
|
|
41370
|
+
3. **Each task is self-contained for its scope.** A task can depend on earlier tasks but must include all changes needed for its own goal.
|
|
41371
|
+
4. **Keep tasks focused.** Each task should do one logical unit of work. Avoid trivially small or overly large tasks.
|
|
41372
|
+
5. **Merge related trivial work.** If two pieces of work are trivially small and tightly related, combine them into one task.
|
|
41373
|
+
|
|
41374
|
+
### Sprint Scope Guidelines
|
|
41375
|
+
|
|
41376
|
+
- If the sprint would exceed 12 tasks, reduce scope or merge related tasks
|
|
41377
|
+
- Ensure acceptance criteria are specific and testable
|
|
41378
|
+
- Keep the sprint focused on the directive — avoid scope creep
|
|
40913
41379
|
|
|
40914
41380
|
## Output Format
|
|
40915
41381
|
|
|
@@ -40922,7 +41388,7 @@ Your entire response must be a single JSON object — no text before it, no text
|
|
|
40922
41388
|
"tasks": [
|
|
40923
41389
|
{
|
|
40924
41390
|
"title": "string",
|
|
40925
|
-
"description": "string (detailed implementation guide: what
|
|
41391
|
+
"description": "string (detailed implementation guide: what, where, how, boundaries)",
|
|
40926
41392
|
"assigneeRole": "BACKEND | FRONTEND | QA | PM | DESIGN",
|
|
40927
41393
|
"priority": "CRITICAL | HIGH | MEDIUM | LOW",
|
|
40928
41394
|
"labels": ["string"],
|
|
@@ -40943,89 +41409,6 @@ IMPORTANT: Tasks are executed sequentially by a single agent. The array order IS
|
|
|
40943
41409
|
return prompt;
|
|
40944
41410
|
}
|
|
40945
41411
|
|
|
40946
|
-
// ../sdk/src/planning/agents/tech-lead.ts
|
|
40947
|
-
function buildTechLeadPrompt(input) {
|
|
40948
|
-
let prompt = `# Role: Senior Tech Lead
|
|
40949
|
-
|
|
40950
|
-
You are a Senior Tech Lead participating in an async sprint planning meeting. Your job is to take the CEO's directive and produce an initial task breakdown.
|
|
40951
|
-
|
|
40952
|
-
## CEO Directive
|
|
40953
|
-
> ${input.directive}
|
|
40954
|
-
`;
|
|
40955
|
-
if (input.feedback) {
|
|
40956
|
-
prompt += `
|
|
40957
|
-
## CEO Feedback on Previous Plan
|
|
40958
|
-
> ${input.feedback}
|
|
40959
|
-
|
|
40960
|
-
IMPORTANT: Incorporate this feedback into your task breakdown. The CEO has reviewed a previous plan and wants changes.
|
|
40961
|
-
`;
|
|
40962
|
-
}
|
|
40963
|
-
prompt += `
|
|
40964
|
-
## Project Context
|
|
40965
|
-
${input.projectContext || "No project context available."}
|
|
40966
|
-
|
|
40967
|
-
## Codebase Structure
|
|
40968
|
-
${input.codebaseIndex || "No codebase index available."}
|
|
40969
|
-
|
|
40970
|
-
## Your Task
|
|
40971
|
-
|
|
40972
|
-
Analyze the CEO's directive and produce a detailed task breakdown. For each task:
|
|
40973
|
-
|
|
40974
|
-
1. **Title** — Clear, action-oriented (e.g., "Implement user registration API endpoint")
|
|
40975
|
-
2. **Description** — A detailed, actionable implementation guide (see description requirements below)
|
|
40976
|
-
3. **Assignee Role** — Who should work on this: BACKEND, FRONTEND, QA, PM, or DESIGN
|
|
40977
|
-
4. **Priority** — HIGH, MEDIUM, or LOW based on business impact
|
|
40978
|
-
5. **Labels** — Relevant tags (e.g., "api", "database", "ui", "auth")
|
|
40979
|
-
6. **Acceptance Criteria** — Specific, testable conditions for completion
|
|
40980
|
-
|
|
40981
|
-
Think about:
|
|
40982
|
-
- What existing code can be reused or extended
|
|
40983
|
-
- Which tasks are independent vs. dependent
|
|
40984
|
-
- What the right granularity is (not too big, not too small)
|
|
40985
|
-
- What risks or unknowns exist
|
|
40986
|
-
|
|
40987
|
-
## CRITICAL: Task Description Requirements
|
|
40988
|
-
|
|
40989
|
-
Each task description will be handed to an INDEPENDENT agent as its primary instruction. The agent will have access to the codebase but NO context about the planning meeting. Descriptions must be clear enough for the agent to execute the task without ambiguity.
|
|
40990
|
-
|
|
40991
|
-
Each description MUST include:
|
|
40992
|
-
1. **What to do** — Clearly state the goal and what needs to be implemented, changed, or created. Be specific about the expected behavior or outcome.
|
|
40993
|
-
2. **Where to do it** — List the specific files, modules, or directories that need to be modified or created. Reference existing code paths when extending functionality.
|
|
40994
|
-
3. **How to do it** — Provide key implementation details: which patterns to follow, which existing utilities or services to use, what the data flow looks like.
|
|
40995
|
-
4. **Boundaries** — Clarify what is NOT in scope for this task to prevent overlap with other tasks.
|
|
40996
|
-
|
|
40997
|
-
Bad example: "Add authentication to the API."
|
|
40998
|
-
Good example: "Implement JWT-based authentication middleware in src/middleware/auth.ts. Create a verifyToken middleware that extracts the Bearer token from the Authorization header, validates it using the existing JWT_SECRET from env config, and attaches the decoded user payload to req.user. Apply this middleware to all routes in src/routes/protected/. Add a POST /auth/login endpoint in src/routes/auth.ts that accepts {email, password}, validates credentials against the users table, and returns a signed JWT. This task does NOT include user registration or password reset — those are handled separately."
|
|
40999
|
-
|
|
41000
|
-
## CRITICAL: Task Ordering Rules
|
|
41001
|
-
|
|
41002
|
-
Tasks are executed SEQUENTIALLY by a single agent on ONE branch. The agent works through tasks in the order they appear in the array. Therefore:
|
|
41003
|
-
|
|
41004
|
-
1. **Foundation first.** Place foundational tasks (schemas, config, shared code) at the beginning of the list. Later tasks can build on earlier ones since they run in sequence on the same branch.
|
|
41005
|
-
2. **Each task must be self-contained.** A task must include ALL the code changes it needs to work — from config to implementation to tests. A task CAN depend on earlier tasks in the list since they will have already been completed.
|
|
41006
|
-
3. **Logical ordering matters.** Tasks are dispatched in the order they appear. Ensure dependent tasks come after their prerequisites.
|
|
41007
|
-
4. **Keep tasks focused.** Each task should do one logical unit of work. Since there are no parallel execution conflicts, tasks can be more granular — but avoid tasks that are too small or trivial.
|
|
41008
|
-
|
|
41009
|
-
## Output Format
|
|
41010
|
-
|
|
41011
|
-
Your entire response must be a single JSON object — no text before it, no text after it, no markdown code blocks, no explanation. Start your response with the "{" character:
|
|
41012
|
-
|
|
41013
|
-
{
|
|
41014
|
-
"tasks": [
|
|
41015
|
-
{
|
|
41016
|
-
"title": "string",
|
|
41017
|
-
"description": "string (detailed implementation guide: what to do, where to do it, how to do it, and boundaries — see description requirements above)",
|
|
41018
|
-
"assigneeRole": "BACKEND | FRONTEND | QA | PM | DESIGN",
|
|
41019
|
-
"priority": "HIGH | MEDIUM | LOW",
|
|
41020
|
-
"labels": ["string"],
|
|
41021
|
-
"acceptanceCriteria": ["string"]
|
|
41022
|
-
}
|
|
41023
|
-
],
|
|
41024
|
-
"technicalNotes": "string (brief notes on architecture decisions, risks, or considerations for the Architect phase)"
|
|
41025
|
-
}`;
|
|
41026
|
-
return prompt;
|
|
41027
|
-
}
|
|
41028
|
-
|
|
41029
41412
|
// ../sdk/src/planning/planning-meeting.ts
|
|
41030
41413
|
import { existsSync as existsSync10, readFileSync as readFileSync9 } from "node:fs";
|
|
41031
41414
|
|
|
@@ -41043,52 +41426,33 @@ class PlanningMeeting {
|
|
|
41043
41426
|
async run(directive, feedback) {
|
|
41044
41427
|
const projectContext = this.getProjectContext();
|
|
41045
41428
|
const codebaseIndex = this.getCodebaseIndex();
|
|
41046
|
-
this.log("Phase 1/
|
|
41047
|
-
const
|
|
41429
|
+
this.log("Phase 1/2: Planner building sprint plan...", "info");
|
|
41430
|
+
const plannerPrompt = buildPlannerPrompt({
|
|
41048
41431
|
directive,
|
|
41049
41432
|
projectContext,
|
|
41050
41433
|
codebaseIndex,
|
|
41051
41434
|
feedback
|
|
41052
41435
|
});
|
|
41053
|
-
const
|
|
41054
|
-
this.log("
|
|
41055
|
-
this.log("Phase 2/
|
|
41056
|
-
const architectPrompt = buildArchitectPrompt({
|
|
41057
|
-
directive,
|
|
41058
|
-
projectContext,
|
|
41059
|
-
techLeadOutput,
|
|
41060
|
-
feedback
|
|
41061
|
-
});
|
|
41062
|
-
const architectOutput = await this.aiRunner.run(architectPrompt);
|
|
41063
|
-
this.log("Architect phase complete.", "success");
|
|
41064
|
-
this.log("Phase 3/4: Sprint Organizer finalizing plan...", "info");
|
|
41065
|
-
const sprintOrganizerPrompt = buildSprintOrganizerPrompt({
|
|
41066
|
-
directive,
|
|
41067
|
-
architectOutput,
|
|
41068
|
-
feedback
|
|
41069
|
-
});
|
|
41070
|
-
const sprintOrganizerOutput = await this.aiRunner.run(sprintOrganizerPrompt);
|
|
41071
|
-
this.log("Sprint Organizer phase complete.", "success");
|
|
41072
|
-
this.log("Phase 4/4: Cross-Task Review checking for conflicts and overlaps...", "info");
|
|
41436
|
+
const plannerOutput = await this.aiRunner.run(plannerPrompt);
|
|
41437
|
+
this.log("Planner phase complete.", "success");
|
|
41438
|
+
this.log("Phase 2/2: Reviewer checking for conflicts and quality...", "info");
|
|
41073
41439
|
const crossTaskReviewerPrompt = buildCrossTaskReviewerPrompt({
|
|
41074
41440
|
directive,
|
|
41075
41441
|
projectContext,
|
|
41076
|
-
|
|
41442
|
+
plannerOutput,
|
|
41077
41443
|
feedback
|
|
41078
41444
|
});
|
|
41079
|
-
const
|
|
41080
|
-
this.log("
|
|
41081
|
-
const plan = parseSprintPlanFromAI(
|
|
41445
|
+
const reviewOutput = await this.aiRunner.run(crossTaskReviewerPrompt);
|
|
41446
|
+
this.log("Review phase complete.", "success");
|
|
41447
|
+
const plan = parseSprintPlanFromAI(reviewOutput, directive);
|
|
41082
41448
|
if (feedback) {
|
|
41083
41449
|
plan.feedback = feedback;
|
|
41084
41450
|
}
|
|
41085
41451
|
return {
|
|
41086
41452
|
plan,
|
|
41087
41453
|
phaseOutputs: {
|
|
41088
|
-
|
|
41089
|
-
|
|
41090
|
-
sprintOrganizer: sprintOrganizerOutput,
|
|
41091
|
-
crossTaskReview: crossTaskReviewOutput
|
|
41454
|
+
planner: plannerOutput,
|
|
41455
|
+
review: reviewOutput
|
|
41092
41456
|
}
|
|
41093
41457
|
};
|
|
41094
41458
|
}
|
|
@@ -41864,8 +42228,8 @@ function showHelp() {
|
|
|
41864
42228
|
${c.dim("Any other input will be sent as a prompt to the AI.")}
|
|
41865
42229
|
`);
|
|
41866
42230
|
}
|
|
41867
|
-
function showHistory(
|
|
41868
|
-
const historyManager =
|
|
42231
|
+
function showHistory(session2, args) {
|
|
42232
|
+
const historyManager = session2.getHistoryManager();
|
|
41869
42233
|
const limit = args ? parseInt(args, 10) : 10;
|
|
41870
42234
|
const sessions = historyManager.listSessions({
|
|
41871
42235
|
limit: Number.isNaN(limit) ? 10 : limit
|
|
@@ -41884,7 +42248,7 @@ function showHistory(session, args) {
|
|
|
41884
42248
|
const dateStr = date5.toLocaleDateString();
|
|
41885
42249
|
const timeStr = date5.toLocaleTimeString();
|
|
41886
42250
|
const msgCount = sess.messages.length;
|
|
41887
|
-
const isCurrent = sess.id ===
|
|
42251
|
+
const isCurrent = sess.id === session2.getSessionId();
|
|
41888
42252
|
const marker = isCurrent ? c.success("*") : " ";
|
|
41889
42253
|
console.log(` ${marker} ${c.cyan(sess.id)} ${c.dim(`- ${dateStr} ${timeStr} (${msgCount} messages)`)}`);
|
|
41890
42254
|
if (sess.messages.length > 0) {
|
|
@@ -41905,7 +42269,7 @@ var init_commands = __esm(() => {
|
|
|
41905
42269
|
name: "exit",
|
|
41906
42270
|
aliases: ["quit", "q"],
|
|
41907
42271
|
description: "Exit interactive mode",
|
|
41908
|
-
execute: (
|
|
42272
|
+
execute: (session2) => session2.shutdown()
|
|
41909
42273
|
},
|
|
41910
42274
|
{
|
|
41911
42275
|
name: "clear",
|
|
@@ -41923,21 +42287,21 @@ var init_commands = __esm(() => {
|
|
|
41923
42287
|
name: "reset",
|
|
41924
42288
|
aliases: ["r"],
|
|
41925
42289
|
description: "Reset conversation context",
|
|
41926
|
-
execute: (
|
|
42290
|
+
execute: (session2) => session2.resetContext()
|
|
41927
42291
|
},
|
|
41928
42292
|
{
|
|
41929
42293
|
name: "history",
|
|
41930
42294
|
aliases: ["hist"],
|
|
41931
42295
|
description: "List recent sessions",
|
|
41932
|
-
execute: (
|
|
42296
|
+
execute: (session2, args) => showHistory(session2, args)
|
|
41933
42297
|
},
|
|
41934
42298
|
{
|
|
41935
42299
|
name: "session",
|
|
41936
42300
|
aliases: ["sid"],
|
|
41937
42301
|
description: "Show current session ID",
|
|
41938
|
-
execute: (
|
|
42302
|
+
execute: (session2) => {
|
|
41939
42303
|
console.log(`
|
|
41940
|
-
${c.dim("Session ID:")} ${c.cyan(
|
|
42304
|
+
${c.dim("Session ID:")} ${c.cyan(session2.getSessionId())}
|
|
41941
42305
|
`);
|
|
41942
42306
|
}
|
|
41943
42307
|
}
|
|
@@ -43030,9 +43394,137 @@ function showDocsSyncHelp() {
|
|
|
43030
43394
|
}
|
|
43031
43395
|
// src/commands/exec.ts
|
|
43032
43396
|
init_index_node();
|
|
43033
|
-
|
|
43397
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
43034
43398
|
import { parseArgs as parseArgs2 } from "node:util";
|
|
43035
43399
|
|
|
43400
|
+
// src/display/json-stream-renderer.ts
|
|
43401
|
+
init_src();
|
|
43402
|
+
|
|
43403
|
+
class JsonStreamRenderer {
|
|
43404
|
+
sessionId;
|
|
43405
|
+
command;
|
|
43406
|
+
model;
|
|
43407
|
+
provider;
|
|
43408
|
+
cwd;
|
|
43409
|
+
statsTracker;
|
|
43410
|
+
started = false;
|
|
43411
|
+
done = false;
|
|
43412
|
+
constructor(options) {
|
|
43413
|
+
this.sessionId = options.sessionId;
|
|
43414
|
+
this.command = options.command;
|
|
43415
|
+
this.model = options.model;
|
|
43416
|
+
this.provider = options.provider;
|
|
43417
|
+
this.cwd = options.cwd;
|
|
43418
|
+
this.statsTracker = new ExecutionStatsTracker;
|
|
43419
|
+
}
|
|
43420
|
+
emitStart() {
|
|
43421
|
+
if (this.started)
|
|
43422
|
+
return;
|
|
43423
|
+
this.started = true;
|
|
43424
|
+
this.emit(createCliStreamEvent(CliStreamEventType.START, this.sessionId, {
|
|
43425
|
+
command: this.command,
|
|
43426
|
+
model: this.model,
|
|
43427
|
+
provider: this.provider,
|
|
43428
|
+
cwd: this.cwd
|
|
43429
|
+
}));
|
|
43430
|
+
}
|
|
43431
|
+
handleChunk(chunk) {
|
|
43432
|
+
this.ensureStarted();
|
|
43433
|
+
switch (chunk.type) {
|
|
43434
|
+
case "text_delta":
|
|
43435
|
+
this.emit(createCliStreamEvent(CliStreamEventType.TEXT_DELTA, this.sessionId, {
|
|
43436
|
+
content: chunk.content
|
|
43437
|
+
}));
|
|
43438
|
+
break;
|
|
43439
|
+
case "thinking":
|
|
43440
|
+
this.emit(createCliStreamEvent(CliStreamEventType.THINKING, this.sessionId, {
|
|
43441
|
+
content: chunk.content
|
|
43442
|
+
}));
|
|
43443
|
+
break;
|
|
43444
|
+
case "tool_use":
|
|
43445
|
+
this.statsTracker.toolStarted(chunk.tool, chunk.id);
|
|
43446
|
+
this.emit(createCliStreamEvent(CliStreamEventType.TOOL_STARTED, this.sessionId, {
|
|
43447
|
+
tool: chunk.tool,
|
|
43448
|
+
toolId: chunk.id,
|
|
43449
|
+
parameters: chunk.parameters
|
|
43450
|
+
}));
|
|
43451
|
+
break;
|
|
43452
|
+
case "tool_result":
|
|
43453
|
+
if (chunk.success) {
|
|
43454
|
+
this.statsTracker.toolCompleted(chunk.tool, chunk.id);
|
|
43455
|
+
} else {
|
|
43456
|
+
this.statsTracker.toolFailed(chunk.tool, chunk.error ?? "Unknown error", chunk.id);
|
|
43457
|
+
}
|
|
43458
|
+
this.emit(createCliStreamEvent(CliStreamEventType.TOOL_COMPLETED, this.sessionId, {
|
|
43459
|
+
tool: chunk.tool,
|
|
43460
|
+
toolId: chunk.id,
|
|
43461
|
+
success: chunk.success,
|
|
43462
|
+
duration: chunk.duration,
|
|
43463
|
+
error: chunk.error
|
|
43464
|
+
}));
|
|
43465
|
+
break;
|
|
43466
|
+
case "tool_parameters":
|
|
43467
|
+
break;
|
|
43468
|
+
case "result":
|
|
43469
|
+
break;
|
|
43470
|
+
case "error":
|
|
43471
|
+
this.statsTracker.setError(chunk.error);
|
|
43472
|
+
this.emitError("UNKNOWN", chunk.error);
|
|
43473
|
+
break;
|
|
43474
|
+
}
|
|
43475
|
+
}
|
|
43476
|
+
emitStatus(status, message) {
|
|
43477
|
+
this.ensureStarted();
|
|
43478
|
+
this.emit(createCliStreamEvent(CliStreamEventType.STATUS, this.sessionId, {
|
|
43479
|
+
status,
|
|
43480
|
+
message
|
|
43481
|
+
}));
|
|
43482
|
+
}
|
|
43483
|
+
emitError(code, message, options) {
|
|
43484
|
+
this.ensureStarted();
|
|
43485
|
+
this.emit(createCliStreamEvent(CliStreamEventType.ERROR, this.sessionId, {
|
|
43486
|
+
error: createProtocolError(code, message, options)
|
|
43487
|
+
}));
|
|
43488
|
+
}
|
|
43489
|
+
emitDone(exitCode) {
|
|
43490
|
+
if (this.done)
|
|
43491
|
+
return;
|
|
43492
|
+
this.done = true;
|
|
43493
|
+
this.ensureStarted();
|
|
43494
|
+
const stats = this.statsTracker.finalize();
|
|
43495
|
+
this.emit(createCliStreamEvent(CliStreamEventType.DONE, this.sessionId, {
|
|
43496
|
+
exitCode,
|
|
43497
|
+
duration: stats.duration,
|
|
43498
|
+
toolsUsed: stats.toolsUsed.length > 0 ? stats.toolsUsed : undefined,
|
|
43499
|
+
tokensUsed: stats.tokensUsed,
|
|
43500
|
+
success: exitCode === 0
|
|
43501
|
+
}));
|
|
43502
|
+
}
|
|
43503
|
+
emitFatalError(code, message, options) {
|
|
43504
|
+
this.statsTracker.setError(message);
|
|
43505
|
+
this.emitError(code, message, {
|
|
43506
|
+
...options,
|
|
43507
|
+
recoverable: false
|
|
43508
|
+
});
|
|
43509
|
+
this.emitDone(1);
|
|
43510
|
+
}
|
|
43511
|
+
isDone() {
|
|
43512
|
+
return this.done;
|
|
43513
|
+
}
|
|
43514
|
+
ensureStarted() {
|
|
43515
|
+
if (!this.started) {
|
|
43516
|
+
this.emitStart();
|
|
43517
|
+
}
|
|
43518
|
+
}
|
|
43519
|
+
emit(event) {
|
|
43520
|
+
process.stdout.write(`${JSON.stringify(event)}
|
|
43521
|
+
`);
|
|
43522
|
+
}
|
|
43523
|
+
}
|
|
43524
|
+
|
|
43525
|
+
// src/commands/exec.ts
|
|
43526
|
+
init_progress_renderer();
|
|
43527
|
+
|
|
43036
43528
|
// src/commands/exec-sessions.ts
|
|
43037
43529
|
init_index_node();
|
|
43038
43530
|
function formatRelativeTime(timestamp) {
|
|
@@ -43070,11 +43562,11 @@ class SessionCommands {
|
|
|
43070
43562
|
console.log(`
|
|
43071
43563
|
${c.primary("Recent Exec Sessions:")}
|
|
43072
43564
|
`);
|
|
43073
|
-
for (const
|
|
43074
|
-
const shortId = this.getShortId(
|
|
43075
|
-
const age = formatRelativeTime(
|
|
43076
|
-
const msgCount =
|
|
43077
|
-
const firstUserMsg =
|
|
43565
|
+
for (const session2 of sessions.slice(0, 10)) {
|
|
43566
|
+
const shortId = this.getShortId(session2.id);
|
|
43567
|
+
const age = formatRelativeTime(session2.updatedAt);
|
|
43568
|
+
const msgCount = session2.messages.length;
|
|
43569
|
+
const firstUserMsg = session2.messages.find((m) => m.role === "user");
|
|
43078
43570
|
const preview = firstUserMsg ? firstUserMsg.content.slice(0, 50).replace(/\n/g, " ") : "(empty session)";
|
|
43079
43571
|
console.log(` ${c.cyan(shortId)} ${c.gray("-")} ${preview}${firstUserMsg && firstUserMsg.content.length > 50 ? "..." : ""}`);
|
|
43080
43572
|
console.log(` ${c.dim(`${msgCount} messages • ${age}`)}`);
|
|
@@ -43094,8 +43586,8 @@ class SessionCommands {
|
|
|
43094
43586
|
`);
|
|
43095
43587
|
return;
|
|
43096
43588
|
}
|
|
43097
|
-
const
|
|
43098
|
-
if (!
|
|
43589
|
+
const session2 = this.historyManager.findSessionByPartialId(sessionId);
|
|
43590
|
+
if (!session2) {
|
|
43099
43591
|
console.error(`
|
|
43100
43592
|
${c.error("Error:")} Session ${c.cyan(sessionId)} not found
|
|
43101
43593
|
`);
|
|
@@ -43104,18 +43596,18 @@ class SessionCommands {
|
|
|
43104
43596
|
return;
|
|
43105
43597
|
}
|
|
43106
43598
|
console.log(`
|
|
43107
|
-
${c.primary("Session:")} ${c.cyan(
|
|
43108
|
-
console.log(` ${c.dim(`Created: ${new Date(
|
|
43109
|
-
console.log(` ${c.dim(`Model: ${
|
|
43599
|
+
${c.primary("Session:")} ${c.cyan(session2.id)}`);
|
|
43600
|
+
console.log(` ${c.dim(`Created: ${new Date(session2.createdAt).toLocaleString()}`)}`);
|
|
43601
|
+
console.log(` ${c.dim(`Model: ${session2.metadata.model} (${session2.metadata.provider})`)}
|
|
43110
43602
|
`);
|
|
43111
|
-
if (
|
|
43603
|
+
if (session2.messages.length === 0) {
|
|
43112
43604
|
console.log(` ${c.dim("(No messages in this session)")}
|
|
43113
43605
|
`);
|
|
43114
43606
|
return;
|
|
43115
43607
|
}
|
|
43116
43608
|
console.log(c.dim(" ─".repeat(30)));
|
|
43117
43609
|
console.log();
|
|
43118
|
-
for (const message of
|
|
43610
|
+
for (const message of session2.messages) {
|
|
43119
43611
|
const role = message.role === "user" ? c.cyan("You") : c.green("AI");
|
|
43120
43612
|
const content = message.content;
|
|
43121
43613
|
console.log(` ${role}:`);
|
|
@@ -43136,17 +43628,17 @@ class SessionCommands {
|
|
|
43136
43628
|
`);
|
|
43137
43629
|
return;
|
|
43138
43630
|
}
|
|
43139
|
-
const
|
|
43140
|
-
if (!
|
|
43631
|
+
const session2 = this.historyManager.findSessionByPartialId(sessionId);
|
|
43632
|
+
if (!session2) {
|
|
43141
43633
|
console.error(`
|
|
43142
43634
|
${c.error("Error:")} Session ${c.cyan(sessionId)} not found
|
|
43143
43635
|
`);
|
|
43144
43636
|
return;
|
|
43145
43637
|
}
|
|
43146
|
-
const deleted = this.historyManager.deleteSession(
|
|
43638
|
+
const deleted = this.historyManager.deleteSession(session2.id);
|
|
43147
43639
|
if (deleted) {
|
|
43148
43640
|
console.log(`
|
|
43149
|
-
${c.success("✔")} Deleted session ${c.cyan(this.getShortId(
|
|
43641
|
+
${c.success("✔")} Deleted session ${c.cyan(this.getShortId(session2.id))}
|
|
43150
43642
|
`);
|
|
43151
43643
|
} else {
|
|
43152
43644
|
console.error(`
|
|
@@ -43206,11 +43698,17 @@ async function execCommand(args) {
|
|
|
43206
43698
|
"no-stream": { type: "boolean" },
|
|
43207
43699
|
"no-status": { type: "boolean" },
|
|
43208
43700
|
interactive: { type: "boolean", short: "i" },
|
|
43209
|
-
session: { type: "string", short: "s" }
|
|
43701
|
+
session: { type: "string", short: "s" },
|
|
43702
|
+
"json-stream": { type: "boolean" }
|
|
43210
43703
|
},
|
|
43211
43704
|
strict: false
|
|
43212
43705
|
});
|
|
43706
|
+
const jsonStream = values["json-stream"];
|
|
43213
43707
|
const projectPath = values.dir || process.cwd();
|
|
43708
|
+
if (jsonStream) {
|
|
43709
|
+
await execJsonStream(values, positionals, projectPath);
|
|
43710
|
+
return;
|
|
43711
|
+
}
|
|
43214
43712
|
requireInitialization(projectPath, "exec");
|
|
43215
43713
|
if (positionals[0] === "sessions") {
|
|
43216
43714
|
const sessionAction = positionals[1];
|
|
@@ -43241,13 +43739,13 @@ async function execCommand(args) {
|
|
|
43241
43739
|
const sessionId = values.session;
|
|
43242
43740
|
if (isInteractive) {
|
|
43243
43741
|
const { InteractiveSession: InteractiveSession2 } = await Promise.resolve().then(() => (init_interactive_session(), exports_interactive_session));
|
|
43244
|
-
const
|
|
43742
|
+
const session2 = new InteractiveSession2({
|
|
43245
43743
|
projectPath,
|
|
43246
43744
|
provider,
|
|
43247
43745
|
model,
|
|
43248
43746
|
sessionId
|
|
43249
43747
|
});
|
|
43250
|
-
await
|
|
43748
|
+
await session2.start();
|
|
43251
43749
|
return;
|
|
43252
43750
|
}
|
|
43253
43751
|
const promptInput = positionals.join(" ");
|
|
@@ -43338,6 +43836,67 @@ async function execCommand(args) {
|
|
|
43338
43836
|
process.exit(1);
|
|
43339
43837
|
}
|
|
43340
43838
|
}
|
|
43839
|
+
async function execJsonStream(values, positionals, projectPath) {
|
|
43840
|
+
const sessionId = values.session ?? randomUUID2();
|
|
43841
|
+
const execSettings = new SettingsManager(projectPath).load();
|
|
43842
|
+
const provider = resolveProvider3(values.provider || execSettings.provider);
|
|
43843
|
+
const model = values.model || execSettings.model || DEFAULT_MODEL[provider];
|
|
43844
|
+
const renderer = new JsonStreamRenderer({
|
|
43845
|
+
sessionId,
|
|
43846
|
+
command: "exec",
|
|
43847
|
+
model,
|
|
43848
|
+
provider,
|
|
43849
|
+
cwd: projectPath
|
|
43850
|
+
});
|
|
43851
|
+
const handleSignal = () => {
|
|
43852
|
+
if (!renderer.isDone()) {
|
|
43853
|
+
renderer.emitFatalError("PROCESS_CRASHED", "Process terminated by signal");
|
|
43854
|
+
}
|
|
43855
|
+
process.exit(1);
|
|
43856
|
+
};
|
|
43857
|
+
process.on("SIGINT", handleSignal);
|
|
43858
|
+
process.on("SIGTERM", handleSignal);
|
|
43859
|
+
try {
|
|
43860
|
+
try {
|
|
43861
|
+
requireInitialization(projectPath, "exec");
|
|
43862
|
+
} catch (initError) {
|
|
43863
|
+
renderer.emitFatalError("CLI_NOT_FOUND", initError instanceof Error ? initError.message : String(initError));
|
|
43864
|
+
process.exit(1);
|
|
43865
|
+
}
|
|
43866
|
+
const promptInput = positionals.join(" ");
|
|
43867
|
+
if (!promptInput) {
|
|
43868
|
+
renderer.emitFatalError("UNKNOWN", 'Prompt is required. Usage: locus exec --json-stream "your prompt"');
|
|
43869
|
+
process.exit(1);
|
|
43870
|
+
}
|
|
43871
|
+
renderer.emitStart();
|
|
43872
|
+
renderer.emitStatus("running", "Building prompt context");
|
|
43873
|
+
const aiRunner = createAiRunner(provider, {
|
|
43874
|
+
projectPath,
|
|
43875
|
+
model
|
|
43876
|
+
});
|
|
43877
|
+
const builder = new PromptBuilder(projectPath);
|
|
43878
|
+
const fullPrompt = await builder.buildGenericPrompt(promptInput);
|
|
43879
|
+
renderer.emitStatus("streaming", "Streaming AI response");
|
|
43880
|
+
const stream4 = aiRunner.runStream(fullPrompt);
|
|
43881
|
+
for await (const chunk of stream4) {
|
|
43882
|
+
renderer.handleChunk(chunk);
|
|
43883
|
+
}
|
|
43884
|
+
try {
|
|
43885
|
+
const knowledgeBase = new KnowledgeBase(projectPath);
|
|
43886
|
+
knowledgeBase.updateProgress({
|
|
43887
|
+
role: "user",
|
|
43888
|
+
content: promptInput
|
|
43889
|
+
});
|
|
43890
|
+
} catch {}
|
|
43891
|
+
renderer.emitDone(0);
|
|
43892
|
+
} catch (error48) {
|
|
43893
|
+
const message = error48 instanceof Error ? error48.message : String(error48);
|
|
43894
|
+
if (!renderer.isDone()) {
|
|
43895
|
+
renderer.emitFatalError("UNKNOWN", message);
|
|
43896
|
+
}
|
|
43897
|
+
process.exit(1);
|
|
43898
|
+
}
|
|
43899
|
+
}
|
|
43341
43900
|
// src/commands/help.ts
|
|
43342
43901
|
init_index_node();
|
|
43343
43902
|
function showHelp2() {
|
|
@@ -43527,12 +44086,7 @@ async function initCommand() {
|
|
|
43527
44086
|
init_index_node();
|
|
43528
44087
|
import { parseArgs as parseArgs4 } from "node:util";
|
|
43529
44088
|
function normalizePlanIdArgs(args) {
|
|
43530
|
-
const planIdFlags = new Set([
|
|
43531
|
-
"--approve",
|
|
43532
|
-
"--reject",
|
|
43533
|
-
"--cancel",
|
|
43534
|
-
"--show"
|
|
43535
|
-
]);
|
|
44089
|
+
const planIdFlags = new Set(["--approve", "--reject", "--cancel", "--show"]);
|
|
43536
44090
|
const result = [];
|
|
43537
44091
|
let i = 0;
|
|
43538
44092
|
while (i < args.length) {
|
|
@@ -44459,10 +45013,11 @@ function versionCommand() {
|
|
|
44459
45013
|
console.log("");
|
|
44460
45014
|
}
|
|
44461
45015
|
// src/cli.ts
|
|
45016
|
+
var isJsonStream = process.argv.includes("--json-stream");
|
|
44462
45017
|
async function main() {
|
|
44463
45018
|
const command = process.argv[2];
|
|
44464
45019
|
const args = process.argv.slice(3);
|
|
44465
|
-
if (command !== "exec") {
|
|
45020
|
+
if (command !== "exec" && !isJsonStream) {
|
|
44466
45021
|
printBanner();
|
|
44467
45022
|
}
|
|
44468
45023
|
switch (command) {
|
|
@@ -44506,6 +45061,11 @@ async function main() {
|
|
|
44506
45061
|
}
|
|
44507
45062
|
}
|
|
44508
45063
|
main().catch((err) => {
|
|
45064
|
+
if (isJsonStream) {
|
|
45065
|
+
process.stderr.write(`${JSON.stringify({ fatal: true, error: err.message })}
|
|
45066
|
+
`);
|
|
45067
|
+
process.exit(1);
|
|
45068
|
+
}
|
|
44509
45069
|
console.error(`
|
|
44510
45070
|
${c.error("✖ Fatal Error")} ${c.red(err.message)}`);
|
|
44511
45071
|
process.exit(1);
|