@awak-app/simy-cli 0.5.68 → 0.5.70

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awak-app/simy-cli",
3
- "version": "0.5.68",
3
+ "version": "0.5.70",
4
4
  "description": "Local SIMY executor for non-coding Local Tasks and Agentic Loop runs.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/agent.js CHANGED
@@ -875,7 +875,7 @@ export async function startAgent({
875
875
  runReview: async (request, provider) => {
876
876
  const scope = await authorizeDesktopWork();
877
877
  const beforeDispatch = () => authorizeDesktopWork(scope);
878
- return (dependencies.runSqmLocalReview || ((value, selected, options) => runStructuredProviderReview(selected, value, options)))(request, provider, { beforeDispatch });
878
+ return (dependencies.runSqmLocalReview || ((value, selected, options) => runStructuredProviderReview(selected, value, options)))(request, provider, { beforeDispatch, readOnlyAnalysis: true });
879
879
  },
880
880
  onChange: notifyDesktopStatusChange,
881
881
  getWorkspaceUrl: () => {
@@ -13,7 +13,7 @@ import {
13
13
  } from "./durable-local-task-steps-contract.js";
14
14
  import { buildExecutionCapabilityContract } from "./execution-capability-contract.js";
15
15
 
16
- export const CLI_VERSION = "0.5.68";
16
+ export const CLI_VERSION = "0.5.70";
17
17
  export const CLI_API_CONTRACT_VERSION = 10;
18
18
 
19
19
  export function withCliContract(
@@ -18,12 +18,13 @@ const DEFAULT_EXECUTION_TIMEOUT_MS = 240_000;
18
18
  export const SQM_CODEX_MODEL = "gpt-6.1-sol";
19
19
 
20
20
  export class SqmLocalReviewError extends Error {
21
- constructor(message, { status = null, code = "sqm_local_review_error", stage = null, jobId = null, failureRecorded = false } = {}) {
21
+ constructor(message, { status = null, code = "sqm_local_review_error", stage = null, jobId = null, failureRecorded = false, validationFeedback = "" } = {}) {
22
22
  super(message);
23
23
  this.name = "SqmLocalReviewError";
24
24
  this.status = status;
25
25
  this.code = code;
26
26
  this.stage = stage; this.jobId = jobId; this.failureRecorded = failureRecorded;
27
+ this.validationFeedback = typeof validationFeedback === "string" ? validationFeedback.slice(0, 2000) : "";
27
28
  }
28
29
  }
29
30
 
@@ -71,6 +72,7 @@ export function createSqmLocalReviewApi({
71
72
  status: response.status,
72
73
  code: machineCode(payload?.code || payload?.detail?.code),
73
74
  stage: payload?.detail?.stage, jobId: payload?.detail?.job_id, failureRecorded: payload?.detail?.failure_recorded === true,
75
+ validationFeedback: payload?.detail?.validation_feedback,
74
76
  });
75
77
  }
76
78
  return payload;
@@ -124,6 +126,23 @@ export function createSqmLocalReviewWorker({
124
126
  lease_token: claim.lease_token,
125
127
  });
126
128
 
129
+ // Repair only a rejected model result, under the same live lease. Network,
130
+ // authorization, and persistence failures must not repeat provider execution.
131
+ const validatedReview = async (request, provider, code, submit, setStage) => {
132
+ let nextRequest = request;
133
+ for (let attempt = 0; ; attempt += 1) {
134
+ setStage(false);
135
+ const review = await runReview(nextRequest, provider);
136
+ setStage(true);
137
+ try {
138
+ return { review, response: await submit(review) };
139
+ } catch (error) {
140
+ if (attempt >= 1 || error.status !== 422 || error.code !== code || !error.validationFeedback) throw error;
141
+ nextRequest = { ...request, prompt: `${request.prompt}\n\nThe previous result failed validation. Return a corrected complete JSON object using only the supplied evidence. Fix these constraints:\n${error.validationFeedback}` };
142
+ }
143
+ }
144
+ };
145
+
127
146
  const processClaim = async (claim, provider, historyScope, workspaceUrl) => {
128
147
  activeJobId = claim.job_id;
129
148
  const priorIndex = history.findIndex(item => item.id === claim.job_id);
@@ -142,25 +161,21 @@ export function createSqmLocalReviewWorker({
142
161
  heartbeatTimer.unref?.();
143
162
  let stage = "analysis";
144
163
  try {
145
- const analysis = await runReview(claim.request, provider);
146
- stage = "advance";
147
- const advanced = await api.request({
164
+ const { review: analysis, response: advanced } = await validatedReview(claim.request, provider, "invalid_sqm_analysis_output", analysis => api.request({
148
165
  action: "advance",
149
166
  ...leaseBody(claim, provider),
150
167
  analysis_output: analysis.output,
151
168
  executor_model: analysis.model,
152
- });
169
+ }), submitting => { stage = submitting ? "advance" : "analysis"; });
153
170
  if (advanced.completed) { await updateTask(claim.job_id, "completed", historyScope); return advanced; }
154
171
  stage = "adjudication";
155
- const adjudication = await runReview(advanced.request, provider);
156
- stage = "complete";
157
- const completed = await api.request({
172
+ const { response: completed } = await validatedReview(advanced.request, provider, "invalid_sqm_adjudication_output", adjudication => api.request({
158
173
  action: "complete",
159
174
  ...leaseBody(claim, provider),
160
175
  analysis_output: analysis.output,
161
176
  adjudication_output: adjudication.output,
162
177
  executor_model: adjudication.model || analysis.model,
163
- });
178
+ }), submitting => { stage = submitting ? "complete" : "adjudication"; });
164
179
  await updateTask(claim.job_id, "completed", historyScope);
165
180
  return completed;
166
181
  } catch (error) {
@@ -253,7 +268,7 @@ export async function runStructuredProviderReview(
253
268
  executionTimeoutMs = DEFAULT_EXECUTION_TIMEOUT_MS,
254
269
  environment = process.env,
255
270
  signal,
256
- readOnlyAnalysis = false,
271
+ readOnlyAnalysis = true,
257
272
  terminationGraceMs = 1_000,
258
273
  beforeDispatch = async () => {},
259
274
  } = {},
@@ -436,7 +451,7 @@ function spawnReview(command, args, prompt, { spawnImpl, executionTimeoutMs, lab
436
451
  function providerSignInRequired(message) {
437
452
  // Match explicit provider authentication failures only, never general 403s
438
453
  // (which can be permissions/quotas) or model-generated prose/tool output.
439
- return typeof message === 'string' && /(?:not logged in|please (?:log|sign) in|invalid api key|authentication token (?:is )?(?:invalid|expired)|refresh token (?:has )?expired)/i.test(message.slice(0, 4000));
454
+ return typeof message === 'string' && /(?:\b401\s+Unauthorized\b|not logged in|please (?:log|sign) in|invalid api key|authentication token (?:is )?(?:invalid|expired)|refresh token (?:has )?expired)/i.test(message.slice(0, 4000));
440
455
  }
441
456
 
442
457
  function safeReviewEnvironment(environment, provider) {