assistme 0.6.7 → 0.6.9

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.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getConfig
3
- } from "./chunk-EPKN2PW5.js";
3
+ } from "./chunk-YYSJHZSO.js";
4
4
 
5
5
  // src/db/auth-store.ts
6
6
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
@@ -278,7 +278,6 @@ var FRAME_CONTEXTS_MAX_SIZE = 500;
278
278
  var MAX_FILE_SEARCH_RESULTS = 50;
279
279
  var MAX_CONTENT_SEARCH_FILES = 200;
280
280
  var MAX_CONTENT_SEARCH_RESULTS = 30;
281
- var SKILL_VALIDATION_MAX_TURNS = 2;
282
281
  var MEMORY_DEDUP_SIMILARITY_THRESHOLD = 0.75;
283
282
  var MEMORY_COMPRESSION_THRESHOLD = 50;
284
283
  var MEMORY_COMPRESSION_TARGET = 30;
@@ -497,7 +496,6 @@ export {
497
496
  MAX_FILE_SEARCH_RESULTS,
498
497
  MAX_CONTENT_SEARCH_FILES,
499
498
  MAX_CONTENT_SEARCH_RESULTS,
500
- SKILL_VALIDATION_MAX_TURNS,
501
499
  MEMORY_DEDUP_SIMILARITY_THRESHOLD,
502
500
  MEMORY_COMPRESSION_THRESHOLD,
503
501
  MEMORY_COMPRESSION_TARGET,
@@ -517,6 +515,5 @@ export {
517
515
  SkillCreateResultSchema,
518
516
  SkillDecisionSchema,
519
517
  BrowseSkillRowSchema,
520
- SelfAnalysisResultSchema,
521
518
  JobRunner
522
519
  };
@@ -8,7 +8,6 @@ var CONFIG_DEFAULTS = {
8
8
  supabaseAnonKey: SUPABASE_ANON_KEY_DEFAULT,
9
9
  sessionName: "Default",
10
10
  model: "claude-sonnet-4-20250514",
11
- maxTurns: 500,
12
11
  taskTimeoutMinutes: 10
13
12
  };
14
13
  var config = new Conf({
@@ -27,7 +26,6 @@ function getConfig() {
27
26
  workspacePath: resolve(workspacePath),
28
27
  sessionName: config.get("sessionName") || "Default",
29
28
  model: config.get("model") || "claude-sonnet-4-20250514",
30
- maxTurns: config.get("maxTurns") || 500,
31
29
  taskTimeoutMinutes: config.get("taskTimeoutMinutes") || 10
32
30
  };
33
31
  }
@@ -3,7 +3,7 @@ import {
3
3
  getConfig,
4
4
  getConfigPath,
5
5
  setConfig
6
- } from "./chunk-EPKN2PW5.js";
6
+ } from "./chunk-YYSJHZSO.js";
7
7
  export {
8
8
  clearConfig,
9
9
  getConfig,
package/dist/index.js CHANGED
@@ -30,8 +30,6 @@ import {
30
30
  SHELL_MAX_OUTPUT,
31
31
  SHELL_TIMEOUT_MS,
32
32
  SKILL_DESCRIPTION_BUDGET_CHARS,
33
- SKILL_VALIDATION_MAX_TURNS,
34
- SelfAnalysisResultSchema,
35
33
  SkillCreateResultSchema,
36
34
  SkillDecisionSchema,
37
35
  SkillRowSchema,
@@ -46,13 +44,13 @@ import {
46
44
  setLogHook,
47
45
  setLogLevel,
48
46
  writeAuthStore
49
- } from "./chunk-5F4P6MYZ.js";
47
+ } from "./chunk-E2PAIRTS.js";
50
48
  import {
51
49
  clearConfig,
52
50
  getConfig,
53
51
  getConfigPath,
54
52
  setConfig
55
- } from "./chunk-EPKN2PW5.js";
53
+ } from "./chunk-YYSJHZSO.js";
56
54
 
57
55
  // src/index.ts
58
56
  import { Command } from "commander";
@@ -92,7 +90,7 @@ async function logout() {
92
90
 
93
91
  // src/db/session.ts
94
92
  async function createSession(sessionName, workspacePath, version2) {
95
- const { getConfig: getConfig2 } = await import("./config-OV2BLYB7.js");
93
+ const { getConfig: getConfig2 } = await import("./config-3RWSAUAZ.js");
96
94
  const data = await callMcpHandler("session.create", {
97
95
  session_name: sessionName,
98
96
  workspace_path: workspacePath,
@@ -343,7 +341,6 @@ function registerConfigCommands(program2) {
343
341
  "workspacePath",
344
342
  "sessionName",
345
343
  "model",
346
- "maxTurns",
347
344
  "browserPort"
348
345
  ];
349
346
  if (!validKeys.includes(key)) {
@@ -351,7 +348,7 @@ function registerConfigCommands(program2) {
351
348
  log.info(`Valid keys: ${validKeys.join(", ")}`);
352
349
  process.exit(1);
353
350
  }
354
- const numericKeys = ["maxTurns", "browserPort"];
351
+ const numericKeys = ["browserPort"];
355
352
  const val = numericKeys.includes(key) ? parseInt(value, 10) : value;
356
353
  setConfig(key, val);
357
354
  log.success(
@@ -373,7 +370,6 @@ function registerConfigCommands(program2) {
373
370
  console.log(` Workspace: ${cfg.workspacePath}`);
374
371
  console.log(` Session Name: ${cfg.sessionName}`);
375
372
  console.log(` Model: ${cfg.model}`);
376
- console.log(` Max Turns: ${cfg.maxTurns}`);
377
373
  console.log(` Config Path: ${getConfigPath()}`);
378
374
  console.log();
379
375
  });
@@ -3616,7 +3612,6 @@ Respond with a JSON object now.`;
3616
3612
  options: {
3617
3613
  resume: sessionId,
3618
3614
  model,
3619
- maxTurns: 1,
3620
3615
  allowedTools: [],
3621
3616
  effort: "low",
3622
3617
  outputFormat: SKILL_DECISION_OUTPUT_FORMAT
@@ -3656,7 +3651,6 @@ ${instructions}`;
3656
3651
  options: {
3657
3652
  resume: sessionId,
3658
3653
  model,
3659
- maxTurns: SKILL_VALIDATION_MAX_TURNS,
3660
3654
  allowedTools: [],
3661
3655
  effort: "low",
3662
3656
  outputFormat: SKILL_VALIDATION_OUTPUT_FORMAT
@@ -3845,58 +3839,11 @@ var SELF_ANALYSIS_OUTPUT_FORMAT = {
3845
3839
  schema: {
3846
3840
  type: "object",
3847
3841
  properties: {
3848
- is_perfect: { type: "boolean" },
3849
- overall_score: { type: "number", minimum: 1, maximum: 10 },
3850
- task_completion_quality: {
3851
- type: "object",
3852
- properties: {
3853
- score: { type: "number", minimum: 1, maximum: 10 },
3854
- assessment: { type: "string" }
3855
- },
3856
- required: ["score", "assessment"]
3857
- },
3858
- improvements: {
3859
- type: "array",
3860
- items: {
3861
- type: "object",
3862
- properties: {
3863
- area: { type: "string" },
3864
- severity: {
3865
- type: "string",
3866
- enum: ["critical", "major", "minor", "suggestion"]
3867
- },
3868
- description: { type: "string" },
3869
- suggestion: { type: "string" }
3870
- },
3871
- required: ["area", "severity", "description", "suggestion"]
3872
- }
3873
- },
3874
- data_quality: {
3875
- type: "object",
3876
- properties: {
3877
- session_logs_useful: { type: "boolean" },
3878
- session_logs_gaps: { type: "string" },
3879
- message_events_useful: { type: "boolean" },
3880
- message_events_gaps: { type: "string" },
3881
- conversation_context_useful: { type: "boolean" },
3882
- conversation_context_gaps: { type: "string" }
3883
- },
3884
- required: [
3885
- "session_logs_useful",
3886
- "message_events_useful",
3887
- "conversation_context_useful"
3888
- ]
3889
- },
3890
- summary: { type: "string" }
3842
+ needsImprovement: { type: "boolean" },
3843
+ title: { type: "string" },
3844
+ description: { type: "string" }
3891
3845
  },
3892
- required: [
3893
- "is_perfect",
3894
- "overall_score",
3895
- "task_completion_quality",
3896
- "improvements",
3897
- "data_quality",
3898
- "summary"
3899
- ]
3846
+ required: ["needsImprovement", "title", "description"]
3900
3847
  }
3901
3848
  };
3902
3849
  var SELF_ANALYSIS_PROMPT = `You just completed a task as the AssistMe agent. Now critically analyze AssistMe's own implementation \u2014 NOT the user's task itself, but how well AssistMe (the agent system) performed and whether AssistMe's codebase can be improved.
@@ -3920,17 +3867,14 @@ Below you will find:
3920
3867
  - **Tool Failures**: Any tool calls that failed during execution
3921
3868
 
3922
3869
  ## Instructions
3923
- Analyze all provided data critically. Consider:
3924
- - Are the session logs capturing enough detail for debugging?
3925
- - Do the message events provide sufficient visibility into the agent's decision-making?
3926
- - Is the conversation context giving enough user intent signal?
3927
- - Were tools used efficiently?
3928
- - Could the overall execution flow be improved?
3929
-
3930
- Set is_perfect to true ONLY if there are genuinely zero improvements to suggest (this should be rare).
3931
- The overall_score should be 1-10 where 10 means absolutely perfect.
3932
-
3933
- Respond with a JSON object now.`;
3870
+ Analyze all provided data critically. Respond with a JSON object containing:
3871
+ - "needsImprovement": set to false ONLY if the task was handled perfectly with zero improvements, true otherwise
3872
+ - "title": a short summary under 100 chars (empty string if needsImprovement is false)
3873
+ - "description": a detailed markdown report (empty string if needsImprovement is false) that includes:
3874
+ - **Summary**: overall assessment of how AssistMe performed
3875
+ - **Task Completion Quality**: score (1-10) and assessment
3876
+ - **Improvements**: numbered list, each with severity (critical/major/minor/suggestion), area, description, and suggestion
3877
+ - **Data Quality Gaps**: any gaps in session logs, message events, or conversation context that limited your analysis`;
3934
3878
  function truncateToChars(text, maxChars) {
3935
3879
  if (text.length <= maxChars) return text;
3936
3880
  return text.slice(0, maxChars) + "\n... [truncated]";
@@ -4060,32 +4004,7 @@ async function buildAnalysisContext(ctx) {
4060
4004
  `;
4061
4005
  return context;
4062
4006
  }
4063
- async function submitSelfAnalysisFeedback(analysis) {
4064
- const title = `Self-Analysis: Score ${analysis.overall_score}/10 \u2014 ${analysis.improvements.length} improvement(s)`;
4065
- const improvementDetails = analysis.improvements.map((imp, i) => `${i + 1}. [${imp.severity}] **${imp.area}**: ${imp.description}
4066
- \u2192 ${imp.suggestion}`).join("\n");
4067
- const dataQualityNotes = [
4068
- analysis.data_quality.session_logs_gaps ? `Session logs: ${analysis.data_quality.session_logs_gaps}` : null,
4069
- analysis.data_quality.message_events_gaps ? `Message events: ${analysis.data_quality.message_events_gaps}` : null,
4070
- analysis.data_quality.conversation_context_gaps ? `Conversation context: ${analysis.data_quality.conversation_context_gaps}` : null
4071
- ].filter(Boolean).join("\n");
4072
- let description = `## Summary
4073
- ${analysis.summary}
4074
-
4075
- `;
4076
- description += `## Task Completion Quality (${analysis.task_completion_quality.score}/10)
4077
- ${analysis.task_completion_quality.assessment}
4078
-
4079
- `;
4080
- description += `## Improvements
4081
- ${improvementDetails}
4082
- `;
4083
- if (dataQualityNotes) {
4084
- description += `
4085
- ## Data Quality Gaps
4086
- ${dataQualityNotes}
4087
- `;
4088
- }
4007
+ async function submitSelfAnalysisFeedback(title, description) {
4089
4008
  if (description.length > 4900) {
4090
4009
  description = description.slice(0, 4900) + "\n...[truncated]";
4091
4010
  }
@@ -4106,22 +4025,14 @@ ${dataQualityNotes}
4106
4025
  }
4107
4026
  }
4108
4027
  async function runAnalysisQuery(model, prompt) {
4109
- const result = await attemptQuery(model, prompt, SELF_ANALYSIS_OUTPUT_FORMAT);
4110
- if (result) return result;
4111
- log.info("Self-analysis: retrying without structured output (fallback)");
4112
- const fallbackResult = await attemptQuery(model, prompt, void 0);
4113
- return fallbackResult;
4114
- }
4115
- async function attemptQuery(model, prompt, outputFormat) {
4116
4028
  let structuredOutput;
4117
4029
  for await (const message of query2({
4118
4030
  prompt,
4119
4031
  options: {
4120
4032
  model,
4121
- maxTurns: 10,
4122
4033
  allowedTools: [],
4123
4034
  effort: "medium",
4124
- ...outputFormat ? { outputFormat } : {}
4035
+ outputFormat: SELF_ANALYSIS_OUTPUT_FORMAT
4125
4036
  }
4126
4037
  })) {
4127
4038
  if (message.type === "result") {
@@ -4133,34 +4044,24 @@ async function attemptQuery(model, prompt, outputFormat) {
4133
4044
  `Self-analysis cost: $${successMsg.total_cost_usd.toFixed(4)}`
4134
4045
  );
4135
4046
  if (!structuredOutput) {
4136
- const text = String(successMsg.result ?? "");
4137
- const parsed = tryParseJson(text);
4138
- if (parsed) {
4139
- log.info("Self-analysis: parsed JSON from text result");
4140
- structuredOutput = parsed;
4141
- } else {
4142
- log.warn(
4143
- `Self-analysis: success but no structured_output. result text: ${text.slice(0, 500)}`
4144
- );
4145
- }
4047
+ log.warn(
4048
+ `Self-analysis: success but no structured_output. result text: ${String(successMsg.result ?? "").slice(0, 500)}`
4049
+ );
4146
4050
  }
4147
4051
  } else {
4148
4052
  log.warn(
4149
- `Self-analysis: query returned subtype="${resultMsg.subtype}". result: ${String(resultMsg.result ?? "").slice(0, 500)}`
4053
+ `Self-analysis: query returned subtype="${resultMsg.subtype}".`
4150
4054
  );
4151
4055
  }
4152
4056
  }
4153
4057
  }
4154
- return structuredOutput;
4155
- }
4156
- function tryParseJson(text) {
4157
- const jsonMatch = text.match(/```(?:json)?\s*([\s\S]*?)```/) || text.match(/(\{[\s\S]*\})/);
4158
- if (!jsonMatch) return null;
4159
- try {
4160
- return JSON.parse(jsonMatch[1]);
4161
- } catch {
4162
- return null;
4163
- }
4058
+ if (!structuredOutput || typeof structuredOutput !== "object") return null;
4059
+ const output = structuredOutput;
4060
+ return {
4061
+ needsImprovement: Boolean(output.needsImprovement),
4062
+ title: String(output.title || ""),
4063
+ description: String(output.description || "")
4064
+ };
4164
4065
  }
4165
4066
  async function analyzeSelfPostTask(opts) {
4166
4067
  const {
@@ -4187,38 +4088,22 @@ async function analyzeSelfPostTask(opts) {
4187
4088
  tokenUsage
4188
4089
  });
4189
4090
  const prompt = `${SELF_ANALYSIS_PROMPT}
4190
- ${analysisContext}
4191
-
4192
- Respond with a JSON object now.`;
4091
+ ${analysisContext}`;
4193
4092
  const analysisPromise = runAnalysisQuery(model, prompt);
4194
4093
  const timeoutPromise = new Promise(
4195
4094
  (_, reject) => setTimeout(() => reject(new Error(`Self-analysis timed out after ${SELF_ANALYSIS_TIMEOUT_MS / 1e3}s`)), SELF_ANALYSIS_TIMEOUT_MS)
4196
4095
  );
4197
- const structuredOutput = await Promise.race([analysisPromise, timeoutPromise]);
4198
- let analysis = null;
4199
- if (structuredOutput) {
4200
- const result = SelfAnalysisResultSchema.safeParse(structuredOutput);
4201
- if (result.success) {
4202
- analysis = result.data;
4203
- } else {
4204
- log.warn(
4205
- `Self-analysis: schema validation failed: ${result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ")}`
4206
- );
4207
- log.debug(`Self-analysis: raw output: ${JSON.stringify(structuredOutput).slice(0, 500)}`);
4208
- }
4209
- }
4210
- if (!analysis) {
4211
- log.warn("Self-analysis: no valid structured output");
4096
+ const result = await Promise.race([analysisPromise, timeoutPromise]);
4097
+ if (!result) {
4098
+ log.warn("Self-analysis: no result from query");
4212
4099
  return;
4213
4100
  }
4214
- log.info(
4215
- `Self-analysis complete: score=${analysis.overall_score}/10, perfect=${analysis.is_perfect}, improvements=${analysis.improvements.length}`
4216
- );
4217
- if (!analysis.is_perfect && analysis.improvements.length > 0) {
4218
- await submitSelfAnalysisFeedback(analysis);
4219
- } else {
4220
- log.debug("Self-analysis: no improvements to report \u2014 skipping feedback");
4101
+ if (!result.needsImprovement) {
4102
+ log.info("Self-analysis complete: no improvements needed");
4103
+ return;
4221
4104
  }
4105
+ log.info(`Self-analysis complete: improvements found \u2014 ${result.title}`);
4106
+ await submitSelfAnalysisFeedback(result.title, result.description);
4222
4107
  } catch (err) {
4223
4108
  log.warn(`Self-analysis error: ${errorMessage(err)}`);
4224
4109
  }
@@ -6449,7 +6334,6 @@ var TaskProcessor = class {
6449
6334
  model: config.model,
6450
6335
  systemPrompt,
6451
6336
  cwd: config.workspacePath,
6452
- maxTurns: config.maxTurns,
6453
6337
  allowedTools,
6454
6338
  permissionMode: "bypassPermissions",
6455
6339
  allowDangerouslySkipPermissions: true,
@@ -7127,7 +7011,7 @@ function registerJobCommands(program2) {
7127
7011
  jobCmd.command("list").description("List your defined jobs").action(async () => {
7128
7012
  try {
7129
7013
  const userId = await getCurrentUserId();
7130
- const { JobRunner: JobRunner2 } = await import("./job-runner-VIGPBGRE.js");
7014
+ const { JobRunner: JobRunner2 } = await import("./job-runner-K7R4WZD4.js");
7131
7015
  const runner = new JobRunner2();
7132
7016
  const jobs = await runner.listJobs();
7133
7017
  if (jobs.length === 0) {
@@ -7151,7 +7035,7 @@ function registerJobCommands(program2) {
7151
7035
  jobCmd.command("status [name]").description("Show run history for a job (or all jobs)").option("-l, --limit <number>", "Max runs to show (default: 5)").action(async (name, opts) => {
7152
7036
  try {
7153
7037
  const userId = await getCurrentUserId();
7154
- const { JobRunner: JobRunner2 } = await import("./job-runner-VIGPBGRE.js");
7038
+ const { JobRunner: JobRunner2 } = await import("./job-runner-K7R4WZD4.js");
7155
7039
  const runner = new JobRunner2();
7156
7040
  const runs = await runner.getRunHistory(name, parseInt(opts.limit || "5"));
7157
7041
  if (runs.length === 0) {
@@ -7190,7 +7074,7 @@ Job Run History${name ? ` \u2014 ${name}` : ""}:`));
7190
7074
  process.exit(1);
7191
7075
  }
7192
7076
  const userId = await getCurrentUserId();
7193
- const { JobRunner: JobRunner2 } = await import("./job-runner-VIGPBGRE.js");
7077
+ const { JobRunner: JobRunner2 } = await import("./job-runner-K7R4WZD4.js");
7194
7078
  const runner = new JobRunner2();
7195
7079
  const job = await runner.loadJob(name);
7196
7080
  if (!job) {
@@ -0,0 +1,7 @@
1
+ import {
2
+ JobRunner
3
+ } from "./chunk-E2PAIRTS.js";
4
+ import "./chunk-YYSJHZSO.js";
5
+ export {
6
+ JobRunner
7
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "assistme",
3
- "version": "0.6.7",
3
+ "version": "0.6.9",
4
4
  "description": "AssistMe CLI Agent - AI-powered assistant that controls your real browser",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -252,7 +252,6 @@ export class TaskProcessor {
252
252
  model: config.model,
253
253
  systemPrompt,
254
254
  cwd: config.workspacePath,
255
- maxTurns: config.maxTurns,
256
255
  allowedTools,
257
256
  permissionMode: "bypassPermissions",
258
257
  allowDangerouslySkipPermissions: true,
@@ -6,10 +6,6 @@ import {
6
6
  } from "@anthropic-ai/claude-agent-sdk";
7
7
  import { submitFeedback, FeedbackError } from "edsger-feedback";
8
8
  import { log } from "../utils/logger.js";
9
- import {
10
- SelfAnalysisResultSchema,
11
- type SelfAnalysisResult,
12
- } from "../utils/schemas.js";
13
9
  import { errorMessage } from "../utils/errors.js";
14
10
  import {
15
11
  getSessionLogs,
@@ -35,58 +31,11 @@ const SELF_ANALYSIS_OUTPUT_FORMAT: OutputFormat = {
35
31
  schema: {
36
32
  type: "object",
37
33
  properties: {
38
- is_perfect: { type: "boolean" },
39
- overall_score: { type: "number", minimum: 1, maximum: 10 },
40
- task_completion_quality: {
41
- type: "object",
42
- properties: {
43
- score: { type: "number", minimum: 1, maximum: 10 },
44
- assessment: { type: "string" },
45
- },
46
- required: ["score", "assessment"],
47
- },
48
- improvements: {
49
- type: "array",
50
- items: {
51
- type: "object",
52
- properties: {
53
- area: { type: "string" },
54
- severity: {
55
- type: "string",
56
- enum: ["critical", "major", "minor", "suggestion"],
57
- },
58
- description: { type: "string" },
59
- suggestion: { type: "string" },
60
- },
61
- required: ["area", "severity", "description", "suggestion"],
62
- },
63
- },
64
- data_quality: {
65
- type: "object",
66
- properties: {
67
- session_logs_useful: { type: "boolean" },
68
- session_logs_gaps: { type: "string" },
69
- message_events_useful: { type: "boolean" },
70
- message_events_gaps: { type: "string" },
71
- conversation_context_useful: { type: "boolean" },
72
- conversation_context_gaps: { type: "string" },
73
- },
74
- required: [
75
- "session_logs_useful",
76
- "message_events_useful",
77
- "conversation_context_useful",
78
- ],
79
- },
80
- summary: { type: "string" },
34
+ needsImprovement: { type: "boolean" },
35
+ title: { type: "string" },
36
+ description: { type: "string" },
81
37
  },
82
- required: [
83
- "is_perfect",
84
- "overall_score",
85
- "task_completion_quality",
86
- "improvements",
87
- "data_quality",
88
- "summary",
89
- ],
38
+ required: ["needsImprovement", "title", "description"],
90
39
  },
91
40
  };
92
41
 
@@ -113,17 +62,14 @@ Below you will find:
113
62
  - **Tool Failures**: Any tool calls that failed during execution
114
63
 
115
64
  ## Instructions
116
- Analyze all provided data critically. Consider:
117
- - Are the session logs capturing enough detail for debugging?
118
- - Do the message events provide sufficient visibility into the agent's decision-making?
119
- - Is the conversation context giving enough user intent signal?
120
- - Were tools used efficiently?
121
- - Could the overall execution flow be improved?
122
-
123
- Set is_perfect to true ONLY if there are genuinely zero improvements to suggest (this should be rare).
124
- The overall_score should be 1-10 where 10 means absolutely perfect.
125
-
126
- Respond with a JSON object now.`;
65
+ Analyze all provided data critically. Respond with a JSON object containing:
66
+ - "needsImprovement": set to false ONLY if the task was handled perfectly with zero improvements, true otherwise
67
+ - "title": a short summary under 100 chars (empty string if needsImprovement is false)
68
+ - "description": a detailed markdown report (empty string if needsImprovement is false) that includes:
69
+ - **Summary**: overall assessment of how AssistMe performed
70
+ - **Task Completion Quality**: score (1-10) and assessment
71
+ - **Improvements**: numbered list, each with severity (critical/major/minor/suggestion), area, description, and suggestion
72
+ - **Data Quality Gaps**: any gaps in session logs, message events, or conversation context that limited your analysis`;
127
73
 
128
74
  // ── Context Building ────────────────────────────────────────────
129
75
 
@@ -294,35 +240,7 @@ async function buildAnalysisContext(ctx: SelfAnalysisContext): Promise<string> {
294
240
 
295
241
  // ── Feedback Submission ─────────────────────────────────────────
296
242
 
297
- async function submitSelfAnalysisFeedback(analysis: SelfAnalysisResult): Promise<void> {
298
- const title = `Self-Analysis: Score ${analysis.overall_score}/10 — ${analysis.improvements.length} improvement(s)`;
299
-
300
- const improvementDetails = analysis.improvements
301
- .map((imp, i) => `${i + 1}. [${imp.severity}] **${imp.area}**: ${imp.description}\n → ${imp.suggestion}`)
302
- .join("\n");
303
-
304
- const dataQualityNotes = [
305
- analysis.data_quality.session_logs_gaps
306
- ? `Session logs: ${analysis.data_quality.session_logs_gaps}`
307
- : null,
308
- analysis.data_quality.message_events_gaps
309
- ? `Message events: ${analysis.data_quality.message_events_gaps}`
310
- : null,
311
- analysis.data_quality.conversation_context_gaps
312
- ? `Conversation context: ${analysis.data_quality.conversation_context_gaps}`
313
- : null,
314
- ]
315
- .filter(Boolean)
316
- .join("\n");
317
-
318
- let description = `## Summary\n${analysis.summary}\n\n`;
319
- description += `## Task Completion Quality (${analysis.task_completion_quality.score}/10)\n${analysis.task_completion_quality.assessment}\n\n`;
320
- description += `## Improvements\n${improvementDetails}\n`;
321
-
322
- if (dataQualityNotes) {
323
- description += `\n## Data Quality Gaps\n${dataQualityNotes}\n`;
324
- }
325
-
243
+ async function submitSelfAnalysisFeedback(title: string, description: string): Promise<void> {
326
244
  // Truncate to fit edsger-feedback's 5000 char limit
327
245
  if (description.length > 4900) {
328
246
  description = description.slice(0, 4900) + "\n...[truncated]";
@@ -347,34 +265,22 @@ async function submitSelfAnalysisFeedback(analysis: SelfAnalysisResult): Promise
347
265
 
348
266
  // ── Query Runner ────────────────────────────────────────────────
349
267
 
350
- async function runAnalysisQuery(model: string, prompt: string): Promise<unknown> {
351
- // First attempt: structured output
352
- const result = await attemptQuery(model, prompt, SELF_ANALYSIS_OUTPUT_FORMAT);
353
- if (result) return result;
354
-
355
- // Fallback: no structured output, parse JSON from text response
356
- log.info("Self-analysis: retrying without structured output (fallback)");
357
- const fallbackResult = await attemptQuery(model, prompt, undefined);
358
- return fallbackResult;
268
+ interface AnalysisResult {
269
+ needsImprovement: boolean;
270
+ title: string;
271
+ description: string;
359
272
  }
360
273
 
361
- async function attemptQuery(
362
- model: string,
363
- prompt: string,
364
- outputFormat: OutputFormat | undefined
365
- ): Promise<unknown> {
274
+ async function runAnalysisQuery(model: string, prompt: string): Promise<AnalysisResult | null> {
366
275
  let structuredOutput: unknown;
367
276
 
368
- // Use independent query() instead of session resume to avoid
369
- // conflicts with skill evaluation which also resumes the session
370
277
  for await (const message of query({
371
278
  prompt,
372
279
  options: {
373
280
  model,
374
- maxTurns: 10,
375
281
  allowedTools: [],
376
282
  effort: "medium",
377
- ...(outputFormat ? { outputFormat } : {}),
283
+ outputFormat: SELF_ANALYSIS_OUTPUT_FORMAT,
378
284
  },
379
285
  })) {
380
286
  if (message.type === "result") {
@@ -386,38 +292,26 @@ async function attemptQuery(
386
292
  `Self-analysis cost: $${successMsg.total_cost_usd.toFixed(4)}`
387
293
  );
388
294
  if (!structuredOutput) {
389
- // Try to parse JSON from text result as fallback
390
- const text = String((successMsg as any).result ?? "");
391
- const parsed = tryParseJson(text);
392
- if (parsed) {
393
- log.info("Self-analysis: parsed JSON from text result");
394
- structuredOutput = parsed;
395
- } else {
396
- log.warn(
397
- `Self-analysis: success but no structured_output. result text: ${text.slice(0, 500)}`
398
- );
399
- }
295
+ log.warn(
296
+ `Self-analysis: success but no structured_output. result text: ${String((successMsg as any).result ?? "").slice(0, 500)}`
297
+ );
400
298
  }
401
299
  } else {
402
300
  log.warn(
403
- `Self-analysis: query returned subtype="${resultMsg.subtype}". result: ${String((resultMsg as any).result ?? "").slice(0, 500)}`
301
+ `Self-analysis: query returned subtype="${resultMsg.subtype}".`
404
302
  );
405
303
  }
406
304
  }
407
305
  }
408
306
 
409
- return structuredOutput;
410
- }
307
+ if (!structuredOutput || typeof structuredOutput !== "object") return null;
411
308
 
412
- function tryParseJson(text: string): unknown {
413
- // Extract JSON from text that may contain markdown code fences
414
- const jsonMatch = text.match(/```(?:json)?\s*([\s\S]*?)```/) || text.match(/(\{[\s\S]*\})/);
415
- if (!jsonMatch) return null;
416
- try {
417
- return JSON.parse(jsonMatch[1]);
418
- } catch {
419
- return null;
420
- }
309
+ const output = structuredOutput as Record<string, unknown>;
310
+ return {
311
+ needsImprovement: Boolean(output.needsImprovement),
312
+ title: String(output.title || ""),
313
+ description: String(output.description || ""),
314
+ };
421
315
  }
422
316
 
423
317
  // ── Main Entry Point ────────────────────────────────────────────
@@ -467,7 +361,7 @@ export async function analyzeSelfPostTask(opts: {
467
361
  tokenUsage,
468
362
  });
469
363
 
470
- const prompt = `${SELF_ANALYSIS_PROMPT}\n${analysisContext}\n\nRespond with a JSON object now.`;
364
+ const prompt = `${SELF_ANALYSIS_PROMPT}\n${analysisContext}`;
471
365
 
472
366
  // Race the analysis against a timeout to avoid hanging forever
473
367
  const analysisPromise = runAnalysisQuery(model, prompt);
@@ -475,37 +369,20 @@ export async function analyzeSelfPostTask(opts: {
475
369
  setTimeout(() => reject(new Error(`Self-analysis timed out after ${SELF_ANALYSIS_TIMEOUT_MS / 1000}s`)), SELF_ANALYSIS_TIMEOUT_MS)
476
370
  );
477
371
 
478
- const structuredOutput = await Promise.race([analysisPromise, timeoutPromise]);
372
+ const result = await Promise.race([analysisPromise, timeoutPromise]);
479
373
 
480
- // Validate against Zod schema
481
- let analysis: SelfAnalysisResult | null = null;
482
- if (structuredOutput) {
483
- const result = SelfAnalysisResultSchema.safeParse(structuredOutput);
484
- if (result.success) {
485
- analysis = result.data;
486
- } else {
487
- log.warn(
488
- `Self-analysis: schema validation failed: ${result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ")}`
489
- );
490
- log.debug(`Self-analysis: raw output: ${JSON.stringify(structuredOutput).slice(0, 500)}`);
491
- }
374
+ if (!result) {
375
+ log.warn("Self-analysis: no result from query");
376
+ return;
492
377
  }
493
378
 
494
- if (!analysis) {
495
- log.warn("Self-analysis: no valid structured output");
379
+ if (!result.needsImprovement) {
380
+ log.info("Self-analysis complete: no improvements needed");
496
381
  return;
497
382
  }
498
383
 
499
- log.info(
500
- `Self-analysis complete: score=${analysis.overall_score}/10, perfect=${analysis.is_perfect}, improvements=${analysis.improvements.length}`
501
- );
502
-
503
- // Only submit feedback if not perfect
504
- if (!analysis.is_perfect && analysis.improvements.length > 0) {
505
- await submitSelfAnalysisFeedback(analysis);
506
- } else {
507
- log.debug("Self-analysis: no improvements to report — skipping feedback");
508
- }
384
+ log.info(`Self-analysis complete: improvements found — ${result.title}`);
385
+ await submitSelfAnalysisFeedback(result.title, result.description);
509
386
  } catch (err) {
510
387
  log.warn(`Self-analysis error: ${errorMessage(err)}`);
511
388
  }
@@ -13,7 +13,6 @@ import {
13
13
  safeParse,
14
14
  } from "../utils/schemas.js";
15
15
  import { errorMessage } from "../utils/errors.js";
16
- import { SKILL_VALIDATION_MAX_TURNS } from "../utils/constants.js";
17
16
 
18
17
  // ── Structured output schemas ───────────────────────────────────────
19
18
 
@@ -141,7 +140,6 @@ Respond with a JSON object now.`;
141
140
  options: {
142
141
  resume: sessionId,
143
142
  model,
144
- maxTurns: 1,
145
143
  allowedTools: [],
146
144
  effort: "low",
147
145
  outputFormat: SKILL_DECISION_OUTPUT_FORMAT,
@@ -197,7 +195,6 @@ async function validateSkill(
197
195
  options: {
198
196
  resume: sessionId,
199
197
  model,
200
- maxTurns: SKILL_VALIDATION_MAX_TURNS,
201
198
  allowedTools: [],
202
199
  effort: "low",
203
200
  outputFormat: SKILL_VALIDATION_OUTPUT_FORMAT,
@@ -25,7 +25,6 @@ export function registerConfigCommands(program: Command): void {
25
25
  "workspacePath",
26
26
  "sessionName",
27
27
  "model",
28
- "maxTurns",
29
28
  "browserPort",
30
29
  ];
31
30
  if (!validKeys.includes(key)) {
@@ -33,7 +32,7 @@ export function registerConfigCommands(program: Command): void {
33
32
  log.info(`Valid keys: ${validKeys.join(", ")}`);
34
33
  process.exit(1);
35
34
  }
36
- const numericKeys = ["maxTurns", "browserPort"];
35
+ const numericKeys = ["browserPort"];
37
36
  const val = numericKeys.includes(key) ? parseInt(value, 10) : value;
38
37
  setConfig(key as keyof AssistMeConfig, val);
39
38
  log.success(
@@ -59,7 +58,6 @@ export function registerConfigCommands(program: Command): void {
59
58
  console.log(` Workspace: ${cfg.workspacePath}`);
60
59
  console.log(` Session Name: ${cfg.sessionName}`);
61
60
  console.log(` Model: ${cfg.model}`);
62
- console.log(` Max Turns: ${cfg.maxTurns}`);
63
61
  console.log(` Config Path: ${getConfigPath()}`);
64
62
  console.log();
65
63
  });
@@ -8,7 +8,6 @@ export interface AssistMeConfig {
8
8
  workspacePath: string;
9
9
  sessionName: string;
10
10
  model: string;
11
- maxTurns: number;
12
11
  taskTimeoutMinutes: number;
13
12
  }
14
13
 
@@ -28,7 +27,6 @@ const CONFIG_DEFAULTS: Partial<AssistMeConfig> = {
28
27
  supabaseAnonKey: SUPABASE_ANON_KEY_DEFAULT,
29
28
  sessionName: "Default",
30
29
  model: "claude-sonnet-4-20250514",
31
- maxTurns: 500,
32
30
  taskTimeoutMinutes: 10,
33
31
  };
34
32
 
@@ -51,7 +49,6 @@ export function getConfig(): AssistMeConfig {
51
49
  workspacePath: resolve(workspacePath),
52
50
  sessionName: config.get("sessionName") || "Default",
53
51
  model: config.get("model") || "claude-sonnet-4-20250514",
54
- maxTurns: config.get("maxTurns") || 500,
55
52
  taskTimeoutMinutes: config.get("taskTimeoutMinutes") || 10,
56
53
  };
57
54
  }
@@ -70,9 +70,6 @@ export const MAX_CONTENT_SEARCH_RESULTS = 30;
70
70
 
71
71
  // ── Agentic Loop ──────────────────────────────────────────────────
72
72
 
73
- /** Max turns for skill validation query */
74
- export const SKILL_VALIDATION_MAX_TURNS = 2;
75
-
76
73
  // ── Memory Maintenance ────────────────────────────────────────────
77
74
 
78
75
  /** Similarity threshold for memory deduplication (0-1) */
@@ -1,7 +0,0 @@
1
- import {
2
- JobRunner
3
- } from "./chunk-5F4P6MYZ.js";
4
- import "./chunk-EPKN2PW5.js";
5
- export {
6
- JobRunner
7
- };